Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
13 changes: 12 additions & 1 deletion clang/lib/CIR/CodeGen/CIRGenExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -949,7 +949,6 @@ LValue CIRGenFunction::emitCastLValue(const CastExpr *e) {
case CK_Dynamic:
case CK_ToUnion:
case CK_BaseToDerived:
case CK_LValueBitCast:
case CK_AddressSpaceConversion:
case CK_ObjCObjectLValueCast:
case CK_VectorSplat:
Expand All @@ -965,6 +964,18 @@ LValue CIRGenFunction::emitCastLValue(const CastExpr *e) {
return {};
}

case CK_LValueBitCast: {
// This must be a reinterpret_cast (or c-style equivalent).
const auto *ce = cast<ExplicitCastExpr>(e);

cgm.emitExplicitCastExprType(ce, this);
LValue LV = emitLValue(e->getSubExpr());
Address V = LV.getAddress().withElementType(
builder, convertTypeForMem(ce->getTypeAsWritten()->getPointeeType()));

return makeAddrLValue(V, e->getType(), LV.getBaseInfo());
}

case CK_NoOp: {
// CK_NoOp can model a qualification conversion, which can remove an array
// bound and change the IR type.
Expand Down
7 changes: 5 additions & 2 deletions clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -189,8 +189,11 @@ mlir::Value ComplexExprEmitter::emitCast(CastKind ck, Expr *op,
}

case CK_LValueBitCast: {
cgf.cgm.errorNYI("ComplexExprEmitter::emitCast CK_LValueBitCast");
return {};
LValue origLV = cgf.emitLValue(op);
Address addr =
origLV.getAddress().withElementType(builder, cgf.convertType(destTy));
LValue destLV = cgf.makeAddrLValue(addr, destTy);
return emitLoadOfLValue(destLV, op->getExprLoc());
}

case CK_LValueToRValueBitCast: {
Expand Down
126 changes: 126 additions & 0 deletions clang/lib/CIR/CodeGen/CIRGenFunction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -923,4 +923,130 @@ CIRGenFunction::emitArrayLength(const clang::ArrayType *origArrayType,
return builder.getConstInt(*currSrcLoc, SizeTy, countFromCLAs);
}

// TODO(cir): Most of this function can be shared between CIRGen
// and traditional LLVM codegen
void CIRGenFunction::emitVariablyModifiedType(QualType type) {
assert(type->isVariablyModifiedType() &&
"Must pass variably modified type to EmitVLASizes!");

// We're going to walk down into the type and look for VLA
// expressions.
do {
assert(type->isVariablyModifiedType());

const Type *ty = type.getTypePtr();
switch (ty->getTypeClass()) {
case Type::CountAttributed:
case Type::PackIndexing:
case Type::ArrayParameter:
case Type::HLSLAttributedResource:
case Type::HLSLInlineSpirv:
case Type::PredefinedSugar:
cgm.errorNYI("CIRGenFunction::emitVariablyModifiedType");

#define TYPE(Class, Base)
#define ABSTRACT_TYPE(Class, Base)
#define NON_CANONICAL_TYPE(Class, Base)
#define DEPENDENT_TYPE(Class, Base) case Type::Class:
#define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base)
#include "clang/AST/TypeNodes.inc"
llvm_unreachable(
"dependent type must be resolved before the CIR codegen");

// These types are never variably-modified.
case Type::Builtin:
case Type::Complex:
case Type::Vector:
case Type::ExtVector:
case Type::ConstantMatrix:
case Type::Record:
case Type::Enum:
case Type::Using:
case Type::TemplateSpecialization:
case Type::ObjCTypeParam:
case Type::ObjCObject:
case Type::ObjCInterface:
case Type::ObjCObjectPointer:
case Type::BitInt:
llvm_unreachable("type class is never variably-modified!");

case Type::Elaborated:
type = cast<clang::ElaboratedType>(ty)->getNamedType();
break;

case Type::Adjusted:
type = cast<clang::AdjustedType>(ty)->getAdjustedType();
break;

case Type::Decayed:
type = cast<clang::DecayedType>(ty)->getPointeeType();
break;

case Type::Pointer:
type = cast<clang::PointerType>(ty)->getPointeeType();
break;

case Type::BlockPointer:
type = cast<clang::BlockPointerType>(ty)->getPointeeType();
break;

case Type::LValueReference:
case Type::RValueReference:
type = cast<clang::ReferenceType>(ty)->getPointeeType();
break;

case Type::MemberPointer:
type = cast<clang::MemberPointerType>(ty)->getPointeeType();
break;

case Type::ConstantArray:
case Type::IncompleteArray:
// Losing element qualification here is fine.
type = cast<clang::ArrayType>(ty)->getElementType();
break;

case Type::VariableArray: {
cgm.errorNYI("CIRGenFunction::emitVariablyModifiedType VLA");
break;
}

case Type::FunctionProto:
case Type::FunctionNoProto:
type = cast<clang::FunctionType>(ty)->getReturnType();
break;

case Type::Paren:
case Type::TypeOf:
case Type::UnaryTransform:
case Type::Attributed:
case Type::BTFTagAttributed:
case Type::SubstTemplateTypeParm:
case Type::MacroQualified:
// Keep walking after single level desugaring.
type = type.getSingleStepDesugaredType(getContext());
break;

case Type::Typedef:
case Type::Decltype:
case Type::Auto:
case Type::DeducedTemplateSpecialization:
// Stop walking: nothing to do.
return;

case Type::TypeOfExpr:
// Stop walking: emit typeof expression.
emitIgnoredExpr(cast<clang::TypeOfExprType>(ty)->getUnderlyingExpr());
return;

case Type::Atomic:
type = cast<clang::AtomicType>(ty)->getValueType();
break;

case Type::Pipe:
type = cast<clang::PipeType>(ty)->getElementType();
break;
}
} while (type->isVariablyModifiedType());
}

} // namespace clang::CIRGen
2 changes: 2 additions & 0 deletions clang/lib/CIR/CodeGen/CIRGenFunction.h
Original file line number Diff line number Diff line change
Expand Up @@ -1201,6 +1201,8 @@ class CIRGenFunction : public CIRGenTypeCache {
/// inside a function, including static vars etc.
void emitVarDecl(const clang::VarDecl &d);

void emitVariablyModifiedType(QualType ty);

mlir::LogicalResult emitWhileStmt(const clang::WhileStmt &s);

/// Given an assignment `*lhs = rhs`, emit a test that checks if \p rhs is
Expand Down
9 changes: 9 additions & 0 deletions clang/lib/CIR/CodeGen/CIRGenModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1208,6 +1208,15 @@ cir::GlobalOp CIRGenModule::getGlobalForStringLiteral(const StringLiteral *s,
return gv;
}

void CIRGenModule::emitExplicitCastExprType(const ExplicitCastExpr *e,
CIRGenFunction *cgf) {
if (cgf && e->getType()->isVariablyModifiedType())
cgf->emitVariablyModifiedType(e->getType());

assert(!cir::MissingFeatures::generateDebugInfo() &&
"emitExplicitCastExprType");
}

void CIRGenModule::emitDeclContext(const DeclContext *dc) {
for (Decl *decl : dc->decls()) {
// Unlike other DeclContexts, the contents of an ObjCImplDecl at TU scope
Expand Down
5 changes: 5 additions & 0 deletions clang/lib/CIR/CodeGen/CIRGenModule.h
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,11 @@ class CIRGenModule : public CIRGenTypeCache {
getAddrOfGlobal(clang::GlobalDecl gd,
ForDefinition_t isForDefinition = NotForDefinition);

/// Emit type info if type of an expression is a variably modified
/// type. Also emit proper debug info for cast types.
void emitExplicitCastExprType(const ExplicitCastExpr *e,
CIRGenFunction *cgf = nullptr);

/// Emit code for a single global function or variable declaration. Forward
/// declarations are emitted lazily.
void emitGlobal(clang::GlobalDecl gd);
Expand Down
19 changes: 18 additions & 1 deletion clang/test/CIR/CodeGen/complex-cast.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -336,7 +336,6 @@ void lvalue_to_rvalue_bitcast() {
double _Complex b = __builtin_bit_cast(double _Complex, a);
}


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

// CIR-AFTER: %{{.*}} = cir.cast(bitcast, %{{.*}} : !cir.ptr<!rec_CX>), !cir.ptr<!cir.complex<!cir.double>>
Expand All @@ -356,3 +355,21 @@ void lvalue_to_rvalue_bitcast() {
// OGCG: %[[B_IMAG_PTR:.*]] = getelementptr inbounds nuw { double, double }, ptr %[[B_ADDR]], i32 0, i32 1
// OGCG: store double %[[A_REAL]], ptr %[[B_REAL_PTR]], align 8
// OGCG: store double %[[A_IMAG]], ptr %[[B_IMAG_PTR]], align 8

void lvalue_bitcast() {
CX a;
(double _Complex &)a = {};
}

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

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

// LLVM: %[[A_ADDR:.*]] = alloca %struct.CX, i64 1, align 8
// LLVM: store { double, double } zeroinitializer, ptr %[[A_ADDR]], align 8

// OGCG: %[[A_ADDR]] = alloca %struct.CX, align 8
// OGCG: %[[A_REAL_PTR:.*]] = getelementptr inbounds nuw { double, double }, ptr %[[A_ADDR]], i32 0, i32 0
// OGCG: %[[A_IMAG_PTR:.*]] = getelementptr inbounds nuw { double, double }, ptr %[[A_ADDR]], i32 0, i32 1
// OGCG: store double 0.000000e+00, ptr %[[A_REAL_PTR]], align 8
// OGCG: store double 0.000000e+00, ptr %[[A_IMAG_PTR]], align 8