diff options
Diffstat (limited to 'clang/lib/CIR/CodeGen')
-rw-r--r-- | clang/lib/CIR/CodeGen/CIRGenBuilder.h | 10 | ||||
-rw-r--r-- | clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp | 4 | ||||
-rw-r--r-- | clang/lib/CIR/CodeGen/CIRGenCXX.cpp | 3 | ||||
-rw-r--r-- | clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp | 2 | ||||
-rw-r--r-- | clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp | 6 | ||||
-rw-r--r-- | clang/lib/CIR/CodeGen/CIRGenFunction.h | 8 | ||||
-rw-r--r-- | clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp | 18 | ||||
-rw-r--r-- | clang/lib/CIR/CodeGen/CIRGenModule.cpp | 87 | ||||
-rw-r--r-- | clang/lib/CIR/CodeGen/CIRGenModule.h | 4 | ||||
-rw-r--r-- | clang/lib/CIR/CodeGen/CIRGenValue.h | 12 |
10 files changed, 131 insertions, 23 deletions
diff --git a/clang/lib/CIR/CodeGen/CIRGenBuilder.h b/clang/lib/CIR/CodeGen/CIRGenBuilder.h index 84acc74..50d585d 100644 --- a/clang/lib/CIR/CodeGen/CIRGenBuilder.h +++ b/clang/lib/CIR/CodeGen/CIRGenBuilder.h @@ -380,6 +380,16 @@ public: /*relative_layout=*/false); } + mlir::Value createDynCastToVoid(mlir::Location loc, mlir::Value src, + bool vtableUseRelativeLayout) { + // TODO(cir): consider address space here. + assert(!cir::MissingFeatures::addressSpace()); + cir::PointerType destTy = getVoidPtrTy(); + return cir::DynamicCastOp::create( + *this, loc, destTy, cir::DynamicCastKind::Ptr, src, + cir::DynamicCastInfoAttr{}, vtableUseRelativeLayout); + } + Address createBaseClassAddr(mlir::Location loc, Address addr, mlir::Type destType, unsigned offset, bool assumeNotNull) { diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp index 4cfa91e..ea31871 100644 --- a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp @@ -463,7 +463,9 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl &gd, unsigned builtinID, return emitLibraryCall(*this, fd, e, cgm.getBuiltinLibFunction(fd, builtinID)); - cgm.errorNYI(e->getSourceRange(), "unimplemented builtin call"); + cgm.errorNYI(e->getSourceRange(), + std::string("unimplemented builtin call: ") + + getContext().BuiltinInfo.getName(builtinID)); return getUndefRValue(e->getType()); } diff --git a/clang/lib/CIR/CodeGen/CIRGenCXX.cpp b/clang/lib/CIR/CodeGen/CIRGenCXX.cpp index 274d11b..171ce1c 100644 --- a/clang/lib/CIR/CodeGen/CIRGenCXX.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenCXX.cpp @@ -171,7 +171,8 @@ cir::FuncOp CIRGenModule::codegenCXXStructor(GlobalDecl gd) { curCGF = nullptr; setNonAliasAttributes(gd, fn); - assert(!cir::MissingFeatures::opFuncAttributesForDefinition()); + setCIRFunctionAttributesForDefinition(mlir::cast<FunctionDecl>(gd.getDecl()), + fn); return fn; } diff --git a/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp b/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp index 81e5fe2..19ed656 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp @@ -871,7 +871,7 @@ bool ConstRecordBuilder::updateRecord(ConstantEmitter &emitter, class ConstExprEmitter : public StmtVisitor<ConstExprEmitter, mlir::Attribute, QualType> { CIRGenModule &cgm; - LLVM_ATTRIBUTE_UNUSED ConstantEmitter &emitter; + [[maybe_unused]] ConstantEmitter &emitter; public: ConstExprEmitter(ConstantEmitter &emitter) diff --git a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp index 637f9ef..138082b 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp @@ -1734,9 +1734,9 @@ mlir::Value ScalarExprEmitter::emitSub(const BinOpInfo &ops) { // LLVM we shall take VLA's, division by element size, etc. // // See more in `EmitSub` in CGExprScalar.cpp. - assert(!cir::MissingFeatures::ptrDiffOp()); - cgf.cgm.errorNYI("ptrdiff"); - return {}; + assert(!cir::MissingFeatures::llvmLoweringPtrDiffConsidersPointee()); + return cir::PtrDiffOp::create(builder, cgf.getLoc(ops.loc), cgf.PtrDiffTy, + ops.lhs, ops.rhs); } mlir::Value ScalarExprEmitter::emitShl(const BinOpInfo &ops) { diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.h b/clang/lib/CIR/CodeGen/CIRGenFunction.h index 0d64c31..3c36f5c 100644 --- a/clang/lib/CIR/CodeGen/CIRGenFunction.h +++ b/clang/lib/CIR/CodeGen/CIRGenFunction.h @@ -1313,10 +1313,10 @@ public: mlir::Value emitCXXNewExpr(const CXXNewExpr *e); - void emitNewArrayInitializer(const CXXNewExpr *E, QualType ElementType, - mlir::Type ElementTy, Address BeginPtr, - mlir::Value NumElements, - mlir::Value AllocSizeWithoutCookie); + void emitNewArrayInitializer(const CXXNewExpr *e, QualType elementType, + mlir::Type elementTy, Address beginPtr, + mlir::Value numElements, + mlir::Value allocSizeWithoutCookie); RValue emitCXXOperatorMemberCallExpr(const CXXOperatorCallExpr *e, const CXXMethodDecl *md, diff --git a/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp b/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp index 1b85a53..c184d4a 100644 --- a/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp @@ -950,8 +950,7 @@ const char *vTableClassNameForType(const CIRGenModule &cgm, const Type *ty) { break; case Type::Enum: - cgm.errorNYI("VTableClassNameForType: Enum"); - break; + return "_ZTVN10__cxxabiv116__enum_type_infoE"; case Type::Record: { const auto *rd = cast<CXXRecordDecl>(cast<RecordType>(ty)->getDecl()) @@ -1945,6 +1944,15 @@ static cir::FuncOp getItaniumDynamicCastFn(CIRGenFunction &cgf) { return cgf.cgm.createRuntimeFunction(FTy, "__dynamic_cast"); } +static Address emitDynamicCastToVoid(CIRGenFunction &cgf, mlir::Location loc, + QualType srcRecordTy, Address src) { + bool vtableUsesRelativeLayout = + cgf.cgm.getItaniumVTableContext().isRelativeLayout(); + mlir::Value ptr = cgf.getBuilder().createDynCastToVoid( + loc, src.getPointer(), vtableUsesRelativeLayout); + return Address{ptr, src.getAlignment()}; +} + static cir::DynamicCastInfoAttr emitDynamicCastInfo(CIRGenFunction &cgf, mlir::Location loc, QualType srcRecordTy, @@ -1979,10 +1987,8 @@ mlir::Value CIRGenItaniumCXXABI::emitDynamicCast(CIRGenFunction &cgf, bool isCastToVoid = destRecordTy.isNull(); assert((!isCastToVoid || !isRefCast) && "cannot cast to void reference"); - if (isCastToVoid) { - cgm.errorNYI(loc, "emitDynamicCastToVoid"); - return {}; - } + if (isCastToVoid) + return emitDynamicCastToVoid(cgf, loc, srcRecordTy, src).getPointer(); // If the destination is effectively final, the cast succeeds if and only // if the dynamic type of the pointer is exactly the destination type. diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.cpp b/clang/lib/CIR/CodeGen/CIRGenModule.cpp index 57c7a44..127f763 100644 --- a/clang/lib/CIR/CodeGen/CIRGenModule.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenModule.cpp @@ -451,7 +451,7 @@ void CIRGenModule::emitGlobalFunctionDefinition(clang::GlobalDecl gd, curCGF = nullptr; setNonAliasAttributes(gd, funcOp); - assert(!cir::MissingFeatures::opFuncAttributesForDefinition()); + setCIRFunctionAttributesForDefinition(funcDecl, funcOp); auto getPriority = [this](const auto *attr) -> int { Expr *e = attr->getPriority(); @@ -1919,6 +1919,91 @@ void CIRGenModule::setFunctionAttributes(GlobalDecl globalDecl, } } +void CIRGenModule::setCIRFunctionAttributesForDefinition( + const clang::FunctionDecl *decl, cir::FuncOp f) { + assert(!cir::MissingFeatures::opFuncUnwindTablesAttr()); + assert(!cir::MissingFeatures::stackProtector()); + + std::optional<cir::InlineKind> existingInlineKind = f.getInlineKind(); + bool isNoInline = + existingInlineKind && *existingInlineKind == cir::InlineKind::NoInline; + bool isAlwaysInline = existingInlineKind && + *existingInlineKind == cir::InlineKind::AlwaysInline; + + if (!decl) { + assert(!cir::MissingFeatures::hlsl()); + + if (!isAlwaysInline && + codeGenOpts.getInlining() == CodeGenOptions::OnlyAlwaysInlining) { + // If inlining is disabled and we don't have a declaration to control + // inlining, mark the function as 'noinline' unless it is explicitly + // marked as 'alwaysinline'. + f.setInlineKindAttr( + cir::InlineAttr::get(&getMLIRContext(), cir::InlineKind::NoInline)); + } + + return; + } + + assert(!cir::MissingFeatures::opFuncArmStreamingAttr()); + assert(!cir::MissingFeatures::opFuncArmNewAttr()); + assert(!cir::MissingFeatures::opFuncOptNoneAttr()); + assert(!cir::MissingFeatures::opFuncMinSizeAttr()); + assert(!cir::MissingFeatures::opFuncNakedAttr()); + assert(!cir::MissingFeatures::opFuncNoDuplicateAttr()); + assert(!cir::MissingFeatures::hlsl()); + + // Handle inline attributes + if (decl->hasAttr<NoInlineAttr>() && !isAlwaysInline) { + // Add noinline if the function isn't always_inline. + f.setInlineKindAttr( + cir::InlineAttr::get(&getMLIRContext(), cir::InlineKind::NoInline)); + } else if (decl->hasAttr<AlwaysInlineAttr>() && !isNoInline) { + // Don't override AlwaysInline with NoInline, or vice versa, since we can't + // specify both in IR. + f.setInlineKindAttr( + cir::InlineAttr::get(&getMLIRContext(), cir::InlineKind::AlwaysInline)); + } else if (codeGenOpts.getInlining() == CodeGenOptions::OnlyAlwaysInlining) { + // If inlining is disabled, force everything that isn't always_inline + // to carry an explicit noinline attribute. + if (!isAlwaysInline) { + f.setInlineKindAttr( + cir::InlineAttr::get(&getMLIRContext(), cir::InlineKind::NoInline)); + } + } else { + // Otherwise, propagate the inline hint attribute and potentially use its + // absence to mark things as noinline. + // Search function and template pattern redeclarations for inline. + if (auto *fd = dyn_cast<FunctionDecl>(decl)) { + // TODO: Share this checkForInline implementation with classic codegen. + // This logic is likely to change over time, so sharing would help ensure + // consistency. + auto checkForInline = [](const FunctionDecl *decl) { + auto checkRedeclForInline = [](const FunctionDecl *redecl) { + return redecl->isInlineSpecified(); + }; + if (any_of(decl->redecls(), checkRedeclForInline)) + return true; + const FunctionDecl *pattern = decl->getTemplateInstantiationPattern(); + if (!pattern) + return false; + return any_of(pattern->redecls(), checkRedeclForInline); + }; + if (checkForInline(fd)) { + f.setInlineKindAttr(cir::InlineAttr::get(&getMLIRContext(), + cir::InlineKind::InlineHint)); + } else if (codeGenOpts.getInlining() == + CodeGenOptions::OnlyHintInlining && + !fd->isInlined() && !isAlwaysInline) { + f.setInlineKindAttr( + cir::InlineAttr::get(&getMLIRContext(), cir::InlineKind::NoInline)); + } + } + } + + assert(!cir::MissingFeatures::opFuncColdHotAttr()); +} + cir::FuncOp CIRGenModule::getOrCreateCIRFunction( StringRef mangledName, mlir::Type funcType, GlobalDecl gd, bool forVTable, bool dontDefer, bool isThunk, ForDefinition_t isForDefinition, diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.h b/clang/lib/CIR/CodeGen/CIRGenModule.h index 690f0ed..1fc116d 100644 --- a/clang/lib/CIR/CodeGen/CIRGenModule.h +++ b/clang/lib/CIR/CodeGen/CIRGenModule.h @@ -429,6 +429,10 @@ public: void setFunctionAttributes(GlobalDecl gd, cir::FuncOp f, bool isIncompleteFunction, bool isThunk); + /// Set extra attributes (inline, etc.) for a function. + void setCIRFunctionAttributesForDefinition(const clang::FunctionDecl *fd, + cir::FuncOp f); + void emitGlobalDefinition(clang::GlobalDecl gd, mlir::Operation *op = nullptr); void emitGlobalFunctionDefinition(clang::GlobalDecl gd, mlir::Operation *op); diff --git a/clang/lib/CIR/CodeGen/CIRGenValue.h b/clang/lib/CIR/CodeGen/CIRGenValue.h index 25b6ecb..c05142e 100644 --- a/clang/lib/CIR/CodeGen/CIRGenValue.h +++ b/clang/lib/CIR/CodeGen/CIRGenValue.h @@ -307,8 +307,8 @@ class AggValueSlot { /// This is set to true if some external code is responsible for setting up a /// destructor for the slot. Otherwise the code which constructs it should /// push the appropriate cleanup. - LLVM_PREFERRED_TYPE(bool) - LLVM_ATTRIBUTE_UNUSED unsigned destructedFlag : 1; + [[maybe_unused]] + LLVM_PREFERRED_TYPE(bool) unsigned destructedFlag : 1; /// This is set to true if the memory in the slot is known to be zero before /// the assignment into it. This means that zero fields don't need to be set. @@ -326,16 +326,16 @@ class AggValueSlot { /// over. Since it's invalid in general to memcpy a non-POD C++ /// object, it's important that this flag never be set when /// evaluating an expression which constructs such an object. - LLVM_PREFERRED_TYPE(bool) - LLVM_ATTRIBUTE_UNUSED unsigned aliasedFlag : 1; + [[maybe_unused]] + LLVM_PREFERRED_TYPE(bool) unsigned aliasedFlag : 1; /// This is set to true if the tail padding of this slot might overlap /// another object that may have already been initialized (and whose /// value must be preserved by this initialization). If so, we may only /// store up to the dsize of the type. Otherwise we can widen stores to /// the size of the type. - LLVM_PREFERRED_TYPE(bool) - LLVM_ATTRIBUTE_UNUSED unsigned overlapFlag : 1; + [[maybe_unused]] + LLVM_PREFERRED_TYPE(bool) unsigned overlapFlag : 1; public: enum IsDestructed_t { IsNotDestructed, IsDestructed }; |