1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194
|
// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -emit-llvm -w -o - %s | FileCheck -check-prefix=PCS %s
// Sign extension is performed by the callee on AArch64, which means
// that we *shouldn't* tag arguments and returns with their extension.
// PCS-LABEL: define i8 @f0(i16 %a)
char f0(short a) {
return a;
}
// PCS: define [1 x i64] @f1()
struct s1 { char f0; };
struct s1 f1(void) {}
// PCS: define [1 x i64] @f2()
struct s2 { short f0; };
struct s2 f2(void) {}
// PCS: define [1 x i64] @f3()
struct s3 { int f0; };
struct s3 f3(void) {}
// PCS: define [1 x i64] @f4()
struct s4 { struct s4_0 { int f0; } f0; };
struct s4 f4(void) {}
// PCS: define [1 x i64] @f5()
struct s5 { struct { } f0; int f1; };
struct s5 f5(void) {}
// PCS: define [1 x i64] @f6()
struct s6 { int f0[1]; };
struct s6 f6(void) {}
// PCS-LABEL: define void @f7()
struct s7 { struct { int : 0; } f0; };
struct s7 f7(void) {}
// PCS-LABEL: define void @f8()
struct s8 { struct { int : 0; } f0[1]; };
struct s8 f8(void) {}
// PCS: define [1 x i64] @f9()
struct s9 { long f0; int : 0; };
struct s9 f9(void) {}
// PCS: define [1 x i64] @f10()
struct s10 { long f0; int : 0; int : 0; };
struct s10 f10(void) {}
// PCS: define [1 x i64] @f11()
struct s11 { int : 0; long f0; };
struct s11 f11(void) {}
// PCS: define [1 x i64] @f12()
union u12 { char f0; short f1; int f2; long f3; };
union u12 f12(void) {}
// PCS-LABEL: define %struct.s13 @f13()
struct s13 { float f0; };
struct s13 f13(void) {}
// PCS-LABEL: define %union.u14 @f14()
union u14 { float f0; };
union u14 f14(void) {}
// PCS-LABEL: define void @f15()
void f15(struct s7 a0) {}
// PCS-LABEL: define void @f16()
void f16(struct s8 a0) {}
// PCS: define [1 x i64] @f17()
struct s17 { short f0 : 13; char f1 : 4; };
struct s17 f17(void) {}
// PCS: define [1 x i64] @f18()
struct s18 { short f0; char f1 : 4; };
struct s18 f18(void) {}
// PCS: define [1 x i64] @f19()
struct s19 { long f0; struct s8 f1; };
struct s19 f19(void) {}
// PCS: define [1 x i64] @f20()
struct s20 { struct s8 f1; long f0; };
struct s20 f20(void) {}
// PCS: define [1 x i64] @f21()
struct s21 { struct {} f1; long f0 : 4; };
struct s21 f21(void) {}
// PCS: define { float, float } @f22()
// PCS: define { double, double } @f23(
_Complex float f22(void) {}
_Complex double f23(void) {}
// PCS: define [1 x i64] @f24()
struct s24 { _Complex char f0; };
struct s24 f24() {}
// PCS: define [1 x i64] @f25()
struct s25 { _Complex short f0; };
struct s25 f25() {}
// PCS: define [1 x i64] @f26()
struct s26 { _Complex int f0; };
struct s26 f26() {}
// PCS: define [2 x i64] @f27()
struct s27 { _Complex long f0; };
struct s27 f27() {}
// PCS-LABEL: define void @f28(i8 %a, i16 %b, i32 %c, i64 %d, float %e, double %f)
void f28(char a, short b, int c, long d, float e, double f) {}
// PCS: define void @f29([2 x i64] %a
struct s29 { int arr[4]; };
void f29(struct s29 a) {}
// PCS-LABEL: define void @f30(%struct.s30* %a)
struct s30 { int arr[4]; char c;};
void f30(struct s30 a) {}
// PCS: define void @f31([4 x double] %a
struct s31 { double arr[4]; };
void f31(struct s31 a) {}
// PCS-LABEL: define void @f32(%struct.s32* %a)
struct s32 { float arr[5]; };
void f32(struct s32 a) {}
// Not the only solution, but it *is* an HFA.
// PCS: define void @f33([3 x float] %a.coerce0, float %a.coerce1)
struct s33 { float arr[3]; float a; };
void f33(struct s33 a) {}
// PCS-LABEL: define void @f34(%struct.s34* noalias sret
struct s34 { int a[4]; char b };
struct s34 f34(void) {}
// PCS-LABEL: define void @f35()
struct s35 {};
void f35(struct s35 a) {}
// Check padding is added:
// PCS: @f36(i32 %x0, i32 %x1, i32 %x2, i32 %x3, i32 %x4, i32 %x5, i32 %x6, [1 x i64], %struct.s36* byval align 8 %stacked)
struct s36 { long a, b; };
void f36(int x0, int x1, int x2, int x3, int x4, int x5, int x6, struct s36 stacked) {}
// But only once:
// PCS: @f37(i32 %x0, i32 %x1, i32 %x2, i32 %x3, i32 %x4, i32 %x5, i32 %x6, [1 x i64], %struct.s37* byval align 8 %stacked, %struct.s37* byval align 8 %stacked2)
struct s37 { long a, b; };
void f37(int x0, int x1, int x2, int x3, int x4, int x5, int x6, struct s37 stacked, struct s37 stacked2) {}
// Check for HFA padding args. Also, they should not end up on the stack in a
// way which will have holes in when lowered further by LLVM. In particular [3 x
// float] would be unacceptable.
// PCS: @f38(float %s0, double %d1, float %s2, float %s3, float %s4, float %s5, [2 x float], %struct.s38* byval align 4 %stacked)
struct s38 { float a, b, c; };
void f38(float s0, double d1, float s2, float s3, float s4, float s5, struct s38 stacked) {}
// Check both VFP and integer arguments are padded (also that pointers and enums
// get counted as integer types correctly).
struct s39_int { long a, b; };
struct s39_float { float a, b, c, d; };
enum s39_enum { Val1, Val2 };
// PCS: @f39(float %s0, i32 %x0, float %s1, i32* %x1, float %s2, i32 %x2, float %s3, float %s4, i32 %x3, [3 x float], %struct.s39_float* byval align 4 %stacked, i32 %x4, i32 %x5, i32 %x6, [1 x i64], %struct.s39_int* byval align 8 %stacked2)
void f39(float s0, int x0, float s1, int *x1, float s2, enum s39_enum x2, float s3, float s4,
int x3, struct s39_float stacked, int x4, int x5, int x6,
struct s39_int stacked2) {}
struct s40 { __int128 a; };
// PCS: @f40(i32 %x0, [1 x i128] %x2_3.coerce, i32 %x4, i32 %x5, i32 %x6, [1 x i64], %struct.s40* byval align 16 %stacked)
void f40(int x0, struct s40 x2_3, int x4, int x5, int x6, struct s40 stacked) {}
// Checking: __int128 will get properly aligned type, with padding so big struct doesn't use x7.
struct s41 { int arr[5]; };
// PCS: @f41(i32 %x0, i32 %x1, i32 %x2, i32 %x3, i32 %x4, i32 %x5, i32 %x6, [1 x i64], i128* byval align 16, %struct.s41* %stacked2)
int f41(int x0, int x1, int x2, int x3, int x4, int x5, int x6, __int128 stacked, struct s41 stacked2) {}
// Checking: __int128 needing to be aligned in registers will consume correct
// number. Previously padding was inserted before "stacked" because x6_7 was
// "allocated" to x5 and x6 by clang.
// PCS: @f42(i32 %x0, i32 %x1, i32 %x2, i32 %x3, i32 %x4, i128 %x6_7, i128* byval align 16)
void f42(int x0, int x1, int x2, int x3, int x4, __int128 x6_7, __int128 stacked) {}
// Checking: __fp16 is extended to double when calling variadic functions
void variadic(int a, ...);
void f43(__fp16 *in) {
variadic(42, *in);
// CHECK: call void @variadic(i32 42, double
}
|