brintos

brintos / llvm-project-archived public Read only

0
0
Text · 7.8 KiB · c284316 Raw
238 lines · cpp
1// RUN: %clang_cc1 -triple arm64-apple-ios7.0 -target-abi darwinpcs -emit-llvm -o - %s | FileCheck %s --check-prefixes=CHECK,DARWIN2// RUN: %clang_cc1 -triple aarch64-linux-gnu -emit-llvm -o - -x c %s | FileCheck %s --check-prefixes=CHECK,C,AAPCS3// RUN: %clang_cc1 -triple aarch64-linux-gnu -emit-llvm -o - %s | FileCheck %s --check-prefixes=CHECK,CXX,AAPCS4 5// Empty structs are ignored for PCS purposes on Darwin and in C mode elsewhere.6// In C++ mode on ELF they consume a register slot though. Functions are7// slightly bigger than minimal to make confirmation against actual GCC8// behaviour easier.9 10#if __cplusplus11#define EXTERNC extern "C"12#else13#define EXTERNC14#endif15 16struct Empty {};17 18// DARWIN: define{{.*}} i32 @empty_arg(i32 noundef %a)19// C: define{{.*}} i32 @empty_arg(i32 noundef %a)20// CXX: define{{.*}} i32 @empty_arg(i64 %e.coerce, i32 noundef %a)21EXTERNC int empty_arg(struct Empty e, int a) {22  return a;23}24 25// CXX: define{{.*}} i32 @empty_align8_arg(i64 %a.coerce, i32 noundef %b)26struct EmptyAlign8 { int __attribute__((aligned(8))) : 0; };27EXTERNC int empty_align8_arg(struct EmptyAlign8 a, int b) {28  return b;29}30 31// CXX: define{{.*}} i32 @empty_align16_arg(i128 %a.coerce, i32 noundef %b)32struct EmptyAlign16 { long long int __attribute__((aligned(16))) : 0; };33EXTERNC int empty_align16_arg(struct EmptyAlign16 a, int b) {34  return b;35}36 37// CXX: define{{.*}} i32 @empty_align32_arg(ptr dead_on_return noundef %a, i32 noundef %b)38struct EmptyAlign32 { long long int __attribute__((aligned(32))) : 0; };39EXTERNC int empty_align32_arg(struct EmptyAlign32 a, int b) {40  return b;41}42 43// DARWIN: define{{.*}} void @empty_ret()44// C: define{{.*}} void @empty_ret()45// CXX: define{{.*}} void @empty_ret()46EXTERNC struct Empty empty_ret(void) {47  struct Empty e;48  return e;49}50 51// However, what counts as "empty" is a baroque mess. This is super-empty, it's52// ignored even in C++ mode. It also has sizeof == 0, violating C++, but that's53// legacy for you:54 55struct SuperEmpty {56  int arr[0];57};58 59// DARWIN: define{{.*}} i32 @super_empty_arg(i32 noundef %a)60// C: define{{.*}} i32 @super_empty_arg(i32 noundef %a)61// CXX: define{{.*}} i32 @super_empty_arg(i32 noundef %a)62EXTERNC int super_empty_arg(struct SuperEmpty e, int a) {63  return a;64}65 66// This is also not empty, and non-standard. We previously considered it to67// consume a register slot, but GCC does not, so we match that.68 69struct SortOfEmpty {70  struct SuperEmpty e;71};72 73// DARWIN: define{{.*}} i32 @sort_of_empty_arg(i32 noundef %a)74// C: define{{.*}} i32 @sort_of_empty_arg(i32 noundef %a)75// CXX: define{{.*}} i32 @sort_of_empty_arg(i32 noundef %a)76EXTERNC int sort_of_empty_arg(struct SortOfEmpty e, int a) {77  return a;78}79 80// DARWIN: define{{.*}} void @sort_of_empty_ret()81// C: define{{.*}} void @sort_of_empty_ret()82// CXX: define{{.*}} void @sort_of_empty_ret()83EXTERNC struct SortOfEmpty sort_of_empty_ret(void) {84  struct SortOfEmpty e;85  return e;86}87 88#include <stdarg.h>89 90// va_arg matches the above rules, consuming an incoming argument in cases91// where one would be passed, and not doing so when the argument should be92// ignored.93 94EXTERNC struct Empty empty_arg_variadic(int a, ...) {95// CHECK-LABEL: @empty_arg_variadic(96// DARWIN-NOT: {{ getelementptr }}97// C-NOT: {{ getelementptr }}98// CXX: %new_reg_offs = add i32 %gr_offs, 899// CXX: %new_stack = getelementptr inbounds i8, ptr %stack, i64 8100  va_list vl;101  va_start(vl, a);102  struct Empty b = va_arg(vl, struct Empty);103  va_end(vl);104  return b;105}106 107EXTERNC struct SuperEmpty super_empty_arg_variadic(int a, ...) {108// CHECK-LABEL: @super_empty_arg_variadic(109// DARWIN-NOT: {{ getelementptr }}110// C-NOT: {{ getelementptr }}111// CXX-NOT: {{ getelementptr }}112  va_list vl;113  va_start(vl, a);114  struct SuperEmpty b = va_arg(vl, struct SuperEmpty);115  va_end(vl);116  return b;117}118 119EXTERNC struct SortOfEmpty sort_of_empty_arg_variadic(int a, ...) {120// CHECK-LABEL: @sort_of_empty_arg_variadic(121// DARWIN: %argp.next = getelementptr inbounds i8, ptr %argp.cur, i64 0122// C-NOT: {{ getelementptr }}123// CXX-NOT: {{ getelementptr }}124  va_list vl;125  va_start(vl, a);126  struct SortOfEmpty b = va_arg(vl, struct SortOfEmpty);127  va_end(vl);128  return b;129}130 131// Base case, nothing interesting.132struct S {133  long x, y;134};135 136// CHECK-LABEL: @g_S(137// CHECK: call void @f_S(i64 noundef 1, [2 x i64] {{.*}})138// CHECK: call void @fm_S(i64 noundef 1, i64 noundef 2, i64 noundef 3, i64 noundef 4, i64 noundef 5, [2 x i64] {{.*}})139EXTERNC void f_S(long, struct S);140EXTERNC void fm_S(long, long, long, long, long, struct S);141EXTERNC void g_S() {142  struct S s = {6, 7};143  f_S(1, s);144  fm_S(1, 2, 3, 4, 5, s);145}146 147// Aligned struct passed according to its natural alignment.148struct __attribute__((aligned(16))) S16 {149  long x, y;150};151 152// CHECK-LABEL: @g_S16(153// DARWIN: call void @f_S16(i64 noundef 1, i128 {{.*}})154// AAPCS: call void @f_S16(i64 noundef 1, [2 x i64] {{.*}})155// DARWIN: call void @fm_S16(i64 noundef 1, i64 noundef 2, i64 noundef 3, i64 noundef 4, i64 noundef 5, i128 {{.*}})156// AAPCS: call void @fm_S16(i64 noundef 1, i64 noundef 2, i64 noundef 3, i64 noundef 4, i64 noundef 5, [2 x i64] {{.*}})157EXTERNC void f_S16(long, struct S16);158EXTERNC void fm_S16(long, long, long, long, long, struct S16);159EXTERNC void g_S16() {160  struct S16 s = {6, 7};161  f_S16(1, s);162  fm_S16(1, 2, 3, 4, 5, s);163}164 165// Aligned struct with increased natural alignment through an aligned field.166struct SF16 {167  __attribute__((aligned(16))) long x;168  long y;169};170 171// CHECK-LABEL: @g_SF16(172// DARWIN: call void @f_SF16(i64 noundef 1, i128 {{.*}})173// AAPCS: call void @f_SF16(i64 noundef 1, i128 {{.*}})174// DARWIN: call void @fm_SF16(i64 noundef 1, i64 noundef 2, i64 noundef 3, i64 noundef 4, i64 noundef 5, i128 {{.*}})175// AAPCS: call void @fm_SF16(i64 noundef 1, i64 noundef 2, i64 noundef 3, i64 noundef 4, i64 noundef 5, i128 {{.*}})176EXTERNC void f_SF16(long, struct SF16);177EXTERNC void fm_SF16(long, long, long, long, long, struct SF16);178EXTERNC void g_SF16() {179  struct SF16 s = {6, 7};180  f_SF16(1, s);181  fm_SF16(1, 2, 3, 4, 5, s);182}183 184#ifdef __cplusplus185// Aligned struct with increased natural alignment through an aligned base class.186struct SB16 : S16 {};187 188// DARWIN-LABEL: @g_SB16(189// CXX-LABEL: @g_SB16(190// DARWIN: call void @f_SB16(i64 noundef 1, i128 {{.*}})191// CXX: call void @f_SB16(i64 noundef 1, i128 {{.*}})192// DARWIN: call void @fm_SB16(i64 noundef 1, i64 noundef 2, i64 noundef 3, i64 noundef 4, i64 noundef 5, i128 {{.*}})193// CXX: call void @fm_SB16(i64 noundef 1, i64 noundef 2, i64 noundef 3, i64 noundef 4, i64 noundef 5, i128 {{.*}})194EXTERNC void f_SB16(long, struct SB16);195EXTERNC void fm_SB16(long, long, long, long, long, struct SB16);196EXTERNC void g_SB16() {197  struct SB16 s = {6, 7};198  f_SB16(1, s);199  fm_SB16(1, 2, 3, 4, 5, s);200}201#endif202 203// Packed structure.204struct  __attribute__((packed)) SP {205  int x;206  long y;207};208 209// CHECK-LABEL: @g_SP(210// CHECK: call void @f_SP(i32 noundef 1, [2 x i64] {{.*}})211// CHECK: call void @fm_SP(i32 noundef 1, i32 noundef 2, i32 noundef 3, i32 noundef 4, i32 noundef 5, [2 x i64] {{.*}})212EXTERNC void f_SP(int, struct SP);213EXTERNC void fm_SP(int, int, int, int, int, struct SP);214EXTERNC void g_SP() {215  struct SP s = {6, 7};216  f_SP(1, s);217  fm_SP(1, 2, 3, 4, 5, s);218}219 220// Packed structure, overaligned, same as above.221struct  __attribute__((packed, aligned(16))) SP16 {222  int x;223  long y;224};225 226// CHECK-LABEL: @g_SP16(227// DARWIN: call void @f_SP16(i32 noundef 1, i128 {{.*}})228// AAPCS: call void @f_SP16(i32 noundef 1, [2 x i64] {{.*}})229// DARWIN: call void @fm_SP16(i32 noundef 1, i32 noundef 2, i32 noundef 3, i32 noundef 4, i32 noundef 5, i128 {{.*}})230// AAPCS: call void @fm_SP16(i32 noundef 1, i32 noundef 2, i32 noundef 3, i32 noundef 4, i32 noundef 5, [2 x i64] {{.*}})231EXTERNC void f_SP16(int, struct SP16);232EXTERNC void fm_SP16(int, int, int, int, int, struct SP16);233EXTERNC void g_SP16() {234  struct SP16 s = {6, 7};235  f_SP16(1, s);236  fm_SP16(1, 2, 3, 4, 5, s);237}238