1212
1313#include " clang/CIR/LowerToLLVM.h"
1414
15+ #include " mlir/Conversion/LLVMCommon/TypeConverter.h"
16+ #include " mlir/Dialect/DLTI/DLTI.h"
17+ #include " mlir/Dialect/Func/IR/FuncOps.h"
18+ #include " mlir/Dialect/LLVMIR/LLVMDialect.h"
19+ #include " mlir/IR/BuiltinDialect.h"
1520#include " mlir/IR/BuiltinOps.h"
21+ #include " mlir/Pass/Pass.h"
22+ #include " mlir/Pass/PassManager.h"
23+ #include " mlir/Target/LLVMIR/Dialect/Builtin/BuiltinToLLVMIRTranslation.h"
24+ #include " mlir/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.h"
25+ #include " mlir/Target/LLVMIR/Export.h"
26+ #include " mlir/Transforms/DialectConversion.h"
27+ #include " clang/CIR/Dialect/IR/CIRDialect.h"
1628#include " llvm/IR/Module.h"
1729#include " llvm/Support/TimeProfiler.h"
1830
@@ -22,13 +34,127 @@ using namespace llvm;
2234namespace cir {
2335namespace direct {
2436
37+ struct ConvertCIRToLLVMPass
38+ : public mlir::PassWrapper<ConvertCIRToLLVMPass,
39+ mlir::OperationPass<mlir::ModuleOp>> {
40+ void getDependentDialects (mlir::DialectRegistry ®istry) const override {
41+ registry.insert <mlir::BuiltinDialect, mlir::DLTIDialect,
42+ mlir::LLVM::LLVMDialect, mlir::func::FuncDialect>();
43+ }
44+ void runOnOperation () final ;
45+
46+ StringRef getDescription () const override {
47+ return " Convert the prepared CIR dialect module to LLVM dialect" ;
48+ }
49+
50+ StringRef getArgument () const override { return " cir-flat-to-llvm" ; }
51+ };
52+
53+ mlir::LogicalResult CIRToLLVMGlobalOpLowering::matchAndRewrite (
54+ cir::GlobalOp op, OpAdaptor adaptor,
55+ mlir::ConversionPatternRewriter &rewriter) const {
56+
57+ // Fetch required values to create LLVM op.
58+ const mlir::Type cirSymType = op.getSymType ();
59+
60+ // This is the LLVM dialect type
61+ const mlir::Type llvmType = getTypeConverter ()->convertType (cirSymType);
62+ // These defaults are just here until the equivalent attributes are
63+ // available on cir.global ops.
64+ const bool isConst = false ;
65+ const bool isDsoLocal = true ;
66+ const mlir::LLVM::Linkage linkage = mlir::LLVM::Linkage::External;
67+ const StringRef symbol = op.getSymName ();
68+ std::optional<mlir::Attribute> init = op.getInitialValue ();
69+
70+ SmallVector<mlir::NamedAttribute> attributes;
71+
72+ // Check for missing funcionalities.
73+ if (!init.has_value ()) {
74+ rewriter.replaceOpWithNewOp <mlir::LLVM::GlobalOp>(
75+ op, llvmType, isConst, linkage, symbol, mlir::Attribute (),
76+ /* alignment*/ 0 , /* addrSpace*/ 0 , /* dsoLocal*/ isDsoLocal,
77+ /* threadLocal*/ false , /* comdat*/ mlir::SymbolRefAttr (), attributes);
78+ return mlir::success ();
79+ }
80+
81+ // Initializer is a constant array: convert it to a compatible llvm init.
82+ if (auto intAttr = mlir::dyn_cast<cir::IntAttr>(init.value ())) {
83+ init = rewriter.getIntegerAttr (llvmType, intAttr.getValue ());
84+ } else {
85+ op.emitError () << " unsupported initializer '" << init.value () << " '" ;
86+ return mlir::failure ();
87+ }
88+
89+ // Rewrite op.
90+ rewriter.replaceOpWithNewOp <mlir::LLVM::GlobalOp>(
91+ op, llvmType, isConst, linkage, symbol, init.value (), /* alignment*/ 0 ,
92+ /* addrSpace*/ 0 , /* dsoLocal*/ isDsoLocal, /* threadLocal*/ false ,
93+ /* comdat*/ mlir::SymbolRefAttr (), attributes);
94+
95+ return mlir::success ();
96+ }
97+
98+ static void prepareTypeConverter (mlir::LLVMTypeConverter &converter,
99+ mlir::DataLayout &dataLayout) {
100+ converter.addConversion ([&](cir::IntType type) -> mlir::Type {
101+ // LLVM doesn't work with signed types, so we drop the CIR signs here.
102+ return mlir::IntegerType::get (type.getContext (), type.getWidth ());
103+ });
104+ }
105+
106+ void ConvertCIRToLLVMPass::runOnOperation () {
107+ llvm::TimeTraceScope scope (" Convert CIR to LLVM Pass" );
108+
109+ mlir::ModuleOp module = getOperation ();
110+ mlir::DataLayout dl (module );
111+ mlir::LLVMTypeConverter converter (&getContext ());
112+ prepareTypeConverter (converter, dl); // , lowerModule.get());
113+
114+ mlir::RewritePatternSet patterns (&getContext ());
115+
116+ patterns.add <CIRToLLVMGlobalOpLowering>(converter, patterns.getContext (), dl);
117+
118+ mlir::ConversionTarget target (getContext ());
119+ target.addLegalOp <mlir::ModuleOp>();
120+ target.addLegalDialect <mlir::LLVM::LLVMDialect>();
121+ target.addIllegalDialect <mlir::BuiltinDialect, cir::CIRDialect,
122+ mlir::func::FuncDialect>();
123+
124+ if (failed (applyPartialConversion (module , target, std::move (patterns))))
125+ signalPassFailure ();
126+ }
127+
128+ static std::unique_ptr<mlir::Pass> createConvertCIRToLLVMPass () {
129+ return std::make_unique<ConvertCIRToLLVMPass>();
130+ }
131+
132+ static void populateCIRToLLVMPasses (mlir::OpPassManager &pm) {
133+ pm.addPass (createConvertCIRToLLVMPass ());
134+ }
135+
25136std::unique_ptr<llvm::Module>
26137lowerDirectlyFromCIRToLLVMIR (mlir::ModuleOp mlirModule, LLVMContext &llvmCtx) {
27138 llvm::TimeTraceScope scope (" lower from CIR to LLVM directly" );
28139
140+ mlir::MLIRContext *mlirCtx = mlirModule.getContext ();
141+
142+ mlir::PassManager pm (mlirCtx);
143+ populateCIRToLLVMPasses (pm);
144+
145+ bool result = !mlir::failed (pm.run (mlirModule));
146+ if (!result)
147+ report_fatal_error (
148+ " The pass manager failed to lower CIR to LLVMIR dialect!" );
149+
150+ mlir::registerBuiltinDialectTranslation (*mlirCtx);
151+ mlir::registerLLVMDialectTranslation (*mlirCtx);
152+
153+ llvm::TimeTraceScope translateScope (" translateModuleToLLVMIR" );
154+
29155 std::optional<StringRef> moduleName = mlirModule.getName ();
30- auto llvmModule = std::make_unique <llvm::Module>(
31- moduleName ? *moduleName : " CIRToLLVMModule" , llvmCtx );
156+ std::unique_ptr <llvm::Module> llvmModule = mlir::translateModuleToLLVMIR (
157+ mlirModule, llvmCtx, moduleName ? *moduleName : " CIRToLLVMModule" );
32158
33159 if (!llvmModule)
34160 report_fatal_error (" Lowering from LLVMIR dialect to llvm IR failed!" );
0 commit comments