231 lines · c
1// REQUIRES: arm-registered-target2// RUN: %clang_cc1 -triple armv7---eabi -target-abi aapcs -mfloat-abi hard -emit-llvm %s -o - | FileCheck %s3 4// RUN: %clang_cc1 -triple arm64-apple-darwin9 -target-abi darwinpcs \5// RUN: -ffreestanding -emit-llvm -w -o - %s | FileCheck -check-prefix=CHECK64 %s6 7// RUN: %clang_cc1 -triple arm64-linux-gnu -ffreestanding -emit-llvm -w -o - %s \8// RUN: | FileCheck --check-prefix=CHECK64 %s9typedef long long int64_t;10typedef unsigned int uint32_t;11 12/* This is not a homogenous aggregate - fundamental types are different */13typedef union {14 float f[4];15 uint32_t i[4];16} union_with_first_floats;17union_with_first_floats g_u_f;18 19extern void takes_union_with_first_floats(union_with_first_floats a);20extern union_with_first_floats returns_union_with_first_floats(void);21 22void test_union_with_first_floats(void) {23 takes_union_with_first_floats(g_u_f);24}25// CHECK: declare arm_aapcs_vfpcc void @takes_union_with_first_floats([4 x i32])26 27void test_return_union_with_first_floats(void) {28 g_u_f = returns_union_with_first_floats();29}30// CHECK: declare arm_aapcs_vfpcc void @returns_union_with_first_floats(ptr dead_on_unwind writable sret(%union.union_with_first_floats) align 4)31 32/* This is not a homogenous aggregate - fundamental types are different */33typedef union {34 uint32_t i[4];35 float f[4];36} union_with_non_first_floats;37union_with_non_first_floats g_u_nf_f;38 39extern void takes_union_with_non_first_floats(union_with_non_first_floats a);40extern union_with_non_first_floats returns_union_with_non_first_floats(void);41 42void test_union_with_non_first_floats(void) {43 takes_union_with_non_first_floats(g_u_nf_f);44}45// CHECK: declare arm_aapcs_vfpcc void @takes_union_with_non_first_floats([4 x i32])46 47void test_return_union_with_non_first_floats(void) {48 g_u_nf_f = returns_union_with_non_first_floats();49}50// CHECK: declare arm_aapcs_vfpcc void @returns_union_with_non_first_floats(ptr dead_on_unwind writable sret(%union.union_with_non_first_floats) align 4)51 52/* This is not a homogenous aggregate - fundamental types are different */53typedef struct {54 float a;55 union_with_first_floats b;56} struct_with_union_with_first_floats;57struct_with_union_with_first_floats g_s_f;58 59extern void takes_struct_with_union_with_first_floats(struct_with_union_with_first_floats a);60extern struct_with_union_with_first_floats returns_struct_with_union_with_first_floats(void);61 62void test_struct_with_union_with_first_floats(void) {63 takes_struct_with_union_with_first_floats(g_s_f);64}65// CHECK: declare arm_aapcs_vfpcc void @takes_struct_with_union_with_first_floats([5 x i32])66 67void test_return_struct_with_union_with_first_floats(void) {68 g_s_f = returns_struct_with_union_with_first_floats();69}70// CHECK: declare arm_aapcs_vfpcc void @returns_struct_with_union_with_first_floats(ptr dead_on_unwind writable sret(%struct.struct_with_union_with_first_floats) align 4)71 72/* This is not a homogenous aggregate - fundamental types are different */73typedef struct {74 float a;75 union_with_non_first_floats b;76} struct_with_union_with_non_first_floats;77struct_with_union_with_non_first_floats g_s_nf_f;78 79extern void takes_struct_with_union_with_non_first_floats(struct_with_union_with_non_first_floats a);80extern struct_with_union_with_non_first_floats returns_struct_with_union_with_non_first_floats(void);81 82void test_struct_with_union_with_non_first_floats(void) {83 takes_struct_with_union_with_non_first_floats(g_s_nf_f);84}85// CHECK: declare arm_aapcs_vfpcc void @takes_struct_with_union_with_non_first_floats([5 x i32])86 87void test_return_struct_with_union_with_non_first_floats(void) {88 g_s_nf_f = returns_struct_with_union_with_non_first_floats();89}90// CHECK: declare arm_aapcs_vfpcc void @returns_struct_with_union_with_non_first_floats(ptr dead_on_unwind writable sret(%struct.struct_with_union_with_non_first_floats) align 4)91 92/* Plain array is not a homogenous aggregate */93extern void takes_array_of_floats(float a[4]);94void test_array_of_floats(void) {95 float a[4] = {1.0, 2.0, 3.0, 4.0};96 takes_array_of_floats(a);97}98// CHECK: declare arm_aapcs_vfpcc void @takes_array_of_floats(ptr noundef)99 100/* Struct-type homogenous aggregate */101typedef struct {102 float x, y, z, w;103} struct_with_fundamental_elems;104struct_with_fundamental_elems g_s;105 106extern void takes_struct_with_fundamental_elems(struct_with_fundamental_elems a);107extern struct_with_fundamental_elems returns_struct_with_fundamental_elems(void);108 109void test_struct_with_fundamental_elems(void) {110 takes_struct_with_fundamental_elems(g_s);111// CHECK: call arm_aapcs_vfpcc void @takes_struct_with_fundamental_elems(%struct.struct_with_fundamental_elems {{.*}})112}113// CHECK: declare arm_aapcs_vfpcc void @takes_struct_with_fundamental_elems(%struct.struct_with_fundamental_elems)114 115void test_return_struct_with_fundamental_elems(void) {116 g_s = returns_struct_with_fundamental_elems();117// CHECK: call arm_aapcs_vfpcc %struct.struct_with_fundamental_elems @returns_struct_with_fundamental_elems()118}119// CHECK: declare arm_aapcs_vfpcc %struct.struct_with_fundamental_elems @returns_struct_with_fundamental_elems()120 121/* Array-type homogenous aggregate */122typedef struct {123 float xyzw[4];124} struct_with_array;125struct_with_array g_s_a;126 127extern void takes_struct_with_array(struct_with_array a);128extern struct_with_array returns_struct_with_array(void);129 130void test_struct_with_array(void) {131 takes_struct_with_array(g_s_a);132// CHECK: call arm_aapcs_vfpcc void @takes_struct_with_array(%struct.struct_with_array {{.*}})133}134// CHECK: declare arm_aapcs_vfpcc void @takes_struct_with_array(%struct.struct_with_array)135 136void test_return_struct_with_array(void) {137 g_s_a = returns_struct_with_array();138// CHECK: call arm_aapcs_vfpcc %struct.struct_with_array @returns_struct_with_array()139}140// CHECK: declare arm_aapcs_vfpcc %struct.struct_with_array @returns_struct_with_array()141 142/* This union is a homogenous aggregate. Check that it's passed properly */143typedef union {144 struct_with_fundamental_elems xyzw;145 float a[3];146} union_with_struct_with_fundamental_elems;147union_with_struct_with_fundamental_elems g_u_s_fe;148 149extern void takes_union_with_struct_with_fundamental_elems(union_with_struct_with_fundamental_elems a);150extern union_with_struct_with_fundamental_elems returns_union_with_struct_with_fundamental_elems(void);151 152void test_union_with_struct_with_fundamental_elems(void) {153 takes_union_with_struct_with_fundamental_elems(g_u_s_fe);154// CHECK: call arm_aapcs_vfpcc void @takes_union_with_struct_with_fundamental_elems(%union.union_with_struct_with_fundamental_elems {{.*}})155}156// CHECK: declare arm_aapcs_vfpcc void @takes_union_with_struct_with_fundamental_elems(%union.union_with_struct_with_fundamental_elems)157 158void test_return_union_with_struct_with_fundamental_elems(void) {159 g_u_s_fe = returns_union_with_struct_with_fundamental_elems();160// CHECK: call arm_aapcs_vfpcc %union.union_with_struct_with_fundamental_elems @returns_union_with_struct_with_fundamental_elems()161}162// CHECK: declare arm_aapcs_vfpcc %union.union_with_struct_with_fundamental_elems @returns_union_with_struct_with_fundamental_elems()163 164// Make sure HAs that can be partially fit into VFP registers will be allocated165// on stack and that later VFP candidates will go on stack as well.166typedef struct {167 double x;168 double a2;169 double a3;170 double a4;171} struct_of_four_doubles;172extern void takes_struct_of_four_doubles(double a, struct_of_four_doubles b, struct_of_four_doubles c, double d);173struct_of_four_doubles g_s4d;174 175void test_struct_of_four_doubles(void) {176// CHECK: test_struct_of_four_doubles177// CHECK: call arm_aapcs_vfpcc void @takes_struct_of_four_doubles(double {{.*}}, %struct.struct_of_four_doubles {{.*}}, %struct.struct_of_four_doubles {{.*}}, double {{.*}})178// CHECK64: test_struct_of_four_doubles179// CHECK64: call void @takes_struct_of_four_doubles(double {{.*}}, [4 x double] {{.*}}, [4 x double] {{.*}}, double {{.*}})180 takes_struct_of_four_doubles(3.0, g_s4d, g_s4d, 4.0);181}182 183extern void takes_struct_of_four_doubles_variadic(double a, struct_of_four_doubles b, struct_of_four_doubles c, double d, ...);184 185void test_struct_of_four_doubles_variadic(void) {186// CHECK: test_struct_of_four_doubles_variadic187// CHECK: call arm_aapcs_vfpcc void (double, [4 x i64], [4 x i64], double, ...) @takes_struct_of_four_doubles_variadic(double {{.*}}, [4 x i64] {{.*}}, [4 x i64] {{.*}}, double {{.*}})188 takes_struct_of_four_doubles_variadic(3.0, g_s4d, g_s4d, 4.0);189}190 191extern void takes_struct_with_backfill(float f1, double a, float f2, struct_of_four_doubles b, struct_of_four_doubles c, double d);192void test_struct_with_backfill(void) {193// CHECK: test_struct_with_backfill194// CHECK: call arm_aapcs_vfpcc void @takes_struct_with_backfill(float {{.*}}, double {{.*}}, float {{.*}}, %struct.struct_of_four_doubles {{.*}}, %struct.struct_of_four_doubles {{.*}}, double {{.*}})195 takes_struct_with_backfill(3.0, 3.1, 3.2, g_s4d, g_s4d, 4.0);196}197 198typedef __attribute__(( ext_vector_type(8) )) char __char8;199typedef __attribute__(( ext_vector_type(4) )) short __short4;200typedef struct {201 __char8 a1;202 __short4 a2;203 __char8 a3;204 __short4 a4;205} struct_of_vecs;206extern void takes_struct_of_vecs(double a, struct_of_vecs b, struct_of_vecs c, double d);207struct_of_vecs g_vec;208 209void test_struct_of_vecs(void) {210// CHECK: test_struct_of_vecs211// CHECK: call arm_aapcs_vfpcc void @takes_struct_of_vecs(double {{.*}}, %struct.struct_of_vecs {{.*}}, %struct.struct_of_vecs {{.*}}, double {{.*}})212// CHECK64: test_struct_of_vecs213// CHECK64: call void @takes_struct_of_vecs(double {{.*}}, [4 x <8 x i8>] {{.*}}, [4 x <8 x i8>] {{.*}}, double {{.*}})214 takes_struct_of_vecs(3.0, g_vec, g_vec, 4.0);215}216 217typedef struct {218 double a;219 long double b;220} struct_of_double_and_long_double;221struct_of_double_and_long_double g_dld;222 223struct_of_double_and_long_double test_struct_of_double_and_long_double(void) {224 return g_dld;225}226// CHECK: define{{.*}} arm_aapcs_vfpcc %struct.struct_of_double_and_long_double @test_struct_of_double_and_long_double()227 228// FIXME: Tests necessary:229// - Vectors230// - C++ stuff231