================ @@ -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(); ---------------- andykaylor wrote:
I'm not sure of the size. I think it's pretty small, mostly a wrapper around a pointer that contains the actual data. Handling it by value like this appears to be common behavior (for instance, in flang). 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