2012-07-10 02:34:21 +08:00
// REQUIRES: arm-registered-target
2012-04-13 19:23:39 +08:00
// RUN: %clang_cc1 -triple armv7---eabi -target-abi aapcs -mfloat-abi hard -emit-llvm %s -o - | FileCheck %s
2012-04-23 17:02:13 +08:00
typedef long long int64_t ;
typedef unsigned int uint32_t ;
2012-04-13 19:23:39 +08:00
/* 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()
2012-10-31 07:21:41 +08:00
// 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 ) ;
}
2014-01-28 18:56:36 +08:00
extern void takes_struct_of_four_doubles_variadic ( double a , struct_of_four_doubles b , struct_of_four_doubles c , double d , . . . ) ;
void test_struct_of_four_doubles_variadic ( void ) {
// CHECK: test_struct_of_four_doubles_variadic
// 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 {{.*}})
takes_struct_of_four_doubles_variadic ( 3.0 , g_s4d , g_s4d , 4.0 ) ;
}
2012-11-01 03:02:26 +08:00
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 ) ;
}
2012-10-31 07:21:41 +08:00
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 ) ;
}
2012-04-13 19:23:39 +08:00
// FIXME: Tests necessary:
// - Vectors
2012-07-10 02:34:21 +08:00
// - C++ stuff