Skip to content

Commit 2762a07

Browse files
authored
[CIR] Implement LValueBitcast for ComplexType (#150668)
This change adds support for LValueBitcast for ComplexType #141365
1 parent 82ad67b commit 2762a07

File tree

7 files changed

+177
-4
lines changed

7 files changed

+177
-4
lines changed

clang/lib/CIR/CodeGen/CIRGenExpr.cpp

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -949,7 +949,6 @@ LValue CIRGenFunction::emitCastLValue(const CastExpr *e) {
949949
case CK_Dynamic:
950950
case CK_ToUnion:
951951
case CK_BaseToDerived:
952-
case CK_LValueBitCast:
953952
case CK_AddressSpaceConversion:
954953
case CK_ObjCObjectLValueCast:
955954
case CK_VectorSplat:
@@ -965,6 +964,18 @@ LValue CIRGenFunction::emitCastLValue(const CastExpr *e) {
965964
return {};
966965
}
967966

967+
case CK_LValueBitCast: {
968+
// This must be a reinterpret_cast (or c-style equivalent).
969+
const auto *ce = cast<ExplicitCastExpr>(e);
970+
971+
cgm.emitExplicitCastExprType(ce, this);
972+
LValue LV = emitLValue(e->getSubExpr());
973+
Address V = LV.getAddress().withElementType(
974+
builder, convertTypeForMem(ce->getTypeAsWritten()->getPointeeType()));
975+
976+
return makeAddrLValue(V, e->getType(), LV.getBaseInfo());
977+
}
978+
968979
case CK_NoOp: {
969980
// CK_NoOp can model a qualification conversion, which can remove an array
970981
// bound and change the IR type.

clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -189,8 +189,11 @@ mlir::Value ComplexExprEmitter::emitCast(CastKind ck, Expr *op,
189189
}
190190

191191
case CK_LValueBitCast: {
192-
cgf.cgm.errorNYI("ComplexExprEmitter::emitCast CK_LValueBitCast");
193-
return {};
192+
LValue origLV = cgf.emitLValue(op);
193+
Address addr =
194+
origLV.getAddress().withElementType(builder, cgf.convertType(destTy));
195+
LValue destLV = cgf.makeAddrLValue(addr, destTy);
196+
return emitLoadOfLValue(destLV, op->getExprLoc());
194197
}
195198

196199
case CK_LValueToRValueBitCast: {

clang/lib/CIR/CodeGen/CIRGenFunction.cpp

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -923,4 +923,130 @@ CIRGenFunction::emitArrayLength(const clang::ArrayType *origArrayType,
923923
return builder.getConstInt(*currSrcLoc, SizeTy, countFromCLAs);
924924
}
925925

926+
// TODO(cir): Most of this function can be shared between CIRGen
927+
// and traditional LLVM codegen
928+
void CIRGenFunction::emitVariablyModifiedType(QualType type) {
929+
assert(type->isVariablyModifiedType() &&
930+
"Must pass variably modified type to EmitVLASizes!");
931+
932+
// We're going to walk down into the type and look for VLA
933+
// expressions.
934+
do {
935+
assert(type->isVariablyModifiedType());
936+
937+
const Type *ty = type.getTypePtr();
938+
switch (ty->getTypeClass()) {
939+
case Type::CountAttributed:
940+
case Type::PackIndexing:
941+
case Type::ArrayParameter:
942+
case Type::HLSLAttributedResource:
943+
case Type::HLSLInlineSpirv:
944+
case Type::PredefinedSugar:
945+
cgm.errorNYI("CIRGenFunction::emitVariablyModifiedType");
946+
947+
#define TYPE(Class, Base)
948+
#define ABSTRACT_TYPE(Class, Base)
949+
#define NON_CANONICAL_TYPE(Class, Base)
950+
#define DEPENDENT_TYPE(Class, Base) case Type::Class:
951+
#define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base)
952+
#include "clang/AST/TypeNodes.inc"
953+
llvm_unreachable(
954+
"dependent type must be resolved before the CIR codegen");
955+
956+
// These types are never variably-modified.
957+
case Type::Builtin:
958+
case Type::Complex:
959+
case Type::Vector:
960+
case Type::ExtVector:
961+
case Type::ConstantMatrix:
962+
case Type::Record:
963+
case Type::Enum:
964+
case Type::Using:
965+
case Type::TemplateSpecialization:
966+
case Type::ObjCTypeParam:
967+
case Type::ObjCObject:
968+
case Type::ObjCInterface:
969+
case Type::ObjCObjectPointer:
970+
case Type::BitInt:
971+
llvm_unreachable("type class is never variably-modified!");
972+
973+
case Type::Elaborated:
974+
type = cast<clang::ElaboratedType>(ty)->getNamedType();
975+
break;
976+
977+
case Type::Adjusted:
978+
type = cast<clang::AdjustedType>(ty)->getAdjustedType();
979+
break;
980+
981+
case Type::Decayed:
982+
type = cast<clang::DecayedType>(ty)->getPointeeType();
983+
break;
984+
985+
case Type::Pointer:
986+
type = cast<clang::PointerType>(ty)->getPointeeType();
987+
break;
988+
989+
case Type::BlockPointer:
990+
type = cast<clang::BlockPointerType>(ty)->getPointeeType();
991+
break;
992+
993+
case Type::LValueReference:
994+
case Type::RValueReference:
995+
type = cast<clang::ReferenceType>(ty)->getPointeeType();
996+
break;
997+
998+
case Type::MemberPointer:
999+
type = cast<clang::MemberPointerType>(ty)->getPointeeType();
1000+
break;
1001+
1002+
case Type::ConstantArray:
1003+
case Type::IncompleteArray:
1004+
// Losing element qualification here is fine.
1005+
type = cast<clang::ArrayType>(ty)->getElementType();
1006+
break;
1007+
1008+
case Type::VariableArray: {
1009+
cgm.errorNYI("CIRGenFunction::emitVariablyModifiedType VLA");
1010+
break;
1011+
}
1012+
1013+
case Type::FunctionProto:
1014+
case Type::FunctionNoProto:
1015+
type = cast<clang::FunctionType>(ty)->getReturnType();
1016+
break;
1017+
1018+
case Type::Paren:
1019+
case Type::TypeOf:
1020+
case Type::UnaryTransform:
1021+
case Type::Attributed:
1022+
case Type::BTFTagAttributed:
1023+
case Type::SubstTemplateTypeParm:
1024+
case Type::MacroQualified:
1025+
// Keep walking after single level desugaring.
1026+
type = type.getSingleStepDesugaredType(getContext());
1027+
break;
1028+
1029+
case Type::Typedef:
1030+
case Type::Decltype:
1031+
case Type::Auto:
1032+
case Type::DeducedTemplateSpecialization:
1033+
// Stop walking: nothing to do.
1034+
return;
1035+
1036+
case Type::TypeOfExpr:
1037+
// Stop walking: emit typeof expression.
1038+
emitIgnoredExpr(cast<clang::TypeOfExprType>(ty)->getUnderlyingExpr());
1039+
return;
1040+
1041+
case Type::Atomic:
1042+
type = cast<clang::AtomicType>(ty)->getValueType();
1043+
break;
1044+
1045+
case Type::Pipe:
1046+
type = cast<clang::PipeType>(ty)->getElementType();
1047+
break;
1048+
}
1049+
} while (type->isVariablyModifiedType());
1050+
}
1051+
9261052
} // namespace clang::CIRGen

clang/lib/CIR/CodeGen/CIRGenFunction.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1201,6 +1201,8 @@ class CIRGenFunction : public CIRGenTypeCache {
12011201
/// inside a function, including static vars etc.
12021202
void emitVarDecl(const clang::VarDecl &d);
12031203

1204+
void emitVariablyModifiedType(QualType ty);
1205+
12041206
mlir::LogicalResult emitWhileStmt(const clang::WhileStmt &s);
12051207

12061208
/// Given an assignment `*lhs = rhs`, emit a test that checks if \p rhs is

clang/lib/CIR/CodeGen/CIRGenModule.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1208,6 +1208,15 @@ cir::GlobalOp CIRGenModule::getGlobalForStringLiteral(const StringLiteral *s,
12081208
return gv;
12091209
}
12101210

1211+
void CIRGenModule::emitExplicitCastExprType(const ExplicitCastExpr *e,
1212+
CIRGenFunction *cgf) {
1213+
if (cgf && e->getType()->isVariablyModifiedType())
1214+
cgf->emitVariablyModifiedType(e->getType());
1215+
1216+
assert(!cir::MissingFeatures::generateDebugInfo() &&
1217+
"emitExplicitCastExprType");
1218+
}
1219+
12111220
void CIRGenModule::emitDeclContext(const DeclContext *dc) {
12121221
for (Decl *decl : dc->decls()) {
12131222
// Unlike other DeclContexts, the contents of an ObjCImplDecl at TU scope

clang/lib/CIR/CodeGen/CIRGenModule.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,11 @@ class CIRGenModule : public CIRGenTypeCache {
252252
getAddrOfGlobal(clang::GlobalDecl gd,
253253
ForDefinition_t isForDefinition = NotForDefinition);
254254

255+
/// Emit type info if type of an expression is a variably modified
256+
/// type. Also emit proper debug info for cast types.
257+
void emitExplicitCastExprType(const ExplicitCastExpr *e,
258+
CIRGenFunction *cgf = nullptr);
259+
255260
/// Emit code for a single global function or variable declaration. Forward
256261
/// declarations are emitted lazily.
257262
void emitGlobal(clang::GlobalDecl gd);

clang/test/CIR/CodeGen/complex-cast.cpp

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -336,7 +336,6 @@ void lvalue_to_rvalue_bitcast() {
336336
double _Complex b = __builtin_bit_cast(double _Complex, a);
337337
}
338338

339-
340339
// CIR-BEFORE: %{{.*}} = cir.cast(bitcast, %{{.*}} : !cir.ptr<!rec_CX>), !cir.ptr<!cir.complex<!cir.double>>
341340

342341
// CIR-AFTER: %{{.*}} = cir.cast(bitcast, %{{.*}} : !cir.ptr<!rec_CX>), !cir.ptr<!cir.complex<!cir.double>>
@@ -356,3 +355,21 @@ void lvalue_to_rvalue_bitcast() {
356355
// OGCG: %[[B_IMAG_PTR:.*]] = getelementptr inbounds nuw { double, double }, ptr %[[B_ADDR]], i32 0, i32 1
357356
// OGCG: store double %[[A_REAL]], ptr %[[B_REAL_PTR]], align 8
358357
// OGCG: store double %[[A_IMAG]], ptr %[[B_IMAG_PTR]], align 8
358+
359+
void lvalue_bitcast() {
360+
CX a;
361+
(double _Complex &)a = {};
362+
}
363+
364+
// CIR-BEFORE: %{{.*}} = cir.cast(bitcast, %{{.*}} : !cir.ptr<!rec_CX>), !cir.ptr<!cir.complex<!cir.double>>
365+
366+
// CIR-AFTER: %{{.*}} = cir.cast(bitcast, %{{.*}} : !cir.ptr<!rec_CX>), !cir.ptr<!cir.complex<!cir.double>>
367+
368+
// LLVM: %[[A_ADDR:.*]] = alloca %struct.CX, i64 1, align 8
369+
// LLVM: store { double, double } zeroinitializer, ptr %[[A_ADDR]], align 8
370+
371+
// OGCG: %[[A_ADDR]] = alloca %struct.CX, align 8
372+
// OGCG: %[[A_REAL_PTR:.*]] = getelementptr inbounds nuw { double, double }, ptr %[[A_ADDR]], i32 0, i32 0
373+
// OGCG: %[[A_IMAG_PTR:.*]] = getelementptr inbounds nuw { double, double }, ptr %[[A_ADDR]], i32 0, i32 1
374+
// OGCG: store double 0.000000e+00, ptr %[[A_REAL_PTR]], align 8
375+
// OGCG: store double 0.000000e+00, ptr %[[A_IMAG_PTR]], align 8

0 commit comments

Comments
 (0)