232 lines · c
1// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o %t.cir2// RUN: FileCheck --check-prefix=CIR --input-file=%t.cir %s3// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o %t-cir.ll4// RUN: FileCheck --check-prefix=LLVM --input-file=%t-cir.ll %s5// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm %s -o %t.ll6// RUN: FileCheck --check-prefix=OGCG --input-file=%t.ll %s7 8union U1 {9 int n;10 char c;11};12 13// CIR: !rec_U1 = !cir.record<union "U1" {!s32i, !s8i}>14// LLVM: %union.U1 = type { i32 }15// OGCG: %union.U1 = type { i32 }16 17union U2 {18 char b;19 short s;20 int i;21 float f;22 double d;23};24 25// CIR: !rec_U2 = !cir.record<union "U2" {!s8i, !s16i, !s32i, !cir.float, !cir.double}>26// LLVM: %union.U2 = type { double }27// OGCG: %union.U2 = type { double }28 29union U3 {30 char c[5];31 int i;32} __attribute__((packed));33 34// CIR: !rec_U3 = !cir.record<union "U3" packed padded {!cir.array<!s8i x 5>, !s32i, !u8i}>35// LLVM: %union.U3 = type <{ i32, i8 }>36// OGCG: %union.U3 = type <{ i32, i8 }>37 38union U4 {39 char c[5];40 int i;41};42 43// CIR: !rec_U4 = !cir.record<union "U4" padded {!cir.array<!s8i x 5>, !s32i, !cir.array<!u8i x 4>}>44// LLVM: %union.U4 = type { i32, [4 x i8] }45// OGCG: %union.U4 = type { i32, [4 x i8] }46 47union IncompleteU *p;48 49// CIR: cir.global external @p = #cir.ptr<null> : !cir.ptr<!rec_IncompleteU>50// LLVM: @p = global ptr null51// OGCG: @p = global ptr null, align 852 53void f1(void) {54 union IncompleteU *p;55}56 57// CIR: cir.func{{.*}} @f1()58// CIR-NEXT: cir.alloca !cir.ptr<!rec_IncompleteU>, !cir.ptr<!cir.ptr<!rec_IncompleteU>>, ["p"]59// CIR-NEXT: cir.return60 61// LLVM: define{{.*}} void @f1()62// LLVM-NEXT: %[[P:.*]] = alloca ptr, i64 1, align 863// LLVM-NEXT: ret void64 65// OGCG: define{{.*}} void @f1()66// OGCG-NEXT: entry:67// OGCG-NEXT: %[[P:.*]] = alloca ptr, align 868// OGCG-NEXT: ret void69 70int f2(void) {71 union U1 u;72 u.n = 42;73 return u.n;74}75 76// CIR: cir.func{{.*}} @f2() -> !s32i77// CIR-NEXT: %[[RETVAL_ADDR:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["__retval"] {alignment = 4 : i64}78// CIR-NEXT: %[[U:.*]] = cir.alloca !rec_U1, !cir.ptr<!rec_U1>, ["u"] {alignment = 4 : i64}79// CIR-NEXT: %[[I:.*]] = cir.const #cir.int<42> : !s32i80// CIR-NEXT: %[[N:.*]] = cir.get_member %[[U]][0] {name = "n"} : !cir.ptr<!rec_U1> -> !cir.ptr<!s32i>81// CIR-NEXT: cir.store{{.*}} %[[I]], %[[N]] : !s32i, !cir.ptr<!s32i>82// CIR-NEXT: %[[N2:.*]] = cir.get_member %[[U]][0] {name = "n"} : !cir.ptr<!rec_U1> -> !cir.ptr<!s32i>83// CIR-NEXT: %[[VAL:.*]] = cir.load{{.*}} %[[N2]] : !cir.ptr<!s32i>, !s32i84// CIR-NEXT: cir.store{{.*}} %[[VAL]], %[[RETVAL_ADDR]] : !s32i, !cir.ptr<!s32i>85// CIR-NEXT: %[[RET:.*]] = cir.load{{.*}} %[[RETVAL_ADDR]] : !cir.ptr<!s32i>, !s32i86// CIR-NEXT: cir.return %[[RET]] : !s32i87 88// LLVM: define{{.*}} i32 @f2()89// LLVM-NEXT: %[[RETVAL:.*]] = alloca i32, i64 1, align 490// LLVM-NEXT: %[[U:.*]] = alloca %union.U1, i64 1, align 491// LLVM-NEXT: store i32 42, ptr %[[U]], align 492// LLVM-NEXT: %[[N_VAL:.*]] = load i32, ptr %[[U]], align 493// LLVM-NEXT: store i32 %[[N_VAL]], ptr %[[RETVAL]], align 494// LLVM-NEXT: %[[RET:.*]] = load i32, ptr %[[RETVAL]], align 495// LLVM-NEXT: ret i32 %[[RET]]96 97// OGCG: define{{.*}} i32 @f2()98// OGCG-NEXT: entry:99// OGCG-NEXT: %[[U:.*]] = alloca %union.U1, align 4100// OGCG-NEXT: store i32 42, ptr %[[U]], align 4101// OGCG-NEXT: %[[N_VAL:.*]] = load i32, ptr %[[U]], align 4102// OGCG-NEXT: ret i32 %[[N_VAL]]103 104void shouldGenerateUnionAccess(union U2 u) {105 u.b = 0;106 u.b;107 u.i = 1;108 u.i;109 u.f = 0.1F;110 u.f;111 u.d = 0.1;112 u.d;113}114 115// CIR: cir.func{{.*}} @shouldGenerateUnionAccess(%[[ARG:.*]]: !rec_U2116// CIR-NEXT: %[[U:.*]] = cir.alloca !rec_U2, !cir.ptr<!rec_U2>, ["u", init] {alignment = 8 : i64}117// CIR-NEXT: cir.store{{.*}} %[[ARG]], %[[U]] : !rec_U2, !cir.ptr<!rec_U2>118// CIR-NEXT: %[[ZERO:.*]] = cir.const #cir.int<0> : !s32i119// CIR-NEXT: %[[ZERO_CHAR:.*]] = cir.cast integral %[[ZERO]] : !s32i -> !s8i120// CIR-NEXT: %[[B_PTR:.*]] = cir.get_member %[[U]][0] {name = "b"} : !cir.ptr<!rec_U2> -> !cir.ptr<!s8i>121// CIR-NEXT: cir.store{{.*}} %[[ZERO_CHAR]], %[[B_PTR]] : !s8i, !cir.ptr<!s8i>122// CIR-NEXT: %[[B_PTR2:.*]] = cir.get_member %[[U]][0] {name = "b"} : !cir.ptr<!rec_U2> -> !cir.ptr<!s8i>123// CIR-NEXT: %[[B_VAL:.*]] = cir.load{{.*}} %[[B_PTR2]] : !cir.ptr<!s8i>, !s8i124// CIR-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i125// CIR-NEXT: %[[I_PTR:.*]] = cir.get_member %[[U]][2] {name = "i"} : !cir.ptr<!rec_U2> -> !cir.ptr<!s32i>126// CIR-NEXT: cir.store{{.*}} %[[ONE]], %[[I_PTR]] : !s32i, !cir.ptr<!s32i>127// CIR-NEXT: %[[I_PTR2:.*]] = cir.get_member %[[U]][2] {name = "i"} : !cir.ptr<!rec_U2> -> !cir.ptr<!s32i>128// CIR-NEXT: %[[I_VAL:.*]] = cir.load{{.*}} %[[I_PTR2]] : !cir.ptr<!s32i>, !s32i129// CIR-NEXT: %[[FLOAT_VAL:.*]] = cir.const #cir.fp<1.000000e-01> : !cir.float130// CIR-NEXT: %[[F_PTR:.*]] = cir.get_member %[[U]][3] {name = "f"} : !cir.ptr<!rec_U2> -> !cir.ptr<!cir.float>131// CIR-NEXT: cir.store{{.*}} %[[FLOAT_VAL]], %[[F_PTR]] : !cir.float, !cir.ptr<!cir.float>132// CIR-NEXT: %[[F_PTR2:.*]] = cir.get_member %[[U]][3] {name = "f"} : !cir.ptr<!rec_U2> -> !cir.ptr<!cir.float>133// CIR-NEXT: %[[F_VAL:.*]] = cir.load{{.*}} %[[F_PTR2]] : !cir.ptr<!cir.float>, !cir.float134// CIR-NEXT: %[[DOUBLE_VAL:.*]] = cir.const #cir.fp<1.000000e-01> : !cir.double135// CIR-NEXT: %[[D_PTR:.*]] = cir.get_member %[[U]][4] {name = "d"} : !cir.ptr<!rec_U2> -> !cir.ptr<!cir.double>136// CIR-NEXT: cir.store{{.*}} %[[DOUBLE_VAL]], %[[D_PTR]] : !cir.double, !cir.ptr<!cir.double>137// CIR-NEXT: %[[D_PTR2:.*]] = cir.get_member %[[U]][4] {name = "d"} : !cir.ptr<!rec_U2> -> !cir.ptr<!cir.double>138// CIR-NEXT: %[[D_VAL:.*]] = cir.load{{.*}} %[[D_PTR2]] : !cir.ptr<!cir.double>, !cir.double139// CIR-NEXT: cir.return140 141// LLVM: define{{.*}} void @shouldGenerateUnionAccess(%union.U2 %[[ARG:.*]])142// LLVM-NEXT: %[[U:.*]] = alloca %union.U2, i64 1, align 8143// LLVM-NEXT: store %union.U2 %[[ARG]], ptr %[[U]], align 8144// LLVM-NEXT: store i8 0, ptr %[[U]], align 8145// LLVM-NEXT: %[[B_VAL:.*]] = load i8, ptr %[[U]], align 8146// LLVM-NEXT: store i32 1, ptr %[[U]], align 8147// LLVM-NEXT: %[[I_VAL:.*]] = load i32, ptr %[[U]], align 8148// LLVM-NEXT: store float 0x3FB99999A0000000, ptr %[[U]], align 8149// LLVM-NEXT: %[[F_VAL:.*]] = load float, ptr %[[U]], align 8150// LLVM-NEXT: store double 1.000000e-01, ptr %[[U]], align 8151// LLVM-NEXT: %[[D_VAL:.*]] = load double, ptr %[[U]], align 8152// LLVM-NEXT: ret void153 154// OGCG: define{{.*}} void @shouldGenerateUnionAccess(i64 %[[ARG:.*]])155// OGCG-NEXT: entry:156// OGCG-NEXT: %[[U:.*]] = alloca %union.U2, align 8157// OGCG-NEXT: %[[COERCE_DIVE:.*]] = getelementptr inbounds nuw %union.U2, ptr %[[U]], i32 0, i32 0158// OGCG-NEXT: store i64 %[[ARG]], ptr %[[COERCE_DIVE]], align 8159// OGCG-NEXT: store i8 0, ptr %[[U]], align 8160// OGCG-NEXT: %[[B_VAL:.*]] = load i8, ptr %[[U]], align 8161// OGCG-NEXT: store i32 1, ptr %[[U]], align 8162// OGCG-NEXT: %[[I_VAL:.*]] = load i32, ptr %[[U]], align 8163// OGCG-NEXT: store float 0x3FB99999A0000000, ptr %[[U]], align 8164// OGCG-NEXT: %[[F_VAL:.*]] = load float, ptr %[[U]], align 8165// OGCG-NEXT: store double 1.000000e-01, ptr %[[U]], align 8166// OGCG-NEXT: %[[D_VAL:.*]] = load double, ptr %[[U]], align 8167// OGCG-NEXT: ret void168 169void f3(union U3 u) {170 u.c[2] = 0;171}172 173// CIR: cir.func{{.*}} @f3(%[[ARG:.*]]: !rec_U3174// CIR-NEXT: %[[U:.*]] = cir.alloca !rec_U3, !cir.ptr<!rec_U3>, ["u", init] {alignment = 1 : i64}175// CIR-NEXT: cir.store{{.*}} %[[ARG]], %[[U]] : !rec_U3, !cir.ptr<!rec_U3>176// CIR-NEXT: %[[ZERO:.*]] = cir.const #cir.int<0> : !s32i177// CIR-NEXT: %[[ZERO_CHAR:.*]] = cir.cast integral %[[ZERO]] : !s32i -> !s8i178// CIR-NEXT: %[[IDX:.*]] = cir.const #cir.int<2> : !s32i179// CIR-NEXT: %[[C_PTR:.*]] = cir.get_member %[[U]][0] {name = "c"} : !cir.ptr<!rec_U3> -> !cir.ptr<!cir.array<!s8i x 5>>180// CIR-NEXT: %[[C_DECAY:.*]] = cir.cast array_to_ptrdecay %[[C_PTR]] : !cir.ptr<!cir.array<!s8i x 5>> -> !cir.ptr<!s8i>181// CIR-NEXT: %[[ELEM_PTR:.*]] = cir.ptr_stride %[[C_DECAY]], %[[IDX]] : (!cir.ptr<!s8i>, !s32i) -> !cir.ptr<!s8i>182// CIR-NEXT: cir.store{{.*}} %[[ZERO_CHAR]], %[[ELEM_PTR]] : !s8i, !cir.ptr<!s8i>183// CIR-NEXT: cir.return184 185// LLVM: define{{.*}} void @f3(%union.U3 %[[ARG:.*]])186// LLVM-NEXT: %[[U:.*]] = alloca %union.U3, i64 1, align 1187// LLVM-NEXT: store %union.U3 %[[ARG]], ptr %[[U]], align 1188// LLVM-NEXT: %[[C_PTR:.*]] = getelementptr i8, ptr %[[U]], i32 0189// LLVM-NEXT: %[[ELEM_PTR:.*]] = getelementptr i8, ptr %[[C_PTR]], i64 2190// LLVM-NEXT: store i8 0, ptr %[[ELEM_PTR]], align 1191// LLVM-NEXT: ret void192 193// OGCG: define{{.*}} void @f3(i40 %[[ARG:.*]])194// OGCG-NEXT: entry:195// OGCG-NEXT: %[[U:.*]] = alloca %union.U3, align 1196// OGCG-NEXT: store i40 %[[ARG]], ptr %[[U]], align 1197// OGCG-NEXT: %[[ARRAYIDX:.*]] = getelementptr inbounds [5 x i8], ptr %[[U]], i64 0, i64 2198// OGCG-NEXT: store i8 0, ptr %[[ARRAYIDX]], align 1199// OGCG-NEXT: ret void200 201void f5(union U4 u) {202 u.c[4] = 65;203}204 205// CIR: cir.func{{.*}} @f5(%[[ARG:.*]]: !rec_U4206// CIR-NEXT: %[[U:.*]] = cir.alloca !rec_U4, !cir.ptr<!rec_U4>, ["u", init] {alignment = 4 : i64}207// CIR-NEXT: cir.store{{.*}} %[[ARG]], %[[U]] : !rec_U4, !cir.ptr<!rec_U4>208// CIR-NEXT: %[[CHAR_VAL:.*]] = cir.const #cir.int<65> : !s32i209// CIR-NEXT: %[[CHAR_CAST:.*]] = cir.cast integral %[[CHAR_VAL]] : !s32i -> !s8i210// CIR-NEXT: %[[IDX:.*]] = cir.const #cir.int<4> : !s32i211// CIR-NEXT: %[[C_PTR:.*]] = cir.get_member %[[U]][0] {name = "c"} : !cir.ptr<!rec_U4> -> !cir.ptr<!cir.array<!s8i x 5>>212// CIR-NEXT: %[[C_DECAY:.*]] = cir.cast array_to_ptrdecay %[[C_PTR]] : !cir.ptr<!cir.array<!s8i x 5>> -> !cir.ptr<!s8i>213// CIR-NEXT: %[[ELEM_PTR:.*]] = cir.ptr_stride %[[C_DECAY]], %[[IDX]] : (!cir.ptr<!s8i>, !s32i) -> !cir.ptr<!s8i>214// CIR-NEXT: cir.store{{.*}} %[[CHAR_CAST]], %[[ELEM_PTR]] : !s8i, !cir.ptr<!s8i>215// CIR-NEXT: cir.return216 217// LLVM: define{{.*}} void @f5(%union.U4 %[[ARG:.*]])218// LLVM-NEXT: %[[U:.*]] = alloca %union.U4, i64 1, align 4219// LLVM-NEXT: store %union.U4 %[[ARG]], ptr %[[U]], align 4220// LLVM-NEXT: %[[C_PTR:.*]] = getelementptr i8, ptr %[[U]], i32 0221// LLVM-NEXT: %[[ELEM_PTR:.*]] = getelementptr i8, ptr %[[C_PTR]], i64 4222// LLVM-NEXT: store i8 65, ptr %[[ELEM_PTR]], align 4223// LLVM-NEXT: ret void224 225// OGCG: define{{.*}} void @f5(i64 %[[ARG:.*]])226// OGCG-NEXT: entry:227// OGCG-NEXT: %[[U:.*]] = alloca %union.U4, align 4228// OGCG-NEXT: store i64 %[[ARG]], ptr %[[U]], align 4229// OGCG-NEXT: %[[ARRAYIDX:.*]] = getelementptr inbounds [5 x i8], ptr %[[U]], i64 0, i64 4230// OGCG-NEXT: store i8 65, ptr %[[ARRAYIDX]], align 4231// OGCG-NEXT: ret void232