[llvm-branch-commits] [llvm] ec6b71d - [JITLink][ORC] Enable creation / linking of raw jitlink::LinkGraphs.
Lang Hames via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Tue Dec 15 19:06:12 PST 2020
Author: Lang Hames
Date: 2020-12-16T14:01:50+11:00
New Revision: ec6b71df70a09681cc0ae87945db9f71649cf188
URL: https://github.com/llvm/llvm-project/commit/ec6b71df70a09681cc0ae87945db9f71649cf188
DIFF: https://github.com/llvm/llvm-project/commit/ec6b71df70a09681cc0ae87945db9f71649cf188.diff
LOG: [JITLink][ORC] Enable creation / linking of raw jitlink::LinkGraphs.
Separates link graph creation from linking. This allows raw LinkGraphs to be
created and passed to a link. ObjectLinkingLayer is updated to support emission
of raw LinkGraphs in addition to object buffers.
Raw LinkGraphs can be created by in-memory compilers to bypass object encoding /
decoding (though this prevents caching, as LinkGraphs have do not have an
on-disk representation), and by utility code to add programatically generated
data structures to the JIT target process.
Added:
Modified:
llvm/include/llvm/ExecutionEngine/JITLink/ELF.h
llvm/include/llvm/ExecutionEngine/JITLink/ELF_x86_64.h
llvm/include/llvm/ExecutionEngine/JITLink/JITLink.h
llvm/include/llvm/ExecutionEngine/JITLink/MachO.h
llvm/include/llvm/ExecutionEngine/JITLink/MachO_arm64.h
llvm/include/llvm/ExecutionEngine/JITLink/MachO_x86_64.h
llvm/include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h
llvm/lib/ExecutionEngine/JITLink/ELF.cpp
llvm/lib/ExecutionEngine/JITLink/ELF_x86_64.cpp
llvm/lib/ExecutionEngine/JITLink/JITLink.cpp
llvm/lib/ExecutionEngine/JITLink/JITLinkGeneric.cpp
llvm/lib/ExecutionEngine/JITLink/JITLinkGeneric.h
llvm/lib/ExecutionEngine/JITLink/MachO.cpp
llvm/lib/ExecutionEngine/JITLink/MachOLinkGraphBuilder.cpp
llvm/lib/ExecutionEngine/JITLink/MachOLinkGraphBuilder.h
llvm/lib/ExecutionEngine/JITLink/MachO_arm64.cpp
llvm/lib/ExecutionEngine/JITLink/MachO_x86_64.cpp
llvm/lib/ExecutionEngine/Orc/ObjectLinkingLayer.cpp
llvm/unittests/ExecutionEngine/JITLink/LinkGraphTests.cpp
Removed:
################################################################################
diff --git a/llvm/include/llvm/ExecutionEngine/JITLink/ELF.h b/llvm/include/llvm/ExecutionEngine/JITLink/ELF.h
index 9f6ea5271f4b..8912f3a2db45 100644
--- a/llvm/include/llvm/ExecutionEngine/JITLink/ELF.h
+++ b/llvm/include/llvm/ExecutionEngine/JITLink/ELF.h
@@ -19,11 +19,20 @@
namespace llvm {
namespace jitlink {
-/// jit-link the given ObjBuffer, which must be a ELF object file.
+/// Create a LinkGraph from an ELF relocatable object.
+///
+/// Note: The graph does not take ownership of the underlying buffer, nor copy
+/// its contents. The caller is responsible for ensuring that the object buffer
+/// outlives the graph.
+Expected<std::unique_ptr<LinkGraph>>
+createLinkGraphFromELFObject(MemoryBufferRef ObjectBuffer);
+
+/// Link the given graph.
///
/// Uses conservative defaults for GOT and stub handling based on the target
/// platform.
-void jitLink_ELF(std::unique_ptr<JITLinkContext> Ctx);
+void link_ELF(std::unique_ptr<LinkGraph> G,
+ std::unique_ptr<JITLinkContext> Ctx);
} // end namespace jitlink
} // end namespace llvm
diff --git a/llvm/include/llvm/ExecutionEngine/JITLink/ELF_x86_64.h b/llvm/include/llvm/ExecutionEngine/JITLink/ELF_x86_64.h
index 1e1e282a8997..1423b0c30b2a 100644
--- a/llvm/include/llvm/ExecutionEngine/JITLink/ELF_x86_64.h
+++ b/llvm/include/llvm/ExecutionEngine/JITLink/ELF_x86_64.h
@@ -44,8 +44,18 @@ enum ELFX86RelocationKind : Edge::Kind {
} // end namespace ELF_x86_64_Edges
+/// Create a LinkGraph from an ELF/x86-64 relocatable object.
+///
+/// Note: The graph does not take ownership of the underlying buffer, nor copy
+/// its contents. The caller is responsible for ensuring that the object buffer
+/// outlives the graph.
+Expected<std::unique_ptr<LinkGraph>>
+createLinkGraphFromELFObject_x86_64(MemoryBufferRef ObjectBuffer);
+
/// jit-link the given object buffer, which must be a ELF x86-64 object file.
-void jitLink_ELF_x86_64(std::unique_ptr<JITLinkContext> Ctx);
+void link_ELF_x86_64(std::unique_ptr<LinkGraph> G,
+ std::unique_ptr<JITLinkContext> Ctx);
+
/// Return the string name of the given ELF x86-64 edge kind.
StringRef getELFX86RelocationKindName(Edge::Kind R);
} // end namespace jitlink
diff --git a/llvm/include/llvm/ExecutionEngine/JITLink/JITLink.h b/llvm/include/llvm/ExecutionEngine/JITLink/JITLink.h
index 48e64335613b..6de0cd589aad 100644
--- a/llvm/include/llvm/ExecutionEngine/JITLink/JITLink.h
+++ b/llvm/include/llvm/ExecutionEngine/JITLink/JITLink.h
@@ -786,24 +786,40 @@ class LinkGraph {
Section::const_block_iterator, const Block *,
getSectionConstBlocks>;
- LinkGraph(std::string Name, unsigned PointerSize,
+ LinkGraph(std::string Name, const Triple &TT, unsigned PointerSize,
support::endianness Endianness)
- : Name(std::move(Name)), PointerSize(PointerSize),
+ : Name(std::move(Name)), TT(TT), PointerSize(PointerSize),
Endianness(Endianness) {}
/// Returns the name of this graph (usually the name of the original
/// underlying MemoryBuffer).
const std::string &getName() { return Name; }
+ /// Returns the target triple for this Graph.
+ const Triple &getTargetTriple() const { return TT; }
+
/// Returns the pointer size for use in this graph.
unsigned getPointerSize() const { return PointerSize; }
/// Returns the endianness of content in this graph.
support::endianness getEndianness() const { return Endianness; }
- /// Allocate a copy of the given String using the LinkGraph's allocator.
+ /// Allocate a copy of the given string using the LinkGraph's allocator.
/// This can be useful when renaming symbols or adding new content to the
/// graph.
+ StringRef allocateString(StringRef Source) {
+ auto *AllocatedBuffer = Allocator.Allocate<char>(Source.size());
+ llvm::copy(Source, AllocatedBuffer);
+ return StringRef(AllocatedBuffer, Source.size());
+ }
+
+ /// Allocate a copy of the given string using the LinkGraph's allocator.
+ /// This can be useful when renaming symbols or adding new content to the
+ /// graph.
+ ///
+ /// Note: This Twine-based overload requires an extra string copy and an
+ /// extra heap allocation for large strings. The StringRef overload should
+ /// be preferred where possible.
StringRef allocateString(Twine Source) {
SmallString<256> TmpBuffer;
auto SourceStr = Source.toStringRef(TmpBuffer);
@@ -1034,6 +1050,7 @@ class LinkGraph {
BumpPtrAllocator Allocator;
std::string Name;
+ Triple TT;
unsigned PointerSize;
support::endianness Endianness;
SectionList Sections;
@@ -1282,10 +1299,6 @@ class JITLinkContext {
/// Return the MemoryManager to be used for this link.
virtual JITLinkMemoryManager &getMemoryManager() = 0;
- /// Returns a StringRef for the object buffer.
- /// This method can not be called once takeObjectBuffer has been called.
- virtual MemoryBufferRef getObjectBuffer() const = 0;
-
/// Notify this context that linking failed.
/// Called by JITLink if linking cannot be completed.
virtual void notifyFailed(Error Err) = 0;
@@ -1339,10 +1352,16 @@ class JITLinkContext {
/// conservative mark-live implementation.
Error markAllSymbolsLive(LinkGraph &G);
-/// Basic JITLink implementation.
+/// Create a LinkGraph from the given object buffer.
///
-/// This function will use sensible defaults for GOT and Stub handling.
-void jitLink(std::unique_ptr<JITLinkContext> Ctx);
+/// Note: The graph does not take ownership of the underlying buffer, nor copy
+/// its contents. The caller is responsible for ensuring that the object buffer
+/// outlives the graph.
+Expected<std::unique_ptr<LinkGraph>>
+createLinkGraphFromObject(MemoryBufferRef ObjectBuffer);
+
+/// Link the given graph.
+void link(std::unique_ptr<LinkGraph> G, std::unique_ptr<JITLinkContext> Ctx);
} // end namespace jitlink
} // end namespace llvm
diff --git a/llvm/include/llvm/ExecutionEngine/JITLink/MachO.h b/llvm/include/llvm/ExecutionEngine/JITLink/MachO.h
index 7facb657a51c..b8432c4d26c6 100644
--- a/llvm/include/llvm/ExecutionEngine/JITLink/MachO.h
+++ b/llvm/include/llvm/ExecutionEngine/JITLink/MachO.h
@@ -18,11 +18,20 @@
namespace llvm {
namespace jitlink {
+/// Create a LinkGraph from a MachO relocatable object.
+///
+/// Note: The graph does not take ownership of the underlying buffer, nor copy
+/// its contents. The caller is responsible for ensuring that the object buffer
+/// outlives the graph.
+Expected<std::unique_ptr<LinkGraph>>
+createLinkGraphFromMachOObject(MemoryBufferRef ObjectBuffer);
+
/// jit-link the given ObjBuffer, which must be a MachO object file.
///
/// Uses conservative defaults for GOT and stub handling based on the target
/// platform.
-void jitLink_MachO(std::unique_ptr<JITLinkContext> Ctx);
+void link_MachO(std::unique_ptr<LinkGraph> G,
+ std::unique_ptr<JITLinkContext> Ctx);
} // end namespace jitlink
} // end namespace llvm
diff --git a/llvm/include/llvm/ExecutionEngine/JITLink/MachO_arm64.h b/llvm/include/llvm/ExecutionEngine/JITLink/MachO_arm64.h
index d70b545fff86..c6aed2b60eac 100644
--- a/llvm/include/llvm/ExecutionEngine/JITLink/MachO_arm64.h
+++ b/llvm/include/llvm/ExecutionEngine/JITLink/MachO_arm64.h
@@ -40,6 +40,14 @@ enum MachOARM64RelocationKind : Edge::Kind {
} // namespace MachO_arm64_Edges
+/// Create a LinkGraph from a MachO/arm64 relocatable object.
+///
+/// Note: The graph does not take ownership of the underlying buffer, nor copy
+/// its contents. The caller is responsible for ensuring that the object buffer
+/// outlives the graph.
+Expected<std::unique_ptr<LinkGraph>>
+createLinkGraphFromMachOObject_arm64(MemoryBufferRef ObjectBuffer);
+
/// jit-link the given object buffer, which must be a MachO arm64 object file.
///
/// If PrePrunePasses is empty then a default mark-live pass will be inserted
@@ -49,7 +57,8 @@ enum MachOARM64RelocationKind : Edge::Kind {
/// If PostPrunePasses is empty then a default GOT-and-stubs insertion pass will
/// be inserted. If PostPrunePasses is not empty then the caller is responsible
/// for including a pass to insert GOT and stub edges.
-void jitLink_MachO_arm64(std::unique_ptr<JITLinkContext> Ctx);
+void link_MachO_arm64(std::unique_ptr<LinkGraph> G,
+ std::unique_ptr<JITLinkContext> Ctx);
/// Return the string name of the given MachO arm64 edge kind.
StringRef getMachOARM64RelocationKindName(Edge::Kind R);
diff --git a/llvm/include/llvm/ExecutionEngine/JITLink/MachO_x86_64.h b/llvm/include/llvm/ExecutionEngine/JITLink/MachO_x86_64.h
index 27fcdf4fa990..66c53d8c8291 100644
--- a/llvm/include/llvm/ExecutionEngine/JITLink/MachO_x86_64.h
+++ b/llvm/include/llvm/ExecutionEngine/JITLink/MachO_x86_64.h
@@ -45,7 +45,15 @@ enum MachOX86RelocationKind : Edge::Kind {
} // namespace MachO_x86_64_Edges
-/// jit-link the given object buffer, which must be a MachO x86-64 object file.
+/// Create a LinkGraph from a MachO/x86-64 relocatable object.
+///
+/// Note: The graph does not take ownership of the underlying buffer, nor copy
+/// its contents. The caller is responsible for ensuring that the object buffer
+/// outlives the graph.
+Expected<std::unique_ptr<LinkGraph>>
+createLinkGraphFromMachOObject_x86_64(MemoryBufferRef ObjectBuffer);
+
+/// jit-link the given LinkGraph.
///
/// If PrePrunePasses is empty then a default mark-live pass will be inserted
/// that will mark all exported atoms live. If PrePrunePasses is not empty, the
@@ -54,7 +62,8 @@ enum MachOX86RelocationKind : Edge::Kind {
/// If PostPrunePasses is empty then a default GOT-and-stubs insertion pass will
/// be inserted. If PostPrunePasses is not empty then the caller is responsible
/// for including a pass to insert GOT and stub edges.
-void jitLink_MachO_x86_64(std::unique_ptr<JITLinkContext> Ctx);
+void link_MachO_x86_64(std::unique_ptr<LinkGraph> G,
+ std::unique_ptr<JITLinkContext> Ctx);
/// Return the string name of the given MachO x86-64 edge kind.
StringRef getMachOX86RelocationKindName(Edge::Kind R);
diff --git a/llvm/include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h b/llvm/include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h
index b73217f09b54..f2975e29fcd6 100644
--- a/llvm/include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h
+++ b/llvm/include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h
@@ -35,6 +35,7 @@ namespace llvm {
namespace jitlink {
class EHFrameRegistrar;
+class LinkGraph;
class Symbol;
} // namespace jitlink
@@ -118,10 +119,14 @@ class ObjectLinkingLayer : public ObjectLayer, private ResourceManager {
return *this;
}
- /// Emit the object.
+ /// Emit an object file.
void emit(std::unique_ptr<MaterializationResponsibility> R,
std::unique_ptr<MemoryBuffer> O) override;
+ /// Emit a LinkGraph.
+ void emit(std::unique_ptr<MaterializationResponsibility> R,
+ std::unique_ptr<jitlink::LinkGraph> G);
+
/// Instructs this ObjectLinkingLayer instance to override the symbol flags
/// found in the AtomGraph with the flags supplied by the
/// MaterializationResponsibility instance. This is a workaround to support
diff --git a/llvm/lib/ExecutionEngine/JITLink/ELF.cpp b/llvm/lib/ExecutionEngine/JITLink/ELF.cpp
index 19b878257709..27eb7d576e2d 100644
--- a/llvm/lib/ExecutionEngine/JITLink/ELF.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/ELF.cpp
@@ -50,32 +50,39 @@ Expected<uint16_t> readTargetMachineArch(StringRef Buffer) {
return ELF::EM_NONE;
}
-void jitLink_ELF(std::unique_ptr<JITLinkContext> Ctx) {
- StringRef Buffer = Ctx->getObjectBuffer().getBuffer();
- if (Buffer.size() < ELF::EI_MAG3 + 1) {
- Ctx->notifyFailed(make_error<JITLinkError>("Truncated ELF buffer"));
- return;
- }
+Expected<std::unique_ptr<LinkGraph>>
+createLinkGraphFromELFObject(MemoryBufferRef ObjectBuffer) {
+ StringRef Buffer = ObjectBuffer.getBuffer();
+ if (Buffer.size() < ELF::EI_MAG3 + 1)
+ return make_error<JITLinkError>("Truncated ELF buffer");
- if (memcmp(Buffer.data(), ELF::ElfMagic, strlen(ELF::ElfMagic)) != 0) {
- Ctx->notifyFailed(make_error<JITLinkError>("ELF magic not valid"));
- return;
- }
+ if (memcmp(Buffer.data(), ELF::ElfMagic, strlen(ELF::ElfMagic)) != 0)
+ return make_error<JITLinkError>("ELF magic not valid");
Expected<uint16_t> TargetMachineArch = readTargetMachineArch(Buffer);
- if (!TargetMachineArch) {
- Ctx->notifyFailed(TargetMachineArch.takeError());
- return;
- }
+ if (!TargetMachineArch)
+ return TargetMachineArch.takeError();
switch (*TargetMachineArch) {
case ELF::EM_X86_64:
- jitLink_ELF_x86_64(std::move(Ctx));
+ return createLinkGraphFromELFObject_x86_64(std::move(ObjectBuffer));
+ default:
+ return make_error<JITLinkError>(
+ "Unsupported target machine architecture in ELF object " +
+ ObjectBuffer.getBufferIdentifier());
+ }
+}
+
+void link_ELF(std::unique_ptr<LinkGraph> G,
+ std::unique_ptr<JITLinkContext> Ctx) {
+ switch (G->getTargetTriple().getArch()) {
+ case Triple::x86_64:
+ link_ELF_x86_64(std::move(G), std::move(Ctx));
return;
default:
Ctx->notifyFailed(make_error<JITLinkError>(
- "Unsupported target machine architecture in ELF object " +
- Ctx->getObjectBuffer().getBufferIdentifier()));
+ "Unsupported target machine architecture in ELF link graph " +
+ G->getName()));
return;
}
}
diff --git a/llvm/lib/ExecutionEngine/JITLink/ELF_x86_64.cpp b/llvm/lib/ExecutionEngine/JITLink/ELF_x86_64.cpp
index 20504b861155..ea05b6c7e638 100644
--- a/llvm/lib/ExecutionEngine/JITLink/ELF_x86_64.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/ELF_x86_64.cpp
@@ -571,10 +571,11 @@ class ELFLinkGraphBuilder_x86_64 {
}
public:
- ELFLinkGraphBuilder_x86_64(std::string filename,
+ ELFLinkGraphBuilder_x86_64(StringRef FileName,
const object::ELFFile<object::ELF64LE> &Obj)
- : G(std::make_unique<LinkGraph>(filename, getPointerSize(Obj),
- getEndianness(Obj))),
+ : G(std::make_unique<LinkGraph>(FileName.str(),
+ Triple("x86_64-unknown-linux"),
+ getPointerSize(Obj), getEndianness(Obj))),
Obj(Obj) {}
Expected<std::unique_ptr<LinkGraph>> buildGraph() {
@@ -610,27 +611,15 @@ class ELFJITLinker_x86_64 : public JITLinker<ELFJITLinker_x86_64> {
public:
ELFJITLinker_x86_64(std::unique_ptr<JITLinkContext> Ctx,
+ std::unique_ptr<LinkGraph> G,
PassConfiguration PassConfig)
- : JITLinker(std::move(Ctx), std::move(PassConfig)) {}
+ : JITLinker(std::move(Ctx), std::move(G), std::move(PassConfig)) {}
private:
StringRef getEdgeKindName(Edge::Kind R) const override {
return getELFX86RelocationKindName(R);
}
- Expected<std::unique_ptr<LinkGraph>>
- buildGraph(MemoryBufferRef ObjBuffer) override {
- auto ELFObj = object::ObjectFile::createELFObjectFile(ObjBuffer);
- if (!ELFObj)
- return ELFObj.takeError();
-
- auto &ELFObjFile = cast<object::ELFObjectFile<object::ELF64LE>>(**ELFObj);
- std::string fileName(ELFObj->get()->getFileName());
- return ELFLinkGraphBuilder_x86_64(std::move(fileName),
- ELFObjFile.getELFFile())
- .buildGraph();
- }
-
Error applyFixup(Block &B, const Edge &E, char *BlockWorkingMem) const {
using namespace ELF_x86_64_Edges;
using namespace llvm::support;
@@ -655,12 +644,30 @@ class ELFJITLinker_x86_64 : public JITLinker<ELFJITLinker_x86_64> {
}
};
-void jitLink_ELF_x86_64(std::unique_ptr<JITLinkContext> Ctx) {
+Expected<std::unique_ptr<LinkGraph>>
+createLinkGraphFromELFObject_x86_64(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 &ELFObjFile = cast<object::ELFObjectFile<object::ELF64LE>>(**ELFObj);
+ return ELFLinkGraphBuilder_x86_64((*ELFObj)->getFileName(),
+ ELFObjFile.getELFFile())
+ .buildGraph();
+}
+
+void link_ELF_x86_64(std::unique_ptr<LinkGraph> G,
+ std::unique_ptr<JITLinkContext> Ctx) {
PassConfiguration Config;
- Triple TT("x86_64-linux");
+
// Construct a JITLinker and run the link function.
// Add a mark-live pass.
- if (auto MarkLive = Ctx->getMarkLivePass(TT))
+ if (auto MarkLive = Ctx->getMarkLivePass(G->getTargetTriple()))
Config.PrePrunePasses.push_back(std::move(MarkLive));
else
Config.PrePrunePasses.push_back(markAllSymbolsLive);
@@ -674,10 +681,10 @@ void jitLink_ELF_x86_64(std::unique_ptr<JITLinkContext> Ctx) {
// Add GOT/Stubs optimizer pass.
Config.PostAllocationPasses.push_back(optimizeELF_x86_64_GOTAndStubs);
- if (auto Err = Ctx->modifyPassConfig(TT, Config))
+ if (auto Err = Ctx->modifyPassConfig(G->getTargetTriple(), Config))
return Ctx->notifyFailed(std::move(Err));
- ELFJITLinker_x86_64::link(std::move(Ctx), std::move(Config));
+ ELFJITLinker_x86_64::link(std::move(Ctx), std::move(G), std::move(Config));
}
StringRef getELFX86RelocationKindName(Edge::Kind R) {
switch (R) {
diff --git a/llvm/lib/ExecutionEngine/JITLink/JITLink.cpp b/llvm/lib/ExecutionEngine/JITLink/JITLink.cpp
index 71ec88639a5b..41b5423dc335 100644
--- a/llvm/lib/ExecutionEngine/JITLink/JITLink.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/JITLink.cpp
@@ -322,15 +322,27 @@ Error markAllSymbolsLive(LinkGraph &G) {
return Error::success();
}
-void jitLink(std::unique_ptr<JITLinkContext> Ctx) {
- auto Magic = identify_magic(Ctx->getObjectBuffer().getBuffer());
+Expected<std::unique_ptr<LinkGraph>>
+createLinkGraphFromObject(MemoryBufferRef ObjectBuffer) {
+ auto Magic = identify_magic(ObjectBuffer.getBuffer());
switch (Magic) {
case file_magic::macho_object:
- return jitLink_MachO(std::move(Ctx));
+ return createLinkGraphFromMachOObject(std::move(ObjectBuffer));
case file_magic::elf_relocatable:
- return jitLink_ELF(std::move(Ctx));
+ return createLinkGraphFromELFObject(std::move(ObjectBuffer));
default:
- Ctx->notifyFailed(make_error<JITLinkError>("Unsupported file format"));
+ return make_error<JITLinkError>("Unsupported file format");
+ };
+}
+
+void link(std::unique_ptr<LinkGraph> G, std::unique_ptr<JITLinkContext> Ctx) {
+ switch (G->getTargetTriple().getObjectFormat()) {
+ case Triple::MachO:
+ return link_MachO(std::move(G), std::move(Ctx));
+ case Triple::ELF:
+ return link_ELF(std::move(G), std::move(Ctx));
+ default:
+ Ctx->notifyFailed(make_error<JITLinkError>("Unsupported object format"));
};
}
diff --git a/llvm/lib/ExecutionEngine/JITLink/JITLinkGeneric.cpp b/llvm/lib/ExecutionEngine/JITLink/JITLinkGeneric.cpp
index 393ed0ea7093..f29f6592e6ff 100644
--- a/llvm/lib/ExecutionEngine/JITLink/JITLinkGeneric.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/JITLinkGeneric.cpp
@@ -24,18 +24,6 @@ JITLinkerBase::~JITLinkerBase() {}
void JITLinkerBase::linkPhase1(std::unique_ptr<JITLinkerBase> Self) {
- LLVM_DEBUG({
- dbgs() << "Building jitlink graph for new input "
- << Ctx->getObjectBuffer().getBufferIdentifier() << "...\n";
- });
-
- // Build the link graph.
- if (auto GraphOrErr = buildGraph(Ctx->getObjectBuffer()))
- G = std::move(*GraphOrErr);
- else
- return Ctx->notifyFailed(GraphOrErr.takeError());
- assert(G && "Graph should have been created by buildGraph above");
-
LLVM_DEBUG({
dbgs() << "Starting link phase 1 for graph " << G->getName() << "\n";
});
diff --git a/llvm/lib/ExecutionEngine/JITLink/JITLinkGeneric.h b/llvm/lib/ExecutionEngine/JITLink/JITLinkGeneric.h
index 87e5e8bbc98d..1d28f5006b2b 100644
--- a/llvm/lib/ExecutionEngine/JITLink/JITLinkGeneric.h
+++ b/llvm/lib/ExecutionEngine/JITLink/JITLinkGeneric.h
@@ -32,9 +32,11 @@ namespace jitlink {
/// remaining linker work) to allow them to be performed asynchronously.
class JITLinkerBase {
public:
- JITLinkerBase(std::unique_ptr<JITLinkContext> Ctx, PassConfiguration Passes)
- : Ctx(std::move(Ctx)), Passes(std::move(Passes)) {
+ JITLinkerBase(std::unique_ptr<JITLinkContext> Ctx,
+ std::unique_ptr<LinkGraph> G, PassConfiguration Passes)
+ : Ctx(std::move(Ctx)), G(std::move(G)), Passes(std::move(Passes)) {
assert(this->Ctx && "Ctx can not be null");
+ assert(this->G && "G can not be null");
}
virtual ~JITLinkerBase();
@@ -50,8 +52,7 @@ class JITLinkerBase {
using SegmentLayoutMap = DenseMap<unsigned, SegmentLayout>;
// Phase 1:
- // 1.1: Build link graph
- // 1.2: Run pre-prune passes
+ // 1.1: Run pre-prune passes
// 1.2: Prune graph
// 1.3: Run post-prune passes
// 1.4: Sort blocks into segments
@@ -72,11 +73,6 @@ class JITLinkerBase {
// 3.1: Call OnFinalized callback, handing off allocation.
void linkPhase3(std::unique_ptr<JITLinkerBase> Self, Error Err);
- // Build a graph from the given object buffer.
- // To be implemented by the client.
- virtual Expected<std::unique_ptr<LinkGraph>>
- buildGraph(MemoryBufferRef ObjBuffer) = 0;
-
// For debug dumping of the link graph.
virtual StringRef getEdgeKindName(Edge::Kind K) const = 0;
@@ -113,8 +109,8 @@ class JITLinkerBase {
void dumpGraph(raw_ostream &OS);
std::unique_ptr<JITLinkContext> Ctx;
- PassConfiguration Passes;
std::unique_ptr<LinkGraph> G;
+ PassConfiguration Passes;
std::unique_ptr<JITLinkMemoryManager::Allocation> Alloc;
};
diff --git a/llvm/lib/ExecutionEngine/JITLink/MachO.cpp b/llvm/lib/ExecutionEngine/JITLink/MachO.cpp
index b3e45868ab22..e9327df6da41 100644
--- a/llvm/lib/ExecutionEngine/JITLink/MachO.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/MachO.cpp
@@ -27,39 +27,29 @@ using namespace llvm;
namespace llvm {
namespace jitlink {
-void jitLink_MachO(std::unique_ptr<JITLinkContext> Ctx) {
-
- // We don't want to do full MachO validation here. Just parse enough of the
- // header to find out what MachO linker to use.
-
- StringRef Data = Ctx->getObjectBuffer().getBuffer();
- if (Data.size() < 4) {
- StringRef BufferName = Ctx->getObjectBuffer().getBufferIdentifier();
- Ctx->notifyFailed(make_error<JITLinkError>("Truncated MachO buffer \"" +
- BufferName + "\""));
- return;
- }
+Expected<std::unique_ptr<LinkGraph>>
+createLinkGraphFromMachOObject(MemoryBufferRef ObjectBuffer) {
+ StringRef Data = ObjectBuffer.getBuffer();
+ if (Data.size() < 4)
+ return make_error<JITLinkError>("Truncated MachO buffer \"" +
+ ObjectBuffer.getBufferIdentifier() + "\"");
uint32_t Magic;
memcpy(&Magic, Data.data(), sizeof(uint32_t));
LLVM_DEBUG({
dbgs() << "jitLink_MachO: magic = " << format("0x%08" PRIx32, Magic)
- << ", identifier = \""
- << Ctx->getObjectBuffer().getBufferIdentifier() << "\"\n";
+ << ", identifier = \"" << ObjectBuffer.getBufferIdentifier()
+ << "\"\n";
});
- if (Magic == MachO::MH_MAGIC || Magic == MachO::MH_CIGAM) {
- Ctx->notifyFailed(
- make_error<JITLinkError>("MachO 32-bit platforms not supported"));
- return;
- } else if (Magic == MachO::MH_MAGIC_64 || Magic == MachO::MH_CIGAM_64) {
+ if (Magic == MachO::MH_MAGIC || Magic == MachO::MH_CIGAM)
+ return make_error<JITLinkError>("MachO 32-bit platforms not supported");
+ else if (Magic == MachO::MH_MAGIC_64 || Magic == MachO::MH_CIGAM_64) {
- if (Data.size() < sizeof(MachO::mach_header_64)) {
- StringRef BufferName = Ctx->getObjectBuffer().getBufferIdentifier();
- Ctx->notifyFailed(make_error<JITLinkError>("Truncated MachO buffer \"" +
- BufferName + "\""));
- return;
- }
+ if (Data.size() < sizeof(MachO::mach_header_64))
+ return make_error<JITLinkError>("Truncated MachO buffer \"" +
+ ObjectBuffer.getBufferIdentifier() +
+ "\"");
// Read the CPU type from the header.
uint32_t CPUType;
@@ -74,15 +64,27 @@ void jitLink_MachO(std::unique_ptr<JITLinkContext> Ctx) {
switch (CPUType) {
case MachO::CPU_TYPE_ARM64:
- return jitLink_MachO_arm64(std::move(Ctx));
+ return createLinkGraphFromMachOObject_arm64(std::move(ObjectBuffer));
case MachO::CPU_TYPE_X86_64:
- return jitLink_MachO_x86_64(std::move(Ctx));
+ return createLinkGraphFromMachOObject_x86_64(std::move(ObjectBuffer));
}
+ return make_error<JITLinkError>("MachO-64 CPU type not valid");
+ } else
+ return make_error<JITLinkError>("Unrecognized MachO magic value");
+}
+
+void link_MachO(std::unique_ptr<LinkGraph> G,
+ std::unique_ptr<JITLinkContext> Ctx) {
+
+ switch (G->getTargetTriple().getArch()) {
+ case Triple::aarch64:
+ return link_MachO_arm64(std::move(G), std::move(Ctx));
+ case Triple::x86_64:
+ return link_MachO_x86_64(std::move(G), std::move(Ctx));
+ default:
Ctx->notifyFailed(make_error<JITLinkError>("MachO-64 CPU type not valid"));
return;
}
-
- Ctx->notifyFailed(make_error<JITLinkError>("MachO magic not valid"));
}
} // end namespace jitlink
diff --git a/llvm/lib/ExecutionEngine/JITLink/MachOLinkGraphBuilder.cpp b/llvm/lib/ExecutionEngine/JITLink/MachOLinkGraphBuilder.cpp
index cf1bb23da665..4602154eb579 100644
--- a/llvm/lib/ExecutionEngine/JITLink/MachOLinkGraphBuilder.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/MachOLinkGraphBuilder.cpp
@@ -45,10 +45,12 @@ Expected<std::unique_ptr<LinkGraph>> MachOLinkGraphBuilder::buildGraph() {
return std::move(G);
}
-MachOLinkGraphBuilder::MachOLinkGraphBuilder(const object::MachOObjectFile &Obj)
+MachOLinkGraphBuilder::MachOLinkGraphBuilder(const object::MachOObjectFile &Obj,
+ Triple TT)
: Obj(Obj),
G(std::make_unique<LinkGraph>(std::string(Obj.getFileName()),
- getPointerSize(Obj), getEndianness(Obj))) {}
+ std::move(TT), getPointerSize(Obj),
+ getEndianness(Obj))) {}
void MachOLinkGraphBuilder::addCustomSectionParser(
StringRef SectionName, SectionParserFunction Parser) {
diff --git a/llvm/lib/ExecutionEngine/JITLink/MachOLinkGraphBuilder.h b/llvm/lib/ExecutionEngine/JITLink/MachOLinkGraphBuilder.h
index dd3bcf27494c..3555d66ace35 100644
--- a/llvm/lib/ExecutionEngine/JITLink/MachOLinkGraphBuilder.h
+++ b/llvm/lib/ExecutionEngine/JITLink/MachOLinkGraphBuilder.h
@@ -81,7 +81,7 @@ class MachOLinkGraphBuilder {
using SectionParserFunction = std::function<Error(NormalizedSection &S)>;
- MachOLinkGraphBuilder(const object::MachOObjectFile &Obj);
+ MachOLinkGraphBuilder(const object::MachOObjectFile &Obj, Triple TT);
LinkGraph &getGraph() const { return *G; }
diff --git a/llvm/lib/ExecutionEngine/JITLink/MachO_arm64.cpp b/llvm/lib/ExecutionEngine/JITLink/MachO_arm64.cpp
index a7178aa1e450..8366e9658539 100644
--- a/llvm/lib/ExecutionEngine/JITLink/MachO_arm64.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/MachO_arm64.cpp
@@ -26,7 +26,7 @@ namespace {
class MachOLinkGraphBuilder_arm64 : public MachOLinkGraphBuilder {
public:
MachOLinkGraphBuilder_arm64(const object::MachOObjectFile &Obj)
- : MachOLinkGraphBuilder(Obj),
+ : MachOLinkGraphBuilder(Obj, Triple("arm64-apple-darwin")),
NumSymbols(Obj.getSymtabLoadCommand().nsyms) {}
private:
@@ -501,22 +501,15 @@ class MachOJITLinker_arm64 : public JITLinker<MachOJITLinker_arm64> {
public:
MachOJITLinker_arm64(std::unique_ptr<JITLinkContext> Ctx,
+ std::unique_ptr<LinkGraph> G,
PassConfiguration PassConfig)
- : JITLinker(std::move(Ctx), std::move(PassConfig)) {}
+ : JITLinker(std::move(Ctx), std::move(G), std::move(PassConfig)) {}
private:
StringRef getEdgeKindName(Edge::Kind R) const override {
return getMachOARM64RelocationKindName(R);
}
- Expected<std::unique_ptr<LinkGraph>>
- buildGraph(MemoryBufferRef ObjBuffer) override {
- auto MachOObj = object::ObjectFile::createMachOObjectFile(ObjBuffer);
- if (!MachOObj)
- return MachOObj.takeError();
- return MachOLinkGraphBuilder_arm64(**MachOObj).buildGraph();
- }
-
static Error targetOutOfRangeError(const Block &B, const Edge &E) {
std::string ErrMsg;
{
@@ -681,13 +674,22 @@ class MachOJITLinker_arm64 : public JITLinker<MachOJITLinker_arm64> {
uint64_t NullValue = 0;
};
-void jitLink_MachO_arm64(std::unique_ptr<JITLinkContext> Ctx) {
+Expected<std::unique_ptr<LinkGraph>>
+createLinkGraphFromMachOObject_arm64(MemoryBufferRef ObjectBuffer) {
+ auto MachOObj = object::ObjectFile::createMachOObjectFile(ObjectBuffer);
+ if (!MachOObj)
+ return MachOObj.takeError();
+ return MachOLinkGraphBuilder_arm64(**MachOObj).buildGraph();
+}
+
+void link_MachO_arm64(std::unique_ptr<LinkGraph> G,
+ std::unique_ptr<JITLinkContext> Ctx) {
+
PassConfiguration Config;
- Triple TT("arm64-apple-ios");
- if (Ctx->shouldAddDefaultTargetPasses(TT)) {
+ if (Ctx->shouldAddDefaultTargetPasses(G->getTargetTriple())) {
// Add a mark-live pass.
- if (auto MarkLive = Ctx->getMarkLivePass(TT))
+ if (auto MarkLive = Ctx->getMarkLivePass(G->getTargetTriple()))
Config.PrePrunePasses.push_back(std::move(MarkLive));
else
Config.PrePrunePasses.push_back(markAllSymbolsLive);
@@ -699,11 +701,11 @@ void jitLink_MachO_arm64(std::unique_ptr<JITLinkContext> Ctx) {
});
}
- if (auto Err = Ctx->modifyPassConfig(TT, Config))
+ if (auto Err = Ctx->modifyPassConfig(G->getTargetTriple(), Config))
return Ctx->notifyFailed(std::move(Err));
// Construct a JITLinker and run the link function.
- MachOJITLinker_arm64::link(std::move(Ctx), std::move(Config));
+ MachOJITLinker_arm64::link(std::move(Ctx), std::move(G), std::move(Config));
}
StringRef getMachOARM64RelocationKindName(Edge::Kind R) {
diff --git a/llvm/lib/ExecutionEngine/JITLink/MachO_x86_64.cpp b/llvm/lib/ExecutionEngine/JITLink/MachO_x86_64.cpp
index a70b0dcd8f85..34e0c3250495 100644
--- a/llvm/lib/ExecutionEngine/JITLink/MachO_x86_64.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/MachO_x86_64.cpp
@@ -26,7 +26,7 @@ namespace {
class MachOLinkGraphBuilder_x86_64 : public MachOLinkGraphBuilder {
public:
MachOLinkGraphBuilder_x86_64(const object::MachOObjectFile &Obj)
- : MachOLinkGraphBuilder(Obj) {}
+ : MachOLinkGraphBuilder(Obj, Triple("x86_64-apple-darwin")) {}
private:
static Expected<MachOX86RelocationKind>
@@ -548,22 +548,15 @@ class MachOJITLinker_x86_64 : public JITLinker<MachOJITLinker_x86_64> {
public:
MachOJITLinker_x86_64(std::unique_ptr<JITLinkContext> Ctx,
+ std::unique_ptr<LinkGraph> G,
PassConfiguration PassConfig)
- : JITLinker(std::move(Ctx), std::move(PassConfig)) {}
+ : JITLinker(std::move(Ctx), std::move(G), std::move(PassConfig)) {}
private:
StringRef getEdgeKindName(Edge::Kind R) const override {
return getMachOX86RelocationKindName(R);
}
- Expected<std::unique_ptr<LinkGraph>>
- buildGraph(MemoryBufferRef ObjBuffer) override {
- auto MachOObj = object::ObjectFile::createMachOObjectFile(ObjBuffer);
- if (!MachOObj)
- return MachOObj.takeError();
- return MachOLinkGraphBuilder_x86_64(**MachOObj).buildGraph();
- }
-
static Error targetOutOfRangeError(const Block &B, const Edge &E) {
std::string ErrMsg;
{
@@ -660,18 +653,27 @@ class MachOJITLinker_x86_64 : public JITLinker<MachOJITLinker_x86_64> {
uint64_t NullValue = 0;
};
-void jitLink_MachO_x86_64(std::unique_ptr<JITLinkContext> Ctx) {
+Expected<std::unique_ptr<LinkGraph>>
+createLinkGraphFromMachOObject_x86_64(MemoryBufferRef ObjectBuffer) {
+ auto MachOObj = object::ObjectFile::createMachOObjectFile(ObjectBuffer);
+ if (!MachOObj)
+ return MachOObj.takeError();
+ return MachOLinkGraphBuilder_x86_64(**MachOObj).buildGraph();
+}
+
+void link_MachO_x86_64(std::unique_ptr<LinkGraph> G,
+ std::unique_ptr<JITLinkContext> Ctx) {
+
PassConfiguration Config;
- Triple TT("x86_64-apple-macosx");
- if (Ctx->shouldAddDefaultTargetPasses(TT)) {
+ if (Ctx->shouldAddDefaultTargetPasses(G->getTargetTriple())) {
// Add eh-frame passses.
Config.PrePrunePasses.push_back(EHFrameSplitter("__eh_frame"));
Config.PrePrunePasses.push_back(
EHFrameEdgeFixer("__eh_frame", NegDelta32, Delta64, Delta64));
// Add a mark-live pass.
- if (auto MarkLive = Ctx->getMarkLivePass(TT))
+ if (auto MarkLive = Ctx->getMarkLivePass(G->getTargetTriple()))
Config.PrePrunePasses.push_back(std::move(MarkLive));
else
Config.PrePrunePasses.push_back(markAllSymbolsLive);
@@ -686,11 +688,11 @@ void jitLink_MachO_x86_64(std::unique_ptr<JITLinkContext> Ctx) {
Config.PostAllocationPasses.push_back(optimizeMachO_x86_64_GOTAndStubs);
}
- if (auto Err = Ctx->modifyPassConfig(TT, Config))
+ if (auto Err = Ctx->modifyPassConfig(G->getTargetTriple(), Config))
return Ctx->notifyFailed(std::move(Err));
// Construct a JITLinker and run the link function.
- MachOJITLinker_x86_64::link(std::move(Ctx), std::move(Config));
+ MachOJITLinker_x86_64::link(std::move(Ctx), std::move(G), std::move(Config));
}
StringRef getMachOX86RelocationKindName(Edge::Kind R) {
diff --git a/llvm/lib/ExecutionEngine/Orc/ObjectLinkingLayer.cpp b/llvm/lib/ExecutionEngine/Orc/ObjectLinkingLayer.cpp
index f8eb1dcfce41..161a30e44616 100644
--- a/llvm/lib/ExecutionEngine/Orc/ObjectLinkingLayer.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/ObjectLinkingLayer.cpp
@@ -34,16 +34,12 @@ class ObjectLinkingLayerJITLinkContext final : public JITLinkContext {
~ObjectLinkingLayerJITLinkContext() {
// If there is an object buffer return function then use it to
// return ownership of the buffer.
- if (Layer.ReturnObjectBuffer)
+ if (Layer.ReturnObjectBuffer && ObjBuffer)
Layer.ReturnObjectBuffer(std::move(ObjBuffer));
}
JITLinkMemoryManager &getMemoryManager() override { return Layer.MemMgr; }
- MemoryBufferRef getObjectBuffer() const override {
- return ObjBuffer->getMemBufferRef();
- }
-
void notifyFailed(Error Err) override {
for (auto &P : Layer.Plugins)
Err = joinErrors(std::move(Err), P->notifyFailed(*MR));
@@ -463,8 +459,19 @@ ObjectLinkingLayer::~ObjectLinkingLayer() {
void ObjectLinkingLayer::emit(std::unique_ptr<MaterializationResponsibility> R,
std::unique_ptr<MemoryBuffer> O) {
assert(O && "Object must not be null");
- jitLink(std::make_unique<ObjectLinkingLayerJITLinkContext>(
- *this, std::move(R), std::move(O)));
+ auto ObjBuffer = O->getMemBufferRef();
+ auto Ctx = std::make_unique<ObjectLinkingLayerJITLinkContext>(
+ *this, std::move(R), std::move(O));
+ if (auto G = createLinkGraphFromObject(std::move(ObjBuffer)))
+ link(std::move(*G), std::move(Ctx));
+ else
+ Ctx->notifyFailed(G.takeError());
+}
+
+void ObjectLinkingLayer::emit(std::unique_ptr<MaterializationResponsibility> R,
+ std::unique_ptr<LinkGraph> G) {
+ link(std::move(G), std::make_unique<ObjectLinkingLayerJITLinkContext>(
+ *this, std::move(R), nullptr));
}
void ObjectLinkingLayer::modifyPassConfig(MaterializationResponsibility &MR,
diff --git a/llvm/unittests/ExecutionEngine/JITLink/LinkGraphTests.cpp b/llvm/unittests/ExecutionEngine/JITLink/LinkGraphTests.cpp
index 0c2d1b63ad4d..360bc8811f1e 100644
--- a/llvm/unittests/ExecutionEngine/JITLink/LinkGraphTests.cpp
+++ b/llvm/unittests/ExecutionEngine/JITLink/LinkGraphTests.cpp
@@ -20,8 +20,9 @@ static auto RWFlags =
TEST(LinkGraphTest, Construction) {
// Check that LinkGraph construction works as expected.
- LinkGraph G("foo", 8, support::little);
+ LinkGraph G("foo", Triple("x86_64-apple-darwin"), 8, support::little);
EXPECT_EQ(G.getName(), "foo");
+ EXPECT_EQ(G.getTargetTriple().str(), "x86_64-apple-darwin");
EXPECT_EQ(G.getPointerSize(), 8U);
EXPECT_EQ(G.getEndianness(), support::little);
EXPECT_TRUE(llvm::empty(G.external_symbols()));
@@ -38,7 +39,7 @@ TEST(LinkGraphTest, BlockAndSymbolIteration) {
0x1C, 0x1D, 0x1E, 0x1F, 0x00};
StringRef BlockContent(BlockContentBytes);
- LinkGraph G("foo", 8, support::little);
+ LinkGraph G("foo", Triple("x86_64-apple-darwin"), 8, support::little);
auto &Sec1 = G.createSection("__data.1", RWFlags);
auto &B1 = G.createContentBlock(Sec1, BlockContent, 0x1000, 8, 0);
auto &B2 = G.createContentBlock(Sec1, BlockContent, 0x2000, 8, 0);
@@ -90,7 +91,7 @@ TEST(LinkGraphTest, SplitBlock) {
0x1C, 0x1D, 0x1E, 0x1F, 0x00};
StringRef BlockContent(BlockContentBytes);
- LinkGraph G("foo", 8, support::little);
+ LinkGraph G("foo", Triple("x86_64-apple-darwin"), 8, support::little);
auto &Sec = G.createSection("__data", RWFlags);
// Create the block to split.
More information about the llvm-branch-commits
mailing list