1 // RUN: %clang_cc1 -std=c23 -triple x86_64-gnu-linux -O3 -disable-llvm-passes -emit-llvm -o - %s | FileCheck %s --check-prefixes=CHECK,CHECK64,LIN64 2 // RUN: %clang_cc1 -std=c23 -triple x86_64-windows-pc -O3 -disable-llvm-passes -emit-llvm -o - %s | FileCheck %s --check-prefixes=CHECK,CHECK64,WIN64 3 // RUN: %clang_cc1 -std=c23 -triple i386-gnu-linux -O3 -disable-llvm-passes -emit-llvm -o - %s | FileCheck %s --check-prefixes=CHECK,LIN32 4 // RUN: %clang_cc1 -std=c23 -triple i386-windows-pc -O3 -disable-llvm-passes -emit-llvm -o - %s | FileCheck %s --check-prefixes=CHECK,WIN32 5 6 // CHECK64: %struct.S1 = type { i32, [4 x i8], [24 x i8] } 7 // WIN32: %struct.S1 = type { i32, [4 x i8], [24 x i8] } 8 // LIN32: %struct.S1 = type { i32, [20 x i8] } 9 // CHECK64: %struct.S2 = type { [40 x i8], i32, [4 x i8] } 10 // WIN32: %struct.S2 = type { [40 x i8], i32, [4 x i8] } 11 // LIN32: %struct.S2 = type { [36 x i8], i32 } 12 // LIN64: %struct.S3 = type { [17 x i8], [7 x i8] } 13 // WIN64: %struct.S3 = type { [24 x i8] } 14 15 //GH62207 16 unsigned _BitInt(1) GlobSize1 = 0; 17 // CHECK: @GlobSize1 = {{.*}}global i8 0 18 19 // CHECK64: @__const.foo.A = private unnamed_addr constant { i32, [4 x i8], <{ i8, [23 x i8] }> } { i32 1, [4 x i8] zeroinitializer, <{ i8, [23 x i8] }> <{ i8 -86, [23 x i8] zeroinitializer }> }, align 8 20 // @BigGlob = global [40 x i8] c"\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF", align 8 21 // CHECK64: @f.p = internal global <{ i8, i8, [22 x i8] }> <{ i8 16, i8 39, [22 x i8] zeroinitializer }>, align 8 22 23 void GenericTest(_BitInt(3) a, unsigned _BitInt(3) b, _BitInt(4) c) { 24 // CHECK: define {{.*}}void @GenericTest 25 int which = _Generic(a, _BitInt(3): 1, unsigned _BitInt(3) : 2, _BitInt(4) : 3); 26 // CHECK: store i32 1 27 int which2 = _Generic(b, _BitInt(3): 1, unsigned _BitInt(3) : 2, _BitInt(4) : 3); 28 // CHECK: store i32 2 29 int which3 = _Generic(c, _BitInt(3): 1, unsigned _BitInt(3) : 2, _BitInt(4) : 3); 30 // CHECK: store i32 3 31 } 32 33 void VLATest(_BitInt(3) A, _BitInt(99) B, _BitInt(123) C) { 34 // CHECK: define {{.*}}void @VLATest 35 int AR1[A]; 36 // CHECK: %[[A:.+]] = zext i3 %{{.+}} to i[[INDXSIZE:[0-9]+]] 37 // CHECK: %[[VLA1:.+]] = alloca i32, i[[INDXSIZE]] %[[A]] 38 int AR2[B]; 39 // CHECK: %[[B:.+]] = trunc i99 %{{.+}} to i[[INDXSIZE]] 40 // CHECK: %[[VLA2:.+]] = alloca i32, i[[INDXSIZE]] %[[B]] 41 int AR3[C]; 42 // CHECK: %[[C:.+]] = trunc i123 %{{.+}} to i[[INDXSIZE]] 43 // CHECK: %[[VLA3:.+]] = alloca i32, i[[INDXSIZE]] %[[C]] 44 } 45 46 struct S { 47 _BitInt(17) A; 48 _BitInt(128) B; 49 _BitInt(17) C; 50 }; 51 52 void OffsetOfTest(void) { 53 // CHECK: define {{.*}}void @OffsetOfTest 54 int A = __builtin_offsetof(struct S,A); 55 // CHECK: store i32 0, ptr %{{.+}} 56 int B = __builtin_offsetof(struct S,B); 57 // CHECK64: store i32 8, ptr %{{.+}} 58 // LIN32: store i32 4, ptr %{{.+}} 59 // WIN32: store i32 8, ptr %{{.+}} 60 int C = __builtin_offsetof(struct S,C); 61 // CHECK64: store i32 24, ptr %{{.+}} 62 // LIN32: store i32 20, ptr %{{.+}} 63 // WIN32: store i32 24, ptr %{{.+}} 64 } 65 66 void Size1ExtIntParam(unsigned _BitInt(1) A) { 67 // CHECK: define {{.*}}void @Size1ExtIntParam(i1{{.*}} %[[PARAM:.+]]) 68 // CHECK: %[[PARAM_ADDR:.+]] = alloca i8 69 // CHECK: %[[B:.+]] = alloca [5 x i8] 70 // CHECK: %[[STOREDV:.+]] = zext i1 %[[PARAM]] to i8 71 // CHECK: store i8 %[[STOREDV]], ptr %[[PARAM_ADDR]] 72 unsigned _BitInt(1) B[5]; 73 74 // CHECK: %[[PARAM_LOAD:.+]] = load i8, ptr %[[PARAM_ADDR]] 75 // CHECK: %[[LOADEDV:.+]] = trunc i8 %0 to i1 76 // CHECK: %[[IDX:.+]] = getelementptr inbounds [5 x i8], ptr %[[B]] 77 // CHECK: %[[STOREDV1:.+]] = zext i1 %[[LOADEDV]] to i8 78 // CHECK: store i8 %[[STOREDV1]], ptr %[[IDX]] 79 B[2] = A; 80 } 81 82 #if __BITINT_MAXWIDTH__ > 128 83 struct S1 { 84 _BitInt(17) A; 85 _BitInt(129) B; 86 }; 87 88 int foo(int a) { 89 // CHECK: %A1 = getelementptr inbounds nuw %struct.S1, ptr %B, i32 0, i32 0 90 // CHECK: store i32 1, ptr %A1 91 // CHECK64: %B2 = getelementptr inbounds nuw %struct.S1, ptr %B, i32 0, i32 2 92 // WIN32: %B2 = getelementptr inbounds nuw %struct.S1, ptr %B, i32 0, i32 2 93 // LIN32: %B2 = getelementptr inbounds nuw %struct.S1, ptr %B, i32 0, i32 1 94 // CHECK: %[[V1:.+]] = load i32, ptr %a.addr, align 4 95 // CHECK: %conv = sext i32 %[[V1]] to i129 96 // CHECK64: storedv = sext i129 %conv to i192 97 // WIN32: storedv = sext i129 %conv to i192 98 // LIN32: storedv = sext i129 %conv to i160 99 // CHECK64: store i192 %storedv, ptr %B2, align 8 100 // WIN32: store i192 %storedv, ptr %B2, align 8 101 // LIN32: store i160 %storedv, ptr %B2, align 4 102 // CHECK64: %B3 = getelementptr inbounds nuw %struct.S1, ptr %A, i32 0, i32 2 103 // WIN32: %B3 = getelementptr inbounds nuw %struct.S1, ptr %A, i32 0, i32 2 104 // LIN32: %B3 = getelementptr inbounds nuw %struct.S1, ptr %A, i32 0, i32 1 105 // CHECK64: %[[V2:.+]] = load i192, ptr %B3, align 8 106 // WIN32: %[[V2:.+]] = load i192, ptr %B3, align 8 107 // LIN32: %[[V2:.+]] = load i160, ptr %B3, align 4 108 // CHECK64: %loadedv = trunc i192 %[[V2]] to i129 109 // WIN32: %loadedv = trunc i192 %[[V2]] to i129 110 // LIN32: %loadedv = trunc i160 %[[V2]] to i129 111 // CHECK: %conv4 = trunc i129 %loadedv to i32 112 struct S1 A = {1, 170}; 113 struct S1 B = {1, a}; 114 return (int)A.B + (int)B.B; 115 } 116 117 struct S2 { 118 _BitInt(257) A; 119 int B; 120 }; 121 122 _BitInt(257) bar() { 123 // CHECK64: define {{.*}}void @bar(ptr {{.*}} sret([40 x i8]) align 8 %[[RET:.+]]) 124 // CHECK64: %A = alloca %struct.S2, align 8 125 // CHECK64: %0 = getelementptr inbounds { <{ i8, [39 x i8] }>, i32, [4 x i8] }, ptr %A, i32 0, i32 0 126 // CHECK64: %1 = getelementptr inbounds <{ i8, [39 x i8] }>, ptr %0, i32 0, i32 0 127 // CHECK64: store i8 1, ptr %1, align 8 128 // CHECK64: %2 = getelementptr inbounds { <{ i8, [39 x i8] }>, i32, [4 x i8] }, ptr %A, i32 0, i32 1 129 // CHECK64: store i32 10000, ptr %2, align 8 130 // CHECK64: %A1 = getelementptr inbounds nuw %struct.S2, ptr %A, i32 0, i32 0 131 // CHECK64: %3 = load i320, ptr %A1, align 8 132 // CHECK64: %loadedv = trunc i320 %3 to i257 133 // CHECK64: %storedv = sext i257 %loadedv to i320 134 // CHECK64: store i320 %storedv, ptr %[[RET]], align 8 135 struct S2 A = {1, 10000}; 136 return A.A; 137 } 138 139 void TakesVarargs(int i, ...) { 140 // CHECK64: define{{.*}} void @TakesVarargs(i32 141 __builtin_va_list args; 142 __builtin_va_start(args, i); 143 144 _BitInt(160) A = __builtin_va_arg(args, _BitInt(160)); 145 // CHECK64: %[[ARG:.+]] = load i192 146 // CHECK64: %[[TRUNC:.+]] = trunc i192 %[[ARG]] to i160 147 // CHECK64: %[[SEXT:.+]] = sext i160 %[[TRUNC]] to i192 148 // CHECK64: store i192 %[[SEXT]], ptr %A, align 8 149 } 150 151 _BitInt(129) *f1(_BitInt(129) *p) { 152 // CHECK64: getelementptr inbounds [24 x i8], {{.*}} i64 1 153 return p + 1; 154 } 155 156 char *f2(char *p) { 157 // CHECK64: getelementptr inbounds nuw i8, {{.*}} i64 24 158 return p + sizeof(_BitInt(129)); 159 } 160 161 auto BigGlob = (_BitInt(257))-1; 162 // CHECK64: define {{.*}}void @foobar(ptr {{.*}} sret([40 x i8]) align 8 %[[RET1:.+]]) 163 _BitInt(257) foobar() { 164 // CHECK64: %A = alloca [40 x i8], align 8 165 // CHECK64: %0 = load i320, ptr @BigGlob, align 8 166 // CHECK64: %loadedv = trunc i320 %0 to i257 167 // CHECK64: %add = add nsw i257 %loadedv, 1 168 // CHECK64: %storedv = sext i257 %add to i320 169 // CHECK64: store i320 %storedv, ptr %A, align 8 170 // CHECK64: %1 = load i320, ptr %A, align 8 171 // CHECK64: %loadedv1 = trunc i320 %1 to i257 172 // CHECK64: %storedv2 = sext i257 %loadedv1 to i320 173 // CHECK64: store i320 %storedv2, ptr %[[RET1]], align 8 174 _BitInt(257) A = BigGlob + 1; 175 return A; 176 } 177 178 void f() { 179 static _BitInt(130) p = {10000}; 180 } 181 182 struct S3 { 183 _BitInt (136) A : 129; 184 }; 185 186 void bitField() { 187 struct S3 s = {1}; 188 struct { 189 _BitInt (136) A : 48; 190 int a; 191 } s1 = {s.A}; 192 s1.A = 36; 193 // LIN64: %s = alloca %struct.S3, align 8 194 // LIN64: %s1 = alloca %struct.anon, align 8 195 // LIN64: call void @llvm.memcpy.p0.p0.i64(ptr align 8 %s, ptr align 8 @__const.bitField.s, i64 24, i1 false) 196 // LIN64: %bf.load = load i136, ptr %s, align 8 197 // LIN64: %bf.shl = shl i136 %bf.load, 7 198 // LIN64: %bf.ashr = ashr i136 %bf.shl, 7 199 // LIN64: %0 = trunc i136 %bf.ashr to i64 200 // LIN64: %bf.load1 = load i64, ptr %s1, align 8 201 // LIN64: %bf.value = and i64 %0, 281474976710655 202 // LIN64: %bf.clear = and i64 %bf.load1, -281474976710656 203 // LIN64: %bf.set = or i64 %bf.clear, %bf.value 204 // LIN64: store i64 %bf.set, ptr %s1, align 8 205 // LIN64: %a = getelementptr inbounds nuw %struct.anon, ptr %s1, i32 0, i32 1 206 // LIN64: store i32 0, ptr %a, align 8 207 // LIN64: %bf.load2 = load i64, ptr %s1, align 8 208 // LIN64: %bf.clear3 = and i64 %bf.load2, -281474976710656 209 // LIN64: %bf.set4 = or i64 %bf.clear3, 36 210 // LIN64: store i64 %bf.set4, ptr %s1, align 8 211 } 212 213 #endif 214