diff --git a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp index f08f0f4caa81..62262f2a730b 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp @@ -637,7 +637,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"); diff --git a/clang/lib/CIR/CodeGen/CIRGenExprAgg.cpp b/clang/lib/CIR/CodeGen/CIRGenExprAgg.cpp index 1b62281c3307..4508476e6088 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExprAgg.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExprAgg.cpp @@ -740,7 +740,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); @@ -792,8 +793,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; } @@ -1111,7 +1111,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 diff --git a/clang/test/CIR/CodeGen/union-init.c b/clang/test/CIR/CodeGen/union-init.c new file mode 100644 index 000000000000..cbd314a221e8 --- /dev/null +++ b/clang/test/CIR/CodeGen/union-init.c @@ -0,0 +1,42 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-cir %s -o - | FileCheck %s + +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 , ["x", init] {alignment = 4 : i64} +// CHECK: [[TMP1:%.*]] = cir.alloca !ty_22A22, cir.ptr , ["a", init] {alignment = 4 : i64} +// CHECK: cir.store %arg0, [[TMP0]] : !s32i, cir.ptr +// CHECK: [[TMP2:%.*]] = cir.get_member [[TMP1]][1] {name = ""} : !cir.ptr -> !cir.ptr +// CHECK: [[TMP3:%.*]] = cir.cast(bitcast, [[TMP2]] : !cir.ptr), !cir.ptr +// CHECK: [[TMP4:%.*]] = cir.load [[TMP0]] : cir.ptr , !s32i +// CHECK: [[TMP5:%.*]] = cir.cast(integral, [[TMP4]] : !s32i), !u32i +// CHECK: [[TMP6:%.*]] = cir.load [[TMP3]] : cir.ptr , !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 +// CHECK: [[TMP12:%.*]] = cir.cast(bitcast, [[TMP2]] : !cir.ptr), !cir.ptr +// 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 +// 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 +// CHECK: cir.return