#include "mlir/Pass/Pass.h"
#include "mlir/Pass/PassManager.h"
#include "mlir/Target/LLVMIR.h"
+#include "mlir/Target/LLVMIR/Export.h"
#include "mlir/Transforms/Passes.h"
#include "llvm/ADT/StringRef.h"
#include "mlir/Pass/Pass.h"
#include "mlir/Pass/PassManager.h"
#include "mlir/Target/LLVMIR.h"
+#include "mlir/Target/LLVMIR/Export.h"
#include "mlir/Transforms/Passes.h"
#include "llvm/ADT/StringRef.h"
// Forward-declare LLVM classes.
namespace llvm {
-class LLVMContext;
class Module;
} // namespace llvm
class DialectRegistry;
class OwningModuleRef;
class MLIRContext;
-class Operation;
-
-/// Convert the given MLIR module into LLVM IR. The LLVM context is extracted
-/// from the registered LLVM IR dialect. In case of error, report it
-/// to the error handler registered with the MLIR context, if any (obtained from
-/// the MLIR module), and return `nullptr`.
-std::unique_ptr<llvm::Module>
-translateModuleToLLVMIR(Operation *op, llvm::LLVMContext &llvmContext,
- StringRef name = "LLVMDialectModule");
/// Convert the given LLVM module into MLIR's LLVM dialect. The LLVM context is
/// extracted from the registered LLVM IR dialect. In case of error, report it
--- /dev/null
+//===- Export.h - MLIR to LLVM IR translation entry point -------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MLIR_TARGET_LLVMIR_EXPORT_H
+#define MLIR_TARGET_LLVMIR_EXPORT_H
+
+#include "llvm/ADT/StringRef.h"
+#include <memory>
+
+namespace llvm {
+class LLVMContext;
+class Module;
+} // namespace llvm
+
+namespace mlir {
+class Operation;
+
+/// Translate operation that satisfies LLVM dialect module requirements into an
+/// LLVM IR module living in the given context. This translates operations from
+/// any dilalect that has a registered implementation of
+/// LLVMTranslationDialectInterface.
+std::unique_ptr<llvm::Module>
+translateModuleToLLVMIR(Operation *module, llvm::LLVMContext &llvmContext,
+ llvm::StringRef name = "LLVMDialectModule");
+} // namespace mlir
+
+#endif // MLIR_TARGET_LLVMIR_EXPORT_H
#ifndef MLIR_TARGET_LLVMIR_MODULETRANSLATION_H
#define MLIR_TARGET_LLVMIR_MODULETRANSLATION_H
-#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
-#include "mlir/Dialect/LLVMIR/Transforms/LegalizeForExport.h"
-#include "mlir/IR/Block.h"
-#include "mlir/IR/BuiltinOps.h"
+#include "mlir/IR/Operation.h"
#include "mlir/IR/Value.h"
+#include "mlir/Target/LLVMIR/Export.h"
#include "mlir/Target/LLVMIR/LLVMTranslationInterface.h"
#include "mlir/Target/LLVMIR/TypeTranslation.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/Frontend/OpenMP/OMPIRBuilder.h"
-#include "llvm/IR/BasicBlock.h"
-#include "llvm/IR/Function.h"
-#include "llvm/IR/IRBuilder.h"
-#include "llvm/IR/MatrixBuilder.h"
-#include "llvm/IR/Value.h"
+
+namespace llvm {
+class BasicBlock;
+class IRBuilderBase;
+class Function;
+class Value;
+} // namespace llvm
namespace mlir {
class Attribute;
+class Block;
class Location;
-class ModuleOp;
-class Operation;
namespace LLVM {
/// mappings in one class since the conversion of control flow operations
/// needs to look up block and function mappings.
class ModuleTranslation {
-public:
- template <typename T = ModuleTranslation>
- static std::unique_ptr<llvm::Module>
- translateModule(Operation *m, llvm::LLVMContext &llvmContext,
- StringRef name = "LLVMDialectModule") {
- if (!satisfiesLLVMModule(m))
- return nullptr;
- if (failed(checkSupportedModuleOps(m)))
- return nullptr;
- std::unique_ptr<llvm::Module> llvmModule =
- prepareLLVMModule(m, llvmContext, name);
-
- LLVM::ensureDistinctSuccessors(m);
-
- T translator(m, std::move(llvmModule));
- if (failed(translator.convertFunctionSignatures()))
- return nullptr;
- if (failed(translator.convertGlobals()))
- return nullptr;
- if (failed(translator.convertFunctions()))
- return nullptr;
-
- return std::move(translator.llvmModule);
- }
-
- /// A helper method to get the single Block in an operation honoring LLVM's
- /// module requirements.
- static Block &getModuleBody(Operation *m) { return m->getRegion(0).front(); }
+ friend std::unique_ptr<llvm::Module>
+ mlir::translateModuleToLLVMIR(Operation *, llvm::LLVMContext &, StringRef);
+public:
/// Stores the mapping between a function name and its LLVM IR representation.
void mapFunction(StringRef name, llvm::Function *func) {
auto result = functionMapping.try_emplace(name, func);
/// PHI nodes are constructed for block arguments but are _not_ connected to
/// the predecessors that may not exist yet.
LogicalResult convertBlock(Block &bb, bool ignoreArguments,
- llvm::IRBuilder<> &builder);
+ llvm::IRBuilderBase &builder);
/// Gets the named metadata in the LLVM IR module being constructed, creating
/// it if it does not exist.
llvm::NamedMDNode *getOrInsertNamedModuleMetadata(StringRef name);
-protected:
- /// Translate the given MLIR module expressed in MLIR LLVM IR dialect into an
- /// LLVM IR module. The MLIR LLVM IR dialect holds a pointer to an
- /// LLVMContext, the LLVM IR module will be created in that context.
+private:
ModuleTranslation(Operation *module,
std::unique_ptr<llvm::Module> llvmModule);
- virtual ~ModuleTranslation();
-
- virtual LogicalResult convertOperation(Operation &op,
- llvm::IRBuilder<> &builder);
-
- static std::unique_ptr<llvm::Module>
- prepareLLVMModule(Operation *m, llvm::LLVMContext &llvmContext,
- StringRef name);
-
-private:
- /// Check whether the module contains only supported ops directly in its body.
- static LogicalResult checkSupportedModuleOps(Operation *m);
+ ~ModuleTranslation();
+ /// Converts individual components.
+ LogicalResult convertOperation(Operation &op, llvm::IRBuilderBase &builder);
LogicalResult convertFunctionSignatures();
LogicalResult convertFunctions();
LogicalResult convertGlobals();
/// Builder for LLVM IR generation of OpenMP constructs.
std::unique_ptr<llvm::OpenMPIRBuilder> ompBuilder;
- /// Precomputed pointer to OpenMP dialect. Note this can be nullptr if the
- /// OpenMP dialect hasn't been loaded (it is always loaded if there are OpenMP
- /// operations in the module though).
- const Dialect *ompDialect;
-
/// Mappings between llvm.mlir.global definitions and corresponding globals.
DenseMap<Operation *, llvm::GlobalValue *> globalsMapping;
#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
#include "mlir/IR/BuiltinOps.h"
#include "mlir/Support/FileUtilities.h"
-#include "mlir/Target/LLVMIR.h"
+#include "mlir/Target/LLVMIR/Export.h"
#include "llvm/ExecutionEngine/JITEventListener.h"
#include "llvm/ExecutionEngine/ObjectCache.h"
using namespace mlir;
-std::unique_ptr<llvm::Module>
-mlir::translateModuleToLLVMIR(Operation *op, llvm::LLVMContext &llvmContext,
- StringRef name) {
- auto llvmModule =
- LLVM::ModuleTranslation::translateModule<>(op, llvmContext, name);
- if (!llvmModule)
- emitError(op->getLoc(), "Fail to convert MLIR to LLVM IR");
- else if (verifyModule(*llvmModule))
- emitError(op->getLoc(), "LLVM IR fails to verify");
- return llvmModule;
-}
-
void mlir::registerLLVMDialectTranslation(DialectRegistry ®istry) {
registry.insert<LLVM::LLVMDialect>();
registry.addDialectInterface<LLVM::LLVMDialect,
"mlir-to-llvmir",
[](ModuleOp module, raw_ostream &output) {
llvm::LLVMContext llvmContext;
- auto llvmModule = LLVM::ModuleTranslation::translateModule<>(
- module, llvmContext, "LLVMDialectModule");
+ auto llvmModule = translateModuleToLLVMIR(module, llvmContext);
if (!llvmModule)
return failure();
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/InlineAsm.h"
#include "llvm/IR/MDBuilder.h"
+#include "llvm/IR/MatrixBuilder.h"
#include "llvm/IR/Operator.h"
using namespace mlir;
sourceTerminator->setSuccessor(0, llvmBB);
}
- llvm::IRBuilder<>::InsertPointGuard guard(builder);
- if (failed(moduleTranslation.convertBlock(
- *bb, bb->isEntryBlock(),
- // TODO: this downcast should be removed after all of
- // ModuleTranslation migrated to using IRBuilderBase &; the cast is
- // safe in practice because the builder always comes from
- // ModuleTranslation itself that only uses this subclass.
- static_cast<llvm::IRBuilder<> &>(builder)))) {
+ llvm::IRBuilderBase::InsertPointGuard guard(builder);
+ if (failed(
+ moduleTranslation.convertBlock(*bb, bb->isEntryBlock(), builder))) {
bodyGenStatus = failure();
return;
}
#include "DebugTranslation.h"
#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
+#include "mlir/Dialect/LLVMIR/Transforms/LegalizeForExport.h"
#include "mlir/Dialect/OpenMP/OpenMPDialect.h"
#include "mlir/IR/Attributes.h"
#include "mlir/IR/BuiltinOps.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/MDBuilder.h"
#include "llvm/IR/Module.h"
+#include "llvm/IR/Verifier.h"
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
#include "llvm/Transforms/Utils/Cloning.h"
: mlirModule(module), llvmModule(std::move(llvmModule)),
debugTranslation(
std::make_unique<DebugTranslation>(module, *this->llvmModule)),
- ompDialect(module->getContext()->getLoadedDialect("omp")),
typeTranslator(this->llvmModule->getContext()),
iface(module->getContext()) {
assert(satisfiesLLVMModule(mlirModule) &&
/// Given a single MLIR operation, create the corresponding LLVM IR operation
/// using the `builder`.
-LogicalResult ModuleTranslation::convertOperation(Operation &opInst,
- llvm::IRBuilder<> &builder) {
+LogicalResult
+ModuleTranslation::convertOperation(Operation &opInst,
+ llvm::IRBuilderBase &builder) {
if (failed(iface.convertOperation(&opInst, builder, *this)))
return opInst.emitError("unsupported or non-LLVM operation: ")
<< opInst.getName();
/// instructions at the end of the block and leaves `builder` in a state
/// suitable for further insertion into the end of the block.
LogicalResult ModuleTranslation::convertBlock(Block &bb, bool ignoreArguments,
- llvm::IRBuilder<> &builder) {
+ llvm::IRBuilderBase &builder) {
builder.SetInsertPoint(lookupBlock(&bb));
auto *subprogram = builder.GetInsertBlock()->getParent()->getSubprogram();
return success();
}
+/// A helper method to get the single Block in an operation honoring LLVM's
+/// module requirements.
+static Block &getModuleBody(Operation *module) {
+ return module->getRegion(0).front();
+}
+
/// Create named global variables that correspond to llvm.mlir.global
/// definitions.
LogicalResult ModuleTranslation::convertGlobals() {
return success();
}
-LogicalResult ModuleTranslation::checkSupportedModuleOps(Operation *m) {
+/// Check whether the module contains only supported ops directly in its body.
+static LogicalResult checkSupportedModuleOps(Operation *m) {
for (Operation &o : getModuleBody(m).getOperations())
if (!isa<LLVM::LLVMFuncOp, LLVM::GlobalOp>(&o) &&
!o.hasTrait<OpTrait::IsTerminator>())
return llvmModule->getOrInsertNamedMetadata(name);
}
-std::unique_ptr<llvm::Module> ModuleTranslation::prepareLLVMModule(
- Operation *m, llvm::LLVMContext &llvmContext, StringRef name) {
+static std::unique_ptr<llvm::Module>
+prepareLLVMModule(Operation *m, llvm::LLVMContext &llvmContext,
+ StringRef name) {
m->getContext()->getOrLoadDialect<LLVM::LLVMDialect>();
auto llvmModule = std::make_unique<llvm::Module>(name, llvmContext);
if (auto dataLayoutAttr =
return llvmModule;
}
+
+std::unique_ptr<llvm::Module>
+mlir::translateModuleToLLVMIR(Operation *module, llvm::LLVMContext &llvmContext,
+ StringRef name) {
+ if (!satisfiesLLVMModule(module))
+ return nullptr;
+ if (failed(checkSupportedModuleOps(module)))
+ return nullptr;
+ std::unique_ptr<llvm::Module> llvmModule =
+ prepareLLVMModule(module, llvmContext, name);
+
+ LLVM::ensureDistinctSuccessors(module);
+
+ ModuleTranslation translator(module, std::move(llvmModule));
+ if (failed(translator.convertFunctionSignatures()))
+ return nullptr;
+ if (failed(translator.convertGlobals()))
+ return nullptr;
+ if (failed(translator.convertFunctions()))
+ return nullptr;
+ if (llvm::verifyModule(*translator.llvmModule, &llvm::errs()))
+ return nullptr;
+
+ return std::move(translator.llvmModule);
+}
#include "mlir/Pass/PassManager.h"
#include "mlir/Target/LLVMIR.h"
#include "mlir/Target/LLVMIR/Dialect/NVVM/NVVMToLLVMIRTranslation.h"
+#include "mlir/Target/LLVMIR/Export.h"
#include "llvm/Support/TargetSelect.h"
using namespace mlir;
#include "mlir/Pass/PassManager.h"
#include "mlir/Target/LLVMIR.h"
#include "mlir/Target/LLVMIR/Dialect/ROCDL/ROCDLToLLVMIRTranslation.h"
+#include "mlir/Target/LLVMIR/Export.h"
#include "llvm/Support/TargetSelect.h"
using namespace mlir;
#include "mlir/Pass/PassManager.h"
#include "mlir/Target/LLVMIR.h"
#include "mlir/Target/LLVMIR/Dialect/NVVM/NVVMToLLVMIRTranslation.h"
+#include "mlir/Target/LLVMIR/Export.h"
#include "mlir/Transforms/DialectConversion.h"
#include "mlir/Transforms/Passes.h"
#include "mlir/Support/FileUtilities.h"
#include "mlir/Target/LLVMIR.h"
#include "mlir/Target/LLVMIR/Dialect/ROCDL/ROCDLToLLVMIRTranslation.h"
-#include "mlir/Target/ROCDLIR.h"
+#include "mlir/Target/LLVMIR/Export.h"
#include "mlir/Transforms/DialectConversion.h"
#include "mlir/Transforms/Passes.h"
#include "llvm/Support/ErrorOr.h"
#include "mlir/Pass/Pass.h"
#include "mlir/Pass/PassManager.h"
#include "mlir/Target/LLVMIR.h"
+#include "mlir/Target/LLVMIR/Export.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"