203 lines
8.6 KiB
C
203 lines
8.6 KiB
C
|
// REQUIRES: arm-registered-target
|
||
|
// RUN: %clang_cc1 -triple armv7---eabi -target-abi aapcs -mfloat-abi hard -emit-llvm %s -o - | FileCheck %s
|
||
|
|
||
|
typedef long long int64_t;
|
||
|
typedef unsigned int uint32_t;
|
||
|
|
||
|
/* This is not a homogenous aggregate - fundamental types are different */
|
||
|
typedef union {
|
||
|
float f[4];
|
||
|
uint32_t i[4];
|
||
|
} union_with_first_floats;
|
||
|
union_with_first_floats g_u_f;
|
||
|
|
||
|
extern void takes_union_with_first_floats(union_with_first_floats a);
|
||
|
extern union_with_first_floats returns_union_with_first_floats(void);
|
||
|
|
||
|
void test_union_with_first_floats(void) {
|
||
|
takes_union_with_first_floats(g_u_f);
|
||
|
}
|
||
|
// CHECK: declare arm_aapcs_vfpcc void @takes_union_with_first_floats([4 x i32])
|
||
|
|
||
|
void test_return_union_with_first_floats(void) {
|
||
|
g_u_f = returns_union_with_first_floats();
|
||
|
}
|
||
|
// CHECK: declare arm_aapcs_vfpcc void @returns_union_with_first_floats(%union.union_with_first_floats* sret)
|
||
|
|
||
|
/* This is not a homogenous aggregate - fundamental types are different */
|
||
|
typedef union {
|
||
|
uint32_t i[4];
|
||
|
float f[4];
|
||
|
} union_with_non_first_floats;
|
||
|
union_with_non_first_floats g_u_nf_f;
|
||
|
|
||
|
extern void takes_union_with_non_first_floats(union_with_non_first_floats a);
|
||
|
extern union_with_non_first_floats returns_union_with_non_first_floats(void);
|
||
|
|
||
|
void test_union_with_non_first_floats(void) {
|
||
|
takes_union_with_non_first_floats(g_u_nf_f);
|
||
|
}
|
||
|
// CHECK: declare arm_aapcs_vfpcc void @takes_union_with_non_first_floats([4 x i32])
|
||
|
|
||
|
void test_return_union_with_non_first_floats(void) {
|
||
|
g_u_nf_f = returns_union_with_non_first_floats();
|
||
|
}
|
||
|
// CHECK: declare arm_aapcs_vfpcc void @returns_union_with_non_first_floats(%union.union_with_non_first_floats* sret)
|
||
|
|
||
|
/* This is not a homogenous aggregate - fundamental types are different */
|
||
|
typedef struct {
|
||
|
float a;
|
||
|
union_with_first_floats b;
|
||
|
} struct_with_union_with_first_floats;
|
||
|
struct_with_union_with_first_floats g_s_f;
|
||
|
|
||
|
extern void takes_struct_with_union_with_first_floats(struct_with_union_with_first_floats a);
|
||
|
extern struct_with_union_with_first_floats returns_struct_with_union_with_first_floats(void);
|
||
|
|
||
|
void test_struct_with_union_with_first_floats(void) {
|
||
|
takes_struct_with_union_with_first_floats(g_s_f);
|
||
|
}
|
||
|
// CHECK: declare arm_aapcs_vfpcc void @takes_struct_with_union_with_first_floats([5 x i32])
|
||
|
|
||
|
void test_return_struct_with_union_with_first_floats(void) {
|
||
|
g_s_f = returns_struct_with_union_with_first_floats();
|
||
|
}
|
||
|
// CHECK: declare arm_aapcs_vfpcc void @returns_struct_with_union_with_first_floats(%struct.struct_with_union_with_first_floats* sret)
|
||
|
|
||
|
/* This is not a homogenous aggregate - fundamental types are different */
|
||
|
typedef struct {
|
||
|
float a;
|
||
|
union_with_non_first_floats b;
|
||
|
} struct_with_union_with_non_first_floats;
|
||
|
struct_with_union_with_non_first_floats g_s_nf_f;
|
||
|
|
||
|
extern void takes_struct_with_union_with_non_first_floats(struct_with_union_with_non_first_floats a);
|
||
|
extern struct_with_union_with_non_first_floats returns_struct_with_union_with_non_first_floats(void);
|
||
|
|
||
|
void test_struct_with_union_with_non_first_floats(void) {
|
||
|
takes_struct_with_union_with_non_first_floats(g_s_nf_f);
|
||
|
}
|
||
|
// CHECK: declare arm_aapcs_vfpcc void @takes_struct_with_union_with_non_first_floats([5 x i32])
|
||
|
|
||
|
void test_return_struct_with_union_with_non_first_floats(void) {
|
||
|
g_s_nf_f = returns_struct_with_union_with_non_first_floats();
|
||
|
}
|
||
|
// CHECK: declare arm_aapcs_vfpcc void @returns_struct_with_union_with_non_first_floats(%struct.struct_with_union_with_non_first_floats* sret)
|
||
|
|
||
|
/* Plain array is not a homogenous aggregate */
|
||
|
extern void takes_array_of_floats(float a[4]);
|
||
|
void test_array_of_floats(void) {
|
||
|
float a[4] = {1.0, 2.0, 3.0, 4.0};
|
||
|
takes_array_of_floats(a);
|
||
|
}
|
||
|
// CHECK: declare arm_aapcs_vfpcc void @takes_array_of_floats(float*)
|
||
|
|
||
|
/* Struct-type homogenous aggregate */
|
||
|
typedef struct {
|
||
|
float x, y, z, w;
|
||
|
} struct_with_fundamental_elems;
|
||
|
struct_with_fundamental_elems g_s;
|
||
|
|
||
|
extern void takes_struct_with_fundamental_elems(struct_with_fundamental_elems a);
|
||
|
extern struct_with_fundamental_elems returns_struct_with_fundamental_elems(void);
|
||
|
|
||
|
void test_struct_with_fundamental_elems(void) {
|
||
|
takes_struct_with_fundamental_elems(g_s);
|
||
|
// CHECK: call arm_aapcs_vfpcc void @takes_struct_with_fundamental_elems(float {{.*}}, float {{.*}}, float{{.*}}, float {{.*}})
|
||
|
}
|
||
|
// CHECK: declare arm_aapcs_vfpcc void @takes_struct_with_fundamental_elems(float, float, float, float)
|
||
|
|
||
|
void test_return_struct_with_fundamental_elems(void) {
|
||
|
g_s = returns_struct_with_fundamental_elems();
|
||
|
// CHECK: call arm_aapcs_vfpcc %struct.struct_with_fundamental_elems @returns_struct_with_fundamental_elems()
|
||
|
}
|
||
|
// CHECK: declare arm_aapcs_vfpcc %struct.struct_with_fundamental_elems @returns_struct_with_fundamental_elems()
|
||
|
|
||
|
/* Array-type homogenous aggregate */
|
||
|
typedef struct {
|
||
|
float xyzw[4];
|
||
|
} struct_with_array;
|
||
|
struct_with_array g_s_a;
|
||
|
|
||
|
extern void takes_struct_with_array(struct_with_array a);
|
||
|
extern struct_with_array returns_struct_with_array(void);
|
||
|
|
||
|
void test_struct_with_array(void) {
|
||
|
takes_struct_with_array(g_s_a);
|
||
|
// CHECK: call arm_aapcs_vfpcc void @takes_struct_with_array(float {{.*}}, float {{.*}}, float {{.*}}, float {{.*}})
|
||
|
}
|
||
|
// CHECK: declare arm_aapcs_vfpcc void @takes_struct_with_array(float, float, float, float)
|
||
|
|
||
|
void test_return_struct_with_array(void) {
|
||
|
g_s_a = returns_struct_with_array();
|
||
|
// CHECK: call arm_aapcs_vfpcc %struct.struct_with_array @returns_struct_with_array()
|
||
|
}
|
||
|
// CHECK: declare arm_aapcs_vfpcc %struct.struct_with_array @returns_struct_with_array()
|
||
|
|
||
|
/* This union is a homogenous aggregate. Check that it's passed properly */
|
||
|
typedef union {
|
||
|
struct_with_fundamental_elems xyzw;
|
||
|
float a[3];
|
||
|
} union_with_struct_with_fundamental_elems;
|
||
|
union_with_struct_with_fundamental_elems g_u_s_fe;
|
||
|
|
||
|
extern void takes_union_with_struct_with_fundamental_elems(union_with_struct_with_fundamental_elems a);
|
||
|
extern union_with_struct_with_fundamental_elems returns_union_with_struct_with_fundamental_elems(void);
|
||
|
|
||
|
void test_union_with_struct_with_fundamental_elems(void) {
|
||
|
takes_union_with_struct_with_fundamental_elems(g_u_s_fe);
|
||
|
// CHECK: call arm_aapcs_vfpcc void @takes_union_with_struct_with_fundamental_elems(float {{.*}}, float {{.*}}, float {{.*}}, float {{.*}})
|
||
|
}
|
||
|
// CHECK: declare arm_aapcs_vfpcc void @takes_union_with_struct_with_fundamental_elems(float, float, float, float)
|
||
|
|
||
|
void test_return_union_with_struct_with_fundamental_elems(void) {
|
||
|
g_u_s_fe = returns_union_with_struct_with_fundamental_elems();
|
||
|
// CHECK: call arm_aapcs_vfpcc %union.union_with_struct_with_fundamental_elems @returns_union_with_struct_with_fundamental_elems()
|
||
|
}
|
||
|
// CHECK: declare arm_aapcs_vfpcc %union.union_with_struct_with_fundamental_elems @returns_union_with_struct_with_fundamental_elems()
|
||
|
|
||
|
// Make sure HAs that can be partially fit into VFP registers will be allocated
|
||
|
// on stack and that later VFP candidates will go on stack as well.
|
||
|
typedef struct {
|
||
|
double x;
|
||
|
double a2;
|
||
|
double a3;
|
||
|
double a4;
|
||
|
} struct_of_four_doubles;
|
||
|
extern void takes_struct_of_four_doubles(double a, struct_of_four_doubles b, struct_of_four_doubles c, double d);
|
||
|
struct_of_four_doubles g_s4d;
|
||
|
|
||
|
void test_struct_of_four_doubles(void) {
|
||
|
// CHECK: test_struct_of_four_doubles
|
||
|
// CHECK: call arm_aapcs_vfpcc void @takes_struct_of_four_doubles(double {{.*}}, double {{.*}}, double {{.*}}, double {{.*}}, double {{.*}}, [6 x float] undef, double {{.*}}, double {{.*}}, double {{.*}}, double {{.*}}, double {{.*}})
|
||
|
takes_struct_of_four_doubles(3.0, g_s4d, g_s4d, 4.0);
|
||
|
}
|
||
|
|
||
|
extern void takes_struct_with_backfill(float f1, double a, float f2, struct_of_four_doubles b, struct_of_four_doubles c, double d);
|
||
|
void test_struct_with_backfill(void) {
|
||
|
// CHECK: test_struct_with_backfill
|
||
|
// CHECK: call arm_aapcs_vfpcc void @takes_struct_with_backfill(float {{.*}}, double {{.*}}, float {{.*}}, double {{.*}}, double {{.*}}, double {{.*}}, double {{.*}}, [4 x float] undef, double {{.*}}, double {{.*}}, double {{.*}}, double {{.*}}, double {{.*}})
|
||
|
takes_struct_with_backfill(3.0, 3.1, 3.2, g_s4d, g_s4d, 4.0);
|
||
|
}
|
||
|
|
||
|
typedef __attribute__(( ext_vector_type(8) )) char __char8;
|
||
|
typedef __attribute__(( ext_vector_type(4) )) short __short4;
|
||
|
typedef struct {
|
||
|
__char8 a1;
|
||
|
__short4 a2;
|
||
|
__char8 a3;
|
||
|
__short4 a4;
|
||
|
} struct_of_vecs;
|
||
|
extern void takes_struct_of_vecs(double a, struct_of_vecs b, struct_of_vecs c, double d);
|
||
|
struct_of_vecs g_vec;
|
||
|
|
||
|
void test_struct_of_vecs(void) {
|
||
|
// CHECK: test_struct_of_vecs
|
||
|
// CHECK: call arm_aapcs_vfpcc void @takes_struct_of_vecs(double {{.*}}, <8 x i8> {{.*}}, <4 x i16> {{.*}}, <8 x i8> {{.*}}, <4 x i16> {{.*}}, [6 x float] undef, <8 x i8> {{.*}}, <4 x i16> {{.*}}, <8 x i8> {{.*}}, <4 x i16> {{.*}}, double {{.*}})
|
||
|
takes_struct_of_vecs(3.0, g_vec, g_vec, 4.0);
|
||
|
}
|
||
|
|
||
|
// FIXME: Tests necessary:
|
||
|
// - Vectors
|
||
|
// - C++ stuff
|