Skip to content

Commit 7196e39

Browse files
gitoleglanza
authored andcommitted
[CIR][CodeGen] Locally inited structures with bitfields (#463)
The second part of the job started in #412 , now about local structures. As it was mentioned previously, sometimes the layout for structures with bit fields inited with constants differ from the originally created in `CIRRecordLayoutBuilder` and it cause `storeOp` verification fail due to different structure type was used to allocation. This PR fix it. An example: ``` typedef struct { int a : 4; int b : 5; int c; } D; void bar () { D d = {1,2,3}; } ``` Well, I can't say I'm proud of these changes - it seems like a type safety violation, but looks like it's the best we can do here. The original codegen doesn't have this problem at all, there is just a `memcpy` there, I provide LLVM IR just for reference: ``` %struct.D = type { i16, i32 } @__const.bar.d = private unnamed_addr constant { i8, i8, i32 } { i8 33, i8 0, i32 3 }, align 4 ; Function Attrs: noinline nounwind optnone uwtable define dso_local void @bar() #0 { entry: %d = alloca %struct.D, align 4 call void @llvm.memcpy.p0.p0.i64(ptr align 4 %d, ptr align 4 @__const.bar.d, i64 8, i1 false) ret void } ```
1 parent 21b39bc commit 7196e39

File tree

2 files changed

+26
-0
lines changed

2 files changed

+26
-0
lines changed

clang/lib/CIR/CodeGen/CIRGenDecl.cpp

+7
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,13 @@ static void emitStoresForConstant(CIRGenModule &CGM, const VarDecl &D,
234234
//
235235
// FIXME(cir): This is closer to memcpy behavior but less optimal, instead of
236236
// copy from a global, we just create a cir.const out of it.
237+
238+
if (addr.getElementType() != Ty) {
239+
auto ptr = addr.getPointer();
240+
ptr = builder.createBitcast(ptr.getLoc(), ptr, builder.getPointerTo(Ty));
241+
addr = addr.withPointer(ptr, addr.isKnownNonNull());
242+
}
243+
237244
auto loc = CGM.getLoc(D.getSourceRange());
238245
builder.createStore(loc, builder.getConstant(loc, constant), addr);
239246
}

clang/test/CIR/CodeGen/bitfields.c

+19
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,12 @@ void m() {
1414
struct __long l;
1515
}
1616

17+
typedef struct {
18+
int a : 4;
19+
int b : 5;
20+
int c;
21+
} D;
22+
1723
typedef struct {
1824
int a : 4;
1925
int b : 27;
@@ -27,9 +33,12 @@ typedef struct {
2733
int a : 3; // one bitfield with size < 8
2834
unsigned b;
2935
} T;
36+
37+
// CHECK: !ty_22D22 = !cir.struct<struct "D" {!cir.int<u, 16>, !cir.int<s, 32>}>
3038
// CHECK: !ty_22S22 = !cir.struct<struct "S" {!cir.int<u, 32>, !cir.int<u, 32>, !cir.int<u, 16>, !cir.int<u, 32>}>
3139
// CHECK: !ty_22T22 = !cir.struct<struct "T" {!cir.int<u, 8>, !cir.int<u, 32>} #cir.record.decl.ast>
3240
// CHECK: !ty_22anon2E122 = !cir.struct<struct "anon.1" {!cir.int<u, 32>} #cir.record.decl.ast>
41+
// CHECK: !ty_anon_struct = !cir.struct<struct {!cir.int<u, 8>, !cir.int<u, 8>, !cir.int<s, 32>}>
3342
// CHECK: !ty_22__long22 = !cir.struct<struct "__long" {!cir.struct<struct "anon.1" {!cir.int<u, 32>} #cir.record.decl.ast>, !cir.int<u, 32>, !cir.ptr<!cir.int<u, 32>>}>
3443

3544
// CHECK: cir.func {{.*@store_field}}
@@ -96,4 +105,14 @@ unsigned load_non_bitfield(S *s) {
96105
// CHECK: cir.func {{.*@load_one_bitfield}}
97106
int load_one_bitfield(T* t) {
98107
return t->a;
108+
}
109+
110+
// for this struct type we create an anon structure with different storage types in initialization
111+
// CHECK: cir.func {{.*@createD}}
112+
// CHECK: %0 = cir.alloca !ty_22D22, cir.ptr <!ty_22D22>, ["d"] {alignment = 4 : i64}
113+
// CHECK: %1 = cir.cast(bitcast, %0 : !cir.ptr<!ty_22D22>), !cir.ptr<!ty_anon_struct>
114+
// CHECK: %2 = cir.const(#cir.const_struct<{#cir.int<33> : !u8i, #cir.int<0> : !u8i, #cir.int<3> : !s32i}> : !ty_anon_struct) : !ty_anon_struct
115+
// CHECK: cir.store %2, %1 : !ty_anon_struct, cir.ptr <!ty_anon_struct>
116+
void createD() {
117+
D d = {1,2,3};
99118
}

0 commit comments

Comments
 (0)