================ @@ -22,13 +34,127 @@ using namespace llvm; namespace cir { namespace direct { +struct ConvertCIRToLLVMPass + : public mlir::PassWrapper<ConvertCIRToLLVMPass, + mlir::OperationPass<mlir::ModuleOp>> { + void getDependentDialects(mlir::DialectRegistry ®istry) const override { + registry.insert<mlir::BuiltinDialect, mlir::DLTIDialect, + mlir::LLVM::LLVMDialect, mlir::func::FuncDialect>(); + } + void runOnOperation() final; + + StringRef getDescription() const override { + return "Convert the prepared CIR dialect module to LLVM dialect"; + } + + StringRef getArgument() const override { return "cir-flat-to-llvm"; } +}; + +mlir::LogicalResult CIRToLLVMGlobalOpLowering::matchAndRewrite( + cir::GlobalOp op, OpAdaptor adaptor, + mlir::ConversionPatternRewriter &rewriter) const { + + // Fetch required values to create LLVM op. + const mlir::Type cirSymType = op.getSymType(); + + // This is the LLVM dialect type + const mlir::Type llvmType = getTypeConverter()->convertType(cirSymType); + // These defaults are just here until the equivalent attributes are + // available on cir.global ops. + const bool isConst = false; + const bool isDsoLocal = true; + const mlir::LLVM::Linkage linkage = mlir::LLVM::Linkage::External; + const StringRef symbol = op.getSymName(); + std::optional<mlir::Attribute> init = op.getInitialValue(); + + SmallVector<mlir::NamedAttribute> attributes; + + // Check for missing funcionalities. + if (!init.has_value()) { + rewriter.replaceOpWithNewOp<mlir::LLVM::GlobalOp>( + op, llvmType, isConst, linkage, symbol, mlir::Attribute(), + /*alignment*/ 0, /*addrSpace*/ 0, /*dsoLocal*/ isDsoLocal, + /*threadLocal*/ false, /*comdat*/ mlir::SymbolRefAttr(), attributes); + return mlir::success(); + } + + // Initializer is a constant array: convert it to a compatible llvm init. + if (auto intAttr = mlir::dyn_cast<cir::IntAttr>(init.value())) { + init = rewriter.getIntegerAttr(llvmType, intAttr.getValue()); + } else { + op.emitError() << "unsupported initializer '" << init.value() << "'"; + return mlir::failure(); + } + + // Rewrite op. + rewriter.replaceOpWithNewOp<mlir::LLVM::GlobalOp>( + op, llvmType, isConst, linkage, symbol, init.value(), /*alignment*/ 0, + /*addrSpace*/ 0, /*dsoLocal*/ isDsoLocal, /*threadLocal*/ false, + /*comdat*/ mlir::SymbolRefAttr(), attributes); + + return mlir::success(); +} + +static void prepareTypeConverter(mlir::LLVMTypeConverter &converter, + mlir::DataLayout &dataLayout) { + converter.addConversion([&](cir::IntType type) -> mlir::Type { + // LLVM doesn't work with signed types, so we drop the CIR signs here. + return mlir::IntegerType::get(type.getContext(), type.getWidth()); + }); +} + +void ConvertCIRToLLVMPass::runOnOperation() { + llvm::TimeTraceScope scope("Convert CIR to LLVM Pass"); + + mlir::ModuleOp module = getOperation(); + mlir::DataLayout dl(module); + mlir::LLVMTypeConverter converter(&getContext()); + prepareTypeConverter(converter, dl); // , lowerModule.get()); + + mlir::RewritePatternSet patterns(&getContext()); + + patterns.add<CIRToLLVMGlobalOpLowering>(converter, patterns.getContext(), dl); + + mlir::ConversionTarget target(getContext()); + target.addLegalOp<mlir::ModuleOp>(); + target.addLegalDialect<mlir::LLVM::LLVMDialect>(); + target.addIllegalDialect<mlir::BuiltinDialect, cir::CIRDialect, + mlir::func::FuncDialect>(); + + if (failed(applyPartialConversion(module, target, std::move(patterns)))) + signalPassFailure(); +} + +static std::unique_ptr<mlir::Pass> createConvertCIRToLLVMPass() { + return std::make_unique<ConvertCIRToLLVMPass>(); +} + +static void populateCIRToLLVMPasses(mlir::OpPassManager &pm) { + pm.addPass(createConvertCIRToLLVMPass()); +} + std::unique_ptr<llvm::Module> lowerDirectlyFromCIRToLLVMIR(mlir::ModuleOp mlirModule, LLVMContext &llvmCtx) { llvm::TimeTraceScope scope("lower from CIR to LLVM directly"); + mlir::MLIRContext *mlirCtx = mlirModule.getContext(); + + mlir::PassManager pm(mlirCtx); + populateCIRToLLVMPasses(pm); + + bool result = !mlir::failed(pm.run(mlirModule)); + if (!result) + report_fatal_error( + "The pass manager failed to lower CIR to LLVMIR dialect!"); + + mlir::registerBuiltinDialectTranslation(*mlirCtx); + mlir::registerLLVMDialectTranslation(*mlirCtx); + + llvm::TimeTraceScope translateScope("translateModuleToLLVMIR"); + std::optional<StringRef> moduleName = mlirModule.getName(); - auto llvmModule = std::make_unique<llvm::Module>( - moduleName ? *moduleName : "CIRToLLVMModule", llvmCtx); + std::unique_ptr<llvm::Module> llvmModule = mlir::translateModuleToLLVMIR( + mlirModule, llvmCtx, moduleName ? *moduleName : "CIRToLLVMModule"); ---------------- erichkeane wrote:
```suggestion mlirModule, llvmCtx, moduleName.value_or("CIRToLLVMModule")); ``` Better yet, make `moduleName` above a `StringRef`, and just do `mlirModule.getName().value_or("CIRToLLVMModule"));` https://github.com/llvm/llvm-project/pull/125260 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits