diff --git a/mlir/include/mlir/Conversion/FuncToLLVM/ConvertFuncToLLVMPass.h b/mlir/include/mlir/Conversion/FuncToLLVM/ConvertFuncToLLVMPass.h --- a/mlir/include/mlir/Conversion/FuncToLLVM/ConvertFuncToLLVMPass.h +++ b/mlir/include/mlir/Conversion/FuncToLLVM/ConvertFuncToLLVMPass.h @@ -16,6 +16,7 @@ class Pass; #define GEN_PASS_DECL_CONVERTFUNCTOLLVMPASS +#define GEN_PASS_DECL_SETLLVMMODULEDATALAYOUTPASS #include "mlir/Conversion/Passes.h.inc" } // namespace mlir diff --git a/mlir/include/mlir/Conversion/Passes.td b/mlir/include/mlir/Conversion/Passes.td --- a/mlir/include/mlir/Conversion/Passes.td +++ b/mlir/include/mlir/Conversion/Passes.td @@ -341,6 +341,21 @@ // FuncToLLVM //===----------------------------------------------------------------------===// +def SetLLVMModuleDataLayoutPass : Pass<"set-llvm-module-datalayout", "ModuleOp"> { + let summary = "Attach a datalayout string as a module attribute"; + let description = [{ + Verify that the dataLayout string is a valid LLVM datalayout string and + attach it as an attribute `LLVMDialect::getDataLayoutAttrName()` to the + module, overriding the existing one. + }]; + let options = [ + Option<"dataLayout", "data-layout", "std::string", + /*default=*/"\"\"", + "String description (LLVM format) of the data layout that is " + "expected on the produced module">, + ]; +} + def ConvertFuncToLLVMPass : Pass<"convert-func-to-llvm", "ModuleOp"> { let summary = "Convert from the Func dialect to the LLVM dialect"; let description = [{ @@ -357,6 +372,11 @@ IR dialect operations, the pass will fail. Any LLVM IR operations or types already present in the IR will be kept as is. + An LLVM datalayout string can be attached as an attribute to the module on + which the pass anchors. Such an attribute is attached by calling the + set-module-datalayout pass. If present, an llvm::DataLayout object is + created from this attribute and used in the conversion to LLVM. + #### Output IR Functions converted to LLVM IR. Function arguments types are converted @@ -374,10 +394,6 @@ Option<"indexBitwidth", "index-bitwidth", "unsigned", /*default=kDeriveIndexBitwidthFromDataLayout*/"0", "Bitwidth of the index type, 0 to use size of machine word">, - Option<"dataLayout", "data-layout", "std::string", - /*default=*/"\"\"", - "String description (LLVM format) of the data layout that is " - "expected on the produced module">, Option<"useOpaquePointers", "use-opaque-pointers", "bool", /*default=*/"true", "Generate LLVM IR using opaque pointers " "instead of typed pointers">, diff --git a/mlir/lib/Conversion/FuncToLLVM/FuncToLLVM.cpp b/mlir/lib/Conversion/FuncToLLVM/FuncToLLVM.cpp --- a/mlir/lib/Conversion/FuncToLLVM/FuncToLLVM.cpp +++ b/mlir/lib/Conversion/FuncToLLVM/FuncToLLVM.cpp @@ -43,6 +43,7 @@ #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/Type.h" +#include "llvm/Support/Casting.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/FormatVariadic.h" #include @@ -50,6 +51,7 @@ namespace mlir { #define GEN_PASS_DEF_CONVERTFUNCTOLLVMPASS +#define GEN_PASS_DEF_SETLLVMMODULEDATALAYOUTPASS #include "mlir/Conversion/Passes.h.inc" } // namespace mlir @@ -746,15 +748,21 @@ /// Run the dialect converter on the module. void runOnOperation() override { + ModuleOp m = getOperation(); + StringRef dataLayout; + auto dataLayoutAttr = dyn_cast_or_null( + m->getAttr(LLVM::LLVMDialect::getDataLayoutAttrName())); + if (dataLayoutAttr) + dataLayout = dataLayoutAttr.getValue(); + if (failed(LLVM::LLVMDialect::verifyDataLayoutString( - this->dataLayout, [this](const Twine &message) { + dataLayout, [this](const Twine &message) { getOperation().emitError() << message.str(); }))) { signalPassFailure(); return; } - ModuleOp m = getOperation(); const auto &dataLayoutAnalysis = getAnalysis(); LowerToLLVMOptions options(&getContext(), @@ -762,7 +770,7 @@ options.useBarePtrCallConv = useBarePtrCallConv; if (indexBitwidth != kDeriveIndexBitwidthFromDataLayout) options.overrideIndexBitwidth(indexBitwidth); - options.dataLayout = llvm::DataLayout(this->dataLayout); + options.dataLayout = llvm::DataLayout(dataLayout); options.useOpaquePointers = useOpaquePointers; LLVMTypeConverter typeConverter(&getContext(), options, @@ -778,7 +786,24 @@ LLVMConversionTarget target(getContext()); if (failed(applyPartialConversion(m, target, std::move(patterns)))) signalPassFailure(); + } +}; + +struct SetLLVMModuleDataLayoutPass + : public impl::SetLLVMModuleDataLayoutPassBase< + SetLLVMModuleDataLayoutPass> { + using Base::Base; + /// Run the dialect converter on the module. + void runOnOperation() override { + if (failed(LLVM::LLVMDialect::verifyDataLayoutString( + this->dataLayout, [this](const Twine &message) { + getOperation().emitError() << message.str(); + }))) { + signalPassFailure(); + return; + } + ModuleOp m = getOperation(); m->setAttr(LLVM::LLVMDialect::getDataLayoutAttrName(), StringAttr::get(m.getContext(), this->dataLayout)); } diff --git a/mlir/test/Conversion/FuncToLLVM/convert-data-layout.mlir b/mlir/test/Conversion/FuncToLLVM/convert-data-layout.mlir --- a/mlir/test/Conversion/FuncToLLVM/convert-data-layout.mlir +++ b/mlir/test/Conversion/FuncToLLVM/convert-data-layout.mlir @@ -1,5 +1,7 @@ -// RUN: mlir-opt -convert-func-to-llvm='use-opaque-pointers=1' %s | FileCheck %s -// RUN-32: mlir-opt -convert-func-to-llvm='data-layout=p:32:32:32 use-opaque-pointers=1' %s | FileCheck %s +// RUN: mlir-opt -set-llvm-module-datalayout -convert-func-to-llvm='use-opaque-pointers=1' %s | FileCheck %s + +// RUN-32: mlir-opt -set-llvm-module-datalayout='data-layout=p:32:32:32' -convert-func-to-llvm='use-opaque-pointers=1' %s \ +// RUN-32: | FileCheck %s // CHECK: module attributes {llvm.data_layout = ""} // CHECK-32: module attributes {llvm.data_layout ="p:32:32:32"}