xref: /llvm-project/clang/test/CodeGen/linux-kernel-struct-union-initializer2.c (revision 627746581b8fde4143533937130f420bbbdf9ddf)
1*62774658Syabinc // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --check-globals all --version 5
2*62774658Syabinc // RUN: %clang_cc1 -triple x86_64-unknown-unknown -std=gnu11 -verify -emit-llvm %s -o - | FileCheck %s
3*62774658Syabinc // expected-no-diagnostics
4*62774658Syabinc 
5*62774658Syabinc union U1 {
6*62774658Syabinc   int x;
7*62774658Syabinc   char y[5];
8*62774658Syabinc };
9*62774658Syabinc 
10*62774658Syabinc struct S1 {
11*62774658Syabinc   int x;
12*62774658Syabinc   long long y;
13*62774658Syabinc };
14*62774658Syabinc 
15*62774658Syabinc struct S2 {
16*62774658Syabinc   unsigned char b1 : 3; // 1st 3 bits (in 1st byte) are b1
17*62774658Syabinc   unsigned char    : 2; // next 2 bits (in 1st byte) are blocked out as unused
18*62774658Syabinc   unsigned char b2 : 6; // 6 bits for b2 - doesn't fit into the 1st byte => starts a 2nd
19*62774658Syabinc   unsigned char b3 : 2; // 2 bits for b3 - next (and final) bits in the 2nd byte
20*62774658Syabinc   int i;
21*62774658Syabinc };
22*62774658Syabinc 
23*62774658Syabinc struct S3 {
24*62774658Syabinc   int x;
25*62774658Syabinc } __attribute__((__aligned__(8)));
26*62774658Syabinc 
27*62774658Syabinc struct S4 {
28*62774658Syabinc   int a;
29*62774658Syabinc   union U1 b;
30*62774658Syabinc };
31*62774658Syabinc 
32*62774658Syabinc struct S5 {
33*62774658Syabinc   char x;
34*62774658Syabinc   unsigned char y : 4;
35*62774658Syabinc   unsigned char z : 7;
36*62774658Syabinc } __attribute__((packed));
37*62774658Syabinc 
38*62774658Syabinc // Test non-const initializer for union with padding.
39*62774658Syabinc // CHECK-LABEL: define dso_local void @test1(
40*62774658Syabinc // CHECK-SAME: i32 noundef [[X:%.*]]) #[[ATTR0:[0-9]+]] {
41*62774658Syabinc // CHECK-NEXT:  [[ENTRY:.*:]]
42*62774658Syabinc // CHECK-NEXT:    [[X_ADDR:%.*]] = alloca i32, align 4
43*62774658Syabinc // CHECK-NEXT:    [[A:%.*]] = alloca [[UNION_U1:%.*]], align 4
44*62774658Syabinc // CHECK-NEXT:    store i32 [[X]], ptr [[X_ADDR]], align 4
45*62774658Syabinc // CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[X_ADDR]], align 4
46*62774658Syabinc // CHECK-NEXT:    store i32 [[TMP0]], ptr [[A]], align 4
47*62774658Syabinc // CHECK-NEXT:    [[TMP1:%.*]] = getelementptr i8, ptr [[A]], i64 4
48*62774658Syabinc // CHECK-NEXT:    call void @llvm.memset.p0.i64(ptr align 4 [[TMP1]], i8 0, i64 4, i1 false)
49*62774658Syabinc // CHECK-NEXT:    ret void
50*62774658Syabinc //
51*62774658Syabinc void test1(int x) {
52*62774658Syabinc   union U1 a = {x};
53*62774658Syabinc }
54*62774658Syabinc 
55*62774658Syabinc // Test non-const initializer for struct with padding.
56*62774658Syabinc // CHECK-LABEL: define dso_local void @test2(
57*62774658Syabinc // CHECK-SAME: i64 noundef [[Y:%.*]]) #[[ATTR0]] {
58*62774658Syabinc // CHECK-NEXT:  [[ENTRY:.*:]]
59*62774658Syabinc // CHECK-NEXT:    [[Y_ADDR:%.*]] = alloca i64, align 8
60*62774658Syabinc // CHECK-NEXT:    [[S:%.*]] = alloca [[STRUCT_S1:%.*]], align 8
61*62774658Syabinc // CHECK-NEXT:    store i64 [[Y]], ptr [[Y_ADDR]], align 8
62*62774658Syabinc // CHECK-NEXT:    [[X:%.*]] = getelementptr inbounds nuw [[STRUCT_S1]], ptr [[S]], i32 0, i32 0
63*62774658Syabinc // CHECK-NEXT:    store i32 0, ptr [[X]], align 8
64*62774658Syabinc // CHECK-NEXT:    [[TMP0:%.*]] = getelementptr i8, ptr [[S]], i64 4
65*62774658Syabinc // CHECK-NEXT:    call void @llvm.memset.p0.i64(ptr align 4 [[TMP0]], i8 0, i64 4, i1 false)
66*62774658Syabinc // CHECK-NEXT:    [[Y1:%.*]] = getelementptr inbounds nuw [[STRUCT_S1]], ptr [[S]], i32 0, i32 1
67*62774658Syabinc // CHECK-NEXT:    [[TMP1:%.*]] = load i64, ptr [[Y_ADDR]], align 8
68*62774658Syabinc // CHECK-NEXT:    store i64 [[TMP1]], ptr [[Y1]], align 8
69*62774658Syabinc // CHECK-NEXT:    ret void
70*62774658Syabinc //
71*62774658Syabinc void test2(long long y) {
72*62774658Syabinc   struct S1 s = {.y = y};
73*62774658Syabinc }
74*62774658Syabinc 
75*62774658Syabinc // Test non-const initializer for struct with padding and bit fields.
76*62774658Syabinc // CHECK-LABEL: define dso_local void @test3(
77*62774658Syabinc // CHECK-SAME: i8 noundef zeroext [[B:%.*]]) #[[ATTR0]] {
78*62774658Syabinc // CHECK-NEXT:  [[ENTRY:.*:]]
79*62774658Syabinc // CHECK-NEXT:    [[B_ADDR:%.*]] = alloca i8, align 1
80*62774658Syabinc // CHECK-NEXT:    [[S:%.*]] = alloca [[STRUCT_S2:%.*]], align 4
81*62774658Syabinc // CHECK-NEXT:    store i8 [[B]], ptr [[B_ADDR]], align 1
82*62774658Syabinc // CHECK-NEXT:    store i16 0, ptr [[S]], align 4
83*62774658Syabinc // CHECK-NEXT:    [[TMP0:%.*]] = load i8, ptr [[B_ADDR]], align 1
84*62774658Syabinc // CHECK-NEXT:    [[TMP1:%.*]] = zext i8 [[TMP0]] to i16
85*62774658Syabinc // CHECK-NEXT:    [[BF_LOAD:%.*]] = load i16, ptr [[S]], align 4
86*62774658Syabinc // CHECK-NEXT:    [[BF_VALUE:%.*]] = and i16 [[TMP1]], 7
87*62774658Syabinc // CHECK-NEXT:    [[BF_CLEAR:%.*]] = and i16 [[BF_LOAD]], -8
88*62774658Syabinc // CHECK-NEXT:    [[BF_SET:%.*]] = or i16 [[BF_CLEAR]], [[BF_VALUE]]
89*62774658Syabinc // CHECK-NEXT:    store i16 [[BF_SET]], ptr [[S]], align 4
90*62774658Syabinc // CHECK-NEXT:    [[BF_LOAD1:%.*]] = load i16, ptr [[S]], align 4
91*62774658Syabinc // CHECK-NEXT:    [[BF_CLEAR2:%.*]] = and i16 [[BF_LOAD1]], -16129
92*62774658Syabinc // CHECK-NEXT:    [[BF_SET3:%.*]] = or i16 [[BF_CLEAR2]], 0
93*62774658Syabinc // CHECK-NEXT:    store i16 [[BF_SET3]], ptr [[S]], align 4
94*62774658Syabinc // CHECK-NEXT:    [[BF_LOAD4:%.*]] = load i16, ptr [[S]], align 4
95*62774658Syabinc // CHECK-NEXT:    [[BF_CLEAR5:%.*]] = and i16 [[BF_LOAD4]], 16383
96*62774658Syabinc // CHECK-NEXT:    [[BF_SET6:%.*]] = or i16 [[BF_CLEAR5]], 0
97*62774658Syabinc // CHECK-NEXT:    store i16 [[BF_SET6]], ptr [[S]], align 4
98*62774658Syabinc // CHECK-NEXT:    [[TMP2:%.*]] = getelementptr i8, ptr [[S]], i64 2
99*62774658Syabinc // CHECK-NEXT:    call void @llvm.memset.p0.i64(ptr align 2 [[TMP2]], i8 0, i64 2, i1 false)
100*62774658Syabinc // CHECK-NEXT:    [[I:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[S]], i32 0, i32 1
101*62774658Syabinc // CHECK-NEXT:    store i32 0, ptr [[I]], align 4
102*62774658Syabinc // CHECK-NEXT:    ret void
103*62774658Syabinc //
104*62774658Syabinc void test3(unsigned char b) {
105*62774658Syabinc   struct S2 s = {.b1 = b};
106*62774658Syabinc }
107*62774658Syabinc 
108*62774658Syabinc // Test non-const initializer for struct with padding at the end of the struct.
109*62774658Syabinc // CHECK-LABEL: define dso_local void @test4(
110*62774658Syabinc // CHECK-SAME: i32 noundef [[X:%.*]]) #[[ATTR0]] {
111*62774658Syabinc // CHECK-NEXT:  [[ENTRY:.*:]]
112*62774658Syabinc // CHECK-NEXT:    [[X_ADDR:%.*]] = alloca i32, align 4
113*62774658Syabinc // CHECK-NEXT:    [[S:%.*]] = alloca [[STRUCT_S3:%.*]], align 8
114*62774658Syabinc // CHECK-NEXT:    store i32 [[X]], ptr [[X_ADDR]], align 4
115*62774658Syabinc // CHECK-NEXT:    [[X1:%.*]] = getelementptr inbounds nuw [[STRUCT_S3]], ptr [[S]], i32 0, i32 0
116*62774658Syabinc // CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[X_ADDR]], align 4
117*62774658Syabinc // CHECK-NEXT:    store i32 [[TMP0]], ptr [[X1]], align 8
118*62774658Syabinc // CHECK-NEXT:    [[TMP1:%.*]] = getelementptr i8, ptr [[S]], i64 4
119*62774658Syabinc // CHECK-NEXT:    call void @llvm.memset.p0.i64(ptr align 4 [[TMP1]], i8 0, i64 4, i1 false)
120*62774658Syabinc // CHECK-NEXT:    ret void
121*62774658Syabinc //
122*62774658Syabinc void test4(int x) {
123*62774658Syabinc   struct S3 s = {x};
124*62774658Syabinc }
125*62774658Syabinc 
126*62774658Syabinc // Test non-const initializer for union in struct.
127*62774658Syabinc // CHECK-LABEL: define dso_local void @test5(
128*62774658Syabinc // CHECK-SAME: i32 noundef [[A:%.*]], i32 noundef [[B:%.*]]) #[[ATTR0]] {
129*62774658Syabinc // CHECK-NEXT:  [[ENTRY:.*:]]
130*62774658Syabinc // CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
131*62774658Syabinc // CHECK-NEXT:    [[B_ADDR:%.*]] = alloca i32, align 4
132*62774658Syabinc // CHECK-NEXT:    [[S:%.*]] = alloca [[STRUCT_S4:%.*]], align 4
133*62774658Syabinc // CHECK-NEXT:    store i32 [[A]], ptr [[A_ADDR]], align 4
134*62774658Syabinc // CHECK-NEXT:    store i32 [[B]], ptr [[B_ADDR]], align 4
135*62774658Syabinc // CHECK-NEXT:    [[A1:%.*]] = getelementptr inbounds nuw [[STRUCT_S4]], ptr [[S]], i32 0, i32 0
136*62774658Syabinc // CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
137*62774658Syabinc // CHECK-NEXT:    store i32 [[TMP0]], ptr [[A1]], align 4
138*62774658Syabinc // CHECK-NEXT:    [[B2:%.*]] = getelementptr inbounds nuw [[STRUCT_S4]], ptr [[S]], i32 0, i32 1
139*62774658Syabinc // CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
140*62774658Syabinc // CHECK-NEXT:    store i32 [[TMP1]], ptr [[B2]], align 4
141*62774658Syabinc // CHECK-NEXT:    [[TMP2:%.*]] = getelementptr i8, ptr [[B2]], i64 4
142*62774658Syabinc // CHECK-NEXT:    call void @llvm.memset.p0.i64(ptr align 4 [[TMP2]], i8 0, i64 4, i1 false)
143*62774658Syabinc // CHECK-NEXT:    ret void
144*62774658Syabinc //
145*62774658Syabinc void test5(int a, int b) {
146*62774658Syabinc   struct S4 s = {a, {b}};
147*62774658Syabinc }
148*62774658Syabinc 
149*62774658Syabinc // CHECK-LABEL: define dso_local void @test6(
150*62774658Syabinc // CHECK-SAME: i8 noundef signext [[X:%.*]]) #[[ATTR0]] {
151*62774658Syabinc // CHECK-NEXT:  [[ENTRY:.*:]]
152*62774658Syabinc // CHECK-NEXT:    [[X_ADDR:%.*]] = alloca i8, align 1
153*62774658Syabinc // CHECK-NEXT:    [[S:%.*]] = alloca [[STRUCT_S5:%.*]], align 1
154*62774658Syabinc // CHECK-NEXT:    store i8 [[X]], ptr [[X_ADDR]], align 1
155*62774658Syabinc // CHECK-NEXT:    [[X1:%.*]] = getelementptr inbounds nuw [[STRUCT_S5]], ptr [[S]], i32 0, i32 0
156*62774658Syabinc // CHECK-NEXT:    [[TMP0:%.*]] = load i8, ptr [[X_ADDR]], align 1
157*62774658Syabinc // CHECK-NEXT:    store i8 [[TMP0]], ptr [[X1]], align 1
158*62774658Syabinc // CHECK-NEXT:    [[TMP1:%.*]] = getelementptr i8, ptr [[S]], i64 1
159*62774658Syabinc // CHECK-NEXT:    store i16 0, ptr [[TMP1]], align 1
160*62774658Syabinc // CHECK-NEXT:    [[Y:%.*]] = getelementptr inbounds nuw [[STRUCT_S5]], ptr [[S]], i32 0, i32 1
161*62774658Syabinc // CHECK-NEXT:    [[BF_LOAD:%.*]] = load i16, ptr [[Y]], align 1
162*62774658Syabinc // CHECK-NEXT:    [[BF_CLEAR:%.*]] = and i16 [[BF_LOAD]], -16
163*62774658Syabinc // CHECK-NEXT:    [[BF_SET:%.*]] = or i16 [[BF_CLEAR]], 0
164*62774658Syabinc // CHECK-NEXT:    store i16 [[BF_SET]], ptr [[Y]], align 1
165*62774658Syabinc // CHECK-NEXT:    [[Z:%.*]] = getelementptr inbounds nuw [[STRUCT_S5]], ptr [[S]], i32 0, i32 1
166*62774658Syabinc // CHECK-NEXT:    [[BF_LOAD2:%.*]] = load i16, ptr [[Z]], align 1
167*62774658Syabinc // CHECK-NEXT:    [[BF_CLEAR3:%.*]] = and i16 [[BF_LOAD2]], -2033
168*62774658Syabinc // CHECK-NEXT:    [[BF_SET4:%.*]] = or i16 [[BF_CLEAR3]], 0
169*62774658Syabinc // CHECK-NEXT:    store i16 [[BF_SET4]], ptr [[Z]], align 1
170*62774658Syabinc // CHECK-NEXT:    ret void
171*62774658Syabinc //
172*62774658Syabinc void test6(char x) {
173*62774658Syabinc   struct S5 s = {.x = x};
174*62774658Syabinc }
175*62774658Syabinc //.
176*62774658Syabinc // CHECK: attributes #[[ATTR0]] = { noinline nounwind optnone "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+cx8,+mmx,+sse,+sse2,+x87" }
177*62774658Syabinc // CHECK: attributes #[[ATTR1:[0-9]+]] = { nocallback nofree nounwind willreturn memory(argmem: write) }
178*62774658Syabinc //.
179*62774658Syabinc // CHECK: [[META0:![0-9]+]] = !{i32 1, !"wchar_size", i32 4}
180*62774658Syabinc // CHECK: [[META1:![0-9]+]] = !{!"{{.*}}clang version {{.*}}"}
181*62774658Syabinc //.
182