brintos

brintos / llvm-project-archived public Read only

0
0
Text · 4.6 KiB · 4e61c78 Raw
132 lines · cpp
1// RUN: %clang_cc1 -triple armv7a-linux-gnueabi -emit-llvm -o - -x c %s | FileCheck %s --check-prefixes=CHECK,C2// RUN: %clang_cc1 -triple armv7a-linux-gnueabi -emit-llvm -o - %s | FileCheck %s --check-prefixes=CHECK,CXX3// RUN: %clang_cc1 -triple armv7a-linux-gnueabi -emit-llvm -o - %s -fclang-abi-compat=19 | FileCheck %s --check-prefixes=CHECK,CXXCLANG194// RUN: %clang_cc1 -triple thumbv7k-apple-watchos2.0 -target-abi aapcs16 -emit-llvm -o - %s | FileCheck %s --check-prefixes=CHECK,WATCHOS5 6// Empty structs are ignored for PCS purposes on WatchOS and in C mode7// elsewhere.  In C++ mode they consume a register slot though. Functions are8// slightly bigger than minimal to make confirmation against actual GCC9// behaviour easier.10 11#if __cplusplus12#define EXTERNC extern "C"13#else14#define EXTERNC15#endif16 17struct Empty {};18 19// C: define{{.*}} i32 @empty_arg(i32 noundef %a)20// CXX: define{{.*}} i32 @empty_arg(i8 %e.coerce, i32 noundef %a)21// CXXCLANG19: define{{.*}} i32 @empty_arg(i32 noundef %a)22// WATCHOS: define{{.*}} i32 @empty_arg(i32 noundef %a)23EXTERNC int empty_arg(struct Empty e, int a) {24  return a;25}26 27// C: define{{.*}} void @empty_ret()28// CXX: define{{.*}} void @empty_ret()29// CXXCLANG19: define{{.*}} void @empty_ret()30// WATCHOS: define{{.*}} void @empty_ret()31EXTERNC struct Empty empty_ret(void) {32  struct Empty e;33  return e;34}35 36// However, what counts as "empty" is a baroque mess. This is super-empty, it's37// ignored even in C++ mode. It also has sizeof == 0, violating C++, but that's38// legacy for you:39 40struct SuperEmpty {41  int arr[0];42};43 44// C: define{{.*}} i32 @super_empty_arg(i32 noundef %a)45// CXX: define{{.*}} i32 @super_empty_arg(i32 noundef %a)46// CXXCLANG19: define{{.*}} i32 @super_empty_arg(i32 noundef %a)47// WATCHOS: define{{.*}} i32 @super_empty_arg(i32 noundef %a)48EXTERNC int super_empty_arg(struct SuperEmpty e, int a) {49  return a;50}51 52struct SortOfEmpty {53  struct SuperEmpty e;54};55 56// C: define{{.*}} i32 @sort_of_empty_arg(i32 noundef %a)57// CXX: define{{.*}} i32 @sort_of_empty_arg(i8 %e.coerce, i32 noundef %a)58// CXXCLANG19: define{{.*}} i32 @sort_of_empty_arg(i32 noundef %a)59// WATCHOS: define{{.*}} i32 @sort_of_empty_arg(i32 noundef %a)60EXTERNC int sort_of_empty_arg(struct Empty e, int a) {61  return a;62}63 64// C: define{{.*}} void @sort_of_empty_ret()65// CXX: define{{.*}} void @sort_of_empty_ret()66// CXXCLANG19: define{{.*}} void @sort_of_empty_ret()67// WATCHOS: define{{.*}} void @sort_of_empty_ret()68EXTERNC struct SortOfEmpty sort_of_empty_ret(void) {69  struct SortOfEmpty e;70  return e;71}72 73#include <stdarg.h>74 75// va_arg matches the above rules, consuming an incoming argument in cases76// where one would be passed, and not doing so when the argument should be77// ignored.78 79EXTERNC int empty_arg_variadic(int a, ...) {80// CHECK-LABEL: @empty_arg_variadic(81// C: %argp.next = getelementptr inbounds i8, ptr %argp.cur, i32 482// C-NOT: {{ getelementptr }}83// CXX: %argp.next = getelementptr inbounds i8, ptr %argp.cur, i32 484// CXX: %argp.next2 = getelementptr inbounds i8, ptr %argp.cur1, i32 485// CXXCLANG19: %argp.next = getelementptr inbounds i8, ptr %argp.cur, i32 486// CXXCLANG19-NOT: {{ getelementptr }}87// WATCHOS: %argp.next = getelementptr inbounds i8, ptr %argp.cur, i32 488// WATCHOS-NOT: {{ getelementptr }}89  va_list vl;90  va_start(vl, a);91  struct Empty b = va_arg(vl, struct Empty);92  int c = va_arg(vl, int);93  va_end(vl);94  return c;95}96 97EXTERNC int super_empty_arg_variadic(int a, ...) {98// CHECK-LABEL: @super_empty_arg_variadic(99// C: %argp.next = getelementptr inbounds i8, ptr %argp.cur, i32 4100// C-NOT: {{ getelementptr }}101// CXX: %argp.next = getelementptr inbounds i8, ptr %argp.cur, i32 4102// CXX-NOT: {{ getelementptr }}103// CXXCLANG19: %argp.next = getelementptr inbounds i8, ptr %argp.cur, i32 4104// CXXCLANG19-NOT: {{ getelementptr }}105// WATCHOS: %argp.next = getelementptr inbounds i8, ptr %argp.cur, i32 4106// WATCHOS-NOT: {{ getelementptr }}107  va_list vl;108  va_start(vl, a);109  struct SuperEmpty b = va_arg(vl, struct SuperEmpty);110  int c = va_arg(vl, int);111  va_end(vl);112  return c;113}114 115EXTERNC int sort_of_empty_arg_variadic(int a, ...) {116// CHECK-LABEL: @sort_of_empty_arg_variadic(117// C: %argp.next = getelementptr inbounds i8, ptr %argp.cur, i32 4118// C-NOT: {{ getelementptr }}119// CXX: %argp.next = getelementptr inbounds i8, ptr %argp.cur, i32 4120// CXX-NOT: {{ getelementptr }}121// CXXCLANG19: %argp.next = getelementptr inbounds i8, ptr %argp.cur, i32 4122// CXXCLANG19-NOT: {{ getelementptr }}123// WATCHOS: %argp.next = getelementptr inbounds i8, ptr %argp.cur, i32 4124// WATCHOS-NOT: {{ getelementptr }}125  va_list vl;126  va_start(vl, a);127  struct SortOfEmpty b = va_arg(vl, struct SortOfEmpty);128  int c = va_arg(vl, int);129  va_end(vl);130  return c;131}132