24 #include "llvm/Bitcode/BitcodeWriter.h"
25 #include "llvm/IR/LegacyPassManager.h"
26 #include "llvm/IRReader/IRReader.h"
27 #include "llvm/Linker/Linker.h"
28 #include "llvm/MC/TargetRegistry.h"
29 #include "llvm/Support/FileSystem.h"
30 #include "llvm/Support/MemoryBuffer.h"
31 #include "llvm/Support/Path.h"
32 #include "llvm/Support/SourceMgr.h"
33 #include "llvm/Support/raw_ostream.h"
34 #include "llvm/Target/TargetMachine.h"
35 #include "llvm/Transforms/IPO/Internalize.h"
41 Operation &module, StringRef triple, StringRef chip, StringRef features,
42 int optLevel,
function_ref<
void(llvm::Module &)> initialLlvmIRCallback,
44 function_ref<
void(llvm::Module &)> optimizedLlvmIRCallback,
46 : module(module), triple(triple), chip(chip), features(features),
47 optLevel(optLevel), initialLlvmIRCallback(initialLlvmIRCallback),
48 linkedLlvmIRCallback(linkedLlvmIRCallback),
49 optimizedLlvmIRCallback(optimizedLlvmIRCallback),
50 isaCallback(isaCallback) {}
56 std::optional<llvm::TargetMachine *>
59 return targetMachine.get();
62 const llvm::Target *target =
63 llvm::TargetRegistry::lookupTarget(
triple, error);
66 <<
"Failed to lookup target for triple '" <<
triple <<
"' " << error;
75 return targetMachine.get();
78 std::unique_ptr<llvm::Module>
80 llvm::SMDiagnostic error;
81 std::unique_ptr<llvm::Module> library =
82 llvm::getLazyIRFileModule(path, error, context);
85 <<
", error: " << error.getMessage();
96 SmallVector<std::unique_ptr<llvm::Module>> &llvmModules,
97 bool failureOnError) {
98 for (
Attribute linkLib : librariesToLink) {
102 if (
auto filePath = dyn_cast<StringAttr>(linkLib)) {
104 if (!llvm::sys::fs::is_regular_file(filePath.strref())) {
106 <<
"File path: " << filePath <<
" does not exist or is not a file.";
111 llvmModules.push_back(std::move(bcFile));
112 else if (failureOnError)
116 if (
auto blobAttr = dyn_cast<BlobAttr>(linkLib)) {
118 llvm::SMDiagnostic error;
120 std::unique_ptr<llvm::MemoryBuffer> buffer =
121 llvm::MemoryBuffer::getMemBuffer(StringRef(data.data(), data.size()),
124 std::unique_ptr<llvm::Module> mod =
125 getLazyIRModule(std::move(buffer), error, context);
129 llvmModules.push_back(std::move(mod));
130 }
else if (failureOnError) {
132 <<
"Couldn't load LLVM library for linking: " << error.getMessage();
137 if (failureOnError) {
139 <<
"Unknown attribute describing LLVM library to load: " << linkLib;
146 std::unique_ptr<llvm::Module>
153 SmallVector<std::unique_ptr<llvm::Module>> &&libs) {
156 llvm::Linker linker(
module);
157 for (std::unique_ptr<llvm::Module> &libModule : libs) {
164 bool err = linker.linkInModule(
165 std::move(libModule), llvm::Linker::Flags::LinkOnlyNeeded,
167 llvm::internalizeModule(m, [&gvs](
const llvm::GlobalValue &gv) {
168 return !gv.hasName() || (gvs.count(gv.getName()) == 0);
184 if (optLevel < 0 || optLevel > 3)
186 <<
"Invalid optimization level: " <<
optLevel <<
".";
188 std::optional<llvm::TargetMachine *> targetMachine =
192 <<
"Target Machine unavailable for triple " <<
triple
193 <<
", can't optimize with LLVM\n";
194 (*targetMachine)->setOptLevel(
static_cast<llvm::CodeGenOptLevel
>(
optLevel));
198 auto error = transformer(&
module);
201 llvm::handleAllErrors(
202 std::move(error), [&mlirError](
const llvm::ErrorInfoBase &ei) {
203 mlirError <<
"Could not optimize LLVM IR: " << ei.message() <<
"\n";
210 std::optional<std::string>
212 llvm::TargetMachine &targetMachine) {
213 std::string targetISA;
214 llvm::raw_string_ostream stream(targetISA);
217 llvm::buffer_ostream pstream(stream);
218 llvm::legacy::PassManager codegenPasses;
220 if (targetMachine.addPassesToEmitFile(codegenPasses, pstream,
nullptr,
221 llvm::CodeGenFileType::AssemblyFile))
224 codegenPasses.run(llvmModule);
231 std::optional<llvm::TargetMachine *> targetMachine =
235 module.setDataLayout((*targetMachine)->createDataLayout());
236 module.setTargetTriple((*targetMachine)->getTargetTriple().getTriple());
240 std::optional<SmallVector<char, 0>>
244 llvm::raw_svector_ostream outputStream(binaryData);
245 llvm::WriteBitcodeToFile(llvmModule, outputStream);
251 llvm::LLVMContext llvmContext;
269 if (failed(
linkFiles(*llvmModule, std::move(*libs))))
Attributes are known-constant values of operations.
This class represents a diagnostic that is inflight and set to be reported.
StringRef features
Target features.
std::unique_ptr< llvm::Module > translateToLLVMIR(llvm::LLVMContext &llvmContext)
Translates the operation to LLVM IR.
virtual std::optional< SmallVector< char, 0 > > run()
Runs the serialization pipeline, returning std::nullopt on error.
static std::optional< std::string > translateToISA(llvm::Module &llvmModule, llvm::TargetMachine &targetMachine)
Utility function for translating to ISA, returns std::nullopt on failure.
LogicalResult loadBitcodeFilesFromList(llvm::LLVMContext &context, ArrayRef< Attribute > librariesToLink, SmallVector< std::unique_ptr< llvm::Module >> &llvmModules, bool failureOnError=true)
Loads multiple bitcode files.
function_ref< void(llvm::Module &)> initialLlvmIRCallback
Callback invoked with the initial LLVM IR for the device module.
function_ref< void(llvm::Module &)> optimizedLlvmIRCallback
Callback invoked with LLVM IR for the device module after LLVM optimizations but before codegen.
virtual std::optional< SmallVector< char, 0 > > moduleToObject(llvm::Module &llvmModule)
Serializes the LLVM IR bitcode to an object file, by default it serializes to LLVM bitcode.
virtual void setDataLayoutAndTriple(llvm::Module &module)
Hook for computing the Datalayout.
virtual void handleModulePreLink(llvm::Module &module)
Hook for performing additional actions on the llvmModule pre linking.
StringRef triple
Target triple.
int optLevel
Optimization level.
virtual LogicalResult handleBitcodeFile(llvm::Module &module)
Hook for performing additional actions on a loaded bitcode file.
std::optional< llvm::TargetMachine * > getOrCreateTargetMachine()
Create the target machine based on the target triple and chip.
Operation & getOperation()
Returns the operation being serialized.
virtual LogicalResult optimizeModule(llvm::Module &module, int optL)
Optimize the module.
LogicalResult linkFiles(llvm::Module &module, SmallVector< std::unique_ptr< llvm::Module >> &&libs)
Link the llvmModule to other bitcode file.
virtual ~ModuleToObject()
function_ref< void(llvm::Module &)> linkedLlvmIRCallback
Callback invoked with LLVM IR for the device module after linking the device libraries.
StringRef chip
Target chip.
std::unique_ptr< llvm::Module > loadBitcodeFile(llvm::LLVMContext &context, StringRef path)
Loads a bitcode file from path.
virtual std::optional< SmallVector< std::unique_ptr< llvm::Module > > > loadBitcodeFiles(llvm::Module &module)
Hook for loading bitcode files, returns std::nullopt on failure.
virtual void handleModulePostLink(llvm::Module &module)
Hook for performing additional actions on the llvmModule post linking.
ModuleToObject(Operation &module, StringRef triple, StringRef chip, StringRef features={}, int optLevel=3, function_ref< void(llvm::Module &)> initialLlvmIRCallback={}, function_ref< void(llvm::Module &)> linkedLlvmIRCallback={}, function_ref< void(llvm::Module &)> optimizedLlvmIRCallback={}, function_ref< void(StringRef)> isaCallback={})
Operation & module
Module to transform to a binary object.
Operation is the basic unit of execution within MLIR.
InFlightDiagnostic emitError(const Twine &message={})
Emit an error about fatal conditions with this operation, reporting up to any diagnostic handlers tha...
Include the generated interface declarations.
std::unique_ptr< llvm::Module > translateModuleToLLVMIR(Operation *module, llvm::LLVMContext &llvmContext, llvm::StringRef name="LLVMDialectModule", bool disableVerification=false)
Translates a given LLVM dialect module into an LLVM IR module living in the given context.
std::function< llvm::Error(llvm::Module *)> makeOptimizingTransformer(unsigned optLevel, unsigned sizeLevel, llvm::TargetMachine *targetMachine)
Create a module transformer function for MLIR ExecutionEngine that runs LLVM IR passes corresponding ...