Skip to content

Commit

Permalink
[CIR][CIRGen] Support for initialization of unions. (#495)
Browse files Browse the repository at this point in the history
PR adds support for initialization of unions. The change is copy-pasted
from the original CodeGen.
  • Loading branch information
YazZz1k authored and lanza committed Nov 2, 2024
1 parent eac2861 commit 069cbdc
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 5 deletions.
4 changes: 3 additions & 1 deletion clang/lib/CIR/CodeGen/CIRGenExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -630,7 +630,9 @@ void CIRGenFunction::buildStoreThroughLValue(RValue Src, LValue Dst) {
builder.createStore(loc, Vector, Dst.getVectorAddress());
return;
}
llvm_unreachable("NYI: non-simple store through lvalue");
assert(Dst.isBitField() && "NIY LValue type");
mlir::Value result;
return buildStoreThroughBitfieldLValue(Src, Dst, result);
}
assert(Dst.isSimple() && "only implemented simple");

Expand Down
38 changes: 34 additions & 4 deletions clang/lib/CIR/CodeGen/CIRGenExprAgg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -743,7 +743,8 @@ void AggExprEmitter::buildNullInitializationToLValue(mlir::Location loc,
// Note that the following is not equivalent to
// EmitStoreThroughBitfieldLValue for ARC types.
if (lv.isBitField()) {
llvm_unreachable("NYI");
mlir::Value result;
CGF.buildStoreThroughBitfieldLValue(RValue::get(null), lv, result);
} else {
assert(lv.isSimple());
CGF.buildStoreOfScalar(null, lv, /* isInitialization */ true);
Expand Down Expand Up @@ -795,8 +796,7 @@ void AggExprEmitter::buildInitializationToLValue(Expr *E, LValue LV) {
if (LV.isSimple()) {
CGF.buildScalarInit(E, CGF.getLoc(E->getSourceRange()), LV);
} else {
llvm_unreachable("NYI");
// CGF.EmitStoreThroughLValue(RValue::get(CGF.EmitScalarExpr(E)), LV);
CGF.buildStoreThroughLValue(RValue::get(CGF.buildScalarExpr(E)), LV);
}
return;
}
Expand Down Expand Up @@ -1114,7 +1114,37 @@ void AggExprEmitter::VisitCXXParenListOrInitListExpr(
CIRGenFunction::FieldConstructionScope FCS(CGF, Dest.getAddress());

if (record->isUnion()) {
llvm_unreachable("NYI");
// Only initialize one field of a union. The field itself is
// specified by the initializer list.
if (!InitializedFieldInUnion) {
// Empty union; we have nothing to do.

#ifndef NDEBUG
// Make sure that it's really an empty and not a failure of
// semantic analysis.
for (const auto *Field : record->fields())
assert(
(Field->isUnnamedBitField() || Field->isAnonymousStructOrUnion()) &&
"Only unnamed bitfields or ananymous class allowed");
#endif
return;
}

// FIXME: volatility
FieldDecl *Field = InitializedFieldInUnion;

LValue FieldLoc =
CGF.buildLValueForFieldInitialization(DestLV, Field, Field->getName());
if (NumInitElements) {
// Store the initializer into the field
buildInitializationToLValue(InitExprs[0], FieldLoc);
} else {
// Default-initialize to null.
buildNullInitializationToLValue(CGF.getLoc(ExprToVisit->getSourceRange()),
FieldLoc);
}

return;
}

// Here we iterate over the fields; this makes it simpler to both
Expand Down
43 changes: 43 additions & 0 deletions clang/test/CIR/CodeGen/union-init.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-cir %s -o - | FileCheck %s
// XFAIL: *

typedef union {
int value;
struct {
int x : 16;
int y : 16;
};
} A;

void foo(int x) {
A a = {.x = x};
}

// CHECK: cir.func @foo(%arg0: !s32i loc({{.*}}))
// CHECK: [[TMP0:%.*]] = cir.alloca !s32i, cir.ptr <!s32i>, ["x", init] {alignment = 4 : i64}
// CHECK: [[TMP1:%.*]] = cir.alloca !ty_22A22, cir.ptr <!ty_22A22>, ["a", init] {alignment = 4 : i64}
// CHECK: cir.store %arg0, [[TMP0]] : !s32i, cir.ptr <!s32i>
// CHECK: [[TMP2:%.*]] = cir.get_member [[TMP1]][1] {name = ""} : !cir.ptr<!ty_22A22> -> !cir.ptr<!ty_22anon2E122>
// CHECK: [[TMP3:%.*]] = cir.cast(bitcast, [[TMP2]] : !cir.ptr<!ty_22anon2E122>), !cir.ptr<!u32i>
// CHECK: [[TMP4:%.*]] = cir.load [[TMP0]] : cir.ptr <!s32i>, !s32i
// CHECK: [[TMP5:%.*]] = cir.cast(integral, [[TMP4]] : !s32i), !u32i
// CHECK: [[TMP6:%.*]] = cir.load [[TMP3]] : cir.ptr <!u32i>, !u32i
// CHECK: [[TMP7:%.*]] = cir.const(#cir.int<65535> : !u32i) : !u32i
// CHECK: [[TMP8:%.*]] = cir.binop(and, [[TMP5]], [[TMP7]]) : !u32i
// CHECK: [[TMP9:%.*]] = cir.const(#cir.int<4294901760> : !u32i) : !u32i
// CHECK: [[TMP10:%.*]] = cir.binop(and, [[TMP6]], [[TMP9]]) : !u32i
// CHECK: [[TMP11:%.*]] = cir.binop(or, [[TMP10]], [[TMP8]]) : !u32i
// CHECK: cir.store [[TMP11]], [[TMP3]] : !u32i, cir.ptr <!u32i>
// CHECK: [[TMP12:%.*]] = cir.cast(bitcast, [[TMP2]] : !cir.ptr<!ty_22anon2E122>), !cir.ptr<!u32i>
// CHECK: [[TMP13:%.*]] = cir.const(#cir.int<0> : !s32i) : !s32i
// CHECK: [[TMP14:%.*]] = cir.cast(integral, [[TMP13]] : !s32i), !u32i
// CHECK: [[TMP15:%.*]] = cir.load [[TMP12]] : cir.ptr <!u32i>, !u32i
// CHECK: [[TMP16:%.*]] = cir.const(#cir.int<65535> : !u32i) : !u32i
// CHECK: [[TMP17:%.*]] = cir.binop(and, [[TMP14]], [[TMP16]]) : !u32i
// CHECK: [[TMP18:%.*]] = cir.const(#cir.int<16> : !u32i) : !u32i
// CHECK: [[TMP19:%.*]] = cir.shift(left, [[TMP17]] : !u32i, [[TMP18]] : !u32i) -> !u32i
// CHECK: [[TMP20:%.*]] = cir.const(#cir.int<65535> : !u32i) : !u32i
// CHECK: [[TMP21:%.*]] = cir.binop(and, [[TMP15]], [[TMP20]]) : !u32i
// CHECK: [[TMP22:%.*]] = cir.binop(or, [[TMP21]], [[TMP19]]) : !u32i
// CHECK: cir.store [[TMP22]], [[TMP12]] : !u32i, cir.ptr <!u32i>
// CHECK: cir.return

0 comments on commit 069cbdc

Please sign in to comment.