aboutsummaryrefslogtreecommitdiff
path: root/llvm/tools/lli/lli.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/tools/lli/lli.cpp')
-rw-r--r--llvm/tools/lli/lli.cpp255
1 files changed, 188 insertions, 67 deletions
diff --git a/llvm/tools/lli/lli.cpp b/llvm/tools/lli/lli.cpp
index bfe7e8f04303..981e0812d45e 100644
--- a/llvm/tools/lli/lli.cpp
+++ b/llvm/tools/lli/lli.cpp
@@ -16,7 +16,7 @@
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/Triple.h"
#include "llvm/Bitcode/BitcodeReader.h"
-#include "llvm/CodeGen/CommandFlags.inc"
+#include "llvm/CodeGen/CommandFlags.h"
#include "llvm/CodeGen/LinkAllCodegenComponents.h"
#include "llvm/Config/llvm-config.h"
#include "llvm/ExecutionEngine/GenericValue.h"
@@ -24,10 +24,13 @@
#include "llvm/ExecutionEngine/JITEventListener.h"
#include "llvm/ExecutionEngine/MCJIT.h"
#include "llvm/ExecutionEngine/ObjectCache.h"
+#include "llvm/ExecutionEngine/Orc/DebugUtils.h"
#include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"
#include "llvm/ExecutionEngine/Orc/JITTargetMachineBuilder.h"
#include "llvm/ExecutionEngine/Orc/LLJIT.h"
+#include "llvm/ExecutionEngine/Orc/MachOPlatform.h"
#include "llvm/ExecutionEngine/Orc/OrcRemoteTargetClient.h"
+#include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h"
#include "llvm/ExecutionEngine/OrcMCJITReplacement.h"
#include "llvm/ExecutionEngine/SectionMemoryManager.h"
#include "llvm/IR/IRBuilder.h"
@@ -67,6 +70,8 @@
using namespace llvm;
+static codegen::RegisterCodeGenFlags CGF;
+
#define DEBUG_TYPE "lli"
namespace {
@@ -115,6 +120,10 @@ namespace {
cl::desc("Specifies the JITDylib to be used for any subsequent "
"-extra-module arguments."));
+ cl::list<std::string>
+ Dylibs("dlopen", cl::desc("Dynamic libraries to load before linking"),
+ cl::ZeroOrMore);
+
// The MCJIT supports building for a target address space separate from
// the JIT compilation process. Use a forked process and a copying
// memory manager with IPC to execute using this functionality.
@@ -197,6 +206,24 @@ namespace {
cl::desc("Generate software floating point library calls"),
cl::init(false));
+ cl::opt<bool> NoProcessSymbols(
+ "no-process-syms",
+ cl::desc("Do not resolve lli process symbols in JIT'd code"),
+ cl::init(false));
+
+ enum class LLJITPlatform { DetectHost, GenericIR, MachO };
+
+ cl::opt<LLJITPlatform>
+ Platform("lljit-platform", cl::desc("Platform to use with LLJIT"),
+ cl::init(LLJITPlatform::DetectHost),
+ cl::values(clEnumValN(LLJITPlatform::DetectHost, "DetectHost",
+ "Select based on JIT target triple"),
+ clEnumValN(LLJITPlatform::GenericIR, "GenericIR",
+ "Use LLJITGenericIRPlatform"),
+ clEnumValN(LLJITPlatform::MachO, "MachO",
+ "Use LLJITMachOPlatform")),
+ cl::Hidden);
+
enum class DumpKind {
NoDump,
DumpFuncsToStdOut,
@@ -250,6 +277,7 @@ public:
SmallString<128> dir(sys::path::parent_path(CacheName));
sys::fs::create_directories(Twine(dir));
}
+
std::error_code EC;
raw_fd_ostream outfile(CacheName, EC, sys::fs::OF_None);
outfile.write(Obj.getBufferStart(), Obj.getBufferSize());
@@ -282,14 +310,16 @@ private:
size_t PrefixLength = Prefix.length();
if (ModID.substr(0, PrefixLength) != Prefix)
return false;
- std::string CacheSubdir = ModID.substr(PrefixLength);
+
+ std::string CacheSubdir = ModID.substr(PrefixLength);
#if defined(_WIN32)
- // Transform "X:\foo" => "/X\foo" for convenience.
- if (isalpha(CacheSubdir[0]) && CacheSubdir[1] == ':') {
- CacheSubdir[1] = CacheSubdir[0];
- CacheSubdir[0] = '/';
- }
+ // Transform "X:\foo" => "/X\foo" for convenience.
+ if (isalpha(CacheSubdir[0]) && CacheSubdir[1] == ':') {
+ CacheSubdir[1] = CacheSubdir[0];
+ CacheSubdir[0] = '/';
+ }
#endif
+
CacheName = CacheDir + CacheSubdir;
size_t pos = CacheName.rfind('.');
CacheName.replace(pos, CacheName.length() - pos, ".o");
@@ -350,6 +380,7 @@ static void reportError(SMDiagnostic Err, const char *ProgName) {
exit(1);
}
+Error loadDylibs();
int runOrcLazyJIT(const char *ProgName);
void disallowOrcOptions();
@@ -375,6 +406,8 @@ int main(int argc, char **argv, char * const *envp) {
if (DisableCoreFiles)
sys::Process::PreventCoreFiles();
+ ExitOnErr(loadDylibs());
+
if (UseJITKind == JITKind::OrcLazy)
return runOrcLazyJIT(argv[0]);
else
@@ -405,13 +438,13 @@ int main(int argc, char **argv, char * const *envp) {
std::string ErrorMsg;
EngineBuilder builder(std::move(Owner));
- builder.setMArch(MArch);
- builder.setMCPU(getCPUStr());
- builder.setMAttrs(getFeatureList());
- if (RelocModel.getNumOccurrences())
- builder.setRelocationModel(RelocModel);
- if (CMModel.getNumOccurrences())
- builder.setCodeModel(CMModel);
+ builder.setMArch(codegen::getMArch());
+ builder.setMCPU(codegen::getCPUStr());
+ builder.setMAttrs(codegen::getFeatureList());
+ if (auto RM = codegen::getExplicitRelocModel())
+ builder.setRelocationModel(RM.getValue());
+ if (auto CM = codegen::getExplicitCodeModel())
+ builder.setCodeModel(CM.getValue());
builder.setErrorStr(&ErrorMsg);
builder.setEngineKind(ForceInterpreter
? EngineKind::Interpreter
@@ -443,9 +476,9 @@ int main(int argc, char **argv, char * const *envp) {
builder.setOptLevel(getOptLevel());
- TargetOptions Options = InitTargetOptionsFromCodeGenFlags();
- if (FloatABIForCalls != FloatABI::Default)
- Options.FloatABIType = FloatABIForCalls;
+ TargetOptions Options = codegen::InitTargetOptionsFromCodeGenFlags();
+ if (codegen::getFloatABIForCalls() != FloatABI::Default)
+ Options.FloatABIType = codegen::getFloatABIForCalls();
builder.setTargetOptions(Options);
@@ -709,7 +742,7 @@ static std::function<void(Module &)> createDebugDumper() {
continue;
if (F.hasName()) {
- std::string Name(F.getName());
+ std::string Name(std::string(F.getName()));
printf("%s ", Name.c_str());
} else
printf("<anon> ");
@@ -738,75 +771,164 @@ static std::function<void(Module &)> createDebugDumper() {
llvm_unreachable("Unknown DumpKind");
}
+Error loadDylibs() {
+ for (const auto &Dylib : Dylibs) {
+ std::string ErrMsg;
+ if (sys::DynamicLibrary::LoadLibraryPermanently(Dylib.c_str(), &ErrMsg))
+ return make_error<StringError>(ErrMsg, inconvertibleErrorCode());
+ }
+
+ return Error::success();
+}
+
static void exitOnLazyCallThroughFailure() { exit(1); }
+Expected<orc::ThreadSafeModule>
+loadModule(StringRef Path, orc::ThreadSafeContext TSCtx) {
+ SMDiagnostic Err;
+ auto M = parseIRFile(Path, Err, *TSCtx.getContext());
+ if (!M) {
+ std::string ErrMsg;
+ {
+ raw_string_ostream ErrMsgStream(ErrMsg);
+ Err.print("lli", ErrMsgStream);
+ }
+ return make_error<StringError>(std::move(ErrMsg), inconvertibleErrorCode());
+ }
+
+ if (EnableCacheManager)
+ M->setModuleIdentifier("file:" + M->getModuleIdentifier());
+
+ return orc::ThreadSafeModule(std::move(M), std::move(TSCtx));
+}
+
int runOrcLazyJIT(const char *ProgName) {
// Start setting up the JIT environment.
// Parse the main module.
orc::ThreadSafeContext TSCtx(std::make_unique<LLVMContext>());
- SMDiagnostic Err;
- auto MainModule = parseIRFile(InputFile, Err, *TSCtx.getContext());
- if (!MainModule)
- reportError(Err, ProgName);
+ auto MainModule = ExitOnErr(loadModule(InputFile, TSCtx));
+
+ // Get TargetTriple and DataLayout from the main module if they're explicitly
+ // set.
+ Optional<Triple> TT;
+ Optional<DataLayout> DL;
+ MainModule.withModuleDo([&](Module &M) {
+ if (!M.getTargetTriple().empty())
+ TT = Triple(M.getTargetTriple());
+ if (!M.getDataLayout().isDefault())
+ DL = M.getDataLayout();
+ });
- const auto &TT = MainModule->getTargetTriple();
orc::LLLazyJITBuilder Builder;
Builder.setJITTargetMachineBuilder(
- TT.empty() ? ExitOnErr(orc::JITTargetMachineBuilder::detectHost())
- : orc::JITTargetMachineBuilder(Triple(TT)));
+ TT ? orc::JITTargetMachineBuilder(*TT)
+ : ExitOnErr(orc::JITTargetMachineBuilder::detectHost()));
- if (!MArch.empty())
- Builder.getJITTargetMachineBuilder()->getTargetTriple().setArchName(MArch);
+ TT = Builder.getJITTargetMachineBuilder()->getTargetTriple();
+ if (DL)
+ Builder.setDataLayout(DL);
+
+ if (!codegen::getMArch().empty())
+ Builder.getJITTargetMachineBuilder()->getTargetTriple().setArchName(
+ codegen::getMArch());
Builder.getJITTargetMachineBuilder()
- ->setCPU(getCPUStr())
- .addFeatures(getFeatureList())
- .setRelocationModel(RelocModel.getNumOccurrences()
- ? Optional<Reloc::Model>(RelocModel)
- : None)
- .setCodeModel(CMModel.getNumOccurrences()
- ? Optional<CodeModel::Model>(CMModel)
- : None);
+ ->setCPU(codegen::getCPUStr())
+ .addFeatures(codegen::getFeatureList())
+ .setRelocationModel(codegen::getExplicitRelocModel())
+ .setCodeModel(codegen::getExplicitCodeModel());
Builder.setLazyCompileFailureAddr(
pointerToJITTargetAddress(exitOnLazyCallThroughFailure));
Builder.setNumCompileThreads(LazyJITCompileThreads);
+ // If the object cache is enabled then set a custom compile function
+ // creator to use the cache.
+ std::unique_ptr<LLIObjectCache> CacheManager;
+ if (EnableCacheManager) {
+
+ CacheManager = std::make_unique<LLIObjectCache>(ObjectCacheDir);
+
+ Builder.setCompileFunctionCreator(
+ [&](orc::JITTargetMachineBuilder JTMB)
+ -> Expected<std::unique_ptr<orc::IRCompileLayer::IRCompiler>> {
+ if (LazyJITCompileThreads > 0)
+ return std::make_unique<orc::ConcurrentIRCompiler>(std::move(JTMB),
+ CacheManager.get());
+
+ auto TM = JTMB.createTargetMachine();
+ if (!TM)
+ return TM.takeError();
+
+ return std::make_unique<orc::TMOwningSimpleCompiler>(std::move(*TM),
+ CacheManager.get());
+ });
+ }
+
+ // Set up LLJIT platform.
+ {
+ LLJITPlatform P = Platform;
+ if (P == LLJITPlatform::DetectHost) {
+ if (TT->isOSBinFormatMachO())
+ P = LLJITPlatform::MachO;
+ else
+ P = LLJITPlatform::GenericIR;
+ }
+
+ switch (P) {
+ case LLJITPlatform::GenericIR:
+ // Nothing to do: LLJITBuilder will use this by default.
+ break;
+ case LLJITPlatform::MachO:
+ Builder.setPlatformSetUp(orc::setUpMachOPlatform);
+ ExitOnErr(orc::enableObjCRegistration("libobjc.dylib"));
+ break;
+ default:
+ llvm_unreachable("Unrecognized platform value");
+ }
+ }
+
auto J = ExitOnErr(Builder.create());
+ if (TT->isOSBinFormatELF())
+ static_cast<llvm::orc::RTDyldObjectLinkingLayer &>(J->getObjLinkingLayer())
+ .registerJITEventListener(
+ *JITEventListener::createGDBRegistrationListener());
+
if (PerModuleLazy)
J->setPartitionFunction(orc::CompileOnDemandLayer::compileWholeModule);
auto Dump = createDebugDumper();
- J->setLazyCompileTransform([&](orc::ThreadSafeModule TSM,
- const orc::MaterializationResponsibility &R) {
- TSM.withModuleDo([&](Module &M) {
- if (verifyModule(M, &dbgs())) {
- dbgs() << "Bad module: " << &M << "\n";
- exit(1);
- }
- Dump(M);
- });
- return TSM;
- });
+ J->getIRTransformLayer().setTransform(
+ [&](orc::ThreadSafeModule TSM,
+ const orc::MaterializationResponsibility &R) {
+ TSM.withModuleDo([&](Module &M) {
+ if (verifyModule(M, &dbgs())) {
+ dbgs() << "Bad module: " << &M << "\n";
+ exit(1);
+ }
+ Dump(M);
+ });
+ return TSM;
+ });
orc::MangleAndInterner Mangle(J->getExecutionSession(), J->getDataLayout());
- J->getMainJITDylib().addGenerator(
- ExitOnErr(orc::DynamicLibrarySearchGenerator::GetForCurrentProcess(
- J->getDataLayout().getGlobalPrefix(),
- [MainName = Mangle("main")](const orc::SymbolStringPtr &Name) {
- return Name != MainName;
- })));
- orc::LocalCXXRuntimeOverrides CXXRuntimeOverrides;
- ExitOnErr(CXXRuntimeOverrides.enable(J->getMainJITDylib(), Mangle));
+ // Unless they've been explicitly disabled, make process symbols available to
+ // JIT'd code.
+ if (!NoProcessSymbols)
+ J->getMainJITDylib().addGenerator(
+ ExitOnErr(orc::DynamicLibrarySearchGenerator::GetForCurrentProcess(
+ J->getDataLayout().getGlobalPrefix(),
+ [MainName = Mangle("main")](const orc::SymbolStringPtr &Name) {
+ return Name != MainName;
+ })));
// Add the main module.
- ExitOnErr(
- J->addLazyIRModule(orc::ThreadSafeModule(std::move(MainModule), TSCtx)));
+ ExitOnErr(J->addLazyIRModule(std::move(MainModule)));
// Create JITDylibs and add any extra modules.
{
@@ -818,23 +940,23 @@ int runOrcLazyJIT(const char *ProgName) {
for (auto JDItr = JITDylibs.begin(), JDEnd = JITDylibs.end();
JDItr != JDEnd; ++JDItr) {
orc::JITDylib *JD = J->getJITDylibByName(*JDItr);
- if (!JD)
- JD = &J->createJITDylib(*JDItr);
+ if (!JD) {
+ JD = &ExitOnErr(J->createJITDylib(*JDItr));
+ J->getMainJITDylib().addToLinkOrder(*JD);
+ JD->addToLinkOrder(J->getMainJITDylib());
+ }
IdxToDylib[JITDylibs.getPosition(JDItr - JITDylibs.begin())] = JD;
}
for (auto EMItr = ExtraModules.begin(), EMEnd = ExtraModules.end();
EMItr != EMEnd; ++EMItr) {
- auto M = parseIRFile(*EMItr, Err, *TSCtx.getContext());
- if (!M)
- reportError(Err, ProgName);
+ auto M = ExitOnErr(loadModule(*EMItr, TSCtx));
auto EMIdx = ExtraModules.getPosition(EMItr - ExtraModules.begin());
assert(EMIdx != 0 && "ExtraModule should have index > 0");
auto JDItr = std::prev(IdxToDylib.lower_bound(EMIdx));
auto &JD = *JDItr->second;
- ExitOnErr(
- J->addLazyIRModule(JD, orc::ThreadSafeModule(std::move(M), TSCtx)));
+ ExitOnErr(J->addLazyIRModule(JD, std::move(M)));
}
for (auto EAItr = ExtraArchives.begin(), EAEnd = ExtraArchives.end();
@@ -844,7 +966,7 @@ int runOrcLazyJIT(const char *ProgName) {
auto JDItr = std::prev(IdxToDylib.lower_bound(EAIdx));
auto &JD = *JDItr->second;
JD.addGenerator(ExitOnErr(orc::StaticLibraryDefinitionGenerator::Load(
- J->getObjLinkingLayer(), EAItr->c_str())));
+ J->getObjLinkingLayer(), EAItr->c_str(), *TT)));
}
}
@@ -855,7 +977,7 @@ int runOrcLazyJIT(const char *ProgName) {
}
// Run any static constructors.
- ExitOnErr(J->runConstructors());
+ ExitOnErr(J->initialize(J->getMainJITDylib()));
// Run any -thread-entry points.
std::vector<std::thread> AltEntryThreads;
@@ -880,8 +1002,7 @@ int runOrcLazyJIT(const char *ProgName) {
AltEntryThread.join();
// Run destructors.
- ExitOnErr(J->runDestructors());
- CXXRuntimeOverrides.runDestructors();
+ ExitOnErr(J->deinitialize(J->getMainJITDylib()));
return Result;
}