Set up TargetMachine for JITLink

I missed this in commit 3ff7c1e8e2 and it seems to work by chance on
macOS, but this is needed on Linux: Before, CLING_JTLINK=1 on x86_64
complained about "Unspported personality pointer encoding 0x00" and
crashed entirely on RISC-V.
This commit is contained in:
Jonas Hahnfeld 2023-02-03 11:41:46 +01:00 committed by jenkins
parent 6ef68e5512
commit 1603be8b87
2 changed files with 33 additions and 20 deletions

View File

@ -15,6 +15,7 @@
#include "cling/Utils/Output.h"
#include "cling/Utils/Utils.h"
#include <clang/Basic/TargetInfo.h>
#include <clang/Basic/TargetOptions.h>
#include <clang/Frontend/CompilerInstance.h>
@ -402,8 +403,23 @@ Error RTDynamicLibrarySearchGenerator::tryToGenerate(
return JD.define(absoluteSymbols(std::move(NewSymbols)), CurrentRT());
}
static bool UseJITLink(const Triple& TT) {
bool jitLink = false;
// Default to JITLink on macOS, as done in LLVM by
// LLJITBuilderState::prepareForConstruction.
if (TT.isOSBinFormatMachO() &&
(TT.getArch() == Triple::aarch64 || TT.getArch() == Triple::x86_64)) {
jitLink = true;
}
// Finally, honor the user's choice by setting an environment variable.
if (const char* clingJitLink = std::getenv("CLING_JITLINK")) {
jitLink = cling::utils::ConvertEnvValueToBool(clingJitLink);
}
return jitLink;
}
static std::unique_ptr<TargetMachine>
CreateHostTargetMachine(const clang::CompilerInstance& CI) {
CreateHostTargetMachine(const clang::CompilerInstance& CI, bool JITLink) {
const clang::TargetOptions& TargetOpts = CI.getTargetOpts();
const clang::CodeGenOptions& CGOpt = CI.getCodeGenOpts();
const std::string& Triple = TargetOpts.Triple;
@ -441,6 +457,13 @@ CreateHostTargetMachine(const clang::CompilerInstance& CI) {
JTMB->setCodeModel(CodeModel::Large);
#endif
if (JITLink) {
// Set up the TargetMachine as otherwise done by
// LLJITBuilderState::prepareForConstruction.
JTMB->setRelocationModel(Reloc::PIC_);
JTMB->setCodeModel(CodeModel::Small);
}
std::unique_ptr<TargetMachine> TM = cantFail(JTMB->createTargetMachine());
// Forcefully disable GlobalISel, it might be enabled on AArch64 without
@ -476,7 +499,8 @@ IncrementalJIT::IncrementalJIT(
std::unique_ptr<llvm::orc::ExecutorProcessControl> EPC, Error& Err,
void *ExtraLibHandle, bool Verbose)
: SkipHostProcessLookup(false),
TM(CreateHostTargetMachine(CI)),
m_JITLink(UseJITLink(CI.getTarget().getTriple())),
m_TM(CreateHostTargetMachine(CI, m_JITLink)),
SingleThreadedContext(std::make_unique<LLVMContext>()) {
ErrorAsOutParameter _(&Err);
@ -487,19 +511,7 @@ IncrementalJIT::IncrementalJIT(
Builder.setObjectLinkingLayerCreator([&](ExecutionSession& ES,
const Triple& TT)
-> std::unique_ptr<ObjectLayer> {
bool jitLink = false;
// Default to JITLink on macOS, as done in LLVM by
// LLJITBuilderState::prepareForConstruction.
if (TT.isOSBinFormatMachO() &&
(TT.getArch() == Triple::aarch64 || TT.getArch() == Triple::x86_64)) {
jitLink = true;
}
// Finally, honor the user's choice by setting an environment variable.
if (const char* clingJitLink = std::getenv("CLING_JITLINK")) {
jitLink = cling::utils::ConvertEnvValueToBool(clingJitLink);
}
if (jitLink) {
if (m_JITLink) {
// For JITLink, we only need a custom memory manager to avoid freeing the
// memory segments; the default InProcessMemoryManager (which is mostly
// copied above) already does slab allocation to keep all segments
@ -540,7 +552,7 @@ IncrementalJIT::IncrementalJIT(
Builder.setCompileFunctionCreator([&](llvm::orc::JITTargetMachineBuilder)
-> llvm::Expected<std::unique_ptr<llvm::orc::IRCompileLayer::IRCompiler>> {
return std::make_unique<SimpleCompiler>(*TM);
return std::make_unique<SimpleCompiler>(*m_TM);
});
if (Expected<std::unique_ptr<LLJIT>> JitInstance = Builder.create()) {
@ -560,7 +572,7 @@ IncrementalJIT::IncrementalJIT(
m_CompiledModules[Unsafe] = std::move(TSM);
});
char LinkerPrefix = this->TM->createDataLayout().getGlobalPrefix();
char LinkerPrefix = this->m_TM->createDataLayout().getGlobalPrefix();
// Process symbol resolution
auto HostProcessLookup
@ -675,7 +687,7 @@ IncrementalJIT::addOrReplaceDefinition(StringRef Name,
return KnownAddr;
llvm::SmallString<128> LinkerMangledName;
char LinkerPrefix = this->TM->createDataLayout().getGlobalPrefix();
char LinkerPrefix = this->m_TM->createDataLayout().getGlobalPrefix();
bool HasLinkerPrefix = LinkerPrefix != '\0';
if (HasLinkerPrefix && Name.front() == LinkerPrefix) {
LinkerMangledName.assign(1, LinkerPrefix);

View File

@ -93,7 +93,7 @@ public:
/// @brief Get the TargetMachine used by the JIT.
/// Non-const because BackendPasses need to update OptLevel.
llvm::TargetMachine &getTargetMachine() { return *TM; }
llvm::TargetMachine &getTargetMachine() { return *m_TM; }
private:
std::unique_ptr<llvm::orc::LLJIT> Jit;
@ -109,8 +109,9 @@ private:
std::map<const Transaction*, llvm::orc::ResourceTrackerSP> m_ResourceTrackers;
std::map<const llvm::Module *, llvm::orc::ThreadSafeModule> m_CompiledModules;
bool m_JITLink;
// FIXME: Move TargetMachine ownership to BackendPasses
std::unique_ptr<llvm::TargetMachine> TM;
std::unique_ptr<llvm::TargetMachine> m_TM;
// TODO: We only need the context for materialization. Instead of defining it
// here we might want to pass one in on a per-module basis.