[rtsan] Remove mkfifoat interceptor (#116997)
[llvm-project.git] / mlir / lib / Target / LLVM / ModuleToObject.cpp
blob3f5b3d5e31864b4b41ff7799a501cf01de228263
1 //===- ModuleToObject.cpp - Module to object base class ---------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file implements the base class for transforming Operations into binary
10 // objects.
12 //===----------------------------------------------------------------------===//
14 #include "mlir/Target/LLVM/ModuleToObject.h"
16 #include "mlir/ExecutionEngine/OptUtils.h"
17 #include "mlir/IR/BuiltinOps.h"
18 #include "mlir/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.h"
19 #include "mlir/Target/LLVMIR/Export.h"
20 #include "mlir/Target/LLVMIR/ModuleTranslation.h"
22 #include "llvm/Bitcode/BitcodeWriter.h"
23 #include "llvm/IR/LegacyPassManager.h"
24 #include "llvm/IRReader/IRReader.h"
25 #include "llvm/Linker/Linker.h"
26 #include "llvm/MC/TargetRegistry.h"
27 #include "llvm/Support/FileSystem.h"
28 #include "llvm/Support/Path.h"
29 #include "llvm/Support/SourceMgr.h"
30 #include "llvm/Support/raw_ostream.h"
31 #include "llvm/Target/TargetMachine.h"
32 #include "llvm/Transforms/IPO/Internalize.h"
34 using namespace mlir;
35 using namespace mlir::LLVM;
37 ModuleToObject::ModuleToObject(
38 Operation &module, StringRef triple, StringRef chip, StringRef features,
39 int optLevel, function_ref<void(llvm::Module &)> initialLlvmIRCallback,
40 function_ref<void(llvm::Module &)> linkedLlvmIRCallback,
41 function_ref<void(llvm::Module &)> optimizedLlvmIRCallback,
42 function_ref<void(StringRef)> isaCallback)
43 : module(module), triple(triple), chip(chip), features(features),
44 optLevel(optLevel), initialLlvmIRCallback(initialLlvmIRCallback),
45 linkedLlvmIRCallback(linkedLlvmIRCallback),
46 optimizedLlvmIRCallback(optimizedLlvmIRCallback),
47 isaCallback(isaCallback) {}
49 ModuleToObject::~ModuleToObject() = default;
51 Operation &ModuleToObject::getOperation() { return module; }
53 std::optional<llvm::TargetMachine *>
54 ModuleToObject::getOrCreateTargetMachine() {
55 if (targetMachine)
56 return targetMachine.get();
57 // Load the target.
58 std::string error;
59 const llvm::Target *target =
60 llvm::TargetRegistry::lookupTarget(triple, error);
61 if (!target) {
62 getOperation().emitError()
63 << "Failed to lookup target for triple '" << triple << "' " << error;
64 return std::nullopt;
67 // Create the target machine using the target.
68 targetMachine.reset(
69 target->createTargetMachine(triple, chip, features, {}, {}));
70 if (!targetMachine)
71 return std::nullopt;
72 return targetMachine.get();
75 std::unique_ptr<llvm::Module>
76 ModuleToObject::loadBitcodeFile(llvm::LLVMContext &context, StringRef path) {
77 llvm::SMDiagnostic error;
78 std::unique_ptr<llvm::Module> library =
79 llvm::getLazyIRFileModule(path, error, context);
80 if (!library) {
81 getOperation().emitError() << "Failed loading file from " << path
82 << ", error: " << error.getMessage();
83 return nullptr;
85 if (failed(handleBitcodeFile(*library))) {
86 return nullptr;
88 return library;
91 LogicalResult ModuleToObject::loadBitcodeFilesFromList(
92 llvm::LLVMContext &context, ArrayRef<std::string> fileList,
93 SmallVector<std::unique_ptr<llvm::Module>> &llvmModules,
94 bool failureOnError) {
95 for (const std::string &str : fileList) {
96 // Test if the path exists, if it doesn't abort.
97 StringRef pathRef = StringRef(str.data(), str.size());
98 if (!llvm::sys::fs::is_regular_file(pathRef)) {
99 getOperation().emitError()
100 << "File path: " << pathRef << " does not exist or is not a file.\n";
101 return failure();
103 // Load the file or abort on error.
104 if (auto bcFile = loadBitcodeFile(context, pathRef))
105 llvmModules.push_back(std::move(bcFile));
106 else if (failureOnError)
107 return failure();
109 return success();
112 std::unique_ptr<llvm::Module>
113 ModuleToObject::translateToLLVMIR(llvm::LLVMContext &llvmContext) {
114 return translateModuleToLLVMIR(&getOperation(), llvmContext);
117 LogicalResult
118 ModuleToObject::linkFiles(llvm::Module &module,
119 SmallVector<std::unique_ptr<llvm::Module>> &&libs) {
120 if (libs.empty())
121 return success();
122 llvm::Linker linker(module);
123 for (std::unique_ptr<llvm::Module> &libModule : libs) {
124 // This bitcode linking imports the library functions into the module,
125 // allowing LLVM optimization passes (which must run after linking) to
126 // optimize across the libraries and the module's code. We also only import
127 // symbols if they are referenced by the module or a previous library since
128 // there will be no other source of references to those symbols in this
129 // compilation and since we don't want to bloat the resulting code object.
130 bool err = linker.linkInModule(
131 std::move(libModule), llvm::Linker::Flags::LinkOnlyNeeded,
132 [](llvm::Module &m, const StringSet<> &gvs) {
133 llvm::internalizeModule(m, [&gvs](const llvm::GlobalValue &gv) {
134 return !gv.hasName() || (gvs.count(gv.getName()) == 0);
137 // True is linker failure
138 if (err) {
139 getOperation().emitError("Unrecoverable failure during bitcode linking.");
140 // We have no guaranties about the state of `ret`, so bail
141 return failure();
144 return success();
147 LogicalResult ModuleToObject::optimizeModule(llvm::Module &module,
149 int optLevel) {
150 if (optLevel < 0 || optLevel > 3)
151 return getOperation().emitError()
152 << "Invalid optimization level: " << optLevel << ".";
154 std::optional<llvm::TargetMachine *> targetMachine =
155 getOrCreateTargetMachine();
156 if (!targetMachine)
157 return getOperation().emitError()
158 << "Target Machine unavailable for triple " << triple
159 << ", can't optimize with LLVM\n";
160 (*targetMachine)->setOptLevel(static_cast<llvm::CodeGenOptLevel>(optLevel));
162 auto transformer =
163 makeOptimizingTransformer(optLevel, /*sizeLevel=*/0, *targetMachine);
164 auto error = transformer(&module);
165 if (error) {
166 InFlightDiagnostic mlirError = getOperation().emitError();
167 llvm::handleAllErrors(
168 std::move(error), [&mlirError](const llvm::ErrorInfoBase &ei) {
169 mlirError << "Could not optimize LLVM IR: " << ei.message() << "\n";
171 return mlirError;
173 return success();
176 std::optional<std::string>
177 ModuleToObject::translateToISA(llvm::Module &llvmModule,
178 llvm::TargetMachine &targetMachine) {
179 std::string targetISA;
180 llvm::raw_string_ostream stream(targetISA);
182 { // Drop pstream after this to prevent the ISA from being stuck buffering
183 llvm::buffer_ostream pstream(stream);
184 llvm::legacy::PassManager codegenPasses;
186 if (targetMachine.addPassesToEmitFile(codegenPasses, pstream, nullptr,
187 llvm::CodeGenFileType::AssemblyFile))
188 return std::nullopt;
190 codegenPasses.run(llvmModule);
192 return targetISA;
195 void ModuleToObject::setDataLayoutAndTriple(llvm::Module &module) {
196 // Create the target machine.
197 std::optional<llvm::TargetMachine *> targetMachine =
198 getOrCreateTargetMachine();
199 if (targetMachine) {
200 // Set the data layout and target triple of the module.
201 module.setDataLayout((*targetMachine)->createDataLayout());
202 module.setTargetTriple((*targetMachine)->getTargetTriple().getTriple());
206 std::optional<SmallVector<char, 0>>
207 ModuleToObject::moduleToObject(llvm::Module &llvmModule) {
208 SmallVector<char, 0> binaryData;
209 // Write the LLVM module bitcode to a buffer.
210 llvm::raw_svector_ostream outputStream(binaryData);
211 llvm::WriteBitcodeToFile(llvmModule, outputStream);
212 return binaryData;
215 std::optional<SmallVector<char, 0>> ModuleToObject::run() {
216 // Translate the module to LLVM IR.
217 llvm::LLVMContext llvmContext;
218 std::unique_ptr<llvm::Module> llvmModule = translateToLLVMIR(llvmContext);
219 if (!llvmModule) {
220 getOperation().emitError() << "Failed creating the llvm::Module.";
221 return std::nullopt;
223 setDataLayoutAndTriple(*llvmModule);
225 if (initialLlvmIRCallback)
226 initialLlvmIRCallback(*llvmModule);
228 // Link bitcode files.
229 handleModulePreLink(*llvmModule);
231 auto libs = loadBitcodeFiles(*llvmModule);
232 if (!libs)
233 return std::nullopt;
234 if (!libs->empty())
235 if (failed(linkFiles(*llvmModule, std::move(*libs))))
236 return std::nullopt;
237 handleModulePostLink(*llvmModule);
240 if (linkedLlvmIRCallback)
241 linkedLlvmIRCallback(*llvmModule);
243 // Optimize the module.
244 if (failed(optimizeModule(*llvmModule, optLevel)))
245 return std::nullopt;
247 if (optimizedLlvmIRCallback)
248 optimizedLlvmIRCallback(*llvmModule);
250 // Return the serialized object.
251 return moduleToObject(*llvmModule);