Skip to content

Commit 97eec75

Browse files
[CIR] Add support for binary operations on bitfield members (#149676)
This PR introduces support for binary operations on bitfield members.
1 parent 0623389 commit 97eec75

File tree

2 files changed

+49
-1
lines changed

2 files changed

+49
-1
lines changed

clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1125,7 +1125,7 @@ LValue ScalarExprEmitter::emitCompoundAssignLValue(
11251125
// 'An assignment expression has the value of the left operand after the
11261126
// assignment...'.
11271127
if (lhsLV.isBitField())
1128-
cgf.cgm.errorNYI(e->getSourceRange(), "store through bitfield lvalue");
1128+
cgf.emitStoreThroughBitfieldLValue(RValue::get(result), lhsLV);
11291129
else
11301130
cgf.emitStoreThroughLValue(RValue::get(result), lhsLV);
11311131

clang/test/CIR/CodeGen/bitfields.c

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -315,3 +315,51 @@ void unOp(S* s) {
315315
// OGCG: [[TMP12:%.*]] = shl i64 [[TMP8]], 62
316316
// OGCG: [[TMP13:%.*]] = ashr i64 [[TMP12]], 62
317317
// OGCG: [[TMP14:%.*]] = trunc i64 [[TMP13]] to i32
318+
319+
void binOp(S* s) {
320+
s->d |= 42;
321+
}
322+
323+
// CIR: cir.func {{.*@binOp}}
324+
// CIR: [[TMP0:%.*]] = cir.const #cir.int<42> : !s32i
325+
// CIR: [[TMP1:%.*]] = cir.get_member {{.*}}[0] {name = "d"} : !cir.ptr<!rec_S> -> !cir.ptr<!u64i>
326+
// CIR: [[TMP2:%.*]] = cir.get_bitfield align(4) (#bfi_d, [[TMP1]] : !cir.ptr<!u64i>) -> !s32i
327+
// CIR: [[TMP3:%.*]] = cir.binop(or, [[TMP2]], [[TMP0]]) : !s32i
328+
// CIR: cir.set_bitfield align(4) (#bfi_d, [[TMP1]] : !cir.ptr<!u64i>, [[TMP3]] : !s32i)
329+
330+
// LLVM: define {{.*@binOp}}
331+
// LLVM: [[TMP0:%.*]] = load ptr, ptr {{.*}}, align 8
332+
// LLVM: [[TMP1:%.*]] = getelementptr %struct.S, ptr [[TMP0]], i32 0, i32 0
333+
// LLVM: [[TMP2:%.*]] = load i64, ptr [[TMP1]], align 4
334+
// LLVM: [[TMP3:%.*]] = shl i64 [[TMP2]], 13
335+
// LLVM: [[TMP4:%.*]] = ashr i64 [[TMP3]], 62
336+
// LLVM: [[TMP5:%.*]] = trunc i64 [[TMP4]] to i32
337+
// LLVM: [[TMP6:%.*]] = or i32 [[TMP5]], 42
338+
// LLVM: [[TMP7:%.*]] = zext i32 [[TMP6]] to i64
339+
// LLVM: [[TMP8:%.*]] = load i64, ptr [[TMP1]], align 4
340+
// LLVM: [[TMP9:%.*]] = and i64 [[TMP7]], 3
341+
// LLVM: [[TMP10:%.*]] = shl i64 [[TMP9]], 49
342+
// LLVM: [[TMP11:%.*]] = and i64 [[TMP8]], -1688849860263937
343+
// LLVM: [[TMP12:%.*]] = or i64 [[TMP11]], [[TMP10]]
344+
// LLVM: store i64 [[TMP12]], ptr [[TMP1]], align 4
345+
// LLVM: [[TMP13:%.*]] = shl i64 [[TMP9]], 62
346+
// LLVM: [[TMP14:%.*]] = ashr i64 [[TMP13]], 62
347+
// LLVM: [[TMP15:%.*]] = trunc i64 [[TMP14]] to i32
348+
349+
// OGCG: define {{.*@binOp}}
350+
// OGCG: [[TMP0:%.*]] = load ptr, ptr %s.addr, align 8
351+
// OGCG: [[TMP1:%.*]] = load i64, ptr [[TMP0]], align 4
352+
// OGCG: [[TMP2:%.*]] = shl i64 [[TMP1]], 13
353+
// OGCG: [[TMP3:%.*]] = ashr i64 [[TMP2]], 62
354+
// OGCG: [[TMP4:%.*]] = trunc i64 [[TMP3]] to i32
355+
// OGCG: [[TMP5:%.*]] = or i32 [[TMP4]], 42
356+
// OGCG: [[TMP6:%.*]] = zext i32 [[TMP5]] to i64
357+
// OGCG: [[TMP7:%.*]] = load i64, ptr [[TMP0]], align 4
358+
// OGCG: [[TMP8:%.*]] = and i64 [[TMP6]], 3
359+
// OGCG: [[TMP9:%.*]] = shl i64 [[TMP8]], 49
360+
// OGCG: [[TMP10:%.*]] = and i64 [[TMP7]], -1688849860263937
361+
// OGCG: [[TMP11:%.*]] = or i64 [[TMP10]], [[TMP9]]
362+
// OGCG: store i64 [[TMP11]], ptr [[TMP0]], align 4
363+
// OGCG: [[TMP12:%.*]] = shl i64 [[TMP8]], 62
364+
// OGCG: [[TMP13:%.*]] = ashr i64 [[TMP12]], 62
365+
// OGCG: [[TMP14:%.*]] = trunc i64 [[TMP13]] to i32

0 commit comments

Comments
 (0)