diff options
Diffstat (limited to 'clang/lib/CIR')
-rw-r--r-- | clang/lib/CIR/CodeGen/CIRGenAtomic.cpp | 4 | ||||
-rw-r--r-- | clang/lib/CIR/CodeGen/CIRGenModule.cpp | 40 | ||||
-rw-r--r-- | clang/lib/CIR/CodeGen/CIRGenModule.h | 7 | ||||
-rw-r--r-- | clang/lib/CIR/CodeGen/CIRGenOpenACCClause.cpp | 6 | ||||
-rw-r--r-- | clang/lib/CIR/CodeGen/CIRGenOpenACCRecipe.cpp | 132 | ||||
-rw-r--r-- | clang/lib/CIR/CodeGen/CIRGenOpenACCRecipe.h | 15 | ||||
-rw-r--r-- | clang/lib/CIR/Dialect/IR/CIRDialect.cpp | 64 | ||||
-rw-r--r-- | clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp | 37 | ||||
-rw-r--r-- | clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 16 |
9 files changed, 271 insertions, 50 deletions
diff --git a/clang/lib/CIR/CodeGen/CIRGenAtomic.cpp b/clang/lib/CIR/CodeGen/CIRGenAtomic.cpp index 0f4d6d2..a9983f8 100644 --- a/clang/lib/CIR/CodeGen/CIRGenAtomic.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenAtomic.cpp @@ -255,7 +255,7 @@ static void emitAtomicCmpXchg(CIRGenFunction &cgf, AtomicExpr *e, bool isWeak, mlir::Value expected = builder.createLoad(loc, val1); mlir::Value desired = builder.createLoad(loc, val2); - auto cmpxchg = cir::AtomicCmpXchg::create( + auto cmpxchg = cir::AtomicCmpXchgOp::create( builder, loc, expected.getType(), builder.getBoolTy(), ptr.getPointer(), expected, desired, cir::MemOrderAttr::get(&cgf.getMLIRContext(), successOrder), @@ -404,7 +404,7 @@ static void emitAtomicOp(CIRGenFunction &cgf, AtomicExpr *expr, Address dest, case AtomicExpr::AO__c11_atomic_exchange: case AtomicExpr::AO__atomic_exchange_n: case AtomicExpr::AO__atomic_exchange: - opName = cir::AtomicXchg::getOperationName(); + opName = cir::AtomicXchgOp::getOperationName(); break; case AtomicExpr::AO__opencl_atomic_init: diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.cpp b/clang/lib/CIR/CodeGen/CIRGenModule.cpp index fe1ea56..82b1051 100644 --- a/clang/lib/CIR/CodeGen/CIRGenModule.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenModule.cpp @@ -451,15 +451,47 @@ void CIRGenModule::emitGlobalFunctionDefinition(clang::GlobalDecl gd, setNonAliasAttributes(gd, funcOp); assert(!cir::MissingFeatures::opFuncAttributesForDefinition()); - if (funcDecl->getAttr<ConstructorAttr>()) - errorNYI(funcDecl->getSourceRange(), "constructor attribute"); - if (funcDecl->getAttr<DestructorAttr>()) - errorNYI(funcDecl->getSourceRange(), "destructor attribute"); + auto getPriority = [this](const auto *attr) -> int { + Expr *e = attr->getPriority(); + if (e) + return e->EvaluateKnownConstInt(this->getASTContext()).getExtValue(); + return attr->DefaultPriority; + }; + + if (const ConstructorAttr *ca = funcDecl->getAttr<ConstructorAttr>()) + addGlobalCtor(funcOp, getPriority(ca)); + if (const DestructorAttr *da = funcDecl->getAttr<DestructorAttr>()) + addGlobalDtor(funcOp, getPriority(da)); if (funcDecl->getAttr<AnnotateAttr>()) errorNYI(funcDecl->getSourceRange(), "deferredAnnotations"); } +/// Track functions to be called before main() runs. +void CIRGenModule::addGlobalCtor(cir::FuncOp ctor, + std::optional<int> priority) { + assert(!cir::MissingFeatures::globalCtorLexOrder()); + assert(!cir::MissingFeatures::globalCtorAssociatedData()); + + // Traditional LLVM codegen directly adds the function to the list of global + // ctors. In CIR we just add a global_ctor attribute to the function. The + // global list is created in LoweringPrepare. + // + // FIXME(from traditional LLVM): Type coercion of void()* types. + ctor.setGlobalCtorPriority(priority); +} + +/// Add a function to the list that will be called when the module is unloaded. +void CIRGenModule::addGlobalDtor(cir::FuncOp dtor, + std::optional<int> priority) { + if (codeGenOpts.RegisterGlobalDtorsWithAtExit && + (!getASTContext().getTargetInfo().getTriple().isOSAIX())) + errorNYI(dtor.getLoc(), "registerGlobalDtorsWithAtExit"); + + // FIXME(from traditional LLVM): Type coercion of void()* types. + dtor.setGlobalDtorPriority(priority); +} + void CIRGenModule::handleCXXStaticMemberVarInstantiation(VarDecl *vd) { VarDecl::DefinitionKind dk = vd->isThisDeclarationADefinition(); if (dk == VarDecl::Definition && vd->hasAttr<DLLImportAttr>()) diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.h b/clang/lib/CIR/CodeGen/CIRGenModule.h index f627bae..690f0ed 100644 --- a/clang/lib/CIR/CodeGen/CIRGenModule.h +++ b/clang/lib/CIR/CodeGen/CIRGenModule.h @@ -159,6 +159,13 @@ public: bool isConstant = false, mlir::Operation *insertPoint = nullptr); + /// Add a global constructor or destructor to the module. + /// The priority is optional, if not specified, the default priority is used. + void addGlobalCtor(cir::FuncOp ctor, + std::optional<int> priority = std::nullopt); + void addGlobalDtor(cir::FuncOp dtor, + std::optional<int> priority = std::nullopt); + bool shouldZeroInitPadding() const { // In C23 (N3096) $6.7.10: // """ diff --git a/clang/lib/CIR/CodeGen/CIRGenOpenACCClause.cpp b/clang/lib/CIR/CodeGen/CIRGenOpenACCClause.cpp index 3d86f71..ce4ae7e 100644 --- a/clang/lib/CIR/CodeGen/CIRGenOpenACCClause.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenOpenACCClause.cpp @@ -1005,7 +1005,7 @@ public: /*temporary=*/nullptr, OpenACCReductionOperator::Invalid, Decl::castToDeclContext(cgf.curFuncDecl), opInfo.origType, opInfo.bounds.size(), opInfo.boundTypes, opInfo.baseType, - privateOp); + privateOp, /*reductionCombinerRecipes=*/{}); // TODO: OpenACC: The dialect is going to change in the near future to // have these be on a different operation, so when that changes, we // probably need to change these here. @@ -1046,7 +1046,7 @@ public: OpenACCReductionOperator::Invalid, Decl::castToDeclContext(cgf.curFuncDecl), opInfo.origType, opInfo.bounds.size(), opInfo.boundTypes, opInfo.baseType, - firstPrivateOp); + firstPrivateOp, /*reductionCombinerRecipe=*/{}); // TODO: OpenACC: The dialect is going to change in the near future to // have these be on a different operation, so when that changes, we @@ -1088,7 +1088,7 @@ public: /*temporary=*/nullptr, clause.getReductionOp(), Decl::castToDeclContext(cgf.curFuncDecl), opInfo.origType, opInfo.bounds.size(), opInfo.boundTypes, opInfo.baseType, - reductionOp); + reductionOp, varRecipe.CombinerRecipes); operation.addReduction(builder.getContext(), reductionOp, recipe); } diff --git a/clang/lib/CIR/CodeGen/CIRGenOpenACCRecipe.cpp b/clang/lib/CIR/CodeGen/CIRGenOpenACCRecipe.cpp index 24a5fc2..ce14aa8 100644 --- a/clang/lib/CIR/CodeGen/CIRGenOpenACCRecipe.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenOpenACCRecipe.cpp @@ -527,16 +527,142 @@ void OpenACCRecipeBuilderBase::createFirstprivateRecipeCopy( // doesn't restore it aftewards. void OpenACCRecipeBuilderBase::createReductionRecipeCombiner( mlir::Location loc, mlir::Location locEnd, mlir::Value mainOp, - mlir::acc::ReductionRecipeOp recipe, size_t numBounds) { + mlir::acc::ReductionRecipeOp recipe, size_t numBounds, QualType origType, + llvm::ArrayRef<OpenACCReductionRecipe::CombinerRecipe> combinerRecipes) { mlir::Block *block = createRecipeBlock(recipe.getCombinerRegion(), mainOp.getType(), loc, numBounds, /*isInit=*/false); builder.setInsertionPointToEnd(&recipe.getCombinerRegion().back()); CIRGenFunction::LexicalScope ls(cgf, loc, block); - mlir::BlockArgument lhsArg = block->getArgument(0); + mlir::Value lhsArg = block->getArgument(0); + mlir::Value rhsArg = block->getArgument(1); + llvm::MutableArrayRef<mlir::BlockArgument> boundsRange = + block->getArguments().drop_front(2); + + if (llvm::any_of(combinerRecipes, [](auto &r) { return r.Op == nullptr; })) { + cgf.cgm.errorNYI(loc, "OpenACC Reduction combiner not generated"); + mlir::acc::YieldOp::create(builder, locEnd, block->getArgument(0)); + return; + } + + // apply the bounds so that we can get our bounds emitted correctly. + for (mlir::BlockArgument boundArg : llvm::reverse(boundsRange)) + std::tie(lhsArg, rhsArg) = + createBoundsLoop(lhsArg, rhsArg, boundArg, loc, /*inverse=*/false); + + // Emitter for when we know this isn't a struct or array we have to loop + // through. This should work for the 'field' once the get-element call has + // been made. + auto emitSingleCombiner = + [&](mlir::Value lhsArg, mlir::Value rhsArg, + const OpenACCReductionRecipe::CombinerRecipe &combiner) { + mlir::Type elementTy = + mlir::cast<cir::PointerType>(lhsArg.getType()).getPointee(); + CIRGenFunction::DeclMapRevertingRAII declMapRAIILhs{cgf, combiner.LHS}; + cgf.setAddrOfLocalVar( + combiner.LHS, Address{lhsArg, elementTy, + cgf.getContext().getDeclAlign(combiner.LHS)}); + CIRGenFunction::DeclMapRevertingRAII declMapRAIIRhs{cgf, combiner.RHS}; + cgf.setAddrOfLocalVar( + combiner.RHS, Address{rhsArg, elementTy, + cgf.getContext().getDeclAlign(combiner.RHS)}); + + [[maybe_unused]] mlir::LogicalResult stmtRes = + cgf.emitStmt(combiner.Op, /*useCurrentScope=*/true); + }; + + // Emitter for when we know this is either a non-array or element of an array + // (which also shouldn't be an array type?). This function should generate the + // initialization code for an entire 'array-element'/non-array, including + // diving into each element of a struct (if necessary). + auto emitCombiner = [&](mlir::Value lhsArg, mlir::Value rhsArg, QualType ty) { + assert(!ty->isArrayType() && "Array type shouldn't get here"); + if (const auto *rd = ty->getAsRecordDecl()) { + if (combinerRecipes.size() == 1 && + cgf.getContext().hasSameType(ty, combinerRecipes[0].LHS->getType())) { + // If this is a 'top level' operator on the type we can just emit this + // as a simple one. + emitSingleCombiner(lhsArg, rhsArg, combinerRecipes[0]); + } else { + // else we have to handle each individual field after after a + // get-element. + for (const auto &[field, combiner] : + llvm::zip_equal(rd->fields(), combinerRecipes)) { + mlir::Type fieldType = cgf.convertType(field->getType()); + auto fieldPtr = cir::PointerType::get(fieldType); + + mlir::Value lhsField = builder.createGetMember( + loc, fieldPtr, lhsArg, field->getName(), field->getFieldIndex()); + mlir::Value rhsField = builder.createGetMember( + loc, fieldPtr, rhsArg, field->getName(), field->getFieldIndex()); + + emitSingleCombiner(lhsField, rhsField, combiner); + } + } + + } else { + // if this is a single-thing (because we should know this isn't an array, + // as Sema wouldn't let us get here), we can just do a normal emit call. + emitSingleCombiner(lhsArg, rhsArg, combinerRecipes[0]); + } + }; + + if (const auto *cat = cgf.getContext().getAsConstantArrayType(origType)) { + // If we're in an array, we have to emit the combiner for each element of + // the array. + auto itrTy = mlir::cast<cir::IntType>(cgf.PtrDiffTy); + auto itrPtrTy = cir::PointerType::get(itrTy); + + mlir::Value zero = + builder.getConstInt(loc, mlir::cast<cir::IntType>(cgf.PtrDiffTy), 0); + mlir::Value itr = + cir::AllocaOp::create(builder, loc, itrPtrTy, itrTy, "itr", + cgf.cgm.getSize(cgf.getPointerAlign())); + builder.CIRBaseBuilderTy::createStore(loc, zero, itr); + + builder.setInsertionPointAfter(builder.createFor( + loc, + /*condBuilder=*/ + [&](mlir::OpBuilder &b, mlir::Location loc) { + auto loadItr = cir::LoadOp::create(builder, loc, {itr}); + mlir::Value arraySize = builder.getConstInt( + loc, mlir::cast<cir::IntType>(cgf.PtrDiffTy), cat->getZExtSize()); + auto cmp = builder.createCompare(loc, cir::CmpOpKind::lt, loadItr, + arraySize); + builder.createCondition(cmp); + }, + /*bodyBuilder=*/ + [&](mlir::OpBuilder &b, mlir::Location loc) { + auto loadItr = cir::LoadOp::create(builder, loc, {itr}); + auto lhsElt = builder.getArrayElement( + loc, loc, lhsArg, cgf.convertType(cat->getElementType()), loadItr, + /*shouldDecay=*/true); + auto rhsElt = builder.getArrayElement( + loc, loc, rhsArg, cgf.convertType(cat->getElementType()), loadItr, + /*shouldDecay=*/true); + + emitCombiner(lhsElt, rhsElt, cat->getElementType()); + builder.createYield(loc); + }, + /*stepBuilder=*/ + [&](mlir::OpBuilder &b, mlir::Location loc) { + auto loadItr = cir::LoadOp::create(builder, loc, {itr}); + auto inc = cir::UnaryOp::create(builder, loc, loadItr.getType(), + cir::UnaryOpKind::Inc, loadItr); + builder.CIRBaseBuilderTy::createStore(loc, inc, itr); + builder.createYield(loc); + })); - mlir::acc::YieldOp::create(builder, locEnd, lhsArg); + } else if (origType->isArrayType()) { + cgf.cgm.errorNYI(loc, + "OpenACC Reduction combiner non-constant array recipe"); + } else { + emitCombiner(lhsArg, rhsArg, origType); + } + + builder.setInsertionPointToEnd(&recipe.getCombinerRegion().back()); + mlir::acc::YieldOp::create(builder, locEnd, block->getArgument(0)); } } // namespace clang::CIRGen diff --git a/clang/lib/CIR/CodeGen/CIRGenOpenACCRecipe.h b/clang/lib/CIR/CodeGen/CIRGenOpenACCRecipe.h index a5da744..745d424 100644 --- a/clang/lib/CIR/CodeGen/CIRGenOpenACCRecipe.h +++ b/clang/lib/CIR/CodeGen/CIRGenOpenACCRecipe.h @@ -64,10 +64,10 @@ protected: // that this function is not 'insertion point' clean, in that it alters the // insertion point to be inside of the 'combiner' section of the recipe, but // doesn't restore it aftewards. - void createReductionRecipeCombiner(mlir::Location loc, mlir::Location locEnd, - mlir::Value mainOp, - mlir::acc::ReductionRecipeOp recipe, - size_t numBounds); + void createReductionRecipeCombiner( + mlir::Location loc, mlir::Location locEnd, mlir::Value mainOp, + mlir::acc::ReductionRecipeOp recipe, size_t numBounds, QualType origType, + llvm::ArrayRef<OpenACCReductionRecipe::CombinerRecipe> combinerRecipes); void createInitRecipe(mlir::Location loc, mlir::Location locEnd, SourceRange exprRange, mlir::Value mainOp, @@ -169,7 +169,9 @@ public: const Expr *varRef, const VarDecl *varRecipe, const VarDecl *temporary, OpenACCReductionOperator reductionOp, DeclContext *dc, QualType origType, size_t numBounds, llvm::ArrayRef<QualType> boundTypes, QualType baseType, - mlir::Value mainOp) { + mlir::Value mainOp, + llvm::ArrayRef<OpenACCReductionRecipe::CombinerRecipe> + reductionCombinerRecipes) { assert(!varRecipe->getType()->isSpecificBuiltinType( BuiltinType::ArraySection) && "array section shouldn't make it to recipe creation"); @@ -208,7 +210,8 @@ public: createInitRecipe(loc, locEnd, varRef->getSourceRange(), mainOp, recipe.getInitRegion(), numBounds, boundTypes, varRecipe, origType, /*emitInitExpr=*/true); - createReductionRecipeCombiner(loc, locEnd, mainOp, recipe, numBounds); + createReductionRecipeCombiner(loc, locEnd, mainOp, recipe, numBounds, + origType, reductionCombinerRecipes); } else { static_assert(std::is_same_v<RecipeTy, mlir::acc::FirstprivateRecipeOp>); createInitRecipe(loc, locEnd, varRef->getSourceRange(), mainOp, diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp index 5f88590..7af3dc1 100644 --- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp +++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp @@ -15,6 +15,7 @@ #include "clang/CIR/Dialect/IR/CIROpsEnums.h" #include "clang/CIR/Dialect/IR/CIRTypes.h" +#include "mlir/IR/DialectImplementation.h" #include "mlir/Interfaces/ControlFlowInterfaces.h" #include "mlir/Interfaces/FunctionImplementation.h" #include "mlir/Support/LLVM.h" @@ -1720,6 +1721,43 @@ ParseResult cir::FuncOp::parse(OpAsmParser &parser, OperationState &state) { hasAlias = true; } + auto parseGlobalDtorCtor = + [&](StringRef keyword, + llvm::function_ref<void(std::optional<int> prio)> createAttr) + -> mlir::LogicalResult { + if (mlir::succeeded(parser.parseOptionalKeyword(keyword))) { + std::optional<int> priority; + if (mlir::succeeded(parser.parseOptionalLParen())) { + auto parsedPriority = mlir::FieldParser<int>::parse(parser); + if (mlir::failed(parsedPriority)) + return parser.emitError(parser.getCurrentLocation(), + "failed to parse 'priority', of type 'int'"); + priority = parsedPriority.value_or(int()); + // Parse literal ')' + if (parser.parseRParen()) + return failure(); + } + createAttr(priority); + } + return success(); + }; + + if (parseGlobalDtorCtor("global_ctor", [&](std::optional<int> priority) { + mlir::IntegerAttr globalCtorPriorityAttr = + builder.getI32IntegerAttr(priority.value_or(65535)); + state.addAttribute(getGlobalCtorPriorityAttrName(state.name), + globalCtorPriorityAttr); + }).failed()) + return failure(); + + if (parseGlobalDtorCtor("global_dtor", [&](std::optional<int> priority) { + mlir::IntegerAttr globalDtorPriorityAttr = + builder.getI32IntegerAttr(priority.value_or(65535)); + state.addAttribute(getGlobalDtorPriorityAttrName(state.name), + globalDtorPriorityAttr); + }).failed()) + return failure(); + // Parse the optional function body. auto *body = state.addRegion(); OptionalParseResult parseResult = parser.parseOptionalRegion( @@ -1801,6 +1839,18 @@ void cir::FuncOp::print(OpAsmPrinter &p) { p << ")"; } + if (auto globalCtorPriority = getGlobalCtorPriority()) { + p << " global_ctor"; + if (globalCtorPriority.value() != 65535) + p << "(" << globalCtorPriority.value() << ")"; + } + + if (auto globalDtorPriority = getGlobalDtorPriority()) { + p << " global_dtor"; + if (globalDtorPriority.value() != 65535) + p << "(" << globalDtorPriority.value() << ")"; + } + // Print the body if this is not an external function. Region &body = getOperation()->getRegion(0); if (!body.empty()) { @@ -2851,20 +2901,6 @@ mlir::LogicalResult cir::ThrowOp::verify() { } //===----------------------------------------------------------------------===// -// AtomicCmpXchg -//===----------------------------------------------------------------------===// - -LogicalResult cir::AtomicCmpXchg::verify() { - mlir::Type pointeeType = getPtr().getType().getPointee(); - - if (pointeeType != getExpected().getType() || - pointeeType != getDesired().getType()) - return emitOpError("ptr, expected and desired types must match"); - - return success(); -} - -//===----------------------------------------------------------------------===// // TypeInfoAttr //===----------------------------------------------------------------------===// diff --git a/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp b/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp index dbff0b9..d99c362 100644 --- a/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp +++ b/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp @@ -105,6 +105,8 @@ struct LoweringPreparePass : public LoweringPrepareBase<LoweringPreparePass> { /// List of ctors and their priorities to be called before main() llvm::SmallVector<std::pair<std::string, uint32_t>, 4> globalCtorList; + /// List of dtors and their priorities to be called when unloading module. + llvm::SmallVector<std::pair<std::string, uint32_t>, 4> globalDtorList; void setASTContext(clang::ASTContext *c) { astCtx = c; @@ -823,10 +825,13 @@ void LoweringPreparePass::buildGlobalCtorDtorList() { mlir::ArrayAttr::get(&getContext(), globalCtors)); } - // We will eventual need to populate a global_dtor list, but that's not - // needed for globals with destructors. It will only be needed for functions - // that are marked as global destructors with an attribute. - assert(!cir::MissingFeatures::opGlobalDtorList()); + if (!globalDtorList.empty()) { + llvm::SmallVector<mlir::Attribute> globalDtors = + prepareCtorDtorAttrList<cir::GlobalDtorAttr>(&getContext(), + globalDtorList); + mlirModule->setAttr(cir::CIRDialect::getGlobalDtorsAttrName(), + mlir::ArrayAttr::get(&getContext(), globalDtors)); + } } void LoweringPreparePass::buildCXXGlobalInitFunc() { @@ -975,22 +980,28 @@ void LoweringPreparePass::lowerArrayCtor(cir::ArrayCtor op) { } void LoweringPreparePass::runOnOp(mlir::Operation *op) { - if (auto arrayCtor = dyn_cast<ArrayCtor>(op)) + if (auto arrayCtor = dyn_cast<cir::ArrayCtor>(op)) { lowerArrayCtor(arrayCtor); - else if (auto arrayDtor = dyn_cast<cir::ArrayDtor>(op)) + } else if (auto arrayDtor = dyn_cast<cir::ArrayDtor>(op)) { lowerArrayDtor(arrayDtor); - else if (auto cast = mlir::dyn_cast<cir::CastOp>(op)) + } else if (auto cast = mlir::dyn_cast<cir::CastOp>(op)) { lowerCastOp(cast); - else if (auto complexDiv = mlir::dyn_cast<cir::ComplexDivOp>(op)) + } else if (auto complexDiv = mlir::dyn_cast<cir::ComplexDivOp>(op)) { lowerComplexDivOp(complexDiv); - else if (auto complexMul = mlir::dyn_cast<cir::ComplexMulOp>(op)) + } else if (auto complexMul = mlir::dyn_cast<cir::ComplexMulOp>(op)) { lowerComplexMulOp(complexMul); - else if (auto glob = mlir::dyn_cast<cir::GlobalOp>(op)) + } else if (auto glob = mlir::dyn_cast<cir::GlobalOp>(op)) { lowerGlobalOp(glob); - else if (auto dynamicCast = mlir::dyn_cast<cir::DynamicCastOp>(op)) + } else if (auto dynamicCast = mlir::dyn_cast<cir::DynamicCastOp>(op)) { lowerDynamicCastOp(dynamicCast); - else if (auto unary = mlir::dyn_cast<cir::UnaryOp>(op)) + } else if (auto unary = mlir::dyn_cast<cir::UnaryOp>(op)) { lowerUnaryOp(unary); + } else if (auto fnOp = dyn_cast<cir::FuncOp>(op)) { + if (auto globalCtor = fnOp.getGlobalCtorPriority()) + globalCtorList.emplace_back(fnOp.getName(), globalCtor.value()); + else if (auto globalDtor = fnOp.getGlobalDtorPriority()) + globalDtorList.emplace_back(fnOp.getName(), globalDtor.value()); + } } void LoweringPreparePass::runOnOperation() { @@ -1003,7 +1014,7 @@ void LoweringPreparePass::runOnOperation() { op->walk([&](mlir::Operation *op) { if (mlir::isa<cir::ArrayCtor, cir::ArrayDtor, cir::CastOp, cir::ComplexMulOp, cir::ComplexDivOp, cir::DynamicCastOp, - cir::GlobalOp, cir::UnaryOp>(op)) + cir::FuncOp, cir::GlobalOp, cir::UnaryOp>(op)) opsToTransform.push_back(op); }); diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp index 26e0ba9..3abba3d 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp @@ -694,8 +694,8 @@ getLLVMMemOrder(std::optional<cir::MemOrder> memorder) { llvm_unreachable("unknown memory order"); } -mlir::LogicalResult CIRToLLVMAtomicCmpXchgLowering::matchAndRewrite( - cir::AtomicCmpXchg op, OpAdaptor adaptor, +mlir::LogicalResult CIRToLLVMAtomicCmpXchgOpLowering::matchAndRewrite( + cir::AtomicCmpXchgOp op, OpAdaptor adaptor, mlir::ConversionPatternRewriter &rewriter) const { mlir::Value expected = adaptor.getExpected(); mlir::Value desired = adaptor.getDesired(); @@ -719,8 +719,8 @@ mlir::LogicalResult CIRToLLVMAtomicCmpXchgLowering::matchAndRewrite( return mlir::success(); } -mlir::LogicalResult CIRToLLVMAtomicXchgLowering::matchAndRewrite( - cir::AtomicXchg op, OpAdaptor adaptor, +mlir::LogicalResult CIRToLLVMAtomicXchgOpLowering::matchAndRewrite( + cir::AtomicXchgOp op, OpAdaptor adaptor, mlir::ConversionPatternRewriter &rewriter) const { assert(!cir::MissingFeatures::atomicSyncScopeID()); mlir::LLVM::AtomicOrdering llvmOrder = getLLVMMemOrder(adaptor.getMemOrder()); @@ -2598,7 +2598,13 @@ void ConvertCIRToLLVMPass::runOnOperation() { return std::make_pair(ctorAttr.getName(), ctorAttr.getPriority()); }); - assert(!cir::MissingFeatures::opGlobalDtorList()); + // Emit the llvm.global_dtors array. + buildCtorDtorList(module, cir::CIRDialect::getGlobalDtorsAttrName(), + "llvm.global_dtors", [](mlir::Attribute attr) { + auto dtorAttr = mlir::cast<cir::GlobalDtorAttr>(attr); + return std::make_pair(dtorAttr.getName(), + dtorAttr.getPriority()); + }); } mlir::LogicalResult CIRToLLVMBrOpLowering::matchAndRewrite( |