Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -194,8 +194,12 @@ mlir::Value ComplexExprEmitter::emitCast(CastKind ck, Expr *op,
}

case CK_LValueToRValueBitCast: {
cgf.cgm.errorNYI("ComplexExprEmitter::emitCast CK_LValueToRValueBitCast");
return {};
LValue sourceLVal = cgf.emitLValue(op);
Address addr = sourceLVal.getAddress().withElementType(
builder, cgf.convertTypeForMem(destTy));
LValue destLV = cgf.makeAddrLValue(addr, destTy);
assert(!cir::MissingFeatures::opTBAA());
return emitLoadOfLValue(destLV, op->getExprLoc());
}

case CK_BitCast:
Expand Down
25 changes: 25 additions & 0 deletions clang/test/CIR/CodeGen/complex-cast.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -326,3 +326,28 @@ void complex_to_complex_cast() {
// OGCG: store i32 %[[REAL_INT_CAST]], ptr {{.*}}, align 4
// OGCG: store i32 %[[IMAG_INT_CAST]], ptr getelementptr inbounds nuw ({ i32, i32 }, ptr {{.*}}, i32 0, i32 1), align 4


void lvalue_to_rvalue_bitcast() {
void *a;
int _Complex b = __builtin_bit_cast(int _Complex, a);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
void lvalue_to_rvalue_bitcast() {
void *a;
int _Complex b = __builtin_bit_cast(int _Complex, a);
}
struct CX {
double real;
double imag;
};
void lvalue_to_rvalue_bitcast() {
CX a;
double _Complex b = __builtin_bit_cast(double _Complex, b);
}

I think the test as you had it is UB, even though it will pass. I think my suggested alternative is not UB.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated, thanks!


// CIR-BEFORE: %{{.*}} = cir.cast(bitcast, %{{.*}} : !cir.ptr<!cir.ptr<!void>>), !cir.ptr<!cir.complex<!s32i>>

// CIR-AFTER: %{{.*}} = cir.cast(bitcast, %{{.*}} : !cir.ptr<!cir.ptr<!void>>), !cir.ptr<!cir.complex<!s32i>>

// LLVM: %[[PTR_ADDR:.*]] = alloca ptr, i64 1, align 8
// LLVM: %[[COMPLEX_ADDR:.*]] = alloca { i32, i32 }, i64 1, align 4
// LLVM: %[[PTR_TO_COMPLEX:.*]] = load { i32, i32 }, ptr %[[PTR_ADDR]], align 8
// LLVM: store { i32, i32 } %[[PTR_TO_COMPLEX]], ptr %[[COMPLEX_ADDR]], align 4

// OGCG: %[[A_ADDR:.*]] = alloca ptr, align 8
// OGCG: %[[B_ADDR:.*]] = alloca { i32, i32 }, align 4
// OGCG: %[[A_REAL_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[A_ADDR]], i32 0, i32 0
// OGCG: %[[A_REAL:.*]] = load i32, ptr %[[A_REAL_PTR]], align 8
// OGCG: %[[A_IMAG_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[A_ADDR]], i32 0, i32 1
// OGCG: %[[A_IMAG:.*]] = load i32, ptr %[[A_IMAG_PTR]], align 4
// OGCG: %[[B_REAL_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[B_ADDR]], i32 0, i32 0
// OGCG: %[[B_IMAG_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[B_ADDR]], i32 0, i32 1
// OGCG: store i32 %[[A_REAL]], ptr %[[B_REAL_PTR]], align 4
// OGCG: store i32 %[[A_IMAG]], ptr %[[B_IMAG_PTR]], align 4