Skip to content

Commit

Permalink
[CIR][CodeGen] Implement union cast (#867)
Browse files Browse the repository at this point in the history
Currently the C style cast is not implemented/supported for unions. 

This PR adds support for union casts as done in `CGExprAgg.cpp`. I have
also added an extra test in `union-init.c`.
  • Loading branch information
bruteforceboy authored Sep 19, 2024
1 parent 923264b commit c947dc7
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 1 deletion.
16 changes: 16 additions & 0 deletions clang/lib/CIR/CodeGen/CIRGenExprAgg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -980,6 +980,22 @@ void AggExprEmitter::VisitCastExpr(CastExpr *E) {
break;
}

case CK_ToUnion: {
// Evaluate even if the destination is ignored.
if (Dest.isIgnored()) {
CGF.buildAnyExpr(E->getSubExpr(), AggValueSlot::ignored(),
/*ignoreResult=*/true);
break;
}

// GCC union extension
QualType Ty = E->getSubExpr()->getType();
Address CastPtr = Dest.getAddress().withElementType(CGF.ConvertType(Ty));
buildInitializationToLValue(E->getSubExpr(),
CGF.makeAddrLValue(CastPtr, Ty));
break;
}

case CK_LValueToRValue:
// If we're loading from a volatile type, force the destination
// into existence.
Expand Down
17 changes: 16 additions & 1 deletion clang/test/CIR/CodeGen/union-init.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,4 +45,19 @@ unsigned is_little(void) {
// CHECK: cir.func @is_little
// CHECK: %[[VAL_1:.*]] = cir.get_global @is_little.one : !cir.ptr<![[anon0]]>
// CHECK: %[[VAL_2:.*]] = cir.cast(bitcast, %[[VAL_1]] : !cir.ptr<![[anon0]]>), !cir.ptr<![[anon1]]>
// CHECK: %[[VAL_3:.*]] = cir.get_member %[[VAL_2]][1] {name = "c"} : !cir.ptr<![[anon1]]> -> !cir.ptr<!cir.array<!u8i x 4>>
// CHECK: %[[VAL_3:.*]] = cir.get_member %[[VAL_2]][1] {name = "c"} : !cir.ptr<![[anon1]]> -> !cir.ptr<!cir.array<!u8i x 4>>

typedef union {
int x;
} U;

// CHECK: %[[VAL_0:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["x", init] {alignment = 4 : i64}
// CHECK: %[[VAL_1:.*]] = cir.alloca !ty_U, !cir.ptr<!ty_U>, ["u", init] {alignment = 4 : i64}
// CHECK: cir.store %arg0, %[[VAL_0]] : !s32i, !cir.ptr<!s32i>
// CHECK: %[[VAL_2:.*]] = cir.load %[[VAL_0]] : !cir.ptr<!s32i>, !s32i
// CHECK: %[[VAL_3:.*]] = cir.cast(bitcast, %[[VAL_1]] : !cir.ptr<!ty_U>), !cir.ptr<!s32i>
// CHECK: cir.store %[[VAL_2]], %[[VAL_3]] : !s32i, !cir.ptr<!s32i>

void union_cast(int x) {
U u = (U) x;
}

0 comments on commit c947dc7

Please sign in to comment.