118 lines · c
1// RUN: %clang_cc1 -triple aarch64-linux-gnu -emit-llvm < %s | FileCheck -check-prefixes=LINUX,COMMON %s2// RUN: %clang_cc1 -triple aarch64-pc-win32 -emit-llvm < %s | FileCheck -check-prefixes=WIN64,COMMON %s3 4struct small_odd {5 char a, b, c;6};7 8struct larger {9 int a, b, c, d, e;10};11 12void __attribute__((ms_abi)) f1(void);13void f2(void);14void f3(void) {15 // LINUX-LABEL: define{{.*}} void @f3()16 // WIN64-LABEL: define dso_local void @f3()17 f1();18 // LINUX: call win64cc void @f1()19 // WIN64: call void @f1()20 f2();21 // COMMON: call void @f2()22}23// LINUX: declare win64cc void @f1()24// LINUX: declare void @f2()25// WIN64: declare dso_local void @f1()26// WIN64: declare dso_local void @f2()27 28// Win64 ABI varargs29void __attribute__((ms_abi)) f4(int a, ...) {30 // LINUX-LABEL: define{{.*}} win64cc void @f431 // WIN64-LABEL: define dso_local void @f432 __builtin_ms_va_list ap;33 __builtin_ms_va_start(ap, a);34 // COMMON: %[[AP:.*]] = alloca ptr35 // COMMON: call void @llvm.va_start36 int b = __builtin_va_arg(ap, int);37 // COMMON: %[[AP_CUR:.*]] = load ptr, ptr %[[AP]]38 // COMMON-NEXT: %[[AP_NEXT:.*]] = getelementptr inbounds i8, ptr %[[AP_CUR]], i64 839 // COMMON-NEXT: store ptr %[[AP_NEXT]], ptr %[[AP]]40 __builtin_ms_va_list ap2;41 __builtin_ms_va_copy(ap2, ap);42 // COMMON: %[[AP_VAL:.*]] = load ptr, ptr %[[AP]]43 // COMMON-NEXT: store ptr %[[AP_VAL]], ptr %[[AP2:.*]]44 __builtin_ms_va_end(ap);45 // COMMON: call void @llvm.va_end46}47 48void __attribute__((ms_abi)) f4_2(int a, ...) {49 // LINUX-LABEL: define{{.*}} win64cc void @f4_250 // WIN64-LABEL: define dso_local void @f4_251 __builtin_ms_va_list ap;52 __builtin_ms_va_start(ap, a);53 // COMMON: %[[AP:.*]] = alloca ptr54 // COMMON: call void @llvm.va_start55 struct small_odd s1 = __builtin_va_arg(ap, struct small_odd);56 // COMMON: %[[AP_CUR:.*]] = load ptr, ptr %[[AP]]57 // COMMON-NEXT: %[[AP_NEXT:.*]] = getelementptr inbounds i8, ptr %[[AP_CUR]], i64 858 // COMMON-NEXT: store ptr %[[AP_NEXT]], ptr %[[AP]]59 struct larger s2 = __builtin_va_arg(ap, struct larger);60 // COMMON: %[[AP_CUR2:.*]] = load ptr, ptr %[[AP]]61 // COMMON-NEXT: %[[AP_NEXT3:.*]] = getelementptr inbounds i8, ptr %[[AP_CUR2]], i64 862 // COMMON-NEXT: store ptr %[[AP_NEXT3]], ptr %[[AP]]63 __builtin_ms_va_end(ap);64}65 66// Let's verify that normal va_lists work right on Win64, too.67void f5(int a, ...) {68 // WIN64-LABEL: define dso_local void @f569 __builtin_va_list ap;70 __builtin_va_start(ap, a);71 // WIN64: %[[AP:.*]] = alloca ptr72 // WIN64: call void @llvm.va_start73 int b = __builtin_va_arg(ap, int);74 // WIN64: %[[AP_CUR:.*]] = load ptr, ptr %[[AP]]75 // WIN64-NEXT: %[[AP_NEXT:.*]] = getelementptr inbounds i8, ptr %[[AP_CUR]], i64 876 // WIN64-NEXT: store ptr %[[AP_NEXT]], ptr %[[AP]]77 __builtin_va_list ap2;78 __builtin_va_copy(ap2, ap);79 // WIN64: call void @llvm.va_copy80 __builtin_va_end(ap);81 // WIN64: call void @llvm.va_end82}83 84struct HFA {85 float a, b, c;86};87 88__attribute__((ms_abi)) void msabi_hfa(struct HFA a);89__attribute__((ms_abi)) void msabi_hfa_vararg(struct HFA a, int b, ...);90 91void call_msabi_hfa(void) {92 // COMMON-LABEL: define{{.*}} void @call_msabi_hfa()93 // WIN64: call void @msabi_hfa([3 x float] {{.*}})94 // LINUX: call win64cc void @msabi_hfa([3 x float] {{.*}})95 msabi_hfa((struct HFA){1.0f, 2.0f, 3.0f});96}97 98void call_msabi_hfa_vararg(void) {99 // COMMON-LABEL: define{{.*}} void @call_msabi_hfa_vararg()100 // WIN64: call void ([2 x i64], i32, ...) @msabi_hfa_vararg([2 x i64] {{.*}}, i32 noundef 4, [2 x i64] {{.*}})101 // LINUX: call win64cc void ([2 x i64], i32, ...) @msabi_hfa_vararg([2 x i64] {{.*}}, i32 noundef 4, [2 x i64] {{.*}})102 msabi_hfa_vararg((struct HFA){1.0f, 2.0f, 3.0f}, 4,103 (struct HFA){5.0f, 6.0f, 7.0f});104}105 106__attribute__((ms_abi)) void get_msabi_hfa_vararg(int a, ...) {107 // COMMON-LABEL: define{{.*}} void @get_msabi_hfa_vararg108 __builtin_ms_va_list ap;109 __builtin_ms_va_start(ap, a);110 // COMMON: %[[AP:.*]] = alloca ptr111 // COMMON: call void @llvm.va_start112 struct HFA b = __builtin_va_arg(ap, struct HFA);113 // COMMON: %[[AP_CUR:.*]] = load ptr, ptr %[[AP]]114 // COMMON-NEXT: %[[AP_NEXT:.*]] = getelementptr inbounds i8, ptr %[[AP_CUR]], i64 16115 // COMMON-NEXT: store ptr %[[AP_NEXT]], ptr %[[AP]]116 __builtin_ms_va_end(ap);117}118