brintos

brintos / llvm-project-archived public Read only

0
0
Text · 6.8 KiB · 2047feb Raw
151 lines · c
1// RUN: %clang_cc1 -triple x86_64-unknown-freebsd10.0 -emit-llvm < %s | FileCheck -check-prefix=FREEBSD %s2// RUN: %clang_cc1 -triple x86_64-pc-win32 -emit-llvm < %s | FileCheck -check-prefix=WIN64 %s3// RUN: %clang_cc1 -triple x86_64-mingw    -emit-llvm < %s | FileCheck -check-prefix=WIN64 %s4// RUN: %clang_cc1 -triple x86_64-cygwin   -emit-llvm < %s | FileCheck -check-prefix=WIN64 %s5// RUN: %clang_cc1 -triple x86_64-uefi -emit-llvm < %s | FileCheck -check-prefix=WIN64 %s6 7struct foo {8  int x;9  float y;10  char z;11};12// FREEBSD: %[[STRUCT_FOO:.*]] = type { i32, float, i8 }13// WIN64: %[[STRUCT_FOO:.*]] = type { i32, float, i8 }14 15void __attribute__((ms_abi)) f1(void);16void __attribute__((sysv_abi)) f2(void);17void f3(void) {18  // FREEBSD-LABEL: define{{.*}} void @f3()19  // WIN64-LABEL: define dso_local void @f3()20  f1();21  // FREEBSD: call win64cc void @f1()22  // WIN64: call void @f1()23  f2();24  // FREEBSD: call void @f2()25  // WIN64: call x86_64_sysvcc void @f2()26}27// FREEBSD: declare win64cc void @f1()28// FREEBSD: declare void @f2()29// WIN64: declare dso_local void @f1()30// WIN64: declare dso_local x86_64_sysvcc void @f2()31 32// Win64 ABI varargs33void __attribute__((ms_abi)) f4(int a, ...) {34  // FREEBSD-LABEL: define{{.*}} win64cc void @f435  // WIN64-LABEL: define dso_local void @f436  __builtin_ms_va_list ap;37  __builtin_ms_va_start(ap, a);38  // FREEBSD: %[[AP:.*]] = alloca ptr39  // FREEBSD: call void @llvm.va_start40  // WIN64: %[[AP:.*]] = alloca ptr41  // WIN64: call void @llvm.va_start42  int b = __builtin_va_arg(ap, int);43  // FREEBSD: %[[AP_CUR:.*]] = load ptr, ptr %[[AP]]44  // FREEBSD-NEXT: %[[AP_NEXT:.*]] = getelementptr inbounds i8, ptr %[[AP_CUR]], i64 845  // FREEBSD-NEXT: store ptr %[[AP_NEXT]], ptr %[[AP]]46  // WIN64: %[[AP_CUR:.*]] = load ptr, ptr %[[AP]]47  // WIN64-NEXT: %[[AP_NEXT:.*]] = getelementptr inbounds i8, ptr %[[AP_CUR]], i64 848  // WIN64-NEXT: store ptr %[[AP_NEXT]], ptr %[[AP]]49  double _Complex c = __builtin_va_arg(ap, double _Complex);50  // FREEBSD: %[[AP_CUR2:.*]] = load ptr, ptr %[[AP]]51  // FREEBSD-NEXT: %[[AP_NEXT2:.*]] = getelementptr inbounds i8, ptr %[[AP_CUR2]], i64 852  // FREEBSD-NEXT: store ptr %[[AP_NEXT2]], ptr %[[AP]]53  // FREEBSD-NEXT: load ptr, ptr %[[AP_CUR2]]54  // WIN64: %[[AP_CUR2:.*]] = load ptr, ptr %[[AP]]55  // WIN64-NEXT: %[[AP_NEXT2:.*]] = getelementptr inbounds i8, ptr %[[AP_CUR2]], i64 856  // WIN64-NEXT: store ptr %[[AP_NEXT2]], ptr %[[AP]]57  // WIN64-NEXT: load ptr, ptr %[[AP_CUR2]]58  struct foo d = __builtin_va_arg(ap, struct foo);59  // FREEBSD: %[[AP_CUR3:.*]] = load ptr, ptr %[[AP]]60  // FREEBSD-NEXT: %[[AP_NEXT3:.*]] = getelementptr inbounds i8, ptr %[[AP_CUR3]], i64 861  // FREEBSD-NEXT: store ptr %[[AP_NEXT3]], ptr %[[AP]]62  // FREEBSD-NEXT: load ptr, ptr %[[AP_CUR3]]63  // WIN64: %[[AP_CUR3:.*]] = load ptr, ptr %[[AP]]64  // WIN64-NEXT: %[[AP_NEXT3:.*]] = getelementptr inbounds i8, ptr %[[AP_CUR3]], i64 865  // WIN64-NEXT: store ptr %[[AP_NEXT3]], ptr %[[AP]]66  // WIN64-NEXT: load ptr, ptr %[[AP_CUR3]]67  __builtin_ms_va_list ap2;68  __builtin_ms_va_copy(ap2, ap);69  // FREEBSD: %[[AP_VAL:.*]] = load ptr, ptr %[[AP]]70  // FREEBSD-NEXT: store ptr %[[AP_VAL]], ptr %[[AP2:.*]]71  // WIN64: %[[AP_VAL:.*]] = load ptr, ptr %[[AP]]72  // WIN64-NEXT: store ptr %[[AP_VAL]], ptr %[[AP2:.*]]73  __builtin_ms_va_end(ap);74  // FREEBSD: call void @llvm.va_end75  // WIN64: call void @llvm.va_end76}77 78// Let's verify that normal va_lists work right on Win64, too.79void f5(int a, ...) {80  // WIN64-LABEL: define dso_local void @f581  __builtin_va_list ap;82  __builtin_va_start(ap, a);83  // WIN64: %[[AP:.*]] = alloca ptr84  // WIN64: call void @llvm.va_start85  int b = __builtin_va_arg(ap, int);86  // WIN64: %[[AP_CUR:.*]] = load ptr, ptr %[[AP]]87  // WIN64-NEXT: %[[AP_NEXT:.*]] = getelementptr inbounds i8, ptr %[[AP_CUR]], i64 888  // WIN64-NEXT: store ptr %[[AP_NEXT]], ptr %[[AP]]89  double _Complex c = __builtin_va_arg(ap, double _Complex);90  // WIN64: %[[AP_CUR2:.*]] = load ptr, ptr %[[AP]]91  // WIN64-NEXT: %[[AP_NEXT2:.*]] = getelementptr inbounds i8, ptr %[[AP_CUR2]], i64 892  // WIN64-NEXT: store ptr %[[AP_NEXT2]], ptr %[[AP]]93  struct foo d = __builtin_va_arg(ap, struct foo);94  // WIN64: %[[AP_CUR3:.*]] = load ptr, ptr %[[AP]]95  // WIN64-NEXT: %[[AP_NEXT3:.*]] = getelementptr inbounds i8, ptr %[[AP_CUR3]], i64 896  // WIN64-NEXT: store ptr %[[AP_NEXT3]], ptr %[[AP]]97  __builtin_va_list ap2;98  __builtin_va_copy(ap2, ap);99  // WIN64: call void @llvm.va_copy100  __builtin_va_end(ap);101  // WIN64: call void @llvm.va_end102}103 104// Verify that using a Win64 va_list from a System V function works.105void __attribute__((sysv_abi)) f6(__builtin_ms_va_list ap) {106  // FREEBSD-LABEL: define{{.*}} void @f6107  // FREEBSD: store ptr %ap, ptr %[[AP:.*]]108  // WIN64-LABEL: define dso_local x86_64_sysvcc void @f6109  // WIN64: store ptr %ap, ptr %[[AP:.*]]110  int b = __builtin_va_arg(ap, int);111  // FREEBSD: %[[AP_CUR:.*]] = load ptr, ptr %[[AP]]112  // FREEBSD-NEXT: %[[AP_NEXT:.*]] = getelementptr inbounds i8, ptr %[[AP_CUR]], i64 8113  // FREEBSD-NEXT: store ptr %[[AP_NEXT]], ptr %[[AP]]114  // WIN64: %[[AP_CUR:.*]] = load ptr, ptr %[[AP]]115  // WIN64-NEXT: %[[AP_NEXT:.*]] = getelementptr inbounds i8, ptr %[[AP_CUR]], i64 8116  // WIN64-NEXT: store ptr %[[AP_NEXT]], ptr %[[AP]]117  double _Complex c = __builtin_va_arg(ap, double _Complex);118  // FREEBSD: %[[AP_CUR2:.*]] = load ptr, ptr %[[AP]]119  // FREEBSD-NEXT: %[[AP_NEXT2:.*]] = getelementptr inbounds i8, ptr %[[AP_CUR2]], i64 8120  // FREEBSD-NEXT: store ptr %[[AP_NEXT2]], ptr %[[AP]]121  // WIN64: %[[AP_CUR2:.*]] = load ptr, ptr %[[AP]]122  // WIN64-NEXT: %[[AP_NEXT2:.*]] = getelementptr inbounds i8, ptr %[[AP_CUR2]], i64 8123  // WIN64-NEXT: store ptr %[[AP_NEXT2]], ptr %[[AP]]124  struct foo d = __builtin_va_arg(ap, struct foo);125  // FREEBSD: %[[AP_CUR3:.*]] = load ptr, ptr %[[AP]]126  // FREEBSD-NEXT: %[[AP_NEXT3:.*]] = getelementptr inbounds i8, ptr %[[AP_CUR3]], i64 8127  // FREEBSD-NEXT: store ptr %[[AP_NEXT3]], ptr %[[AP]]128  // WIN64: %[[AP_CUR3:.*]] = load ptr, ptr %[[AP]]129  // WIN64-NEXT: %[[AP_NEXT3:.*]] = getelementptr inbounds i8, ptr %[[AP_CUR3]], i64 8130  // WIN64-NEXT: store ptr %[[AP_NEXT3]], ptr %[[AP]]131  __builtin_ms_va_list ap2;132  __builtin_ms_va_copy(ap2, ap);133  // FREEBSD: %[[AP_VAL:.*]] = load ptr, ptr %[[AP]]134  // FREEBSD-NEXT: store ptr %[[AP_VAL]], ptr %[[AP2:.*]]135  // WIN64: %[[AP_VAL:.*]] = load ptr, ptr %[[AP]]136  // WIN64-NEXT: store ptr %[[AP_VAL]], ptr %[[AP2:.*]]137}138 139// This test checks if structs are passed according to Win64 calling convention140// when it's enforced by __attribute((ms_abi)).141struct i128 {142  unsigned long long a;143  unsigned long long b;144};145 146__attribute__((ms_abi)) struct i128 f7(struct i128 a) {147  // WIN64: define dso_local void @f7(ptr dead_on_unwind noalias writable sret(%struct.i128) align 8 %agg.result, ptr dead_on_return noundef %a)148  // FREEBSD: define{{.*}} win64cc void @f7(ptr dead_on_unwind noalias writable sret(%struct.i128) align 8 %agg.result, ptr dead_on_return noundef %a)149  return a;150}151