aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/ExecutionEngine
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/ExecutionEngine')
-rw-r--r--llvm/lib/ExecutionEngine/ExecutionEngine.cpp16
-rw-r--r--llvm/lib/ExecutionEngine/GDBRegistrationListener.cpp2
-rw-r--r--llvm/lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp9
-rw-r--r--llvm/lib/ExecutionEngine/Interpreter/Interpreter.h2
-rw-r--r--llvm/lib/ExecutionEngine/JITLink/COFFDirectiveParser.h2
-rw-r--r--llvm/lib/ExecutionEngine/JITLink/COFFLinkGraphBuilder.cpp25
-rw-r--r--llvm/lib/ExecutionEngine/JITLink/COFFLinkGraphBuilder.h5
-rw-r--r--llvm/lib/ExecutionEngine/JITLink/COFF_x86_64.cpp28
-rw-r--r--llvm/lib/ExecutionEngine/JITLink/ELF.cpp25
-rw-r--r--llvm/lib/ExecutionEngine/JITLink/ELFLinkGraphBuilder.h148
-rw-r--r--llvm/lib/ExecutionEngine/JITLink/ELF_aarch32.cpp311
-rw-r--r--llvm/lib/ExecutionEngine/JITLink/ELF_aarch64.cpp64
-rw-r--r--llvm/lib/ExecutionEngine/JITLink/ELF_i386.cpp26
-rw-r--r--llvm/lib/ExecutionEngine/JITLink/ELF_loongarch.cpp16
-rw-r--r--llvm/lib/ExecutionEngine/JITLink/ELF_ppc64.cpp396
-rw-r--r--llvm/lib/ExecutionEngine/JITLink/ELF_riscv.cpp406
-rw-r--r--llvm/lib/ExecutionEngine/JITLink/ELF_x86_64.cpp139
-rw-r--r--llvm/lib/ExecutionEngine/JITLink/JITLink.cpp16
-rw-r--r--llvm/lib/ExecutionEngine/JITLink/JITLinkGeneric.cpp9
-rw-r--r--llvm/lib/ExecutionEngine/JITLink/JITLinkGeneric.h55
-rw-r--r--llvm/lib/ExecutionEngine/JITLink/JITLinkMemoryManager.cpp45
-rw-r--r--llvm/lib/ExecutionEngine/JITLink/MachO.cpp2
-rw-r--r--llvm/lib/ExecutionEngine/JITLink/MachOLinkGraphBuilder.cpp28
-rw-r--r--llvm/lib/ExecutionEngine/JITLink/MachOLinkGraphBuilder.h1
-rw-r--r--llvm/lib/ExecutionEngine/JITLink/MachO_arm64.cpp13
-rw-r--r--llvm/lib/ExecutionEngine/JITLink/MachO_x86_64.cpp13
-rw-r--r--llvm/lib/ExecutionEngine/JITLink/SEHFrameSupport.h2
-rw-r--r--llvm/lib/ExecutionEngine/JITLink/aarch32.cpp519
-rw-r--r--llvm/lib/ExecutionEngine/JITLink/aarch64.cpp6
-rw-r--r--llvm/lib/ExecutionEngine/JITLink/i386.cpp48
-rw-r--r--llvm/lib/ExecutionEngine/JITLink/ppc64.cpp102
-rw-r--r--llvm/lib/ExecutionEngine/JITLink/riscv.cpp4
-rw-r--r--llvm/lib/ExecutionEngine/JITLink/x86_64.cpp8
-rw-r--r--llvm/lib/ExecutionEngine/Orc/COFFPlatform.cpp150
-rw-r--r--llvm/lib/ExecutionEngine/Orc/COFFVCRuntimeSupport.cpp2
-rw-r--r--llvm/lib/ExecutionEngine/Orc/Core.cpp84
-rw-r--r--llvm/lib/ExecutionEngine/Orc/DebugObjectManagerPlugin.cpp101
-rw-r--r--llvm/lib/ExecutionEngine/Orc/DebugUtils.cpp11
-rw-r--r--llvm/lib/ExecutionEngine/Orc/DebuggerSupportPlugin.cpp11
-rw-r--r--llvm/lib/ExecutionEngine/Orc/ELFNixPlatform.cpp168
-rw-r--r--llvm/lib/ExecutionEngine/Orc/EPCDebugObjectRegistrar.cpp11
-rw-r--r--llvm/lib/ExecutionEngine/Orc/EPCDynamicLibrarySearchGenerator.cpp3
-rw-r--r--llvm/lib/ExecutionEngine/Orc/EPCEHFrameRegistrar.cpp5
-rw-r--r--llvm/lib/ExecutionEngine/Orc/EPCGenericJITLinkMemoryManager.cpp2
-rw-r--r--llvm/lib/ExecutionEngine/Orc/EPCGenericRTDyldMemoryManager.cpp2
-rw-r--r--llvm/lib/ExecutionEngine/Orc/EPCIndirectionUtils.cpp77
-rw-r--r--llvm/lib/ExecutionEngine/Orc/ExecutionUtils.cpp162
-rw-r--r--llvm/lib/ExecutionEngine/Orc/ExecutorProcessControl.cpp4
-rw-r--r--llvm/lib/ExecutionEngine/Orc/IndirectionUtils.cpp73
-rw-r--r--llvm/lib/ExecutionEngine/Orc/JITTargetMachineBuilder.cpp5
-rw-r--r--llvm/lib/ExecutionEngine/Orc/LLJIT.cpp407
-rw-r--r--llvm/lib/ExecutionEngine/Orc/Layer.cpp4
-rw-r--r--llvm/lib/ExecutionEngine/Orc/LazyReexports.cpp29
-rw-r--r--llvm/lib/ExecutionEngine/Orc/LookupAndRecordAddrs.cpp4
-rw-r--r--llvm/lib/ExecutionEngine/Orc/MachOPlatform.cpp416
-rw-r--r--llvm/lib/ExecutionEngine/Orc/MemoryMapper.cpp3
-rw-r--r--llvm/lib/ExecutionEngine/Orc/ObjectFileInterface.cpp24
-rw-r--r--llvm/lib/ExecutionEngine/Orc/ObjectLinkingLayer.cpp93
-rw-r--r--llvm/lib/ExecutionEngine/Orc/OrcABISupport.cpp212
-rw-r--r--llvm/lib/ExecutionEngine/Orc/OrcV2CBindings.cpp48
-rw-r--r--llvm/lib/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.cpp5
-rw-r--r--llvm/lib/ExecutionEngine/Orc/Shared/ObjectFormats.cpp94
-rw-r--r--llvm/lib/ExecutionEngine/Orc/SimpleRemoteEPC.cpp36
-rw-r--r--llvm/lib/ExecutionEngine/Orc/Speculation.cpp11
-rw-r--r--llvm/lib/ExecutionEngine/Orc/TargetProcess/ExecutorSharedMemoryMapperService.cpp11
-rw-r--r--llvm/lib/ExecutionEngine/Orc/TargetProcess/JITLoaderGDB.cpp25
-rw-r--r--llvm/lib/ExecutionEngine/Orc/TargetProcess/SimpleExecutorMemoryManager.cpp4
-rw-r--r--llvm/lib/ExecutionEngine/Orc/TargetProcess/SimpleRemoteEPCServer.cpp22
-rw-r--r--llvm/lib/ExecutionEngine/PerfJITEvents/PerfJITEventListener.cpp2
-rw-r--r--llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCOFF.cpp2
-rw-r--r--llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp14
-rw-r--r--llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h4
-rw-r--r--llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFAArch64.h1
-rw-r--r--llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFThumb.h1
-rw-r--r--llvm/lib/ExecutionEngine/SectionMemoryManager.cpp17
-rw-r--r--llvm/lib/ExecutionEngine/TargetSelect.cpp7
76 files changed, 3711 insertions, 1147 deletions
diff --git a/llvm/lib/ExecutionEngine/ExecutionEngine.cpp b/llvm/lib/ExecutionEngine/ExecutionEngine.cpp
index 2a90b67bee4b..768d84501337 100644
--- a/llvm/lib/ExecutionEngine/ExecutionEngine.cpp
+++ b/llvm/lib/ExecutionEngine/ExecutionEngine.cpp
@@ -34,9 +34,9 @@
#include "llvm/Support/Debug.h"
#include "llvm/Support/DynamicLibrary.h"
#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/Host.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetMachine.h"
+#include "llvm/TargetParser/Host.h"
#include <cmath>
#include <cstring>
#include <mutex>
@@ -878,6 +878,12 @@ GenericValue ExecutionEngine::getConstantValue(const Constant *C) {
report_fatal_error(OS.str());
}
+ if (auto *TETy = dyn_cast<TargetExtType>(C->getType())) {
+ assert(TETy->hasProperty(TargetExtType::HasZeroInit) && C->isNullValue() &&
+ "TargetExtType only supports null constant value");
+ C = Constant::getNullValue(TETy->getLayoutType());
+ }
+
// Otherwise, we have a simple constant.
GenericValue Result;
switch (C->getType()->getTypeID()) {
@@ -1017,6 +1023,11 @@ GenericValue ExecutionEngine::getConstantValue(const Constant *C) {
void ExecutionEngine::StoreValueToMemory(const GenericValue &Val,
GenericValue *Ptr, Type *Ty) {
+ // It is safe to treat TargetExtType as its layout type since the underlying
+ // bits are only copied and are not inspected.
+ if (auto *TETy = dyn_cast<TargetExtType>(Ty))
+ Ty = TETy->getLayoutType();
+
const unsigned StoreBytes = getDataLayout().getTypeStoreSize(Ty);
switch (Ty->getTypeID()) {
@@ -1068,6 +1079,9 @@ void ExecutionEngine::StoreValueToMemory(const GenericValue &Val,
void ExecutionEngine::LoadValueFromMemory(GenericValue &Result,
GenericValue *Ptr,
Type *Ty) {
+ if (auto *TETy = dyn_cast<TargetExtType>(Ty))
+ Ty = TETy->getLayoutType();
+
const unsigned LoadBytes = getDataLayout().getTypeStoreSize(Ty);
switch (Ty->getTypeID()) {
diff --git a/llvm/lib/ExecutionEngine/GDBRegistrationListener.cpp b/llvm/lib/ExecutionEngine/GDBRegistrationListener.cpp
index f1eeee3b3599..b5b76130c55e 100644
--- a/llvm/lib/ExecutionEngine/GDBRegistrationListener.cpp
+++ b/llvm/lib/ExecutionEngine/GDBRegistrationListener.cpp
@@ -176,7 +176,7 @@ void GDBJITRegistrationListener::notifyObjectLoaded(
size_t Size = DebugObj.getBinary()->getMemoryBufferRef().getBufferSize();
std::lock_guard<llvm::sys::Mutex> locked(JITDebugLock);
- assert(ObjectBufferMap.find(K) == ObjectBufferMap.end() &&
+ assert(!ObjectBufferMap.contains(K) &&
"Second attempt to perform debug registration.");
jit_code_entry* JITCodeEntry = new jit_code_entry();
diff --git a/llvm/lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp b/llvm/lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp
index 29f481a1e4e8..4f8f883a75f3 100644
--- a/llvm/lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp
+++ b/llvm/lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp
@@ -344,6 +344,12 @@ static GenericValue lle_X_abort(FunctionType *FT, ArrayRef<GenericValue> Args) {
return GenericValue();
}
+// Silence warnings about sprintf. (See also
+// https://github.com/llvm/llvm-project/issues/58086)
+#if defined(__clang__)
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+#endif
// int sprintf(char *, const char *, ...) - a very rough implementation to make
// output useful.
static GenericValue lle_X_sprintf(FunctionType *FT,
@@ -425,6 +431,9 @@ static GenericValue lle_X_sprintf(FunctionType *FT,
}
return GV;
}
+#if defined(__clang__)
+#pragma clang diagnostic pop
+#endif
// int printf(const char *, ...) - a very rough implementation to make output
// useful.
diff --git a/llvm/lib/ExecutionEngine/Interpreter/Interpreter.h b/llvm/lib/ExecutionEngine/Interpreter/Interpreter.h
index 3dfe736dc5be..41a0389442d3 100644
--- a/llvm/lib/ExecutionEngine/Interpreter/Interpreter.h
+++ b/llvm/lib/ExecutionEngine/Interpreter/Interpreter.h
@@ -224,8 +224,6 @@ private: // Helper functions
ExecutionContext &SF);
GenericValue executeBitCastInst(Value *SrcVal, Type *DstTy,
ExecutionContext &SF);
- GenericValue executeCastOperation(Instruction::CastOps opcode, Value *SrcVal,
- Type *Ty, ExecutionContext &SF);
void popStackAndReturnValueToCaller(Type *RetTy, GenericValue Result);
};
diff --git a/llvm/lib/ExecutionEngine/JITLink/COFFDirectiveParser.h b/llvm/lib/ExecutionEngine/JITLink/COFFDirectiveParser.h
index 8d5e0f7314dd..5c953da7581f 100644
--- a/llvm/lib/ExecutionEngine/JITLink/COFFDirectiveParser.h
+++ b/llvm/lib/ExecutionEngine/JITLink/COFFDirectiveParser.h
@@ -13,13 +13,13 @@
#ifndef LLVM_EXECUTIONENGINE_JITLINK_COFFDIRECTIVEPARSER_H
#define LLVM_EXECUTIONENGINE_JITLINK_COFFDIRECTIVEPARSER_H
-#include "llvm/ADT/Triple.h"
#include "llvm/ExecutionEngine/JITLink/JITLink.h"
#include "llvm/Option/Arg.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/StringSaver.h"
+#include "llvm/TargetParser/Triple.h"
namespace llvm {
namespace jitlink {
diff --git a/llvm/lib/ExecutionEngine/JITLink/COFFLinkGraphBuilder.cpp b/llvm/lib/ExecutionEngine/JITLink/COFFLinkGraphBuilder.cpp
index 782928c26084..6668854e1a6a 100644
--- a/llvm/lib/ExecutionEngine/JITLink/COFFLinkGraphBuilder.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/COFFLinkGraphBuilder.cpp
@@ -24,13 +24,12 @@ static Triple createTripleWithCOFFFormat(Triple T) {
}
COFFLinkGraphBuilder::COFFLinkGraphBuilder(
- const object::COFFObjectFile &Obj, Triple TT,
+ const object::COFFObjectFile &Obj, Triple TT, SubtargetFeatures Features,
LinkGraph::GetEdgeKindNameFunction GetEdgeKindName)
- : Obj(Obj),
- G(std::make_unique<LinkGraph>(Obj.getFileName().str(),
- createTripleWithCOFFFormat(TT),
- getPointerSize(Obj), getEndianness(Obj),
- std::move(GetEdgeKindName))) {
+ : Obj(Obj), G(std::make_unique<LinkGraph>(
+ Obj.getFileName().str(), createTripleWithCOFFFormat(TT),
+ std::move(Features), getPointerSize(Obj),
+ getEndianness(Obj), std::move(GetEdgeKindName))) {
LLVM_DEBUG({
dbgs() << "Created COFFLinkGraphBuilder for \"" << Obj.getFileName()
<< "\"\n";
@@ -135,6 +134,13 @@ Error COFFLinkGraphBuilder::graphifySections() {
SectionName = *SecNameOrErr;
// FIXME: Skip debug info sections
+ if (SectionName == ".voltbl") {
+ LLVM_DEBUG({
+ dbgs() << " "
+ << "Skipping section \"" << SectionName << "\"\n";
+ });
+ continue;
+ }
LLVM_DEBUG({
dbgs() << " "
@@ -152,8 +158,11 @@ Error COFFLinkGraphBuilder::graphifySections() {
// Look for existing sections first.
auto *GraphSec = G->findSectionByName(SectionName);
- if (!GraphSec)
+ if (!GraphSec) {
GraphSec = &G->createSection(SectionName, Prot);
+ if ((*Sec)->Characteristics & COFF::IMAGE_SCN_LNK_REMOVE)
+ GraphSec->setMemLifetimePolicy(orc::MemLifetimePolicy::NoAlloc);
+ }
if (GraphSec->getMemProt() != Prot)
return make_error<JITLinkError>("MemProt should match");
@@ -287,7 +296,7 @@ Error COFFLinkGraphBuilder::handleDirectiveSection(StringRef Str) {
break;
}
case COFF_OPT_incl: {
- auto DataCopy = G->allocateString(S);
+ auto DataCopy = G->allocateContent(S);
StringRef StrCopy(DataCopy.data(), DataCopy.size());
ExternalSymbols[StrCopy] = &G->addExternalSymbol(StrCopy, 0, false);
ExternalSymbols[StrCopy]->setLive(true);
diff --git a/llvm/lib/ExecutionEngine/JITLink/COFFLinkGraphBuilder.h b/llvm/lib/ExecutionEngine/JITLink/COFFLinkGraphBuilder.h
index 0c0a1a536deb..e64823759540 100644
--- a/llvm/lib/ExecutionEngine/JITLink/COFFLinkGraphBuilder.h
+++ b/llvm/lib/ExecutionEngine/JITLink/COFFLinkGraphBuilder.h
@@ -39,6 +39,7 @@ protected:
using COFFSymbolIndex = int32_t;
COFFLinkGraphBuilder(const object::COFFObjectFile &Obj, Triple TT,
+ SubtargetFeatures Features,
LinkGraph::GetEdgeKindNameFunction GetEdgeKindName);
LinkGraph &getGraph() const { return *G; }
@@ -192,6 +193,10 @@ Error COFFLinkGraphBuilder::forEachRelocation(const object::SectionRef &RelSec,
Expected<StringRef> Name = Obj.getSectionName(COFFRelSect);
if (!Name)
return Name.takeError();
+
+ // Skip the unhandled metadata sections.
+ if (*Name == ".voltbl")
+ return Error::success();
LLVM_DEBUG(dbgs() << " " << *Name << ":\n");
// Lookup the link-graph node corresponding to the target section name.
diff --git a/llvm/lib/ExecutionEngine/JITLink/COFF_x86_64.cpp b/llvm/lib/ExecutionEngine/JITLink/COFF_x86_64.cpp
index b09dc769b81c..3257a2ae94f6 100644
--- a/llvm/lib/ExecutionEngine/JITLink/COFF_x86_64.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/COFF_x86_64.cpp
@@ -181,8 +181,10 @@ private:
}
public:
- COFFLinkGraphBuilder_x86_64(const object::COFFObjectFile &Obj, const Triple T)
- : COFFLinkGraphBuilder(Obj, std::move(T), getCOFFX86RelocationKindName) {}
+ COFFLinkGraphBuilder_x86_64(const object::COFFObjectFile &Obj, const Triple T,
+ const SubtargetFeatures Features)
+ : COFFLinkGraphBuilder(Obj, std::move(T), std::move(Features),
+ getCOFFX86RelocationKindName) {}
};
class COFFLinkGraphLowering_x86_64 {
@@ -196,7 +198,7 @@ public:
auto ImageBase = getImageBaseAddress(G, Ctx);
if (!ImageBase)
return ImageBase.takeError();
- E.setAddend(E.getAddend() - *ImageBase);
+ E.setAddend(E.getAddend() - ImageBase->getValue());
E.setKind(x86_64::Pointer32);
break;
}
@@ -238,19 +240,19 @@ private:
return SectionStartCache[&Sec];
}
- Expected<JITTargetAddress> getImageBaseAddress(LinkGraph &G,
- JITLinkContext &Ctx) {
+ Expected<orc::ExecutorAddr> getImageBaseAddress(LinkGraph &G,
+ JITLinkContext &Ctx) {
if (this->ImageBase)
return this->ImageBase;
for (auto *S : G.defined_symbols())
if (S->getName() == getImageBaseSymbolName()) {
- this->ImageBase = S->getAddress().getValue();
+ this->ImageBase = S->getAddress();
return this->ImageBase;
}
JITLinkContext::LookupMap Symbols;
Symbols[getImageBaseSymbolName()] = SymbolLookupFlags::RequiredSymbol;
- JITTargetAddress ImageBase;
+ orc::ExecutorAddr ImageBase;
Error Err = Error::success();
Ctx.lookup(Symbols,
createLookupContinuation([&](Expected<AsyncLookupResult> LR) {
@@ -259,8 +261,7 @@ private:
Err = LR.takeError();
return;
}
- auto &ImageBaseSymbol = LR->begin()->second;
- ImageBase = ImageBaseSymbol.getAddress();
+ ImageBase = LR->begin()->second.getAddress();
}));
if (Err)
return std::move(Err);
@@ -269,7 +270,7 @@ private:
}
DenseMap<Section *, orc::ExecutorAddr> SectionStartCache;
- JITTargetAddress ImageBase = 0;
+ orc::ExecutorAddr ImageBase;
};
Error lowerEdges_COFF_x86_64(LinkGraph &G, JITLinkContext *Ctx) {
@@ -315,7 +316,12 @@ createLinkGraphFromCOFFObject_x86_64(MemoryBufferRef ObjectBuffer) {
if (!COFFObj)
return COFFObj.takeError();
- return COFFLinkGraphBuilder_x86_64(**COFFObj, (*COFFObj)->makeTriple())
+ auto Features = (*COFFObj)->getFeatures();
+ if (!Features)
+ return Features.takeError();
+
+ return COFFLinkGraphBuilder_x86_64(**COFFObj, (*COFFObj)->makeTriple(),
+ std::move(*Features))
.buildGraph();
}
diff --git a/llvm/lib/ExecutionEngine/JITLink/ELF.cpp b/llvm/lib/ExecutionEngine/JITLink/ELF.cpp
index ef0f19a78571..dd08a23306ff 100644
--- a/llvm/lib/ExecutionEngine/JITLink/ELF.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/ELF.cpp
@@ -13,9 +13,11 @@
#include "llvm/ExecutionEngine/JITLink/ELF.h"
#include "llvm/BinaryFormat/ELF.h"
+#include "llvm/ExecutionEngine/JITLink/ELF_aarch32.h"
#include "llvm/ExecutionEngine/JITLink/ELF_aarch64.h"
#include "llvm/ExecutionEngine/JITLink/ELF_i386.h"
#include "llvm/ExecutionEngine/JITLink/ELF_loongarch.h"
+#include "llvm/ExecutionEngine/JITLink/ELF_ppc64.h"
#include "llvm/ExecutionEngine/JITLink/ELF_riscv.h"
#include "llvm/ExecutionEngine/JITLink/ELF_x86_64.h"
#include "llvm/Object/ELF.h"
@@ -56,12 +58,13 @@ Expected<uint16_t> readTargetMachineArch(StringRef Buffer) {
Expected<std::unique_ptr<LinkGraph>>
createLinkGraphFromELFObject(MemoryBufferRef ObjectBuffer) {
StringRef Buffer = ObjectBuffer.getBuffer();
- if (Buffer.size() < ELF::EI_MAG3 + 1)
+ if (Buffer.size() < ELF::EI_NIDENT)
return make_error<JITLinkError>("Truncated ELF buffer");
if (memcmp(Buffer.data(), ELF::ElfMagic, strlen(ELF::ElfMagic)) != 0)
return make_error<JITLinkError>("ELF magic not valid");
+ uint8_t DataEncoding = Buffer.data()[ELF::EI_DATA];
Expected<uint16_t> TargetMachineArch = readTargetMachineArch(Buffer);
if (!TargetMachineArch)
return TargetMachineArch.takeError();
@@ -69,8 +72,16 @@ createLinkGraphFromELFObject(MemoryBufferRef ObjectBuffer) {
switch (*TargetMachineArch) {
case ELF::EM_AARCH64:
return createLinkGraphFromELFObject_aarch64(ObjectBuffer);
+ case ELF::EM_ARM:
+ return createLinkGraphFromELFObject_aarch32(ObjectBuffer);
case ELF::EM_LOONGARCH:
return createLinkGraphFromELFObject_loongarch(ObjectBuffer);
+ case ELF::EM_PPC64: {
+ if (DataEncoding == ELF::ELFDATA2LSB)
+ return createLinkGraphFromELFObject_ppc64le(ObjectBuffer);
+ else
+ return createLinkGraphFromELFObject_ppc64(ObjectBuffer);
+ }
case ELF::EM_RISCV:
return createLinkGraphFromELFObject_riscv(ObjectBuffer);
case ELF::EM_X86_64:
@@ -90,10 +101,22 @@ void link_ELF(std::unique_ptr<LinkGraph> G,
case Triple::aarch64:
link_ELF_aarch64(std::move(G), std::move(Ctx));
return;
+ case Triple::arm:
+ case Triple::armeb:
+ case Triple::thumb:
+ case Triple::thumbeb:
+ link_ELF_aarch32(std::move(G), std::move(Ctx));
+ return;
case Triple::loongarch32:
case Triple::loongarch64:
link_ELF_loongarch(std::move(G), std::move(Ctx));
return;
+ case Triple::ppc64:
+ link_ELF_ppc64(std::move(G), std::move(Ctx));
+ return;
+ case Triple::ppc64le:
+ link_ELF_ppc64le(std::move(G), std::move(Ctx));
+ return;
case Triple::riscv32:
case Triple::riscv64:
link_ELF_riscv(std::move(G), std::move(Ctx));
diff --git a/llvm/lib/ExecutionEngine/JITLink/ELFLinkGraphBuilder.h b/llvm/lib/ExecutionEngine/JITLink/ELFLinkGraphBuilder.h
index 953a9f512784..e72645798349 100644
--- a/llvm/lib/ExecutionEngine/JITLink/ELFLinkGraphBuilder.h
+++ b/llvm/lib/ExecutionEngine/JITLink/ELFLinkGraphBuilder.h
@@ -59,9 +59,17 @@ class ELFLinkGraphBuilder : public ELFLinkGraphBuilderBase {
public:
ELFLinkGraphBuilder(const object::ELFFile<ELFT> &Obj, Triple TT,
- StringRef FileName,
+ SubtargetFeatures Features, StringRef FileName,
LinkGraph::GetEdgeKindNameFunction GetEdgeKindName);
+ /// Debug sections are included in the graph by default. Use
+ /// setProcessDebugSections(false) to ignore them if debug info is not
+ /// needed.
+ ELFLinkGraphBuilder &setProcessDebugSections(bool ProcessDebugSections) {
+ this->ProcessDebugSections = ProcessDebugSections;
+ return *this;
+ }
+
/// Attempt to construct and return the LinkGraph.
Expected<std::unique_ptr<LinkGraph>> buildGraph();
@@ -83,10 +91,7 @@ protected:
}
Block *getGraphBlock(ELFSectionIndex SecIndex) {
- auto I = GraphBlocks.find(SecIndex);
- if (I == GraphBlocks.end())
- return nullptr;
- return I->second;
+ return GraphBlocks.lookup(SecIndex);
}
void setGraphSymbol(ELFSymbolIndex SymIndex, Symbol &Sym) {
@@ -95,19 +100,33 @@ protected:
}
Symbol *getGraphSymbol(ELFSymbolIndex SymIndex) {
- auto I = GraphSymbols.find(SymIndex);
- if (I == GraphSymbols.end())
- return nullptr;
- return I->second;
+ return GraphSymbols.lookup(SymIndex);
}
Expected<std::pair<Linkage, Scope>>
getSymbolLinkageAndScope(const typename ELFT::Sym &Sym, StringRef Name);
+ /// Set the target flags on the given Symbol.
+ virtual TargetFlagsType makeTargetFlags(const typename ELFT::Sym &Sym) {
+ return TargetFlagsType{};
+ }
+
+ /// Get the physical offset of the symbol on the target platform.
+ virtual orc::ExecutorAddrDiff getRawOffset(const typename ELFT::Sym &Sym,
+ TargetFlagsType Flags) {
+ return Sym.getValue();
+ }
+
Error prepare();
Error graphifySections();
Error graphifySymbols();
+ /// Override in derived classes to suppress certain sections in the link
+ /// graph.
+ virtual bool excludeSection(const typename ELFT::Shdr &Sect) const {
+ return false;
+ }
+
/// Traverse all matching ELFT::Rela relocation records in the given section.
/// The handler function Func should be callable with this signature:
/// Error(const typename ELFT::Rela &,
@@ -115,8 +134,7 @@ protected:
///
template <typename RelocHandlerMethod>
Error forEachRelaRelocation(const typename ELFT::Shdr &RelSect,
- RelocHandlerMethod &&Func,
- bool ProcessDebugSections = false);
+ RelocHandlerMethod &&Func);
/// Traverse all matching ELFT::Rel relocation records in the given section.
/// The handler function Func should be callable with this signature:
@@ -125,22 +143,19 @@ protected:
///
template <typename RelocHandlerMethod>
Error forEachRelRelocation(const typename ELFT::Shdr &RelSect,
- RelocHandlerMethod &&Func,
- bool ProcessDebugSections = false);
+ RelocHandlerMethod &&Func);
/// Traverse all matching rela relocation records in the given section.
/// Convenience wrapper to allow passing a member function for the handler.
///
template <typename ClassT, typename RelocHandlerMethod>
Error forEachRelaRelocation(const typename ELFT::Shdr &RelSect,
- ClassT *Instance, RelocHandlerMethod &&Method,
- bool ProcessDebugSections = false) {
+ ClassT *Instance, RelocHandlerMethod &&Method) {
return forEachRelaRelocation(
RelSect,
[Instance, Method](const auto &Rel, const auto &Target, auto &GS) {
return (Instance->*Method)(Rel, Target, GS);
- },
- ProcessDebugSections);
+ });
}
/// Traverse all matching rel relocation records in the given section.
@@ -148,14 +163,12 @@ protected:
///
template <typename ClassT, typename RelocHandlerMethod>
Error forEachRelRelocation(const typename ELFT::Shdr &RelSect,
- ClassT *Instance, RelocHandlerMethod &&Method,
- bool ProcessDebugSections = false) {
+ ClassT *Instance, RelocHandlerMethod &&Method) {
return forEachRelRelocation(
RelSect,
[Instance, Method](const auto &Rel, const auto &Target, auto &GS) {
return (Instance->*Method)(Rel, Target, GS);
- },
- ProcessDebugSections);
+ });
}
const ELFFile &Obj;
@@ -163,6 +176,7 @@ protected:
typename ELFFile::Elf_Shdr_Range Sections;
const typename ELFFile::Elf_Shdr *SymTabSec = nullptr;
StringRef SectionStringTab;
+ bool ProcessDebugSections = true;
// Maps ELF section indexes to LinkGraph Blocks.
// Only SHF_ALLOC sections will have graph blocks.
@@ -175,11 +189,11 @@ protected:
template <typename ELFT>
ELFLinkGraphBuilder<ELFT>::ELFLinkGraphBuilder(
- const ELFFile &Obj, Triple TT, StringRef FileName,
- LinkGraph::GetEdgeKindNameFunction GetEdgeKindName)
+ const ELFFile &Obj, Triple TT, SubtargetFeatures Features,
+ StringRef FileName, LinkGraph::GetEdgeKindNameFunction GetEdgeKindName)
: ELFLinkGraphBuilderBase(std::make_unique<LinkGraph>(
- FileName.str(), Triple(std::move(TT)), ELFT::Is64Bits ? 8 : 4,
- support::endianness(ELFT::TargetEndianness),
+ FileName.str(), Triple(std::move(TT)), std::move(Features),
+ ELFT::Is64Bits ? 8 : 4, support::endianness(ELFT::TargetEndianness),
std::move(GetEdgeKindName))),
Obj(Obj) {
LLVM_DEBUG(
@@ -307,23 +321,28 @@ template <typename ELFT> Error ELFLinkGraphBuilder<ELFT>::graphifySections() {
auto Name = Obj.getSectionName(Sec, SectionStringTab);
if (!Name)
return Name.takeError();
+ if (excludeSection(Sec)) {
+ LLVM_DEBUG({
+ dbgs() << " " << SecIndex << ": Skipping section \"" << *Name
+ << "\" explicitly\n";
+ });
+ continue;
+ }
- // If the name indicates that it's a debug section then skip it: We don't
- // support those yet.
- if (isDwarfSection(*Name)) {
+ // Skip null sections.
+ if (Sec.sh_type == ELF::SHT_NULL) {
LLVM_DEBUG({
- dbgs() << " " << SecIndex << ": \"" << *Name
- << "\" is a debug section: "
- "No graph section will be created.\n";
+ dbgs() << " " << SecIndex << ": has type SHT_NULL. Skipping.\n";
});
continue;
}
- // Skip non-SHF_ALLOC sections
- if (!(Sec.sh_flags & ELF::SHF_ALLOC)) {
+ // If the name indicates that it's a debug section then skip it: We don't
+ // support those yet.
+ if (!ProcessDebugSections && isDwarfSection(*Name)) {
LLVM_DEBUG({
dbgs() << " " << SecIndex << ": \"" << *Name
- << "\" is not an SHF_ALLOC section: "
+ << "\" is a debug section: "
"No graph section will be created.\n";
});
continue;
@@ -335,16 +354,26 @@ template <typename ELFT> Error ELFLinkGraphBuilder<ELFT>::graphifySections() {
});
// Get the section's memory protection flags.
- orc::MemProt Prot;
+ orc::MemProt Prot = orc::MemProt::Read;
if (Sec.sh_flags & ELF::SHF_EXECINSTR)
- Prot = orc::MemProt::Read | orc::MemProt::Exec;
- else
- Prot = orc::MemProt::Read | orc::MemProt::Write;
+ Prot |= orc::MemProt::Exec;
+ if (Sec.sh_flags & ELF::SHF_WRITE)
+ Prot |= orc::MemProt::Write;
// Look for existing sections first.
auto *GraphSec = G->findSectionByName(*Name);
- if (!GraphSec)
+ if (!GraphSec) {
GraphSec = &G->createSection(*Name, Prot);
+ // Non-SHF_ALLOC sections get NoAlloc memory lifetimes.
+ if (!(Sec.sh_flags & ELF::SHF_ALLOC)) {
+ GraphSec->setMemLifetimePolicy(orc::MemLifetimePolicy::NoAlloc);
+ LLVM_DEBUG({
+ dbgs() << " " << SecIndex << ": \"" << *Name
+ << "\" is not a SHF_ALLOC section. Using NoAlloc lifetime.\n";
+ });
+ }
+ }
+
assert(GraphSec->getMemProt() == Prot && "MemProt should match");
Block *B = nullptr;
@@ -467,6 +496,9 @@ template <typename ELFT> Error ELFLinkGraphBuilder<ELFT>::graphifySymbols() {
<< "\"\n";
});
+ TargetFlagsType Flags = makeTargetFlags(Sym);
+ orc::ExecutorAddrDiff Offset = getRawOffset(Sym, Flags);
+
// In RISCV, temporary symbols (Used to generate dwarf, eh_frame
// sections...) will appear in object code's symbol table, and LLVM does
// not use names on these temporary symbols (RISCV gnu toolchain uses
@@ -474,10 +506,13 @@ template <typename ELFT> Error ELFLinkGraphBuilder<ELFT>::graphifySymbols() {
// anonymous symbol.
auto &GSym =
Name->empty()
- ? G->addAnonymousSymbol(*B, Sym.getValue(), Sym.st_size,
+ ? G->addAnonymousSymbol(*B, Offset, Sym.st_size,
false, false)
- : G->addDefinedSymbol(*B, Sym.getValue(), *Name, Sym.st_size, L,
- S, Sym.getType() == ELF::STT_FUNC, false);
+ : G->addDefinedSymbol(*B, Offset, *Name, Sym.st_size, L,
+ S, Sym.getType() == ELF::STT_FUNC,
+ false);
+
+ GSym.setTargetFlags(Flags);
setGraphSymbol(SymIndex, GSym);
}
} else if (Sym.isUndefined() && Sym.isExternal()) {
@@ -499,6 +534,21 @@ template <typename ELFT> Error ELFLinkGraphBuilder<ELFT>::graphifySymbols() {
auto &GSym = G->addExternalSymbol(*Name, Sym.st_size,
Sym.getBinding() == ELF::STB_WEAK);
setGraphSymbol(SymIndex, GSym);
+ } else if (Sym.isUndefined() && Sym.st_value == 0 && Sym.st_size == 0 &&
+ Sym.getType() == ELF::STT_NOTYPE &&
+ Sym.getBinding() == ELF::STB_LOCAL && Name->empty()) {
+ // Some relocations (e.g., R_RISCV_ALIGN) don't have a target symbol and
+ // use this kind of null symbol as a placeholder.
+ LLVM_DEBUG({
+ dbgs() << " " << SymIndex << ": Creating null graph symbol\n";
+ });
+
+ auto SymName =
+ G->allocateContent("__jitlink_ELF_SYM_UND_" + Twine(SymIndex));
+ auto SymNameRef = StringRef(SymName.data(), SymName.size());
+ auto &GSym = G->addAbsoluteSymbol(SymNameRef, orc::ExecutorAddr(0), 0,
+ Linkage::Strong, Scope::Local, false);
+ setGraphSymbol(SymIndex, GSym);
} else {
LLVM_DEBUG({
dbgs() << " " << SymIndex
@@ -514,8 +564,7 @@ template <typename ELFT> Error ELFLinkGraphBuilder<ELFT>::graphifySymbols() {
template <typename ELFT>
template <typename RelocHandlerFunction>
Error ELFLinkGraphBuilder<ELFT>::forEachRelaRelocation(
- const typename ELFT::Shdr &RelSect, RelocHandlerFunction &&Func,
- bool ProcessDebugSections) {
+ const typename ELFT::Shdr &RelSect, RelocHandlerFunction &&Func) {
// Only look into sections that store relocation entries.
if (RelSect.sh_type != ELF::SHT_RELA)
return Error::success();
@@ -537,6 +586,10 @@ Error ELFLinkGraphBuilder<ELFT>::forEachRelaRelocation(
LLVM_DEBUG(dbgs() << " skipped (dwarf section)\n\n");
return Error::success();
}
+ if (excludeSection(**FixupSection)) {
+ LLVM_DEBUG(dbgs() << " skipped (fixup section excluded explicitly)\n\n");
+ return Error::success();
+ }
// Lookup the link-graph node corresponding to the target section name.
auto *BlockToFix = getGraphBlock(RelSect.sh_info);
@@ -561,8 +614,7 @@ Error ELFLinkGraphBuilder<ELFT>::forEachRelaRelocation(
template <typename ELFT>
template <typename RelocHandlerFunction>
Error ELFLinkGraphBuilder<ELFT>::forEachRelRelocation(
- const typename ELFT::Shdr &RelSect, RelocHandlerFunction &&Func,
- bool ProcessDebugSections) {
+ const typename ELFT::Shdr &RelSect, RelocHandlerFunction &&Func) {
// Only look into sections that store relocation entries.
if (RelSect.sh_type != ELF::SHT_REL)
return Error::success();
@@ -584,6 +636,10 @@ Error ELFLinkGraphBuilder<ELFT>::forEachRelRelocation(
LLVM_DEBUG(dbgs() << " skipped (dwarf section)\n\n");
return Error::success();
}
+ if (excludeSection(**FixupSection)) {
+ LLVM_DEBUG(dbgs() << " skipped (fixup section excluded explicitly)\n\n");
+ return Error::success();
+ }
// Lookup the link-graph node corresponding to the target section name.
auto *BlockToFix = getGraphBlock(RelSect.sh_info);
diff --git a/llvm/lib/ExecutionEngine/JITLink/ELF_aarch32.cpp b/llvm/lib/ExecutionEngine/JITLink/ELF_aarch32.cpp
new file mode 100644
index 000000000000..a1bc4c853323
--- /dev/null
+++ b/llvm/lib/ExecutionEngine/JITLink/ELF_aarch32.cpp
@@ -0,0 +1,311 @@
+//===----- ELF_aarch32.cpp - JIT linker implementation for arm/thumb ------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+// ELF/aarch32 jit-link implementation.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ExecutionEngine/JITLink/ELF_aarch32.h"
+
+#include "llvm/BinaryFormat/ELF.h"
+#include "llvm/ExecutionEngine/JITLink/JITLink.h"
+#include "llvm/ExecutionEngine/JITLink/aarch32.h"
+#include "llvm/Object/ELF.h"
+#include "llvm/Object/ELFObjectFile.h"
+#include "llvm/Support/Endian.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/TargetParser/ARMTargetParser.h"
+
+#include "ELFLinkGraphBuilder.h"
+#include "JITLinkGeneric.h"
+
+#define DEBUG_TYPE "jitlink"
+
+using namespace llvm::object;
+
+namespace llvm {
+namespace jitlink {
+
+/// Translate from ELF relocation type to JITLink-internal edge kind.
+Expected<aarch32::EdgeKind_aarch32> getJITLinkEdgeKind(uint32_t ELFType) {
+ switch (ELFType) {
+ case ELF::R_ARM_ABS32:
+ return aarch32::Data_Pointer32;
+ case ELF::R_ARM_REL32:
+ return aarch32::Data_Delta32;
+ case ELF::R_ARM_CALL:
+ return aarch32::Arm_Call;
+ case ELF::R_ARM_THM_CALL:
+ return aarch32::Thumb_Call;
+ case ELF::R_ARM_THM_JUMP24:
+ return aarch32::Thumb_Jump24;
+ case ELF::R_ARM_THM_MOVW_ABS_NC:
+ return aarch32::Thumb_MovwAbsNC;
+ case ELF::R_ARM_THM_MOVT_ABS:
+ return aarch32::Thumb_MovtAbs;
+ }
+
+ return make_error<JITLinkError>(
+ "Unsupported aarch32 relocation " + formatv("{0:d}: ", ELFType) +
+ object::getELFRelocationTypeName(ELF::EM_ARM, ELFType));
+}
+
+/// Translate from JITLink-internal edge kind back to ELF relocation type.
+Expected<uint32_t> getELFRelocationType(Edge::Kind Kind) {
+ switch (static_cast<aarch32::EdgeKind_aarch32>(Kind)) {
+ case aarch32::Data_Delta32:
+ return ELF::R_ARM_REL32;
+ case aarch32::Data_Pointer32:
+ return ELF::R_ARM_ABS32;
+ case aarch32::Arm_Call:
+ return ELF::R_ARM_CALL;
+ case aarch32::Thumb_Call:
+ return ELF::R_ARM_THM_CALL;
+ case aarch32::Thumb_Jump24:
+ return ELF::R_ARM_THM_JUMP24;
+ case aarch32::Thumb_MovwAbsNC:
+ return ELF::R_ARM_THM_MOVW_ABS_NC;
+ case aarch32::Thumb_MovtAbs:
+ return ELF::R_ARM_THM_MOVT_ABS;
+ }
+
+ return make_error<JITLinkError>(formatv("Invalid aarch32 edge {0:d}: ",
+ Kind));
+}
+
+/// Get a human-readable name for the given ELF AArch32 edge kind.
+const char *getELFAArch32EdgeKindName(Edge::Kind R) {
+ // No ELF-specific edge kinds yet
+ return aarch32::getEdgeKindName(R);
+}
+
+class ELFJITLinker_aarch32 : public JITLinker<ELFJITLinker_aarch32> {
+ friend class JITLinker<ELFJITLinker_aarch32>;
+
+public:
+ ELFJITLinker_aarch32(std::unique_ptr<JITLinkContext> Ctx,
+ std::unique_ptr<LinkGraph> G, PassConfiguration PassCfg,
+ aarch32::ArmConfig ArmCfg)
+ : JITLinker(std::move(Ctx), std::move(G), std::move(PassCfg)),
+ ArmCfg(std::move(ArmCfg)) {}
+
+private:
+ aarch32::ArmConfig ArmCfg;
+
+ Error applyFixup(LinkGraph &G, Block &B, const Edge &E) const {
+ return aarch32::applyFixup(G, B, E, ArmCfg);
+ }
+};
+
+template <support::endianness DataEndianness>
+class ELFLinkGraphBuilder_aarch32
+ : public ELFLinkGraphBuilder<ELFType<DataEndianness, false>> {
+private:
+ using ELFT = ELFType<DataEndianness, false>;
+ using Base = ELFLinkGraphBuilder<ELFT>;
+
+ bool excludeSection(const typename ELFT::Shdr &Sect) const override {
+ // TODO: An .ARM.exidx (Exception Index table) entry is 8-bytes in size and
+ // consists of 2 words. It might be sufficient to process only relocations
+ // in the the second word (offset 4). Please find more details in: Exception
+ // Handling ABI for the Arm® Architecture -> Index table entries
+ if (Sect.sh_type == ELF::SHT_ARM_EXIDX)
+ return true;
+ return false;
+ }
+
+ Error addRelocations() override {
+ LLVM_DEBUG(dbgs() << "Processing relocations:\n");
+ using Self = ELFLinkGraphBuilder_aarch32<DataEndianness>;
+ for (const auto &RelSect : Base::Sections) {
+ if (Error Err = Base::forEachRelRelocation(RelSect, this,
+ &Self::addSingleRelRelocation))
+ return Err;
+ }
+ return Error::success();
+ }
+
+ Error addSingleRelRelocation(const typename ELFT::Rel &Rel,
+ const typename ELFT::Shdr &FixupSect,
+ Block &BlockToFix) {
+ uint32_t SymbolIndex = Rel.getSymbol(false);
+ auto ObjSymbol = Base::Obj.getRelocationSymbol(Rel, Base::SymTabSec);
+ if (!ObjSymbol)
+ return ObjSymbol.takeError();
+
+ Symbol *GraphSymbol = Base::getGraphSymbol(SymbolIndex);
+ if (!GraphSymbol)
+ return make_error<StringError>(
+ formatv("Could not find symbol at given index, did you add it to "
+ "JITSymbolTable? index: {0}, shndx: {1} Size of table: {2}",
+ SymbolIndex, (*ObjSymbol)->st_shndx,
+ Base::GraphSymbols.size()),
+ inconvertibleErrorCode());
+
+ uint32_t Type = Rel.getType(false);
+ Expected<aarch32::EdgeKind_aarch32> Kind = getJITLinkEdgeKind(Type);
+ if (!Kind)
+ return Kind.takeError();
+
+ auto FixupAddress = orc::ExecutorAddr(FixupSect.sh_addr) + Rel.r_offset;
+ Edge::OffsetT Offset = FixupAddress - BlockToFix.getAddress();
+ Edge E(*Kind, Offset, *GraphSymbol, 0);
+
+ Expected<int64_t> Addend =
+ aarch32::readAddend(*Base::G, BlockToFix, E, ArmCfg);
+ if (!Addend)
+ return Addend.takeError();
+
+ E.setAddend(*Addend);
+ LLVM_DEBUG({
+ dbgs() << " ";
+ printEdge(dbgs(), BlockToFix, E, getELFAArch32EdgeKindName(*Kind));
+ dbgs() << "\n";
+ });
+
+ BlockToFix.addEdge(std::move(E));
+ return Error::success();
+ }
+
+ aarch32::ArmConfig ArmCfg;
+
+protected:
+ TargetFlagsType makeTargetFlags(const typename ELFT::Sym &Sym) override {
+ if (Sym.getValue() & 0x01)
+ return aarch32::ThumbSymbol;
+ return TargetFlagsType{};
+ }
+
+ orc::ExecutorAddrDiff getRawOffset(const typename ELFT::Sym &Sym,
+ TargetFlagsType Flags) override {
+ assert((makeTargetFlags(Sym) & Flags) == Flags);
+ static constexpr uint64_t ThumbBit = 0x01;
+ return Sym.getValue() & ~ThumbBit;
+ }
+
+public:
+ ELFLinkGraphBuilder_aarch32(StringRef FileName,
+ const llvm::object::ELFFile<ELFT> &Obj, Triple TT,
+ SubtargetFeatures Features,
+ aarch32::ArmConfig ArmCfg)
+ : ELFLinkGraphBuilder<ELFT>(Obj, std::move(TT), std::move(Features),
+ FileName, getELFAArch32EdgeKindName),
+ ArmCfg(std::move(ArmCfg)) {}
+};
+
+template <aarch32::StubsFlavor Flavor>
+Error buildTables_ELF_aarch32(LinkGraph &G) {
+ LLVM_DEBUG(dbgs() << "Visiting edges in graph:\n");
+
+ aarch32::StubsManager<Flavor> PLT;
+ visitExistingEdges(G, PLT);
+ return Error::success();
+}
+
+Expected<std::unique_ptr<LinkGraph>>
+createLinkGraphFromELFObject_aarch32(MemoryBufferRef ObjectBuffer) {
+ LLVM_DEBUG({
+ dbgs() << "Building jitlink graph for new input "
+ << ObjectBuffer.getBufferIdentifier() << "...\n";
+ });
+
+ auto ELFObj = ObjectFile::createELFObjectFile(ObjectBuffer);
+ if (!ELFObj)
+ return ELFObj.takeError();
+
+ auto Features = (*ELFObj)->getFeatures();
+ if (!Features)
+ return Features.takeError();
+
+ // Find out what exact AArch32 instruction set and features we target.
+ auto TT = (*ELFObj)->makeTriple();
+ ARM::ArchKind AK = ARM::parseArch(TT.getArchName());
+ if (AK == ARM::ArchKind::INVALID)
+ return make_error<JITLinkError>(
+ "Failed to build ELF link graph: Invalid ARM ArchKind");
+
+ // Resolve our internal configuration for the target. If at some point the
+ // CPUArch alone becomes too unprecise, we can find more details in the
+ // Tag_CPU_arch_profile.
+ aarch32::ArmConfig ArmCfg;
+ using namespace ARMBuildAttrs;
+ auto Arch = static_cast<CPUArch>(ARM::getArchAttr(AK));
+ switch (Arch) {
+ case v7:
+ case v8_A:
+ ArmCfg = aarch32::getArmConfigForCPUArch(Arch);
+ assert(ArmCfg.Stubs != aarch32::Unsupported &&
+ "Provide a config for each supported CPU");
+ break;
+ default:
+ return make_error<JITLinkError>(
+ "Failed to build ELF link graph: Unsupported CPU arch " +
+ StringRef(aarch32::getCPUArchName(Arch)));
+ }
+
+ // Populate the link-graph.
+ switch (TT.getArch()) {
+ case Triple::arm:
+ case Triple::thumb: {
+ auto &ELFFile = cast<ELFObjectFile<ELF32LE>>(**ELFObj).getELFFile();
+ return ELFLinkGraphBuilder_aarch32<support::little>(
+ (*ELFObj)->getFileName(), ELFFile, TT, std::move(*Features),
+ ArmCfg)
+ .buildGraph();
+ }
+ case Triple::armeb:
+ case Triple::thumbeb: {
+ auto &ELFFile = cast<ELFObjectFile<ELF32BE>>(**ELFObj).getELFFile();
+ return ELFLinkGraphBuilder_aarch32<support::big>(
+ (*ELFObj)->getFileName(), ELFFile, TT, std::move(*Features),
+ ArmCfg)
+ .buildGraph();
+ }
+ default:
+ return make_error<JITLinkError>(
+ "Failed to build ELF/aarch32 link graph: Invalid target triple " +
+ TT.getTriple());
+ }
+}
+
+void link_ELF_aarch32(std::unique_ptr<LinkGraph> G,
+ std::unique_ptr<JITLinkContext> Ctx) {
+ const Triple &TT = G->getTargetTriple();
+
+ using namespace ARMBuildAttrs;
+ ARM::ArchKind AK = ARM::parseArch(TT.getArchName());
+ auto CPU = static_cast<CPUArch>(ARM::getArchAttr(AK));
+ aarch32::ArmConfig ArmCfg = aarch32::getArmConfigForCPUArch(CPU);
+
+ PassConfiguration PassCfg;
+ if (Ctx->shouldAddDefaultTargetPasses(TT)) {
+ // Add a mark-live pass.
+ if (auto MarkLive = Ctx->getMarkLivePass(TT))
+ PassCfg.PrePrunePasses.push_back(std::move(MarkLive));
+ else
+ PassCfg.PrePrunePasses.push_back(markAllSymbolsLive);
+
+ switch (ArmCfg.Stubs) {
+ case aarch32::Thumbv7:
+ PassCfg.PostPrunePasses.push_back(
+ buildTables_ELF_aarch32<aarch32::Thumbv7>);
+ break;
+ case aarch32::Unsupported:
+ llvm_unreachable("Check before building graph");
+ }
+ }
+
+ if (auto Err = Ctx->modifyPassConfig(*G, PassCfg))
+ return Ctx->notifyFailed(std::move(Err));
+
+ ELFJITLinker_aarch32::link(std::move(Ctx), std::move(G), std::move(PassCfg),
+ std::move(ArmCfg));
+}
+
+} // namespace jitlink
+} // namespace llvm
diff --git a/llvm/lib/ExecutionEngine/JITLink/ELF_aarch64.cpp b/llvm/lib/ExecutionEngine/JITLink/ELF_aarch64.cpp
index 567d5a4dd47a..652eb931190e 100644
--- a/llvm/lib/ExecutionEngine/JITLink/ELF_aarch64.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/ELF_aarch64.cpp
@@ -47,6 +47,7 @@ class ELFLinkGraphBuilder_aarch64 : public ELFLinkGraphBuilder<ELFT> {
private:
enum ELFAArch64RelocationKind : Edge::Kind {
ELFCall26 = Edge::FirstRelocation,
+ ELFAdrLo21,
ELFAdrPage21,
ELFAddAbs12,
ELFLdSt8Abs12,
@@ -58,6 +59,9 @@ private:
ELFMovwAbsG1,
ELFMovwAbsG2,
ELFMovwAbsG3,
+ ELFTstBr14,
+ ELFCondBr19,
+ ELFAbs32,
ELFAbs64,
ELFPrel32,
ELFPrel64,
@@ -76,6 +80,8 @@ private:
case ELF::R_AARCH64_CALL26:
case ELF::R_AARCH64_JUMP26:
return ELFCall26;
+ case ELF::R_AARCH64_ADR_PREL_LO21:
+ return ELFAdrLo21;
case ELF::R_AARCH64_ADR_PREL_PG_HI21:
return ELFAdrPage21;
case ELF::R_AARCH64_ADD_ABS_LO12_NC:
@@ -98,6 +104,12 @@ private:
return ELFMovwAbsG2;
case ELF::R_AARCH64_MOVW_UABS_G3:
return ELFMovwAbsG3;
+ case ELF::R_AARCH64_TSTBR14:
+ return ELFTstBr14;
+ case ELF::R_AARCH64_CONDBR19:
+ return ELFCondBr19;
+ case ELF::R_AARCH64_ABS32:
+ return ELFAbs32;
case ELF::R_AARCH64_ABS64:
return ELFAbs64;
case ELF::R_AARCH64_PREL32:
@@ -177,6 +189,15 @@ private:
Kind = aarch64::Branch26PCRel;
break;
}
+ case ELFAdrLo21: {
+ uint32_t Instr = *(const ulittle32_t *)FixupContent;
+ if (!aarch64::isADR(Instr))
+ return make_error<JITLinkError>(
+ "R_AARCH64_ADR_PREL_LO21 target is not an ADR instruction");
+
+ Kind = aarch64::ADRLiteral21;
+ break;
+ }
case ELFAdrPage21: {
Kind = aarch64::Page21;
break;
@@ -284,6 +305,29 @@ private:
Kind = aarch64::MoveWide16;
break;
}
+ case ELFTstBr14: {
+ uint32_t Instr = *(const ulittle32_t *)FixupContent;
+ if (!aarch64::isTestAndBranchImm14(Instr))
+ return make_error<JITLinkError>("R_AARCH64_TSTBR14 target is not a "
+ "test and branch instruction");
+
+ Kind = aarch64::TestAndBranch14PCRel;
+ break;
+ }
+ case ELFCondBr19: {
+ uint32_t Instr = *(const ulittle32_t *)FixupContent;
+ if (!aarch64::isCondBranchImm19(Instr) &&
+ !aarch64::isCompAndBranchImm19(Instr))
+ return make_error<JITLinkError>("R_AARCH64_CONDBR19 target is not a "
+ "conditional branch instruction");
+
+ Kind = aarch64::CondBranch19PCRel;
+ break;
+ }
+ case ELFAbs32: {
+ Kind = aarch64::Pointer32;
+ break;
+ }
case ELFAbs64: {
Kind = aarch64::Pointer64;
break;
@@ -357,6 +401,8 @@ private:
return "ELFMovwAbsG2";
case ELFMovwAbsG3:
return "ELFMovwAbsG3";
+ case ELFAbs32:
+ return "ELFAbs32";
case ELFAbs64:
return "ELFAbs64";
case ELFPrel32:
@@ -382,9 +428,10 @@ private:
public:
ELFLinkGraphBuilder_aarch64(StringRef FileName,
- const object::ELFFile<ELFT> &Obj, const Triple T)
- : ELFLinkGraphBuilder<ELFT>(Obj, std::move(T), FileName,
- aarch64::getEdgeKindName) {}
+ const object::ELFFile<ELFT> &Obj, Triple TT,
+ SubtargetFeatures Features)
+ : ELFLinkGraphBuilder<ELFT>(Obj, std::move(TT), std::move(Features),
+ FileName, aarch64::getEdgeKindName) {}
};
// TLS Info Builder.
@@ -532,13 +579,17 @@ createLinkGraphFromELFObject_aarch64(MemoryBufferRef ObjectBuffer) {
if (!ELFObj)
return ELFObj.takeError();
+ auto Features = (*ELFObj)->getFeatures();
+ if (!Features)
+ return Features.takeError();
+
assert((*ELFObj)->getArch() == Triple::aarch64 &&
"Only AArch64 (little endian) is supported for now");
auto &ELFObjFile = cast<object::ELFObjectFile<object::ELF64LE>>(**ELFObj);
- return ELFLinkGraphBuilder_aarch64<object::ELF64LE>((*ELFObj)->getFileName(),
- ELFObjFile.getELFFile(),
- (*ELFObj)->makeTriple())
+ return ELFLinkGraphBuilder_aarch64<object::ELF64LE>(
+ (*ELFObj)->getFileName(), ELFObjFile.getELFFile(),
+ (*ELFObj)->makeTriple(), std::move(*Features))
.buildGraph();
}
@@ -552,6 +603,7 @@ void link_ELF_aarch64(std::unique_ptr<LinkGraph> G,
Config.PrePrunePasses.push_back(EHFrameEdgeFixer(
".eh_frame", 8, aarch64::Pointer32, aarch64::Pointer64,
aarch64::Delta32, aarch64::Delta64, aarch64::NegDelta32));
+ Config.PrePrunePasses.push_back(EHFrameNullTerminator(".eh_frame"));
// Add a mark-live pass.
if (auto MarkLive = Ctx->getMarkLivePass(TT))
diff --git a/llvm/lib/ExecutionEngine/JITLink/ELF_i386.cpp b/llvm/lib/ExecutionEngine/JITLink/ELF_i386.cpp
index 1fee1b24b6bd..860165365a7e 100644
--- a/llvm/lib/ExecutionEngine/JITLink/ELF_i386.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/ELF_i386.cpp
@@ -30,7 +30,8 @@ Error buildTables_ELF_i386(LinkGraph &G) {
LLVM_DEBUG(dbgs() << "Visiting edges in graph:\n");
i386::GOTTableManager GOT;
- visitExistingEdges(G, GOT);
+ i386::PLTTableManager PLT(GOT);
+ visitExistingEdges(G, GOT, PLT);
return Error::success();
}
} // namespace
@@ -130,6 +131,8 @@ private:
return EdgeKind_i386::Delta32;
case ELF::R_386_GOTOFF:
return EdgeKind_i386::Delta32FromGOT;
+ case ELF::R_386_PLT32:
+ return EdgeKind_i386::BranchPCRel32;
}
return make_error<JITLinkError>("Unsupported i386 relocation:" +
@@ -207,9 +210,9 @@ private:
public:
ELFLinkGraphBuilder_i386(StringRef FileName, const object::ELFFile<ELFT> &Obj,
- const Triple T)
- : ELFLinkGraphBuilder<ELFT>(Obj, std::move(T), FileName,
- i386::getEdgeKindName) {}
+ Triple TT, SubtargetFeatures Features)
+ : ELFLinkGraphBuilder<ELFT>(Obj, std::move(TT), std::move(Features),
+ FileName, i386::getEdgeKindName) {}
};
Expected<std::unique_ptr<LinkGraph>>
@@ -223,13 +226,17 @@ createLinkGraphFromELFObject_i386(MemoryBufferRef ObjectBuffer) {
if (!ELFObj)
return ELFObj.takeError();
+ auto Features = (*ELFObj)->getFeatures();
+ if (!Features)
+ return Features.takeError();
+
assert((*ELFObj)->getArch() == Triple::x86 &&
"Only i386 (little endian) is supported for now");
auto &ELFObjFile = cast<object::ELFObjectFile<object::ELF32LE>>(**ELFObj);
- return ELFLinkGraphBuilder_i386<object::ELF32LE>((*ELFObj)->getFileName(),
- ELFObjFile.getELFFile(),
- (*ELFObj)->makeTriple())
+ return ELFLinkGraphBuilder_i386<object::ELF32LE>(
+ (*ELFObj)->getFileName(), ELFObjFile.getELFFile(),
+ (*ELFObj)->makeTriple(), std::move(*Features))
.buildGraph();
}
@@ -243,8 +250,11 @@ void link_ELF_i386(std::unique_ptr<LinkGraph> G,
else
Config.PrePrunePasses.push_back(markAllSymbolsLive);
- // Add an in-place GOT build pass.
+ // Add an in-place GOT and PLT build pass.
Config.PostPrunePasses.push_back(buildTables_ELF_i386);
+
+ // Add GOT/Stubs optimizer pass.
+ Config.PreFixupPasses.push_back(i386::optimizeGOTAndStubAccesses);
}
if (auto Err = Ctx->modifyPassConfig(*G, Config))
return Ctx->notifyFailed(std::move(Err));
diff --git a/llvm/lib/ExecutionEngine/JITLink/ELF_loongarch.cpp b/llvm/lib/ExecutionEngine/JITLink/ELF_loongarch.cpp
index cd70217b4c0a..7f76b45aecbb 100644
--- a/llvm/lib/ExecutionEngine/JITLink/ELF_loongarch.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/ELF_loongarch.cpp
@@ -129,10 +129,10 @@ private:
public:
ELFLinkGraphBuilder_loongarch(StringRef FileName,
- const object::ELFFile<ELFT> &Obj,
- const Triple T)
- : ELFLinkGraphBuilder<ELFT>(Obj, std::move(T), FileName,
- loongarch::getEdgeKindName) {}
+ const object::ELFFile<ELFT> &Obj, Triple TT,
+ SubtargetFeatures Features)
+ : ELFLinkGraphBuilder<ELFT>(Obj, std::move(TT), std::move(Features),
+ FileName, loongarch::getEdgeKindName) {}
};
Error buildTables_ELF_loongarch(LinkGraph &G) {
@@ -160,11 +160,15 @@ createLinkGraphFromELFObject_loongarch(MemoryBufferRef ObjectBuffer) {
if (!ELFObj)
return ELFObj.takeError();
+ auto Features = (*ELFObj)->getFeatures();
+ if (!Features)
+ return Features.takeError();
+
if ((*ELFObj)->getArch() == Triple::loongarch64) {
auto &ELFObjFile = cast<object::ELFObjectFile<object::ELF64LE>>(**ELFObj);
return ELFLinkGraphBuilder_loongarch<object::ELF64LE>(
(*ELFObj)->getFileName(), ELFObjFile.getELFFile(),
- (*ELFObj)->makeTriple())
+ (*ELFObj)->makeTriple(), std::move(*Features))
.buildGraph();
}
@@ -173,7 +177,7 @@ createLinkGraphFromELFObject_loongarch(MemoryBufferRef ObjectBuffer) {
auto &ELFObjFile = cast<object::ELFObjectFile<object::ELF32LE>>(**ELFObj);
return ELFLinkGraphBuilder_loongarch<object::ELF32LE>(
(*ELFObj)->getFileName(), ELFObjFile.getELFFile(),
- (*ELFObj)->makeTriple())
+ (*ELFObj)->makeTriple(), std::move(*Features))
.buildGraph();
}
diff --git a/llvm/lib/ExecutionEngine/JITLink/ELF_ppc64.cpp b/llvm/lib/ExecutionEngine/JITLink/ELF_ppc64.cpp
new file mode 100644
index 000000000000..a30b9ce51c84
--- /dev/null
+++ b/llvm/lib/ExecutionEngine/JITLink/ELF_ppc64.cpp
@@ -0,0 +1,396 @@
+//===------- ELF_ppc64.cpp -JIT linker implementation for ELF/ppc64 -------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+// ELF/ppc64 jit-link implementation.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ExecutionEngine/JITLink/ELF_ppc64.h"
+#include "llvm/ExecutionEngine/JITLink/DWARFRecordSectionSplitter.h"
+#include "llvm/ExecutionEngine/JITLink/TableManager.h"
+#include "llvm/ExecutionEngine/JITLink/ppc64.h"
+#include "llvm/Object/ELFObjectFile.h"
+#include "llvm/Support/Endian.h"
+
+#include "EHFrameSupportImpl.h"
+#include "ELFLinkGraphBuilder.h"
+#include "JITLinkGeneric.h"
+
+#define DEBUG_TYPE "jitlink"
+
+namespace {
+
+using namespace llvm;
+using namespace llvm::jitlink;
+
+constexpr StringRef ELFTOCSymbolName = ".TOC.";
+constexpr StringRef TOCSymbolAliasIdent = "__TOC__";
+constexpr uint64_t ELFTOCBaseOffset = 0x8000;
+
+template <support::endianness Endianness>
+Symbol &createELFGOTHeader(LinkGraph &G,
+ ppc64::TOCTableManager<Endianness> &TOC) {
+ Symbol *TOCSymbol = nullptr;
+
+ for (Symbol *Sym : G.defined_symbols())
+ if (LLVM_UNLIKELY(Sym->getName() == ELFTOCSymbolName)) {
+ TOCSymbol = Sym;
+ break;
+ }
+
+ if (LLVM_LIKELY(TOCSymbol == nullptr)) {
+ for (Symbol *Sym : G.external_symbols())
+ if (Sym->getName() == ELFTOCSymbolName) {
+ TOCSymbol = Sym;
+ break;
+ }
+ }
+
+ if (!TOCSymbol)
+ TOCSymbol = &G.addExternalSymbol(ELFTOCSymbolName, 0, false);
+
+ return TOC.getEntryForTarget(G, *TOCSymbol);
+}
+
+// Register preexisting GOT entries with TOC table manager.
+template <support::endianness Endianness>
+inline void
+registerExistingGOTEntries(LinkGraph &G,
+ ppc64::TOCTableManager<Endianness> &TOC) {
+ auto isGOTEntry = [](const Edge &E) {
+ return E.getKind() == ppc64::Pointer64 && E.getTarget().isExternal();
+ };
+ if (Section *dotTOCSection = G.findSectionByName(".toc")) {
+ for (Block *B : dotTOCSection->blocks())
+ for (Edge &E : B->edges())
+ if (isGOTEntry(E))
+ TOC.registerPreExistingEntry(E.getTarget(),
+ G.addAnonymousSymbol(*B, E.getOffset(),
+ G.getPointerSize(),
+ false, false));
+ }
+}
+
+template <support::endianness Endianness>
+Error buildTables_ELF_ppc64(LinkGraph &G) {
+ LLVM_DEBUG(dbgs() << "Visiting edges in graph:\n");
+ ppc64::TOCTableManager<Endianness> TOC;
+ // Before visiting edges, we create a header containing the address of TOC
+ // base as ELFABIv2 suggests:
+ // > The GOT consists of an 8-byte header that contains the TOC base (the
+ // first TOC base when multiple TOCs are present), followed by an array of
+ // 8-byte addresses.
+ createELFGOTHeader(G, TOC);
+
+ // There might be compiler-generated GOT entries in ELF relocatable file.
+ registerExistingGOTEntries(G, TOC);
+
+ ppc64::PLTTableManager<Endianness> PLT(TOC);
+ visitExistingEdges(G, TOC, PLT);
+ // TODO: Add TLS support.
+
+ // After visiting edges in LinkGraph, we have GOT entries built in the
+ // synthesized section.
+ // Merge sections included in TOC into synthesized TOC section,
+ // thus TOC is compact and reducing chances of relocation
+ // overflow.
+ if (Section *TOCSection = G.findSectionByName(TOC.getSectionName())) {
+ // .got and .plt are not normally present in a relocatable object file
+ // because they are linker generated.
+ if (Section *gotSection = G.findSectionByName(".got"))
+ G.mergeSections(*TOCSection, *gotSection);
+ if (Section *tocSection = G.findSectionByName(".toc"))
+ G.mergeSections(*TOCSection, *tocSection);
+ if (Section *sdataSection = G.findSectionByName(".sdata"))
+ G.mergeSections(*TOCSection, *sdataSection);
+ if (Section *sbssSection = G.findSectionByName(".sbss"))
+ G.mergeSections(*TOCSection, *sbssSection);
+ // .tocbss no longer appears in ELFABIv2. Leave it here to be compatible
+ // with rtdyld.
+ if (Section *tocbssSection = G.findSectionByName(".tocbss"))
+ G.mergeSections(*TOCSection, *tocbssSection);
+ if (Section *pltSection = G.findSectionByName(".plt"))
+ G.mergeSections(*TOCSection, *pltSection);
+ }
+
+ return Error::success();
+}
+
+} // namespace
+
+namespace llvm::jitlink {
+
+template <support::endianness Endianness>
+class ELFLinkGraphBuilder_ppc64
+ : public ELFLinkGraphBuilder<object::ELFType<Endianness, true>> {
+private:
+ using ELFT = object::ELFType<Endianness, true>;
+ using Base = ELFLinkGraphBuilder<ELFT>;
+
+ using Base::G; // Use LinkGraph pointer from base class.
+
+ Error addRelocations() override {
+ LLVM_DEBUG(dbgs() << "Processing relocations:\n");
+
+ using Self = ELFLinkGraphBuilder_ppc64<Endianness>;
+ for (const auto &RelSect : Base::Sections) {
+ // Validate the section to read relocation entries from.
+ if (RelSect.sh_type == ELF::SHT_REL)
+ return make_error<StringError>("No SHT_REL in valid " +
+ G->getTargetTriple().getArchName() +
+ " ELF object files",
+ inconvertibleErrorCode());
+
+ if (Error Err = Base::forEachRelaRelocation(RelSect, this,
+ &Self::addSingleRelocation))
+ return Err;
+ }
+
+ return Error::success();
+ }
+
+ Error addSingleRelocation(const typename ELFT::Rela &Rel,
+ const typename ELFT::Shdr &FixupSection,
+ Block &BlockToFix) {
+ using Base = ELFLinkGraphBuilder<ELFT>;
+ auto ELFReloc = Rel.getType(false);
+
+ // R_PPC64_NONE is a no-op.
+ if (LLVM_UNLIKELY(ELFReloc == ELF::R_PPC64_NONE))
+ return Error::success();
+
+ auto ObjSymbol = Base::Obj.getRelocationSymbol(Rel, Base::SymTabSec);
+ if (!ObjSymbol)
+ return ObjSymbol.takeError();
+
+ uint32_t SymbolIndex = Rel.getSymbol(false);
+ Symbol *GraphSymbol = Base::getGraphSymbol(SymbolIndex);
+ if (!GraphSymbol)
+ return make_error<StringError>(
+ formatv("Could not find symbol at given index, did you add it to "
+ "JITSymbolTable? index: {0}, shndx: {1} Size of table: {2}",
+ SymbolIndex, (*ObjSymbol)->st_shndx,
+ Base::GraphSymbols.size()),
+ inconvertibleErrorCode());
+
+ int64_t Addend = Rel.r_addend;
+ orc::ExecutorAddr FixupAddress =
+ orc::ExecutorAddr(FixupSection.sh_addr) + Rel.r_offset;
+ Edge::OffsetT Offset = FixupAddress - BlockToFix.getAddress();
+ Edge::Kind Kind = Edge::Invalid;
+
+ switch (ELFReloc) {
+ default:
+ return make_error<JITLinkError>(
+ "In " + G->getName() + ": Unsupported ppc64 relocation type " +
+ object::getELFRelocationTypeName(ELF::EM_PPC64, ELFReloc));
+ case ELF::R_PPC64_ADDR64:
+ Kind = ppc64::Pointer64;
+ break;
+ case ELF::R_PPC64_TOC16_HA:
+ Kind = ppc64::TOCDelta16HA;
+ break;
+ case ELF::R_PPC64_TOC16_DS:
+ Kind = ppc64::TOCDelta16DS;
+ break;
+ case ELF::R_PPC64_TOC16_LO:
+ Kind = ppc64::TOCDelta16LO;
+ break;
+ case ELF::R_PPC64_TOC16_LO_DS:
+ Kind = ppc64::TOCDelta16LODS;
+ break;
+ case ELF::R_PPC64_REL16:
+ Kind = ppc64::Delta16;
+ break;
+ case ELF::R_PPC64_REL16_HA:
+ Kind = ppc64::Delta16HA;
+ break;
+ case ELF::R_PPC64_REL16_LO:
+ Kind = ppc64::Delta16LO;
+ break;
+ case ELF::R_PPC64_REL32:
+ Kind = ppc64::Delta32;
+ break;
+ case ELF::R_PPC64_REL24_NOTOC:
+ case ELF::R_PPC64_REL24: {
+ bool isLocal = !GraphSymbol->isExternal();
+ if (isLocal) {
+ // TODO: There are cases a local function call need a call stub.
+ // 1. Caller uses TOC, the callee doesn't, need a r2 save stub.
+ // 2. Caller doesn't use TOC, the callee does, need a r12 setup stub.
+ // FIXME: For a local call, we might need a thunk if branch target is
+ // out of range.
+ Kind = ppc64::CallBranchDelta;
+ // Branch to local entry.
+ Addend += ELF::decodePPC64LocalEntryOffset((*ObjSymbol)->st_other);
+ } else {
+ Kind = ELFReloc == ELF::R_PPC64_REL24 ? ppc64::RequestPLTCallStubSaveTOC
+ : ppc64::RequestPLTCallStubNoTOC;
+ }
+ break;
+ }
+ case ELF::R_PPC64_REL64:
+ Kind = ppc64::Delta64;
+ break;
+ }
+
+ Edge GE(Kind, Offset, *GraphSymbol, Addend);
+ BlockToFix.addEdge(std::move(GE));
+ return Error::success();
+ }
+
+public:
+ ELFLinkGraphBuilder_ppc64(StringRef FileName,
+ const object::ELFFile<ELFT> &Obj, Triple TT,
+ SubtargetFeatures Features)
+ : ELFLinkGraphBuilder<ELFT>(Obj, std::move(TT), std::move(Features),
+ FileName, ppc64::getEdgeKindName) {}
+};
+
+template <support::endianness Endianness>
+class ELFJITLinker_ppc64 : public JITLinker<ELFJITLinker_ppc64<Endianness>> {
+ using JITLinkerBase = JITLinker<ELFJITLinker_ppc64<Endianness>>;
+ friend JITLinkerBase;
+
+public:
+ ELFJITLinker_ppc64(std::unique_ptr<JITLinkContext> Ctx,
+ std::unique_ptr<LinkGraph> G, PassConfiguration PassConfig)
+ : JITLinkerBase(std::move(Ctx), std::move(G), std::move(PassConfig)) {
+ JITLinkerBase::getPassConfig().PostAllocationPasses.push_back(
+ [this](LinkGraph &G) { return defineTOCBase(G); });
+ }
+
+private:
+ Symbol *TOCSymbol = nullptr;
+
+ Error defineTOCBase(LinkGraph &G) {
+ for (Symbol *Sym : G.defined_symbols()) {
+ if (LLVM_UNLIKELY(Sym->getName() == ELFTOCSymbolName)) {
+ TOCSymbol = Sym;
+ return Error::success();
+ }
+ }
+
+ assert(TOCSymbol == nullptr &&
+ "TOCSymbol should not be defined at this point");
+
+ for (Symbol *Sym : G.external_symbols()) {
+ if (Sym->getName() == ELFTOCSymbolName) {
+ TOCSymbol = Sym;
+ break;
+ }
+ }
+
+ if (Section *TOCSection = G.findSectionByName(
+ ppc64::TOCTableManager<Endianness>::getSectionName())) {
+ assert(!TOCSection->empty() && "TOC section should have reserved an "
+ "entry for containing the TOC base");
+
+ SectionRange SR(*TOCSection);
+ orc::ExecutorAddr TOCBaseAddr(SR.getFirstBlock()->getAddress() +
+ ELFTOCBaseOffset);
+ assert(TOCSymbol && TOCSymbol->isExternal() &&
+ ".TOC. should be a external symbol at this point");
+ G.makeAbsolute(*TOCSymbol, TOCBaseAddr);
+ // Create an alias of .TOC. so that rtdyld checker can recognize.
+ G.addAbsoluteSymbol(TOCSymbolAliasIdent, TOCSymbol->getAddress(),
+ TOCSymbol->getSize(), TOCSymbol->getLinkage(),
+ TOCSymbol->getScope(), TOCSymbol->isLive());
+ return Error::success();
+ }
+
+ // If TOC section doesn't exist, which means no TOC relocation is found, we
+ // don't need a TOCSymbol.
+ return Error::success();
+ }
+
+ Error applyFixup(LinkGraph &G, Block &B, const Edge &E) const {
+ return ppc64::applyFixup<Endianness>(G, B, E, TOCSymbol);
+ }
+};
+
+template <support::endianness Endianness>
+Expected<std::unique_ptr<LinkGraph>>
+createLinkGraphFromELFObject_ppc64(MemoryBufferRef ObjectBuffer) {
+ LLVM_DEBUG({
+ dbgs() << "Building jitlink graph for new input "
+ << ObjectBuffer.getBufferIdentifier() << "...\n";
+ });
+
+ auto ELFObj = object::ObjectFile::createELFObjectFile(ObjectBuffer);
+ if (!ELFObj)
+ return ELFObj.takeError();
+
+ auto Features = (*ELFObj)->getFeatures();
+ if (!Features)
+ return Features.takeError();
+
+ using ELFT = object::ELFType<Endianness, true>;
+ auto &ELFObjFile = cast<object::ELFObjectFile<ELFT>>(**ELFObj);
+ return ELFLinkGraphBuilder_ppc64<Endianness>(
+ (*ELFObj)->getFileName(), ELFObjFile.getELFFile(),
+ (*ELFObj)->makeTriple(), std::move(*Features))
+ .buildGraph();
+}
+
+template <support::endianness Endianness>
+void link_ELF_ppc64(std::unique_ptr<LinkGraph> G,
+ std::unique_ptr<JITLinkContext> Ctx) {
+ PassConfiguration Config;
+
+ if (Ctx->shouldAddDefaultTargetPasses(G->getTargetTriple())) {
+ // Construct a JITLinker and run the link function.
+
+ // Add eh-frame passses.
+ Config.PrePrunePasses.push_back(DWARFRecordSectionSplitter(".eh_frame"));
+ Config.PrePrunePasses.push_back(EHFrameEdgeFixer(
+ ".eh_frame", G->getPointerSize(), ppc64::Pointer32, ppc64::Pointer64,
+ ppc64::Delta32, ppc64::Delta64, ppc64::NegDelta32));
+ Config.PrePrunePasses.push_back(EHFrameNullTerminator(".eh_frame"));
+
+ // Add a mark-live pass.
+ if (auto MarkLive = Ctx->getMarkLivePass(G->getTargetTriple()))
+ Config.PrePrunePasses.push_back(std::move(MarkLive));
+ else
+ Config.PrePrunePasses.push_back(markAllSymbolsLive);
+ }
+
+ Config.PostPrunePasses.push_back(buildTables_ELF_ppc64<Endianness>);
+
+ if (auto Err = Ctx->modifyPassConfig(*G, Config))
+ return Ctx->notifyFailed(std::move(Err));
+
+ ELFJITLinker_ppc64<Endianness>::link(std::move(Ctx), std::move(G),
+ std::move(Config));
+}
+
+Expected<std::unique_ptr<LinkGraph>>
+createLinkGraphFromELFObject_ppc64(MemoryBufferRef ObjectBuffer) {
+ return createLinkGraphFromELFObject_ppc64<support::big>(
+ std::move(ObjectBuffer));
+}
+
+Expected<std::unique_ptr<LinkGraph>>
+createLinkGraphFromELFObject_ppc64le(MemoryBufferRef ObjectBuffer) {
+ return createLinkGraphFromELFObject_ppc64<support::little>(
+ std::move(ObjectBuffer));
+}
+
+/// jit-link the given object buffer, which must be a ELF ppc64 object file.
+void link_ELF_ppc64(std::unique_ptr<LinkGraph> G,
+ std::unique_ptr<JITLinkContext> Ctx) {
+ return link_ELF_ppc64<support::big>(std::move(G), std::move(Ctx));
+}
+
+/// jit-link the given object buffer, which must be a ELF ppc64le object file.
+void link_ELF_ppc64le(std::unique_ptr<LinkGraph> G,
+ std::unique_ptr<JITLinkContext> Ctx) {
+ return link_ELF_ppc64<support::little>(std::move(G), std::move(Ctx));
+}
+
+} // end namespace llvm::jitlink
diff --git a/llvm/lib/ExecutionEngine/JITLink/ELF_riscv.cpp b/llvm/lib/ExecutionEngine/JITLink/ELF_riscv.cpp
index 90d3bbe6a276..410dd7fedad1 100644
--- a/llvm/lib/ExecutionEngine/JITLink/ELF_riscv.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/ELF_riscv.cpp
@@ -70,13 +70,17 @@ public:
}
void fixPLTEdge(Edge &E, Symbol &PLTStubs) {
- assert(E.getKind() == R_RISCV_CALL_PLT && "Not a R_RISCV_CALL_PLT edge?");
+ assert((E.getKind() == R_RISCV_CALL || E.getKind() == R_RISCV_CALL_PLT ||
+ E.getKind() == CallRelaxable) &&
+ "Not a PLT edge?");
E.setKind(R_RISCV_CALL);
E.setTarget(PLTStubs);
}
bool isExternalBranchEdge(Edge &E) const {
- return E.getKind() == R_RISCV_CALL_PLT;
+ return (E.getKind() == R_RISCV_CALL || E.getKind() == R_RISCV_CALL_PLT ||
+ E.getKind() == CallRelaxable) &&
+ !E.getTarget().isDefined();
}
private:
@@ -229,6 +233,9 @@ private:
(RawInstr & 0xFFF) | Imm20 | Imm10_1 | Imm11 | Imm19_12;
break;
}
+ case CallRelaxable:
+ // Treat as R_RISCV_CALL when the relaxation pass did not run
+ case R_RISCV_CALL_PLT:
case R_RISCV_CALL: {
int64_t Value = E.getTarget().getAddress() + E.getAddend() - FixupAddress;
int64_t Hi = Value + 0x800;
@@ -322,63 +329,52 @@ private:
case R_RISCV_ADD8: {
int64_t Value =
(E.getTarget().getAddress() +
- *(reinterpret_cast<const uint8_t *>(FixupAddress.getValue())) +
- E.getAddend())
+ *(reinterpret_cast<const uint8_t *>(FixupPtr)) + E.getAddend())
.getValue();
*FixupPtr = static_cast<uint8_t>(Value);
break;
}
case R_RISCV_ADD16: {
int64_t Value = (E.getTarget().getAddress() +
- support::endian::read16le(reinterpret_cast<const void *>(
- FixupAddress.getValue())) +
- E.getAddend())
+ support::endian::read16le(FixupPtr) + E.getAddend())
.getValue();
*(little16_t *)FixupPtr = static_cast<uint16_t>(Value);
break;
}
case R_RISCV_ADD32: {
int64_t Value = (E.getTarget().getAddress() +
- support::endian::read32le(reinterpret_cast<const void *>(
- FixupAddress.getValue())) +
- E.getAddend())
+ support::endian::read32le(FixupPtr) + E.getAddend())
.getValue();
*(little32_t *)FixupPtr = static_cast<uint32_t>(Value);
break;
}
case R_RISCV_ADD64: {
int64_t Value = (E.getTarget().getAddress() +
- support::endian::read64le(reinterpret_cast<const void *>(
- FixupAddress.getValue())) +
- E.getAddend())
+ support::endian::read64le(FixupPtr) + E.getAddend())
.getValue();
*(little64_t *)FixupPtr = static_cast<uint64_t>(Value);
break;
}
case R_RISCV_SUB8: {
- int64_t Value =
- *(reinterpret_cast<const uint8_t *>(FixupAddress.getValue())) -
- E.getTarget().getAddress().getValue() - E.getAddend();
+ int64_t Value = *(reinterpret_cast<const uint8_t *>(FixupPtr)) -
+ E.getTarget().getAddress().getValue() - E.getAddend();
*FixupPtr = static_cast<uint8_t>(Value);
break;
}
case R_RISCV_SUB16: {
- int64_t Value = support::endian::read16le(reinterpret_cast<const void *>(
- FixupAddress.getValue())) -
+ int64_t Value = support::endian::read16le(FixupPtr) -
E.getTarget().getAddress().getValue() - E.getAddend();
*(little16_t *)FixupPtr = static_cast<uint32_t>(Value);
break;
}
case R_RISCV_SUB32: {
- int64_t Value = support::endian::read32le(reinterpret_cast<const void *>(
- FixupAddress.getValue())) -
+ int64_t Value = support::endian::read32le(FixupPtr) -
E.getTarget().getAddress().getValue() - E.getAddend();
*(little32_t *)FixupPtr = static_cast<uint32_t>(Value);
break;
}
case R_RISCV_SUB64: {
- int64_t Value = support::endian::read64le(reinterpret_cast<const void *>(
- FixupAddress.getValue())) -
+ int64_t Value = support::endian::read64le(FixupPtr) -
E.getTarget().getAddress().getValue() - E.getAddend();
*(little64_t *)FixupPtr = static_cast<uint64_t>(Value);
break;
@@ -419,8 +415,7 @@ private:
break;
}
case R_RISCV_SUB6: {
- int64_t Value =
- *(reinterpret_cast<const uint8_t *>(FixupAddress.getValue())) & 0x3f;
+ int64_t Value = *(reinterpret_cast<const uint8_t *>(FixupPtr)) & 0x3f;
Value -= E.getTarget().getAddress().getValue() - E.getAddend();
*FixupPtr = (*FixupPtr & 0xc0) | (static_cast<uint8_t>(Value) & 0x3f);
break;
@@ -458,11 +453,318 @@ private:
*(little32_t *)FixupPtr = Word32;
break;
}
+ case AlignRelaxable:
+ // Ignore when the relaxation pass did not run
+ break;
}
return Error::success();
}
};
+namespace {
+
+struct SymbolAnchor {
+ uint64_t Offset;
+ Symbol *Sym;
+ bool End; // true for the anchor of getOffset() + getSize()
+};
+
+struct BlockRelaxAux {
+ // This records symbol start and end offsets which will be adjusted according
+ // to the nearest RelocDeltas element.
+ SmallVector<SymbolAnchor, 0> Anchors;
+ // All edges that either 1) are R_RISCV_ALIGN or 2) have a R_RISCV_RELAX edge
+ // at the same offset.
+ SmallVector<Edge *, 0> RelaxEdges;
+ // For RelaxEdges[I], the actual offset is RelaxEdges[I]->getOffset() - (I ?
+ // RelocDeltas[I - 1] : 0).
+ SmallVector<uint32_t, 0> RelocDeltas;
+ // For RelaxEdges[I], the actual type is EdgeKinds[I].
+ SmallVector<Edge::Kind, 0> EdgeKinds;
+ // List of rewritten instructions. Contains one raw encoded instruction per
+ // element in EdgeKinds that isn't Invalid or R_RISCV_ALIGN.
+ SmallVector<uint32_t, 0> Writes;
+};
+
+struct RelaxConfig {
+ bool IsRV32;
+ bool HasRVC;
+};
+
+struct RelaxAux {
+ RelaxConfig Config;
+ DenseMap<Block *, BlockRelaxAux> Blocks;
+};
+
+} // namespace
+
+static bool shouldRelax(const Section &S) {
+ return (S.getMemProt() & orc::MemProt::Exec) != orc::MemProt::None;
+}
+
+static bool isRelaxable(const Edge &E) {
+ switch (E.getKind()) {
+ default:
+ return false;
+ case CallRelaxable:
+ case AlignRelaxable:
+ return true;
+ }
+}
+
+static RelaxAux initRelaxAux(LinkGraph &G) {
+ RelaxAux Aux;
+ Aux.Config.IsRV32 = G.getTargetTriple().isRISCV32();
+ const auto &Features = G.getFeatures().getFeatures();
+ Aux.Config.HasRVC =
+ std::find(Features.begin(), Features.end(), "+c") != Features.end();
+
+ for (auto &S : G.sections()) {
+ if (!shouldRelax(S))
+ continue;
+ for (auto *B : S.blocks()) {
+ auto BlockEmplaceResult = Aux.Blocks.try_emplace(B);
+ assert(BlockEmplaceResult.second && "Block encountered twice");
+ auto &BlockAux = BlockEmplaceResult.first->second;
+
+ for (auto &E : B->edges())
+ if (isRelaxable(E))
+ BlockAux.RelaxEdges.push_back(&E);
+
+ if (BlockAux.RelaxEdges.empty()) {
+ Aux.Blocks.erase(BlockEmplaceResult.first);
+ continue;
+ }
+
+ const auto NumEdges = BlockAux.RelaxEdges.size();
+ BlockAux.RelocDeltas.resize(NumEdges, 0);
+ BlockAux.EdgeKinds.resize_for_overwrite(NumEdges);
+
+ // Store anchors (offset and offset+size) for symbols.
+ for (auto *Sym : S.symbols()) {
+ if (!Sym->isDefined() || &Sym->getBlock() != B)
+ continue;
+
+ BlockAux.Anchors.push_back({Sym->getOffset(), Sym, false});
+ BlockAux.Anchors.push_back(
+ {Sym->getOffset() + Sym->getSize(), Sym, true});
+ }
+ }
+ }
+
+ // Sort anchors by offset so that we can find the closest relocation
+ // efficiently. For a zero size symbol, ensure that its start anchor precedes
+ // its end anchor. For two symbols with anchors at the same offset, their
+ // order does not matter.
+ for (auto &BlockAuxIter : Aux.Blocks) {
+ llvm::sort(BlockAuxIter.second.Anchors, [](auto &A, auto &B) {
+ return std::make_pair(A.Offset, A.End) < std::make_pair(B.Offset, B.End);
+ });
+ }
+
+ return Aux;
+}
+
+static void relaxAlign(orc::ExecutorAddr Loc, const Edge &E, uint32_t &Remove,
+ Edge::Kind &NewEdgeKind) {
+ // E points to the start of the padding bytes.
+ // E + Addend points to the instruction to be aligned by removing padding.
+ // Alignment is the smallest power of 2 strictly greater than Addend.
+ const auto Align = NextPowerOf2(E.getAddend());
+ const auto DestLoc = alignTo(Loc.getValue(), Align);
+ const auto SrcLoc = Loc.getValue() + E.getAddend();
+ Remove = SrcLoc - DestLoc;
+ assert(static_cast<int32_t>(Remove) >= 0 &&
+ "R_RISCV_ALIGN needs expanding the content");
+ NewEdgeKind = AlignRelaxable;
+}
+
+static void relaxCall(const Block &B, BlockRelaxAux &Aux,
+ const RelaxConfig &Config, orc::ExecutorAddr Loc,
+ const Edge &E, uint32_t &Remove,
+ Edge::Kind &NewEdgeKind) {
+ const auto JALR =
+ support::endian::read32le(B.getContent().data() + E.getOffset() + 4);
+ const auto RD = extractBits(JALR, 7, 5);
+ const auto Dest = E.getTarget().getAddress() + E.getAddend();
+ const auto Displace = Dest - Loc;
+
+ if (Config.HasRVC && isInt<12>(Displace) && RD == 0) {
+ NewEdgeKind = R_RISCV_RVC_JUMP;
+ Aux.Writes.push_back(0xa001); // c.j
+ Remove = 6;
+ } else if (Config.HasRVC && Config.IsRV32 && isInt<12>(Displace) && RD == 1) {
+ NewEdgeKind = R_RISCV_RVC_JUMP;
+ Aux.Writes.push_back(0x2001); // c.jal
+ Remove = 6;
+ } else if (isInt<21>(Displace)) {
+ NewEdgeKind = R_RISCV_JAL;
+ Aux.Writes.push_back(0x6f | RD << 7); // jal
+ Remove = 4;
+ } else {
+ // Not relaxable
+ NewEdgeKind = R_RISCV_CALL_PLT;
+ Remove = 0;
+ }
+}
+
+static bool relaxBlock(LinkGraph &G, Block &Block, BlockRelaxAux &Aux,
+ const RelaxConfig &Config) {
+ const auto BlockAddr = Block.getAddress();
+ bool Changed = false;
+ ArrayRef<SymbolAnchor> SA = ArrayRef(Aux.Anchors);
+ uint32_t Delta = 0;
+
+ Aux.EdgeKinds.assign(Aux.EdgeKinds.size(), Edge::Invalid);
+ Aux.Writes.clear();
+
+ for (auto [I, E] : llvm::enumerate(Aux.RelaxEdges)) {
+ const auto Loc = BlockAddr + E->getOffset() - Delta;
+ auto &Cur = Aux.RelocDeltas[I];
+ uint32_t Remove = 0;
+ switch (E->getKind()) {
+ case AlignRelaxable:
+ relaxAlign(Loc, *E, Remove, Aux.EdgeKinds[I]);
+ break;
+ case CallRelaxable:
+ relaxCall(Block, Aux, Config, Loc, *E, Remove, Aux.EdgeKinds[I]);
+ break;
+ default:
+ llvm_unreachable("Unexpected relaxable edge kind");
+ }
+
+ // For all anchors whose offsets are <= E->getOffset(), they are preceded by
+ // the previous relocation whose RelocDeltas value equals Delta.
+ // Decrease their offset and update their size.
+ for (; SA.size() && SA[0].Offset <= E->getOffset(); SA = SA.slice(1)) {
+ if (SA[0].End)
+ SA[0].Sym->setSize(SA[0].Offset - Delta - SA[0].Sym->getOffset());
+ else
+ SA[0].Sym->setOffset(SA[0].Offset - Delta);
+ }
+
+ Delta += Remove;
+ if (Delta != Cur) {
+ Cur = Delta;
+ Changed = true;
+ }
+ }
+
+ for (const SymbolAnchor &A : SA) {
+ if (A.End)
+ A.Sym->setSize(A.Offset - Delta - A.Sym->getOffset());
+ else
+ A.Sym->setOffset(A.Offset - Delta);
+ }
+
+ return Changed;
+}
+
+static bool relaxOnce(LinkGraph &G, RelaxAux &Aux) {
+ bool Changed = false;
+
+ for (auto &[B, BlockAux] : Aux.Blocks)
+ Changed |= relaxBlock(G, *B, BlockAux, Aux.Config);
+
+ return Changed;
+}
+
+static void finalizeBlockRelax(LinkGraph &G, Block &Block, BlockRelaxAux &Aux) {
+ auto Contents = Block.getAlreadyMutableContent();
+ auto *Dest = Contents.data();
+ auto NextWrite = Aux.Writes.begin();
+ uint32_t Offset = 0;
+ uint32_t Delta = 0;
+
+ // Update section content: remove NOPs for R_RISCV_ALIGN and rewrite
+ // instructions for relaxed relocations.
+ for (auto [I, E] : llvm::enumerate(Aux.RelaxEdges)) {
+ uint32_t Remove = Aux.RelocDeltas[I] - Delta;
+ Delta = Aux.RelocDeltas[I];
+ if (Remove == 0 && Aux.EdgeKinds[I] == Edge::Invalid)
+ continue;
+
+ // Copy from last location to the current relocated location.
+ const auto Size = E->getOffset() - Offset;
+ std::memmove(Dest, Contents.data() + Offset, Size);
+ Dest += Size;
+
+ uint32_t Skip = 0;
+ switch (Aux.EdgeKinds[I]) {
+ case Edge::Invalid:
+ break;
+ case AlignRelaxable:
+ // For R_RISCV_ALIGN, we will place Offset in a location (among NOPs) to
+ // satisfy the alignment requirement. If both Remove and E->getAddend()
+ // are multiples of 4, it is as if we have skipped some NOPs. Otherwise we
+ // are in the middle of a 4-byte NOP, and we need to rewrite the NOP
+ // sequence.
+ if (Remove % 4 || E->getAddend() % 4) {
+ Skip = E->getAddend() - Remove;
+ uint32_t J = 0;
+ for (; J + 4 <= Skip; J += 4)
+ support::endian::write32le(Dest + J, 0x00000013); // nop
+ if (J != Skip) {
+ assert(J + 2 == Skip);
+ support::endian::write16le(Dest + J, 0x0001); // c.nop
+ }
+ }
+ break;
+ case R_RISCV_RVC_JUMP:
+ Skip = 2;
+ support::endian::write16le(Dest, *NextWrite++);
+ break;
+ case R_RISCV_JAL:
+ Skip = 4;
+ support::endian::write32le(Dest, *NextWrite++);
+ break;
+ }
+
+ Dest += Skip;
+ Offset = E->getOffset() + Skip + Remove;
+ }
+
+ std::memmove(Dest, Contents.data() + Offset, Contents.size() - Offset);
+
+ // Fixup edge offsets and kinds.
+ Delta = 0;
+ size_t I = 0;
+ for (auto &E : Block.edges()) {
+ E.setOffset(E.getOffset() - Delta);
+
+ if (I < Aux.RelaxEdges.size() && Aux.RelaxEdges[I] == &E) {
+ if (Aux.EdgeKinds[I] != Edge::Invalid)
+ E.setKind(Aux.EdgeKinds[I]);
+
+ Delta = Aux.RelocDeltas[I];
+ ++I;
+ }
+ }
+
+ // Remove AlignRelaxable edges: all other relaxable edges got modified and
+ // will be used later while linking. Alignment is entirely handled here so we
+ // don't need these edges anymore.
+ for (auto IE = Block.edges().begin(); IE != Block.edges().end();) {
+ if (IE->getKind() == AlignRelaxable)
+ IE = Block.removeEdge(IE);
+ else
+ ++IE;
+ }
+}
+
+static void finalizeRelax(LinkGraph &G, RelaxAux &Aux) {
+ for (auto &[B, BlockAux] : Aux.Blocks)
+ finalizeBlockRelax(G, *B, BlockAux);
+}
+
+static Error relax(LinkGraph &G) {
+ auto Aux = initRelaxAux(G);
+ while (relaxOnce(G, Aux)) {
+ }
+ finalizeRelax(G, Aux);
+ return Error::success();
+}
+
template <typename ELFT>
class ELFLinkGraphBuilder_riscv : public ELFLinkGraphBuilder<ELFT> {
private:
@@ -528,6 +830,8 @@ private:
return EdgeKind_riscv::R_RISCV_SET32;
case ELF::R_RISCV_32_PCREL:
return EdgeKind_riscv::R_RISCV_32_PCREL;
+ case ELF::R_RISCV_ALIGN:
+ return EdgeKind_riscv::AlignRelaxable;
}
return make_error<JITLinkError>(
@@ -535,6 +839,17 @@ private:
object::getELFRelocationTypeName(ELF::EM_RISCV, Type));
}
+ EdgeKind_riscv getRelaxableRelocationKind(EdgeKind_riscv Kind) {
+ switch (Kind) {
+ default:
+ // Just ignore unsupported relaxations
+ return Kind;
+ case R_RISCV_CALL:
+ case R_RISCV_CALL_PLT:
+ return CallRelaxable;
+ }
+ }
+
Error addRelocations() override {
LLVM_DEBUG(dbgs() << "Processing relocations:\n");
@@ -554,22 +869,17 @@ private:
using Base = ELFLinkGraphBuilder<ELFT>;
uint32_t Type = Rel.getType(false);
- // We do not implement linker relaxation, except what is required for
- // alignment (see below).
- if (Type == llvm::ELF::R_RISCV_RELAX)
- return Error::success();
-
int64_t Addend = Rel.r_addend;
- if (Type == llvm::ELF::R_RISCV_ALIGN) {
- uint64_t Alignment = PowerOf2Ceil(Addend);
- // FIXME: Implement support for ensuring alignment together with linker
- // relaxation; 2 bytes are guaranteed by the length of compressed
- // instructions, so this does not need any action from our side.
- if (Alignment > 2)
- return make_error<JITLinkError>(
- formatv("Unsupported relocation R_RISCV_ALIGN with alignment {0} "
- "larger than 2 (addend: {1})",
- Alignment, Addend));
+
+ if (Type == ELF::R_RISCV_RELAX) {
+ if (BlockToFix.edges_empty())
+ return make_error<StringError>(
+ "R_RISCV_RELAX without preceding relocation",
+ inconvertibleErrorCode());
+
+ auto &PrevEdge = *std::prev(BlockToFix.edges().end());
+ auto Kind = static_cast<EdgeKind_riscv>(PrevEdge.getKind());
+ PrevEdge.setKind(getRelaxableRelocationKind(Kind));
return Error::success();
}
@@ -606,9 +916,10 @@ private:
public:
ELFLinkGraphBuilder_riscv(StringRef FileName,
- const object::ELFFile<ELFT> &Obj, const Triple T)
- : ELFLinkGraphBuilder<ELFT>(Obj, std::move(T), FileName,
- riscv::getEdgeKindName) {}
+ const object::ELFFile<ELFT> &Obj, Triple TT,
+ SubtargetFeatures Features)
+ : ELFLinkGraphBuilder<ELFT>(Obj, std::move(TT), std::move(Features),
+ FileName, riscv::getEdgeKindName) {}
};
Expected<std::unique_ptr<LinkGraph>>
@@ -622,11 +933,15 @@ createLinkGraphFromELFObject_riscv(MemoryBufferRef ObjectBuffer) {
if (!ELFObj)
return ELFObj.takeError();
+ auto Features = (*ELFObj)->getFeatures();
+ if (!Features)
+ return Features.takeError();
+
if ((*ELFObj)->getArch() == Triple::riscv64) {
auto &ELFObjFile = cast<object::ELFObjectFile<object::ELF64LE>>(**ELFObj);
return ELFLinkGraphBuilder_riscv<object::ELF64LE>(
(*ELFObj)->getFileName(), ELFObjFile.getELFFile(),
- (*ELFObj)->makeTriple())
+ (*ELFObj)->makeTriple(), std::move(*Features))
.buildGraph();
} else {
assert((*ELFObj)->getArch() == Triple::riscv32 &&
@@ -634,7 +949,7 @@ createLinkGraphFromELFObject_riscv(MemoryBufferRef ObjectBuffer) {
auto &ELFObjFile = cast<object::ELFObjectFile<object::ELF32LE>>(**ELFObj);
return ELFLinkGraphBuilder_riscv<object::ELF32LE>(
(*ELFObj)->getFileName(), ELFObjFile.getELFFile(),
- (*ELFObj)->makeTriple())
+ (*ELFObj)->makeTriple(), std::move(*Features))
.buildGraph();
}
}
@@ -650,6 +965,7 @@ void link_ELF_riscv(std::unique_ptr<LinkGraph> G,
Config.PrePrunePasses.push_back(markAllSymbolsLive);
Config.PostPrunePasses.push_back(
PerGraphGOTAndPLTStubsBuilder_ELF_riscv::asPass);
+ Config.PostAllocationPasses.push_back(relax);
}
if (auto Err = Ctx->modifyPassConfig(*G, Config))
return Ctx->notifyFailed(std::move(Err));
@@ -657,5 +973,7 @@ void link_ELF_riscv(std::unique_ptr<LinkGraph> G,
ELFJITLinker_riscv::link(std::move(Ctx), std::move(G), std::move(Config));
}
+LinkGraphPassFunction createRelaxationPass_ELF_riscv() { return relax; }
+
} // namespace jitlink
} // namespace llvm
diff --git a/llvm/lib/ExecutionEngine/JITLink/ELF_x86_64.cpp b/llvm/lib/ExecutionEngine/JITLink/ELF_x86_64.cpp
index c9359522c248..1bdddd4c722b 100644
--- a/llvm/lib/ExecutionEngine/JITLink/ELF_x86_64.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/ELF_x86_64.cpp
@@ -100,60 +100,10 @@ Error buildTables_ELF_x86_64(LinkGraph &G) {
namespace llvm {
namespace jitlink {
-// This should become a template as the ELFFile is so a lot of this could become
-// generic
class ELFLinkGraphBuilder_x86_64 : public ELFLinkGraphBuilder<object::ELF64LE> {
private:
using ELFT = object::ELF64LE;
- enum ELFX86RelocationKind : Edge::Kind {
- Branch32 = Edge::FirstRelocation,
- Pointer32Signed,
- Pointer64,
- PCRel32,
- PCRel32GOTLoad,
- PCRel32GOTLoadRelaxable,
- PCRel32REXGOTLoadRelaxable,
- PCRel32TLV,
- PCRel64GOT,
- GOTOFF64,
- GOT64,
- Delta64,
- };
-
- static Expected<ELFX86RelocationKind> getRelocationKind(const uint32_t Type) {
- switch (Type) {
- case ELF::R_X86_64_32S:
- return ELFX86RelocationKind::Pointer32Signed;
- case ELF::R_X86_64_PC32:
- return ELFX86RelocationKind::PCRel32;
- case ELF::R_X86_64_PC64:
- case ELF::R_X86_64_GOTPC64:
- return ELFX86RelocationKind::Delta64;
- case ELF::R_X86_64_64:
- return ELFX86RelocationKind::Pointer64;
- case ELF::R_X86_64_GOTPCREL:
- return ELFX86RelocationKind::PCRel32GOTLoad;
- case ELF::R_X86_64_GOTPCRELX:
- return ELFX86RelocationKind::PCRel32GOTLoadRelaxable;
- case ELF::R_X86_64_REX_GOTPCRELX:
- return ELFX86RelocationKind::PCRel32REXGOTLoadRelaxable;
- case ELF::R_X86_64_GOTPCREL64:
- return ELFX86RelocationKind::PCRel64GOT;
- case ELF::R_X86_64_GOT64:
- return ELFX86RelocationKind::GOT64;
- case ELF::R_X86_64_GOTOFF64:
- return ELFX86RelocationKind::GOTOFF64;
- case ELF::R_X86_64_PLT32:
- return ELFX86RelocationKind::Branch32;
- case ELF::R_X86_64_TLSGD:
- return ELFX86RelocationKind::PCRel32TLV;
- }
- return make_error<JITLinkError>(
- "Unsupported x86-64 relocation type " + formatv("{0:d}: ", Type) +
- object::getELFRelocationTypeName(ELF::EM_X86_64, Type));
- }
-
Error addRelocations() override {
LLVM_DEBUG(dbgs() << "Processing relocations:\n");
@@ -179,6 +129,12 @@ private:
Block &BlockToFix) {
using Base = ELFLinkGraphBuilder<ELFT>;
+ auto ELFReloc = Rel.getType(false);
+
+ // R_X86_64_NONE is a no-op.
+ if (LLVM_UNLIKELY(ELFReloc == ELF::R_X86_64_NONE))
+ return Error::success();
+
uint32_t SymbolIndex = Rel.getSymbol(false);
auto ObjSymbol = Base::Obj.getRelocationSymbol(Rel, Base::SymTabSec);
if (!ObjSymbol)
@@ -194,62 +150,66 @@ private:
inconvertibleErrorCode());
// Validate the relocation kind.
- auto ELFRelocKind = getRelocationKind(Rel.getType(false));
- if (!ELFRelocKind)
- return ELFRelocKind.takeError();
-
int64_t Addend = Rel.r_addend;
Edge::Kind Kind = Edge::Invalid;
- switch (*ELFRelocKind) {
- case PCRel32:
+
+ switch (ELFReloc) {
+ case ELF::R_X86_64_PC32:
+ case ELF::R_X86_64_GOTPC32:
Kind = x86_64::Delta32;
break;
- case Delta64:
+ case ELF::R_X86_64_PC64:
+ case ELF::R_X86_64_GOTPC64:
Kind = x86_64::Delta64;
break;
- case Pointer32Signed:
+ case ELF::R_X86_64_32:
+ Kind = x86_64::Pointer32;
+ break;
+ case ELF::R_X86_64_16:
+ Kind = x86_64::Pointer16;
+ break;
+ case ELF::R_X86_64_8:
+ Kind = x86_64::Pointer8;
+ break;
+ case ELF::R_X86_64_32S:
Kind = x86_64::Pointer32Signed;
break;
- case Pointer64:
+ case ELF::R_X86_64_64:
Kind = x86_64::Pointer64;
break;
- case PCRel32GOTLoad: {
+ case ELF::R_X86_64_GOTPCREL:
Kind = x86_64::RequestGOTAndTransformToDelta32;
break;
- }
- case PCRel32REXGOTLoadRelaxable: {
+ case ELF::R_X86_64_REX_GOTPCRELX:
Kind = x86_64::RequestGOTAndTransformToPCRel32GOTLoadREXRelaxable;
Addend = 0;
break;
- }
- case PCRel32TLV: {
+ case ELF::R_X86_64_TLSGD:
Kind = x86_64::RequestTLSDescInGOTAndTransformToDelta32;
break;
- }
- case PCRel32GOTLoadRelaxable: {
+ case ELF::R_X86_64_GOTPCRELX:
Kind = x86_64::RequestGOTAndTransformToPCRel32GOTLoadRelaxable;
Addend = 0;
break;
- }
- case PCRel64GOT: {
+ case ELF::R_X86_64_GOTPCREL64:
Kind = x86_64::RequestGOTAndTransformToDelta64;
break;
- }
- case GOT64: {
+ case ELF::R_X86_64_GOT64:
Kind = x86_64::RequestGOTAndTransformToDelta64FromGOT;
break;
- }
- case GOTOFF64: {
+ case ELF::R_X86_64_GOTOFF64:
Kind = x86_64::Delta64FromGOT;
break;
- }
- case Branch32: {
+ case ELF::R_X86_64_PLT32:
Kind = x86_64::BranchPCRel32;
// BranchPCRel32 implicitly handles the '-4' PC adjustment, so we have to
// adjust the addend by '+4' to compensate.
Addend += 4;
break;
- }
+ default:
+ return make_error<JITLinkError>(
+ "In " + G->getName() + ": Unsupported x86-64 relocation type " +
+ object::getELFRelocationTypeName(ELF::EM_X86_64, ELFReloc));
}
auto FixupAddress = orc::ExecutorAddr(FixupSection.sh_addr) + Rel.r_offset;
@@ -267,8 +227,10 @@ private:
public:
ELFLinkGraphBuilder_x86_64(StringRef FileName,
- const object::ELFFile<object::ELF64LE> &Obj)
- : ELFLinkGraphBuilder(Obj, Triple("x86_64-unknown-linux"), FileName,
+ const object::ELFFile<object::ELF64LE> &Obj,
+ SubtargetFeatures Features)
+ : ELFLinkGraphBuilder(Obj, Triple("x86_64-unknown-linux"),
+ std::move(Features), FileName,
x86_64::getEdgeKindName) {}
};
@@ -334,6 +296,22 @@ private:
Linkage::Strong, Scope::Local, false, true);
}
+ // If we still haven't found a GOT symbol then double check the externals.
+ // We may have a GOT-relative reference but no GOT section, in which case
+ // we just need to point the GOT symbol at some address in this graph.
+ if (!GOTSymbol) {
+ for (auto *Sym : G.external_symbols()) {
+ if (Sym->getName() == ELFGOTSymbolName) {
+ auto Blocks = G.blocks();
+ if (!Blocks.empty()) {
+ G.makeAbsolute(*Sym, (*Blocks.begin())->getAddress());
+ GOTSymbol = Sym;
+ break;
+ }
+ }
+ }
+ }
+
return Error::success();
}
@@ -353,9 +331,14 @@ createLinkGraphFromELFObject_x86_64(MemoryBufferRef ObjectBuffer) {
if (!ELFObj)
return ELFObj.takeError();
+ auto Features = (*ELFObj)->getFeatures();
+ if (!Features)
+ return Features.takeError();
+
auto &ELFObjFile = cast<object::ELFObjectFile<object::ELF64LE>>(**ELFObj);
return ELFLinkGraphBuilder_x86_64((*ELFObj)->getFileName(),
- ELFObjFile.getELFFile())
+ ELFObjFile.getELFFile(),
+ std::move(*Features))
.buildGraph();
}
diff --git a/llvm/lib/ExecutionEngine/JITLink/JITLink.cpp b/llvm/lib/ExecutionEngine/JITLink/JITLink.cpp
index bd5b4d585550..4a2755d3696b 100644
--- a/llvm/lib/ExecutionEngine/JITLink/JITLink.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/JITLink.cpp
@@ -8,6 +8,7 @@
#include "llvm/ExecutionEngine/JITLink/JITLink.h"
+#include "llvm/ADT/StringExtras.h"
#include "llvm/BinaryFormat/Magic.h"
#include "llvm/ExecutionEngine/JITLink/COFF.h"
#include "llvm/ExecutionEngine/JITLink/ELF.h"
@@ -88,6 +89,21 @@ const char *getScopeName(Scope S) {
llvm_unreachable("Unrecognized llvm.jitlink.Scope enum");
}
+bool isCStringBlock(Block &B) {
+ if (B.getSize() == 0) // Empty blocks are not valid C-strings.
+ return false;
+
+ // Zero-fill blocks of size one are valid empty strings.
+ if (B.isZeroFill())
+ return B.getSize() == 1;
+
+ for (size_t I = 0; I != B.getSize() - 1; ++I)
+ if (B.getContent()[I] == '\0')
+ return false;
+
+ return B.getContent()[B.getSize() - 1] == '\0';
+}
+
raw_ostream &operator<<(raw_ostream &OS, const Block &B) {
return OS << B.getAddress() << " -- " << (B.getAddress() + B.getSize())
<< ": "
diff --git a/llvm/lib/ExecutionEngine/JITLink/JITLinkGeneric.cpp b/llvm/lib/ExecutionEngine/JITLink/JITLinkGeneric.cpp
index 17de84fa6e11..feaa0fb6a58c 100644
--- a/llvm/lib/ExecutionEngine/JITLink/JITLinkGeneric.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/JITLinkGeneric.cpp
@@ -65,7 +65,7 @@ void JITLinkerBase::linkPhase2(std::unique_ptr<JITLinkerBase> Self,
if (AR)
Alloc = std::move(*AR);
else
- return Ctx->notifyFailed(AR.takeError());
+ return abandonAllocAndBailOut(std::move(Self), AR.takeError());
LLVM_DEBUG({
dbgs() << "Link graph \"" << G->getName()
@@ -75,13 +75,13 @@ void JITLinkerBase::linkPhase2(std::unique_ptr<JITLinkerBase> Self,
// Run post-allocation passes.
if (auto Err = runPasses(Passes.PostAllocationPasses))
- return Ctx->notifyFailed(std::move(Err));
+ return abandonAllocAndBailOut(std::move(Self), std::move(Err));
// Notify client that the defined symbols have been assigned addresses.
LLVM_DEBUG(dbgs() << "Resolving symbols defined in " << G->getName() << "\n");
if (auto Err = Ctx->notifyResolved(*G))
- return Ctx->notifyFailed(std::move(Err));
+ return abandonAllocAndBailOut(std::move(Self), std::move(Err));
auto ExternalSymbols = getExternalSymbolNames();
@@ -218,8 +218,7 @@ void JITLinkerBase::applyLookupResult(AsyncLookupResult Result) {
assert(!Sym->isDefined() && "Symbol being resolved is already defined");
auto ResultI = Result.find(Sym->getName());
if (ResultI != Result.end()) {
- Sym->getAddressable().setAddress(
- orc::ExecutorAddr(ResultI->second.getAddress()));
+ Sym->getAddressable().setAddress(ResultI->second.getAddress());
Sym->setLinkage(ResultI->second.getFlags().isWeak() ? Linkage::Weak
: Linkage::Strong);
Sym->setScope(ResultI->second.getFlags().isExported() ? Scope::Default
diff --git a/llvm/lib/ExecutionEngine/JITLink/JITLinkGeneric.h b/llvm/lib/ExecutionEngine/JITLink/JITLinkGeneric.h
index 2c9244526536..e69eddd6e119 100644
--- a/llvm/lib/ExecutionEngine/JITLink/JITLinkGeneric.h
+++ b/llvm/lib/ExecutionEngine/JITLink/JITLinkGeneric.h
@@ -123,26 +123,47 @@ private:
Error fixUpBlocks(LinkGraph &G) const override {
LLVM_DEBUG(dbgs() << "Fixing up blocks:\n");
- for (auto *B : G.blocks()) {
- LLVM_DEBUG(dbgs() << " " << *B << ":\n");
+ for (auto &Sec : G.sections()) {
+ bool NoAllocSection =
+ Sec.getMemLifetimePolicy() == orc::MemLifetimePolicy::NoAlloc;
- // Copy Block data and apply fixups.
- LLVM_DEBUG(dbgs() << " Applying fixups.\n");
- assert((!B->isZeroFill() || all_of(B->edges(),
- [](const Edge &E) {
- return E.getKind() ==
- Edge::KeepAlive;
- })) &&
- "Non-KeepAlive edges in zero-fill block?");
- for (auto &E : B->edges()) {
+ for (auto *B : Sec.blocks()) {
+ LLVM_DEBUG(dbgs() << " " << *B << ":\n");
- // Skip non-relocation edges.
- if (!E.isRelocation())
- continue;
+ // Copy Block data and apply fixups.
+ LLVM_DEBUG(dbgs() << " Applying fixups.\n");
+ assert((!B->isZeroFill() || all_of(B->edges(),
+ [](const Edge &E) {
+ return E.getKind() ==
+ Edge::KeepAlive;
+ })) &&
+ "Non-KeepAlive edges in zero-fill block?");
- // Dispatch to LinkerImpl for fixup.
- if (auto Err = impl().applyFixup(G, *B, E))
- return Err;
+ // If this is a no-alloc section then copy the block content into
+ // memory allocated on the Graph's allocator (if it hasn't been
+ // already).
+ if (NoAllocSection)
+ (void)B->getMutableContent(G);
+
+ for (auto &E : B->edges()) {
+
+ // Skip non-relocation edges.
+ if (!E.isRelocation())
+ continue;
+
+ // If B is a block in a Standard or Finalize section then make sure
+ // that no edges point to symbols in NoAlloc sections.
+ assert(
+ (NoAllocSection || !E.getTarget().isDefined() ||
+ E.getTarget().getBlock().getSection().getMemLifetimePolicy() !=
+ orc::MemLifetimePolicy::NoAlloc) &&
+ "Block in allocated section has edge pointing to no-alloc "
+ "section");
+
+ // Dispatch to LinkerImpl for fixup.
+ if (auto Err = impl().applyFixup(G, *B, E))
+ return Err;
+ }
}
}
diff --git a/llvm/lib/ExecutionEngine/JITLink/JITLinkMemoryManager.cpp b/llvm/lib/ExecutionEngine/JITLink/JITLinkMemoryManager.cpp
index bd44b86f3081..f481504135a5 100644
--- a/llvm/lib/ExecutionEngine/JITLink/JITLinkMemoryManager.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/JITLinkMemoryManager.cpp
@@ -24,11 +24,12 @@ JITLinkMemoryManager::InFlightAlloc::~InFlightAlloc() = default;
BasicLayout::BasicLayout(LinkGraph &G) : G(G) {
for (auto &Sec : G.sections()) {
- // Skip empty sections.
- if (Sec.blocks().empty())
+ // Skip empty sections, and sections with NoAlloc lifetime policies.
+ if (Sec.blocks().empty() ||
+ Sec.getMemLifetimePolicy() == orc::MemLifetimePolicy::NoAlloc)
continue;
- auto &Seg = Segments[{Sec.getMemProt(), Sec.getMemDeallocPolicy()}];
+ auto &Seg = Segments[{Sec.getMemProt(), Sec.getMemLifetimePolicy()}];
for (auto *B : Sec.blocks())
if (LLVM_LIKELY(!B->isZeroFill()))
Seg.ContentBlocks.push_back(B);
@@ -89,7 +90,7 @@ BasicLayout::getContiguousPageBasedLayoutSizes(uint64_t PageSize) {
inconvertibleErrorCode());
uint64_t SegSize = alignTo(Seg.ContentSize + Seg.ZeroFillSize, PageSize);
- if (AG.getMemDeallocPolicy() == orc::MemDeallocPolicy::Standard)
+ if (AG.getMemLifetimePolicy() == orc::MemLifetimePolicy::Standard)
SegsSizes.StandardSegs += SegSize;
else
SegsSizes.FinalizeSegs += SegSize;
@@ -146,7 +147,7 @@ void SimpleSegmentAlloc::Create(JITLinkMemoryManager &MemMgr,
const JITLinkDylib *JD, SegmentMap Segments,
OnCreatedFunction OnCreated) {
- static_assert(orc::AllocGroup::NumGroups == 16,
+ static_assert(orc::AllocGroup::NumGroups == 32,
"AllocGroup has changed. Section names below must be updated");
StringRef AGSectionNames[] = {
"__---.standard", "__R--.standard", "__-W-.standard", "__RW-.standard",
@@ -163,12 +164,15 @@ void SimpleSegmentAlloc::Create(JITLinkMemoryManager &MemMgr,
auto &AG = KV.first;
auto &Seg = KV.second;
+ assert(AG.getMemLifetimePolicy() != orc::MemLifetimePolicy::NoAlloc &&
+ "NoAlloc segments are not supported by SimpleSegmentAlloc");
+
auto AGSectionName =
AGSectionNames[static_cast<unsigned>(AG.getMemProt()) |
- static_cast<bool>(AG.getMemDeallocPolicy()) << 3];
+ static_cast<bool>(AG.getMemLifetimePolicy()) << 3];
auto &Sec = G->createSection(AGSectionName, AG.getMemProt());
- Sec.setMemDeallocPolicy(AG.getMemDeallocPolicy());
+ Sec.setMemLifetimePolicy(AG.getMemLifetimePolicy());
if (Seg.ContentSize != 0) {
NextAddr =
@@ -236,10 +240,14 @@ public:
IPInFlightAlloc(InProcessMemoryManager &MemMgr, LinkGraph &G, BasicLayout BL,
sys::MemoryBlock StandardSegments,
sys::MemoryBlock FinalizationSegments)
- : MemMgr(MemMgr), G(G), BL(std::move(BL)),
+ : MemMgr(MemMgr), G(&G), BL(std::move(BL)),
StandardSegments(std::move(StandardSegments)),
FinalizationSegments(std::move(FinalizationSegments)) {}
+ ~IPInFlightAlloc() {
+ assert(!G && "InFlight alloc neither abandoned nor finalized");
+ }
+
void finalize(OnFinalizedFunction OnFinalized) override {
// Apply memory protections to all segments.
@@ -249,7 +257,7 @@ public:
}
// Run finalization actions.
- auto DeallocActions = runFinalizeActions(G.allocActions());
+ auto DeallocActions = runFinalizeActions(G->allocActions());
if (!DeallocActions) {
OnFinalized(DeallocActions.takeError());
return;
@@ -261,6 +269,13 @@ public:
return;
}
+#ifndef NDEBUG
+ // Set 'G' to null to flag that we've been successfully finalized.
+ // This allows us to assert at destruction time that a call has been made
+ // to either finalize or abandon.
+ G = nullptr;
+#endif
+
// Continue with finalized allocation.
OnFinalized(MemMgr.createFinalizedAlloc(std::move(StandardSegments),
std::move(*DeallocActions)));
@@ -272,6 +287,14 @@ public:
Err = joinErrors(std::move(Err), errorCodeToError(EC));
if (auto EC = sys::Memory::releaseMappedMemory(StandardSegments))
Err = joinErrors(std::move(Err), errorCodeToError(EC));
+
+#ifndef NDEBUG
+ // Set 'G' to null to flag that we've been successfully finalized.
+ // This allows us to assert at destruction time that a call has been made
+ // to either finalize or abandon.
+ G = nullptr;
+#endif
+
OnAbandoned(std::move(Err));
}
@@ -295,7 +318,7 @@ private:
}
InProcessMemoryManager &MemMgr;
- LinkGraph &G;
+ LinkGraph *G;
BasicLayout BL;
sys::MemoryBlock StandardSegments;
sys::MemoryBlock FinalizationSegments;
@@ -397,7 +420,7 @@ void InProcessMemoryManager::allocate(const JITLinkDylib *JD, LinkGraph &G,
auto &Seg = KV.second;
auto &SegAddr =
- (AG.getMemDeallocPolicy() == orc::MemDeallocPolicy::Standard)
+ (AG.getMemLifetimePolicy() == orc::MemLifetimePolicy::Standard)
? NextStandardSegAddr
: NextFinalizeSegAddr;
diff --git a/llvm/lib/ExecutionEngine/JITLink/MachO.cpp b/llvm/lib/ExecutionEngine/JITLink/MachO.cpp
index e49480c78662..40086ccf2b66 100644
--- a/llvm/lib/ExecutionEngine/JITLink/MachO.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/MachO.cpp
@@ -54,7 +54,7 @@ createLinkGraphFromMachOObject(MemoryBufferRef ObjectBuffer) {
uint32_t CPUType;
memcpy(&CPUType, Data.data() + 4, sizeof(uint32_t));
if (Magic == MachO::MH_CIGAM_64)
- CPUType = ByteSwap_32(CPUType);
+ CPUType = llvm::byteswap<uint32_t>(CPUType);
LLVM_DEBUG({
dbgs() << "jitLink_MachO: cputype = " << format("0x%08" PRIx32, CPUType)
diff --git a/llvm/lib/ExecutionEngine/JITLink/MachOLinkGraphBuilder.cpp b/llvm/lib/ExecutionEngine/JITLink/MachOLinkGraphBuilder.cpp
index 987689993397..c40e0f9ffc8d 100644
--- a/llvm/lib/ExecutionEngine/JITLink/MachOLinkGraphBuilder.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/MachOLinkGraphBuilder.cpp
@@ -47,12 +47,13 @@ Expected<std::unique_ptr<LinkGraph>> MachOLinkGraphBuilder::buildGraph() {
}
MachOLinkGraphBuilder::MachOLinkGraphBuilder(
- const object::MachOObjectFile &Obj, Triple TT,
+ const object::MachOObjectFile &Obj, Triple TT, SubtargetFeatures Features,
LinkGraph::GetEdgeKindNameFunction GetEdgeKindName)
: Obj(Obj),
- G(std::make_unique<LinkGraph>(
- std::string(Obj.getFileName()), std::move(TT), getPointerSize(Obj),
- getEndianness(Obj), std::move(GetEdgeKindName))) {
+ G(std::make_unique<LinkGraph>(std::string(Obj.getFileName()),
+ std::move(TT), std::move(Features),
+ getPointerSize(Obj), getEndianness(Obj),
+ std::move(GetEdgeKindName))) {
auto &MachHeader = Obj.getHeader64();
SubsectionsViaSymbols = MachHeader.flags & MachO::MH_SUBSECTIONS_VIA_SYMBOLS;
}
@@ -185,10 +186,14 @@ Error MachOLinkGraphBuilder::createNormalizedSections() {
Prot = orc::MemProt::Read | orc::MemProt::Write;
auto FullyQualifiedName =
- G->allocateString(StringRef(NSec.SegName) + "," + NSec.SectName);
+ G->allocateContent(StringRef(NSec.SegName) + "," + NSec.SectName);
NSec.GraphSection = &G->createSection(
StringRef(FullyQualifiedName.data(), FullyQualifiedName.size()), Prot);
+ // TODO: Are there any other criteria for NoAlloc lifetime?
+ if (NSec.Flags & MachO::S_ATTR_DEBUG)
+ NSec.GraphSection->setMemLifetimePolicy(orc::MemLifetimePolicy::NoAlloc);
+
IndexToSection.insert(std::make_pair(SecIndex, std::move(NSec)));
}
@@ -267,7 +272,11 @@ Error MachOLinkGraphBuilder::createNormalizedSymbols() {
Name = *NameOrErr;
else
return NameOrErr.takeError();
- }
+ } else if (Type & MachO::N_EXT)
+ return make_error<JITLinkError>("Symbol at index " +
+ formatv("{0}", SymbolIndex) +
+ " has no name (string table index 0), "
+ "but N_EXT bit is set");
LLVM_DEBUG({
dbgs() << " ";
@@ -656,7 +665,7 @@ Error MachOLinkGraphBuilder::graphifyCStringSection(
orc::ExecutorAddrDiff BlockStart = 0;
// Scan section for null characters.
- for (size_t I = 0; I != NSec.Size; ++I)
+ for (size_t I = 0; I != NSec.Size; ++I) {
if (NSec.Data[I] == '\0') {
size_t BlockSize = I + 1 - BlockStart;
// Create a block for this null terminated string.
@@ -723,6 +732,11 @@ Error MachOLinkGraphBuilder::graphifyCStringSection(
BlockStart += BlockSize;
}
+ }
+
+ assert(llvm::all_of(NSec.GraphSection->blocks(),
+ [](Block *B) { return isCStringBlock(*B); }) &&
+ "All blocks in section should hold single c-strings");
return Error::success();
}
diff --git a/llvm/lib/ExecutionEngine/JITLink/MachOLinkGraphBuilder.h b/llvm/lib/ExecutionEngine/JITLink/MachOLinkGraphBuilder.h
index ba6cfaf8aa94..2805c2960b9b 100644
--- a/llvm/lib/ExecutionEngine/JITLink/MachOLinkGraphBuilder.h
+++ b/llvm/lib/ExecutionEngine/JITLink/MachOLinkGraphBuilder.h
@@ -84,6 +84,7 @@ protected:
using SectionParserFunction = std::function<Error(NormalizedSection &S)>;
MachOLinkGraphBuilder(const object::MachOObjectFile &Obj, Triple TT,
+ SubtargetFeatures Features,
LinkGraph::GetEdgeKindNameFunction GetEdgeKindName);
LinkGraph &getGraph() const { return *G; }
diff --git a/llvm/lib/ExecutionEngine/JITLink/MachO_arm64.cpp b/llvm/lib/ExecutionEngine/JITLink/MachO_arm64.cpp
index 3380bb563140..dd0b5d37d1b7 100644
--- a/llvm/lib/ExecutionEngine/JITLink/MachO_arm64.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/MachO_arm64.cpp
@@ -25,9 +25,10 @@ namespace {
class MachOLinkGraphBuilder_arm64 : public MachOLinkGraphBuilder {
public:
- MachOLinkGraphBuilder_arm64(const object::MachOObjectFile &Obj)
+ MachOLinkGraphBuilder_arm64(const object::MachOObjectFile &Obj,
+ SubtargetFeatures Features)
: MachOLinkGraphBuilder(Obj, Triple("arm64-apple-darwin"),
- aarch64::getEdgeKindName),
+ std::move(Features), aarch64::getEdgeKindName),
NumSymbols(Obj.getSymtabLoadCommand().nsyms) {}
private:
@@ -541,7 +542,13 @@ createLinkGraphFromMachOObject_arm64(MemoryBufferRef ObjectBuffer) {
auto MachOObj = object::ObjectFile::createMachOObjectFile(ObjectBuffer);
if (!MachOObj)
return MachOObj.takeError();
- return MachOLinkGraphBuilder_arm64(**MachOObj).buildGraph();
+
+ auto Features = (*MachOObj)->getFeatures();
+ if (!Features)
+ return Features.takeError();
+
+ return MachOLinkGraphBuilder_arm64(**MachOObj, std::move(*Features))
+ .buildGraph();
}
void link_MachO_arm64(std::unique_ptr<LinkGraph> G,
diff --git a/llvm/lib/ExecutionEngine/JITLink/MachO_x86_64.cpp b/llvm/lib/ExecutionEngine/JITLink/MachO_x86_64.cpp
index be40b740a5a7..4dba27bc61cb 100644
--- a/llvm/lib/ExecutionEngine/JITLink/MachO_x86_64.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/MachO_x86_64.cpp
@@ -25,9 +25,10 @@ namespace {
class MachOLinkGraphBuilder_x86_64 : public MachOLinkGraphBuilder {
public:
- MachOLinkGraphBuilder_x86_64(const object::MachOObjectFile &Obj)
+ MachOLinkGraphBuilder_x86_64(const object::MachOObjectFile &Obj,
+ SubtargetFeatures Features)
: MachOLinkGraphBuilder(Obj, Triple("x86_64-apple-darwin"),
- x86_64::getEdgeKindName) {}
+ std::move(Features), x86_64::getEdgeKindName) {}
private:
enum MachONormalizedRelocationType : unsigned {
@@ -466,7 +467,13 @@ createLinkGraphFromMachOObject_x86_64(MemoryBufferRef ObjectBuffer) {
auto MachOObj = object::ObjectFile::createMachOObjectFile(ObjectBuffer);
if (!MachOObj)
return MachOObj.takeError();
- return MachOLinkGraphBuilder_x86_64(**MachOObj).buildGraph();
+
+ auto Features = (*MachOObj)->getFeatures();
+ if (!Features)
+ return Features.takeError();
+
+ return MachOLinkGraphBuilder_x86_64(**MachOObj, std::move(*Features))
+ .buildGraph();
}
void link_MachO_x86_64(std::unique_ptr<LinkGraph> G,
diff --git a/llvm/lib/ExecutionEngine/JITLink/SEHFrameSupport.h b/llvm/lib/ExecutionEngine/JITLink/SEHFrameSupport.h
index 0d95fbf439b5..21bfd36d44a2 100644
--- a/llvm/lib/ExecutionEngine/JITLink/SEHFrameSupport.h
+++ b/llvm/lib/ExecutionEngine/JITLink/SEHFrameSupport.h
@@ -13,10 +13,10 @@
#ifndef LLVM_EXECUTIONENGINE_JITLINK_SEHFRAMESUPPORT_H
#define LLVM_EXECUTIONENGINE_JITLINK_SEHFRAMESUPPORT_H
-#include "llvm/ADT/Triple.h"
#include "llvm/ExecutionEngine/JITLink/JITLink.h"
#include "llvm/ExecutionEngine/JITSymbol.h"
#include "llvm/Support/Error.h"
+#include "llvm/TargetParser/Triple.h"
namespace llvm {
namespace jitlink {
diff --git a/llvm/lib/ExecutionEngine/JITLink/aarch32.cpp b/llvm/lib/ExecutionEngine/JITLink/aarch32.cpp
new file mode 100644
index 000000000000..ffc3950cdec8
--- /dev/null
+++ b/llvm/lib/ExecutionEngine/JITLink/aarch32.cpp
@@ -0,0 +1,519 @@
+//===--------- aarch32.cpp - Generic JITLink arm/thumb utilities ----------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+// Generic utilities for graphs representing arm/thumb objects.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ExecutionEngine/JITLink/aarch32.h"
+
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/BinaryFormat/ELF.h"
+#include "llvm/ExecutionEngine/JITLink/JITLink.h"
+#include "llvm/Object/ELFObjectFile.h"
+#include "llvm/Support/Endian.h"
+#include "llvm/Support/MathExtras.h"
+
+#define DEBUG_TYPE "jitlink"
+
+namespace llvm {
+namespace jitlink {
+namespace aarch32 {
+
+/// Encode 22-bit immediate value for branch instructions without J1J2 range
+/// extension (formats B T4, BL T1 and BLX T2).
+///
+/// 00000:Imm11H:Imm11L:0 -> [ 00000:Imm11H, 00000:Imm11L ]
+/// J1^ ^J2 will always be 1
+///
+HalfWords encodeImmBT4BlT1BlxT2(int64_t Value) {
+ constexpr uint32_t J1J2 = 0x2800;
+ uint32_t Imm11H = (Value >> 12) & 0x07ff;
+ uint32_t Imm11L = (Value >> 1) & 0x07ff;
+ return HalfWords{Imm11H, Imm11L | J1J2};
+}
+
+/// Decode 22-bit immediate value for branch instructions without J1J2 range
+/// extension (formats B T4, BL T1 and BLX T2).
+///
+/// [ 00000:Imm11H, 00000:Imm11L ] -> 00000:Imm11H:Imm11L:0
+/// J1^ ^J2 will always be 1
+///
+int64_t decodeImmBT4BlT1BlxT2(uint32_t Hi, uint32_t Lo) {
+ uint32_t Imm11H = Hi & 0x07ff;
+ uint32_t Imm11L = Lo & 0x07ff;
+ return SignExtend64<22>(Imm11H << 12 | Imm11L << 1);
+}
+
+/// Encode 25-bit immediate value for branch instructions with J1J2 range
+/// extension (formats B T4, BL T1 and BLX T2).
+///
+/// S:I1:I2:Imm10:Imm11:0 -> [ 00000:S:Imm10, 00:J1:0:J2:Imm11 ]
+///
+HalfWords encodeImmBT4BlT1BlxT2_J1J2(int64_t Value) {
+ uint32_t S = (Value >> 14) & 0x0400;
+ uint32_t J1 = (((~(Value >> 10)) ^ (Value >> 11)) & 0x2000);
+ uint32_t J2 = (((~(Value >> 11)) ^ (Value >> 13)) & 0x0800);
+ uint32_t Imm10 = (Value >> 12) & 0x03ff;
+ uint32_t Imm11 = (Value >> 1) & 0x07ff;
+ return HalfWords{S | Imm10, J1 | J2 | Imm11};
+}
+
+/// Decode 25-bit immediate value for branch instructions with J1J2 range
+/// extension (formats B T4, BL T1 and BLX T2).
+///
+/// [ 00000:S:Imm10, 00:J1:0:J2:Imm11] -> S:I1:I2:Imm10:Imm11:0
+///
+int64_t decodeImmBT4BlT1BlxT2_J1J2(uint32_t Hi, uint32_t Lo) {
+ uint32_t S = Hi & 0x0400;
+ uint32_t I1 = ~((Lo ^ (Hi << 3)) << 10) & 0x00800000;
+ uint32_t I2 = ~((Lo ^ (Hi << 1)) << 11) & 0x00400000;
+ uint32_t Imm10 = Hi & 0x03ff;
+ uint32_t Imm11 = Lo & 0x07ff;
+ return SignExtend64<25>(S << 14 | I1 | I2 | Imm10 << 12 | Imm11 << 1);
+}
+
+/// Encode 16-bit immediate value for move instruction formats MOVT T1 and
+/// MOVW T3.
+///
+/// Imm4:Imm1:Imm3:Imm8 -> [ 00000:i:000000:Imm4, 0:Imm3:0000:Imm8 ]
+///
+HalfWords encodeImmMovtT1MovwT3(uint16_t Value) {
+ uint32_t Imm4 = (Value >> 12) & 0x0f;
+ uint32_t Imm1 = (Value >> 11) & 0x01;
+ uint32_t Imm3 = (Value >> 8) & 0x07;
+ uint32_t Imm8 = Value & 0xff;
+ return HalfWords{Imm1 << 10 | Imm4, Imm3 << 12 | Imm8};
+}
+
+/// Decode 16-bit immediate value from move instruction formats MOVT T1 and
+/// MOVW T3.
+///
+/// [ 00000:i:000000:Imm4, 0:Imm3:0000:Imm8 ] -> Imm4:Imm1:Imm3:Imm8
+///
+uint16_t decodeImmMovtT1MovwT3(uint32_t Hi, uint32_t Lo) {
+ uint32_t Imm4 = Hi & 0x0f;
+ uint32_t Imm1 = (Hi >> 10) & 0x01;
+ uint32_t Imm3 = (Lo >> 12) & 0x07;
+ uint32_t Imm8 = Lo & 0xff;
+ uint32_t Imm16 = Imm4 << 12 | Imm1 << 11 | Imm3 << 8 | Imm8;
+ assert(Imm16 <= 0xffff && "Decoded value out-of-range");
+ return Imm16;
+}
+
+/// Encode register ID for instruction formats MOVT T1 and MOVW T3.
+///
+/// Rd4 -> [0000000000000000, 0000:Rd4:00000000]
+///
+HalfWords encodeRegMovtT1MovwT3(int64_t Value) {
+ uint32_t Rd4 = (Value & 0x0f) << 8;
+ return HalfWords{0, Rd4};
+}
+
+/// Decode register ID from instruction formats MOVT T1 and MOVW T3.
+///
+/// [0000000000000000, 0000:Rd4:00000000] -> Rd4
+///
+int64_t decodeRegMovtT1MovwT3(uint32_t Hi, uint32_t Lo) {
+ uint32_t Rd4 = (Lo >> 8) & 0x0f;
+ return Rd4;
+}
+
+/// 32-bit Thumb instructions are stored as two little-endian halfwords.
+/// An instruction at address A encodes bytes A+1, A in the first halfword (Hi),
+/// followed by bytes A+3, A+2 in the second halfword (Lo).
+struct WritableThumbRelocation {
+ /// Create a writable reference to a Thumb32 fixup.
+ WritableThumbRelocation(char *FixupPtr)
+ : Hi{*reinterpret_cast<support::ulittle16_t *>(FixupPtr)},
+ Lo{*reinterpret_cast<support::ulittle16_t *>(FixupPtr + 2)} {}
+
+ support::ulittle16_t &Hi; // First halfword
+ support::ulittle16_t &Lo; // Second halfword
+};
+
+struct ThumbRelocation {
+ /// Create a read-only reference to a Thumb32 fixup.
+ ThumbRelocation(const char *FixupPtr)
+ : Hi{*reinterpret_cast<const support::ulittle16_t *>(FixupPtr)},
+ Lo{*reinterpret_cast<const support::ulittle16_t *>(FixupPtr + 2)} {}
+
+ /// Create a read-only Thumb32 fixup from a writeable one.
+ ThumbRelocation(WritableThumbRelocation &Writable)
+ : Hi{Writable.Hi}, Lo(Writable.Lo) {}
+
+ const support::ulittle16_t &Hi; // First halfword
+ const support::ulittle16_t &Lo; // Second halfword
+};
+
+Error makeUnexpectedOpcodeError(const LinkGraph &G, const ThumbRelocation &R,
+ Edge::Kind Kind) {
+ return make_error<JITLinkError>(
+ formatv("Invalid opcode [ 0x{0:x4}, 0x{1:x4} ] for relocation: {2}",
+ static_cast<uint16_t>(R.Hi), static_cast<uint16_t>(R.Lo),
+ G.getEdgeKindName(Kind)));
+}
+
+template <EdgeKind_aarch32 Kind> bool checkOpcode(const ThumbRelocation &R) {
+ uint16_t Hi = R.Hi & FixupInfo<Kind>::OpcodeMask.Hi;
+ uint16_t Lo = R.Lo & FixupInfo<Kind>::OpcodeMask.Lo;
+ return Hi == FixupInfo<Kind>::Opcode.Hi && Lo == FixupInfo<Kind>::Opcode.Lo;
+}
+
+template <EdgeKind_aarch32 Kind>
+bool checkRegister(const ThumbRelocation &R, HalfWords Reg) {
+ uint16_t Hi = R.Hi & FixupInfo<Kind>::RegMask.Hi;
+ uint16_t Lo = R.Lo & FixupInfo<Kind>::RegMask.Lo;
+ return Hi == Reg.Hi && Lo == Reg.Lo;
+}
+
+template <EdgeKind_aarch32 Kind>
+bool writeRegister(WritableThumbRelocation &R, HalfWords Reg) {
+ static constexpr HalfWords Mask = FixupInfo<Kind>::RegMask;
+ assert((Mask.Hi & Reg.Hi) == Reg.Hi && (Mask.Hi & Reg.Hi) == Reg.Hi &&
+ "Value bits exceed bit range of given mask");
+ R.Hi = (R.Hi & ~Mask.Hi) | Reg.Hi;
+ R.Lo = (R.Lo & ~Mask.Lo) | Reg.Lo;
+}
+
+template <EdgeKind_aarch32 Kind>
+void writeImmediate(WritableThumbRelocation &R, HalfWords Imm) {
+ static constexpr HalfWords Mask = FixupInfo<Kind>::ImmMask;
+ assert((Mask.Hi & Imm.Hi) == Imm.Hi && (Mask.Hi & Imm.Hi) == Imm.Hi &&
+ "Value bits exceed bit range of given mask");
+ R.Hi = (R.Hi & ~Mask.Hi) | Imm.Hi;
+ R.Lo = (R.Lo & ~Mask.Lo) | Imm.Lo;
+}
+
+Expected<int64_t> readAddendData(LinkGraph &G, Block &B, const Edge &E) {
+ support::endianness Endian = G.getEndianness();
+ assert(Endian != support::native && "Declare as little or big explicitly");
+
+ Edge::Kind Kind = E.getKind();
+ const char *BlockWorkingMem = B.getContent().data();
+ const char *FixupPtr = BlockWorkingMem + E.getOffset();
+
+ switch (Kind) {
+ case Data_Delta32:
+ case Data_Pointer32:
+ return SignExtend64<32>(support::endian::read32(FixupPtr, Endian));
+ default:
+ return make_error<JITLinkError>(
+ "In graph " + G.getName() + ", section " + B.getSection().getName() +
+ " can not read implicit addend for aarch32 edge kind " +
+ G.getEdgeKindName(E.getKind()));
+ }
+}
+
+Expected<int64_t> readAddendArm(LinkGraph &G, Block &B, const Edge &E) {
+ Edge::Kind Kind = E.getKind();
+
+ switch (Kind) {
+ case Arm_Call:
+ return make_error<JITLinkError>(
+ "Addend extraction for relocation type not yet implemented: " +
+ StringRef(G.getEdgeKindName(Kind)));
+ default:
+ return make_error<JITLinkError>(
+ "In graph " + G.getName() + ", section " + B.getSection().getName() +
+ " can not read implicit addend for aarch32 edge kind " +
+ G.getEdgeKindName(E.getKind()));
+ }
+}
+
+Expected<int64_t> readAddendThumb(LinkGraph &G, Block &B, const Edge &E,
+ const ArmConfig &ArmCfg) {
+ ThumbRelocation R(B.getContent().data() + E.getOffset());
+ Edge::Kind Kind = E.getKind();
+
+ switch (Kind) {
+ case Thumb_Call:
+ if (!checkOpcode<Thumb_Call>(R))
+ return makeUnexpectedOpcodeError(G, R, Kind);
+ return LLVM_LIKELY(ArmCfg.J1J2BranchEncoding)
+ ? decodeImmBT4BlT1BlxT2_J1J2(R.Hi, R.Lo)
+ : decodeImmBT4BlT1BlxT2(R.Hi, R.Lo);
+
+ case Thumb_Jump24:
+ if (!checkOpcode<Thumb_Jump24>(R))
+ return makeUnexpectedOpcodeError(G, R, Kind);
+ if (R.Lo & FixupInfo<Thumb_Jump24>::LoBitConditional)
+ return make_error<JITLinkError>("Relocation expects an unconditional "
+ "B.W branch instruction: " +
+ StringRef(G.getEdgeKindName(Kind)));
+ return LLVM_LIKELY(ArmCfg.J1J2BranchEncoding)
+ ? decodeImmBT4BlT1BlxT2_J1J2(R.Hi, R.Lo)
+ : decodeImmBT4BlT1BlxT2(R.Hi, R.Lo);
+
+ case Thumb_MovwAbsNC:
+ if (!checkOpcode<Thumb_MovwAbsNC>(R))
+ return makeUnexpectedOpcodeError(G, R, Kind);
+ // Initial addend is interpreted as a signed value
+ return SignExtend64<16>(decodeImmMovtT1MovwT3(R.Hi, R.Lo));
+
+ case Thumb_MovtAbs:
+ if (!checkOpcode<Thumb_MovtAbs>(R))
+ return makeUnexpectedOpcodeError(G, R, Kind);
+ // Initial addend is interpreted as a signed value
+ return SignExtend64<16>(decodeImmMovtT1MovwT3(R.Hi, R.Lo));
+
+ default:
+ return make_error<JITLinkError>(
+ "In graph " + G.getName() + ", section " + B.getSection().getName() +
+ " can not read implicit addend for aarch32 edge kind " +
+ G.getEdgeKindName(E.getKind()));
+ }
+}
+
+Error applyFixupData(LinkGraph &G, Block &B, const Edge &E) {
+ using namespace support;
+
+ char *BlockWorkingMem = B.getAlreadyMutableContent().data();
+ char *FixupPtr = BlockWorkingMem + E.getOffset();
+
+ auto Write32 = [FixupPtr, Endian = G.getEndianness()](int64_t Value) {
+ assert(Endian != native && "Must be explicit: little or big");
+ assert(isInt<32>(Value) && "Must be in signed 32-bit range");
+ uint32_t Imm = static_cast<int32_t>(Value);
+ if (LLVM_LIKELY(Endian == little))
+ endian::write32<little>(FixupPtr, Imm);
+ else
+ endian::write32<big>(FixupPtr, Imm);
+ };
+
+ Edge::Kind Kind = E.getKind();
+ uint64_t FixupAddress = (B.getAddress() + E.getOffset()).getValue();
+ int64_t Addend = E.getAddend();
+ Symbol &TargetSymbol = E.getTarget();
+ uint64_t TargetAddress = TargetSymbol.getAddress().getValue();
+ assert(!TargetSymbol.hasTargetFlags(ThumbSymbol));
+
+ // Regular data relocations have size 4, alignment 1 and write the full 32-bit
+ // result to the place; no need for overflow checking. There are three
+ // exceptions: R_ARM_ABS8, R_ARM_ABS16, R_ARM_PREL31
+ switch (Kind) {
+ case Data_Delta32: {
+ int64_t Value = TargetAddress - FixupAddress + Addend;
+ if (!isInt<32>(Value))
+ return makeTargetOutOfRangeError(G, B, E);
+ Write32(Value);
+ return Error::success();
+ }
+ case Data_Pointer32: {
+ int64_t Value = TargetAddress + Addend;
+ if (!isInt<32>(Value))
+ return makeTargetOutOfRangeError(G, B, E);
+ Write32(Value);
+ return Error::success();
+ }
+ default:
+ return make_error<JITLinkError>(
+ "In graph " + G.getName() + ", section " + B.getSection().getName() +
+ " encountered unfixable aarch32 edge kind " +
+ G.getEdgeKindName(E.getKind()));
+ }
+}
+
+Error applyFixupArm(LinkGraph &G, Block &B, const Edge &E) {
+ Edge::Kind Kind = E.getKind();
+
+ switch (Kind) {
+ case Arm_Call:
+ return make_error<JITLinkError>(
+ "Fix-up for relocation type not yet implemented: " +
+ StringRef(G.getEdgeKindName(Kind)));
+ default:
+ return make_error<JITLinkError>(
+ "In graph " + G.getName() + ", section " + B.getSection().getName() +
+ " encountered unfixable aarch32 edge kind " +
+ G.getEdgeKindName(E.getKind()));
+ }
+}
+
+Error applyFixupThumb(LinkGraph &G, Block &B, const Edge &E,
+ const ArmConfig &ArmCfg) {
+ WritableThumbRelocation R(B.getAlreadyMutableContent().data() +
+ E.getOffset());
+
+ Edge::Kind Kind = E.getKind();
+ uint64_t FixupAddress = (B.getAddress() + E.getOffset()).getValue();
+ int64_t Addend = E.getAddend();
+ Symbol &TargetSymbol = E.getTarget();
+ uint64_t TargetAddress = TargetSymbol.getAddress().getValue();
+ if (TargetSymbol.hasTargetFlags(ThumbSymbol))
+ TargetAddress |= 0x01;
+
+ switch (Kind) {
+ case Thumb_Jump24: {
+ if (!checkOpcode<Thumb_Jump24>(R))
+ return makeUnexpectedOpcodeError(G, R, Kind);
+ if (R.Lo & FixupInfo<Thumb_Jump24>::LoBitConditional)
+ return make_error<JITLinkError>("Relocation expects an unconditional "
+ "B.W branch instruction: " +
+ StringRef(G.getEdgeKindName(Kind)));
+ if (!(TargetSymbol.hasTargetFlags(ThumbSymbol)))
+ return make_error<JITLinkError>("Branch relocation needs interworking "
+ "stub when bridging to ARM: " +
+ StringRef(G.getEdgeKindName(Kind)));
+
+ int64_t Value = TargetAddress - FixupAddress + Addend;
+ if (LLVM_LIKELY(ArmCfg.J1J2BranchEncoding)) {
+ if (!isInt<25>(Value))
+ return makeTargetOutOfRangeError(G, B, E);
+ writeImmediate<Thumb_Jump24>(R, encodeImmBT4BlT1BlxT2_J1J2(Value));
+ } else {
+ if (!isInt<22>(Value))
+ return makeTargetOutOfRangeError(G, B, E);
+ writeImmediate<Thumb_Jump24>(R, encodeImmBT4BlT1BlxT2(Value));
+ }
+
+ return Error::success();
+ }
+
+ case Thumb_Call: {
+ if (!checkOpcode<Thumb_Call>(R))
+ return makeUnexpectedOpcodeError(G, R, Kind);
+
+ int64_t Value = TargetAddress - FixupAddress + Addend;
+
+ // The call instruction itself is Thumb. The call destination can either be
+ // Thumb or Arm. We use BL to stay in Thumb and BLX to change to Arm.
+ bool TargetIsArm = !TargetSymbol.hasTargetFlags(ThumbSymbol);
+ bool InstrIsBlx = (R.Lo & FixupInfo<Thumb_Call>::LoBitNoBlx) == 0;
+ if (TargetIsArm != InstrIsBlx) {
+ if (LLVM_LIKELY(TargetIsArm)) {
+ // Change opcode BL -> BLX and fix range value (account for 4-byte
+ // aligned destination while instruction may only be 2-byte aligned
+ // and clear Thumb bit).
+ R.Lo = R.Lo & ~FixupInfo<Thumb_Call>::LoBitNoBlx;
+ R.Lo = R.Lo & ~FixupInfo<Thumb_Call>::LoBitH;
+ Value = alignTo(Value, 4);
+ } else {
+ // Change opcode BLX -> BL and set Thumb bit
+ R.Lo = R.Lo & ~FixupInfo<Thumb_Call>::LoBitNoBlx;
+ Value |= 0x01;
+ }
+ }
+
+ if (LLVM_LIKELY(ArmCfg.J1J2BranchEncoding)) {
+ if (!isInt<25>(Value))
+ return makeTargetOutOfRangeError(G, B, E);
+ writeImmediate<Thumb_Call>(R, encodeImmBT4BlT1BlxT2_J1J2(Value));
+ } else {
+ if (!isInt<22>(Value))
+ return makeTargetOutOfRangeError(G, B, E);
+ writeImmediate<Thumb_Call>(R, encodeImmBT4BlT1BlxT2(Value));
+ }
+
+ assert(((R.Lo & FixupInfo<Thumb_Call>::LoBitNoBlx) ||
+ (R.Lo & FixupInfo<Thumb_Call>::LoBitH) == 0) &&
+ "Opcode BLX implies H bit is clear (avoid UB in BLX T2)");
+ return Error::success();
+ }
+
+ case Thumb_MovwAbsNC: {
+ if (!checkOpcode<Thumb_MovwAbsNC>(R))
+ return makeUnexpectedOpcodeError(G, R, Kind);
+ uint16_t Value = (TargetAddress + Addend) & 0xffff;
+ writeImmediate<Thumb_MovwAbsNC>(R, encodeImmMovtT1MovwT3(Value));
+ return Error::success();
+ }
+
+ case Thumb_MovtAbs: {
+ if (!checkOpcode<Thumb_MovtAbs>(R))
+ return makeUnexpectedOpcodeError(G, R, Kind);
+ uint16_t Value = ((TargetAddress + Addend) >> 16) & 0xffff;
+ writeImmediate<Thumb_MovtAbs>(R, encodeImmMovtT1MovwT3(Value));
+ return Error::success();
+ }
+
+ default:
+ return make_error<JITLinkError>(
+ "In graph " + G.getName() + ", section " + B.getSection().getName() +
+ " encountered unfixable aarch32 edge kind " +
+ G.getEdgeKindName(E.getKind()));
+ }
+}
+
+const uint8_t Thumbv7ABS[] = {
+ 0x40, 0xf2, 0x00, 0x0c, // movw r12, #0x0000 ; lower 16-bit
+ 0xc0, 0xf2, 0x00, 0x0c, // movt r12, #0x0000 ; upper 16-bit
+ 0x60, 0x47 // bx r12
+};
+
+template <>
+Symbol &StubsManager<Thumbv7>::createEntry(LinkGraph &G, Symbol &Target) {
+ constexpr uint64_t Alignment = 4;
+ Block &B = addStub(G, Thumbv7ABS, Alignment);
+ LLVM_DEBUG({
+ const char *StubPtr = B.getContent().data();
+ HalfWords Reg12 = encodeRegMovtT1MovwT3(12);
+ assert(checkRegister<Thumb_MovwAbsNC>(StubPtr, Reg12) &&
+ checkRegister<Thumb_MovtAbs>(StubPtr + 4, Reg12) &&
+ "Linker generated stubs may only corrupt register r12 (IP)");
+ });
+ B.addEdge(Thumb_MovwAbsNC, 0, Target, 0);
+ B.addEdge(Thumb_MovtAbs, 4, Target, 0);
+ Symbol &Stub = G.addAnonymousSymbol(B, 0, B.getSize(), true, false);
+ Stub.setTargetFlags(ThumbSymbol);
+ return Stub;
+}
+
+const char *getEdgeKindName(Edge::Kind K) {
+#define KIND_NAME_CASE(K) \
+ case K: \
+ return #K;
+
+ switch (K) {
+ KIND_NAME_CASE(Data_Delta32)
+ KIND_NAME_CASE(Arm_Call)
+ KIND_NAME_CASE(Thumb_Call)
+ KIND_NAME_CASE(Thumb_Jump24)
+ KIND_NAME_CASE(Thumb_MovwAbsNC)
+ KIND_NAME_CASE(Thumb_MovtAbs)
+ default:
+ return getGenericEdgeKindName(K);
+ }
+#undef KIND_NAME_CASE
+}
+
+const char *getCPUArchName(ARMBuildAttrs::CPUArch K) {
+#define CPUARCH_NAME_CASE(K) \
+ case K: \
+ return #K;
+
+ using namespace ARMBuildAttrs;
+ switch (K) {
+ CPUARCH_NAME_CASE(Pre_v4)
+ CPUARCH_NAME_CASE(v4)
+ CPUARCH_NAME_CASE(v4T)
+ CPUARCH_NAME_CASE(v5T)
+ CPUARCH_NAME_CASE(v5TE)
+ CPUARCH_NAME_CASE(v5TEJ)
+ CPUARCH_NAME_CASE(v6)
+ CPUARCH_NAME_CASE(v6KZ)
+ CPUARCH_NAME_CASE(v6T2)
+ CPUARCH_NAME_CASE(v6K)
+ CPUARCH_NAME_CASE(v7)
+ CPUARCH_NAME_CASE(v6_M)
+ CPUARCH_NAME_CASE(v6S_M)
+ CPUARCH_NAME_CASE(v7E_M)
+ CPUARCH_NAME_CASE(v8_A)
+ CPUARCH_NAME_CASE(v8_R)
+ CPUARCH_NAME_CASE(v8_M_Base)
+ CPUARCH_NAME_CASE(v8_M_Main)
+ CPUARCH_NAME_CASE(v8_1_M_Main)
+ CPUARCH_NAME_CASE(v9_A)
+ }
+ llvm_unreachable("Missing CPUArch in switch?");
+#undef CPUARCH_NAME_CASE
+}
+
+} // namespace aarch32
+} // namespace jitlink
+} // namespace llvm
diff --git a/llvm/lib/ExecutionEngine/JITLink/aarch64.cpp b/llvm/lib/ExecutionEngine/JITLink/aarch64.cpp
index 1011fa81f750..cc58255a338d 100644
--- a/llvm/lib/ExecutionEngine/JITLink/aarch64.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/aarch64.cpp
@@ -47,6 +47,12 @@ const char *getEdgeKindName(Edge::Kind R) {
return "MoveWide16";
case LDRLiteral19:
return "LDRLiteral19";
+ case TestAndBranch14PCRel:
+ return "TestAndBranch14PCRel";
+ case CondBranch19PCRel:
+ return "CondBranch19PCRel";
+ case ADRLiteral21:
+ return "ADRLiteral21";
case Page21:
return "Page21";
case PageOffset12:
diff --git a/llvm/lib/ExecutionEngine/JITLink/i386.cpp b/llvm/lib/ExecutionEngine/JITLink/i386.cpp
index c2c5761cd272..e984bb10983d 100644
--- a/llvm/lib/ExecutionEngine/JITLink/i386.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/i386.cpp
@@ -34,10 +34,58 @@ const char *getEdgeKindName(Edge::Kind K) {
return "Delta32FromGOT";
case RequestGOTAndTransformToDelta32FromGOT:
return "RequestGOTAndTransformToDelta32FromGOT";
+ case BranchPCRel32:
+ return "BranchPCRel32";
+ case BranchPCRel32ToPtrJumpStub:
+ return "BranchPCRel32ToPtrJumpStub";
+ case BranchPCRel32ToPtrJumpStubBypassable:
+ return "BranchPCRel32ToPtrJumpStubBypassable";
}
return getGenericEdgeKindName(K);
}
const char NullPointerContent[PointerSize] = {0x00, 0x00, 0x00, 0x00};
+
+const char PointerJumpStubContent[6] = {
+ static_cast<char>(0xFFu), 0x25, 0x00, 0x00, 0x00, 0x00};
+
+Error optimizeGOTAndStubAccesses(LinkGraph &G) {
+ LLVM_DEBUG(dbgs() << "Optimizing GOT entries and stubs:\n");
+
+ for (auto *B : G.blocks())
+ for (auto &E : B->edges()) {
+ if (E.getKind() == i386::BranchPCRel32ToPtrJumpStubBypassable) {
+ auto &StubBlock = E.getTarget().getBlock();
+ assert(StubBlock.getSize() == sizeof(PointerJumpStubContent) &&
+ "Stub block should be stub sized");
+ assert(StubBlock.edges_size() == 1 &&
+ "Stub block should only have one outgoing edge");
+
+ auto &GOTBlock = StubBlock.edges().begin()->getTarget().getBlock();
+ assert(GOTBlock.getSize() == G.getPointerSize() &&
+ "GOT block should be pointer sized");
+ assert(GOTBlock.edges_size() == 1 &&
+ "GOT block should only have one outgoing edge");
+
+ auto &GOTTarget = GOTBlock.edges().begin()->getTarget();
+ orc::ExecutorAddr EdgeAddr = B->getAddress() + E.getOffset();
+ orc::ExecutorAddr TargetAddr = GOTTarget.getAddress();
+
+ int64_t Displacement = TargetAddr - EdgeAddr + 4;
+ if (isInt<32>(Displacement)) {
+ E.setKind(i386::BranchPCRel32);
+ E.setTarget(GOTTarget);
+ LLVM_DEBUG({
+ dbgs() << " Replaced stub branch with direct branch:\n ";
+ printEdge(dbgs(), *B, E, getEdgeKindName(E.getKind()));
+ dbgs() << "\n";
+ });
+ }
+ }
+ }
+
+ return Error::success();
+}
+
} // namespace llvm::jitlink::i386
diff --git a/llvm/lib/ExecutionEngine/JITLink/ppc64.cpp b/llvm/lib/ExecutionEngine/JITLink/ppc64.cpp
new file mode 100644
index 000000000000..4e21eace21d0
--- /dev/null
+++ b/llvm/lib/ExecutionEngine/JITLink/ppc64.cpp
@@ -0,0 +1,102 @@
+//===----- ppc64.cpp - Generic JITLink ppc64 edge kinds, utilities ------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+// Generic utilities for graphs representing 64-bit PowerPC objects.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ExecutionEngine/JITLink/ppc64.h"
+
+#define DEBUG_TYPE "jitlink"
+
+namespace llvm::jitlink::ppc64 {
+
+const char NullPointerContent[8] = {0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00};
+
+const char PointerJumpStubContent_little[20] = {
+ 0x18, 0x00, 0x41, (char)0xf8, // std r2, 24(r1)
+ 0x00, 0x00, (char)0x82, 0x3d, // addis r12, r2, OffHa
+ 0x00, 0x00, (char)0x8c, (char)0xe9, // ld r12, OffLo(r12)
+ (char)0xa6, 0x03, (char)0x89, 0x7d, // mtctr r12
+ 0x20, 0x04, (char)0x80, 0x4e, // bctr
+};
+
+const char PointerJumpStubContent_big[20] = {
+ (char)0xf8, 0x41, 0x00, 0x18, // std r2, 24(r1)
+ 0x3d, (char)0x82, 0x00, 0x00, // addis r12, r2, OffHa
+ (char)0xe9, (char)0x8c, 0x00, 0x00, // ld r12, OffLo(r12)
+ 0x7d, (char)0x89, 0x03, (char)0xa6, // mtctr r12
+ 0x4e, (char)0x80, 0x04, 0x20, // bctr
+};
+
+// TODO: We can use prefixed instructions if LLJIT is running on power10.
+const char PointerJumpStubNoTOCContent_little[32] = {
+ (char)0xa6, 0x02, (char)0x88, 0x7d, // mflr 12
+ 0x05, (char)0x00, (char)0x9f, 0x42, // bcl 20,31,.+4
+ (char)0xa6, 0x02, 0x68, 0x7d, // mflr 11
+ (char)0xa6, 0x03, (char)0x88, 0x7d, // mtlr 12
+ 0x00, 0x00, (char)0x8b, 0x3d, // addis 12,11,OffHa
+ 0x00, 0x00, (char)0x8c, (char)0xe9, // ld 12, OffLo(12)
+ (char)0xa6, 0x03, (char)0x89, 0x7d, // mtctr 12
+ 0x20, 0x04, (char)0x80, 0x4e, // bctr
+};
+
+const char PointerJumpStubNoTOCContent_big[32] = {
+ 0x7d, (char)0x88, 0x02, (char)0xa6, // mflr 12
+ 0x42, (char)0x9f, 0x00, 0x05, // bcl 20,31,.+4
+ 0x7d, 0x68, 0x02, (char)0xa6, // mflr 11
+ 0x7d, (char)0x88, 0x03, (char)0xa6, // mtlr 12
+ 0x3d, (char)0x8b, 0x00, 0x00, // addis 12,11,OffHa
+ (char)0xe9, (char)0x8c, 0x00, 0x00, // ld 12, OffLo(12)
+ 0x7d, (char)0x89, 0x03, (char)0xa6, // mtctr 12
+ 0x4e, (char)0x80, 0x04, 0x20, // bctr
+};
+
+const char *getEdgeKindName(Edge::Kind K) {
+ switch (K) {
+ case Pointer64:
+ return "Pointer64";
+ case Pointer32:
+ return "Pointer32";
+ case Delta64:
+ return "Delta64";
+ case Delta32:
+ return "Delta32";
+ case NegDelta32:
+ return "NegDelta32";
+ case Delta16:
+ return "Delta16";
+ case Delta16HA:
+ return "Delta16HA";
+ case Delta16LO:
+ return "Delta16LO";
+ case TOCDelta16HA:
+ return "TOCDelta16HA";
+ case TOCDelta16LO:
+ return "TOCDelta16LO";
+ case TOCDelta16DS:
+ return "TOCDelta16DS";
+ case TOCDelta16LODS:
+ return "TOCDelta16LODS";
+ case CallBranchDelta:
+ return "CallBranchDelta";
+ case CallBranchDeltaRestoreTOC:
+ return "CallBranchDeltaRestoreTOC";
+ case RequestPLTCallStub:
+ return "RequestPLTCallStub";
+ case RequestPLTCallStubSaveTOC:
+ return "RequestPLTCallStubSaveTOC";
+ case RequestPLTCallStubNoTOC:
+ return "RequestPLTCallStubNoTOC";
+ default:
+ return getGenericEdgeKindName(static_cast<Edge::Kind>(K));
+ }
+}
+
+} // end namespace llvm::jitlink::ppc64
diff --git a/llvm/lib/ExecutionEngine/JITLink/riscv.cpp b/llvm/lib/ExecutionEngine/JITLink/riscv.cpp
index 6ee92b065ca1..a78843b16147 100644
--- a/llvm/lib/ExecutionEngine/JITLink/riscv.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/riscv.cpp
@@ -78,6 +78,10 @@ const char *getEdgeKindName(Edge::Kind K) {
return "R_RISCV_SET32";
case R_RISCV_32_PCREL:
return "R_RISCV_32_PCREL";
+ case CallRelaxable:
+ return "CallRelaxable";
+ case AlignRelaxable:
+ return "AlignRelaxable";
}
return getGenericEdgeKindName(K);
}
diff --git a/llvm/lib/ExecutionEngine/JITLink/x86_64.cpp b/llvm/lib/ExecutionEngine/JITLink/x86_64.cpp
index 097e19e02530..273ac7b372a7 100644
--- a/llvm/lib/ExecutionEngine/JITLink/x86_64.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/x86_64.cpp
@@ -28,6 +28,8 @@ const char *getEdgeKindName(Edge::Kind K) {
return "Pointer32Signed";
case Pointer16:
return "Pointer16";
+ case Pointer8:
+ return "Pointer8";
case Delta64:
return "Delta64";
case Delta32:
@@ -102,8 +104,8 @@ Error optimizeGOTAndStubAccesses(LinkGraph &G) {
orc::ExecutorAddr TargetAddr = GOTTarget.getAddress();
orc::ExecutorAddr EdgeAddr = B->getFixupAddress(E);
int64_t Displacement = TargetAddr - EdgeAddr + 4;
- bool TargetInRangeForImmU32 = isInRangeForImmU32(TargetAddr.getValue());
- bool DisplacementInRangeForImmS32 = isInRangeForImmS32(Displacement);
+ bool TargetInRangeForImmU32 = isUInt<32>(TargetAddr.getValue());
+ bool DisplacementInRangeForImmS32 = isInt<32>(Displacement);
// If both of the Target and displacement is out of range, then
// there isn't optimization chance.
@@ -173,7 +175,7 @@ Error optimizeGOTAndStubAccesses(LinkGraph &G) {
orc::ExecutorAddr TargetAddr = GOTTarget.getAddress();
int64_t Displacement = TargetAddr - EdgeAddr + 4;
- if (isInRangeForImmS32(Displacement)) {
+ if (isInt<32>(Displacement)) {
E.setKind(x86_64::BranchPCRel32);
E.setTarget(GOTTarget);
LLVM_DEBUG({
diff --git a/llvm/lib/ExecutionEngine/Orc/COFFPlatform.cpp b/llvm/lib/ExecutionEngine/Orc/COFFPlatform.cpp
index 40716a7f9b61..7c869bead0b0 100644
--- a/llvm/lib/ExecutionEngine/Orc/COFFPlatform.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/COFFPlatform.cpp
@@ -10,6 +10,7 @@
#include "llvm/ExecutionEngine/Orc/DebugUtils.h"
#include "llvm/ExecutionEngine/Orc/LookupAndRecordAddrs.h"
#include "llvm/ExecutionEngine/Orc/ObjectFileInterface.h"
+#include "llvm/ExecutionEngine/Orc/Shared/ObjectFormats.h"
#include "llvm/Object/COFF.h"
@@ -54,8 +55,7 @@ public:
void materialize(std::unique_ptr<MaterializationResponsibility> R) override {
unsigned PointerSize;
support::endianness Endianness;
- const auto &TT =
- CP.getExecutionSession().getExecutorProcessControl().getTargetTriple();
+ const auto &TT = CP.getExecutionSession().getTargetTriple();
switch (TT.getArch()) {
case Triple::x86_64:
@@ -125,8 +125,8 @@ private:
llvm_unreachable("Unrecognized architecture");
}
- auto HeaderContent = G.allocateString(
- StringRef(reinterpret_cast<const char *>(&Hdr), sizeof(Hdr)));
+ auto HeaderContent = G.allocateContent(
+ ArrayRef<char>(reinterpret_cast<const char *>(&Hdr), sizeof(Hdr)));
return G.createContentBlock(HeaderSection, HeaderContent, ExecutorAddr(), 8,
0);
@@ -159,20 +159,36 @@ private:
namespace llvm {
namespace orc {
-Expected<std::unique_ptr<COFFPlatform>>
-COFFPlatform::Create(ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer,
- JITDylib &PlatformJD, const char *OrcRuntimePath,
- LoadDynamicLibrary LoadDynLibrary, bool StaticVCRuntime,
- const char *VCRuntimePath,
- std::optional<SymbolAliasMap> RuntimeAliases) {
- auto &EPC = ES.getExecutorProcessControl();
+Expected<std::unique_ptr<COFFPlatform>> COFFPlatform::Create(
+ ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer,
+ JITDylib &PlatformJD, std::unique_ptr<MemoryBuffer> OrcRuntimeArchiveBuffer,
+ LoadDynamicLibrary LoadDynLibrary, bool StaticVCRuntime,
+ const char *VCRuntimePath, std::optional<SymbolAliasMap> RuntimeAliases) {
// If the target is not supported then bail out immediately.
- if (!supportedTarget(EPC.getTargetTriple()))
+ if (!supportedTarget(ES.getTargetTriple()))
return make_error<StringError>("Unsupported COFFPlatform triple: " +
- EPC.getTargetTriple().str(),
+ ES.getTargetTriple().str(),
inconvertibleErrorCode());
+ auto &EPC = ES.getExecutorProcessControl();
+
+ auto GeneratorArchive =
+ object::Archive::create(OrcRuntimeArchiveBuffer->getMemBufferRef());
+ if (!GeneratorArchive)
+ return GeneratorArchive.takeError();
+
+ auto OrcRuntimeArchiveGenerator = StaticLibraryDefinitionGenerator::Create(
+ ObjLinkingLayer, nullptr, std::move(*GeneratorArchive));
+ if (!OrcRuntimeArchiveGenerator)
+ return OrcRuntimeArchiveGenerator.takeError();
+
+ // We need a second instance of the archive (for now) for the Platform. We
+ // can `cantFail` this call, since if it were going to fail it would have
+ // failed above.
+ auto RuntimeArchive = cantFail(
+ object::Archive::create(OrcRuntimeArchiveBuffer->getMemBufferRef()));
+
// Create default aliases if the caller didn't supply any.
if (!RuntimeAliases)
RuntimeAliases = standardPlatformAliases(ES);
@@ -184,13 +200,13 @@ COFFPlatform::Create(ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer,
auto &HostFuncJD = ES.createBareJITDylib("$<PlatformRuntimeHostFuncJD>");
// Add JIT-dispatch function support symbols.
- if (auto Err = HostFuncJD.define(absoluteSymbols(
- {{ES.intern("__orc_rt_jit_dispatch"),
- {EPC.getJITDispatchInfo().JITDispatchFunction.getValue(),
- JITSymbolFlags::Exported}},
- {ES.intern("__orc_rt_jit_dispatch_ctx"),
- {EPC.getJITDispatchInfo().JITDispatchContext.getValue(),
- JITSymbolFlags::Exported}}})))
+ if (auto Err = HostFuncJD.define(
+ absoluteSymbols({{ES.intern("__orc_rt_jit_dispatch"),
+ {EPC.getJITDispatchInfo().JITDispatchFunction,
+ JITSymbolFlags::Exported}},
+ {ES.intern("__orc_rt_jit_dispatch_ctx"),
+ {EPC.getJITDispatchInfo().JITDispatchContext,
+ JITSymbolFlags::Exported}}})))
return std::move(Err);
PlatformJD.addToLinkOrder(HostFuncJD);
@@ -198,13 +214,30 @@ COFFPlatform::Create(ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer,
// Create the instance.
Error Err = Error::success();
auto P = std::unique_ptr<COFFPlatform>(new COFFPlatform(
- ES, ObjLinkingLayer, PlatformJD, OrcRuntimePath,
+ ES, ObjLinkingLayer, PlatformJD, std::move(*OrcRuntimeArchiveGenerator),
+ std::move(OrcRuntimeArchiveBuffer), std::move(RuntimeArchive),
std::move(LoadDynLibrary), StaticVCRuntime, VCRuntimePath, Err));
if (Err)
return std::move(Err);
return std::move(P);
}
+Expected<std::unique_ptr<COFFPlatform>>
+COFFPlatform::Create(ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer,
+ JITDylib &PlatformJD, const char *OrcRuntimePath,
+ LoadDynamicLibrary LoadDynLibrary, bool StaticVCRuntime,
+ const char *VCRuntimePath,
+ std::optional<SymbolAliasMap> RuntimeAliases) {
+
+ auto ArchiveBuffer = MemoryBuffer::getFile(OrcRuntimePath);
+ if (!ArchiveBuffer)
+ return createFileError(OrcRuntimePath, ArchiveBuffer.getError());
+
+ return Create(ES, ObjLinkingLayer, PlatformJD, std::move(*ArchiveBuffer),
+ std::move(LoadDynLibrary), StaticVCRuntime, VCRuntimePath,
+ std::move(RuntimeAliases));
+}
+
Expected<MemoryBufferRef> COFFPlatform::getPerJDObjectFile() {
auto PerJDObj = OrcRuntimeArchive->findSym("__orc_rt_coff_per_jd_marker");
if (!PerJDObj)
@@ -348,37 +381,22 @@ bool COFFPlatform::supportedTarget(const Triple &TT) {
}
}
-COFFPlatform::COFFPlatform(ExecutionSession &ES,
- ObjectLinkingLayer &ObjLinkingLayer,
- JITDylib &PlatformJD, const char *OrcRuntimePath,
- LoadDynamicLibrary LoadDynLibrary,
- bool StaticVCRuntime, const char *VCRuntimePath,
- Error &Err)
+COFFPlatform::COFFPlatform(
+ ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer,
+ JITDylib &PlatformJD,
+ std::unique_ptr<StaticLibraryDefinitionGenerator> OrcRuntimeGenerator,
+ std::unique_ptr<MemoryBuffer> OrcRuntimeArchiveBuffer,
+ std::unique_ptr<object::Archive> OrcRuntimeArchive,
+ LoadDynamicLibrary LoadDynLibrary, bool StaticVCRuntime,
+ const char *VCRuntimePath, Error &Err)
: ES(ES), ObjLinkingLayer(ObjLinkingLayer),
LoadDynLibrary(std::move(LoadDynLibrary)),
+ OrcRuntimeArchiveBuffer(std::move(OrcRuntimeArchiveBuffer)),
+ OrcRuntimeArchive(std::move(OrcRuntimeArchive)),
StaticVCRuntime(StaticVCRuntime),
COFFHeaderStartSymbol(ES.intern("__ImageBase")) {
ErrorAsOutParameter _(&Err);
- // Create a generator for the ORC runtime archive.
- auto OrcRuntimeArchiveGenerator =
- StaticLibraryDefinitionGenerator::Load(ObjLinkingLayer, OrcRuntimePath);
- if (!OrcRuntimeArchiveGenerator) {
- Err = OrcRuntimeArchiveGenerator.takeError();
- return;
- }
-
- auto ArchiveBuffer = MemoryBuffer::getFile(OrcRuntimePath);
- if (!ArchiveBuffer) {
- Err = createFileError(OrcRuntimePath, ArchiveBuffer.getError());
- return;
- }
- OrcRuntimeArchiveBuffer = std::move(*ArchiveBuffer);
- OrcRuntimeArchive =
- std::make_unique<object::Archive>(*OrcRuntimeArchiveBuffer, Err);
- if (Err)
- return;
-
Bootstrapping.store(true);
ObjLinkingLayer.addPlugin(std::make_unique<COFFPlatformPlugin>(*this));
@@ -391,7 +409,7 @@ COFFPlatform::COFFPlatform(ExecutionSession &ES,
}
VCRuntimeBootstrap = std::move(*VCRT);
- for (auto &Lib : (*OrcRuntimeArchiveGenerator)->getImportedDynamicLibraries())
+ for (auto &Lib : OrcRuntimeGenerator->getImportedDynamicLibraries())
DylibsToPreload.insert(Lib);
auto ImportedLibs =
@@ -405,7 +423,7 @@ COFFPlatform::COFFPlatform(ExecutionSession &ES,
for (auto &Lib : *ImportedLibs)
DylibsToPreload.insert(Lib);
- PlatformJD.addGenerator(std::move(*OrcRuntimeArchiveGenerator));
+ PlatformJD.addGenerator(std::move(OrcRuntimeGenerator));
// PlatformJD hasn't been set up by the platform yet (since we're creating
// the platform now), so set it up.
@@ -415,10 +433,10 @@ COFFPlatform::COFFPlatform(ExecutionSession &ES,
}
for (auto& Lib : DylibsToPreload)
- if (auto E2 = LoadDynLibrary(PlatformJD, Lib)) {
- Err = std::move(E2);
- return;
- }
+ if (auto E2 = this->LoadDynLibrary(PlatformJD, Lib)) {
+ Err = std::move(E2);
+ return;
+ }
if (StaticVCRuntime)
if (auto E2 = VCRuntimeBootstrap->initializeStaticVCRuntime(PlatformJD)) {
@@ -561,10 +579,9 @@ void COFFPlatform::rt_pushInitializers(PushInitializersSendResultFn SendResult,
});
if (!JD) {
- SendResult(
- make_error<StringError>("No JITDylib with header addr " +
- formatv("{0:x}", JDHeaderAddr.getValue()),
- inconvertibleErrorCode()));
+ SendResult(make_error<StringError>("No JITDylib with header addr " +
+ formatv("{0:x}", JDHeaderAddr),
+ inconvertibleErrorCode()));
return;
}
@@ -579,10 +596,7 @@ void COFFPlatform::rt_pushInitializers(PushInitializersSendResultFn SendResult,
void COFFPlatform::rt_lookupSymbol(SendSymbolAddressFn SendResult,
ExecutorAddr Handle, StringRef SymbolName) {
- LLVM_DEBUG({
- dbgs() << "COFFPlatform::rt_lookupSymbol(\""
- << formatv("{0:x}", Handle.getValue()) << "\")\n";
- });
+ LLVM_DEBUG(dbgs() << "COFFPlatform::rt_lookupSymbol(\"" << Handle << "\")\n");
JITDylib *JD = nullptr;
@@ -594,12 +608,9 @@ void COFFPlatform::rt_lookupSymbol(SendSymbolAddressFn SendResult,
}
if (!JD) {
- LLVM_DEBUG({
- dbgs() << " No JITDylib for handle "
- << formatv("{0:x}", Handle.getValue()) << "\n";
- });
+ LLVM_DEBUG(dbgs() << " No JITDylib for handle " << Handle << "\n");
SendResult(make_error<StringError>("No JITDylib associated with handle " +
- formatv("{0:x}", Handle.getValue()),
+ formatv("{0:x}", Handle),
inconvertibleErrorCode()));
return;
}
@@ -612,7 +623,7 @@ void COFFPlatform::rt_lookupSymbol(SendSymbolAddressFn SendResult,
void operator()(Expected<SymbolMap> Result) {
if (Result) {
assert(Result->size() == 1 && "Unexpected result map count");
- SendResult(ExecutorAddr(Result->begin()->second.getAddress()));
+ SendResult(Result->begin()->second.getAddress());
} else {
SendResult(Result.takeError());
}
@@ -850,7 +861,7 @@ Error COFFPlatform::COFFPlatformPlugin::preserveInitializerSections(
jitlink::LinkGraph &G, MaterializationResponsibility &MR) {
JITLinkSymbolSet InitSectionSymbols;
for (auto &Sec : G.sections())
- if (COFFPlatform::isInitializerSection(Sec.getName()))
+ if (isCOFFInitializerSection(Sec.getName()))
for (auto *B : Sec.blocks())
if (!B->edges_empty())
InitSectionSymbols.insert(
@@ -885,14 +896,13 @@ Error COFFPlatform::COFFPlatformPlugin::
// Collect static initializers
for (auto &S : G.sections())
- if (COFFPlatform::isInitializerSection(S.getName()))
+ if (isCOFFInitializerSection(S.getName()))
for (auto *B : S.blocks()) {
if (B->edges_empty())
continue;
for (auto &E : B->edges())
BState.Initializers.push_back(std::make_pair(
- S.getName().str(),
- ExecutorAddr(E.getTarget().getAddress() + E.getAddend())));
+ S.getName().str(), E.getTarget().getAddress() + E.getAddend()));
}
return Error::success();
diff --git a/llvm/lib/ExecutionEngine/Orc/COFFVCRuntimeSupport.cpp b/llvm/lib/ExecutionEngine/Orc/COFFVCRuntimeSupport.cpp
index d9316fab2de3..94f696fa2086 100644
--- a/llvm/lib/ExecutionEngine/Orc/COFFVCRuntimeSupport.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/COFFVCRuntimeSupport.cpp
@@ -160,7 +160,7 @@ COFFVCRuntimeBootstrapper::getMSVCToolchainPath() {
if (!findVCToolChainViaCommandLine(*VFS, std::nullopt, std::nullopt,
std::nullopt, VCToolChainPath, VSLayout) &&
!findVCToolChainViaEnvironment(*VFS, VCToolChainPath, VSLayout) &&
- !findVCToolChainViaSetupConfig(*VFS, VCToolChainPath, VSLayout) &&
+ !findVCToolChainViaSetupConfig(*VFS, {}, VCToolChainPath, VSLayout) &&
!findVCToolChainViaRegistry(VCToolChainPath, VSLayout))
return make_error<StringError>("Couldn't find msvc toolchain.",
inconvertibleErrorCode());
diff --git a/llvm/lib/ExecutionEngine/Orc/Core.cpp b/llvm/lib/ExecutionEngine/Orc/Core.cpp
index 4a9d0d470a8e..0c23f2b25219 100644
--- a/llvm/lib/ExecutionEngine/Orc/Core.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/Core.cpp
@@ -167,15 +167,16 @@ AsynchronousSymbolQuery::AsynchronousSymbolQuery(
OutstandingSymbolsCount = Symbols.size();
for (auto &KV : Symbols)
- ResolvedSymbols[KV.first] = nullptr;
+ ResolvedSymbols[KV.first] = ExecutorSymbolDef();
}
void AsynchronousSymbolQuery::notifySymbolMetRequiredState(
- const SymbolStringPtr &Name, JITEvaluatedSymbol Sym) {
+ const SymbolStringPtr &Name, ExecutorSymbolDef Sym) {
auto I = ResolvedSymbols.find(Name);
assert(I != ResolvedSymbols.end() &&
"Resolving symbol outside the requested set");
- assert(I->second.getAddress() == 0 && "Redundantly resolving symbol Name");
+ assert(I->second == ExecutorSymbolDef() &&
+ "Redundantly resolving symbol Name");
// If this is a materialization-side-effects-only symbol then drop it,
// otherwise update its map entry with its resolved address.
@@ -447,8 +448,8 @@ void ReExportsMaterializationUnit::materialize(
if (KV.second.AliasFlags.hasMaterializationSideEffectsOnly())
continue;
- ResolutionMap[KV.first] = JITEvaluatedSymbol(
- (*Result)[KV.second.Aliasee].getAddress(), KV.second.AliasFlags);
+ ResolutionMap[KV.first] = {(*Result)[KV.second.Aliasee].getAddress(),
+ KV.second.AliasFlags};
}
if (auto Err = QueryInfo->R->notifyResolved(ResolutionMap)) {
ES.reportError(std::move(Err));
@@ -688,11 +689,15 @@ void JITDylib::removeGenerator(DefinitionGenerator &G) {
}
Expected<SymbolFlagsMap>
-JITDylib::defineMaterializing(SymbolFlagsMap SymbolFlags) {
+JITDylib::defineMaterializing(MaterializationResponsibility &FromMR,
+ SymbolFlagsMap SymbolFlags) {
return ES.runSessionLocked([&]() -> Expected<SymbolFlagsMap> {
- std::vector<SymbolTable::iterator> AddedSyms;
- std::vector<SymbolFlagsMap::iterator> RejectedWeakDefs;
+ if (FromMR.RT->isDefunct())
+ return make_error<ResourceTrackerDefunct>(FromMR.RT);
+
+ std::vector<NonOwningSymbolStringPtr> AddedSyms;
+ std::vector<NonOwningSymbolStringPtr> RejectedWeakDefs;
for (auto SFItr = SymbolFlags.begin(), SFEnd = SymbolFlags.end();
SFItr != SFEnd; ++SFItr) {
@@ -708,27 +713,27 @@ JITDylib::defineMaterializing(SymbolFlagsMap SymbolFlags) {
// If this is a strong definition then error out.
if (!Flags.isWeak()) {
// Remove any symbols already added.
- for (auto &SI : AddedSyms)
- Symbols.erase(SI);
+ for (auto &S : AddedSyms)
+ Symbols.erase(Symbols.find_as(S));
// FIXME: Return all duplicates.
return make_error<DuplicateDefinition>(std::string(*Name));
}
// Otherwise just make a note to discard this symbol after the loop.
- RejectedWeakDefs.push_back(SFItr);
+ RejectedWeakDefs.push_back(NonOwningSymbolStringPtr(Name));
continue;
} else
EntryItr =
Symbols.insert(std::make_pair(Name, SymbolTableEntry(Flags))).first;
- AddedSyms.push_back(EntryItr);
+ AddedSyms.push_back(NonOwningSymbolStringPtr(Name));
EntryItr->second.setState(SymbolState::Materializing);
}
// Remove any rejected weak definitions from the SymbolFlags map.
while (!RejectedWeakDefs.empty()) {
- SymbolFlags.erase(RejectedWeakDefs.back());
+ SymbolFlags.erase(SymbolFlags.find_as(RejectedWeakDefs.back()));
RejectedWeakDefs.pop_back();
}
@@ -944,7 +949,7 @@ Error JITDylib::resolve(MaterializationResponsibility &MR,
struct WorklistEntry {
SymbolTable::iterator SymI;
- JITEvaluatedSymbol ResolvedSym;
+ ExecutorSymbolDef ResolvedSym;
};
SymbolNameSet SymbolsInErrorState;
@@ -964,7 +969,7 @@ Error JITDylib::resolve(MaterializationResponsibility &MR,
"Resolving symbol with materializer attached?");
assert(SymI->second.getState() == SymbolState::Materializing &&
"Symbol should be materializing");
- assert(SymI->second.getAddress() == 0 &&
+ assert(SymI->second.getAddress() == ExecutorAddr() &&
"Symbol has already been resolved");
if (SymI->second.getFlags().hasError())
@@ -976,8 +981,7 @@ Error JITDylib::resolve(MaterializationResponsibility &MR,
(SymI->second.getFlags() & ~JITSymbolFlags::Common) &&
"Resolved flags should match the declared flags");
- Worklist.push_back(
- {SymI, JITEvaluatedSymbol(KV.second.getAddress(), Flags)});
+ Worklist.push_back({SymI, {KV.second.getAddress(), Flags}});
}
}
@@ -1328,6 +1332,18 @@ void JITDylib::setLinkOrder(JITDylibSearchOrder NewLinkOrder,
});
}
+void JITDylib::addToLinkOrder(const JITDylibSearchOrder &NewLinks) {
+ ES.runSessionLocked([&]() {
+ for (auto &KV : NewLinks) {
+ // Skip elements of NewLinks that are already in the link order.
+ if (llvm::find(LinkOrder, KV) != LinkOrder.end())
+ continue;
+
+ LinkOrder.push_back(std::move(KV));
+ }
+ });
+}
+
void JITDylib::addToLinkOrder(JITDylib &JD, JITDylibLookupFlags JDLookupFlags) {
ES.runSessionLocked([&]() { LinkOrder.push_back({&JD, JDLookupFlags}); });
}
@@ -1437,16 +1453,23 @@ void JITDylib::dump(raw_ostream &OS) {
OS << "Link order: " << LinkOrder << "\n"
<< "Symbol table:\n";
- for (auto &KV : Symbols) {
+ // Sort symbols so we get a deterministic order and can check them in tests.
+ std::vector<std::pair<SymbolStringPtr, SymbolTableEntry *>> SymbolsSorted;
+ for (auto &KV : Symbols)
+ SymbolsSorted.emplace_back(KV.first, &KV.second);
+ std::sort(SymbolsSorted.begin(), SymbolsSorted.end(),
+ [](const auto &L, const auto &R) { return *L.first < *R.first; });
+
+ for (auto &KV : SymbolsSorted) {
OS << " \"" << *KV.first << "\": ";
- if (auto Addr = KV.second.getAddress())
- OS << format("0x%016" PRIx64, Addr);
+ if (auto Addr = KV.second->getAddress())
+ OS << Addr;
else
OS << "<not resolved> ";
- OS << " " << KV.second.getFlags() << " " << KV.second.getState();
+ OS << " " << KV.second->getFlags() << " " << KV.second->getState();
- if (KV.second.hasMaterializerAttached()) {
+ if (KV.second->hasMaterializerAttached()) {
OS << " (Materializer ";
auto I = UnmaterializedInfos.find(KV.first);
assert(I != UnmaterializedInfos.end() &&
@@ -1940,6 +1963,7 @@ JITDylib *ExecutionSession::getJITDylibByName(StringRef Name) {
JITDylib &ExecutionSession::createBareJITDylib(std::string Name) {
assert(!getJITDylibByName(Name) && "JITDylib with that name already exists");
return runSessionLocked([&, this]() -> JITDylib & {
+ assert(SessionOpen && "Cannot create JITDylib after session is closed");
JDs.push_back(new JITDylib(*this, std::move(Name)));
return *JDs.back();
});
@@ -2156,7 +2180,7 @@ ExecutionSession::lookup(const JITDylibSearchOrder &SearchOrder,
#endif
}
-Expected<JITEvaluatedSymbol>
+Expected<ExecutorSymbolDef>
ExecutionSession::lookup(const JITDylibSearchOrder &SearchOrder,
SymbolStringPtr Name, SymbolState RequiredState) {
SymbolLookupSet Names({Name});
@@ -2170,13 +2194,13 @@ ExecutionSession::lookup(const JITDylibSearchOrder &SearchOrder,
return ResultMap.takeError();
}
-Expected<JITEvaluatedSymbol>
+Expected<ExecutorSymbolDef>
ExecutionSession::lookup(ArrayRef<JITDylib *> SearchOrder, SymbolStringPtr Name,
SymbolState RequiredState) {
return lookup(makeJITDylibSearchOrder(SearchOrder), Name, RequiredState);
}
-Expected<JITEvaluatedSymbol>
+Expected<ExecutorSymbolDef>
ExecutionSession::lookup(ArrayRef<JITDylib *> SearchOrder, StringRef Name,
SymbolState RequiredState) {
return lookup(SearchOrder, intern(Name), RequiredState);
@@ -2213,9 +2237,9 @@ Error ExecutionSession::registerJITDispatchHandlers(
return Error::success();
}
-void ExecutionSession::runJITDispatchHandler(
- SendResultFunction SendResult, JITTargetAddress HandlerFnTagAddr,
- ArrayRef<char> ArgBuffer) {
+void ExecutionSession::runJITDispatchHandler(SendResultFunction SendResult,
+ ExecutorAddr HandlerFnTagAddr,
+ ArrayRef<char> ArgBuffer) {
std::shared_ptr<JITDispatchHandlerFunction> F;
{
@@ -2666,7 +2690,7 @@ void ExecutionSession::OL_completeLookup(
// whether it has a materializer attached, and if so prepare to run
// it.
if (SymI->second.hasMaterializerAttached()) {
- assert(SymI->second.getAddress() == 0 &&
+ assert(SymI->second.getAddress() == ExecutorAddr() &&
"Symbol not resolved but already has address?");
auto UMII = JD.UnmaterializedInfos.find(Name);
assert(UMII != JD.UnmaterializedInfos.end() &&
@@ -2946,7 +2970,7 @@ Error ExecutionSession::OL_defineMaterializing(
<< NewSymbolFlags << "\n";
});
if (auto AcceptedDefs =
- MR.JD.defineMaterializing(std::move(NewSymbolFlags))) {
+ MR.JD.defineMaterializing(MR, std::move(NewSymbolFlags))) {
// Add all newly accepted symbols to this responsibility object.
for (auto &KV : *AcceptedDefs)
MR.SymbolFlags.insert(KV);
diff --git a/llvm/lib/ExecutionEngine/Orc/DebugObjectManagerPlugin.cpp b/llvm/lib/ExecutionEngine/Orc/DebugObjectManagerPlugin.cpp
index 02c3e617df68..acbf33888ade 100644
--- a/llvm/lib/ExecutionEngine/Orc/DebugObjectManagerPlugin.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/DebugObjectManagerPlugin.cpp
@@ -60,26 +60,13 @@ public:
private:
typename ELFT::Shdr *Header;
-
- bool isTextOrDataSection() const;
};
template <typename ELFT>
void ELFDebugObjectSection<ELFT>::setTargetMemoryRange(SectionRange Range) {
- // Only patch load-addresses for executable and data sections.
- if (isTextOrDataSection())
- Header->sh_addr =
- static_cast<typename ELFT::uint>(Range.getStart().getValue());
-}
-
-template <typename ELFT>
-bool ELFDebugObjectSection<ELFT>::isTextOrDataSection() const {
- switch (Header->sh_type) {
- case ELF::SHT_PROGBITS:
- case ELF::SHT_X86_64_UNWIND:
- return Header->sh_flags & (ELF::SHF_EXECINSTR | ELF::SHF_ALLOC);
- }
- return false;
+ // All recorded sections are candidates for load-address patching.
+ Header->sh_addr =
+ static_cast<typename ELFT::uint>(Range.getStart().getValue());
}
template <typename ELFT>
@@ -106,16 +93,19 @@ Error ELFDebugObjectSection<ELFT>::validateInBounds(StringRef Buffer,
template <typename ELFT>
void ELFDebugObjectSection<ELFT>::dump(raw_ostream &OS, StringRef Name) {
- if (auto Addr = static_cast<JITTargetAddress>(Header->sh_addr)) {
+ if (uint64_t Addr = Header->sh_addr) {
OS << formatv(" {0:x16} {1}\n", Addr, Name);
} else {
OS << formatv(" {0}\n", Name);
}
}
-enum class Requirement {
+enum DebugObjectFlags : int {
// Request final target memory load-addresses for all sections.
- ReportFinalSectionLoadAddresses,
+ ReportFinalSectionLoadAddresses = 1 << 0,
+
+ // We found sections with debug information when processing the input object.
+ HasDebugSections = 1 << 1,
};
/// The plugin creates a debug object from when JITLink starts processing the
@@ -127,10 +117,15 @@ class DebugObject {
public:
DebugObject(JITLinkMemoryManager &MemMgr, const JITLinkDylib *JD,
ExecutionSession &ES)
- : MemMgr(MemMgr), JD(JD), ES(ES) {}
+ : MemMgr(MemMgr), JD(JD), ES(ES), Flags(DebugObjectFlags{}) {}
- void set(Requirement Req) { Reqs.insert(Req); }
- bool has(Requirement Req) const { return Reqs.count(Req) > 0; }
+ bool hasFlags(DebugObjectFlags F) const { return Flags & F; }
+ void setFlags(DebugObjectFlags F) {
+ Flags = static_cast<DebugObjectFlags>(Flags | F);
+ }
+ void clearFlags(DebugObjectFlags F) {
+ Flags = static_cast<DebugObjectFlags>(Flags & ~F);
+ }
using FinalizeContinuation = std::function<void(Expected<ExecutorAddrRange>)>;
@@ -159,7 +154,7 @@ protected:
private:
ExecutionSession &ES;
- std::set<Requirement> Reqs;
+ DebugObjectFlags Flags;
FinalizedAlloc Alloc;
};
@@ -171,8 +166,7 @@ void DebugObject::finalizeAsync(FinalizeContinuation OnFinalize) {
if (auto SimpleSegAlloc = finalizeWorkingMemory()) {
auto ROSeg = SimpleSegAlloc->getSegInfo(MemProt::Read);
- ExecutorAddrRange DebugObjRange(ExecutorAddr(ROSeg.Addr),
- ExecutorAddrDiff(ROSeg.WorkingMem.size()));
+ ExecutorAddrRange DebugObjRange(ROSeg.Addr, ROSeg.WorkingMem.size());
SimpleSegAlloc->finalize(
[this, DebugObjRange,
OnFinalize = std::move(OnFinalize)](Expected<FinalizedAlloc> FA) {
@@ -222,7 +216,7 @@ private:
JITLinkMemoryManager &MemMgr, const JITLinkDylib *JD,
ExecutionSession &ES)
: DebugObject(MemMgr, JD, ES), Buffer(std::move(Buffer)) {
- set(Requirement::ReportFinalSectionLoadAddresses);
+ setFlags(ReportFinalSectionLoadAddresses);
}
std::unique_ptr<WritableMemoryBuffer> Buffer;
@@ -271,24 +265,23 @@ ELFDebugObject::CreateArchType(MemoryBufferRef Buffer,
if (!ObjRef)
return ObjRef.takeError();
- // TODO: Add support for other architectures.
- uint16_t TargetMachineArch = ObjRef->getHeader().e_machine;
- if (TargetMachineArch != ELF::EM_X86_64)
- return nullptr;
-
Expected<ArrayRef<SectionHeader>> Sections = ObjRef->sections();
if (!Sections)
return Sections.takeError();
- bool HasDwarfSection = false;
for (const SectionHeader &Header : *Sections) {
Expected<StringRef> Name = ObjRef->getSectionName(Header);
if (!Name)
return Name.takeError();
if (Name->empty())
continue;
- HasDwarfSection |= isDwarfSection(*Name);
+ if (isDwarfSection(*Name))
+ DebugObj->setFlags(HasDebugSections);
+ // Only record text and data sections (i.e. no bss, comments, rel, etc.)
+ if (Header.sh_type != ELF::SHT_PROGBITS &&
+ Header.sh_type != ELF::SHT_X86_64_UNWIND)
+ continue;
if (!(Header.sh_flags & ELF::SHF_ALLOC))
continue;
@@ -297,13 +290,6 @@ ELFDebugObject::CreateArchType(MemoryBufferRef Buffer,
return std::move(Err);
}
- if (!HasDwarfSection) {
- LLVM_DEBUG(dbgs() << "Aborting debug registration for LinkGraph \""
- << DebugObj->Buffer->getBufferIdentifier()
- << "\": input object contains no debug info\n");
- return nullptr;
- }
-
return std::move(DebugObj);
}
@@ -371,12 +357,11 @@ Error ELFDebugObject::recordSection(
StringRef Name, std::unique_ptr<ELFDebugObjectSection<ELFT>> Section) {
if (Error Err = Section->validateInBounds(this->getBuffer(), Name.data()))
return Err;
- auto ItInserted = Sections.try_emplace(Name, std::move(Section));
- if (!ItInserted.second)
- return make_error<StringError>("In " + Buffer->getBufferIdentifier() +
- ", encountered duplicate section \"" +
- Name + "\" while building debug object",
- inconvertibleErrorCode());
+ bool Inserted = Sections.try_emplace(Name, std::move(Section)).second;
+ if (!Inserted)
+ LLVM_DEBUG(dbgs() << "Skipping debug registration for section '" << Name
+ << "' in object " << Buffer->getBufferIdentifier()
+ << " (duplicate name)\n");
return Error::success();
}
@@ -403,8 +388,15 @@ createDebugObjectFromBuffer(ExecutionSession &ES, LinkGraph &G,
}
DebugObjectManagerPlugin::DebugObjectManagerPlugin(
+ ExecutionSession &ES, std::unique_ptr<DebugObjectRegistrar> Target,
+ bool RequireDebugSections, bool AutoRegisterCode)
+ : ES(ES), Target(std::move(Target)),
+ RequireDebugSections(RequireDebugSections),
+ AutoRegisterCode(AutoRegisterCode) {}
+
+DebugObjectManagerPlugin::DebugObjectManagerPlugin(
ExecutionSession &ES, std::unique_ptr<DebugObjectRegistrar> Target)
- : ES(ES), Target(std::move(Target)) {}
+ : DebugObjectManagerPlugin(ES, std::move(Target), true, true) {}
DebugObjectManagerPlugin::~DebugObjectManagerPlugin() = default;
@@ -418,8 +410,14 @@ void DebugObjectManagerPlugin::notifyMaterializing(
if (auto DebugObj = createDebugObjectFromBuffer(ES, G, Ctx, ObjBuffer)) {
// Not all link artifacts allow debugging.
- if (*DebugObj != nullptr)
- PendingObjs[&MR] = std::move(*DebugObj);
+ if (*DebugObj == nullptr)
+ return;
+ if (RequireDebugSections && !(**DebugObj).hasFlags(HasDebugSections)) {
+ LLVM_DEBUG(dbgs() << "Skipping debug registration for LinkGraph '"
+ << G.getName() << "': no debug info\n");
+ return;
+ }
+ PendingObjs[&MR] = std::move(*DebugObj);
} else {
ES.reportError(DebugObj.takeError());
}
@@ -435,7 +433,7 @@ void DebugObjectManagerPlugin::modifyPassConfig(
return;
DebugObject &DebugObj = *It->second;
- if (DebugObj.has(Requirement::ReportFinalSectionLoadAddresses)) {
+ if (DebugObj.hasFlags(ReportFinalSectionLoadAddresses)) {
PassConfig.PostAllocationPasses.push_back(
[&DebugObj](LinkGraph &Graph) -> Error {
for (const Section &GraphSection : Graph.sections())
@@ -467,7 +465,8 @@ Error DebugObjectManagerPlugin::notifyEmitted(
FinalizePromise.set_value(TargetMem.takeError());
return;
}
- if (Error Err = Target->registerDebugObject(*TargetMem)) {
+ if (Error Err =
+ Target->registerDebugObject(*TargetMem, AutoRegisterCode)) {
FinalizePromise.set_value(std::move(Err));
return;
}
diff --git a/llvm/lib/ExecutionEngine/Orc/DebugUtils.cpp b/llvm/lib/ExecutionEngine/Orc/DebugUtils.cpp
index 028bd245fb55..aca457642212 100644
--- a/llvm/lib/ExecutionEngine/Orc/DebugUtils.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/DebugUtils.cpp
@@ -172,9 +172,8 @@ raw_ostream &operator<<(raw_ostream &OS, const JITSymbolFlags &Flags) {
return OS;
}
-raw_ostream &operator<<(raw_ostream &OS, const JITEvaluatedSymbol &Sym) {
- return OS << format("0x%016" PRIx64, Sym.getAddress()) << " "
- << Sym.getFlags();
+raw_ostream &operator<<(raw_ostream &OS, const ExecutorSymbolDef &Sym) {
+ return OS << Sym.getAddress() << " " << Sym.getFlags();
}
raw_ostream &operator<<(raw_ostream &OS, const SymbolFlagsMap::value_type &KV) {
@@ -299,8 +298,12 @@ raw_ostream &operator<<(raw_ostream &OS, const SymbolState &S) {
raw_ostream &operator<<(raw_ostream &OS, const SymbolStringPool &SSP) {
std::lock_guard<std::mutex> Lock(SSP.PoolMutex);
+ SmallVector<std::pair<StringRef, int>, 0> Vec;
for (auto &KV : SSP.Pool)
- OS << KV.first() << ": " << KV.second << "\n";
+ Vec.emplace_back(KV.first(), KV.second);
+ llvm::sort(Vec, less_first());
+ for (auto &[K, V] : Vec)
+ OS << K << ": " << V << "\n";
return OS;
}
diff --git a/llvm/lib/ExecutionEngine/Orc/DebuggerSupportPlugin.cpp b/llvm/lib/ExecutionEngine/Orc/DebuggerSupportPlugin.cpp
index 15e7ffb2f75a..830582bb3649 100644
--- a/llvm/lib/ExecutionEngine/Orc/DebuggerSupportPlugin.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/DebuggerSupportPlugin.cpp
@@ -348,11 +348,12 @@ public:
Writer.write(SecCmd);
}
+ static constexpr bool AutoRegisterCode = true;
SectionRange R(MachOContainerBlock->getSection());
G.allocActions().push_back(
{cantFail(shared::WrapperFunctionCall::Create<
- shared::SPSArgList<shared::SPSExecutorAddrRange>>(
- RegisterActionAddr, R.getRange())),
+ shared::SPSArgList<shared::SPSExecutorAddrRange, bool>>(
+ RegisterActionAddr, R.getRange(), AutoRegisterCode)),
{}});
return Error::success();
}
@@ -377,11 +378,11 @@ GDBJITDebugInfoRegistrationPlugin::Create(ExecutionSession &ES,
? ES.intern("_llvm_orc_registerJITLoaderGDBAllocAction")
: ES.intern("llvm_orc_registerJITLoaderGDBAllocAction");
- if (auto Addr = ES.lookup({&ProcessJD}, RegisterActionAddr))
+ if (auto RegisterSym = ES.lookup({&ProcessJD}, RegisterActionAddr))
return std::make_unique<GDBJITDebugInfoRegistrationPlugin>(
- ExecutorAddr(Addr->getAddress()));
+ RegisterSym->getAddress());
else
- return Addr.takeError();
+ return RegisterSym.takeError();
}
Error GDBJITDebugInfoRegistrationPlugin::notifyFailed(
diff --git a/llvm/lib/ExecutionEngine/Orc/ELFNixPlatform.cpp b/llvm/lib/ExecutionEngine/Orc/ELFNixPlatform.cpp
index 00032e4dca3f..1bb4ecdff299 100644
--- a/llvm/lib/ExecutionEngine/Orc/ELFNixPlatform.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/ELFNixPlatform.cpp
@@ -14,6 +14,7 @@
#include "llvm/ExecutionEngine/JITLink/x86_64.h"
#include "llvm/ExecutionEngine/Orc/DebugUtils.h"
#include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"
+#include "llvm/ExecutionEngine/Orc/Shared/ObjectFormats.h"
#include "llvm/Support/BinaryByteStream.h"
#include "llvm/Support/Debug.h"
#include <optional>
@@ -40,8 +41,7 @@ public:
unsigned PointerSize;
support::endianness Endianness;
jitlink::Edge::Kind EdgeKind;
- const auto &TT =
- ENP.getExecutionSession().getExecutorProcessControl().getTargetTriple();
+ const auto &TT = ENP.getExecutionSession().getTargetTriple();
switch (TT.getArch()) {
case Triple::x86_64:
@@ -96,31 +96,24 @@ private:
ELFNixPlatform &ENP;
};
-StringRef EHFrameSectionName = ".eh_frame";
-StringRef InitArrayFuncSectionName = ".init_array";
-
-StringRef ThreadBSSSectionName = ".tbss";
-StringRef ThreadDataSectionName = ".tdata";
-
} // end anonymous namespace
namespace llvm {
namespace orc {
-Expected<std::unique_ptr<ELFNixPlatform>>
-ELFNixPlatform::Create(ExecutionSession &ES,
- ObjectLinkingLayer &ObjLinkingLayer,
- JITDylib &PlatformJD, const char *OrcRuntimePath,
- std::optional<SymbolAliasMap> RuntimeAliases) {
-
- auto &EPC = ES.getExecutorProcessControl();
+Expected<std::unique_ptr<ELFNixPlatform>> ELFNixPlatform::Create(
+ ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer,
+ JITDylib &PlatformJD, std::unique_ptr<DefinitionGenerator> OrcRuntime,
+ std::optional<SymbolAliasMap> RuntimeAliases) {
// If the target is not supported then bail out immediately.
- if (!supportedTarget(EPC.getTargetTriple()))
+ if (!supportedTarget(ES.getTargetTriple()))
return make_error<StringError>("Unsupported ELFNixPlatform triple: " +
- EPC.getTargetTriple().str(),
+ ES.getTargetTriple().str(),
inconvertibleErrorCode());
+ auto &EPC = ES.getExecutorProcessControl();
+
// Create default aliases if the caller didn't supply any.
if (!RuntimeAliases) {
auto StandardRuntimeAliases = standardPlatformAliases(ES, PlatformJD);
@@ -134,31 +127,41 @@ ELFNixPlatform::Create(ExecutionSession &ES,
return std::move(Err);
// Add JIT-dispatch function support symbols.
- if (auto Err = PlatformJD.define(absoluteSymbols(
- {{ES.intern("__orc_rt_jit_dispatch"),
- {EPC.getJITDispatchInfo().JITDispatchFunction.getValue(),
- JITSymbolFlags::Exported}},
- {ES.intern("__orc_rt_jit_dispatch_ctx"),
- {EPC.getJITDispatchInfo().JITDispatchContext.getValue(),
- JITSymbolFlags::Exported}}})))
+ if (auto Err = PlatformJD.define(
+ absoluteSymbols({{ES.intern("__orc_rt_jit_dispatch"),
+ {EPC.getJITDispatchInfo().JITDispatchFunction,
+ JITSymbolFlags::Exported}},
+ {ES.intern("__orc_rt_jit_dispatch_ctx"),
+ {EPC.getJITDispatchInfo().JITDispatchContext,
+ JITSymbolFlags::Exported}}})))
return std::move(Err);
- // Create a generator for the ORC runtime archive.
- auto OrcRuntimeArchiveGenerator = StaticLibraryDefinitionGenerator::Load(
- ObjLinkingLayer, OrcRuntimePath, EPC.getTargetTriple());
- if (!OrcRuntimeArchiveGenerator)
- return OrcRuntimeArchiveGenerator.takeError();
-
// Create the instance.
Error Err = Error::success();
- auto P = std::unique_ptr<ELFNixPlatform>(
- new ELFNixPlatform(ES, ObjLinkingLayer, PlatformJD,
- std::move(*OrcRuntimeArchiveGenerator), Err));
+ auto P = std::unique_ptr<ELFNixPlatform>(new ELFNixPlatform(
+ ES, ObjLinkingLayer, PlatformJD, std::move(OrcRuntime), Err));
if (Err)
return std::move(Err);
return std::move(P);
}
+Expected<std::unique_ptr<ELFNixPlatform>>
+ELFNixPlatform::Create(ExecutionSession &ES,
+ ObjectLinkingLayer &ObjLinkingLayer,
+ JITDylib &PlatformJD, const char *OrcRuntimePath,
+ std::optional<SymbolAliasMap> RuntimeAliases) {
+
+ // Create a generator for the ORC runtime archive.
+ auto OrcRuntimeArchiveGenerator =
+ StaticLibraryDefinitionGenerator::Load(ObjLinkingLayer, OrcRuntimePath);
+ if (!OrcRuntimeArchiveGenerator)
+ return OrcRuntimeArchiveGenerator.takeError();
+
+ return Create(ES, ObjLinkingLayer, PlatformJD,
+ std::move(*OrcRuntimeArchiveGenerator),
+ std::move(RuntimeAliases));
+}
+
Error ELFNixPlatform::setupJITDylib(JITDylib &JD) {
return JD.define(
std::make_unique<DSOHandleMaterializationUnit>(*this, DSOHandleSymbol));
@@ -204,47 +207,6 @@ ELFNixPlatform::standardPlatformAliases(ExecutionSession &ES,
SymbolAliasMap Aliases;
addAliases(ES, Aliases, requiredCXXAliases());
addAliases(ES, Aliases, standardRuntimeUtilityAliases());
-
- // Determine whether or not the libunwind extended-API function for
- // dynamically registering an entire .eh_frame section is available.
- // If it is not, we assume that libgcc_s is being used, and alias to
- // its __register_frame with the same functionality.
- auto RTRegisterFrame = ES.intern("__orc_rt_register_eh_frame_section");
- auto LibUnwindRegisterFrame = ES.intern("__unw_add_dynamic_eh_frame_section");
- auto RTDeregisterFrame = ES.intern("__orc_rt_deregister_eh_frame_section");
- auto LibUnwindDeregisterFrame =
- ES.intern("__unw_remove_dynamic_eh_frame_section");
- auto SM = ES.lookup(makeJITDylibSearchOrder(&PlatformJD),
- SymbolLookupSet()
- .add(LibUnwindRegisterFrame,
- SymbolLookupFlags::WeaklyReferencedSymbol)
- .add(LibUnwindDeregisterFrame,
- SymbolLookupFlags::WeaklyReferencedSymbol));
- if (!SM) { // Weak-ref means no "missing symbol" errors, so this must be
- // something more serious that we should report.
- return SM.takeError();
- } else if (SM->size() == 2) {
- LLVM_DEBUG({
- dbgs() << "Using libunwind " << LibUnwindRegisterFrame
- << " for unwind info registration\n";
- });
- Aliases[std::move(RTRegisterFrame)] = {LibUnwindRegisterFrame,
- JITSymbolFlags::Exported};
- Aliases[std::move(RTDeregisterFrame)] = {LibUnwindDeregisterFrame,
- JITSymbolFlags::Exported};
- } else {
- // Since LLVM libunwind is not present, we assume that unwinding
- // is provided by libgcc
- LLVM_DEBUG({
- dbgs() << "Using libgcc __register_frame"
- << " for unwind info registration\n";
- });
- Aliases[std::move(RTRegisterFrame)] = {ES.intern("__register_frame"),
- JITSymbolFlags::Exported};
- Aliases[std::move(RTDeregisterFrame)] = {ES.intern("__deregister_frame"),
- JITSymbolFlags::Exported};
- }
-
return Aliases;
}
@@ -272,13 +234,6 @@ ELFNixPlatform::standardRuntimeUtilityAliases() {
StandardRuntimeUtilityAliases);
}
-bool ELFNixPlatform::isInitializerSection(StringRef SecName) {
- if (SecName.consume_front(InitArrayFuncSectionName) &&
- (SecName.empty() || SecName[0] == '.'))
- return true;
- return false;
-}
-
bool ELFNixPlatform::supportedTarget(const Triple &TT) {
switch (TT.getArch()) {
case Triple::x86_64:
@@ -433,8 +388,7 @@ void ELFNixPlatform::rt_getInitializers(SendInitializerSequenceFn SendResult,
void ELFNixPlatform::rt_getDeinitializers(
SendDeinitializerSequenceFn SendResult, ExecutorAddr Handle) {
LLVM_DEBUG({
- dbgs() << "ELFNixPlatform::rt_getDeinitializers(\""
- << formatv("{0:x}", Handle.getValue()) << "\")\n";
+ dbgs() << "ELFNixPlatform::rt_getDeinitializers(\"" << Handle << "\")\n";
});
JITDylib *JD = nullptr;
@@ -447,12 +401,9 @@ void ELFNixPlatform::rt_getDeinitializers(
}
if (!JD) {
- LLVM_DEBUG({
- dbgs() << " No JITDylib for handle "
- << formatv("{0:x}", Handle.getValue()) << "\n";
- });
+ LLVM_DEBUG(dbgs() << " No JITDylib for handle " << Handle << "\n");
SendResult(make_error<StringError>("No JITDylib associated with handle " +
- formatv("{0:x}", Handle.getValue()),
+ formatv("{0:x}", Handle),
inconvertibleErrorCode()));
return;
}
@@ -464,8 +415,7 @@ void ELFNixPlatform::rt_lookupSymbol(SendSymbolAddressFn SendResult,
ExecutorAddr Handle,
StringRef SymbolName) {
LLVM_DEBUG({
- dbgs() << "ELFNixPlatform::rt_lookupSymbol(\""
- << formatv("{0:x}", Handle.getValue()) << "\")\n";
+ dbgs() << "ELFNixPlatform::rt_lookupSymbol(\"" << Handle << "\")\n";
});
JITDylib *JD = nullptr;
@@ -478,12 +428,9 @@ void ELFNixPlatform::rt_lookupSymbol(SendSymbolAddressFn SendResult,
}
if (!JD) {
- LLVM_DEBUG({
- dbgs() << " No JITDylib for handle "
- << formatv("{0:x}", Handle.getValue()) << "\n";
- });
+ LLVM_DEBUG(dbgs() << " No JITDylib for handle " << Handle << "\n");
SendResult(make_error<StringError>("No JITDylib associated with handle " +
- formatv("{0:x}", Handle.getValue()),
+ formatv("{0:x}", Handle),
inconvertibleErrorCode()));
return;
}
@@ -496,7 +443,7 @@ void ELFNixPlatform::rt_lookupSymbol(SendSymbolAddressFn SendResult,
void operator()(Expected<SymbolMap> Result) {
if (Result) {
assert(Result->size() == 1 && "Unexpected result map count");
- SendResult(ExecutorAddr(Result->begin()->second.getAddress()));
+ SendResult(Result->begin()->second.getAddress());
} else {
SendResult(Result.takeError());
}
@@ -538,7 +485,7 @@ Error ELFNixPlatform::bootstrapELFNixRuntime(JITDylib &PlatformJD) {
for (const auto &KV : AddrsToRecord) {
auto &Name = KV.first;
assert(RuntimeSymbolAddrs->count(Name) && "Missing runtime symbol?");
- KV.second->setValue((*RuntimeSymbolAddrs)[Name].getAddress());
+ *KV.second = (*RuntimeSymbolAddrs)[Name].getAddress();
}
auto PJDDSOHandle = ES.lookup(
@@ -547,7 +494,8 @@ Error ELFNixPlatform::bootstrapELFNixRuntime(JITDylib &PlatformJD) {
return PJDDSOHandle.takeError();
if (auto Err = ES.callSPSWrapper<void(uint64_t)>(
- orc_rt_elfnix_platform_bootstrap, PJDDSOHandle->getAddress()))
+ orc_rt_elfnix_platform_bootstrap,
+ PJDDSOHandle->getAddress().getValue()))
return Err;
// FIXME: Ordering is fuzzy here. We're probably best off saying
@@ -596,8 +544,7 @@ Error ELFNixPlatform::registerInitInfo(
for (auto *Sec : InitSections) {
// FIXME: Avoid copy here.
jitlink::SectionRange R(*Sec);
- InitSeq->InitSections[Sec->getName()].push_back(
- {ExecutorAddr(R.getStart()), ExecutorAddr(R.getEnd())});
+ InitSeq->InitSections[Sec->getName()].push_back(R.getRange());
}
return Error::success();
@@ -724,20 +671,19 @@ void ELFNixPlatform::ELFNixPlatformPlugin::addEHAndTLVSupportPasses(
Config.PostFixupPasses.push_back([this](jitlink::LinkGraph &G) -> Error {
ELFPerObjectSectionsToRegister POSR;
- if (auto *EHFrameSection = G.findSectionByName(EHFrameSectionName)) {
+ if (auto *EHFrameSection = G.findSectionByName(ELFEHFrameSectionName)) {
jitlink::SectionRange R(*EHFrameSection);
if (!R.empty())
- POSR.EHFrameSection = {ExecutorAddr(R.getStart()),
- ExecutorAddr(R.getEnd())};
+ POSR.EHFrameSection = R.getRange();
}
// Get a pointer to the thread data section if there is one. It will be used
// below.
jitlink::Section *ThreadDataSection =
- G.findSectionByName(ThreadDataSectionName);
+ G.findSectionByName(ELFThreadDataSectionName);
// Handle thread BSS section if there is one.
- if (auto *ThreadBSSSection = G.findSectionByName(ThreadBSSSectionName)) {
+ if (auto *ThreadBSSSection = G.findSectionByName(ELFThreadBSSSectionName)) {
// If there's already a thread data section in this graph then merge the
// thread BSS section content into it, otherwise just treat the thread
// BSS section as the thread data section.
@@ -752,8 +698,7 @@ void ELFNixPlatform::ELFNixPlatformPlugin::addEHAndTLVSupportPasses(
if (ThreadDataSection) {
jitlink::SectionRange R(*ThreadDataSection);
if (!R.empty())
- POSR.ThreadDataSection = {ExecutorAddr(R.getStart()),
- ExecutorAddr(R.getEnd())};
+ POSR.ThreadDataSection = R.getRange();
}
if (POSR.EHFrameSection.Start || POSR.ThreadDataSection.Start) {
@@ -781,7 +726,7 @@ Error ELFNixPlatform::ELFNixPlatformPlugin::preserveInitSections(
JITLinkSymbolSet InitSectionSymbols;
for (auto &InitSection : G.sections()) {
// Skip non-init sections.
- if (!isInitializerSection(InitSection.getName()))
+ if (!isELFInitializerSection(InitSection.getName()))
continue;
// Make a pass over live symbols in the section: those blocks are already
@@ -816,10 +761,10 @@ Error ELFNixPlatform::ELFNixPlatformPlugin::registerInitSections(
SmallVector<jitlink::Section *> InitSections;
- LLVM_DEBUG({ dbgs() << "ELFNixPlatform::registerInitSections\n"; });
+ LLVM_DEBUG(dbgs() << "ELFNixPlatform::registerInitSections\n");
for (auto &Sec : G.sections()) {
- if (isInitializerSection(Sec.getName())) {
+ if (isELFInitializerSection(Sec.getName())) {
InitSections.push_back(&Sec);
}
}
@@ -829,8 +774,7 @@ Error ELFNixPlatform::ELFNixPlatformPlugin::registerInitSections(
dbgs() << "ELFNixPlatform: Scraped " << G.getName() << " init sections:\n";
for (auto *Sec : InitSections) {
jitlink::SectionRange R(*Sec);
- dbgs() << " " << Sec->getName() << ": "
- << formatv("[ {0:x} -- {1:x} ]", R.getStart(), R.getEnd()) << "\n";
+ dbgs() << " " << Sec->getName() << ": " << R.getRange() << "\n";
}
});
diff --git a/llvm/lib/ExecutionEngine/Orc/EPCDebugObjectRegistrar.cpp b/llvm/lib/ExecutionEngine/Orc/EPCDebugObjectRegistrar.cpp
index 30d641ee00cf..b8969de54936 100644
--- a/llvm/lib/ExecutionEngine/Orc/EPCDebugObjectRegistrar.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/EPCDebugObjectRegistrar.cpp
@@ -45,14 +45,13 @@ Expected<std::unique_ptr<EPCDebugObjectRegistrar>> createJITLoaderGDBRegistrar(
assert((*Result)[0].size() == 1 &&
"Unexpected number of addresses in result");
- return std::make_unique<EPCDebugObjectRegistrar>(
- ES, ExecutorAddr((*Result)[0][0]));
+ return std::make_unique<EPCDebugObjectRegistrar>(ES, (*Result)[0][0]);
}
-Error EPCDebugObjectRegistrar::registerDebugObject(
- ExecutorAddrRange TargetMem) {
- return ES.callSPSWrapper<void(shared::SPSExecutorAddrRange)>(RegisterFn,
- TargetMem);
+Error EPCDebugObjectRegistrar::registerDebugObject(ExecutorAddrRange TargetMem,
+ bool AutoRegisterCode) {
+ return ES.callSPSWrapper<void(shared::SPSExecutorAddrRange, bool)>(
+ RegisterFn, TargetMem, AutoRegisterCode);
}
} // namespace orc
diff --git a/llvm/lib/ExecutionEngine/Orc/EPCDynamicLibrarySearchGenerator.cpp b/llvm/lib/ExecutionEngine/Orc/EPCDynamicLibrarySearchGenerator.cpp
index 1adcc9156957..46e16a55c7e1 100644
--- a/llvm/lib/ExecutionEngine/Orc/EPCDynamicLibrarySearchGenerator.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/EPCDynamicLibrarySearchGenerator.cpp
@@ -53,8 +53,7 @@ Error EPCDynamicLibrarySearchGenerator::tryToGenerate(
auto ResultI = Result->front().begin();
for (auto &KV : LookupSymbols) {
if (*ResultI)
- NewSymbols[KV.first] =
- JITEvaluatedSymbol(ResultI->getValue(), JITSymbolFlags::Exported);
+ NewSymbols[KV.first] = {*ResultI, JITSymbolFlags::Exported};
++ResultI;
}
diff --git a/llvm/lib/ExecutionEngine/Orc/EPCEHFrameRegistrar.cpp b/llvm/lib/ExecutionEngine/Orc/EPCEHFrameRegistrar.cpp
index 3aa94a7f43e2..56cd982cd5e1 100644
--- a/llvm/lib/ExecutionEngine/Orc/EPCEHFrameRegistrar.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/EPCEHFrameRegistrar.cpp
@@ -57,9 +57,8 @@ Expected<std::unique_ptr<EPCEHFrameRegistrar>> EPCEHFrameRegistrar::Create(
auto RegisterEHFrameWrapperFnAddr = (*Result)[0][0];
auto DeregisterEHFrameWrapperFnAddr = (*Result)[0][1];
- return std::make_unique<EPCEHFrameRegistrar>(
- ES, ExecutorAddr(RegisterEHFrameWrapperFnAddr),
- ExecutorAddr(DeregisterEHFrameWrapperFnAddr));
+ return std::make_unique<EPCEHFrameRegistrar>(ES, RegisterEHFrameWrapperFnAddr,
+ DeregisterEHFrameWrapperFnAddr);
}
Error EPCEHFrameRegistrar::registerEHFrames(ExecutorAddrRange EHFrameSection) {
diff --git a/llvm/lib/ExecutionEngine/Orc/EPCGenericJITLinkMemoryManager.cpp b/llvm/lib/ExecutionEngine/Orc/EPCGenericJITLinkMemoryManager.cpp
index a3d857c3bfc4..b05f08fd7cdf 100644
--- a/llvm/lib/ExecutionEngine/Orc/EPCGenericJITLinkMemoryManager.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/EPCGenericJITLinkMemoryManager.cpp
@@ -158,7 +158,7 @@ void EPCGenericJITLinkMemoryManager::completeAllocation(
auto &SegInfo = SegInfos[AG];
SegInfo.ContentSize = Seg.ContentSize;
SegInfo.ZeroFillSize = Seg.ZeroFillSize;
- SegInfo.Addr = ExecutorAddr(Seg.Addr);
+ SegInfo.Addr = Seg.Addr;
SegInfo.WorkingMem = Seg.WorkingMem;
}
diff --git a/llvm/lib/ExecutionEngine/Orc/EPCGenericRTDyldMemoryManager.cpp b/llvm/lib/ExecutionEngine/Orc/EPCGenericRTDyldMemoryManager.cpp
index ec82081937e2..fbe25d70c38a 100644
--- a/llvm/lib/ExecutionEngine/Orc/EPCGenericRTDyldMemoryManager.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/EPCGenericRTDyldMemoryManager.cpp
@@ -235,7 +235,7 @@ bool EPCGenericRTDyldMemoryManager::finalizeMemory(std::string *ErrMsg) {
for (unsigned I = 0; I != 3; ++I) {
FR.Segments.push_back({});
auto &Seg = FR.Segments.back();
- Seg.AG = SegMemProts[I];
+ Seg.RAG = SegMemProts[I];
Seg.Addr = RemoteAddrs[I]->Start;
for (auto &SecAlloc : *SegSections[I]) {
Seg.Size = alignTo(Seg.Size, SecAlloc.Align);
diff --git a/llvm/lib/ExecutionEngine/Orc/EPCIndirectionUtils.cpp b/llvm/lib/ExecutionEngine/Orc/EPCIndirectionUtils.cpp
index ddfb30500c7b..833be826f8ae 100644
--- a/llvm/lib/ExecutionEngine/Orc/EPCIndirectionUtils.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/EPCIndirectionUtils.cpp
@@ -58,16 +58,16 @@ public:
Error deallocateStubs();
- Error createStub(StringRef StubName, JITTargetAddress StubAddr,
+ Error createStub(StringRef StubName, ExecutorAddr StubAddr,
JITSymbolFlags StubFlags) override;
Error createStubs(const StubInitsMap &StubInits) override;
- JITEvaluatedSymbol findStub(StringRef Name, bool ExportedStubsOnly) override;
+ ExecutorSymbolDef findStub(StringRef Name, bool ExportedStubsOnly) override;
- JITEvaluatedSymbol findPointer(StringRef Name) override;
+ ExecutorSymbolDef findPointer(StringRef Name) override;
- Error updatePointer(StringRef Name, JITTargetAddress NewAddr) override;
+ Error updatePointer(StringRef Name, ExecutorAddr NewAddr) override;
private:
using StubInfo = std::pair<IndirectStubInfo, JITSymbolFlags>;
@@ -118,12 +118,10 @@ Error EPCTrampolinePool::grow() {
unsigned NumTrampolines = TrampolinesPerPage;
auto SegInfo = Alloc->getSegInfo(MemProt::Read | MemProt::Exec);
- EPCIU.getABISupport().writeTrampolines(SegInfo.WorkingMem.data(),
- SegInfo.Addr.getValue(),
- ResolverAddress, NumTrampolines);
+ EPCIU.getABISupport().writeTrampolines(
+ SegInfo.WorkingMem.data(), SegInfo.Addr, ResolverAddress, NumTrampolines);
for (unsigned I = 0; I < NumTrampolines; ++I)
- AvailableTrampolines.push_back(SegInfo.Addr.getValue() +
- (I * TrampolineSize));
+ AvailableTrampolines.push_back(SegInfo.Addr + (I * TrampolineSize));
auto FA = Alloc->finalize();
if (!FA)
@@ -135,7 +133,7 @@ Error EPCTrampolinePool::grow() {
}
Error EPCIndirectStubsManager::createStub(StringRef StubName,
- JITTargetAddress StubAddr,
+ ExecutorAddr StubAddr,
JITSymbolFlags StubFlags) {
StubInitsMap SIM;
SIM[StubName] = std::make_pair(StubAddr, StubFlags);
@@ -162,18 +160,16 @@ Error EPCIndirectStubsManager::createStubs(const StubInitsMap &StubInits) {
unsigned ASIdx = 0;
std::vector<tpctypes::UInt32Write> PtrUpdates;
for (auto &SI : StubInits)
- PtrUpdates.push_back(
- {ExecutorAddr((*AvailableStubInfos)[ASIdx++].PointerAddress),
- static_cast<uint32_t>(SI.second.first)});
+ PtrUpdates.push_back({(*AvailableStubInfos)[ASIdx++].PointerAddress,
+ static_cast<uint32_t>(SI.second.first.getValue())});
return MemAccess.writeUInt32s(PtrUpdates);
}
case 8: {
unsigned ASIdx = 0;
std::vector<tpctypes::UInt64Write> PtrUpdates;
for (auto &SI : StubInits)
- PtrUpdates.push_back(
- {ExecutorAddr((*AvailableStubInfos)[ASIdx++].PointerAddress),
- static_cast<uint64_t>(SI.second.first)});
+ PtrUpdates.push_back({(*AvailableStubInfos)[ASIdx++].PointerAddress,
+ static_cast<uint64_t>(SI.second.first.getValue())});
return MemAccess.writeUInt64s(PtrUpdates);
}
default:
@@ -182,27 +178,27 @@ Error EPCIndirectStubsManager::createStubs(const StubInitsMap &StubInits) {
}
}
-JITEvaluatedSymbol EPCIndirectStubsManager::findStub(StringRef Name,
- bool ExportedStubsOnly) {
+ExecutorSymbolDef EPCIndirectStubsManager::findStub(StringRef Name,
+ bool ExportedStubsOnly) {
std::lock_guard<std::mutex> Lock(ISMMutex);
auto I = StubInfos.find(Name);
if (I == StubInfos.end())
- return nullptr;
+ return ExecutorSymbolDef();
return {I->second.first.StubAddress, I->second.second};
}
-JITEvaluatedSymbol EPCIndirectStubsManager::findPointer(StringRef Name) {
+ExecutorSymbolDef EPCIndirectStubsManager::findPointer(StringRef Name) {
std::lock_guard<std::mutex> Lock(ISMMutex);
auto I = StubInfos.find(Name);
if (I == StubInfos.end())
- return nullptr;
+ return ExecutorSymbolDef();
return {I->second.first.PointerAddress, I->second.second};
}
Error EPCIndirectStubsManager::updatePointer(StringRef Name,
- JITTargetAddress NewAddr) {
+ ExecutorAddr NewAddr) {
- JITTargetAddress PtrAddr = 0;
+ ExecutorAddr PtrAddr;
{
std::lock_guard<std::mutex> Lock(ISMMutex);
auto I = StubInfos.find(Name);
@@ -215,11 +211,11 @@ Error EPCIndirectStubsManager::updatePointer(StringRef Name,
auto &MemAccess = EPCIU.getExecutorProcessControl().getMemoryAccess();
switch (EPCIU.getABISupport().getPointerSize()) {
case 4: {
- tpctypes::UInt32Write PUpdate(ExecutorAddr(PtrAddr), NewAddr);
+ tpctypes::UInt32Write PUpdate(PtrAddr, NewAddr.getValue());
return MemAccess.writeUInt32s(PUpdate);
}
case 8: {
- tpctypes::UInt64Write PUpdate(ExecutorAddr(PtrAddr), NewAddr);
+ tpctypes::UInt64Write PUpdate(PtrAddr, NewAddr.getValue());
return MemAccess.writeUInt64s(PUpdate);
}
default:
@@ -290,9 +286,9 @@ Error EPCIndirectionUtils::cleanup() {
return Err;
}
-Expected<JITTargetAddress>
-EPCIndirectionUtils::writeResolverBlock(JITTargetAddress ReentryFnAddr,
- JITTargetAddress ReentryCtxAddr) {
+Expected<ExecutorAddr>
+EPCIndirectionUtils::writeResolverBlock(ExecutorAddr ReentryFnAddr,
+ ExecutorAddr ReentryCtxAddr) {
using namespace jitlink;
assert(ABI && "ABI can not be null");
@@ -307,7 +303,7 @@ EPCIndirectionUtils::writeResolverBlock(JITTargetAddress ReentryFnAddr,
return Alloc.takeError();
auto SegInfo = Alloc->getSegInfo(MemProt::Read | MemProt::Exec);
- ResolverBlockAddr = SegInfo.Addr.getValue();
+ ResolverBlockAddr = SegInfo.Addr;
ABI->writeResolverCode(SegInfo.WorkingMem.data(), ResolverBlockAddr,
ReentryFnAddr, ReentryCtxAddr);
@@ -331,7 +327,7 @@ TrampolinePool &EPCIndirectionUtils::getTrampolinePool() {
}
LazyCallThroughManager &EPCIndirectionUtils::createLazyCallThroughManager(
- ExecutionSession &ES, JITTargetAddress ErrorHandlerAddr) {
+ ExecutionSession &ES, ExecutorAddr ErrorHandlerAddr) {
assert(!LCTM &&
"createLazyCallThroughManager can not have been called before");
LCTM = std::make_unique<LazyCallThroughManager>(ES, ErrorHandlerAddr,
@@ -377,9 +373,8 @@ EPCIndirectionUtils::getIndirectStubs(unsigned NumStubs) {
auto StubSeg = Alloc->getSegInfo(StubProt);
auto PtrSeg = Alloc->getSegInfo(PtrProt);
- ABI->writeIndirectStubsBlock(StubSeg.WorkingMem.data(),
- StubSeg.Addr.getValue(),
- PtrSeg.Addr.getValue(), NumStubsToAllocate);
+ ABI->writeIndirectStubsBlock(StubSeg.WorkingMem.data(), StubSeg.Addr,
+ PtrSeg.Addr, NumStubsToAllocate);
auto FA = Alloc->finalize();
if (!FA)
@@ -390,8 +385,8 @@ EPCIndirectionUtils::getIndirectStubs(unsigned NumStubs) {
auto StubExecutorAddr = StubSeg.Addr;
auto PtrExecutorAddr = PtrSeg.Addr;
for (unsigned I = 0; I != NumStubsToAllocate; ++I) {
- AvailableIndirectStubs.push_back(IndirectStubInfo(
- StubExecutorAddr.getValue(), PtrExecutorAddr.getValue()));
+ AvailableIndirectStubs.push_back(
+ IndirectStubInfo(StubExecutorAddr, PtrExecutorAddr));
StubExecutorAddr += ABI->getStubSize();
PtrExecutorAddr += ABI->getPointerSize();
}
@@ -412,19 +407,19 @@ EPCIndirectionUtils::getIndirectStubs(unsigned NumStubs) {
static JITTargetAddress reentry(JITTargetAddress LCTMAddr,
JITTargetAddress TrampolineAddr) {
auto &LCTM = *jitTargetAddressToPointer<LazyCallThroughManager *>(LCTMAddr);
- std::promise<JITTargetAddress> LandingAddrP;
+ std::promise<ExecutorAddr> LandingAddrP;
auto LandingAddrF = LandingAddrP.get_future();
LCTM.resolveTrampolineLandingAddress(
- TrampolineAddr,
- [&](JITTargetAddress Addr) { LandingAddrP.set_value(Addr); });
- return LandingAddrF.get();
+ ExecutorAddr(TrampolineAddr),
+ [&](ExecutorAddr Addr) { LandingAddrP.set_value(Addr); });
+ return LandingAddrF.get().getValue();
}
Error setUpInProcessLCTMReentryViaEPCIU(EPCIndirectionUtils &EPCIU) {
auto &LCTM = EPCIU.getLazyCallThroughManager();
return EPCIU
- .writeResolverBlock(pointerToJITTargetAddress(&reentry),
- pointerToJITTargetAddress(&LCTM))
+ .writeResolverBlock(ExecutorAddr::fromPtr(&reentry),
+ ExecutorAddr::fromPtr(&LCTM))
.takeError();
}
diff --git a/llvm/lib/ExecutionEngine/Orc/ExecutionUtils.cpp b/llvm/lib/ExecutionEngine/Orc/ExecutionUtils.cpp
index 377a59993eb0..fb685e6c3727 100644
--- a/llvm/lib/ExecutionEngine/Orc/ExecutionUtils.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/ExecutionUtils.cpp
@@ -156,8 +156,7 @@ Error CtorDtorRunner::run() {
for (auto &KV : CtorDtorsByPriority) {
for (auto &Name : KV.second) {
assert(CtorDtorMap->count(Name) && "No entry for Name");
- auto CtorDtor = reinterpret_cast<CtorDtorTy>(
- static_cast<uintptr_t>((*CtorDtorMap)[Name].getAddress()));
+ auto CtorDtor = (*CtorDtorMap)[Name].getAddress().toPtr<CtorDtorTy>();
CtorDtor();
}
}
@@ -186,12 +185,10 @@ int LocalCXXRuntimeOverridesBase::CXAAtExitOverride(DestructorPtr Destructor,
Error LocalCXXRuntimeOverrides::enable(JITDylib &JD,
MangleAndInterner &Mangle) {
SymbolMap RuntimeInterposes;
- RuntimeInterposes[Mangle("__dso_handle")] =
- JITEvaluatedSymbol(toTargetAddress(&DSOHandleOverride),
- JITSymbolFlags::Exported);
- RuntimeInterposes[Mangle("__cxa_atexit")] =
- JITEvaluatedSymbol(toTargetAddress(&CXAAtExitOverride),
- JITSymbolFlags::Exported);
+ RuntimeInterposes[Mangle("__dso_handle")] = {
+ ExecutorAddr::fromPtr(&DSOHandleOverride), JITSymbolFlags::Exported};
+ RuntimeInterposes[Mangle("__cxa_atexit")] = {
+ ExecutorAddr::fromPtr(&CXAAtExitOverride), JITSymbolFlags::Exported};
return JD.define(absoluteSymbols(std::move(RuntimeInterposes)));
}
@@ -257,11 +254,8 @@ Error DynamicLibrarySearchGenerator::tryToGenerate(
std::string Tmp((*Name).data() + HasGlobalPrefix,
(*Name).size() - HasGlobalPrefix);
- if (void *Addr = Dylib.getAddressOfSymbol(Tmp.c_str())) {
- NewSymbols[Name] = JITEvaluatedSymbol(
- static_cast<JITTargetAddress>(reinterpret_cast<uintptr_t>(Addr)),
- JITSymbolFlags::Exported);
- }
+ if (void *P = Dylib.getAddressOfSymbol(Tmp.c_str()))
+ NewSymbols[Name] = {ExecutorAddr::fromPtr(P), JITSymbolFlags::Exported};
}
if (NewSymbols.empty())
@@ -274,57 +268,41 @@ Expected<std::unique_ptr<StaticLibraryDefinitionGenerator>>
StaticLibraryDefinitionGenerator::Load(
ObjectLayer &L, const char *FileName,
GetObjectFileInterface GetObjFileInterface) {
- auto ArchiveBuffer = MemoryBuffer::getFile(FileName);
-
- if (!ArchiveBuffer)
- return createFileError(FileName, ArchiveBuffer.getError());
-
- return Create(L, std::move(*ArchiveBuffer), std::move(GetObjFileInterface));
-}
-
-Expected<std::unique_ptr<StaticLibraryDefinitionGenerator>>
-StaticLibraryDefinitionGenerator::Load(
- ObjectLayer &L, const char *FileName, const Triple &TT,
- GetObjectFileInterface GetObjFileInterface) {
auto B = object::createBinary(FileName);
if (!B)
return createFileError(FileName, B.takeError());
// If this is a regular archive then create an instance from it.
- if (isa<object::Archive>(B->getBinary()))
- return Create(L, std::move(B->takeBinary().second),
+ if (isa<object::Archive>(B->getBinary())) {
+ auto [Archive, ArchiveBuffer] = B->takeBinary();
+ return Create(L, std::move(ArchiveBuffer),
+ std::unique_ptr<object::Archive>(
+ static_cast<object::Archive *>(Archive.release())),
std::move(GetObjFileInterface));
+ }
// If this is a universal binary then search for a slice matching the given
// Triple.
if (auto *UB = cast<object::MachOUniversalBinary>(B->getBinary())) {
- for (const auto &Obj : UB->objects()) {
- auto ObjTT = Obj.getTriple();
- if (ObjTT.getArch() == TT.getArch() &&
- ObjTT.getSubArch() == TT.getSubArch() &&
- (TT.getVendor() == Triple::UnknownVendor ||
- ObjTT.getVendor() == TT.getVendor())) {
- // We found a match. Create an instance from a buffer covering this
- // slice.
- auto SliceBuffer = MemoryBuffer::getFileSlice(FileName, Obj.getSize(),
- Obj.getOffset());
- if (!SliceBuffer)
- return make_error<StringError>(
- Twine("Could not create buffer for ") + TT.str() + " slice of " +
- FileName + ": [ " + formatv("{0:x}", Obj.getOffset()) +
- " .. " + formatv("{0:x}", Obj.getOffset() + Obj.getSize()) +
- ": " + SliceBuffer.getError().message(),
- SliceBuffer.getError());
- return Create(L, std::move(*SliceBuffer),
- std::move(GetObjFileInterface));
- }
- }
- return make_error<StringError>(Twine("Universal binary ") + FileName +
- " does not contain a slice for " +
- TT.str(),
- inconvertibleErrorCode());
+ const auto &TT = L.getExecutionSession().getTargetTriple();
+
+ auto SliceRange = getSliceRangeForArch(*UB, TT);
+ if (!SliceRange)
+ return SliceRange.takeError();
+
+ auto SliceBuffer = MemoryBuffer::getFileSlice(FileName, SliceRange->second,
+ SliceRange->first);
+ if (!SliceBuffer)
+ return make_error<StringError>(
+ Twine("Could not create buffer for ") + TT.str() + " slice of " +
+ FileName + ": [ " + formatv("{0:x}", SliceRange->first) + " .. " +
+ formatv("{0:x}", SliceRange->first + SliceRange->second) + ": " +
+ SliceBuffer.getError().message(),
+ SliceBuffer.getError());
+
+ return Create(L, std::move(*SliceBuffer), std::move(GetObjFileInterface));
}
return make_error<StringError>(Twine("Unrecognized file type for ") +
@@ -335,12 +313,15 @@ StaticLibraryDefinitionGenerator::Load(
Expected<std::unique_ptr<StaticLibraryDefinitionGenerator>>
StaticLibraryDefinitionGenerator::Create(
ObjectLayer &L, std::unique_ptr<MemoryBuffer> ArchiveBuffer,
+ std::unique_ptr<object::Archive> Archive,
GetObjectFileInterface GetObjFileInterface) {
+
Error Err = Error::success();
std::unique_ptr<StaticLibraryDefinitionGenerator> ADG(
new StaticLibraryDefinitionGenerator(
- L, std::move(ArchiveBuffer), std::move(GetObjFileInterface), Err));
+ L, std::move(ArchiveBuffer), std::move(Archive),
+ std::move(GetObjFileInterface), Err));
if (Err)
return std::move(Err);
@@ -348,6 +329,50 @@ StaticLibraryDefinitionGenerator::Create(
return std::move(ADG);
}
+Expected<std::unique_ptr<StaticLibraryDefinitionGenerator>>
+StaticLibraryDefinitionGenerator::Create(
+ ObjectLayer &L, std::unique_ptr<MemoryBuffer> ArchiveBuffer,
+ GetObjectFileInterface GetObjFileInterface) {
+
+ auto B = object::createBinary(ArchiveBuffer->getMemBufferRef());
+ if (!B)
+ return B.takeError();
+
+ // If this is a regular archive then create an instance from it.
+ if (isa<object::Archive>(*B))
+ return Create(L, std::move(ArchiveBuffer),
+ std::unique_ptr<object::Archive>(
+ static_cast<object::Archive *>(B->release())),
+ std::move(GetObjFileInterface));
+
+ // If this is a universal binary then search for a slice matching the given
+ // Triple.
+ if (auto *UB = cast<object::MachOUniversalBinary>(B->get())) {
+
+ const auto &TT = L.getExecutionSession().getTargetTriple();
+
+ auto SliceRange = getSliceRangeForArch(*UB, TT);
+ if (!SliceRange)
+ return SliceRange.takeError();
+
+ MemoryBufferRef SliceRef(
+ StringRef(ArchiveBuffer->getBufferStart() + SliceRange->first,
+ SliceRange->second),
+ ArchiveBuffer->getBufferIdentifier());
+
+ auto Archive = object::Archive::create(SliceRef);
+ if (!Archive)
+ return Archive.takeError();
+
+ return Create(L, std::move(ArchiveBuffer), std::move(*Archive),
+ std::move(GetObjFileInterface));
+ }
+
+ return make_error<StringError>(Twine("Unrecognized file type for ") +
+ ArchiveBuffer->getBufferIdentifier(),
+ inconvertibleErrorCode());
+}
+
Error StaticLibraryDefinitionGenerator::tryToGenerate(
LookupState &LS, LookupKind K, JITDylib &JD,
JITDylibLookupFlags JDLookupFlags, const SymbolLookupSet &Symbols) {
@@ -417,12 +442,33 @@ Error StaticLibraryDefinitionGenerator::buildObjectFilesMap() {
return Error::success();
}
+Expected<std::pair<size_t, size_t>>
+StaticLibraryDefinitionGenerator::getSliceRangeForArch(
+ object::MachOUniversalBinary &UB, const Triple &TT) {
+
+ for (const auto &Obj : UB.objects()) {
+ auto ObjTT = Obj.getTriple();
+ if (ObjTT.getArch() == TT.getArch() &&
+ ObjTT.getSubArch() == TT.getSubArch() &&
+ (TT.getVendor() == Triple::UnknownVendor ||
+ ObjTT.getVendor() == TT.getVendor())) {
+ // We found a match. Return the range for the slice.
+ return std::make_pair(Obj.getOffset(), Obj.getSize());
+ }
+ }
+
+ return make_error<StringError>(Twine("Universal binary ") + UB.getFileName() +
+ " does not contain a slice for " +
+ TT.str(),
+ inconvertibleErrorCode());
+}
+
StaticLibraryDefinitionGenerator::StaticLibraryDefinitionGenerator(
ObjectLayer &L, std::unique_ptr<MemoryBuffer> ArchiveBuffer,
+ std::unique_ptr<object::Archive> Archive,
GetObjectFileInterface GetObjFileInterface, Error &Err)
: L(L), GetObjFileInterface(std::move(GetObjFileInterface)),
- ArchiveBuffer(std::move(ArchiveBuffer)),
- Archive(std::make_unique<object::Archive>(*this->ArchiveBuffer, Err)) {
+ ArchiveBuffer(std::move(ArchiveBuffer)), Archive(std::move(Archive)) {
ErrorAsOutParameter _(&Err);
if (!this->GetObjFileInterface)
this->GetObjFileInterface = getObjectFileInterface;
@@ -506,7 +552,7 @@ DLLImportDefinitionGenerator::getTargetEndianness(const Triple &TT) {
Expected<std::unique_ptr<jitlink::LinkGraph>>
DLLImportDefinitionGenerator::createStubsGraph(const SymbolMap &Resolved) {
- Triple TT = ES.getExecutorProcessControl().getTargetTriple();
+ Triple TT = ES.getTargetTriple();
auto PointerSize = getTargetEndianness(TT);
if (!PointerSize)
return PointerSize.takeError();
@@ -522,13 +568,13 @@ DLLImportDefinitionGenerator::createStubsGraph(const SymbolMap &Resolved) {
for (auto &KV : Resolved) {
jitlink::Symbol &Target = G->addAbsoluteSymbol(
- *KV.first, ExecutorAddr(KV.second.getAddress()), *PointerSize,
+ *KV.first, KV.second.getAddress(), *PointerSize,
jitlink::Linkage::Strong, jitlink::Scope::Local, false);
// Create __imp_ symbol
jitlink::Symbol &Ptr =
jitlink::x86_64::createAnonymousPointer(*G, Sec, &Target);
- auto NameCopy = G->allocateString(Twine(getImpPrefix()) + *KV.first);
+ auto NameCopy = G->allocateContent(Twine(getImpPrefix()) + *KV.first);
StringRef NameCopyRef = StringRef(NameCopy.data(), NameCopy.size());
Ptr.setName(NameCopyRef);
Ptr.setLinkage(jitlink::Linkage::Strong);
diff --git a/llvm/lib/ExecutionEngine/Orc/ExecutorProcessControl.cpp b/llvm/lib/ExecutionEngine/Orc/ExecutorProcessControl.cpp
index 361fcd4a2e9c..b8b013f8a7a9 100644
--- a/llvm/lib/ExecutionEngine/Orc/ExecutorProcessControl.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/ExecutorProcessControl.cpp
@@ -11,8 +11,8 @@
#include "llvm/ExecutionEngine/Orc/Core.h"
#include "llvm/ExecutionEngine/Orc/TargetProcess/TargetExecutionUtils.h"
#include "llvm/Support/FormatVariadic.h"
-#include "llvm/Support/Host.h"
#include "llvm/Support/Process.h"
+#include "llvm/TargetParser/Host.h"
#define DEBUG_TYPE "orc"
@@ -192,7 +192,7 @@ SelfExecutorProcessControl::jitDispatchViaWrapperFunctionManager(
shared::WrapperFunctionResult Result) mutable {
ResultP.set_value(std::move(Result));
},
- pointerToJITTargetAddress(FnTag), {Data, Size});
+ ExecutorAddr::fromPtr(FnTag), {Data, Size});
return ResultF.get().release();
}
diff --git a/llvm/lib/ExecutionEngine/Orc/IndirectionUtils.cpp b/llvm/lib/ExecutionEngine/Orc/IndirectionUtils.cpp
index 989bb094cc25..a0d81cdf2086 100644
--- a/llvm/lib/ExecutionEngine/Orc/IndirectionUtils.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/IndirectionUtils.cpp
@@ -8,13 +8,13 @@
#include "llvm/ExecutionEngine/Orc/IndirectionUtils.h"
#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/Triple.h"
#include "llvm/ExecutionEngine/JITLink/x86_64.h"
#include "llvm/ExecutionEngine/Orc/OrcABISupport.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/MC/MCDisassembler/MCDisassembler.h"
#include "llvm/MC/MCInstrAnalysis.h"
#include "llvm/Support/Format.h"
+#include "llvm/TargetParser/Triple.h"
#include "llvm/Transforms/Utils/Cloning.h"
#include <sstream>
@@ -40,7 +40,7 @@ public:
private:
void materialize(std::unique_ptr<MaterializationResponsibility> R) override {
SymbolMap Result;
- Result[Name] = JITEvaluatedSymbol(Compile(), JITSymbolFlags::Exported);
+ Result[Name] = {Compile(), JITSymbolFlags::Exported};
// No dependencies, so these calls cannot fail.
cantFail(R->notifyResolved(Result));
cantFail(R->notifyEmitted());
@@ -62,7 +62,7 @@ namespace orc {
TrampolinePool::~TrampolinePool() = default;
void IndirectStubsManager::anchor() {}
-Expected<JITTargetAddress>
+Expected<ExecutorAddr>
JITCompileCallbackManager::getCompileCallback(CompileFunction Compile) {
if (auto TrampolineAddr = TP->getTrampoline()) {
auto CallbackName =
@@ -78,8 +78,8 @@ JITCompileCallbackManager::getCompileCallback(CompileFunction Compile) {
return TrampolineAddr.takeError();
}
-JITTargetAddress JITCompileCallbackManager::executeCompileCallback(
- JITTargetAddress TrampolineAddr) {
+ExecutorAddr
+JITCompileCallbackManager::executeCompileCallback(ExecutorAddr TrampolineAddr) {
SymbolStringPtr Name;
{
@@ -91,14 +91,10 @@ JITTargetAddress JITCompileCallbackManager::executeCompileCallback(
// callee.
if (I == AddrToSymbol.end()) {
Lock.unlock();
- std::string ErrMsg;
- {
- raw_string_ostream ErrMsgStream(ErrMsg);
- ErrMsgStream << "No compile callback for trampoline at "
- << format("0x%016" PRIx64, TrampolineAddr);
- }
ES.reportError(
- make_error<StringError>(std::move(ErrMsg), inconvertibleErrorCode()));
+ make_error<StringError>("No compile callback for trampoline at " +
+ formatv("{0:x}", TrampolineAddr),
+ inconvertibleErrorCode()));
return ErrorHandlerAddress;
} else
Name = I->second;
@@ -120,7 +116,7 @@ JITTargetAddress JITCompileCallbackManager::executeCompileCallback(
Expected<std::unique_ptr<JITCompileCallbackManager>>
createLocalCompileCallbackManager(const Triple &T, ExecutionSession &ES,
- JITTargetAddress ErrorHandlerAddress) {
+ ExecutorAddr ErrorHandlerAddress) {
switch (T.getArch()) {
default:
return make_error<StringError>(
@@ -244,9 +240,9 @@ createLocalIndirectStubsManagerBuilder(const Triple &T) {
}
}
-Constant* createIRTypedAddress(FunctionType &FT, JITTargetAddress Addr) {
+Constant* createIRTypedAddress(FunctionType &FT, ExecutorAddr Addr) {
Constant *AddrIntVal =
- ConstantInt::get(Type::getInt64Ty(FT.getContext()), Addr);
+ ConstantInt::get(Type::getInt64Ty(FT.getContext()), Addr.getValue());
Constant *AddrPtrVal =
ConstantExpr::getCast(Instruction::IntToPtr, AddrIntVal,
PointerType::get(&FT, 0));
@@ -329,26 +325,6 @@ Function* cloneFunctionDecl(Module &Dst, const Function &F,
return NewF;
}
-void moveFunctionBody(Function &OrigF, ValueToValueMapTy &VMap,
- ValueMaterializer *Materializer,
- Function *NewF) {
- assert(!OrigF.isDeclaration() && "Nothing to move");
- if (!NewF)
- NewF = cast<Function>(VMap[&OrigF]);
- else
- assert(VMap[&OrigF] == NewF && "Incorrect function mapping in VMap.");
- assert(NewF && "Function mapping missing from VMap.");
- assert(NewF->getParent() != OrigF.getParent() &&
- "moveFunctionBody should only be used to move bodies between "
- "modules.");
-
- SmallVector<ReturnInst *, 8> Returns; // Ignore returns cloned.
- CloneFunctionInto(NewF, &OrigF, VMap,
- CloneFunctionChangeType::DifferentModule, Returns, "",
- nullptr, nullptr, Materializer);
- OrigF.deleteBody();
-}
-
GlobalVariable* cloneGlobalVariableDecl(Module &Dst, const GlobalVariable &GV,
ValueToValueMapTy *VMap) {
GlobalVariable *NewGV = new GlobalVariable(
@@ -361,24 +337,6 @@ GlobalVariable* cloneGlobalVariableDecl(Module &Dst, const GlobalVariable &GV,
return NewGV;
}
-void moveGlobalVariableInitializer(GlobalVariable &OrigGV,
- ValueToValueMapTy &VMap,
- ValueMaterializer *Materializer,
- GlobalVariable *NewGV) {
- assert(OrigGV.hasInitializer() && "Nothing to move");
- if (!NewGV)
- NewGV = cast<GlobalVariable>(VMap[&OrigGV]);
- else
- assert(VMap[&OrigGV] == NewGV &&
- "Incorrect global variable mapping in VMap.");
- assert(NewGV->getParent() != OrigGV.getParent() &&
- "moveGlobalVariableInitializer should only be used to move "
- "initializers between modules");
-
- NewGV->setInitializer(MapValue(OrigGV.getInitializer(), VMap, RF_None,
- nullptr, Materializer));
-}
-
GlobalAlias* cloneGlobalAliasDecl(Module &Dst, const GlobalAlias &OrigA,
ValueToValueMapTy &VMap) {
assert(OrigA.getAliasee() && "Original alias doesn't have an aliasee?");
@@ -390,15 +348,6 @@ GlobalAlias* cloneGlobalAliasDecl(Module &Dst, const GlobalAlias &OrigA,
return NewA;
}
-void cloneModuleFlagsMetadata(Module &Dst, const Module &Src,
- ValueToValueMapTy &VMap) {
- auto *MFs = Src.getModuleFlagsMetadata();
- if (!MFs)
- return;
- for (auto *MF : MFs->operands())
- Dst.addModuleFlag(MapMetadata(MF, VMap));
-}
-
Error addFunctionPointerRelocationsToCurrentSymbol(jitlink::Symbol &Sym,
jitlink::LinkGraph &G,
MCDisassembler &Disassembler,
diff --git a/llvm/lib/ExecutionEngine/Orc/JITTargetMachineBuilder.cpp b/llvm/lib/ExecutionEngine/Orc/JITTargetMachineBuilder.cpp
index 70a3c404d836..b66f52f1ec5d 100644
--- a/llvm/lib/ExecutionEngine/Orc/JITTargetMachineBuilder.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/JITTargetMachineBuilder.cpp
@@ -9,8 +9,8 @@
#include "llvm/ExecutionEngine/Orc/JITTargetMachineBuilder.h"
#include "llvm/MC/TargetRegistry.h"
-#include "llvm/Support/Host.h"
#include "llvm/Support/raw_ostream.h"
+#include "llvm/TargetParser/Host.h"
namespace llvm {
namespace orc {
@@ -18,13 +18,10 @@ namespace orc {
JITTargetMachineBuilder::JITTargetMachineBuilder(Triple TT)
: TT(std::move(TT)) {
Options.EmulatedTLS = true;
- Options.ExplicitEmulatedTLS = true;
Options.UseInitArray = true;
}
Expected<JITTargetMachineBuilder> JITTargetMachineBuilder::detectHost() {
- // FIXME: getProcessTriple is bogus. It returns the host LLVM was compiled on,
- // rather than a valid triple for the current process.
JITTargetMachineBuilder TMBuilder((Triple(sys::getProcessTriple())));
// Retrieve host CPU name and sub-target features and add them to builder.
diff --git a/llvm/lib/ExecutionEngine/Orc/LLJIT.cpp b/llvm/lib/ExecutionEngine/Orc/LLJIT.cpp
index bc84988e3254..7c7c2f000368 100644
--- a/llvm/lib/ExecutionEngine/Orc/LLJIT.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/LLJIT.cpp
@@ -9,6 +9,11 @@
#include "llvm/ExecutionEngine/Orc/LLJIT.h"
#include "llvm/ExecutionEngine/JITLink/EHFrameSupport.h"
#include "llvm/ExecutionEngine/JITLink/JITLinkMemoryManager.h"
+#include "llvm/ExecutionEngine/Orc/COFFPlatform.h"
+#include "llvm/ExecutionEngine/Orc/DebugObjectManagerPlugin.h"
+#include "llvm/ExecutionEngine/Orc/DebuggerSupportPlugin.h"
+#include "llvm/ExecutionEngine/Orc/ELFNixPlatform.h"
+#include "llvm/ExecutionEngine/Orc/EPCDynamicLibrarySearchGenerator.h"
#include "llvm/ExecutionEngine/Orc/EPCEHFrameRegistrar.h"
#include "llvm/ExecutionEngine/Orc/ExecutorProcessControl.h"
#include "llvm/ExecutionEngine/Orc/MachOPlatform.h"
@@ -98,10 +103,16 @@ public:
ORC_RT_RTLD_GLOBAL = 0x8
};
- if (auto WrapperAddr = J.lookup("__orc_rt_jit_dlopen_wrapper")) {
- return J.getExecutionSession().callSPSWrapper<SPSDLOpenSig>(
- *WrapperAddr, DSOHandles[&JD], JD.getName(),
- int32_t(ORC_RT_RTLD_LAZY));
+ auto &ES = J.getExecutionSession();
+ auto MainSearchOrder = J.getMainJITDylib().withLinkOrderDo(
+ [](const JITDylibSearchOrder &SO) { return SO; });
+
+ if (auto WrapperAddr =
+ ES.lookup(MainSearchOrder,
+ J.mangleAndIntern("__orc_rt_jit_dlopen_wrapper"))) {
+ return ES.callSPSWrapper<SPSDLOpenSig>(WrapperAddr->getAddress(),
+ DSOHandles[&JD], JD.getName(),
+ int32_t(ORC_RT_RTLD_LAZY));
} else
return WrapperAddr.takeError();
}
@@ -110,10 +121,16 @@ public:
using llvm::orc::shared::SPSExecutorAddr;
using SPSDLCloseSig = int32_t(SPSExecutorAddr);
- if (auto WrapperAddr = J.lookup("__orc_rt_jit_dlclose_wrapper")) {
+ auto &ES = J.getExecutionSession();
+ auto MainSearchOrder = J.getMainJITDylib().withLinkOrderDo(
+ [](const JITDylibSearchOrder &SO) { return SO; });
+
+ if (auto WrapperAddr =
+ ES.lookup(MainSearchOrder,
+ J.mangleAndIntern("__orc_rt_jit_dlclose_wrapper"))) {
int32_t result;
auto E = J.getExecutionSession().callSPSWrapper<SPSDLCloseSig>(
- *WrapperAddr, result, DSOHandles[&JD]);
+ WrapperAddr->getAddress(), result, DSOHandles[&JD]);
if (E)
return E;
else if (result)
@@ -176,7 +193,7 @@ private:
/// some runtime API, including __cxa_atexit, dlopen, and dlclose.
class GenericLLVMIRPlatformSupport : public LLJIT::PlatformSupport {
public:
- GenericLLVMIRPlatformSupport(LLJIT &J)
+ GenericLLVMIRPlatformSupport(LLJIT &J, JITDylib &PlatformJD)
: J(J), InitFunctionPrefix(J.mangle("__orc_init_func.")),
DeInitFunctionPrefix(J.mangle("__orc_deinit_func.")) {
@@ -188,17 +205,14 @@ public:
SymbolMap StdInterposes;
- StdInterposes[J.mangleAndIntern("__lljit.platform_support_instance")] =
- JITEvaluatedSymbol(pointerToJITTargetAddress(this),
- JITSymbolFlags::Exported);
- StdInterposes[J.mangleAndIntern("__lljit.cxa_atexit_helper")] =
- JITEvaluatedSymbol(pointerToJITTargetAddress(registerCxaAtExitHelper),
- JITSymbolFlags());
+ StdInterposes[J.mangleAndIntern("__lljit.platform_support_instance")] = {
+ ExecutorAddr::fromPtr(this), JITSymbolFlags::Exported};
+ StdInterposes[J.mangleAndIntern("__lljit.cxa_atexit_helper")] = {
+ ExecutorAddr::fromPtr(registerCxaAtExitHelper), JITSymbolFlags()};
- cantFail(
- J.getMainJITDylib().define(absoluteSymbols(std::move(StdInterposes))));
- cantFail(setupJITDylib(J.getMainJITDylib()));
- cantFail(J.addIRModule(J.getMainJITDylib(), createPlatformRuntimeModule()));
+ cantFail(PlatformJD.define(absoluteSymbols(std::move(StdInterposes))));
+ cantFail(setupJITDylib(PlatformJD));
+ cantFail(J.addIRModule(PlatformJD, createPlatformRuntimeModule()));
}
ExecutionSession &getExecutionSession() { return J.getExecutionSession(); }
@@ -208,12 +222,10 @@ public:
// Add per-jitdylib standard interposes.
SymbolMap PerJDInterposes;
- PerJDInterposes[J.mangleAndIntern("__lljit.run_atexits_helper")] =
- JITEvaluatedSymbol(pointerToJITTargetAddress(runAtExitsHelper),
- JITSymbolFlags());
- PerJDInterposes[J.mangleAndIntern("__lljit.atexit_helper")] =
- JITEvaluatedSymbol(pointerToJITTargetAddress(registerAtExitHelper),
- JITSymbolFlags());
+ PerJDInterposes[J.mangleAndIntern("__lljit.run_atexits_helper")] = {
+ ExecutorAddr::fromPtr(runAtExitsHelper), JITSymbolFlags()};
+ PerJDInterposes[J.mangleAndIntern("__lljit.atexit_helper")] = {
+ ExecutorAddr::fromPtr(registerAtExitHelper), JITSymbolFlags()};
cantFail(JD.define(absoluteSymbols(std::move(PerJDInterposes))));
auto Ctx = std::make_unique<LLVMContext>();
@@ -227,7 +239,7 @@ public:
"__dso_handle");
DSOHandle->setVisibility(GlobalValue::DefaultVisibility);
DSOHandle->setInitializer(
- ConstantInt::get(Int64Ty, pointerToJITTargetAddress(&JD)));
+ ConstantInt::get(Int64Ty, ExecutorAddr::fromPtr(&JD).getValue()));
auto *GenericIRPlatformSupportTy =
StructType::create(*Ctx, "lljit.GenericLLJITIRPlatformSupport");
@@ -287,7 +299,7 @@ public:
dbgs() << " Running init " << formatv("{0:x16}", InitFnAddr)
<< "...\n";
});
- auto *InitFn = jitTargetAddressToFunction<void (*)()>(InitFnAddr);
+ auto *InitFn = InitFnAddr.toPtr<void (*)()>();
InitFn();
}
} else
@@ -308,7 +320,7 @@ public:
dbgs() << " Running deinit " << formatv("{0:x16}", DeinitFnAddr)
<< "...\n";
});
- auto *DeinitFn = jitTargetAddressToFunction<void (*)()>(DeinitFnAddr);
+ auto *DeinitFn = DeinitFnAddr.toPtr<void (*)()>();
DeinitFn();
}
} else
@@ -329,8 +341,7 @@ public:
}
private:
-
- Expected<std::vector<JITTargetAddress>> getInitializers(JITDylib &JD) {
+ Expected<std::vector<ExecutorAddr>> getInitializers(JITDylib &JD) {
if (auto Err = issueInitLookups(JD))
return std::move(Err);
@@ -370,7 +381,7 @@ private:
if (!LookupResult)
return LookupResult.takeError();
- std::vector<JITTargetAddress> Initializers;
+ std::vector<ExecutorAddr> Initializers;
while (!DFSLinkOrder.empty()) {
auto &NextJD = *DFSLinkOrder.back();
DFSLinkOrder.pop_back();
@@ -384,7 +395,7 @@ private:
return Initializers;
}
- Expected<std::vector<JITTargetAddress>> getDeinitializers(JITDylib &JD) {
+ Expected<std::vector<ExecutorAddr>> getDeinitializers(JITDylib &JD) {
auto &ES = getExecutionSession();
auto LLJITRunAtExits = J.mangleAndIntern("__lljit_run_atexits");
@@ -427,7 +438,7 @@ private:
if (!LookupResult)
return LookupResult.takeError();
- std::vector<JITTargetAddress> DeInitializers;
+ std::vector<ExecutorAddr> DeInitializers;
for (auto &NextJD : DFSLinkOrder) {
auto DeInitsItr = LookupResult->find(NextJD.get());
assert(DeInitsItr != LookupResult->end() &&
@@ -695,6 +706,14 @@ Error LLJITBuilderState::prepareForConstruction() {
dbgs() << "\n";
});
+ // Create DL if not specified.
+ if (!DL) {
+ if (auto DLOrErr = JTMB->getDefaultDataLayoutForTarget())
+ DL = std::move(*DLOrErr);
+ else
+ return DLOrErr.takeError();
+ }
+
// If neither ES nor EPC has been set then create an EPC instance.
if (!ES && !EPC) {
LLVM_DEBUG({
@@ -705,21 +724,38 @@ Error LLJITBuilderState::prepareForConstruction() {
EPC = std::move(*EPCOrErr);
else
return EPCOrErr.takeError();
- } else
+ } else if (EPC) {
LLVM_DEBUG({
dbgs() << "Using explicitly specified ExecutorProcessControl instance "
<< EPC.get() << "\n";
});
+ } else {
+ LLVM_DEBUG({
+ dbgs() << "Using explicitly specified ExecutionSession instance "
+ << ES.get() << "\n";
+ });
+ }
// If the client didn't configure any linker options then auto-configure the
// JIT linker.
if (!CreateObjectLinkingLayer) {
auto &TT = JTMB->getTargetTriple();
- if (TT.getArch() == Triple::riscv64 ||
- TT.getArch() == Triple::loongarch64 ||
- (TT.isOSBinFormatMachO() &&
- (TT.getArch() == Triple::aarch64 || TT.getArch() == Triple::x86_64))) {
-
+ bool UseJITLink = false;
+ switch (TT.getArch()) {
+ case Triple::riscv64:
+ case Triple::loongarch64:
+ UseJITLink = true;
+ break;
+ case Triple::aarch64:
+ UseJITLink = !TT.isOSBinFormatCOFF();
+ break;
+ case Triple::x86_64:
+ UseJITLink = !TT.isOSBinFormatCOFF();
+ break;
+ default:
+ break;
+ }
+ if (UseJITLink) {
JTMB->setRelocationModel(Reloc::PIC_);
JTMB->setCodeModel(CodeModel::Small);
CreateObjectLinkingLayer =
@@ -737,6 +773,30 @@ Error LLJITBuilderState::prepareForConstruction() {
}
}
+ // If we need a process JITDylib but no setup function has been given then
+ // create a default one.
+ if (!SetupProcessSymbolsJITDylib &&
+ (LinkProcessSymbolsByDefault || EnableDebuggerSupport)) {
+
+ LLVM_DEBUG({
+ dbgs() << "Creating default Process JD setup function (neeeded for";
+ if (LinkProcessSymbolsByDefault)
+ dbgs() << " <link-process-syms-by-default>";
+ if (EnableDebuggerSupport)
+ dbgs() << " <debugger-support>";
+ dbgs() << ")\n";
+ });
+
+ SetupProcessSymbolsJITDylib = [this](JITDylib &JD) -> Error {
+ auto G = orc::DynamicLibrarySearchGenerator::GetForCurrentProcess(
+ DL->getGlobalPrefix());
+ if (!G)
+ return G.takeError();
+ JD.addGenerator(std::move(*G));
+ return Error::success();
+ };
+ }
+
return Error::success();
}
@@ -747,6 +807,54 @@ LLJIT::~LLJIT() {
ES->reportError(std::move(Err));
}
+JITDylibSP LLJIT::getProcessSymbolsJITDylib() { return ProcessSymbols; }
+
+JITDylibSP LLJIT::getPlatformJITDylib() { return Platform; }
+
+Expected<JITDylib &> LLJIT::createJITDylib(std::string Name) {
+ auto JD = ES->createJITDylib(std::move(Name));
+ if (!JD)
+ return JD.takeError();
+
+ JD->addToLinkOrder(DefaultLinks);
+ return JD;
+}
+
+Expected<JITDylib &> LLJIT::loadPlatformDynamicLibrary(const char *Path) {
+ auto G = EPCDynamicLibrarySearchGenerator::Load(*ES, Path);
+ if (!G)
+ return G.takeError();
+
+ if (auto *ExistingJD = ES->getJITDylibByName(Path))
+ return *ExistingJD;
+
+ auto &JD = ES->createBareJITDylib(Path);
+ JD.addGenerator(std::move(*G));
+ return JD;
+}
+
+Error LLJIT::linkStaticLibraryInto(JITDylib &JD,
+ std::unique_ptr<MemoryBuffer> LibBuffer) {
+ auto G = StaticLibraryDefinitionGenerator::Create(*ObjLinkingLayer,
+ std::move(LibBuffer));
+ if (!G)
+ return G.takeError();
+
+ JD.addGenerator(std::move(*G));
+
+ return Error::success();
+}
+
+Error LLJIT::linkStaticLibraryInto(JITDylib &JD, const char *Path) {
+ auto G = StaticLibraryDefinitionGenerator::Load(*ObjLinkingLayer, Path);
+ if (!G)
+ return G.takeError();
+
+ JD.addGenerator(std::move(*G));
+
+ return Error::success();
+}
+
Error LLJIT::addIRModule(ResourceTrackerSP RT, ThreadSafeModule TSM) {
assert(TSM && "Can not add null module");
@@ -777,7 +885,7 @@ Expected<ExecutorAddr> LLJIT::lookupLinkerMangled(JITDylib &JD,
if (auto Sym = ES->lookup(
makeJITDylibSearchOrder(&JD, JITDylibLookupFlags::MatchAllSymbols),
Name))
- return ExecutorAddr(Sym->getAddress());
+ return Sym->getAddress();
else
return Sym.takeError();
}
@@ -832,7 +940,7 @@ LLJIT::createCompileFunction(LLJITBuilderState &S,
}
LLJIT::LLJIT(LLJITBuilderState &S, Error &Err)
- : DL(""), TT(S.JTMB->getTargetTriple()) {
+ : DL(std::move(*S.DL)), TT(S.JTMB->getTargetTriple()) {
ErrorAsOutParameter _(&Err);
@@ -851,22 +959,6 @@ LLJIT::LLJIT(LLJITBuilderState &S, Error &Err)
}
}
- if (auto MainOrErr = this->ES->createJITDylib("main"))
- Main = &*MainOrErr;
- else {
- Err = MainOrErr.takeError();
- return;
- }
-
- if (S.DL)
- DL = std::move(*S.DL);
- else if (auto DLOrErr = S.JTMB->getDefaultDataLayoutForTarget())
- DL = std::move(*DLOrErr);
- else {
- Err = DLOrErr.takeError();
- return;
- }
-
auto ObjLayer = createObjectLinkingLayer(S, *ES);
if (!ObjLayer) {
Err = ObjLayer.takeError();
@@ -905,10 +997,77 @@ LLJIT::LLJIT(LLJITBuilderState &S, Error &Err)
});
}
- if (S.SetUpPlatform)
- Err = S.SetUpPlatform(*this);
- else
- setUpGenericLLVMIRPlatform(*this);
+ if (S.SetupProcessSymbolsJITDylib) {
+ ProcessSymbols = &ES->createBareJITDylib("<Process Symbols>");
+ if (auto Err2 = S.SetupProcessSymbolsJITDylib(*ProcessSymbols)) {
+ Err = std::move(Err2);
+ return;
+ }
+ }
+
+ if (S.EnableDebuggerSupport) {
+ if (auto *OLL = dyn_cast<ObjectLinkingLayer>(ObjLinkingLayer.get())) {
+ switch (TT.getObjectFormat()) {
+ case Triple::ELF: {
+ auto Registrar = createJITLoaderGDBRegistrar(*ES);
+ if (!Registrar) {
+ Err = Registrar.takeError();
+ return;
+ }
+ OLL->addPlugin(std::make_unique<DebugObjectManagerPlugin>(
+ *ES, std::move(*Registrar), true, true));
+ break;
+ }
+ case Triple::MachO: {
+ assert(ProcessSymbols && "ProcessSymbols JD should be available when "
+ "EnableDebuggerSupport is set");
+ auto DS =
+ GDBJITDebugInfoRegistrationPlugin::Create(*ES, *ProcessSymbols, TT);
+ if (!DS) {
+ Err = DS.takeError();
+ return;
+ }
+ OLL->addPlugin(std::move(*DS));
+ break;
+ }
+ default:
+ LLVM_DEBUG({
+ dbgs() << "Cannot enable LLJIT debugger support: "
+ << Triple::getObjectFormatTypeName(TT.getObjectFormat())
+ << " not supported.\n";
+ });
+ }
+ } else {
+ LLVM_DEBUG({
+ dbgs() << "Cannot enable LLJIT debugger support: "
+ " debugger support is only available when using JITLink.\n";
+ });
+ }
+ }
+
+ if (!S.SetUpPlatform)
+ S.SetUpPlatform = setUpGenericLLVMIRPlatform;
+
+ if (auto PlatformJDOrErr = S.SetUpPlatform(*this)) {
+ Platform = PlatformJDOrErr->get();
+ if (Platform)
+ DefaultLinks.push_back(
+ {Platform, JITDylibLookupFlags::MatchExportedSymbolsOnly});
+ } else {
+ Err = PlatformJDOrErr.takeError();
+ return;
+ }
+
+ if (S.LinkProcessSymbolsByDefault)
+ DefaultLinks.push_back(
+ {ProcessSymbols, JITDylibLookupFlags::MatchExportedSymbolsOnly});
+
+ if (auto MainOrErr = createJITDylib("main"))
+ Main = &*MainOrErr;
+ else {
+ Err = MainOrErr.takeError();
+ return;
+ }
}
std::string LLJIT::mangle(StringRef UnmangledName) const {
@@ -934,24 +1093,136 @@ Error LLJIT::applyDataLayout(Module &M) {
return Error::success();
}
-Error setUpOrcPlatform(LLJIT& J) {
- LLVM_DEBUG(
- { dbgs() << "Setting up orc platform support for LLJIT\n"; });
- J.setPlatformSupport(std::make_unique<ORCPlatformSupport>(J));
+Error setUpOrcPlatformManually(LLJIT &J) {
+ LLVM_DEBUG({ dbgs() << "Setting up orc platform support for LLJIT\n"; });
+ J.setPlatformSupport(std::make_unique<ORCPlatformSupport>(J));
+ return Error::success();
+}
+
+class LoadAndLinkDynLibrary {
+public:
+ LoadAndLinkDynLibrary(LLJIT &J) : J(J) {}
+ Error operator()(JITDylib &JD, StringRef DLLName) {
+ if (!DLLName.ends_with_insensitive(".dll"))
+ return make_error<StringError>("DLLName not ending with .dll",
+ inconvertibleErrorCode());
+ auto DLLNameStr = DLLName.str(); // Guarantees null-termination.
+ auto DLLJD = J.loadPlatformDynamicLibrary(DLLNameStr.c_str());
+ if (!DLLJD)
+ return DLLJD.takeError();
+ JD.addToLinkOrder(*DLLJD);
return Error::success();
+ }
+
+private:
+ LLJIT &J;
+};
+
+Expected<JITDylibSP> ExecutorNativePlatform::operator()(LLJIT &J) {
+ auto ProcessSymbolsJD = J.getProcessSymbolsJITDylib();
+ if (!ProcessSymbolsJD)
+ return make_error<StringError>(
+ "Native platforms require a process symbols JITDylib",
+ inconvertibleErrorCode());
+
+ const Triple &TT = J.getTargetTriple();
+ ObjectLinkingLayer *ObjLinkingLayer =
+ dyn_cast<ObjectLinkingLayer>(&J.getObjLinkingLayer());
+
+ if (!ObjLinkingLayer)
+ return make_error<StringError>(
+ "SetUpTargetPlatform requires ObjectLinkingLayer",
+ inconvertibleErrorCode());
+
+ std::unique_ptr<MemoryBuffer> RuntimeArchiveBuffer;
+ if (OrcRuntime.index() == 0) {
+ auto A = errorOrToExpected(MemoryBuffer::getFile(std::get<0>(OrcRuntime)));
+ if (!A)
+ return A.takeError();
+ RuntimeArchiveBuffer = std::move(*A);
+ } else
+ RuntimeArchiveBuffer = std::move(std::get<1>(OrcRuntime));
+
+ auto &ES = J.getExecutionSession();
+ auto &PlatformJD = ES.createBareJITDylib("<Platform>");
+ PlatformJD.addToLinkOrder(*ProcessSymbolsJD);
+
+ J.setPlatformSupport(std::make_unique<ORCPlatformSupport>(J));
+
+ switch (TT.getObjectFormat()) {
+ case Triple::COFF: {
+ const char *VCRuntimePath = nullptr;
+ bool StaticVCRuntime = false;
+ if (VCRuntime) {
+ VCRuntimePath = VCRuntime->first.c_str();
+ StaticVCRuntime = VCRuntime->second;
+ }
+ if (auto P = COFFPlatform::Create(
+ ES, *ObjLinkingLayer, PlatformJD, std::move(RuntimeArchiveBuffer),
+ LoadAndLinkDynLibrary(J), StaticVCRuntime, VCRuntimePath))
+ J.getExecutionSession().setPlatform(std::move(*P));
+ else
+ return P.takeError();
+ break;
+ }
+ case Triple::ELF: {
+ auto G = StaticLibraryDefinitionGenerator::Create(
+ *ObjLinkingLayer, std::move(RuntimeArchiveBuffer));
+ if (!G)
+ return G.takeError();
+
+ if (auto P = ELFNixPlatform::Create(ES, *ObjLinkingLayer, PlatformJD,
+ std::move(*G)))
+ J.getExecutionSession().setPlatform(std::move(*P));
+ else
+ return P.takeError();
+ break;
+ }
+ case Triple::MachO: {
+ auto G = StaticLibraryDefinitionGenerator::Create(
+ *ObjLinkingLayer, std::move(RuntimeArchiveBuffer));
+ if (!G)
+ return G.takeError();
+
+ if (auto P = MachOPlatform::Create(ES, *ObjLinkingLayer, PlatformJD,
+ std::move(*G)))
+ ES.setPlatform(std::move(*P));
+ else
+ return P.takeError();
+ break;
+ }
+ default:
+ return make_error<StringError>("Unsupported object format in triple " +
+ TT.str(),
+ inconvertibleErrorCode());
+ }
+
+ return &PlatformJD;
}
-void setUpGenericLLVMIRPlatform(LLJIT &J) {
+Expected<JITDylibSP> setUpGenericLLVMIRPlatform(LLJIT &J) {
LLVM_DEBUG(
{ dbgs() << "Setting up GenericLLVMIRPlatform support for LLJIT\n"; });
- J.setPlatformSupport(std::make_unique<GenericLLVMIRPlatformSupport>(J));
+ auto ProcessSymbolsJD = J.getProcessSymbolsJITDylib();
+ if (!ProcessSymbolsJD)
+ return make_error<StringError>(
+ "Native platforms require a process symbols JITDylib",
+ inconvertibleErrorCode());
+
+ auto &PlatformJD = J.getExecutionSession().createBareJITDylib("<Platform>");
+ PlatformJD.addToLinkOrder(*ProcessSymbolsJD);
+
+ J.setPlatformSupport(
+ std::make_unique<GenericLLVMIRPlatformSupport>(J, PlatformJD));
+
+ return &PlatformJD;
}
-Error setUpInactivePlatform(LLJIT &J) {
+Expected<JITDylibSP> setUpInactivePlatform(LLJIT &J) {
LLVM_DEBUG(
{ dbgs() << "Explicitly deactivated platform support for LLJIT\n"; });
J.setPlatformSupport(std::make_unique<InactivePlatformSupport>());
- return Error::success();
+ return nullptr;
}
Error LLLazyJITBuilderState::prepareForConstruction() {
@@ -984,7 +1255,7 @@ LLLazyJIT::LLLazyJIT(LLLazyJITBuilderState &S, Error &Err) : LLJIT(S, Err) {
LCTMgr = std::move(S.LCTMgr);
else {
if (auto LCTMgrOrErr = createLocalLazyCallThroughManager(
- S.TT, *ES, S.LazyCompileFailureAddr.getValue()))
+ S.TT, *ES, S.LazyCompileFailureAddr))
LCTMgr = std::move(*LCTMgrOrErr);
else {
Err = LCTMgrOrErr.takeError();
diff --git a/llvm/lib/ExecutionEngine/Orc/Layer.cpp b/llvm/lib/ExecutionEngine/Orc/Layer.cpp
index 95380d912392..3368d3276cb3 100644
--- a/llvm/lib/ExecutionEngine/Orc/Layer.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/Layer.cpp
@@ -125,6 +125,10 @@ void IRMaterializationUnit::discard(const JITDylib &JD,
assert(!I->second->isDeclaration() &&
"Discard should only apply to definitions");
I->second->setLinkage(GlobalValue::AvailableExternallyLinkage);
+ // According to the IR verifier, "Declaration[s] may not be in a Comdat!"
+ // Remove it, if this is a GlobalObject.
+ if (auto *GO = dyn_cast<GlobalObject>(I->second))
+ GO->setComdat(nullptr);
SymbolToDefinition.erase(I);
}
diff --git a/llvm/lib/ExecutionEngine/Orc/LazyReexports.cpp b/llvm/lib/ExecutionEngine/Orc/LazyReexports.cpp
index c0a740d42dbd..d95a642934f1 100644
--- a/llvm/lib/ExecutionEngine/Orc/LazyReexports.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/LazyReexports.cpp
@@ -8,19 +8,20 @@
#include "llvm/ExecutionEngine/Orc/LazyReexports.h"
-#include "llvm/ADT/Triple.h"
#include "llvm/ExecutionEngine/Orc/OrcABISupport.h"
+#include "llvm/TargetParser/Triple.h"
#define DEBUG_TYPE "orc"
namespace llvm {
namespace orc {
-LazyCallThroughManager::LazyCallThroughManager(
- ExecutionSession &ES, JITTargetAddress ErrorHandlerAddr, TrampolinePool *TP)
+LazyCallThroughManager::LazyCallThroughManager(ExecutionSession &ES,
+ ExecutorAddr ErrorHandlerAddr,
+ TrampolinePool *TP)
: ES(ES), ErrorHandlerAddr(ErrorHandlerAddr), TP(TP) {}
-Expected<JITTargetAddress> LazyCallThroughManager::getCallThroughTrampoline(
+Expected<ExecutorAddr> LazyCallThroughManager::getCallThroughTrampoline(
JITDylib &SourceJD, SymbolStringPtr SymbolName,
NotifyResolvedFunction NotifyResolved) {
assert(TP && "TrampolinePool not set");
@@ -36,24 +37,24 @@ Expected<JITTargetAddress> LazyCallThroughManager::getCallThroughTrampoline(
return *Trampoline;
}
-JITTargetAddress LazyCallThroughManager::reportCallThroughError(Error Err) {
+ExecutorAddr LazyCallThroughManager::reportCallThroughError(Error Err) {
ES.reportError(std::move(Err));
return ErrorHandlerAddr;
}
Expected<LazyCallThroughManager::ReexportsEntry>
-LazyCallThroughManager::findReexport(JITTargetAddress TrampolineAddr) {
+LazyCallThroughManager::findReexport(ExecutorAddr TrampolineAddr) {
std::lock_guard<std::mutex> Lock(LCTMMutex);
auto I = Reexports.find(TrampolineAddr);
if (I == Reexports.end())
return createStringError(inconvertibleErrorCode(),
- "Missing reexport for trampoline address %p",
- TrampolineAddr);
+ "Missing reexport for trampoline address %p" +
+ formatv("{0:x}", TrampolineAddr));
return I->second;
}
-Error LazyCallThroughManager::notifyResolved(JITTargetAddress TrampolineAddr,
- JITTargetAddress ResolvedAddr) {
+Error LazyCallThroughManager::notifyResolved(ExecutorAddr TrampolineAddr,
+ ExecutorAddr ResolvedAddr) {
NotifyResolvedFunction NotifyResolved;
{
std::lock_guard<std::mutex> Lock(LCTMMutex);
@@ -68,7 +69,7 @@ Error LazyCallThroughManager::notifyResolved(JITTargetAddress TrampolineAddr,
}
void LazyCallThroughManager::resolveTrampolineLandingAddress(
- JITTargetAddress TrampolineAddr,
+ ExecutorAddr TrampolineAddr,
NotifyLandingResolvedFunction NotifyLandingResolved) {
auto Entry = findReexport(TrampolineAddr);
@@ -84,7 +85,7 @@ void LazyCallThroughManager::resolveTrampolineLandingAddress(
if (Result) {
assert(Result->size() == 1 && "Unexpected result size");
assert(Result->count(SymbolName) && "Unexpected result value");
- JITTargetAddress LandingAddr = (*Result)[SymbolName].getAddress();
+ ExecutorAddr LandingAddr = (*Result)[SymbolName].getAddress();
if (auto Err = notifyResolved(TrampolineAddr, LandingAddr))
NotifyLandingResolved(reportCallThroughError(std::move(Err)));
@@ -104,7 +105,7 @@ void LazyCallThroughManager::resolveTrampolineLandingAddress(
Expected<std::unique_ptr<LazyCallThroughManager>>
createLocalLazyCallThroughManager(const Triple &T, ExecutionSession &ES,
- JITTargetAddress ErrorHandlerAddr) {
+ ExecutorAddr ErrorHandlerAddr) {
switch (T.getArch()) {
default:
return make_error<StringError>(
@@ -187,7 +188,7 @@ void LazyReexportsMaterializationUnit::materialize(
auto CallThroughTrampoline = LCTManager.getCallThroughTrampoline(
SourceJD, Alias.second.Aliasee,
[&ISManager = this->ISManager,
- StubSym = Alias.first](JITTargetAddress ResolvedAddr) -> Error {
+ StubSym = Alias.first](ExecutorAddr ResolvedAddr) -> Error {
return ISManager.updatePointer(*StubSym, ResolvedAddr);
});
diff --git a/llvm/lib/ExecutionEngine/Orc/LookupAndRecordAddrs.cpp b/llvm/lib/ExecutionEngine/Orc/LookupAndRecordAddrs.cpp
index 59c63d38458b..75075c5c2a22 100644
--- a/llvm/lib/ExecutionEngine/Orc/LookupAndRecordAddrs.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/LookupAndRecordAddrs.cpp
@@ -31,8 +31,8 @@ void lookupAndRecordAddrs(
return OnRec(Result.takeError());
for (auto &KV : Pairs) {
auto I = Result->find(KV.first);
- KV.second->setValue((I != Result->end()) ? I->second.getAddress()
- : 0);
+ *KV.second =
+ I != Result->end() ? I->second.getAddress() : orc::ExecutorAddr();
}
OnRec(Error::success());
},
diff --git a/llvm/lib/ExecutionEngine/Orc/MachOPlatform.cpp b/llvm/lib/ExecutionEngine/Orc/MachOPlatform.cpp
index 914a1b5afc71..a3a766d602c1 100644
--- a/llvm/lib/ExecutionEngine/Orc/MachOPlatform.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/MachOPlatform.cpp
@@ -9,10 +9,13 @@
#include "llvm/ExecutionEngine/Orc/MachOPlatform.h"
#include "llvm/BinaryFormat/MachO.h"
+#include "llvm/ExecutionEngine/JITLink/MachO.h"
+#include "llvm/ExecutionEngine/JITLink/aarch64.h"
#include "llvm/ExecutionEngine/JITLink/x86_64.h"
#include "llvm/ExecutionEngine/Orc/DebugUtils.h"
#include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"
#include "llvm/ExecutionEngine/Orc/LookupAndRecordAddrs.h"
+#include "llvm/ExecutionEngine/Orc/Shared/ObjectFormats.h"
#include "llvm/Support/BinaryByteStream.h"
#include "llvm/Support/Debug.h"
#include <optional>
@@ -62,8 +65,7 @@ std::unique_ptr<jitlink::LinkGraph> createPlatformGraph(MachOPlatform &MOP,
std::string Name) {
unsigned PointerSize;
support::endianness Endianness;
- const auto &TT =
- MOP.getExecutionSession().getExecutorProcessControl().getTargetTriple();
+ const auto &TT = MOP.getExecutionSession().getTargetTriple();
switch (TT.getArch()) {
case Triple::aarch64:
@@ -147,8 +149,8 @@ private:
if (G.getEndianness() != support::endian::system_endianness())
MachO::swapStruct(Hdr);
- auto HeaderContent = G.allocateString(
- StringRef(reinterpret_cast<const char *>(&Hdr), sizeof(Hdr)));
+ auto HeaderContent = G.allocateContent(
+ ArrayRef<char>(reinterpret_cast<const char *>(&Hdr), sizeof(Hdr)));
return G.createContentBlock(HeaderSection, HeaderContent, ExecutorAddr(), 8,
0);
@@ -246,24 +248,23 @@ private:
ExecutorAddr MachOHeaderAddr;
};
-StringRef DataCommonSectionName = "__DATA,__common";
-StringRef DataDataSectionName = "__DATA,__data";
-StringRef EHFrameSectionName = "__TEXT,__eh_frame";
-StringRef CompactUnwindInfoSectionName = "__TEXT,__unwind_info";
-StringRef ModInitFuncSectionName = "__DATA,__mod_init_func";
-StringRef ObjCClassListSectionName = "__DATA,__objc_classlist";
-StringRef ObjCImageInfoSectionName = "__DATA,__objc_image_info";
-StringRef ObjCSelRefsSectionName = "__DATA,__objc_selrefs";
-StringRef Swift5ProtoSectionName = "__TEXT,__swift5_proto";
-StringRef Swift5ProtosSectionName = "__TEXT,__swift5_protos";
-StringRef Swift5TypesSectionName = "__TEXT,__swift5_types";
-StringRef ThreadBSSSectionName = "__DATA,__thread_bss";
-StringRef ThreadDataSectionName = "__DATA,__thread_data";
-StringRef ThreadVarsSectionName = "__DATA,__thread_vars";
+static StringRef ObjCRuntimeObjectSectionsData[] = {
+ MachOObjCCatListSectionName, MachOObjCClassListSectionName,
+ MachOObjCClassRefsSectionName, MachOObjCConstSectionName,
+ MachOObjCDataSectionName, MachOObjCSelRefsSectionName};
-StringRef InitSectionNames[] = {
- ModInitFuncSectionName, ObjCSelRefsSectionName, ObjCClassListSectionName,
- Swift5ProtosSectionName, Swift5ProtoSectionName, Swift5TypesSectionName};
+static StringRef ObjCRuntimeObjectSectionsText[] = {
+ MachOObjCClassNameSectionName, MachOObjCMethNameSectionName,
+ MachOObjCMethTypeSectionName, MachOSwift5TypesSectionName,
+ MachOSwift5TypeRefSectionName, MachOSwift5FieldMetadataSectionName,
+ MachOSwift5EntrySectionName, MachOSwift5ProtoSectionName,
+ MachOSwift5ProtosSectionName};
+
+static StringRef ObjCRuntimeObjectSectionName =
+ "__llvm_jitlink_ObjCRuntimeRegistrationObject";
+
+static StringRef ObjCImageInfoSymbolName =
+ "__llvm_jitlink_macho_objc_imageinfo";
} // end anonymous namespace
@@ -272,17 +273,18 @@ namespace orc {
Expected<std::unique_ptr<MachOPlatform>>
MachOPlatform::Create(ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer,
- JITDylib &PlatformJD, const char *OrcRuntimePath,
+ JITDylib &PlatformJD,
+ std::unique_ptr<DefinitionGenerator> OrcRuntime,
std::optional<SymbolAliasMap> RuntimeAliases) {
- auto &EPC = ES.getExecutorProcessControl();
-
// If the target is not supported then bail out immediately.
- if (!supportedTarget(EPC.getTargetTriple()))
+ if (!supportedTarget(ES.getTargetTriple()))
return make_error<StringError>("Unsupported MachOPlatform triple: " +
- EPC.getTargetTriple().str(),
+ ES.getTargetTriple().str(),
inconvertibleErrorCode());
+ auto &EPC = ES.getExecutorProcessControl();
+
// Create default aliases if the caller didn't supply any.
if (!RuntimeAliases)
RuntimeAliases = standardPlatformAliases(ES);
@@ -292,31 +294,40 @@ MachOPlatform::Create(ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer,
return std::move(Err);
// Add JIT-dispatch function support symbols.
- if (auto Err = PlatformJD.define(absoluteSymbols(
- {{ES.intern("___orc_rt_jit_dispatch"),
- {EPC.getJITDispatchInfo().JITDispatchFunction.getValue(),
- JITSymbolFlags::Exported}},
- {ES.intern("___orc_rt_jit_dispatch_ctx"),
- {EPC.getJITDispatchInfo().JITDispatchContext.getValue(),
- JITSymbolFlags::Exported}}})))
+ if (auto Err = PlatformJD.define(
+ absoluteSymbols({{ES.intern("___orc_rt_jit_dispatch"),
+ {EPC.getJITDispatchInfo().JITDispatchFunction,
+ JITSymbolFlags::Exported}},
+ {ES.intern("___orc_rt_jit_dispatch_ctx"),
+ {EPC.getJITDispatchInfo().JITDispatchContext,
+ JITSymbolFlags::Exported}}})))
return std::move(Err);
- // Create a generator for the ORC runtime archive.
- auto OrcRuntimeArchiveGenerator = StaticLibraryDefinitionGenerator::Load(
- ObjLinkingLayer, OrcRuntimePath, EPC.getTargetTriple());
- if (!OrcRuntimeArchiveGenerator)
- return OrcRuntimeArchiveGenerator.takeError();
-
// Create the instance.
Error Err = Error::success();
- auto P = std::unique_ptr<MachOPlatform>(
- new MachOPlatform(ES, ObjLinkingLayer, PlatformJD,
- std::move(*OrcRuntimeArchiveGenerator), Err));
+ auto P = std::unique_ptr<MachOPlatform>(new MachOPlatform(
+ ES, ObjLinkingLayer, PlatformJD, std::move(OrcRuntime), Err));
if (Err)
return std::move(Err);
return std::move(P);
}
+Expected<std::unique_ptr<MachOPlatform>>
+MachOPlatform::Create(ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer,
+ JITDylib &PlatformJD, const char *OrcRuntimePath,
+ std::optional<SymbolAliasMap> RuntimeAliases) {
+
+ // Create a generator for the ORC runtime archive.
+ auto OrcRuntimeArchiveGenerator =
+ StaticLibraryDefinitionGenerator::Load(ObjLinkingLayer, OrcRuntimePath);
+ if (!OrcRuntimeArchiveGenerator)
+ return OrcRuntimeArchiveGenerator.takeError();
+
+ return Create(ES, ObjLinkingLayer, PlatformJD,
+ std::move(*OrcRuntimeArchiveGenerator),
+ std::move(RuntimeAliases));
+}
+
Error MachOPlatform::setupJITDylib(JITDylib &JD) {
if (auto Err = JD.define(std::make_unique<MachOHeaderMaterializationUnit>(
*this, MachOHeaderStartSymbol)))
@@ -398,15 +409,6 @@ MachOPlatform::standardRuntimeUtilityAliases() {
StandardRuntimeUtilityAliases);
}
-bool MachOPlatform::isInitializerSection(StringRef SegName,
- StringRef SectName) {
- for (auto &Name : InitSectionNames) {
- if (Name.startswith(SegName) && Name.substr(7) == SectName)
- return true;
- }
- return false;
-}
-
bool MachOPlatform::supportedTarget(const Triple &TT) {
switch (TT.getArch()) {
case Triple::aarch64:
@@ -654,10 +656,9 @@ void MachOPlatform::rt_pushInitializers(PushInitializersSendResultFn SendResult,
});
if (!JD) {
- SendResult(
- make_error<StringError>("No JITDylib with header addr " +
- formatv("{0:x}", JDHeaderAddr.getValue()),
- inconvertibleErrorCode()));
+ SendResult(make_error<StringError>("No JITDylib with header addr " +
+ formatv("{0:x}", JDHeaderAddr),
+ inconvertibleErrorCode()));
return;
}
@@ -667,8 +668,7 @@ void MachOPlatform::rt_pushInitializers(PushInitializersSendResultFn SendResult,
void MachOPlatform::rt_lookupSymbol(SendSymbolAddressFn SendResult,
ExecutorAddr Handle, StringRef SymbolName) {
LLVM_DEBUG({
- dbgs() << "MachOPlatform::rt_lookupSymbol(\""
- << formatv("{0:x}", Handle.getValue()) << "\")\n";
+ dbgs() << "MachOPlatform::rt_lookupSymbol(\"" << Handle << "\")\n";
});
JITDylib *JD = nullptr;
@@ -681,12 +681,9 @@ void MachOPlatform::rt_lookupSymbol(SendSymbolAddressFn SendResult,
}
if (!JD) {
- LLVM_DEBUG({
- dbgs() << " No JITDylib for handle "
- << formatv("{0:x}", Handle.getValue()) << "\n";
- });
+ LLVM_DEBUG(dbgs() << " No JITDylib for handle " << Handle << "\n");
SendResult(make_error<StringError>("No JITDylib associated with handle " +
- formatv("{0:x}", Handle.getValue()),
+ formatv("{0:x}", Handle),
inconvertibleErrorCode()));
return;
}
@@ -699,7 +696,7 @@ void MachOPlatform::rt_lookupSymbol(SendSymbolAddressFn SendResult,
void operator()(Expected<SymbolMap> Result) {
if (Result) {
assert(Result->size() == 1 && "Unexpected result map count");
- SendResult(ExecutorAddr(Result->begin()->second.getAddress()));
+ SendResult(Result->begin()->second.getAddress());
} else {
SendResult(Result.takeError());
}
@@ -766,10 +763,14 @@ void MachOPlatform::MachOPlatformPlugin::modifyPassConfig(
// then add passes to preserve, process and register the init
// sections/symbols.
Config.PrePrunePasses.push_back([this, &MR](LinkGraph &G) {
- if (auto Err = preserveInitSections(G, MR))
+ if (auto Err = preserveImportantSections(G, MR))
return Err;
return processObjCImageInfo(G, MR);
});
+ Config.PostPrunePasses.push_back(
+ [this](LinkGraph &G) { return createObjCRuntimeObject(G); });
+ Config.PostAllocationPasses.push_back(
+ [this, &MR](LinkGraph &G) { return populateObjCRuntimeObject(G, MR); });
}
// Insert TLV lowering at the start of the PostPrunePasses, since we want
@@ -829,7 +830,10 @@ Error MachOPlatform::MachOPlatformPlugin::
&MP.RegisterObjectPlatformSections.Addr},
{*MP.DeregisterObjectPlatformSections.Name,
&MP.DeregisterObjectPlatformSections.Addr},
- {*MP.CreatePThreadKey.Name, &MP.CreatePThreadKey.Addr}};
+ {*MP.CreatePThreadKey.Name, &MP.CreatePThreadKey.Addr},
+ {*MP.RegisterObjCRuntimeObject.Name, &MP.RegisterObjCRuntimeObject.Addr},
+ {*MP.DeregisterObjCRuntimeObject.Name,
+ &MP.DeregisterObjCRuntimeObject.Addr}};
bool RegisterMachOHeader = false;
@@ -898,11 +902,40 @@ Error MachOPlatform::MachOPlatformPlugin::associateJITDylibHeaderSymbol(
return Error::success();
}
-Error MachOPlatform::MachOPlatformPlugin::preserveInitSections(
+Error MachOPlatform::MachOPlatformPlugin::preserveImportantSections(
jitlink::LinkGraph &G, MaterializationResponsibility &MR) {
+ // __objc_imageinfo is "important": we want to preserve it and record its
+ // address in the first graph that it appears in, then verify and discard it
+ // in all subsequent graphs. In this pass we preserve unconditionally -- we'll
+ // manually throw it away in the processObjCImageInfo pass.
+ if (auto *ObjCImageInfoSec =
+ G.findSectionByName(MachOObjCImageInfoSectionName)) {
+ if (ObjCImageInfoSec->blocks_size() != 1)
+ return make_error<StringError>(
+ "In " + G.getName() +
+ "__DATA,__objc_imageinfo contains multiple blocks",
+ inconvertibleErrorCode());
+ G.addAnonymousSymbol(**ObjCImageInfoSec->blocks().begin(), 0, 0, false,
+ true);
+ for (auto *B : ObjCImageInfoSec->blocks())
+ if (!B->edges_empty())
+ return make_error<StringError>("In " + G.getName() + ", " +
+ MachOObjCImageInfoSectionName +
+ " contains references to symbols",
+ inconvertibleErrorCode());
+ }
+
+ // Init sections are important: We need to preserve them and so that their
+ // addresses can be captured and reported to the ORC runtime in
+ // registerObjectPlatformSections.
JITLinkSymbolSet InitSectionSymbols;
- for (auto &InitSectionName : InitSectionNames) {
+ for (auto &InitSectionName : MachOInitSectionNames) {
+ // Skip ObjCImageInfo -- this shouldn't have any dependencies, and we may
+ // remove it later.
+ if (InitSectionName == MachOObjCImageInfoSectionName)
+ continue;
+
// Skip non-init sections.
auto *InitSection = G.findSectionByName(InitSectionName);
if (!InitSection)
@@ -944,7 +977,7 @@ Error MachOPlatform::MachOPlatformPlugin::processObjCImageInfo(
// OR
// (2) We already have a recorded __objc_imageinfo for this JITDylib,
// in which case we just verify it.
- auto *ObjCImageInfo = G.findSectionByName(ObjCImageInfoSectionName);
+ auto *ObjCImageInfo = G.findSectionByName(MachOObjCImageInfoSectionName);
if (!ObjCImageInfo)
return Error::success();
@@ -952,14 +985,14 @@ Error MachOPlatform::MachOPlatformPlugin::processObjCImageInfo(
// Check that the section is not empty if present.
if (ObjCImageInfoBlocks.empty())
- return make_error<StringError>("Empty " + ObjCImageInfoSectionName +
+ return make_error<StringError>("Empty " + MachOObjCImageInfoSectionName +
" section in " + G.getName(),
inconvertibleErrorCode());
// Check that there's only one block in the section.
if (std::next(ObjCImageInfoBlocks.begin()) != ObjCImageInfoBlocks.end())
return make_error<StringError>("Multiple blocks in " +
- ObjCImageInfoSectionName +
+ MachOObjCImageInfoSectionName +
" section in " + G.getName(),
inconvertibleErrorCode());
@@ -971,7 +1004,7 @@ Error MachOPlatform::MachOPlatformPlugin::processObjCImageInfo(
for (auto &E : B->edges())
if (E.getTarget().isDefined() &&
&E.getTarget().getBlock().getSection() == ObjCImageInfo)
- return make_error<StringError>(ObjCImageInfoSectionName +
+ return make_error<StringError>(MachOObjCImageInfoSectionName +
" is referenced within file " +
G.getName(),
inconvertibleErrorCode());
@@ -990,12 +1023,12 @@ Error MachOPlatform::MachOPlatformPlugin::processObjCImageInfo(
if (ObjCImageInfoItr != ObjCImageInfos.end()) {
// We've already registered an __objc_imageinfo section. Verify the
// content of this new section matches, then delete it.
- if (ObjCImageInfoItr->second.first != Version)
+ if (ObjCImageInfoItr->second.Version != Version)
return make_error<StringError>(
"ObjC version in " + G.getName() +
" does not match first registered version",
inconvertibleErrorCode());
- if (ObjCImageInfoItr->second.second != Flags)
+ if (ObjCImageInfoItr->second.Flags != Flags)
return make_error<StringError>("ObjC flags in " + G.getName() +
" do not match first registered flags",
inconvertibleErrorCode());
@@ -1007,7 +1040,14 @@ Error MachOPlatform::MachOPlatformPlugin::processObjCImageInfo(
} else {
// We haven't registered an __objc_imageinfo section yet. Register and
// move on. The section should already be marked no-dead-strip.
- ObjCImageInfos[&MR.getTargetJITDylib()] = std::make_pair(Version, Flags);
+ G.addDefinedSymbol(ObjCImageInfoBlock, 0, ObjCImageInfoSymbolName,
+ ObjCImageInfoBlock.getSize(), jitlink::Linkage::Strong,
+ jitlink::Scope::Hidden, false, true);
+ if (auto Err = MR.defineMaterializing(
+ {{MR.getExecutionSession().intern(ObjCImageInfoSymbolName),
+ JITSymbolFlags()}}))
+ return Err;
+ ObjCImageInfos[&MR.getTargetJITDylib()] = {Version, Flags};
}
return Error::success();
@@ -1024,7 +1064,7 @@ Error MachOPlatform::MachOPlatformPlugin::fixTLVSectionsAndEdges(
}
// Store key in __thread_vars struct fields.
- if (auto *ThreadDataSec = G.findSectionByName(ThreadVarsSectionName)) {
+ if (auto *ThreadDataSec = G.findSectionByName(MachOThreadVarsSectionName)) {
std::optional<uint64_t> Key;
{
std::lock_guard<std::mutex> Lock(MP.PlatformMutex);
@@ -1098,10 +1138,11 @@ MachOPlatform::MachOPlatformPlugin::findUnwindSectionInfo(
}
};
- if (Section *EHFrameSec = G.findSectionByName(EHFrameSectionName))
+ if (Section *EHFrameSec = G.findSectionByName(MachOEHFrameSectionName))
ScanUnwindInfoSection(*EHFrameSec, US.DwarfSection);
- if (Section *CUInfoSec = G.findSectionByName(CompactUnwindInfoSectionName))
+ if (Section *CUInfoSec =
+ G.findSectionByName(MachOCompactUnwindInfoSectionName))
ScanUnwindInfoSection(*CUInfoSec, US.CompactUnwindSection);
// If we didn't find any pointed-to code-blocks then there's no need to
@@ -1150,10 +1191,10 @@ Error MachOPlatform::MachOPlatformPlugin::registerObjectPlatformSections(
// Get a pointer to the thread data section if there is one. It will be used
// below.
jitlink::Section *ThreadDataSection =
- G.findSectionByName(ThreadDataSectionName);
+ G.findSectionByName(MachOThreadDataSectionName);
// Handle thread BSS section if there is one.
- if (auto *ThreadBSSSection = G.findSectionByName(ThreadBSSSectionName)) {
+ if (auto *ThreadBSSSection = G.findSectionByName(MachOThreadBSSSectionName)) {
// If there's already a thread data section in this graph then merge the
// thread BSS section content into it, otherwise just treat the thread
// BSS section as the thread data section.
@@ -1166,8 +1207,9 @@ Error MachOPlatform::MachOPlatformPlugin::registerObjectPlatformSections(
SmallVector<std::pair<StringRef, ExecutorAddrRange>, 8> MachOPlatformSecs;
// Collect data sections to register.
- StringRef DataSections[] = {DataDataSectionName, DataCommonSectionName,
- EHFrameSectionName};
+ StringRef DataSections[] = {MachODataDataSectionName,
+ MachODataCommonSectionName,
+ MachOEHFrameSectionName};
for (auto &SecName : DataSections) {
if (auto *Sec = G.findSectionByName(SecName)) {
jitlink::SectionRange R(*Sec);
@@ -1181,17 +1223,13 @@ Error MachOPlatform::MachOPlatformPlugin::registerObjectPlatformSections(
if (ThreadDataSection) {
jitlink::SectionRange R(*ThreadDataSection);
if (!R.empty())
- MachOPlatformSecs.push_back({ThreadDataSectionName, R.getRange()});
+ MachOPlatformSecs.push_back({MachOThreadDataSectionName, R.getRange()});
}
// If any platform sections were found then add an allocation action to call
// the registration function.
- StringRef PlatformSections[] = {
- ModInitFuncSectionName, ObjCClassListSectionName,
- ObjCImageInfoSectionName, ObjCSelRefsSectionName,
- Swift5ProtoSectionName, Swift5ProtosSectionName,
- Swift5TypesSectionName,
- };
+ StringRef PlatformSections[] = {MachOModInitFuncSectionName,
+ ObjCRuntimeObjectSectionName};
for (auto &SecName : PlatformSections) {
auto *Sec = G.findSectionByName(SecName);
@@ -1252,5 +1290,207 @@ Error MachOPlatform::MachOPlatformPlugin::registerObjectPlatformSections(
return Error::success();
}
+Error MachOPlatform::MachOPlatformPlugin::createObjCRuntimeObject(
+ jitlink::LinkGraph &G) {
+
+ bool NeedTextSegment = false;
+ size_t NumRuntimeSections = 0;
+
+ for (auto ObjCRuntimeSectionName : ObjCRuntimeObjectSectionsData)
+ if (G.findSectionByName(ObjCRuntimeSectionName))
+ ++NumRuntimeSections;
+
+ for (auto ObjCRuntimeSectionName : ObjCRuntimeObjectSectionsText) {
+ if (G.findSectionByName(ObjCRuntimeSectionName)) {
+ ++NumRuntimeSections;
+ NeedTextSegment = true;
+ }
+ }
+
+ // Early out for no runtime sections.
+ if (NumRuntimeSections == 0)
+ return Error::success();
+
+ // If there were any runtime sections then we need to add an __objc_imageinfo
+ // section.
+ ++NumRuntimeSections;
+
+ size_t MachOSize = sizeof(MachO::mach_header_64) +
+ (NeedTextSegment + 1) * sizeof(MachO::segment_command_64) +
+ NumRuntimeSections * sizeof(MachO::section_64);
+
+ auto &Sec = G.createSection(ObjCRuntimeObjectSectionName,
+ MemProt::Read | MemProt::Write);
+ G.createMutableContentBlock(Sec, MachOSize, ExecutorAddr(), 16, 0, true);
+
+ return Error::success();
+}
+
+Error MachOPlatform::MachOPlatformPlugin::populateObjCRuntimeObject(
+ jitlink::LinkGraph &G, MaterializationResponsibility &MR) {
+
+ auto *ObjCRuntimeObjectSec =
+ G.findSectionByName(ObjCRuntimeObjectSectionName);
+
+ if (!ObjCRuntimeObjectSec)
+ return Error::success();
+
+ switch (G.getTargetTriple().getArch()) {
+ case Triple::aarch64:
+ case Triple::x86_64:
+ // Supported.
+ break;
+ default:
+ return make_error<StringError>("Unrecognized MachO arch in triple " +
+ G.getTargetTriple().str(),
+ inconvertibleErrorCode());
+ }
+
+ auto &SecBlock = **ObjCRuntimeObjectSec->blocks().begin();
+
+ struct SecDesc {
+ MachO::section_64 Sec;
+ unique_function<void(size_t RecordOffset)> AddFixups;
+ };
+
+ std::vector<SecDesc> TextSections, DataSections;
+ auto AddSection = [&](SecDesc &SD, jitlink::Section &GraphSec) {
+ jitlink::SectionRange SR(GraphSec);
+ StringRef FQName = GraphSec.getName();
+ memset(&SD.Sec, 0, sizeof(MachO::section_64));
+ memcpy(SD.Sec.sectname, FQName.drop_front(7).data(), FQName.size() - 7);
+ memcpy(SD.Sec.segname, FQName.data(), 6);
+ SD.Sec.addr = SR.getStart() - SecBlock.getAddress();
+ SD.Sec.size = SR.getSize();
+ SD.Sec.flags = MachO::S_REGULAR;
+ };
+
+ // Add the __objc_imageinfo section.
+ {
+ DataSections.push_back({});
+ auto &SD = DataSections.back();
+ memset(&SD.Sec, 0, sizeof(SD.Sec));
+ memcpy(SD.Sec.sectname, "__objc_imageinfo", 16);
+ strcpy(SD.Sec.segname, "__DATA");
+ SD.Sec.size = 8;
+ SD.AddFixups = [&](size_t RecordOffset) {
+ jitlink::Edge::Kind PointerEdge = jitlink::Edge::Invalid;
+ switch (G.getTargetTriple().getArch()) {
+ case Triple::aarch64:
+ PointerEdge = jitlink::aarch64::Pointer64;
+ break;
+ case Triple::x86_64:
+ PointerEdge = jitlink::x86_64::Pointer64;
+ break;
+ default:
+ llvm_unreachable("Unsupported architecture");
+ }
+
+ // Look for an existing __objc_imageinfo symbol.
+ jitlink::Symbol *ObjCImageInfoSym = nullptr;
+ for (auto *Sym : G.external_symbols())
+ if (Sym->getName() == ObjCImageInfoSymbolName) {
+ ObjCImageInfoSym = Sym;
+ break;
+ }
+ if (!ObjCImageInfoSym)
+ for (auto *Sym : G.absolute_symbols())
+ if (Sym->getName() == ObjCImageInfoSymbolName) {
+ ObjCImageInfoSym = Sym;
+ break;
+ }
+ if (!ObjCImageInfoSym)
+ for (auto *Sym : G.defined_symbols())
+ if (Sym->hasName() && Sym->getName() == ObjCImageInfoSymbolName) {
+ ObjCImageInfoSym = Sym;
+ break;
+ }
+ if (!ObjCImageInfoSym)
+ ObjCImageInfoSym =
+ &G.addExternalSymbol(ObjCImageInfoSymbolName, 8, false);
+
+ SecBlock.addEdge(PointerEdge,
+ RecordOffset + ((char *)&SD.Sec.addr - (char *)&SD.Sec),
+ *ObjCImageInfoSym, -SecBlock.getAddress().getValue());
+ };
+ }
+
+ for (auto ObjCRuntimeSectionName : ObjCRuntimeObjectSectionsData) {
+ if (auto *GraphSec = G.findSectionByName(ObjCRuntimeSectionName)) {
+ DataSections.push_back({});
+ AddSection(DataSections.back(), *GraphSec);
+ }
+ }
+
+ for (auto ObjCRuntimeSectionName : ObjCRuntimeObjectSectionsText) {
+ if (auto *GraphSec = G.findSectionByName(ObjCRuntimeSectionName)) {
+ TextSections.push_back({});
+ AddSection(TextSections.back(), *GraphSec);
+ }
+ }
+
+ assert(ObjCRuntimeObjectSec->blocks_size() == 1 &&
+ "Unexpected number of blocks in runtime sections object");
+
+ // Build the header struct up-front. This also gives us a chance to check
+ // that the triple is supported, which we'll assume below.
+ MachO::mach_header_64 Hdr;
+ Hdr.magic = MachO::MH_MAGIC_64;
+ switch (G.getTargetTriple().getArch()) {
+ case Triple::aarch64:
+ Hdr.cputype = MachO::CPU_TYPE_ARM64;
+ Hdr.cpusubtype = MachO::CPU_SUBTYPE_ARM64_ALL;
+ break;
+ case Triple::x86_64:
+ Hdr.cputype = MachO::CPU_TYPE_X86_64;
+ Hdr.cpusubtype = MachO::CPU_SUBTYPE_X86_64_ALL;
+ break;
+ default:
+ llvm_unreachable("Unsupported architecture");
+ }
+
+ Hdr.filetype = MachO::MH_DYLIB;
+ Hdr.ncmds = 1 + !TextSections.empty();
+ Hdr.sizeofcmds =
+ Hdr.ncmds * sizeof(MachO::segment_command_64) +
+ (TextSections.size() + DataSections.size()) * sizeof(MachO::section_64);
+ Hdr.flags = 0;
+ Hdr.reserved = 0;
+
+ auto SecContent = SecBlock.getAlreadyMutableContent();
+ char *P = SecContent.data();
+ auto WriteMachOStruct = [&](auto S) {
+ if (G.getEndianness() != support::endian::system_endianness())
+ MachO::swapStruct(S);
+ memcpy(P, &S, sizeof(S));
+ P += sizeof(S);
+ };
+
+ auto WriteSegment = [&](StringRef Name, std::vector<SecDesc> &Secs) {
+ MachO::segment_command_64 SegLC;
+ memset(&SegLC, 0, sizeof(SegLC));
+ memcpy(SegLC.segname, Name.data(), Name.size());
+ SegLC.cmd = MachO::LC_SEGMENT_64;
+ SegLC.cmdsize = sizeof(MachO::segment_command_64) +
+ Secs.size() * sizeof(MachO::section_64);
+ SegLC.nsects = Secs.size();
+ WriteMachOStruct(SegLC);
+ for (auto &SD : Secs) {
+ if (SD.AddFixups)
+ SD.AddFixups(P - SecContent.data());
+ WriteMachOStruct(SD.Sec);
+ }
+ };
+
+ WriteMachOStruct(Hdr);
+ if (!TextSections.empty())
+ WriteSegment("__TEXT", TextSections);
+ if (!DataSections.empty())
+ WriteSegment("__DATA", DataSections);
+
+ assert(P == SecContent.end() && "Underflow writing ObjC runtime object");
+ return Error::success();
+}
+
} // End namespace orc.
} // End namespace llvm.
diff --git a/llvm/lib/ExecutionEngine/Orc/MemoryMapper.cpp b/llvm/lib/ExecutionEngine/Orc/MemoryMapper.cpp
index b457c7297bed..ca4950077ffe 100644
--- a/llvm/lib/ExecutionEngine/Orc/MemoryMapper.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/MemoryMapper.cpp
@@ -322,7 +322,8 @@ void SharedMemoryMapper::initialize(MemoryMapper::AllocInfo &AI,
std::memset(Base + Segment.ContentSize, 0, Segment.ZeroFillSize);
tpctypes::SharedMemorySegFinalizeRequest SegReq;
- SegReq.AG = Segment.AG;
+ SegReq.RAG = {Segment.AG.getMemProt(), Segment.AG.getMemLifetimePolicy() ==
+ MemLifetimePolicy::Finalize};
SegReq.Addr = AI.MappingBase + Segment.Offset;
SegReq.Size = Segment.ContentSize + Segment.ZeroFillSize;
diff --git a/llvm/lib/ExecutionEngine/Orc/ObjectFileInterface.cpp b/llvm/lib/ExecutionEngine/Orc/ObjectFileInterface.cpp
index 0c3beba43a35..7c8fa63477d0 100644
--- a/llvm/lib/ExecutionEngine/Orc/ObjectFileInterface.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/ObjectFileInterface.cpp
@@ -10,6 +10,7 @@
#include "llvm/ExecutionEngine/Orc/COFFPlatform.h"
#include "llvm/ExecutionEngine/Orc/ELFNixPlatform.h"
#include "llvm/ExecutionEngine/Orc/MachOPlatform.h"
+#include "llvm/ExecutionEngine/Orc/Shared/ObjectFormats.h"
#include "llvm/Object/COFF.h"
#include "llvm/Object/ELFObjectFile.h"
#include "llvm/Object/MachO.h"
@@ -85,7 +86,7 @@ getMachOObjectFileSymbolInfo(ExecutionSession &ES,
}
auto SegName = Obj.getSectionFinalSegmentName(Sec.getRawDataRefImpl());
auto SecName = cantFail(Obj.getSectionName(Sec.getRawDataRefImpl()));
- if (MachOPlatform::isInitializerSection(SegName, SecName)) {
+ if (isMachOInitializerSection(SegName, SecName)) {
addInitSymbol(I, ES, Obj.getFileName());
break;
}
@@ -138,7 +139,7 @@ getELFObjectFileSymbolInfo(ExecutionSession &ES,
SymbolStringPtr InitSymbol;
for (auto &Sec : Obj.sections()) {
if (auto SecName = Sec.getName()) {
- if (ELFNixPlatform::isInitializerSection(*SecName)) {
+ if (isELFInitializerSection(*SecName)) {
addInitSymbol(I, ES, Obj.getFileName());
break;
}
@@ -219,7 +220,7 @@ getCOFFObjectFileSymbolInfo(ExecutionSession &ES,
SymbolStringPtr InitSymbol;
for (auto &Sec : Obj.sections()) {
if (auto SecName = Sec.getName()) {
- if (COFFPlatform::isInitializerSection(*SecName)) {
+ if (isCOFFInitializerSection(*SecName)) {
addInitSymbol(I, ES, Obj.getFileName());
break;
}
@@ -287,22 +288,5 @@ getObjectFileInterface(ExecutionSession &ES, MemoryBufferRef ObjBuffer) {
return getGenericObjectFileSymbolInfo(ES, **Obj);
}
-bool hasInitializerSection(jitlink::LinkGraph &G) {
- bool IsMachO = G.getTargetTriple().isOSBinFormatMachO();
- bool IsElf = G.getTargetTriple().isOSBinFormatELF();
- if (!IsMachO && !IsElf)
- return false;
-
- for (auto &Sec : G.sections()) {
- if (IsMachO && std::apply(MachOPlatform::isInitializerSection,
- Sec.getName().split(",")))
- return true;
- if (IsElf && ELFNixPlatform::isInitializerSection(Sec.getName()))
- return true;
- }
-
- return false;
-}
-
} // End namespace orc.
} // End namespace llvm.
diff --git a/llvm/lib/ExecutionEngine/Orc/ObjectLinkingLayer.cpp b/llvm/lib/ExecutionEngine/Orc/ObjectLinkingLayer.cpp
index 2b11c472e812..a29f3d1c3aec 100644
--- a/llvm/lib/ExecutionEngine/Orc/ObjectLinkingLayer.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/ObjectLinkingLayer.cpp
@@ -8,8 +8,10 @@
#include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h"
#include "llvm/ExecutionEngine/JITLink/EHFrameSupport.h"
+#include "llvm/ExecutionEngine/JITLink/aarch32.h"
#include "llvm/ExecutionEngine/Orc/DebugObjectManagerPlugin.h"
#include "llvm/ExecutionEngine/Orc/ObjectFileInterface.h"
+#include "llvm/ExecutionEngine/Orc/Shared/ObjectFormats.h"
#include "llvm/Support/MemoryBuffer.h"
#include <string>
#include <vector>
@@ -22,6 +24,55 @@ using namespace llvm::orc;
namespace {
+bool hasInitializerSection(jitlink::LinkGraph &G) {
+ bool IsMachO = G.getTargetTriple().isOSBinFormatMachO();
+ bool IsElf = G.getTargetTriple().isOSBinFormatELF();
+ if (!IsMachO && !IsElf)
+ return false;
+
+ for (auto &Sec : G.sections()) {
+ if (IsMachO && isMachOInitializerSection(Sec.getName()))
+ return true;
+ if (IsElf && isELFInitializerSection(Sec.getName()))
+ return true;
+ }
+
+ return false;
+}
+
+ExecutorAddr getJITSymbolPtrForSymbol(Symbol &Sym, const Triple &TT) {
+ switch (TT.getArch()) {
+ case Triple::arm:
+ case Triple::armeb:
+ case Triple::thumb:
+ case Triple::thumbeb:
+ if (Sym.hasTargetFlags(aarch32::ThumbSymbol)) {
+ // Set LSB to indicate thumb target
+ assert(Sym.isCallable() && "Only callable symbols can have thumb flag");
+ assert((Sym.getAddress().getValue() & 0x01) == 0 && "LSB is clear");
+ return Sym.getAddress() + 0x01;
+ }
+ return Sym.getAddress();
+ default:
+ return Sym.getAddress();
+ }
+}
+
+JITSymbolFlags getJITSymbolFlagsForSymbol(Symbol &Sym) {
+ JITSymbolFlags Flags;
+
+ if (Sym.getLinkage() == Linkage::Weak)
+ Flags |= JITSymbolFlags::Weak;
+
+ if (Sym.getScope() == Scope::Default)
+ Flags |= JITSymbolFlags::Exported;
+
+ if (Sym.isCallable())
+ Flags |= JITSymbolFlags::Callable;
+
+ return Flags;
+}
+
class LinkGraphMaterializationUnit : public MaterializationUnit {
public:
static std::unique_ptr<LinkGraphMaterializationUnit>
@@ -48,14 +99,8 @@ private:
continue;
assert(Sym->hasName() && "Anonymous non-local symbol?");
- JITSymbolFlags Flags;
- if (Sym->getScope() == Scope::Default)
- Flags |= JITSymbolFlags::Exported;
-
- if (Sym->isCallable())
- Flags |= JITSymbolFlags::Callable;
-
- LGI.SymbolFlags[ES.intern(Sym->getName())] = Flags;
+ LGI.SymbolFlags[ES.intern(Sym->getName())] =
+ getJITSymbolFlagsForSymbol(*Sym);
}
if (hasInitializerSection(G))
@@ -189,17 +234,9 @@ public:
for (auto *Sym : G.defined_symbols())
if (Sym->hasName() && Sym->getScope() != Scope::Local) {
auto InternedName = ES.intern(Sym->getName());
- JITSymbolFlags Flags;
-
- if (Sym->isCallable())
- Flags |= JITSymbolFlags::Callable;
- if (Sym->getScope() == Scope::Default)
- Flags |= JITSymbolFlags::Exported;
- if (Sym->getLinkage() == Linkage::Weak)
- Flags |= JITSymbolFlags::Weak;
-
- InternedResult[InternedName] =
- JITEvaluatedSymbol(Sym->getAddress().getValue(), Flags);
+ auto Ptr = getJITSymbolPtrForSymbol(*Sym, G.getTargetTriple());
+ auto Flags = getJITSymbolFlagsForSymbol(*Sym);
+ InternedResult[InternedName] = {Ptr, Flags};
if (AutoClaim && !MR->getSymbols().count(InternedName)) {
assert(!ExtraSymbolsToClaim.count(InternedName) &&
"Duplicate symbol to claim?");
@@ -210,15 +247,9 @@ public:
for (auto *Sym : G.absolute_symbols())
if (Sym->hasName() && Sym->getScope() != Scope::Local) {
auto InternedName = ES.intern(Sym->getName());
- JITSymbolFlags Flags;
- if (Sym->isCallable())
- Flags |= JITSymbolFlags::Callable;
- if (Sym->getScope() == Scope::Default)
- Flags |= JITSymbolFlags::Exported;
- if (Sym->getLinkage() == Linkage::Weak)
- Flags |= JITSymbolFlags::Weak;
- InternedResult[InternedName] =
- JITEvaluatedSymbol(Sym->getAddress().getValue(), Flags);
+ auto Ptr = getJITSymbolPtrForSymbol(*Sym, G.getTargetTriple());
+ auto Flags = getJITSymbolFlagsForSymbol(*Sym);
+ InternedResult[InternedName] = {Ptr, Flags};
if (AutoClaim && !MR->getSymbols().count(InternedName)) {
assert(!ExtraSymbolsToClaim.count(InternedName) &&
"Duplicate symbol to claim?");
@@ -407,10 +438,8 @@ private:
Sym->getScope() != Scope::Local) {
auto Name = ES.intern(Sym->getName());
if (!MR->getSymbols().count(ES.intern(Sym->getName()))) {
- JITSymbolFlags SF = JITSymbolFlags::Weak;
- if (Sym->getScope() == Scope::Default)
- SF |= JITSymbolFlags::Exported;
- NewSymbolsToClaim[Name] = SF;
+ NewSymbolsToClaim[Name] =
+ getJITSymbolFlagsForSymbol(*Sym) | JITSymbolFlags::Weak;
NameToSym.push_back(std::make_pair(std::move(Name), Sym));
}
}
diff --git a/llvm/lib/ExecutionEngine/Orc/OrcABISupport.cpp b/llvm/lib/ExecutionEngine/Orc/OrcABISupport.cpp
index 48dd0df80415..6d568199378a 100644
--- a/llvm/lib/ExecutionEngine/Orc/OrcABISupport.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/OrcABISupport.cpp
@@ -14,17 +14,17 @@
#define DEBUG_TYPE "orc"
using namespace llvm;
+using namespace llvm::orc;
template <typename ORCABI>
-bool stubAndPointerRangesOk(JITTargetAddress StubBlockAddr,
- JITTargetAddress PointerBlockAddr,
- unsigned NumStubs) {
+static bool stubAndPointerRangesOk(ExecutorAddr StubBlockAddr,
+ ExecutorAddr PointerBlockAddr,
+ unsigned NumStubs) {
constexpr unsigned MaxDisp = ORCABI::StubToPointerMaxDisplacement;
- JITTargetAddress FirstStub = StubBlockAddr;
- JITTargetAddress LastStub = FirstStub + ((NumStubs - 1) * ORCABI::StubSize);
- JITTargetAddress FirstPointer = PointerBlockAddr;
- JITTargetAddress LastPointer =
- FirstPointer + ((NumStubs - 1) * ORCABI::StubSize);
+ ExecutorAddr FirstStub = StubBlockAddr;
+ ExecutorAddr LastStub = FirstStub + ((NumStubs - 1) * ORCABI::StubSize);
+ ExecutorAddr FirstPointer = PointerBlockAddr;
+ ExecutorAddr LastPointer = FirstPointer + ((NumStubs - 1) * ORCABI::StubSize);
if (FirstStub < FirstPointer) {
if (LastStub >= FirstPointer)
@@ -44,9 +44,9 @@ namespace llvm {
namespace orc {
void OrcAArch64::writeResolverCode(char *ResolverWorkingMem,
- JITTargetAddress ResolverTargetAddress,
- JITTargetAddress ReentryFnAddr,
- JITTargetAddress ReentryCtxAddr) {
+ ExecutorAddr ResolverTargetAddress,
+ ExecutorAddr ReentryFnAddr,
+ ExecutorAddr ReentryCtxAddr) {
const uint32_t ResolverCode[] = {
// resolver_entry:
@@ -135,8 +135,8 @@ void OrcAArch64::writeResolverCode(char *ResolverWorkingMem,
}
void OrcAArch64::writeTrampolines(char *TrampolineBlockWorkingMem,
- JITTargetAddress TrampolineBlockTargetAddress,
- JITTargetAddress ResolverAddr,
+ ExecutorAddr TrampolineBlockTargetAddress,
+ ExecutorAddr ResolverAddr,
unsigned NumTrampolines) {
unsigned OffsetToPtr = alignTo(NumTrampolines * TrampolineSize, 8);
@@ -159,17 +159,17 @@ void OrcAArch64::writeTrampolines(char *TrampolineBlockWorkingMem,
}
void OrcAArch64::writeIndirectStubsBlock(
- char *StubsBlockWorkingMem, JITTargetAddress StubsBlockTargetAddress,
- JITTargetAddress PointersBlockTargetAddress, unsigned NumStubs) {
+ char *StubsBlockWorkingMem, ExecutorAddr StubsBlockTargetAddress,
+ ExecutorAddr PointersBlockTargetAddress, unsigned NumStubs) {
// Stub format is:
//
// .section __orc_stubs
// stub1:
- // ldr x0, ptr1 ; PC-rel load of ptr1
- // br x0 ; Jump to resolver
+ // ldr x16, ptr1 ; PC-rel load of ptr1
+ // br x16 ; Jump to resolver
// stub2:
- // ldr x0, ptr2 ; PC-rel load of ptr2
- // br x0 ; Jump to resolver
+ // ldr x16, ptr2 ; PC-rel load of ptr2
+ // br x16 ; Jump to resolver
//
// ...
//
@@ -188,17 +188,19 @@ void OrcAArch64::writeIndirectStubsBlock(
"PointersBlock is out of range");
uint64_t PtrDisplacement =
PointersBlockTargetAddress - StubsBlockTargetAddress;
+ assert((PtrDisplacement % 8 == 0) &&
+ "Displacement to pointer is not a multiple of 8");
uint64_t *Stub = reinterpret_cast<uint64_t *>(StubsBlockWorkingMem);
- uint64_t PtrOffsetField = PtrDisplacement << 3;
+ uint64_t PtrOffsetField = ((PtrDisplacement >> 2) & 0x7ffff) << 5;
for (unsigned I = 0; I < NumStubs; ++I)
Stub[I] = 0xd61f020058000010 | PtrOffsetField;
}
-void OrcX86_64_Base::writeTrampolines(
- char *TrampolineBlockWorkingMem,
- JITTargetAddress TrampolineBlockTargetAddress,
- JITTargetAddress ResolverAddr, unsigned NumTrampolines) {
+void OrcX86_64_Base::writeTrampolines(char *TrampolineBlockWorkingMem,
+ ExecutorAddr TrampolineBlockTargetAddress,
+ ExecutorAddr ResolverAddr,
+ unsigned NumTrampolines) {
unsigned OffsetToPtr = NumTrampolines * TrampolineSize;
@@ -214,8 +216,8 @@ void OrcX86_64_Base::writeTrampolines(
}
void OrcX86_64_Base::writeIndirectStubsBlock(
- char *StubsBlockWorkingMem, JITTargetAddress StubsBlockTargetAddress,
- JITTargetAddress PointersBlockTargetAddress, unsigned NumStubs) {
+ char *StubsBlockWorkingMem, ExecutorAddr StubsBlockTargetAddress,
+ ExecutorAddr PointersBlockTargetAddress, unsigned NumStubs) {
// Stub format is:
//
// .section __orc_stubs
@@ -250,9 +252,9 @@ void OrcX86_64_Base::writeIndirectStubsBlock(
}
void OrcX86_64_SysV::writeResolverCode(char *ResolverWorkingMem,
- JITTargetAddress ResolverTargetAddress,
- JITTargetAddress ReentryFnAddr,
- JITTargetAddress ReentryCtxAddr) {
+ ExecutorAddr ResolverTargetAddress,
+ ExecutorAddr ReentryFnAddr,
+ ExecutorAddr ReentryCtxAddr) {
LLVM_DEBUG({
dbgs() << "Writing resolver code to "
@@ -324,9 +326,9 @@ void OrcX86_64_SysV::writeResolverCode(char *ResolverWorkingMem,
}
void OrcX86_64_Win32::writeResolverCode(char *ResolverWorkingMem,
- JITTargetAddress ResolverTargetAddress,
- JITTargetAddress ReentryFnAddr,
- JITTargetAddress ReentryCtxAddr) {
+ ExecutorAddr ResolverTargetAddress,
+ ExecutorAddr ReentryFnAddr,
+ ExecutorAddr ReentryCtxAddr) {
// resolverCode is similar to OrcX86_64 with differences specific to windows
// x64 calling convention: arguments go into rcx, rdx and come in reverse
@@ -402,12 +404,13 @@ void OrcX86_64_Win32::writeResolverCode(char *ResolverWorkingMem,
}
void OrcI386::writeResolverCode(char *ResolverWorkingMem,
- JITTargetAddress ResolverTargetAddress,
- JITTargetAddress ReentryFnAddr,
- JITTargetAddress ReentryCtxAddr) {
+ ExecutorAddr ResolverTargetAddress,
+ ExecutorAddr ReentryFnAddr,
+ ExecutorAddr ReentryCtxAddr) {
- assert((ReentryFnAddr >> 32) == 0 && "ReentryFnAddr out of range");
- assert((ReentryCtxAddr >> 32) == 0 && "ReentryCtxAddr out of range");
+ assert((ReentryFnAddr.getValue() >> 32) == 0 && "ReentryFnAddr out of range");
+ assert((ReentryCtxAddr.getValue() >> 32) == 0 &&
+ "ReentryCtxAddr out of range");
const uint8_t ResolverCode[] = {
// resolver_entry:
@@ -455,10 +458,10 @@ void OrcI386::writeResolverCode(char *ResolverWorkingMem,
}
void OrcI386::writeTrampolines(char *TrampolineWorkingMem,
- JITTargetAddress TrampolineBlockTargetAddress,
- JITTargetAddress ResolverAddr,
+ ExecutorAddr TrampolineBlockTargetAddress,
+ ExecutorAddr ResolverAddr,
unsigned NumTrampolines) {
- assert((ResolverAddr >> 32) == 0 && "ResolverAddr out of range");
+ assert((ResolverAddr.getValue() >> 32) == 0 && "ResolverAddr out of range");
uint64_t CallRelImm = 0xF1C4C400000000e8;
uint64_t ResolverRel = ResolverAddr - TrampolineBlockTargetAddress - 5;
@@ -468,12 +471,13 @@ void OrcI386::writeTrampolines(char *TrampolineWorkingMem,
Trampolines[I] = CallRelImm | (ResolverRel << 8);
}
-void OrcI386::writeIndirectStubsBlock(
- char *StubsBlockWorkingMem, JITTargetAddress StubsBlockTargetAddress,
- JITTargetAddress PointersBlockTargetAddress, unsigned NumStubs) {
- assert((StubsBlockTargetAddress >> 32) == 0 &&
+void OrcI386::writeIndirectStubsBlock(char *StubsBlockWorkingMem,
+ ExecutorAddr StubsBlockTargetAddress,
+ ExecutorAddr PointersBlockTargetAddress,
+ unsigned NumStubs) {
+ assert((StubsBlockTargetAddress.getValue() >> 32) == 0 &&
"StubsBlockTargetAddress is out of range");
- assert((PointersBlockTargetAddress >> 32) == 0 &&
+ assert((PointersBlockTargetAddress.getValue() >> 32) == 0 &&
"PointersBlockTargetAddress is out of range");
// Stub format is:
@@ -501,15 +505,15 @@ void OrcI386::writeIndirectStubsBlock(
"PointersBlock is out of range");
uint64_t *Stub = reinterpret_cast<uint64_t *>(StubsBlockWorkingMem);
- uint64_t PtrAddr = PointersBlockTargetAddress;
+ uint64_t PtrAddr = PointersBlockTargetAddress.getValue();
for (unsigned I = 0; I < NumStubs; ++I, PtrAddr += 4)
Stub[I] = 0xF1C40000000025ff | (PtrAddr << 16);
}
void OrcMips32_Base::writeResolverCode(char *ResolverWorkingMem,
- JITTargetAddress ResolverTargetAddress,
- JITTargetAddress ReentryFnAddr,
- JITTargetAddress ReentryCtxAddr,
+ ExecutorAddr ResolverTargetAddress,
+ ExecutorAddr ReentryFnAddr,
+ ExecutorAddr ReentryCtxAddr,
bool isBigEndian) {
const uint32_t ResolverCode[] = {
@@ -596,32 +600,32 @@ void OrcMips32_Base::writeResolverCode(char *ResolverWorkingMem,
memcpy(ResolverWorkingMem + Offsett, &MoveVxT9, sizeof(MoveVxT9));
uint32_t ReentryCtxLUi =
- 0x3c040000 | (((ReentryCtxAddr + 0x8000) >> 16) & 0xFFFF);
- uint32_t ReentryCtxADDiu = 0x24840000 | ((ReentryCtxAddr)&0xFFFF);
+ 0x3c040000 | (((ReentryCtxAddr.getValue() + 0x8000) >> 16) & 0xFFFF);
+ uint32_t ReentryCtxADDiu = 0x24840000 | (ReentryCtxAddr.getValue() & 0xFFFF);
memcpy(ResolverWorkingMem + ReentryCtxAddrOffset, &ReentryCtxLUi,
sizeof(ReentryCtxLUi));
memcpy(ResolverWorkingMem + ReentryCtxAddrOffset + 4, &ReentryCtxADDiu,
sizeof(ReentryCtxADDiu));
uint32_t ReentryFnLUi =
- 0x3c190000 | (((ReentryFnAddr + 0x8000) >> 16) & 0xFFFF);
- uint32_t ReentryFnADDiu = 0x27390000 | ((ReentryFnAddr)&0xFFFF);
+ 0x3c190000 | (((ReentryFnAddr.getValue() + 0x8000) >> 16) & 0xFFFF);
+ uint32_t ReentryFnADDiu = 0x27390000 | (ReentryFnAddr.getValue() & 0xFFFF);
memcpy(ResolverWorkingMem + ReentryFnAddrOffset, &ReentryFnLUi,
sizeof(ReentryFnLUi));
memcpy(ResolverWorkingMem + ReentryFnAddrOffset + 4, &ReentryFnADDiu,
sizeof(ReentryFnADDiu));
}
-void OrcMips32_Base::writeTrampolines(
- char *TrampolineBlockWorkingMem,
- JITTargetAddress TrampolineBlockTargetAddress,
- JITTargetAddress ResolverAddr, unsigned NumTrampolines) {
+void OrcMips32_Base::writeTrampolines(char *TrampolineBlockWorkingMem,
+ ExecutorAddr TrampolineBlockTargetAddress,
+ ExecutorAddr ResolverAddr,
+ unsigned NumTrampolines) {
- assert((ResolverAddr >> 32) == 0 && "ResolverAddr out of range");
+ assert((ResolverAddr.getValue() >> 32) == 0 && "ResolverAddr out of range");
uint32_t *Trampolines =
reinterpret_cast<uint32_t *>(TrampolineBlockWorkingMem);
- uint32_t RHiAddr = ((ResolverAddr + 0x8000) >> 16);
+ uint32_t RHiAddr = ((ResolverAddr.getValue() + 0x8000) >> 16);
for (unsigned I = 0; I < NumTrampolines; ++I) {
// move $t8,$ra
@@ -631,16 +635,16 @@ void OrcMips32_Base::writeTrampolines(
// nop
Trampolines[5 * I + 0] = 0x03e0c025;
Trampolines[5 * I + 1] = 0x3c190000 | (RHiAddr & 0xFFFF);
- Trampolines[5 * I + 2] = 0x27390000 | (ResolverAddr & 0xFFFF);
+ Trampolines[5 * I + 2] = 0x27390000 | (ResolverAddr.getValue() & 0xFFFF);
Trampolines[5 * I + 3] = 0x0320f809;
Trampolines[5 * I + 4] = 0x00000000;
}
}
void OrcMips32_Base::writeIndirectStubsBlock(
- char *StubsBlockWorkingMem, JITTargetAddress StubsBlockTargetAddress,
- JITTargetAddress PointersBlockTargetAddress, unsigned NumStubs) {
- assert((StubsBlockTargetAddress >> 32) == 0 &&
+ char *StubsBlockWorkingMem, ExecutorAddr StubsBlockTargetAddress,
+ ExecutorAddr PointersBlockTargetAddress, unsigned NumStubs) {
+ assert((StubsBlockTargetAddress.getValue() >> 32) == 0 &&
"InitialPtrVal is out of range");
// Stub format is:
@@ -671,7 +675,7 @@ void OrcMips32_Base::writeIndirectStubsBlock(
// Populate the stubs page stubs and mark it executable.
uint32_t *Stub = reinterpret_cast<uint32_t *>(StubsBlockWorkingMem);
- uint64_t PtrAddr = PointersBlockTargetAddress;
+ uint64_t PtrAddr = PointersBlockTargetAddress.getValue();
for (unsigned I = 0; I < NumStubs; ++I) {
uint32_t HiAddr = ((PtrAddr + 0x8000) >> 16);
@@ -684,9 +688,9 @@ void OrcMips32_Base::writeIndirectStubsBlock(
}
void OrcMips64::writeResolverCode(char *ResolverWorkingMem,
- JITTargetAddress ResolverTargetAddress,
- JITTargetAddress ReentryFnAddr,
- JITTargetAddress ReentryCtxAddr) {
+ ExecutorAddr ResolverTargetAddress,
+ ExecutorAddr ReentryFnAddr,
+ ExecutorAddr ReentryCtxAddr) {
const uint32_t ResolverCode[] = {
//resolver_entry:
@@ -775,14 +779,16 @@ void OrcMips64::writeResolverCode(char *ResolverWorkingMem,
memcpy(ResolverWorkingMem, ResolverCode, sizeof(ResolverCode));
uint32_t ReentryCtxLUi =
- 0x3c040000 | (((ReentryCtxAddr + 0x800080008000) >> 48) & 0xFFFF);
+ 0x3c040000 |
+ (((ReentryCtxAddr.getValue() + 0x800080008000) >> 48) & 0xFFFF);
uint32_t ReentryCtxDADDiu =
- 0x64840000 | (((ReentryCtxAddr + 0x80008000) >> 32) & 0xFFFF);
+ 0x64840000 | (((ReentryCtxAddr.getValue() + 0x80008000) >> 32) & 0xFFFF);
uint32_t ReentryCtxDSLL = 0x00042438;
uint32_t ReentryCtxDADDiu2 =
- 0x64840000 | ((((ReentryCtxAddr + 0x8000) >> 16) & 0xFFFF));
+ 0x64840000 | ((((ReentryCtxAddr.getValue() + 0x8000) >> 16) & 0xFFFF));
uint32_t ReentryCtxDSLL2 = 0x00042438;
- uint32_t ReentryCtxDADDiu3 = 0x64840000 | ((ReentryCtxAddr)&0xFFFF);
+ uint32_t ReentryCtxDADDiu3 =
+ 0x64840000 | (ReentryCtxAddr.getValue() & 0xFFFF);
memcpy(ResolverWorkingMem + ReentryCtxAddrOffset, &ReentryCtxLUi,
sizeof(ReentryCtxLUi));
@@ -798,19 +804,20 @@ void OrcMips64::writeResolverCode(char *ResolverWorkingMem,
sizeof(ReentryCtxDADDiu3));
uint32_t ReentryFnLUi =
- 0x3c190000 | (((ReentryFnAddr + 0x800080008000) >> 48) & 0xFFFF);
+ 0x3c190000 |
+ (((ReentryFnAddr.getValue() + 0x800080008000) >> 48) & 0xFFFF);
uint32_t ReentryFnDADDiu =
- 0x67390000 | (((ReentryFnAddr + 0x80008000) >> 32) & 0xFFFF);
+ 0x67390000 | (((ReentryFnAddr.getValue() + 0x80008000) >> 32) & 0xFFFF);
uint32_t ReentryFnDSLL = 0x0019cc38;
uint32_t ReentryFnDADDiu2 =
- 0x67390000 | (((ReentryFnAddr + 0x8000) >> 16) & 0xFFFF);
+ 0x67390000 | (((ReentryFnAddr.getValue() + 0x8000) >> 16) & 0xFFFF);
uint32_t ReentryFnDSLL2 = 0x0019cc38;
- uint32_t ReentryFnDADDiu3 = 0x67390000 | ((ReentryFnAddr)&0xFFFF);
+ uint32_t ReentryFnDADDiu3 = 0x67390000 | (ReentryFnAddr.getValue() & 0xFFFF);
memcpy(ResolverWorkingMem + ReentryFnAddrOffset, &ReentryFnLUi,
sizeof(ReentryFnLUi));
@@ -827,16 +834,16 @@ void OrcMips64::writeResolverCode(char *ResolverWorkingMem,
}
void OrcMips64::writeTrampolines(char *TrampolineBlockWorkingMem,
- JITTargetAddress TrampolineBlockTargetAddress,
- JITTargetAddress ResolverAddr,
+ ExecutorAddr TrampolineBlockTargetAddress,
+ ExecutorAddr ResolverAddr,
unsigned NumTrampolines) {
uint32_t *Trampolines =
reinterpret_cast<uint32_t *>(TrampolineBlockWorkingMem);
- uint64_t HeighestAddr = ((ResolverAddr + 0x800080008000) >> 48);
- uint64_t HeigherAddr = ((ResolverAddr + 0x80008000) >> 32);
- uint64_t HiAddr = ((ResolverAddr + 0x8000) >> 16);
+ uint64_t HeighestAddr = ((ResolverAddr.getValue() + 0x800080008000) >> 48);
+ uint64_t HeigherAddr = ((ResolverAddr.getValue() + 0x80008000) >> 32);
+ uint64_t HiAddr = ((ResolverAddr.getValue() + 0x8000) >> 16);
for (unsigned I = 0; I < NumTrampolines; ++I) {
Trampolines[10 * I + 0] = 0x03e0c025; // move $t8,$ra
@@ -845,17 +852,18 @@ void OrcMips64::writeTrampolines(char *TrampolineBlockWorkingMem,
Trampolines[10 * I + 3] = 0x0019cc38; // dsll $t9,$t9,16
Trampolines[10 * I + 4] = 0x67390000 | (HiAddr & 0xFFFF); // daddiu $t9,$t9,%hi(ptr)
Trampolines[10 * I + 5] = 0x0019cc38; // dsll $t9,$t9,16
- Trampolines[10 * I + 6] =
- 0x67390000 | (ResolverAddr & 0xFFFF); // daddiu $t9,$t9,%lo(ptr)
+ Trampolines[10 * I + 6] = 0x67390000 | (ResolverAddr.getValue() &
+ 0xFFFF); // daddiu $t9,$t9,%lo(ptr)
Trampolines[10 * I + 7] = 0x0320f809; // jalr $t9
Trampolines[10 * I + 8] = 0x00000000; // nop
Trampolines[10 * I + 9] = 0x00000000; // nop
}
}
-void OrcMips64::writeIndirectStubsBlock(
- char *StubsBlockWorkingMem, JITTargetAddress StubsBlockTargetAddress,
- JITTargetAddress PointersBlockTargetAddress, unsigned NumStubs) {
+void OrcMips64::writeIndirectStubsBlock(char *StubsBlockWorkingMem,
+ ExecutorAddr StubsBlockTargetAddress,
+ ExecutorAddr PointersBlockTargetAddress,
+ unsigned NumStubs) {
// Stub format is:
//
// .section __orc_stubs
@@ -890,7 +898,7 @@ void OrcMips64::writeIndirectStubsBlock(
// Populate the stubs page stubs and mark it executable.
uint32_t *Stub = reinterpret_cast<uint32_t *>(StubsBlockWorkingMem);
- uint64_t PtrAddr = PointersBlockTargetAddress;
+ uint64_t PtrAddr = PointersBlockTargetAddress.getValue();
for (unsigned I = 0; I < NumStubs; ++I, PtrAddr += 8) {
uint64_t HeighestAddr = ((PtrAddr + 0x800080008000) >> 48);
@@ -908,9 +916,9 @@ void OrcMips64::writeIndirectStubsBlock(
}
void OrcRiscv64::writeResolverCode(char *ResolverWorkingMem,
- JITTargetAddress ResolverTargetAddress,
- JITTargetAddress ReentryFnAddr,
- JITTargetAddress ReentryCtxAddr) {
+ ExecutorAddr ResolverTargetAddress,
+ ExecutorAddr ReentryFnAddr,
+ ExecutorAddr ReentryCtxAddr) {
const uint32_t ResolverCode[] = {
0xef810113, // 0x00: addi sp,sp,-264
@@ -1008,8 +1016,8 @@ void OrcRiscv64::writeResolverCode(char *ResolverWorkingMem,
}
void OrcRiscv64::writeTrampolines(char *TrampolineBlockWorkingMem,
- JITTargetAddress TrampolineBlockTargetAddress,
- JITTargetAddress ResolverAddr,
+ ExecutorAddr TrampolineBlockTargetAddress,
+ ExecutorAddr ResolverAddr,
unsigned NumTrampolines) {
unsigned OffsetToPtr = alignTo(NumTrampolines * TrampolineSize, 8);
@@ -1031,8 +1039,8 @@ void OrcRiscv64::writeTrampolines(char *TrampolineBlockWorkingMem,
}
void OrcRiscv64::writeIndirectStubsBlock(
- char *StubsBlockWorkingMem, JITTargetAddress StubsBlockTargetAddress,
- JITTargetAddress PointersBlockTargetAddress, unsigned NumStubs) {
+ char *StubsBlockWorkingMem, ExecutorAddr StubsBlockTargetAddress,
+ ExecutorAddr PointersBlockTargetAddress, unsigned NumStubs) {
// Stub format is:
//
// .section __orc_stubs
@@ -1078,9 +1086,9 @@ void OrcRiscv64::writeIndirectStubsBlock(
}
void OrcLoongArch64::writeResolverCode(char *ResolverWorkingMem,
- JITTargetAddress ResolverTargetAddress,
- JITTargetAddress ReentryFnAddr,
- JITTargetAddress ReentryCtxAddr) {
+ ExecutorAddr ResolverTargetAddress,
+ ExecutorAddr ReentryFnAddr,
+ ExecutorAddr ReentryCtxAddr) {
LLVM_DEBUG({
dbgs() << "Writing resolver code to "
@@ -1150,10 +1158,10 @@ void OrcLoongArch64::writeResolverCode(char *ResolverWorkingMem,
sizeof(uint64_t));
}
-void OrcLoongArch64::writeTrampolines(
- char *TrampolineBlockWorkingMem,
- JITTargetAddress TrampolineBlockTargetAddress,
- JITTargetAddress ResolverAddr, unsigned NumTrampolines) {
+void OrcLoongArch64::writeTrampolines(char *TrampolineBlockWorkingMem,
+ ExecutorAddr TrampolineBlockTargetAddress,
+ ExecutorAddr ResolverAddr,
+ unsigned NumTrampolines) {
LLVM_DEBUG({
dbgs() << "Writing trampoline code to "
@@ -1181,8 +1189,8 @@ void OrcLoongArch64::writeTrampolines(
}
void OrcLoongArch64::writeIndirectStubsBlock(
- char *StubsBlockWorkingMem, JITTargetAddress StubsBlockTargetAddress,
- JITTargetAddress PointersBlockTargetAddress, unsigned NumStubs) {
+ char *StubsBlockWorkingMem, ExecutorAddr StubsBlockTargetAddress,
+ ExecutorAddr PointersBlockTargetAddress, unsigned NumStubs) {
// Stub format is:
//
// .section __orc_stubs
diff --git a/llvm/lib/ExecutionEngine/Orc/OrcV2CBindings.cpp b/llvm/lib/ExecutionEngine/Orc/OrcV2CBindings.cpp
index b823197b404f..a73aec6d98c6 100644
--- a/llvm/lib/ExecutionEngine/Orc/OrcV2CBindings.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/OrcV2CBindings.cpp
@@ -184,8 +184,8 @@ static SymbolMap toSymbolMap(LLVMOrcCSymbolMapPairs Syms, size_t NumPairs) {
SymbolMap SM;
for (size_t I = 0; I != NumPairs; ++I) {
JITSymbolFlags Flags = toJITSymbolFlags(Syms[I].Sym.Flags);
- SM[OrcV2CAPIHelper::moveToSymbolStringPtr(unwrap(Syms[I].Name))] =
- JITEvaluatedSymbol(Syms[I].Sym.Address, Flags);
+ SM[OrcV2CAPIHelper::moveToSymbolStringPtr(unwrap(Syms[I].Name))] = {
+ ExecutorAddr(Syms[I].Sym.Address), Flags};
}
return SM;
}
@@ -269,8 +269,8 @@ static LLVMOrcSymbolLookupFlags fromSymbolLookupFlags(SymbolLookupFlags SLF) {
}
static LLVMJITEvaluatedSymbol
-fromJITEvaluatedSymbol(const JITEvaluatedSymbol &S) {
- return {S.getAddress(), fromJITSymbolFlags(S.getFlags())};
+fromExecutorSymbolDef(const ExecutorSymbolDef &S) {
+ return {S.getAddress().getValue(), fromJITSymbolFlags(S.getFlags())};
}
} // end anonymous namespace
@@ -385,7 +385,7 @@ void LLVMOrcExecutionSessionLookup(
for (auto &KV : *Result)
CResult.push_back(LLVMOrcCSymbolMapPair{
wrap(OrcV2CAPIHelper::getRawPoolEntryPtr(KV.first)),
- fromJITEvaluatedSymbol(KV.second)});
+ fromExecutorSymbolDef(KV.second)});
HandleResult(LLVMErrorSuccess, CResult.data(), CResult.size(), Ctx);
} else
HandleResult(wrap(Result.takeError()), nullptr, 0, Ctx);
@@ -741,31 +741,19 @@ LLVMErrorRef LLVMOrcCreateDynamicLibrarySearchGeneratorForPath(
LLVMErrorRef LLVMOrcCreateStaticLibrarySearchGeneratorForPath(
LLVMOrcDefinitionGeneratorRef *Result, LLVMOrcObjectLayerRef ObjLayer,
- const char *FileName, const char *TargetTriple) {
+ const char *FileName) {
assert(Result && "Result can not be null");
assert(FileName && "Filename can not be null");
assert(ObjLayer && "ObjectLayer can not be null");
- if (TargetTriple) {
- auto TT = Triple(TargetTriple);
- auto LibrarySymsGenerator =
- StaticLibraryDefinitionGenerator::Load(*unwrap(ObjLayer), FileName, TT);
- if (!LibrarySymsGenerator) {
- *Result = nullptr;
- return wrap(LibrarySymsGenerator.takeError());
- }
- *Result = wrap(LibrarySymsGenerator->release());
- return LLVMErrorSuccess;
- } else {
- auto LibrarySymsGenerator =
- StaticLibraryDefinitionGenerator::Load(*unwrap(ObjLayer), FileName);
- if (!LibrarySymsGenerator) {
- *Result = nullptr;
- return wrap(LibrarySymsGenerator.takeError());
- }
- *Result = wrap(LibrarySymsGenerator->release());
- return LLVMErrorSuccess;
+ auto LibrarySymsGenerator =
+ StaticLibraryDefinitionGenerator::Load(*unwrap(ObjLayer), FileName);
+ if (!LibrarySymsGenerator) {
+ *Result = nullptr;
+ return wrap(LibrarySymsGenerator.takeError());
}
+ *Result = wrap(LibrarySymsGenerator->release());
+ return LLVMErrorSuccess;
}
LLVMOrcThreadSafeContextRef LLVMOrcCreateNewThreadSafeContext(void) {
@@ -859,9 +847,9 @@ LLVMErrorRef LLVMOrcObjectLayerAddObjectFile(LLVMOrcObjectLayerRef ObjLayer,
*unwrap(JD), std::unique_ptr<MemoryBuffer>(unwrap(ObjBuffer))));
}
-LLVMErrorRef LLVMOrcLLJITAddObjectFileWithRT(LLVMOrcObjectLayerRef ObjLayer,
- LLVMOrcResourceTrackerRef RT,
- LLVMMemoryBufferRef ObjBuffer) {
+LLVMErrorRef LLVMOrcObjectLayerAddObjectFileWithRT(LLVMOrcObjectLayerRef ObjLayer,
+ LLVMOrcResourceTrackerRef RT,
+ LLVMMemoryBufferRef ObjBuffer) {
return wrap(
unwrap(ObjLayer)->add(ResourceTrackerSP(unwrap(RT)),
std::unique_ptr<MemoryBuffer>(unwrap(ObjBuffer))));
@@ -1210,8 +1198,8 @@ LLVMErrorRef LLVMOrcCreateLocalLazyCallThroughManager(
const char *TargetTriple, LLVMOrcExecutionSessionRef ES,
LLVMOrcJITTargetAddress ErrorHandlerAddr,
LLVMOrcLazyCallThroughManagerRef *Result) {
- auto LCTM = createLocalLazyCallThroughManager(Triple(TargetTriple),
- *unwrap(ES), ErrorHandlerAddr);
+ auto LCTM = createLocalLazyCallThroughManager(
+ Triple(TargetTriple), *unwrap(ES), ExecutorAddr(ErrorHandlerAddr));
if (!LCTM)
return wrap(LCTM.takeError());
diff --git a/llvm/lib/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.cpp b/llvm/lib/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.cpp
index 07b19b2e54f1..9ef333222028 100644
--- a/llvm/lib/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.cpp
@@ -38,7 +38,8 @@ public:
LookupResult Result;
for (auto &KV : *InternedResult)
- Result[*KV.first] = std::move(KV.second);
+ Result[*KV.first] = {KV.second.getAddress().getValue(),
+ KV.second.getFlags()};
OnResolved(Result);
};
@@ -326,7 +327,7 @@ Error RTDyldObjectLinkingLayer::onObjLoad(
} else if (AutoClaimObjectSymbols)
ExtraSymbolsToClaim[InternedName] = Flags;
- Symbols[InternedName] = JITEvaluatedSymbol(KV.second.getAddress(), Flags);
+ Symbols[InternedName] = {ExecutorAddr(KV.second.getAddress()), Flags};
}
if (!ExtraSymbolsToClaim.empty()) {
diff --git a/llvm/lib/ExecutionEngine/Orc/Shared/ObjectFormats.cpp b/llvm/lib/ExecutionEngine/Orc/Shared/ObjectFormats.cpp
new file mode 100644
index 000000000000..ecf5e2915773
--- /dev/null
+++ b/llvm/lib/ExecutionEngine/Orc/Shared/ObjectFormats.cpp
@@ -0,0 +1,94 @@
+//===---------- ObjectFormats.cpp - Object format details for ORC ---------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+// ORC-specific object format details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ExecutionEngine/Orc/Shared/ObjectFormats.h"
+
+namespace llvm {
+namespace orc {
+
+StringRef MachODataCommonSectionName = "__DATA,__common";
+StringRef MachODataDataSectionName = "__DATA,__data";
+StringRef MachOEHFrameSectionName = "__TEXT,__eh_frame";
+StringRef MachOCompactUnwindInfoSectionName = "__TEXT,__unwind_info";
+StringRef MachOModInitFuncSectionName = "__DATA,__mod_init_func";
+StringRef MachOObjCCatListSectionName = "__DATA,__objc_catlist";
+StringRef MachOObjCCatList2SectionName = "__DATA,__objc_catlist2";
+StringRef MachOObjCClassListSectionName = "__DATA,__objc_classlist";
+StringRef MachOObjCClassNameSectionName = "__TEXT,__objc_classname";
+StringRef MachOObjCClassRefsSectionName = "__DATA,__objc_classrefs";
+StringRef MachOObjCConstSectionName = "__DATA,__objc_const";
+StringRef MachOObjCDataSectionName = "__DATA,__objc_data";
+StringRef MachOObjCImageInfoSectionName = "__DATA,__objc_imageinfo";
+StringRef MachOObjCMethNameSectionName = "__TEXT,__objc_methname";
+StringRef MachOObjCMethTypeSectionName = "__TEXT,__objc_methtype";
+StringRef MachOObjCNLCatListSectionName = "__DATA,__objc_nlcatlist";
+StringRef MachOObjCSelRefsSectionName = "__DATA,__objc_selrefs";
+StringRef MachOSwift5ProtoSectionName = "__TEXT,__swift5_proto";
+StringRef MachOSwift5ProtosSectionName = "__TEXT,__swift5_protos";
+StringRef MachOSwift5TypesSectionName = "__TEXT,__swift5_types";
+StringRef MachOSwift5TypeRefSectionName = "__TEXT,__swift5_typeref";
+StringRef MachOSwift5FieldMetadataSectionName = "__TEXT,__swift5_fieldmd";
+StringRef MachOSwift5EntrySectionName = "__TEXT,__swift5_entry";
+StringRef MachOThreadBSSSectionName = "__DATA,__thread_bss";
+StringRef MachOThreadDataSectionName = "__DATA,__thread_data";
+StringRef MachOThreadVarsSectionName = "__DATA,__thread_vars";
+
+StringRef MachOInitSectionNames[19] = {
+ MachOModInitFuncSectionName, MachOObjCCatListSectionName,
+ MachOObjCCatList2SectionName, MachOObjCClassListSectionName,
+ MachOObjCClassNameSectionName, MachOObjCClassRefsSectionName,
+ MachOObjCConstSectionName, MachOObjCDataSectionName,
+ MachOObjCImageInfoSectionName, MachOObjCMethNameSectionName,
+ MachOObjCMethTypeSectionName, MachOObjCNLCatListSectionName,
+ MachOObjCSelRefsSectionName, MachOSwift5ProtoSectionName,
+ MachOSwift5ProtosSectionName, MachOSwift5TypesSectionName,
+ MachOSwift5TypeRefSectionName, MachOSwift5FieldMetadataSectionName,
+ MachOSwift5EntrySectionName,
+};
+
+StringRef ELFEHFrameSectionName = ".eh_frame";
+StringRef ELFInitArrayFuncSectionName = ".init_array";
+
+StringRef ELFThreadBSSSectionName = ".tbss";
+StringRef ELFThreadDataSectionName = ".tdata";
+
+bool isMachOInitializerSection(StringRef SegName, StringRef SecName) {
+ for (auto &InitSection : MachOInitSectionNames) {
+ // Loop below assumes all MachO init sectios have a length-6
+ // segment name.
+ assert(InitSection[6] == ',' && "Init section seg name has length != 6");
+ if (InitSection.starts_with(SegName) && InitSection.substr(7) == SecName)
+ return true;
+ }
+ return false;
+}
+
+bool isMachOInitializerSection(StringRef QualifiedName) {
+ for (auto &InitSection : MachOInitSectionNames)
+ if (InitSection == QualifiedName)
+ return true;
+ return false;
+}
+
+bool isELFInitializerSection(StringRef SecName) {
+ if (SecName.consume_front(ELFInitArrayFuncSectionName) &&
+ (SecName.empty() || SecName[0] == '.'))
+ return true;
+ return false;
+}
+
+bool isCOFFInitializerSection(StringRef SecName) {
+ return SecName.startswith(".CRT");
+}
+
+} // namespace orc
+} // namespace llvm
diff --git a/llvm/lib/ExecutionEngine/Orc/SimpleRemoteEPC.cpp b/llvm/lib/ExecutionEngine/Orc/SimpleRemoteEPC.cpp
index 1bd10c9c6c0e..3d3ca891d881 100644
--- a/llvm/lib/ExecutionEngine/Orc/SimpleRemoteEPC.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/SimpleRemoteEPC.cpp
@@ -49,7 +49,7 @@ Expected<int32_t> SimpleRemoteEPC::runAsMain(ExecutorAddr MainFnAddr,
ArrayRef<std::string> Args) {
int64_t Result = 0;
if (auto Err = callSPSWrapper<rt::SPSRunAsMainSignature>(
- RunAsMainAddr, Result, ExecutorAddr(MainFnAddr), Args))
+ RunAsMainAddr, Result, MainFnAddr, Args))
return std::move(Err);
return Result;
}
@@ -57,7 +57,7 @@ Expected<int32_t> SimpleRemoteEPC::runAsMain(ExecutorAddr MainFnAddr,
Expected<int32_t> SimpleRemoteEPC::runAsVoidFunction(ExecutorAddr VoidFnAddr) {
int32_t Result = 0;
if (auto Err = callSPSWrapper<rt::SPSRunAsVoidFunctionSignature>(
- RunAsVoidFunctionAddr, Result, ExecutorAddr(VoidFnAddr)))
+ RunAsVoidFunctionAddr, Result, VoidFnAddr))
return std::move(Err);
return Result;
}
@@ -66,7 +66,7 @@ Expected<int32_t> SimpleRemoteEPC::runAsIntFunction(ExecutorAddr IntFnAddr,
int Arg) {
int32_t Result = 0;
if (auto Err = callSPSWrapper<rt::SPSRunAsIntFunctionSignature>(
- RunAsIntFunctionAddr, Result, ExecutorAddr(IntFnAddr), Arg))
+ RunAsIntFunctionAddr, Result, IntFnAddr, Arg))
return std::move(Err);
return Result;
}
@@ -126,23 +126,22 @@ SimpleRemoteEPC::handleMessage(SimpleRemoteEPCOpcode OpC, uint64_t SeqNo,
case SimpleRemoteEPCOpcode::Setup:
dbgs() << "Setup";
assert(SeqNo == 0 && "Non-zero SeqNo for Setup?");
- assert(TagAddr.getValue() == 0 && "Non-zero TagAddr for Setup?");
+ assert(!TagAddr && "Non-zero TagAddr for Setup?");
break;
case SimpleRemoteEPCOpcode::Hangup:
dbgs() << "Hangup";
assert(SeqNo == 0 && "Non-zero SeqNo for Hangup?");
- assert(TagAddr.getValue() == 0 && "Non-zero TagAddr for Hangup?");
+ assert(!TagAddr && "Non-zero TagAddr for Hangup?");
break;
case SimpleRemoteEPCOpcode::Result:
dbgs() << "Result";
- assert(TagAddr.getValue() == 0 && "Non-zero TagAddr for Result?");
+ assert(!TagAddr && "Non-zero TagAddr for Result?");
break;
case SimpleRemoteEPCOpcode::CallWrapper:
dbgs() << "CallWrapper";
break;
}
- dbgs() << ", seqno = " << SeqNo
- << ", tag-addr = " << formatv("{0:x}", TagAddr.getValue())
+ dbgs() << ", seqno = " << SeqNo << ", tag-addr = " << TagAddr
<< ", arg-buffer = " << formatv("{0:x}", ArgBytes.size())
<< " bytes\n";
});
@@ -227,11 +226,11 @@ Error SimpleRemoteEPC::sendMessage(SimpleRemoteEPCOpcode OpC, uint64_t SeqNo,
case SimpleRemoteEPCOpcode::Hangup:
dbgs() << "Hangup";
assert(SeqNo == 0 && "Non-zero SeqNo for Hangup?");
- assert(TagAddr.getValue() == 0 && "Non-zero TagAddr for Hangup?");
+ assert(!TagAddr && "Non-zero TagAddr for Hangup?");
break;
case SimpleRemoteEPCOpcode::Result:
dbgs() << "Result";
- assert(TagAddr.getValue() == 0 && "Non-zero TagAddr for Result?");
+ assert(!TagAddr && "Non-zero TagAddr for Result?");
break;
case SimpleRemoteEPCOpcode::CallWrapper:
dbgs() << "CallWrapper";
@@ -239,8 +238,7 @@ Error SimpleRemoteEPC::sendMessage(SimpleRemoteEPCOpcode OpC, uint64_t SeqNo,
default:
llvm_unreachable("Invalid opcode");
}
- dbgs() << ", seqno = " << SeqNo
- << ", tag-addr = " << formatv("{0:x}", TagAddr.getValue())
+ dbgs() << ", seqno = " << SeqNo << ", tag-addr = " << TagAddr
<< ", arg-buffer = " << formatv("{0:x}", ArgBytes.size())
<< " bytes\n";
});
@@ -317,13 +315,19 @@ Error SimpleRemoteEPC::setup(Setup S) {
dbgs() << "SimpleRemoteEPC received setup message:\n"
<< " Triple: " << EI->TargetTriple << "\n"
<< " Page size: " << EI->PageSize << "\n"
- << " Bootstrap symbols:\n";
+ << " Bootstrap map" << (EI->BootstrapMap.empty() ? " empty" : ":")
+ << "\n";
+ for (const auto &KV : EI->BootstrapMap)
+ dbgs() << " " << KV.first() << ": " << KV.second.size()
+ << "-byte SPS encoded buffer\n";
+ dbgs() << " Bootstrap symbols"
+ << (EI->BootstrapSymbols.empty() ? " empty" : ":") << "\n";
for (const auto &KV : EI->BootstrapSymbols)
- dbgs() << " " << KV.first() << ": "
- << formatv("{0:x16}", KV.second.getValue()) << "\n";
+ dbgs() << " " << KV.first() << ": " << KV.second << "\n";
});
TargetTriple = Triple(EI->TargetTriple);
PageSize = EI->PageSize;
+ BootstrapMap = std::move(EI->BootstrapMap);
BootstrapSymbols = std::move(EI->BootstrapSymbols);
if (auto Err = getBootstrapSymbols(
@@ -402,7 +406,7 @@ void SimpleRemoteEPC::handleCallWrapper(
ExecutorAddr(), {WFR.data(), WFR.size()}))
getExecutionSession().reportError(std::move(Err));
},
- TagAddr.getValue(), ArgBytes);
+ TagAddr, ArgBytes);
},
"callWrapper task"));
}
diff --git a/llvm/lib/ExecutionEngine/Orc/Speculation.cpp b/llvm/lib/ExecutionEngine/Orc/Speculation.cpp
index b52d01318c0d..d4cbd1970d8f 100644
--- a/llvm/lib/ExecutionEngine/Orc/Speculation.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/Speculation.cpp
@@ -36,16 +36,15 @@ void ImplSymbolMap::trackImpls(SymbolAliasMap ImplMaps, JITDylib *SrcJD) {
// Trigger Speculative Compiles.
void Speculator::speculateForEntryPoint(Speculator *Ptr, uint64_t StubId) {
assert(Ptr && " Null Address Received in orc_speculate_for ");
- Ptr->speculateFor(StubId);
+ Ptr->speculateFor(ExecutorAddr(StubId));
}
Error Speculator::addSpeculationRuntime(JITDylib &JD,
MangleAndInterner &Mangle) {
- JITEvaluatedSymbol ThisPtr(pointerToJITTargetAddress(this),
- JITSymbolFlags::Exported);
- JITEvaluatedSymbol SpeculateForEntryPtr(
- pointerToJITTargetAddress(&speculateForEntryPoint),
- JITSymbolFlags::Exported);
+ ExecutorSymbolDef ThisPtr(ExecutorAddr::fromPtr(this),
+ JITSymbolFlags::Exported);
+ ExecutorSymbolDef SpeculateForEntryPtr(
+ ExecutorAddr::fromPtr(&speculateForEntryPoint), JITSymbolFlags::Exported);
return JD.define(absoluteSymbols({
{Mangle("__orc_speculator"), ThisPtr}, // Data Symbol
{Mangle("__orc_speculate_for"), SpeculateForEntryPtr} // Callable Symbol
diff --git a/llvm/lib/ExecutionEngine/Orc/TargetProcess/ExecutorSharedMemoryMapperService.cpp b/llvm/lib/ExecutionEngine/Orc/TargetProcess/ExecutorSharedMemoryMapperService.cpp
index 147f915f61d6..3f70dbf60437 100644
--- a/llvm/lib/ExecutionEngine/Orc/TargetProcess/ExecutorSharedMemoryMapperService.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/TargetProcess/ExecutorSharedMemoryMapperService.cpp
@@ -132,11 +132,11 @@ Expected<ExecutorAddr> ExecutorSharedMemoryMapperService::initialize(
#if defined(LLVM_ON_UNIX)
int NativeProt = 0;
- if ((Segment.AG.getMemProt() & MemProt::Read) == MemProt::Read)
+ if ((Segment.RAG.Prot & MemProt::Read) == MemProt::Read)
NativeProt |= PROT_READ;
- if ((Segment.AG.getMemProt() & MemProt::Write) == MemProt::Write)
+ if ((Segment.RAG.Prot & MemProt::Write) == MemProt::Write)
NativeProt |= PROT_WRITE;
- if ((Segment.AG.getMemProt() & MemProt::Exec) == MemProt::Exec)
+ if ((Segment.RAG.Prot & MemProt::Exec) == MemProt::Exec)
NativeProt |= PROT_EXEC;
if (mprotect(Segment.Addr.toPtr<void *>(), Segment.Size, NativeProt))
@@ -144,8 +144,7 @@ Expected<ExecutorAddr> ExecutorSharedMemoryMapperService::initialize(
#elif defined(_WIN32)
- DWORD NativeProt =
- getWindowsProtectionFlags(Segment.AG.getMemProt());
+ DWORD NativeProt = getWindowsProtectionFlags(Segment.RAG.Prot);
if (!VirtualProtect(Segment.Addr.toPtr<void *>(), Segment.Size, NativeProt,
&NativeProt))
@@ -153,7 +152,7 @@ Expected<ExecutorAddr> ExecutorSharedMemoryMapperService::initialize(
#endif
- if ((Segment.AG.getMemProt() & MemProt::Exec) == MemProt::Exec)
+ if ((Segment.RAG.Prot & MemProt::Exec) == MemProt::Exec)
sys::Memory::InvalidateInstructionCache(Segment.Addr.toPtr<void *>(),
Segment.Size);
}
diff --git a/llvm/lib/ExecutionEngine/Orc/TargetProcess/JITLoaderGDB.cpp b/llvm/lib/ExecutionEngine/Orc/TargetProcess/JITLoaderGDB.cpp
index 8296b03398a0..8eca874c48b8 100644
--- a/llvm/lib/ExecutionEngine/Orc/TargetProcess/JITLoaderGDB.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/TargetProcess/JITLoaderGDB.cpp
@@ -67,9 +67,9 @@ using namespace llvm;
using namespace llvm::orc;
// Register debug object, return error message or null for success.
-static void registerJITLoaderGDBImpl(const char *ObjAddr, size_t Size) {
+static void appendJITDebugDescriptor(const char *ObjAddr, size_t Size) {
LLVM_DEBUG({
- dbgs() << "Registering debug object with GDB JIT interface "
+ dbgs() << "Adding debug object to GDB JIT interface "
<< formatv("([{0:x16} -- {1:x16}])",
reinterpret_cast<uintptr_t>(ObjAddr),
reinterpret_cast<uintptr_t>(ObjAddr + Size))
@@ -94,20 +94,20 @@ static void registerJITLoaderGDBImpl(const char *ObjAddr, size_t Size) {
__jit_debug_descriptor.first_entry = E;
__jit_debug_descriptor.relevant_entry = E;
-
- // Run into the rendezvous breakpoint.
__jit_debug_descriptor.action_flag = JIT_REGISTER_FN;
- __jit_debug_register_code();
}
extern "C" orc::shared::CWrapperFunctionResult
llvm_orc_registerJITLoaderGDBAllocAction(const char *Data, size_t Size) {
using namespace orc::shared;
- return WrapperFunction<SPSError(SPSExecutorAddrRange)>::handle(
+ return WrapperFunction<SPSError(SPSExecutorAddrRange, bool)>::handle(
Data, Size,
- [](ExecutorAddrRange R) {
- registerJITLoaderGDBImpl(R.Start.toPtr<const char *>(),
+ [](ExecutorAddrRange R, bool AutoRegisterCode) {
+ appendJITDebugDescriptor(R.Start.toPtr<const char *>(),
R.size());
+ // Run into the rendezvous breakpoint.
+ if (AutoRegisterCode)
+ __jit_debug_register_code();
return Error::success();
})
.release();
@@ -116,11 +116,14 @@ llvm_orc_registerJITLoaderGDBAllocAction(const char *Data, size_t Size) {
extern "C" orc::shared::CWrapperFunctionResult
llvm_orc_registerJITLoaderGDBWrapper(const char *Data, uint64_t Size) {
using namespace orc::shared;
- return WrapperFunction<SPSError(SPSExecutorAddrRange)>::handle(
+ return WrapperFunction<SPSError(SPSExecutorAddrRange, bool)>::handle(
Data, Size,
- [](ExecutorAddrRange R) {
- registerJITLoaderGDBImpl(R.Start.toPtr<const char *>(),
+ [](ExecutorAddrRange R, bool AutoRegisterCode) {
+ appendJITDebugDescriptor(R.Start.toPtr<const char *>(),
R.size());
+ // Run into the rendezvous breakpoint.
+ if (AutoRegisterCode)
+ __jit_debug_register_code();
return Error::success();
})
.release();
diff --git a/llvm/lib/ExecutionEngine/Orc/TargetProcess/SimpleExecutorMemoryManager.cpp b/llvm/lib/ExecutionEngine/Orc/TargetProcess/SimpleExecutorMemoryManager.cpp
index ce94bf1e039a..4da031716e32 100644
--- a/llvm/lib/ExecutionEngine/Orc/TargetProcess/SimpleExecutorMemoryManager.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/TargetProcess/SimpleExecutorMemoryManager.cpp
@@ -132,9 +132,9 @@ Error SimpleExecutorMemoryManager::finalize(tpctypes::FinalizeRequest &FR) {
assert(Seg.Size <= std::numeric_limits<size_t>::max());
if (auto EC = sys::Memory::protectMappedMemory(
{Mem, static_cast<size_t>(Seg.Size)},
- toSysMemoryProtectionFlags(Seg.AG.getMemProt())))
+ toSysMemoryProtectionFlags(Seg.RAG.Prot)))
return BailOut(errorCodeToError(EC));
- if ((Seg.AG.getMemProt() & MemProt::Exec) == MemProt::Exec)
+ if ((Seg.RAG.Prot & MemProt::Exec) == MemProt::Exec)
sys::Memory::InvalidateInstructionCache(Mem, Seg.Size);
}
diff --git a/llvm/lib/ExecutionEngine/Orc/TargetProcess/SimpleRemoteEPCServer.cpp b/llvm/lib/ExecutionEngine/Orc/TargetProcess/SimpleRemoteEPCServer.cpp
index 8ab0af3eab6e..67bc379f9821 100644
--- a/llvm/lib/ExecutionEngine/Orc/TargetProcess/SimpleRemoteEPCServer.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/TargetProcess/SimpleRemoteEPCServer.cpp
@@ -10,8 +10,8 @@
#include "llvm/ExecutionEngine/Orc/Shared/TargetProcessControlTypes.h"
#include "llvm/Support/FormatVariadic.h"
-#include "llvm/Support/Host.h"
#include "llvm/Support/Process.h"
+#include "llvm/TargetParser/Host.h"
#include "OrcRTBootstrap.h"
@@ -68,23 +68,22 @@ SimpleRemoteEPCServer::handleMessage(SimpleRemoteEPCOpcode OpC, uint64_t SeqNo,
case SimpleRemoteEPCOpcode::Setup:
dbgs() << "Setup";
assert(SeqNo == 0 && "Non-zero SeqNo for Setup?");
- assert(TagAddr.getValue() == 0 && "Non-zero TagAddr for Setup?");
+ assert(!TagAddr && "Non-zero TagAddr for Setup?");
break;
case SimpleRemoteEPCOpcode::Hangup:
dbgs() << "Hangup";
assert(SeqNo == 0 && "Non-zero SeqNo for Hangup?");
- assert(TagAddr.getValue() == 0 && "Non-zero TagAddr for Hangup?");
+ assert(!TagAddr && "Non-zero TagAddr for Hangup?");
break;
case SimpleRemoteEPCOpcode::Result:
dbgs() << "Result";
- assert(TagAddr.getValue() == 0 && "Non-zero TagAddr for Result?");
+ assert(!TagAddr && "Non-zero TagAddr for Result?");
break;
case SimpleRemoteEPCOpcode::CallWrapper:
dbgs() << "CallWrapper";
break;
}
- dbgs() << ", seqno = " << SeqNo
- << ", tag-addr = " << formatv("{0:x}", TagAddr.getValue())
+ dbgs() << ", seqno = " << SeqNo << ", tag-addr = " << TagAddr
<< ", arg-buffer = " << formatv("{0:x}", ArgBytes.size())
<< " bytes\n";
});
@@ -158,23 +157,22 @@ Error SimpleRemoteEPCServer::sendMessage(SimpleRemoteEPCOpcode OpC,
case SimpleRemoteEPCOpcode::Setup:
dbgs() << "Setup";
assert(SeqNo == 0 && "Non-zero SeqNo for Setup?");
- assert(TagAddr.getValue() == 0 && "Non-zero TagAddr for Setup?");
+ assert(!TagAddr && "Non-zero TagAddr for Setup?");
break;
case SimpleRemoteEPCOpcode::Hangup:
dbgs() << "Hangup";
assert(SeqNo == 0 && "Non-zero SeqNo for Hangup?");
- assert(TagAddr.getValue() == 0 && "Non-zero TagAddr for Hangup?");
+ assert(!TagAddr && "Non-zero TagAddr for Hangup?");
break;
case SimpleRemoteEPCOpcode::Result:
dbgs() << "Result";
- assert(TagAddr.getValue() == 0 && "Non-zero TagAddr for Result?");
+ assert(!TagAddr && "Non-zero TagAddr for Result?");
break;
case SimpleRemoteEPCOpcode::CallWrapper:
dbgs() << "CallWrapper";
break;
}
- dbgs() << ", seqno = " << SeqNo
- << ", tag-addr = " << formatv("{0:x}", TagAddr.getValue())
+ dbgs() << ", seqno = " << SeqNo << ", tag-addr = " << TagAddr
<< ", arg-buffer = " << formatv("{0:x}", ArgBytes.size())
<< " bytes\n";
});
@@ -187,6 +185,7 @@ Error SimpleRemoteEPCServer::sendMessage(SimpleRemoteEPCOpcode OpC,
}
Error SimpleRemoteEPCServer::sendSetupMessage(
+ StringMap<std::vector<char>> BootstrapMap,
StringMap<ExecutorAddr> BootstrapSymbols) {
using namespace SimpleRemoteEPCDefaultBootstrapSymbolNames;
@@ -198,6 +197,7 @@ Error SimpleRemoteEPCServer::sendSetupMessage(
EI.PageSize = *PageSize;
else
return PageSize.takeError();
+ EI.BootstrapMap = std::move(BootstrapMap);
EI.BootstrapSymbols = std::move(BootstrapSymbols);
assert(!EI.BootstrapSymbols.count(ExecutorSessionObjectName) &&
diff --git a/llvm/lib/ExecutionEngine/PerfJITEvents/PerfJITEventListener.cpp b/llvm/lib/ExecutionEngine/PerfJITEvents/PerfJITEventListener.cpp
index b425eec5f6d6..62cab22a1c45 100644
--- a/llvm/lib/ExecutionEngine/PerfJITEvents/PerfJITEventListener.cpp
+++ b/llvm/lib/ExecutionEngine/PerfJITEvents/PerfJITEventListener.cpp
@@ -417,7 +417,7 @@ void PerfJITEventListener::NotifyCode(Expected<llvm::StringRef> &Symbol,
rec.Prefix.Timestamp = perf_get_timestamp();
rec.CodeSize = CodeSize;
- rec.Vma = 0;
+ rec.Vma = CodeAddr;
rec.CodeAddr = CodeAddr;
rec.Pid = Pid;
rec.Tid = get_threadid();
diff --git a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCOFF.cpp b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCOFF.cpp
index 1d8f1ac8ac8a..9255311f992d 100644
--- a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCOFF.cpp
+++ b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCOFF.cpp
@@ -16,9 +16,9 @@
#include "Targets/RuntimeDyldCOFFThumb.h"
#include "Targets/RuntimeDyldCOFFX86_64.h"
#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/Triple.h"
#include "llvm/Object/ObjectFile.h"
#include "llvm/Support/FormatVariadic.h"
+#include "llvm/TargetParser/Triple.h"
using namespace llvm;
using namespace llvm::object;
diff --git a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp
index 2fe49fefae2d..d439b1b4ebfb 100644
--- a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp
+++ b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp
@@ -15,12 +15,12 @@
#include "Targets/RuntimeDyldELFMips.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/Triple.h"
#include "llvm/BinaryFormat/ELF.h"
#include "llvm/Object/ELFObjectFile.h"
#include "llvm/Object/ObjectFile.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/TargetParser/Triple.h"
using namespace llvm;
using namespace llvm::object;
@@ -426,13 +426,15 @@ void RuntimeDyldELF::resolveAArch64Relocation(const SectionEntry &Section,
break;
case ELF::R_AARCH64_ABS16: {
uint64_t Result = Value + Addend;
- assert(static_cast<int64_t>(Result) >= INT16_MIN && Result < UINT16_MAX);
+ assert(Result == static_cast<uint64_t>(llvm::SignExtend64(Result, 16)) ||
+ (Result >> 16) == 0);
write(isBE, TargetPtr, static_cast<uint16_t>(Result & 0xffffU));
break;
}
case ELF::R_AARCH64_ABS32: {
uint64_t Result = Value + Addend;
- assert(static_cast<int64_t>(Result) >= INT32_MIN && Result < UINT32_MAX);
+ assert(Result == static_cast<uint64_t>(llvm::SignExtend64(Result, 32)) ||
+ (Result >> 32) == 0);
write(isBE, TargetPtr, static_cast<uint32_t>(Result & 0xffffffffU));
break;
}
@@ -477,7 +479,9 @@ void RuntimeDyldELF::resolveAArch64Relocation(const SectionEntry &Section,
assert(isInt<16>(BranchImm));
- *TargetPtr &= 0xfff8001fU;
+ uint32_t RawInstr = *(support::little32_t *)TargetPtr;
+ *(support::little32_t *)TargetPtr = RawInstr & 0xfff8001fU;
+
// Immediate:15:2 goes in bits 18:5 of TBZ, TBNZ
or32le(TargetPtr, (BranchImm & 0x0000FFFC) << 3);
break;
@@ -1282,6 +1286,7 @@ RuntimeDyldELF::processRelocationRef(
}
case SymbolRef::ST_Data:
case SymbolRef::ST_Function:
+ case SymbolRef::ST_Other:
case SymbolRef::ST_Unknown: {
Value.SymbolName = TargetName.data();
Value.Addend = Addend;
@@ -2405,6 +2410,7 @@ Error RuntimeDyldELF::finalizeLoad(const ObjectFile &Obj,
}
}
+ GOTOffsetMap.clear();
GOTSectionID = 0;
CurrentGOTIndex = 0;
diff --git a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h
index bf33a2dec18a..501417db421a 100644
--- a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h
+++ b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h
@@ -15,7 +15,6 @@
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringMap.h"
-#include "llvm/ADT/Triple.h"
#include "llvm/ExecutionEngine/RTDyldMemoryManager.h"
#include "llvm/ExecutionEngine/RuntimeDyld.h"
#include "llvm/ExecutionEngine/RuntimeDyldChecker.h"
@@ -23,9 +22,10 @@
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Format.h"
-#include "llvm/Support/Host.h"
#include "llvm/Support/Mutex.h"
#include "llvm/Support/SwapByteOrder.h"
+#include "llvm/TargetParser/Host.h"
+#include "llvm/TargetParser/Triple.h"
#include <deque>
#include <map>
#include <system_error>
diff --git a/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFAArch64.h b/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFAArch64.h
index 342c4221ff0c..da381986e9de 100644
--- a/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFAArch64.h
+++ b/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFAArch64.h
@@ -15,6 +15,7 @@
#define LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_TARGETS_RUNTIMEDYLDCOFFAARCH64_H
#include "../RuntimeDyldCOFF.h"
+#include "llvm/ADT/SmallString.h"
#include "llvm/BinaryFormat/COFF.h"
#include "llvm/Object/COFF.h"
#include "llvm/Support/Endian.h"
diff --git a/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFThumb.h b/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFThumb.h
index 3859f36ac4bd..22f1cf33158c 100644
--- a/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFThumb.h
+++ b/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFThumb.h
@@ -14,6 +14,7 @@
#define LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_TARGETS_RUNTIMEDYLDCOFFTHUMB_H
#include "../RuntimeDyldCOFF.h"
+#include "llvm/ADT/SmallString.h"
#include "llvm/BinaryFormat/COFF.h"
#include "llvm/Object/COFF.h"
diff --git a/llvm/lib/ExecutionEngine/SectionMemoryManager.cpp b/llvm/lib/ExecutionEngine/SectionMemoryManager.cpp
index b23e33039c35..436888730bfb 100644
--- a/llvm/lib/ExecutionEngine/SectionMemoryManager.cpp
+++ b/llvm/lib/ExecutionEngine/SectionMemoryManager.cpp
@@ -101,7 +101,7 @@ uint8_t *SectionMemoryManager::allocateSection(
// FIXME: Initialize the Near member for each memory group to avoid
// interleaving.
std::error_code ec;
- sys::MemoryBlock MB = MMapper.allocateMappedMemory(
+ sys::MemoryBlock MB = MMapper->allocateMappedMemory(
Purpose, RequiredSize, &MemGroup.Near,
sys::Memory::MF_READ | sys::Memory::MF_WRITE, ec);
if (ec) {
@@ -204,7 +204,7 @@ std::error_code
SectionMemoryManager::applyMemoryGroupPermissions(MemoryGroup &MemGroup,
unsigned Permissions) {
for (sys::MemoryBlock &MB : MemGroup.PendingMem)
- if (std::error_code EC = MMapper.protectMappedMemory(MB, Permissions))
+ if (std::error_code EC = MMapper->protectMappedMemory(MB, Permissions))
return EC;
MemGroup.PendingMem.clear();
@@ -234,7 +234,7 @@ void SectionMemoryManager::invalidateInstructionCache() {
SectionMemoryManager::~SectionMemoryManager() {
for (MemoryGroup *Group : {&CodeMem, &RWDataMem, &RODataMem}) {
for (sys::MemoryBlock &Block : Group->AllocatedMem)
- MMapper.releaseMappedMemory(Block);
+ MMapper->releaseMappedMemory(Block);
}
}
@@ -263,11 +263,14 @@ public:
return sys::Memory::releaseMappedMemory(M);
}
};
-
-DefaultMMapper DefaultMMapperInstance;
} // namespace
-SectionMemoryManager::SectionMemoryManager(MemoryMapper *MM)
- : MMapper(MM ? *MM : DefaultMMapperInstance) {}
+SectionMemoryManager::SectionMemoryManager(MemoryMapper *UnownedMM)
+ : MMapper(UnownedMM), OwnedMMapper(nullptr) {
+ if (!MMapper) {
+ OwnedMMapper = std::make_unique<DefaultMMapper>();
+ MMapper = OwnedMMapper.get();
+ }
+}
} // namespace llvm
diff --git a/llvm/lib/ExecutionEngine/TargetSelect.cpp b/llvm/lib/ExecutionEngine/TargetSelect.cpp
index c67a1a7661d6..72fb16fbf203 100644
--- a/llvm/lib/ExecutionEngine/TargetSelect.cpp
+++ b/llvm/lib/ExecutionEngine/TargetSelect.cpp
@@ -13,13 +13,13 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/ADT/Triple.h"
#include "llvm/ExecutionEngine/ExecutionEngine.h"
#include "llvm/IR/Module.h"
-#include "llvm/MC/SubtargetFeature.h"
#include "llvm/MC/TargetRegistry.h"
-#include "llvm/Support/Host.h"
#include "llvm/Target/TargetMachine.h"
+#include "llvm/TargetParser/Host.h"
+#include "llvm/TargetParser/SubtargetFeature.h"
+#include "llvm/TargetParser/Triple.h"
using namespace llvm;
@@ -89,7 +89,6 @@ TargetMachine *EngineBuilder::selectTarget(const Triple &TargetTriple,
Options, RelocModel, CMModel, OptLevel,
/*JIT*/ true);
Target->Options.EmulatedTLS = EmulatedTLS;
- Target->Options.ExplicitEmulatedTLS = true;
assert(Target && "Could not allocate target machine!");
return Target;