Update prebuilt Clang to r365631c1 from Android.
The version we had was segfaulting.
Bug: 132420445
Change-Id: Icb45a6fe0b4e2166f7895e669df1157cec9fb4e0
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/JITLink/EHFrameSupport.h b/linux-x64/clang/include/llvm/ExecutionEngine/JITLink/EHFrameSupport.h
new file mode 100644
index 0000000..8d2f641
--- /dev/null
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/JITLink/EHFrameSupport.h
@@ -0,0 +1,80 @@
+//===--------- EHFrameSupport.h - JITLink eh-frame utils --------*- C++ -*-===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+// EHFrame registration support for JITLink.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_EXECUTIONENGINE_JITLINK_EHFRAMESUPPORT_H
+#define LLVM_EXECUTIONENGINE_JITLINK_EHFRAMESUPPORT_H
+
+#include "llvm/ADT/Triple.h"
+#include "llvm/ExecutionEngine/JITLink/JITLink.h"
+#include "llvm/ExecutionEngine/JITSymbol.h"
+#include "llvm/Support/Error.h"
+
+namespace llvm {
+namespace jitlink {
+
+/// Registers all FDEs in the given eh-frame section with the current process.
+Error registerEHFrameSection(const void *EHFrameSectionAddr);
+
+/// Deregisters all FDEs in the given eh-frame section with the current process.
+Error deregisterEHFrameSection(const void *EHFrameSectionAddr);
+
+/// Supports registration/deregistration of EH-frames in a target process.
+class EHFrameRegistrar {
+public:
+ virtual ~EHFrameRegistrar();
+ virtual Error registerEHFrames(JITTargetAddress EHFrameSectionAddr) = 0;
+ virtual Error deregisterEHFrames(JITTargetAddress EHFrameSectionAddr) = 0;
+};
+
+/// Registers / Deregisters EH-frames in the current process.
+class InProcessEHFrameRegistrar final : public EHFrameRegistrar {
+public:
+ /// Get a reference to the InProcessEHFrameRegistrar singleton.
+ static InProcessEHFrameRegistrar &getInstance();
+
+ InProcessEHFrameRegistrar(const InProcessEHFrameRegistrar &) = delete;
+ InProcessEHFrameRegistrar &
+ operator=(const InProcessEHFrameRegistrar &) = delete;
+
+ InProcessEHFrameRegistrar(InProcessEHFrameRegistrar &&) = delete;
+ InProcessEHFrameRegistrar &operator=(InProcessEHFrameRegistrar &&) = delete;
+
+ Error registerEHFrames(JITTargetAddress EHFrameSectionAddr) override {
+ return registerEHFrameSection(
+ jitTargetAddressToPointer<void *>(EHFrameSectionAddr));
+ }
+
+ Error deregisterEHFrames(JITTargetAddress EHFrameSectionAddr) override {
+ return deregisterEHFrameSection(
+ jitTargetAddressToPointer<void *>(EHFrameSectionAddr));
+ }
+
+private:
+ InProcessEHFrameRegistrar();
+};
+
+using StoreFrameAddressFunction = std::function<void(JITTargetAddress)>;
+
+/// Creates a pass that records the address of the EH frame section. If no
+/// eh-frame section is found, it will set EHFrameAddr to zero.
+///
+/// Authors of JITLinkContexts can use this function to register a post-fixup
+/// pass that records the address of the eh-frame section. This address can
+/// be used after finalization to register and deregister the frame.
+AtomGraphPassFunction
+createEHFrameRecorderPass(const Triple &TT,
+ StoreFrameAddressFunction StoreFrameAddress);
+
+} // end namespace jitlink
+} // end namespace llvm
+
+#endif // LLVM_EXECUTIONENGINE_JITLINK_EHFRAMESUPPORT_H
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/JITLink/JITLink.h b/linux-x64/clang/include/llvm/ExecutionEngine/JITLink/JITLink.h
new file mode 100644
index 0000000..be80d44
--- /dev/null
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/JITLink/JITLink.h
@@ -0,0 +1,930 @@
+//===------------ JITLink.h - JIT linker functionality ----------*- C++ -*-===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+// Contains generic JIT-linker types.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_EXECUTIONENGINE_JITLINK_JITLINK_H
+#define LLVM_EXECUTIONENGINE_JITLINK_JITLINK_H
+
+#include "JITLinkMemoryManager.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/ExecutionEngine/JITSymbol.h"
+#include "llvm/Support/Allocator.h"
+#include "llvm/Support/Endian.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/FormatVariadic.h"
+#include "llvm/Support/MathExtras.h"
+#include "llvm/Support/Memory.h"
+#include "llvm/Support/MemoryBuffer.h"
+
+#include <map>
+#include <string>
+#include <system_error>
+
+namespace llvm {
+namespace jitlink {
+
+/// Base class for errors originating in JIT linker, e.g. missing relocation
+/// support.
+class JITLinkError : public ErrorInfo<JITLinkError> {
+public:
+ static char ID;
+
+ JITLinkError(Twine ErrMsg) : ErrMsg(ErrMsg.str()) {}
+
+ void log(raw_ostream &OS) const override;
+ const std::string &getErrorMessage() const { return ErrMsg; }
+ std::error_code convertToErrorCode() const override;
+
+private:
+ std::string ErrMsg;
+};
+
+// Forward declare the Atom class.
+class Atom;
+
+/// Edge class. Represents both object file relocations, as well as layout and
+/// keep-alive constraints.
+class Edge {
+public:
+ using Kind = uint8_t;
+
+ using GenericEdgeKind = enum : Kind {
+ Invalid, // Invalid edge value.
+ FirstKeepAlive, // Keeps target alive. Offset/addend zero.
+ KeepAlive = FirstKeepAlive, // Tag first edge kind that preserves liveness.
+ LayoutNext, // Layout constraint. Offset/Addend zero.
+ FirstRelocation // First architecture specific relocation.
+ };
+
+ using OffsetT = uint32_t;
+ using AddendT = int64_t;
+
+ Edge(Kind K, OffsetT Offset, Atom &Target, AddendT Addend)
+ : Target(&Target), Offset(Offset), Addend(Addend), K(K) {}
+
+ OffsetT getOffset() const { return Offset; }
+ Kind getKind() const { return K; }
+ void setKind(Kind K) { this->K = K; }
+ bool isRelocation() const { return K >= FirstRelocation; }
+ Kind getRelocation() const {
+ assert(isRelocation() && "Not a relocation edge");
+ return K - FirstRelocation;
+ }
+ bool isKeepAlive() const { return K >= FirstKeepAlive; }
+ Atom &getTarget() const { return *Target; }
+ void setTarget(Atom &Target) { this->Target = &Target; }
+ AddendT getAddend() const { return Addend; }
+ void setAddend(AddendT Addend) { this->Addend = Addend; }
+
+private:
+ Atom *Target;
+ OffsetT Offset;
+ AddendT Addend;
+ Kind K = 0;
+};
+
+using EdgeVector = std::vector<Edge>;
+
+const StringRef getGenericEdgeKindName(Edge::Kind K);
+
+/// Base Atom class. Used by absolute and undefined atoms.
+class Atom {
+ friend class AtomGraph;
+
+protected:
+ /// Create a named (as yet unresolved) atom.
+ Atom(StringRef Name)
+ : Name(Name), IsDefined(false), IsLive(false), ShouldDiscard(false),
+ IsGlobal(false), IsAbsolute(false), IsCallable(false),
+ IsExported(false), IsWeak(false), HasLayoutNext(false),
+ IsCommon(false) {}
+
+ /// Create an absolute symbol atom.
+ Atom(StringRef Name, JITTargetAddress Address)
+ : Name(Name), Address(Address), IsDefined(true), IsLive(false),
+ ShouldDiscard(false), IsGlobal(false), IsAbsolute(false),
+ IsCallable(false), IsExported(false), IsWeak(false),
+ HasLayoutNext(false), IsCommon(false) {}
+
+public:
+ /// Returns true if this atom has a name.
+ bool hasName() const { return Name != StringRef(); }
+
+ /// Returns the name of this atom.
+ StringRef getName() const { return Name; }
+
+ /// Returns the current target address of this atom.
+ /// The initial target address (for atoms that have one) will be taken from
+ /// the input object file's virtual address space. During the layout phase
+ /// of JIT linking the atom's address will be updated to point to its final
+ /// address in the JIT'd process.
+ JITTargetAddress getAddress() const { return Address; }
+
+ /// Set the current target address of this atom.
+ void setAddress(JITTargetAddress Address) { this->Address = Address; }
+
+ /// Returns true if this is a defined atom.
+ bool isDefined() const { return IsDefined; }
+
+ /// Returns true if this atom is marked as live.
+ bool isLive() const { return IsLive; }
+
+ /// Mark this atom as live.
+ ///
+ /// Note: Only defined and absolute atoms can be marked live.
+ void setLive(bool IsLive) {
+ assert((IsDefined || IsAbsolute || !IsLive) &&
+ "Only defined and absolute atoms can be marked live");
+ this->IsLive = IsLive;
+ }
+
+ /// Returns true if this atom should be discarded during pruning.
+ bool shouldDiscard() const { return ShouldDiscard; }
+
+ /// Mark this atom to be discarded.
+ ///
+ /// Note: Only defined and absolute atoms can be marked live.
+ void setShouldDiscard(bool ShouldDiscard) {
+ assert((IsDefined || IsAbsolute || !ShouldDiscard) &&
+ "Only defined and absolute atoms can be marked live");
+ this->ShouldDiscard = ShouldDiscard;
+ }
+
+ /// Returns true if this definition is global (i.e. visible outside this
+ /// linkage unit).
+ ///
+ /// Note: This is distict from Exported, which means visibile outside the
+ /// JITDylib that this graph is being linked in to.
+ bool isGlobal() const { return IsGlobal; }
+
+ /// Mark this atom as global.
+ void setGlobal(bool IsGlobal) { this->IsGlobal = IsGlobal; }
+
+ /// Returns true if this atom represents an absolute symbol.
+ bool isAbsolute() const { return IsAbsolute; }
+
+ /// Returns true if this atom is known to be callable.
+ ///
+ /// Primarily provided for easy interoperability with ORC, which uses the
+ /// JITSymbolFlags::Common flag to identify symbols that can be interposed
+ /// with stubs.
+ bool isCallable() const { return IsCallable; }
+
+ /// Mark this atom as callable.
+ void setCallable(bool IsCallable) {
+ assert((IsDefined || IsAbsolute || !IsCallable) &&
+ "Callable atoms must be defined or absolute");
+ this->IsCallable = IsCallable;
+ }
+
+ /// Returns true if this atom should appear in the symbol table of a final
+ /// linked image.
+ bool isExported() const { return IsExported; }
+
+ /// Mark this atom as exported.
+ void setExported(bool IsExported) {
+ assert((!IsExported || ((IsDefined || IsAbsolute) && hasName())) &&
+ "Exported atoms must have names");
+ this->IsExported = IsExported;
+ }
+
+ /// Returns true if this is a weak symbol.
+ bool isWeak() const { return IsWeak; }
+
+ /// Mark this atom as weak.
+ void setWeak(bool IsWeak) { this->IsWeak = IsWeak; }
+
+private:
+ StringRef Name;
+ JITTargetAddress Address = 0;
+
+ bool IsDefined : 1;
+ bool IsLive : 1;
+ bool ShouldDiscard : 1;
+
+ bool IsGlobal : 1;
+ bool IsAbsolute : 1;
+ bool IsCallable : 1;
+ bool IsExported : 1;
+ bool IsWeak : 1;
+
+protected:
+ // These flags only make sense for DefinedAtom, but we can minimize the size
+ // of DefinedAtom by defining them here.
+ bool HasLayoutNext : 1;
+ bool IsCommon : 1;
+};
+
+// Forward declare DefinedAtom.
+class DefinedAtom;
+
+raw_ostream &operator<<(raw_ostream &OS, const Atom &A);
+void printEdge(raw_ostream &OS, const Atom &FixupAtom, const Edge &E,
+ StringRef EdgeKindName);
+
+/// Represents a section address range via a pair of DefinedAtom pointers to
+/// the first and last atoms in the section.
+class SectionRange {
+public:
+ SectionRange() = default;
+ SectionRange(DefinedAtom *First, DefinedAtom *Last)
+ : First(First), Last(Last) {}
+ DefinedAtom *getFirstAtom() const {
+ assert((!Last || First) && "First can not be null if end is non-null");
+ return First;
+ }
+ DefinedAtom *getLastAtom() const {
+ assert((First || !Last) && "Last can not be null if start is non-null");
+ return Last;
+ }
+ bool isEmpty() const {
+ assert((First || !Last) && "Last can not be null if start is non-null");
+ return !First;
+ }
+ JITTargetAddress getStart() const;
+ JITTargetAddress getEnd() const;
+ uint64_t getSize() const;
+
+private:
+ DefinedAtom *First = nullptr;
+ DefinedAtom *Last = nullptr;
+};
+
+/// Represents an object file section.
+class Section {
+ friend class AtomGraph;
+
+private:
+ Section(StringRef Name, uint32_t Alignment, sys::Memory::ProtectionFlags Prot,
+ unsigned Ordinal, bool IsZeroFill)
+ : Name(Name), Alignment(Alignment), Prot(Prot), Ordinal(Ordinal),
+ IsZeroFill(IsZeroFill) {
+ assert(isPowerOf2_32(Alignment) && "Alignments must be a power of 2");
+ }
+
+ using DefinedAtomSet = DenseSet<DefinedAtom *>;
+
+public:
+ using atom_iterator = DefinedAtomSet::iterator;
+ using const_atom_iterator = DefinedAtomSet::const_iterator;
+
+ ~Section();
+ StringRef getName() const { return Name; }
+ uint32_t getAlignment() const { return Alignment; }
+ sys::Memory::ProtectionFlags getProtectionFlags() const { return Prot; }
+ unsigned getSectionOrdinal() const { return Ordinal; }
+ size_t getNextAtomOrdinal() { return ++NextAtomOrdinal; }
+
+ bool isZeroFill() const { return IsZeroFill; }
+
+ /// Returns an iterator over the atoms in the section (in no particular
+ /// order).
+ iterator_range<atom_iterator> atoms() {
+ return make_range(DefinedAtoms.begin(), DefinedAtoms.end());
+ }
+
+ /// Returns an iterator over the atoms in the section (in no particular
+ /// order).
+ iterator_range<const_atom_iterator> atoms() const {
+ return make_range(DefinedAtoms.begin(), DefinedAtoms.end());
+ }
+
+ /// Return the number of atoms in this section.
+ DefinedAtomSet::size_type atoms_size() { return DefinedAtoms.size(); }
+
+ /// Return true if this section contains no atoms.
+ bool atoms_empty() const { return DefinedAtoms.empty(); }
+
+ /// Returns the range of this section as the pair of atoms with the lowest
+ /// and highest target address. This operation is expensive, as it
+ /// must traverse all atoms in the section.
+ ///
+ /// Note: If the section is empty, both values will be null. The section
+ /// address will evaluate to null, and the size to zero. If the section
+ /// contains a single atom both values will point to it, the address will
+ /// evaluate to the address of that atom, and the size will be the size of
+ /// that atom.
+ SectionRange getRange() const;
+
+private:
+ void addAtom(DefinedAtom &DA) {
+ assert(!DefinedAtoms.count(&DA) && "Atom is already in this section");
+ DefinedAtoms.insert(&DA);
+ }
+
+ void removeAtom(DefinedAtom &DA) {
+ assert(DefinedAtoms.count(&DA) && "Atom is not in this section");
+ DefinedAtoms.erase(&DA);
+ }
+
+ StringRef Name;
+ uint32_t Alignment = 0;
+ sys::Memory::ProtectionFlags Prot;
+ unsigned Ordinal = 0;
+ unsigned NextAtomOrdinal = 0;
+ bool IsZeroFill = false;
+ DefinedAtomSet DefinedAtoms;
+};
+
+/// Defined atom class. Suitable for use by defined named and anonymous
+/// atoms.
+class DefinedAtom : public Atom {
+ friend class AtomGraph;
+
+private:
+ DefinedAtom(Section &Parent, JITTargetAddress Address, uint32_t Alignment)
+ : Atom("", Address), Parent(Parent), Ordinal(Parent.getNextAtomOrdinal()),
+ Alignment(Alignment) {
+ assert(isPowerOf2_32(Alignment) && "Alignments must be a power of two");
+ }
+
+ DefinedAtom(Section &Parent, StringRef Name, JITTargetAddress Address,
+ uint32_t Alignment)
+ : Atom(Name, Address), Parent(Parent),
+ Ordinal(Parent.getNextAtomOrdinal()), Alignment(Alignment) {
+ assert(isPowerOf2_32(Alignment) && "Alignments must be a power of two");
+ }
+
+public:
+ using edge_iterator = EdgeVector::iterator;
+
+ Section &getSection() const { return Parent; }
+
+ uint64_t getSize() const { return Size; }
+
+ StringRef getContent() const {
+ assert(!Parent.isZeroFill() && "Trying to get content for zero-fill atom");
+ assert(Size <= std::numeric_limits<size_t>::max() &&
+ "Content size too large");
+ return {ContentPtr, static_cast<size_t>(Size)};
+ }
+ void setContent(StringRef Content) {
+ assert(!Parent.isZeroFill() && "Calling setContent on zero-fill atom?");
+ ContentPtr = Content.data();
+ Size = Content.size();
+ }
+
+ bool isZeroFill() const { return Parent.isZeroFill(); }
+
+ void setZeroFill(uint64_t Size) {
+ assert(Parent.isZeroFill() && !ContentPtr &&
+ "Can't set zero-fill length of a non zero-fill atom");
+ this->Size = Size;
+ }
+
+ uint64_t getZeroFillSize() const {
+ assert(Parent.isZeroFill() &&
+ "Can't get zero-fill length of a non zero-fill atom");
+ return Size;
+ }
+
+ uint32_t getAlignment() const { return Alignment; }
+
+ bool hasLayoutNext() const { return HasLayoutNext; }
+ void setLayoutNext(DefinedAtom &Next) {
+ assert(!HasLayoutNext && "Atom already has layout-next constraint");
+ HasLayoutNext = true;
+ Edges.push_back(Edge(Edge::LayoutNext, 0, Next, 0));
+ }
+ DefinedAtom &getLayoutNext() {
+ assert(HasLayoutNext && "Atom does not have a layout-next constraint");
+ DefinedAtom *Next = nullptr;
+ for (auto &E : edges())
+ if (E.getKind() == Edge::LayoutNext) {
+ assert(E.getTarget().isDefined() &&
+ "layout-next target atom must be a defined atom");
+ Next = static_cast<DefinedAtom *>(&E.getTarget());
+ break;
+ }
+ assert(Next && "Missing LayoutNext edge");
+ return *Next;
+ }
+
+ bool isCommon() const { return IsCommon; }
+
+ void addEdge(Edge::Kind K, Edge::OffsetT Offset, Atom &Target,
+ Edge::AddendT Addend) {
+ assert(K != Edge::LayoutNext &&
+ "Layout edges should be added via setLayoutNext");
+ Edges.push_back(Edge(K, Offset, Target, Addend));
+ }
+
+ iterator_range<edge_iterator> edges() {
+ return make_range(Edges.begin(), Edges.end());
+ }
+ size_t edges_size() const { return Edges.size(); }
+ bool edges_empty() const { return Edges.empty(); }
+
+ unsigned getOrdinal() const { return Ordinal; }
+
+private:
+ void setCommon(uint64_t Size) {
+ assert(ContentPtr == 0 && "Atom already has content?");
+ IsCommon = true;
+ setZeroFill(Size);
+ }
+
+ EdgeVector Edges;
+ uint64_t Size = 0;
+ Section &Parent;
+ const char *ContentPtr = nullptr;
+ unsigned Ordinal = 0;
+ uint32_t Alignment = 0;
+};
+
+inline JITTargetAddress SectionRange::getStart() const {
+ return First ? First->getAddress() : 0;
+}
+
+inline JITTargetAddress SectionRange::getEnd() const {
+ return Last ? Last->getAddress() + Last->getSize() : 0;
+}
+
+inline uint64_t SectionRange::getSize() const { return getEnd() - getStart(); }
+
+inline SectionRange Section::getRange() const {
+ if (atoms_empty())
+ return SectionRange();
+ DefinedAtom *First = *DefinedAtoms.begin(), *Last = *DefinedAtoms.begin();
+ for (auto *DA : atoms()) {
+ if (DA->getAddress() < First->getAddress())
+ First = DA;
+ if (DA->getAddress() > Last->getAddress())
+ Last = DA;
+ }
+ return SectionRange(First, Last);
+}
+
+class AtomGraph {
+private:
+ using SectionList = std::vector<std::unique_ptr<Section>>;
+ using AddressToAtomMap = std::map<JITTargetAddress, DefinedAtom *>;
+ using NamedAtomMap = DenseMap<StringRef, Atom *>;
+ using ExternalAtomSet = DenseSet<Atom *>;
+
+public:
+ using external_atom_iterator = ExternalAtomSet::iterator;
+
+ using section_iterator = pointee_iterator<SectionList::iterator>;
+ using const_section_iterator = pointee_iterator<SectionList::const_iterator>;
+
+ template <typename SecItrT, typename AtomItrT, typename T>
+ class defined_atom_iterator_impl
+ : public iterator_facade_base<
+ defined_atom_iterator_impl<SecItrT, AtomItrT, T>,
+ std::forward_iterator_tag, T> {
+ public:
+ defined_atom_iterator_impl() = default;
+
+ defined_atom_iterator_impl(SecItrT SI, SecItrT SE)
+ : SI(SI), SE(SE),
+ AI(SI != SE ? SI->atoms().begin() : Section::atom_iterator()) {
+ moveToNextAtomOrEnd();
+ }
+
+ bool operator==(const defined_atom_iterator_impl &RHS) const {
+ return (SI == RHS.SI) && (AI == RHS.AI);
+ }
+
+ T operator*() const {
+ assert(AI != SI->atoms().end() && "Dereferencing end?");
+ return *AI;
+ }
+
+ defined_atom_iterator_impl operator++() {
+ ++AI;
+ moveToNextAtomOrEnd();
+ return *this;
+ }
+
+ private:
+ void moveToNextAtomOrEnd() {
+ while (SI != SE && AI == SI->atoms().end()) {
+ ++SI;
+ if (SI == SE)
+ AI = Section::atom_iterator();
+ else
+ AI = SI->atoms().begin();
+ }
+ }
+
+ SecItrT SI, SE;
+ AtomItrT AI;
+ };
+
+ using defined_atom_iterator =
+ defined_atom_iterator_impl<section_iterator, Section::atom_iterator,
+ DefinedAtom *>;
+
+ using const_defined_atom_iterator =
+ defined_atom_iterator_impl<const_section_iterator,
+ Section::const_atom_iterator,
+ const DefinedAtom *>;
+
+ AtomGraph(std::string Name, unsigned PointerSize,
+ support::endianness Endianness)
+ : Name(std::move(Name)), 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 pointer size for use in this graph.
+ unsigned getPointerSize() const { return PointerSize; }
+
+ /// Returns the endianness of atom-content in this graph.
+ support::endianness getEndianness() const { return Endianness; }
+
+ /// Create a section with the given name, protection flags, and alignment.
+ Section &createSection(StringRef Name, uint32_t Alignment,
+ sys::Memory::ProtectionFlags Prot, bool IsZeroFill) {
+ std::unique_ptr<Section> Sec(
+ new Section(Name, Alignment, Prot, Sections.size(), IsZeroFill));
+ Sections.push_back(std::move(Sec));
+ return *Sections.back();
+ }
+
+ /// Add an external atom representing an undefined symbol in this graph.
+ Atom &addExternalAtom(StringRef Name) {
+ assert(!NamedAtoms.count(Name) && "Duplicate named atom inserted");
+ Atom *A = reinterpret_cast<Atom *>(
+ AtomAllocator.Allocate(sizeof(Atom), alignof(Atom)));
+ new (A) Atom(Name);
+ ExternalAtoms.insert(A);
+ NamedAtoms[Name] = A;
+ return *A;
+ }
+
+ /// Add an external atom representing an absolute symbol.
+ Atom &addAbsoluteAtom(StringRef Name, JITTargetAddress Addr) {
+ assert(!NamedAtoms.count(Name) && "Duplicate named atom inserted");
+ Atom *A = reinterpret_cast<Atom *>(
+ AtomAllocator.Allocate(sizeof(Atom), alignof(Atom)));
+ new (A) Atom(Name, Addr);
+ AbsoluteAtoms.insert(A);
+ NamedAtoms[Name] = A;
+ return *A;
+ }
+
+ /// Add an anonymous defined atom to the graph.
+ ///
+ /// Anonymous atoms have content but no name. They must have an address.
+ DefinedAtom &addAnonymousAtom(Section &Parent, JITTargetAddress Address,
+ uint32_t Alignment) {
+ DefinedAtom *A = reinterpret_cast<DefinedAtom *>(
+ AtomAllocator.Allocate(sizeof(DefinedAtom), alignof(DefinedAtom)));
+ new (A) DefinedAtom(Parent, Address, Alignment);
+ Parent.addAtom(*A);
+ getAddrToAtomMap()[A->getAddress()] = A;
+ return *A;
+ }
+
+ /// Add a defined atom to the graph.
+ ///
+ /// Allocates and constructs a DefinedAtom instance with the given parent,
+ /// name, address, and alignment.
+ DefinedAtom &addDefinedAtom(Section &Parent, StringRef Name,
+ JITTargetAddress Address, uint32_t Alignment) {
+ assert(!NamedAtoms.count(Name) && "Duplicate named atom inserted");
+ DefinedAtom *A = reinterpret_cast<DefinedAtom *>(
+ AtomAllocator.Allocate(sizeof(DefinedAtom), alignof(DefinedAtom)));
+ new (A) DefinedAtom(Parent, Name, Address, Alignment);
+ Parent.addAtom(*A);
+ getAddrToAtomMap()[A->getAddress()] = A;
+ NamedAtoms[Name] = A;
+ return *A;
+ }
+
+ /// Add a common symbol atom to the graph.
+ ///
+ /// Adds a common-symbol atom to the graph with the given parent, name,
+ /// address, alignment and size.
+ DefinedAtom &addCommonAtom(Section &Parent, StringRef Name,
+ JITTargetAddress Address, uint32_t Alignment,
+ uint64_t Size) {
+ assert(!NamedAtoms.count(Name) && "Duplicate named atom inserted");
+ DefinedAtom *A = reinterpret_cast<DefinedAtom *>(
+ AtomAllocator.Allocate(sizeof(DefinedAtom), alignof(DefinedAtom)));
+ new (A) DefinedAtom(Parent, Name, Address, Alignment);
+ A->setCommon(Size);
+ Parent.addAtom(*A);
+ NamedAtoms[Name] = A;
+ return *A;
+ }
+
+ iterator_range<section_iterator> sections() {
+ return make_range(section_iterator(Sections.begin()),
+ section_iterator(Sections.end()));
+ }
+
+ /// Returns the section with the given name if it exists, otherwise returns
+ /// null.
+ Section *findSectionByName(StringRef Name) {
+ for (auto &S : sections())
+ if (S.getName() == Name)
+ return &S;
+ return nullptr;
+ }
+
+ iterator_range<external_atom_iterator> external_atoms() {
+ return make_range(ExternalAtoms.begin(), ExternalAtoms.end());
+ }
+
+ iterator_range<external_atom_iterator> absolute_atoms() {
+ return make_range(AbsoluteAtoms.begin(), AbsoluteAtoms.end());
+ }
+
+ iterator_range<defined_atom_iterator> defined_atoms() {
+ return make_range(defined_atom_iterator(Sections.begin(), Sections.end()),
+ defined_atom_iterator(Sections.end(), Sections.end()));
+ }
+
+ iterator_range<const_defined_atom_iterator> defined_atoms() const {
+ return make_range(
+ const_defined_atom_iterator(Sections.begin(), Sections.end()),
+ const_defined_atom_iterator(Sections.end(), Sections.end()));
+ }
+
+ /// Returns the atom with the given name, which must exist in this graph.
+ Atom &getAtomByName(StringRef Name) {
+ auto I = NamedAtoms.find(Name);
+ assert(I != NamedAtoms.end() && "Name not in NamedAtoms map");
+ return *I->second;
+ }
+
+ /// Returns the atom with the given name, which must exist in this graph and
+ /// be a DefinedAtom.
+ DefinedAtom &getDefinedAtomByName(StringRef Name) {
+ auto &A = getAtomByName(Name);
+ assert(A.isDefined() && "Atom is not a defined atom");
+ return static_cast<DefinedAtom &>(A);
+ }
+
+ /// Search for the given atom by name.
+ /// Returns the atom (if found) or an error (if no atom with this name
+ /// exists).
+ Expected<Atom &> findAtomByName(StringRef Name) {
+ auto I = NamedAtoms.find(Name);
+ if (I == NamedAtoms.end())
+ return make_error<JITLinkError>("No atom named " + Name);
+ return *I->second;
+ }
+
+ /// Search for the given defined atom by name.
+ /// Returns the defined atom (if found) or an error (if no atom with this
+ /// name exists, or if one exists but is not a defined atom).
+ Expected<DefinedAtom &> findDefinedAtomByName(StringRef Name) {
+ auto I = NamedAtoms.find(Name);
+ if (I == NamedAtoms.end())
+ return make_error<JITLinkError>("No atom named " + Name);
+ if (!I->second->isDefined())
+ return make_error<JITLinkError>("Atom " + Name +
+ " exists but is not a "
+ "defined atom");
+ return static_cast<DefinedAtom &>(*I->second);
+ }
+
+ /// Returns the atom covering the given address, or an error if no such atom
+ /// exists.
+ ///
+ /// Returns null if no atom exists at the given address.
+ DefinedAtom *getAtomByAddress(JITTargetAddress Address) {
+ refreshAddrToAtomCache();
+
+ // If there are no defined atoms, bail out early.
+ if (AddrToAtomCache->empty())
+ return nullptr;
+
+ // Find the atom *after* the given address.
+ auto I = AddrToAtomCache->upper_bound(Address);
+
+ // If this address falls before any known atom, bail out.
+ if (I == AddrToAtomCache->begin())
+ return nullptr;
+
+ // The atom we're looking for is the one before the atom we found.
+ --I;
+
+ // Otherwise range check the atom that was found.
+ assert(!I->second->getContent().empty() && "Atom content not set");
+ if (Address >= I->second->getAddress() + I->second->getContent().size())
+ return nullptr;
+
+ return I->second;
+ }
+
+ /// Like getAtomByAddress, but returns an Error if the given address is not
+ /// covered by an atom, rather than a null pointer.
+ Expected<DefinedAtom &> findAtomByAddress(JITTargetAddress Address) {
+ if (auto *DA = getAtomByAddress(Address))
+ return *DA;
+ return make_error<JITLinkError>("No atom at address " +
+ formatv("{0:x16}", Address));
+ }
+
+ // Remove the given external atom from the graph.
+ void removeExternalAtom(Atom &A) {
+ assert(!A.isDefined() && !A.isAbsolute() && "A is not an external atom");
+ assert(ExternalAtoms.count(&A) && "A is not in the external atoms set");
+ ExternalAtoms.erase(&A);
+ A.~Atom();
+ }
+
+ /// Remove the given absolute atom from the graph.
+ void removeAbsoluteAtom(Atom &A) {
+ assert(A.isAbsolute() && "A is not an absolute atom");
+ assert(AbsoluteAtoms.count(&A) && "A is not in the absolute atoms set");
+ AbsoluteAtoms.erase(&A);
+ A.~Atom();
+ }
+
+ /// Remove the given defined atom from the graph.
+ void removeDefinedAtom(DefinedAtom &DA) {
+ if (AddrToAtomCache) {
+ assert(AddrToAtomCache->count(DA.getAddress()) &&
+ "Cache exists, but does not contain atom");
+ AddrToAtomCache->erase(DA.getAddress());
+ }
+ if (DA.hasName()) {
+ assert(NamedAtoms.count(DA.getName()) && "Named atom not in map");
+ NamedAtoms.erase(DA.getName());
+ }
+ DA.getSection().removeAtom(DA);
+ DA.~DefinedAtom();
+ }
+
+ /// Invalidate the atom-to-address map.
+ void invalidateAddrToAtomMap() { AddrToAtomCache = None; }
+
+ /// Dump the graph.
+ ///
+ /// If supplied, the EdgeKindToName function will be used to name edge
+ /// kinds in the debug output. Otherwise raw edge kind numbers will be
+ /// displayed.
+ void dump(raw_ostream &OS,
+ std::function<StringRef(Edge::Kind)> EdegKindToName =
+ std::function<StringRef(Edge::Kind)>());
+
+private:
+ AddressToAtomMap &getAddrToAtomMap() {
+ refreshAddrToAtomCache();
+ return *AddrToAtomCache;
+ }
+
+ const AddressToAtomMap &getAddrToAtomMap() const {
+ refreshAddrToAtomCache();
+ return *AddrToAtomCache;
+ }
+
+ void refreshAddrToAtomCache() const {
+ if (!AddrToAtomCache) {
+ AddrToAtomCache = AddressToAtomMap();
+ for (auto *DA : defined_atoms())
+ (*AddrToAtomCache)[DA->getAddress()] = const_cast<DefinedAtom *>(DA);
+ }
+ }
+
+ // Put the BumpPtrAllocator first so that we don't free any of the atoms in
+ // it until all of their destructors have been run.
+ BumpPtrAllocator AtomAllocator;
+
+ std::string Name;
+ unsigned PointerSize;
+ support::endianness Endianness;
+ SectionList Sections;
+ NamedAtomMap NamedAtoms;
+ ExternalAtomSet ExternalAtoms;
+ ExternalAtomSet AbsoluteAtoms;
+ mutable Optional<AddressToAtomMap> AddrToAtomCache;
+};
+
+/// A function for mutating AtomGraphs.
+using AtomGraphPassFunction = std::function<Error(AtomGraph &)>;
+
+/// A list of atom graph passes.
+using AtomGraphPassList = std::vector<AtomGraphPassFunction>;
+
+/// An atom graph pass configuration, consisting of a list of pre-prune,
+/// post-prune, and post-fixup passes.
+struct PassConfiguration {
+
+ /// Pre-prune passes.
+ ///
+ /// These passes are called on the graph after it is built, and before any
+ /// atoms have been pruned.
+ ///
+ /// Notable use cases: Marking atoms live or should-discard.
+ AtomGraphPassList PrePrunePasses;
+
+ /// Post-prune passes.
+ ///
+ /// These passes are called on the graph after dead and should-discard atoms
+ /// have been removed, but before fixups are applied.
+ ///
+ /// Notable use cases: Building GOT, stub, and TLV atoms.
+ AtomGraphPassList PostPrunePasses;
+
+ /// Post-fixup passes.
+ ///
+ /// These passes are called on the graph after atom contents has been copied
+ /// to working memory, and fixups applied.
+ ///
+ /// Notable use cases: Testing and validation.
+ AtomGraphPassList PostFixupPasses;
+};
+
+/// A map of symbol names to resolved addresses.
+using AsyncLookupResult = DenseMap<StringRef, JITEvaluatedSymbol>;
+
+/// A function to call with a resolved symbol map (See AsyncLookupResult) or an
+/// error if resolution failed.
+using JITLinkAsyncLookupContinuation =
+ std::function<void(Expected<AsyncLookupResult> LR)>;
+
+/// An asynchronous symbol lookup. Performs a search (possibly asynchronously)
+/// for the given symbols, calling the given continuation with either the result
+/// (if the lookup succeeds), or an error (if the lookup fails).
+using JITLinkAsyncLookupFunction =
+ std::function<void(const DenseSet<StringRef> &Symbols,
+ JITLinkAsyncLookupContinuation LookupContinuation)>;
+
+/// Holds context for a single jitLink invocation.
+class JITLinkContext {
+public:
+ /// Destroy a JITLinkContext.
+ virtual ~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;
+
+ /// Called by JITLink to resolve external symbols. This method is passed a
+ /// lookup continutation which it must call with a result to continue the
+ /// linking process.
+ virtual void lookup(const DenseSet<StringRef> &Symbols,
+ JITLinkAsyncLookupContinuation LookupContinuation) = 0;
+
+ /// Called by JITLink once all defined atoms in the graph have been assigned
+ /// their final memory locations in the target process. At this point he
+ /// atom graph can be, inspected to build a symbol table however the atom
+ /// content will not generally have been copied to the target location yet.
+ virtual void notifyResolved(AtomGraph &G) = 0;
+
+ /// Called by JITLink to notify the context that the object has been
+ /// finalized (i.e. emitted to memory and memory permissions set). If all of
+ /// this objects dependencies have also been finalized then the code is ready
+ /// to run.
+ virtual void
+ notifyFinalized(std::unique_ptr<JITLinkMemoryManager::Allocation> A) = 0;
+
+ /// Called by JITLink prior to linking to determine whether default passes for
+ /// the target should be added. The default implementation returns true.
+ /// If subclasses override this method to return false for any target then
+ /// they are required to fully configure the pass pipeline for that target.
+ virtual bool shouldAddDefaultTargetPasses(const Triple &TT) const;
+
+ /// Returns the mark-live pass to be used for this link. If no pass is
+ /// returned (the default) then the target-specific linker implementation will
+ /// choose a conservative default (usually marking all atoms live).
+ /// This function is only called if shouldAddDefaultTargetPasses returns true,
+ /// otherwise the JITContext is responsible for adding a mark-live pass in
+ /// modifyPassConfig.
+ virtual AtomGraphPassFunction getMarkLivePass(const Triple &TT) const;
+
+ /// Called by JITLink to modify the pass pipeline prior to linking.
+ /// The default version performs no modification.
+ virtual Error modifyPassConfig(const Triple &TT, PassConfiguration &Config);
+};
+
+/// Marks all atoms in a graph live. This can be used as a default, conservative
+/// mark-live implementation.
+Error markAllAtomsLive(AtomGraph &G);
+
+/// Basic JITLink implementation.
+///
+/// This function will use sensible defaults for GOT and Stub handling.
+void jitLink(std::unique_ptr<JITLinkContext> Ctx);
+
+} // end namespace jitlink
+} // end namespace llvm
+
+#endif // LLVM_EXECUTIONENGINE_JITLINK_JITLINK_H
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/JITLink/JITLinkMemoryManager.h b/linux-x64/clang/include/llvm/ExecutionEngine/JITLink/JITLinkMemoryManager.h
new file mode 100644
index 0000000..9d0b37f
--- /dev/null
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/JITLink/JITLinkMemoryManager.h
@@ -0,0 +1,99 @@
+//===-- JITLinkMemoryManager.h - JITLink mem manager interface --*- C++ -*-===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+// Contains the JITLinkMemoryManager interface.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_EXECUTIONENGINE_JITLINK_JITLINKMEMORYMANAGER_H
+#define LLVM_EXECUTIONENGINE_JITLINK_JITLINKMEMORYMANAGER_H
+
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ExecutionEngine/JITSymbol.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/Memory.h"
+#include <cstdint>
+
+namespace llvm {
+namespace jitlink {
+
+/// Manages allocations of JIT memory.
+///
+/// Instances of this class may be accessed concurrently from multiple threads
+/// and their implemetations should include any necessary synchronization.
+class JITLinkMemoryManager {
+public:
+ using ProtectionFlags = sys::Memory::ProtectionFlags;
+
+ class SegmentRequest {
+ public:
+ SegmentRequest() = default;
+ SegmentRequest(size_t ContentSize, unsigned ContentAlign,
+ uint64_t ZeroFillSize, unsigned ZeroFillAlign)
+ : ContentSize(ContentSize), ZeroFillSize(ZeroFillSize),
+ ContentAlign(ContentAlign), ZeroFillAlign(ZeroFillAlign) {}
+ size_t getContentSize() const { return ContentSize; }
+ unsigned getContentAlignment() const { return ContentAlign; }
+ uint64_t getZeroFillSize() const { return ZeroFillSize; }
+ unsigned getZeroFillAlignment() const { return ZeroFillAlign; }
+
+ private:
+ size_t ContentSize = 0;
+ uint64_t ZeroFillSize = 0;
+ unsigned ContentAlign = 0;
+ unsigned ZeroFillAlign = 0;
+ };
+
+ using SegmentsRequestMap = DenseMap<unsigned, SegmentRequest>;
+
+ /// Represents an allocation created by the memory manager.
+ ///
+ /// An allocation object is responsible for allocating and owning jit-linker
+ /// working and target memory, and for transfering from working to target
+ /// memory.
+ ///
+ class Allocation {
+ public:
+ using FinalizeContinuation = std::function<void(Error)>;
+
+ virtual ~Allocation();
+
+ /// Should return the address of linker working memory for the segment with
+ /// the given protection flags.
+ virtual MutableArrayRef<char> getWorkingMemory(ProtectionFlags Seg) = 0;
+
+ /// Should return the final address in the target process where the segment
+ /// will reside.
+ virtual JITTargetAddress getTargetMemory(ProtectionFlags Seg) = 0;
+
+ /// Should transfer from working memory to target memory, and release
+ /// working memory.
+ virtual void finalizeAsync(FinalizeContinuation OnFinalize) = 0;
+
+ /// Should deallocate target memory.
+ virtual Error deallocate() = 0;
+ };
+
+ virtual ~JITLinkMemoryManager();
+
+ /// Create an Allocation object.
+ virtual Expected<std::unique_ptr<Allocation>>
+ allocate(const SegmentsRequestMap &Request) = 0;
+};
+
+/// A JITLinkMemoryManager that allocates in-process memory.
+class InProcessMemoryManager : public JITLinkMemoryManager {
+public:
+ Expected<std::unique_ptr<Allocation>>
+ allocate(const SegmentsRequestMap &Request) override;
+};
+
+} // end namespace jitlink
+} // end namespace llvm
+
+#endif // LLVM_EXECUTIONENGINE_JITLINK_JITLINK_H
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/JITLink/MachO.h b/linux-x64/clang/include/llvm/ExecutionEngine/JITLink/MachO.h
new file mode 100644
index 0000000..7facb65
--- /dev/null
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/JITLink/MachO.h
@@ -0,0 +1,30 @@
+//===------- MachO.h - Generic JIT link function for MachO ------*- C++ -*-===//
+//
+// 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 jit-link functions for MachO.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_EXECUTIONENGINE_JITLINK_MACHO_H
+#define LLVM_EXECUTIONENGINE_JITLINK_MACHO_H
+
+#include "llvm/ExecutionEngine/JITLink/JITLink.h"
+
+namespace llvm {
+namespace jitlink {
+
+/// 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);
+
+} // end namespace jitlink
+} // end namespace llvm
+
+#endif // LLVM_EXECUTIONENGINE_JITLINK_MACHO_H
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/JITLink/MachO_x86_64.h b/linux-x64/clang/include/llvm/ExecutionEngine/JITLink/MachO_x86_64.h
new file mode 100644
index 0000000..1d5b586
--- /dev/null
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/JITLink/MachO_x86_64.h
@@ -0,0 +1,63 @@
+//===--- MachO_x86_64.h - JIT link functions for MachO/x86-64 ---*- C++ -*-===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+// jit-link functions for MachO/x86-64.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_EXECUTIONENGINE_JITLINK_MACHO_X86_64_H
+#define LLVM_EXECUTIONENGINE_JITLINK_MACHO_X86_64_H
+
+#include "llvm/ExecutionEngine/JITLink/JITLink.h"
+
+namespace llvm {
+namespace jitlink {
+
+namespace MachO_x86_64_Edges {
+
+enum MachOX86RelocationKind : Edge::Kind {
+ Branch32 = Edge::FirstRelocation,
+ Pointer64,
+ Pointer64Anon,
+ PCRel32,
+ PCRel32Minus1,
+ PCRel32Minus2,
+ PCRel32Minus4,
+ PCRel32Anon,
+ PCRel32Minus1Anon,
+ PCRel32Minus2Anon,
+ PCRel32Minus4Anon,
+ PCRel32GOTLoad,
+ PCRel32GOT,
+ PCRel32TLV,
+ Delta32,
+ Delta64,
+ NegDelta32,
+ NegDelta64,
+};
+
+} // namespace MachO_x86_64_Edges
+
+/// jit-link the given object buffer, which must be a MachO x86-64 object file.
+///
+/// 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
+/// caller is responsible for including a pass to mark atoms as live.
+///
+/// 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);
+
+/// Return the string name of the given MachO x86-64 edge kind.
+StringRef getMachOX86RelocationKindName(Edge::Kind R);
+
+} // end namespace jitlink
+} // end namespace llvm
+
+#endif // LLVM_EXECUTIONENGINE_JITLINK_MACHO_X86_64_H
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/JITSymbol.h b/linux-x64/clang/include/llvm/ExecutionEngine/JITSymbol.h
index da1352f..b14154c 100644
--- a/linux-x64/clang/include/llvm/ExecutionEngine/JITSymbol.h
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/JITSymbol.h
@@ -55,7 +55,7 @@
class JITSymbolFlags {
public:
using UnderlyingType = uint8_t;
- using TargetFlagsType = uint64_t;
+ using TargetFlagsType = uint8_t;
enum FlagNames : UnderlyingType {
None = 0,
@@ -65,15 +65,9 @@
Absolute = 1U << 3,
Exported = 1U << 4,
Callable = 1U << 5,
- Lazy = 1U << 6,
- Materializing = 1U << 7,
- LLVM_MARK_AS_BITMASK_ENUM(/* LargestValue = */ Materializing)
+ LLVM_MARK_AS_BITMASK_ENUM(/* LargestValue = */ Callable)
};
- static JITSymbolFlags stripTransientFlags(JITSymbolFlags Orig) {
- return static_cast<FlagNames>(Orig.Flags & ~Lazy & ~Materializing);
- }
-
/// Default-construct a JITSymbolFlags instance.
JITSymbolFlags() = default;
@@ -83,7 +77,7 @@
/// Construct a JITSymbolFlags instance from the given flags and target
/// flags.
JITSymbolFlags(FlagNames Flags, TargetFlagsType TargetFlags)
- : Flags(Flags), TargetFlags(TargetFlags) {}
+ : TargetFlags(TargetFlags), Flags(Flags) {}
/// Implicitly convert to bool. Returs true if any flag is set.
explicit operator bool() const { return Flags != None || TargetFlags != 0; }
@@ -110,19 +104,6 @@
return (Flags & HasError) == HasError;
}
- /// Returns true if this is a lazy symbol.
- /// This flag is used internally by the JIT APIs to track
- /// materialization states.
- bool isLazy() const { return Flags & Lazy; }
-
- /// Returns true if this symbol is in the process of being
- /// materialized.
- bool isMaterializing() const { return Flags & Materializing; }
-
- /// Returns true if this symbol is fully materialized.
- /// (i.e. neither lazy, nor materializing).
- bool isMaterialized() const { return !(Flags & (Lazy | Materializing)); }
-
/// Returns true if the Weak flag is set.
bool isWeak() const {
return (Flags & Weak) == Weak;
@@ -167,8 +148,8 @@
fromObjectSymbol(const object::SymbolRef &Symbol);
private:
- FlagNames Flags = None;
TargetFlagsType TargetFlags = 0;
+ FlagNames Flags = None;
};
inline JITSymbolFlags operator&(const JITSymbolFlags &LHS,
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/CompileUtils.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/CompileUtils.h
index 15a6566..1585925 100644
--- a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/CompileUtils.h
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/CompileUtils.h
@@ -13,25 +13,17 @@
#ifndef LLVM_EXECUTIONENGINE_ORC_COMPILEUTILS_H
#define LLVM_EXECUTIONENGINE_ORC_COMPILEUTILS_H
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/ExecutionEngine/ObjectCache.h"
#include "llvm/ExecutionEngine/Orc/JITTargetMachineBuilder.h"
-#include "llvm/IR/LegacyPassManager.h"
-#include "llvm/Object/Binary.h"
-#include "llvm/Object/ObjectFile.h"
-#include "llvm/Support/Error.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/SmallVectorMemoryBuffer.h"
-#include "llvm/Support/raw_ostream.h"
-#include "llvm/Target/TargetMachine.h"
-#include <algorithm>
#include <memory>
namespace llvm {
+class JITTargetMachineBuilder;
class MCContext;
+class MemoryBuffer;
class Module;
+class ObjectCache;
+class TargetMachine;
namespace orc {
@@ -50,51 +42,11 @@
void setObjectCache(ObjectCache *NewCache) { ObjCache = NewCache; }
/// Compile a Module to an ObjectFile.
- CompileResult operator()(Module &M) {
- CompileResult CachedObject = tryToLoadFromObjectCache(M);
- if (CachedObject)
- return CachedObject;
-
- SmallVector<char, 0> ObjBufferSV;
-
- {
- raw_svector_ostream ObjStream(ObjBufferSV);
-
- legacy::PassManager PM;
- MCContext *Ctx;
- if (TM.addPassesToEmitMC(PM, Ctx, ObjStream))
- llvm_unreachable("Target does not support MC emission.");
- PM.run(M);
- }
-
- auto ObjBuffer =
- llvm::make_unique<SmallVectorMemoryBuffer>(std::move(ObjBufferSV));
- auto Obj =
- object::ObjectFile::createObjectFile(ObjBuffer->getMemBufferRef());
-
- if (Obj) {
- notifyObjectCompiled(M, *ObjBuffer);
- return std::move(ObjBuffer);
- }
-
- // TODO: Actually report errors helpfully.
- consumeError(Obj.takeError());
- return nullptr;
- }
+ CompileResult operator()(Module &M);
private:
-
- CompileResult tryToLoadFromObjectCache(const Module &M) {
- if (!ObjCache)
- return CompileResult();
-
- return ObjCache->getObject(&M);
- }
-
- void notifyObjectCompiled(const Module &M, const MemoryBuffer &ObjBuffer) {
- if (ObjCache)
- ObjCache->notifyObjectCompiled(&M, ObjBuffer.getMemBufferRef());
- }
+ CompileResult tryToLoadFromObjectCache(const Module &M);
+ void notifyObjectCompiled(const Module &M, const MemoryBuffer &ObjBuffer);
TargetMachine &TM;
ObjectCache *ObjCache = nullptr;
@@ -107,16 +59,11 @@
class ConcurrentIRCompiler {
public:
ConcurrentIRCompiler(JITTargetMachineBuilder JTMB,
- ObjectCache *ObjCache = nullptr)
- : JTMB(std::move(JTMB)), ObjCache(ObjCache) {}
+ ObjectCache *ObjCache = nullptr);
void setObjectCache(ObjectCache *ObjCache) { this->ObjCache = ObjCache; }
- std::unique_ptr<MemoryBuffer> operator()(Module &M) {
- auto TM = cantFail(JTMB.createTargetMachine());
- SimpleCompiler C(*TM, ObjCache);
- return C(M);
- }
+ std::unique_ptr<MemoryBuffer> operator()(Module &M);
private:
JITTargetMachineBuilder JTMB;
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/Core.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/Core.h
index 299247a..016fd82 100644
--- a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/Core.h
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/Core.h
@@ -33,6 +33,7 @@
class MaterializationUnit;
class MaterializationResponsibility;
class JITDylib;
+enum class SymbolState : uint8_t;
/// VModuleKey provides a unique identifier (allocated and managed by
/// ExecutionSessions) for a module added to the JIT.
@@ -56,6 +57,18 @@
/// A list of (JITDylib*, bool) pairs.
using JITDylibSearchList = std::vector<std::pair<JITDylib *, bool>>;
+struct SymbolAliasMapEntry {
+ SymbolAliasMapEntry() = default;
+ SymbolAliasMapEntry(SymbolStringPtr Aliasee, JITSymbolFlags AliasFlags)
+ : Aliasee(std::move(Aliasee)), AliasFlags(AliasFlags) {}
+
+ SymbolStringPtr Aliasee;
+ JITSymbolFlags AliasFlags;
+};
+
+/// A map of Symbols to (Symbol, Flags) pairs.
+using SymbolAliasMap = DenseMap<SymbolStringPtr, SymbolAliasMapEntry>;
+
/// Render a SymbolStringPtr.
raw_ostream &operator<<(raw_ostream &OS, const SymbolStringPtr &Sym);
@@ -87,12 +100,15 @@
/// Render a JITDylibSearchList.
raw_ostream &operator<<(raw_ostream &OS, const JITDylibSearchList &JDs);
+/// Render a SymbolAliasMap.
+raw_ostream &operator<<(raw_ostream &OS, const SymbolAliasMap &Aliases);
+
+/// Render a SymbolState.
+raw_ostream &operator<<(raw_ostream &OS, const SymbolState &S);
+
/// Callback to notify client that symbols have been resolved.
using SymbolsResolvedCallback = std::function<void(Expected<SymbolMap>)>;
-/// Callback to notify client that symbols are ready for execution.
-using SymbolsReadyCallback = std::function<void(Error)>;
-
/// Callback to register the dependencies for a given query.
using RegisterDependenciesFunction =
std::function<void(const SymbolDependenceMap &)>;
@@ -174,7 +190,7 @@
/// Note: The returned flags may have transient flags (Lazy, Materializing)
/// set. These should be stripped with JITSymbolFlags::stripTransientFlags
/// before using.
- const SymbolFlagsMap &getSymbols() { return SymbolFlags; }
+ const SymbolFlagsMap &getSymbols() const { return SymbolFlags; }
/// Returns the names of any symbols covered by this
/// MaterializationResponsibility object that have queries pending. This
@@ -188,12 +204,12 @@
/// symbols must be ones covered by this MaterializationResponsibility
/// instance. Individual calls to this method may resolve a subset of the
/// symbols, but all symbols must have been resolved prior to calling emit.
- void resolve(const SymbolMap &Symbols);
+ void notifyResolved(const SymbolMap &Symbols);
/// Notifies the target JITDylib (and any pending queries on that JITDylib)
/// that all symbols covered by this MaterializationResponsibility instance
/// have been emitted.
- void emit();
+ void notifyEmitted();
/// Adds new symbols to the JITDylib and this responsibility instance.
/// JITDylib entries start out in the materializing state.
@@ -333,18 +349,6 @@
std::move(Symbols), std::move(K));
}
-struct SymbolAliasMapEntry {
- SymbolAliasMapEntry() = default;
- SymbolAliasMapEntry(SymbolStringPtr Aliasee, JITSymbolFlags AliasFlags)
- : Aliasee(std::move(Aliasee)), AliasFlags(AliasFlags) {}
-
- SymbolStringPtr Aliasee;
- JITSymbolFlags AliasFlags;
-};
-
-/// A map of Symbols to (Symbol, Flags) pairs.
-using SymbolAliasMap = DenseMap<SymbolStringPtr, SymbolAliasMapEntry>;
-
/// A materialization unit for symbol aliases. Allows existing symbols to be
/// aliased with alternate flags.
class ReExportsMaterializationUnit : public MaterializationUnit {
@@ -418,7 +422,7 @@
ReexportsGenerator(JITDylib &SourceJD, bool MatchNonExported = false,
SymbolPredicate Allow = SymbolPredicate());
- SymbolNameSet operator()(JITDylib &JD, const SymbolNameSet &Names);
+ Expected<SymbolNameSet> operator()(JITDylib &JD, const SymbolNameSet &Names);
private:
JITDylib &SourceJD;
@@ -426,6 +430,15 @@
SymbolPredicate Allow;
};
+/// Represents the state that a symbol has reached during materialization.
+enum class SymbolState : uint8_t {
+ Invalid, /// No symbol should be in this state.
+ NeverSearched, /// Added to the symbol table, never queried.
+ Materializing, /// Queried, materialization begun.
+ Resolved, /// Assigned address, still materializing.
+ Ready = 0x3f /// Ready and safe for clients to access.
+};
+
/// A symbol query that returns results via a callback when results are
/// ready.
///
@@ -436,38 +449,30 @@
friend class JITSymbolResolverAdapter;
public:
-
- /// Create a query for the given symbols, notify-resolved and
- /// notify-ready callbacks.
+ /// Create a query for the given symbols. The NotifyComplete
+ /// callback will be called once all queried symbols reach the given
+ /// minimum state.
AsynchronousSymbolQuery(const SymbolNameSet &Symbols,
- SymbolsResolvedCallback NotifySymbolsResolved,
- SymbolsReadyCallback NotifySymbolsReady);
+ SymbolState RequiredState,
+ SymbolsResolvedCallback NotifyComplete);
- /// Set the resolved symbol information for the given symbol name.
- void resolve(const SymbolStringPtr &Name, JITEvaluatedSymbol Sym);
+ /// Notify the query that a requested symbol has reached the required state.
+ void notifySymbolMetRequiredState(const SymbolStringPtr &Name,
+ JITEvaluatedSymbol Sym);
/// Returns true if all symbols covered by this query have been
/// resolved.
- bool isFullyResolved() const { return NotYetResolvedCount == 0; }
+ bool isComplete() const { return OutstandingSymbolsCount == 0; }
- /// Call the NotifySymbolsResolved callback.
+ /// Call the NotifyComplete callback.
///
- /// This should only be called if all symbols covered by the query have been
- /// resolved.
- void handleFullyResolved();
-
- /// Notify the query that a requested symbol is ready for execution.
- void notifySymbolReady();
-
- /// Returns true if all symbols covered by this query are ready.
- bool isFullyReady() const { return NotYetReadyCount == 0; }
-
- /// Calls the NotifySymbolsReady callback.
- ///
- /// This should only be called if all symbols covered by this query are ready.
- void handleFullyReady();
+ /// This should only be called if all symbols covered by the query have
+ /// reached the specified state.
+ void handleComplete();
private:
+ SymbolState getRequiredState() { return RequiredState; }
+
void addQueryDependence(JITDylib &JD, SymbolStringPtr Name);
void removeQueryDependence(JITDylib &JD, const SymbolStringPtr &Name);
@@ -478,12 +483,11 @@
void detach();
- SymbolsResolvedCallback NotifySymbolsResolved;
- SymbolsReadyCallback NotifySymbolsReady;
+ SymbolsResolvedCallback NotifyComplete;
SymbolDependenceMap QueryRegistrations;
SymbolMap ResolvedSymbols;
- size_t NotYetResolvedCount;
- size_t NotYetReadyCount;
+ size_t OutstandingSymbolsCount;
+ SymbolState RequiredState;
};
/// A symbol table that supports asynchoronous symbol queries.
@@ -497,7 +501,7 @@
friend class ExecutionSession;
friend class MaterializationResponsibility;
public:
- using GeneratorFunction = std::function<SymbolNameSet(
+ using GeneratorFunction = std::function<Expected<SymbolNameSet>(
JITDylib &Parent, const SymbolNameSet &Names)>;
using AsynchronousSymbolQuerySet =
@@ -595,7 +599,7 @@
/// Search the given JITDylib for the symbols in Symbols. If found, store
/// the flags for each symbol in Flags. Returns any unresolved symbols.
- SymbolFlagsMap lookupFlags(const SymbolNameSet &Names);
+ Expected<SymbolFlagsMap> lookupFlags(const SymbolNameSet &Names);
/// Dump current JITDylib state to OS.
void dump(raw_ostream &OS);
@@ -608,8 +612,8 @@
/// and the query will not be applied. The Query is not failed and can be
/// re-used in a subsequent lookup once the symbols have been added, or
/// manually failed.
- SymbolNameSet legacyLookup(std::shared_ptr<AsynchronousSymbolQuery> Q,
- SymbolNameSet Names);
+ Expected<SymbolNameSet>
+ legacyLookup(std::shared_ptr<AsynchronousSymbolQuery> Q, SymbolNameSet Names);
private:
using AsynchronousSymbolQueryList =
@@ -626,40 +630,92 @@
DenseMap<SymbolStringPtr, std::shared_ptr<UnmaterializedInfo>>;
struct MaterializingInfo {
- AsynchronousSymbolQueryList PendingQueries;
SymbolDependenceMap Dependants;
SymbolDependenceMap UnemittedDependencies;
bool IsEmitted = false;
+
+ void addQuery(std::shared_ptr<AsynchronousSymbolQuery> Q);
+ void removeQuery(const AsynchronousSymbolQuery &Q);
+ AsynchronousSymbolQueryList takeQueriesMeeting(SymbolState RequiredState);
+ AsynchronousSymbolQueryList takeAllQueries();
+ bool hasQueriesPending() const { return !PendingQueries.empty(); }
+ const AsynchronousSymbolQueryList &pendingQueries() const {
+ return PendingQueries;
+ }
+
+ private:
+ AsynchronousSymbolQueryList PendingQueries;
};
using MaterializingInfosMap = DenseMap<SymbolStringPtr, MaterializingInfo>;
- using LookupImplActionFlags = enum {
- None = 0,
- NotifyFullyResolved = 1 << 0U,
- NotifyFullyReady = 1 << 1U,
- LLVM_MARK_AS_BITMASK_ENUM(NotifyFullyReady)
+ class SymbolTableEntry {
+ public:
+ SymbolTableEntry() = default;
+ SymbolTableEntry(JITSymbolFlags Flags)
+ : Flags(Flags), State(static_cast<uint8_t>(SymbolState::NeverSearched)),
+ MaterializerAttached(false), PendingRemoval(false) {}
+
+ JITTargetAddress getAddress() const { return Addr; }
+ JITSymbolFlags getFlags() const { return Flags; }
+ SymbolState getState() const { return static_cast<SymbolState>(State); }
+
+ bool isInMaterializationPhase() const {
+ return getState() == SymbolState::Materializing ||
+ getState() == SymbolState::Resolved;
+ }
+
+ bool hasMaterializerAttached() const { return MaterializerAttached; }
+ bool isPendingRemoval() const { return PendingRemoval; }
+
+ void setAddress(JITTargetAddress Addr) { this->Addr = Addr; }
+ void setFlags(JITSymbolFlags Flags) { this->Flags = Flags; }
+ void setState(SymbolState State) {
+ assert(static_cast<uint8_t>(State) < (1 << 6) &&
+ "State does not fit in bitfield");
+ this->State = static_cast<uint8_t>(State);
+ }
+
+ void setMaterializerAttached(bool MaterializerAttached) {
+ this->MaterializerAttached = MaterializerAttached;
+ }
+
+ void setPendingRemoval(bool PendingRemoval) {
+ this->PendingRemoval = PendingRemoval;
+ }
+
+ JITEvaluatedSymbol getSymbol() const {
+ return JITEvaluatedSymbol(Addr, Flags);
+ }
+
+ private:
+ JITTargetAddress Addr = 0;
+ JITSymbolFlags Flags;
+ uint8_t State : 6;
+ uint8_t MaterializerAttached : 1;
+ uint8_t PendingRemoval : 1;
};
+ using SymbolTable = DenseMap<SymbolStringPtr, SymbolTableEntry>;
+
JITDylib(ExecutionSession &ES, std::string Name);
Error defineImpl(MaterializationUnit &MU);
- SymbolNameSet lookupFlagsImpl(SymbolFlagsMap &Flags,
- const SymbolNameSet &Names);
+ Expected<SymbolNameSet> lookupFlagsImpl(SymbolFlagsMap &Flags,
+ const SymbolNameSet &Names);
- void lodgeQuery(std::shared_ptr<AsynchronousSymbolQuery> &Q,
- SymbolNameSet &Unresolved, bool MatchNonExported,
- MaterializationUnitList &MUs);
+ Error lodgeQuery(std::shared_ptr<AsynchronousSymbolQuery> &Q,
+ SymbolNameSet &Unresolved, bool MatchNonExported,
+ MaterializationUnitList &MUs);
void lodgeQueryImpl(std::shared_ptr<AsynchronousSymbolQuery> &Q,
SymbolNameSet &Unresolved, bool MatchNonExported,
MaterializationUnitList &MUs);
- LookupImplActionFlags
- lookupImpl(std::shared_ptr<AsynchronousSymbolQuery> &Q,
- std::vector<std::unique_ptr<MaterializationUnit>> &MUs,
- SymbolNameSet &Unresolved);
+ bool lookupImpl(std::shared_ptr<AsynchronousSymbolQuery> &Q,
+ std::vector<std::unique_ptr<MaterializationUnit>> &MUs,
+ SymbolNameSet &Unresolved);
void detachQueryHelper(AsynchronousSymbolQuery &Q,
const SymbolNameSet &QuerySymbols);
@@ -685,7 +741,7 @@
ExecutionSession &ES;
std::string JITDylibName;
- SymbolMap Symbols;
+ SymbolTable Symbols;
UnmaterializedInfosMap UnmaterializedInfos;
MaterializingInfosMap MaterializingInfos;
GeneratorFunction DefGenerator;
@@ -726,7 +782,15 @@
/// the ExecutionSession.
JITDylib &getMainJITDylib();
+ /// Return a pointer to the "name" JITDylib.
+ /// Ownership of JITDylib remains within Execution Session
+ JITDylib *getJITDylibByName(StringRef Name);
+
/// Add a new JITDylib to this ExecutionSession.
+ ///
+ /// The JITDylib Name is required to be unique. Clients should verify that
+ /// names are not being re-used (e.g. by calling getJITDylibByName) if names
+ /// are based on user input.
JITDylib &createJITDylib(std::string Name,
bool AddToMainDylibSearchOrder = true);
@@ -768,7 +832,7 @@
/// Do not use -- this will be removed soon.
Expected<SymbolMap>
legacyLookup(LegacyAsyncLookupFunction AsyncLookup, SymbolNameSet Names,
- bool WaiUntilReady,
+ SymbolState RequiredState,
RegisterDependenciesFunction RegisterDependencies);
/// Search the given JITDylib list for the given symbols.
@@ -778,11 +842,8 @@
/// (hidden visibility) symbols in that dylib (true means match against
/// non-exported symbols, false means do not match).
///
- /// The OnResolve callback will be called once all requested symbols are
- /// resolved, or if an error occurs prior to resolution.
- ///
- /// The OnReady callback will be called once all requested symbols are ready,
- /// or if an error occurs after resolution but before all symbols are ready.
+ /// The NotifyComplete callback will be called once all requested symbols
+ /// reach the required state.
///
/// If all symbols are found, the RegisterDependencies function will be called
/// while the session lock is held. This gives clients a chance to register
@@ -794,7 +855,7 @@
/// client to get an address to call) then the value NoDependenciesToRegister
/// can be used.
void lookup(const JITDylibSearchList &SearchOrder, SymbolNameSet Symbols,
- SymbolsResolvedCallback OnResolve, SymbolsReadyCallback OnReady,
+ SymbolState RequiredState, SymbolsResolvedCallback NotifyComplete,
RegisterDependenciesFunction RegisterDependencies);
/// Blocking version of lookup above. Returns the resolved symbol map.
@@ -806,9 +867,9 @@
/// error will be reported via reportErrors.
Expected<SymbolMap> lookup(const JITDylibSearchList &SearchOrder,
const SymbolNameSet &Symbols,
+ SymbolState RequiredState = SymbolState::Ready,
RegisterDependenciesFunction RegisterDependencies =
- NoDependenciesToRegister,
- bool WaitUntilReady = true);
+ NoDependenciesToRegister);
/// Convenience version of blocking lookup.
/// Searches each of the JITDylibs in the search order in turn for the given
@@ -831,10 +892,11 @@
/// Materialize the given unit.
void dispatchMaterialization(JITDylib &JD,
std::unique_ptr<MaterializationUnit> MU) {
- LLVM_DEBUG(runSessionLocked([&]() {
- dbgs() << "Compiling, for " << JD.getName() << ", " << *MU
- << "\n";
- }););
+ LLVM_DEBUG({
+ runSessionLocked([&]() {
+ dbgs() << "Dispatching " << *MU << " for " << JD.getName() << "\n";
+ });
+ });
DispatchMaterialization(JD, std::move(MU));
}
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h
index 40dd415..ae3ab8c 100644
--- a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h
@@ -217,28 +217,29 @@
/// Create a DynamicLibrarySearchGenerator that searches for symbols in the
/// given sys::DynamicLibrary.
+ ///
/// If the Allow predicate is given then only symbols matching the predicate
- /// will be searched for in the DynamicLibrary. If the predicate is not given
- /// then all symbols will be searched for.
- DynamicLibrarySearchGenerator(sys::DynamicLibrary Dylib, const DataLayout &DL,
+ /// will be searched for. If the predicate is not given then all symbols will
+ /// be searched for.
+ DynamicLibrarySearchGenerator(sys::DynamicLibrary Dylib, char GlobalPrefix,
SymbolPredicate Allow = SymbolPredicate());
/// Permanently loads the library at the given path and, on success, returns
/// a DynamicLibrarySearchGenerator that will search it for symbol definitions
/// in the library. On failure returns the reason the library failed to load.
static Expected<DynamicLibrarySearchGenerator>
- Load(const char *FileName, const DataLayout &DL,
+ Load(const char *FileName, char GlobalPrefix,
SymbolPredicate Allow = SymbolPredicate());
/// Creates a DynamicLibrarySearchGenerator that searches for symbols in
/// the current process.
static Expected<DynamicLibrarySearchGenerator>
- GetForCurrentProcess(const DataLayout &DL,
+ GetForCurrentProcess(char GlobalPrefix,
SymbolPredicate Allow = SymbolPredicate()) {
- return Load(nullptr, DL, std::move(Allow));
+ return Load(nullptr, GlobalPrefix, std::move(Allow));
}
- SymbolNameSet operator()(JITDylib &JD, const SymbolNameSet &Names);
+ Expected<SymbolNameSet> operator()(JITDylib &JD, const SymbolNameSet &Names);
private:
sys::DynamicLibrary Dylib;
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h
index 2ea9ac1..a7ed537 100644
--- a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h
@@ -146,13 +146,13 @@
std::error_code EC;
auto TrampolineBlock =
sys::OwningMemoryBlock(sys::Memory::allocateMappedMemory(
- sys::Process::getPageSize(), nullptr,
+ sys::Process::getPageSizeEstimate(), nullptr,
sys::Memory::MF_READ | sys::Memory::MF_WRITE, EC));
if (EC)
return errorCodeToError(EC);
unsigned NumTrampolines =
- (sys::Process::getPageSize() - ORCABI::PointerSize) /
+ (sys::Process::getPageSizeEstimate() - ORCABI::PointerSize) /
ORCABI::TrampolineSize;
uint8_t *TrampolineMem = static_cast<uint8_t *>(TrampolineBlock.base());
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/LLJIT.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/LLJIT.h
index b0ef20d..b54c7d8 100644
--- a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/LLJIT.h
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/LLJIT.h
@@ -20,35 +20,49 @@
#include "llvm/ExecutionEngine/Orc/IRTransformLayer.h"
#include "llvm/ExecutionEngine/Orc/JITTargetMachineBuilder.h"
#include "llvm/ExecutionEngine/Orc/ObjectTransformLayer.h"
-#include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h"
#include "llvm/ExecutionEngine/Orc/ThreadSafeModule.h"
#include "llvm/Support/ThreadPool.h"
namespace llvm {
namespace orc {
+class LLJITBuilderState;
+class LLLazyJITBuilderState;
+
/// A pre-fabricated ORC JIT stack that can serve as an alternative to MCJIT.
+///
+/// Create instances using LLJITBuilder.
class LLJIT {
+ template <typename, typename, typename> friend class LLJITBuilderSetters;
+
public:
+ static Expected<std::unique_ptr<LLJIT>> Create(LLJITBuilderState &S);
/// Destruct this instance. If a multi-threaded instance, waits for all
/// compile threads to complete.
~LLJIT();
- /// Create an LLJIT instance.
- /// If NumCompileThreads is not equal to zero, creates a multi-threaded
- /// LLJIT with the given number of compile threads.
- static Expected<std::unique_ptr<LLJIT>>
- Create(JITTargetMachineBuilder JTMB, DataLayout DL,
- unsigned NumCompileThreads = 0);
-
/// Returns the ExecutionSession for this instance.
ExecutionSession &getExecutionSession() { return *ES; }
+ /// Returns a reference to the DataLayout for this instance.
+ const DataLayout &getDataLayout() const { return DL; }
+
/// Returns a reference to the JITDylib representing the JIT'd main program.
JITDylib &getMainJITDylib() { return Main; }
+ /// Returns the JITDylib with the given name, or nullptr if no JITDylib with
+ /// that name exists.
+ JITDylib *getJITDylibByName(StringRef Name) {
+ return ES->getJITDylibByName(Name);
+ }
+
/// Create a new JITDylib with the given name and return a reference to it.
+ ///
+ /// JITDylib names must be unique. If the given name is derived from user
+ /// input or elsewhere in the environment then the client should check
+ /// (e.g. by calling getJITDylibByName) that the given name is not already in
+ /// use.
JITDylib &createJITDylib(std::string Name) {
return ES->createJITDylib(std::move(Name));
}
@@ -56,8 +70,6 @@
/// Convenience method for defining an absolute symbol.
Error defineAbsolute(StringRef Name, JITEvaluatedSymbol Address);
- /// Convenience method for defining an
-
/// Adds an IR module to the given JITDylib.
Error addIRModule(JITDylib &JD, ThreadSafeModule TSM);
@@ -103,17 +115,14 @@
Error runDestructors() { return DtorRunner.run(); }
/// Returns a reference to the ObjLinkingLayer
- RTDyldObjectLinkingLayer &getObjLinkingLayer() { return ObjLinkingLayer; }
+ ObjectLayer &getObjLinkingLayer() { return *ObjLinkingLayer; }
protected:
+ static std::unique_ptr<ObjectLayer>
+ createObjectLinkingLayer(LLJITBuilderState &S, ExecutionSession &ES);
/// Create an LLJIT instance with a single compile thread.
- LLJIT(std::unique_ptr<ExecutionSession> ES, std::unique_ptr<TargetMachine> TM,
- DataLayout DL);
-
- /// Create an LLJIT instance with multiple compile threads.
- LLJIT(std::unique_ptr<ExecutionSession> ES, JITTargetMachineBuilder JTMB,
- DataLayout DL, unsigned NumCompileThreads);
+ LLJIT(LLJITBuilderState &S, Error &Err);
std::string mangle(StringRef UnmangledName);
@@ -127,8 +136,8 @@
DataLayout DL;
std::unique_ptr<ThreadPool> CompileThreads;
- RTDyldObjectLinkingLayer ObjLinkingLayer;
- IRCompileLayer CompileLayer;
+ std::unique_ptr<ObjectLayer> ObjLinkingLayer;
+ std::unique_ptr<IRCompileLayer> CompileLayer;
CtorDtorRunner CtorRunner, DtorRunner;
};
@@ -136,25 +145,20 @@
/// An extended version of LLJIT that supports lazy function-at-a-time
/// compilation of LLVM IR.
class LLLazyJIT : public LLJIT {
-public:
+ template <typename, typename, typename> friend class LLJITBuilderSetters;
- /// Create an LLLazyJIT instance.
- /// If NumCompileThreads is not equal to zero, creates a multi-threaded
- /// LLLazyJIT with the given number of compile threads.
- static Expected<std::unique_ptr<LLLazyJIT>>
- Create(JITTargetMachineBuilder JTMB, DataLayout DL,
- JITTargetAddress ErrorAddr, unsigned NumCompileThreads = 0);
+public:
/// Set an IR transform (e.g. pass manager pipeline) to run on each function
/// when it is compiled.
void setLazyCompileTransform(IRTransformLayer::TransformFunction Transform) {
- TransformLayer.setTransform(std::move(Transform));
+ TransformLayer->setTransform(std::move(Transform));
}
/// Sets the partition function.
void
setPartitionFunction(CompileOnDemandLayer::PartitionFunction Partition) {
- CODLayer.setPartitionFunction(std::move(Partition));
+ CODLayer->setPartitionFunction(std::move(Partition));
}
/// Add a module to be lazily compiled to JITDylib JD.
@@ -168,24 +172,144 @@
private:
// Create a single-threaded LLLazyJIT instance.
- LLLazyJIT(std::unique_ptr<ExecutionSession> ES,
- std::unique_ptr<TargetMachine> TM, DataLayout DL,
- std::unique_ptr<LazyCallThroughManager> LCTMgr,
- std::function<std::unique_ptr<IndirectStubsManager>()> ISMBuilder);
-
- // Create a multi-threaded LLLazyJIT instance.
- LLLazyJIT(std::unique_ptr<ExecutionSession> ES, JITTargetMachineBuilder JTMB,
- DataLayout DL, unsigned NumCompileThreads,
- std::unique_ptr<LazyCallThroughManager> LCTMgr,
- std::function<std::unique_ptr<IndirectStubsManager>()> ISMBuilder);
+ LLLazyJIT(LLLazyJITBuilderState &S, Error &Err);
std::unique_ptr<LazyCallThroughManager> LCTMgr;
- std::function<std::unique_ptr<IndirectStubsManager>()> ISMBuilder;
-
- IRTransformLayer TransformLayer;
- CompileOnDemandLayer CODLayer;
+ std::unique_ptr<IRTransformLayer> TransformLayer;
+ std::unique_ptr<CompileOnDemandLayer> CODLayer;
};
+class LLJITBuilderState {
+public:
+ using CreateObjectLinkingLayerFunction =
+ std::function<std::unique_ptr<ObjectLayer>(ExecutionSession &)>;
+
+ std::unique_ptr<ExecutionSession> ES;
+ Optional<JITTargetMachineBuilder> JTMB;
+ CreateObjectLinkingLayerFunction CreateObjectLinkingLayer;
+ unsigned NumCompileThreads = 0;
+
+ /// Called prior to JIT class construcion to fix up defaults.
+ Error prepareForConstruction();
+};
+
+template <typename JITType, typename SetterImpl, typename State>
+class LLJITBuilderSetters {
+public:
+ /// Set the JITTargetMachineBuilder for this instance.
+ ///
+ /// If this method is not called, JITTargetMachineBuilder::detectHost will be
+ /// used to construct a default target machine builder for the host platform.
+ SetterImpl &setJITTargetMachineBuilder(JITTargetMachineBuilder JTMB) {
+ impl().JTMB = std::move(JTMB);
+ return impl();
+ }
+
+ /// Return a reference to the JITTargetMachineBuilder.
+ ///
+ Optional<JITTargetMachineBuilder> &getJITTargetMachineBuilder() {
+ return impl().JTMB;
+ }
+
+ /// Set an ObjectLinkingLayer creation function.
+ ///
+ /// If this method is not called, a default creation function will be used
+ /// that will construct an RTDyldObjectLinkingLayer.
+ SetterImpl &setCreateObjectLinkingLayer(
+ LLJITBuilderState::CreateObjectLinkingLayerFunction
+ CreateObjectLinkingLayer) {
+ impl().CreateObjectLinkingLayer = std::move(CreateObjectLinkingLayer);
+ return impl();
+ }
+
+ /// Set the number of compile threads to use.
+ ///
+ /// If set to zero, compilation will be performed on the execution thread when
+ /// JITing in-process. If set to any other number N, a thread pool of N
+ /// threads will be created for compilation.
+ ///
+ /// If this method is not called, behavior will be as if it were called with
+ /// a zero argument.
+ SetterImpl &setNumCompileThreads(unsigned NumCompileThreads) {
+ impl().NumCompileThreads = NumCompileThreads;
+ return impl();
+ }
+
+ /// Create an instance of the JIT.
+ Expected<std::unique_ptr<JITType>> create() {
+ if (auto Err = impl().prepareForConstruction())
+ return std::move(Err);
+
+ Error Err = Error::success();
+ std::unique_ptr<JITType> J(new JITType(impl(), Err));
+ if (Err)
+ return std::move(Err);
+ return std::move(J);
+ }
+
+protected:
+ SetterImpl &impl() { return static_cast<SetterImpl &>(*this); }
+};
+
+/// Constructs LLJIT instances.
+class LLJITBuilder
+ : public LLJITBuilderState,
+ public LLJITBuilderSetters<LLJIT, LLJITBuilder, LLJITBuilderState> {};
+
+class LLLazyJITBuilderState : public LLJITBuilderState {
+ friend class LLLazyJIT;
+
+public:
+ using IndirectStubsManagerBuilderFunction =
+ std::function<std::unique_ptr<IndirectStubsManager>()>;
+
+ Triple TT;
+ JITTargetAddress LazyCompileFailureAddr = 0;
+ std::unique_ptr<LazyCallThroughManager> LCTMgr;
+ IndirectStubsManagerBuilderFunction ISMBuilder;
+
+ Error prepareForConstruction();
+};
+
+template <typename JITType, typename SetterImpl, typename State>
+class LLLazyJITBuilderSetters
+ : public LLJITBuilderSetters<JITType, SetterImpl, State> {
+public:
+ /// Set the address in the target address to call if a lazy compile fails.
+ ///
+ /// If this method is not called then the value will default to 0.
+ SetterImpl &setLazyCompileFailureAddr(JITTargetAddress Addr) {
+ this->impl().LazyCompileFailureAddr = Addr;
+ return this->impl();
+ }
+
+ /// Set the lazy-callthrough manager.
+ ///
+ /// If this method is not called then a default, in-process lazy callthrough
+ /// manager for the host platform will be used.
+ SetterImpl &
+ setLazyCallthroughManager(std::unique_ptr<LazyCallThroughManager> LCTMgr) {
+ this->impl().LCTMgr = std::move(LCTMgr);
+ return this->impl();
+ }
+
+ /// Set the IndirectStubsManager builder function.
+ ///
+ /// If this method is not called then a default, in-process
+ /// IndirectStubsManager builder for the host platform will be used.
+ SetterImpl &setIndirectStubsManagerBuilder(
+ LLLazyJITBuilderState::IndirectStubsManagerBuilderFunction ISMBuilder) {
+ this->impl().ISMBuilder = std::move(ISMBuilder);
+ return this->impl();
+ }
+};
+
+/// Constructs LLLazyJIT instances.
+class LLLazyJITBuilder
+ : public LLLazyJITBuilderState,
+ public LLLazyJITBuilderSetters<LLLazyJIT, LLLazyJITBuilder,
+ LLLazyJITBuilderState> {};
+
} // End namespace orc
} // End namespace llvm
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/LazyEmittingLayer.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/LazyEmittingLayer.h
index fdf64d0..e5c5feb 100644
--- a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/LazyEmittingLayer.h
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/LazyEmittingLayer.h
@@ -34,8 +34,8 @@
/// Lazy-emitting IR layer.
///
-/// This layer accepts LLVM IR Modules (via addModule), but does not
-/// immediately emit them the layer below. Instead, emissing to the base layer
+/// This layer accepts LLVM IR Modules (via addModule) but does not
+/// immediately emit them the layer below. Instead, emission to the base layer
/// is deferred until the first time the client requests the address (via
/// JITSymbol::getAddress) for a symbol contained in this layer.
template <typename BaseLayerT> class LazyEmittingLayer {
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/Legacy.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/Legacy.h
index e0e5526..f9cbbf6 100644
--- a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/Legacy.h
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/Legacy.h
@@ -148,8 +148,8 @@
for (auto &S : Symbols) {
if (JITSymbol Sym = FindSymbol(*S)) {
if (auto Addr = Sym.getAddress()) {
- Query.resolve(S, JITEvaluatedSymbol(*Addr, Sym.getFlags()));
- Query.notifySymbolReady();
+ Query.notifySymbolMetRequiredState(
+ S, JITEvaluatedSymbol(*Addr, Sym.getFlags()));
NewSymbolsResolved = true;
} else {
ES.legacyFailQuery(Query, Addr.takeError());
@@ -162,11 +162,8 @@
SymbolsNotFound.insert(S);
}
- if (NewSymbolsResolved && Query.isFullyResolved())
- Query.handleFullyResolved();
-
- if (NewSymbolsResolved && Query.isFullyReady())
- Query.handleFullyReady();
+ if (NewSymbolsResolved && Query.isComplete())
+ Query.handleComplete();
return SymbolsNotFound;
}
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h
new file mode 100644
index 0000000..c1e7d27
--- /dev/null
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h
@@ -0,0 +1,165 @@
+//===-- ObjectLinkingLayer.h - JITLink-based jit linking layer --*- C++ -*-===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+// Contains the definition for an JITLink-based, in-process object linking
+// layer.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_EXECUTIONENGINE_ORC_OBJECTLINKINGLAYER_H
+#define LLVM_EXECUTIONENGINE_ORC_OBJECTLINKINGLAYER_H
+
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ExecutionEngine/JITLink/JITLink.h"
+#include "llvm/ExecutionEngine/JITSymbol.h"
+#include "llvm/ExecutionEngine/Orc/Core.h"
+#include "llvm/ExecutionEngine/Orc/Layer.h"
+#include "llvm/Support/Error.h"
+#include <algorithm>
+#include <cassert>
+#include <functional>
+#include <list>
+#include <memory>
+#include <string>
+#include <utility>
+#include <vector>
+
+namespace llvm {
+
+namespace jitlink {
+class EHFrameRegistrar;
+} // namespace jitlink
+
+namespace object {
+class ObjectFile;
+} // namespace object
+
+namespace orc {
+
+class ObjectLinkingLayerJITLinkContext;
+
+/// An ObjectLayer implementation built on JITLink.
+///
+/// Clients can use this class to add relocatable object files to an
+/// ExecutionSession, and it typically serves as the base layer (underneath
+/// a compiling layer like IRCompileLayer) for the rest of the JIT.
+class ObjectLinkingLayer : public ObjectLayer {
+ friend class ObjectLinkingLayerJITLinkContext;
+
+public:
+ /// Plugin instances can be added to the ObjectLinkingLayer to receive
+ /// callbacks when code is loaded or emitted, and when JITLink is being
+ /// configured.
+ class Plugin {
+ public:
+ virtual ~Plugin();
+ virtual void modifyPassConfig(MaterializationResponsibility &MR,
+ const Triple &TT,
+ jitlink::PassConfiguration &Config) {}
+ virtual void notifyLoaded(MaterializationResponsibility &MR) {}
+ virtual Error notifyEmitted(MaterializationResponsibility &MR) {
+ return Error::success();
+ }
+ virtual Error notifyRemovingModule(VModuleKey K) {
+ return Error::success();
+ }
+ virtual Error notifyRemovingAllModules() { return Error::success(); }
+ };
+
+ /// Construct an ObjectLinkingLayer with the given NotifyLoaded,
+ /// and NotifyEmitted functors.
+ ObjectLinkingLayer(ExecutionSession &ES,
+ jitlink::JITLinkMemoryManager &MemMgr);
+
+ /// Destruct an ObjectLinkingLayer.
+ ~ObjectLinkingLayer();
+
+ /// Add a pass-config modifier.
+ ObjectLinkingLayer &addPlugin(std::unique_ptr<Plugin> P) {
+ std::lock_guard<std::mutex> Lock(LayerMutex);
+ Plugins.push_back(std::move(P));
+ return *this;
+ }
+
+ /// Emit the object.
+ void emit(MaterializationResponsibility R,
+ std::unique_ptr<MemoryBuffer> O) override;
+
+ /// 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
+ /// symbol visibility in COFF, which does not use the libObject's
+ /// SF_Exported flag. Use only when generating / adding COFF object files.
+ ///
+ /// FIXME: We should be able to remove this if/when COFF properly tracks
+ /// exported symbols.
+ ObjectLinkingLayer &
+ setOverrideObjectFlagsWithResponsibilityFlags(bool OverrideObjectFlags) {
+ this->OverrideObjectFlags = OverrideObjectFlags;
+ return *this;
+ }
+
+ /// If set, this ObjectLinkingLayer instance will claim responsibility
+ /// for any symbols provided by a given object file that were not already in
+ /// the MaterializationResponsibility instance. Setting this flag allows
+ /// higher-level program representations (e.g. LLVM IR) to be added based on
+ /// only a subset of the symbols they provide, without having to write
+ /// intervening layers to scan and add the additional symbols. This trades
+ /// diagnostic quality for convenience however: If all symbols are enumerated
+ /// up-front then clashes can be detected and reported early (and usually
+ /// deterministically). If this option is set, clashes for the additional
+ /// symbols may not be detected until late, and detection may depend on
+ /// the flow of control through JIT'd code. Use with care.
+ ObjectLinkingLayer &
+ setAutoClaimResponsibilityForObjectSymbols(bool AutoClaimObjectSymbols) {
+ this->AutoClaimObjectSymbols = AutoClaimObjectSymbols;
+ return *this;
+ }
+
+private:
+ using AllocPtr = std::unique_ptr<jitlink::JITLinkMemoryManager::Allocation>;
+
+ void modifyPassConfig(MaterializationResponsibility &MR, const Triple &TT,
+ jitlink::PassConfiguration &PassConfig);
+ void notifyLoaded(MaterializationResponsibility &MR);
+ Error notifyEmitted(MaterializationResponsibility &MR, AllocPtr Alloc);
+
+ Error removeModule(VModuleKey K);
+ Error removeAllModules();
+
+ mutable std::mutex LayerMutex;
+ jitlink::JITLinkMemoryManager &MemMgr;
+ bool OverrideObjectFlags = false;
+ bool AutoClaimObjectSymbols = false;
+ DenseMap<VModuleKey, AllocPtr> TrackedAllocs;
+ std::vector<AllocPtr> UntrackedAllocs;
+ std::vector<std::unique_ptr<Plugin>> Plugins;
+};
+
+class EHFrameRegistrationPlugin : public ObjectLinkingLayer::Plugin {
+public:
+ EHFrameRegistrationPlugin(jitlink::EHFrameRegistrar &Registrar);
+ Error notifyEmitted(MaterializationResponsibility &MR) override;
+ void modifyPassConfig(MaterializationResponsibility &MR, const Triple &TT,
+ jitlink::PassConfiguration &PassConfig) override;
+ Error notifyRemovingModule(VModuleKey K) override;
+ Error notifyRemovingAllModules() override;
+
+private:
+ jitlink::EHFrameRegistrar &Registrar;
+ DenseMap<MaterializationResponsibility *, JITTargetAddress> InProcessLinks;
+ DenseMap<VModuleKey, JITTargetAddress> TrackedEHFrameAddrs;
+ std::vector<JITTargetAddress> UntrackedEHFrameAddrs;
+};
+
+} // end namespace orc
+} // end namespace llvm
+
+#endif // LLVM_EXECUTIONENGINE_ORC_OBJECTLINKINGLAYER_H
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetServer.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetServer.h
index 9684481..4c8e2ea 100644
--- a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetServer.h
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetServer.h
@@ -299,13 +299,13 @@
std::error_code EC;
auto TrampolineBlock =
sys::OwningMemoryBlock(sys::Memory::allocateMappedMemory(
- sys::Process::getPageSize(), nullptr,
+ sys::Process::getPageSizeEstimate(), nullptr,
sys::Memory::MF_READ | sys::Memory::MF_WRITE, EC));
if (EC)
return errorCodeToError(EC);
uint32_t NumTrampolines =
- (sys::Process::getPageSize() - TargetT::PointerSize) /
+ (sys::Process::getPageSizeEstimate() - TargetT::PointerSize) /
TargetT::TrampolineSize;
uint8_t *TrampolineMem = static_cast<uint8_t *>(TrampolineBlock.base());
@@ -335,7 +335,7 @@
handleGetRemoteInfo() {
std::string ProcessTriple = sys::getProcessTriple();
uint32_t PointerSize = TargetT::PointerSize;
- uint32_t PageSize = sys::Process::getPageSize();
+ uint32_t PageSize = sys::Process::getPageSizeEstimate();
uint32_t TrampolineSize = TargetT::TrampolineSize;
uint32_t IndirectStubSize = TargetT::IndirectStubsInfo::StubSize;
LLVM_DEBUG(dbgs() << " Remote info:\n"
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h
index cd9ec36..479658b 100644
--- a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h
@@ -43,22 +43,34 @@
const RuntimeDyld::LoadedObjectInfo &)>;
/// Functor for receiving finalization notifications.
- using NotifyEmittedFunction = std::function<void(VModuleKey)>;
+ using NotifyEmittedFunction =
+ std::function<void(VModuleKey, std::unique_ptr<MemoryBuffer>)>;
using GetMemoryManagerFunction =
std::function<std::unique_ptr<RuntimeDyld::MemoryManager>()>;
/// Construct an ObjectLinkingLayer with the given NotifyLoaded,
/// and NotifyEmitted functors.
- RTDyldObjectLinkingLayer(
- ExecutionSession &ES, GetMemoryManagerFunction GetMemoryManager,
- NotifyLoadedFunction NotifyLoaded = NotifyLoadedFunction(),
- NotifyEmittedFunction NotifyEmitted = NotifyEmittedFunction());
+ RTDyldObjectLinkingLayer(ExecutionSession &ES,
+ GetMemoryManagerFunction GetMemoryManager);
/// Emit the object.
void emit(MaterializationResponsibility R,
std::unique_ptr<MemoryBuffer> O) override;
+ /// Set the NotifyLoaded callback.
+ RTDyldObjectLinkingLayer &setNotifyLoaded(NotifyLoadedFunction NotifyLoaded) {
+ this->NotifyLoaded = std::move(NotifyLoaded);
+ return *this;
+ }
+
+ /// Set the NotifyEmitted callback.
+ RTDyldObjectLinkingLayer &
+ setNotifyEmitted(NotifyEmittedFunction NotifyEmitted) {
+ this->NotifyEmitted = std::move(NotifyEmitted);
+ return *this;
+ }
+
/// Set the 'ProcessAllSections' flag.
///
/// If set to true, all sections in each object file will be allocated using
@@ -108,7 +120,8 @@
std::map<StringRef, JITEvaluatedSymbol> Resolved,
std::set<StringRef> &InternalSymbols);
- void onObjEmit(VModuleKey K, MaterializationResponsibility &R, Error Err);
+ void onObjEmit(VModuleKey K, std::unique_ptr<MemoryBuffer> ObjBuffer,
+ MaterializationResponsibility &R, Error Err);
mutable std::mutex RTDyldLayerMutex;
GetMemoryManagerFunction GetMemoryManager;
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/SymbolStringPool.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/SymbolStringPool.h
index 39fa74b..c354f6c 100644
--- a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/SymbolStringPool.h
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/SymbolStringPool.h
@@ -50,25 +50,20 @@
class SymbolStringPtr {
friend class SymbolStringPool;
friend struct DenseMapInfo<SymbolStringPtr>;
- friend bool operator==(const SymbolStringPtr &LHS,
- const SymbolStringPtr &RHS);
- friend bool operator<(const SymbolStringPtr &LHS, const SymbolStringPtr &RHS);
-
- static SymbolStringPool::PoolMapEntry Tombstone;
public:
SymbolStringPtr() = default;
SymbolStringPtr(const SymbolStringPtr &Other)
: S(Other.S) {
- if (S)
+ if (isRealPoolEntry(S))
++S->getValue();
}
SymbolStringPtr& operator=(const SymbolStringPtr &Other) {
- if (S)
+ if (isRealPoolEntry(S))
--S->getValue();
S = Other.S;
- if (S)
+ if (isRealPoolEntry(S))
++S->getValue();
return *this;
}
@@ -78,7 +73,7 @@
}
SymbolStringPtr& operator=(SymbolStringPtr &&Other) {
- if (S)
+ if (isRealPoolEntry(S))
--S->getValue();
S = nullptr;
std::swap(S, Other.S);
@@ -86,35 +81,65 @@
}
~SymbolStringPtr() {
- if (S)
+ if (isRealPoolEntry(S))
--S->getValue();
}
StringRef operator*() const { return S->first(); }
+ friend bool operator==(const SymbolStringPtr &LHS,
+ const SymbolStringPtr &RHS) {
+ return LHS.S == RHS.S;
+ }
+
+ friend bool operator!=(const SymbolStringPtr &LHS,
+ const SymbolStringPtr &RHS) {
+ return !(LHS == RHS);
+ }
+
+ friend bool operator<(const SymbolStringPtr &LHS,
+ const SymbolStringPtr &RHS) {
+ return LHS.S < RHS.S;
+ }
+
private:
+ using PoolEntryPtr = SymbolStringPool::PoolMapEntry *;
SymbolStringPtr(SymbolStringPool::PoolMapEntry *S)
: S(S) {
- if (S)
+ if (isRealPoolEntry(S))
++S->getValue();
}
- SymbolStringPool::PoolMapEntry *S = nullptr;
+ // Returns false for null, empty, and tombstone values, true otherwise.
+ bool isRealPoolEntry(PoolEntryPtr P) {
+ return ((reinterpret_cast<uintptr_t>(P) - 1) & InvalidPtrMask) !=
+ InvalidPtrMask;
+ }
+
+ static SymbolStringPtr getEmptyVal() {
+ return SymbolStringPtr(reinterpret_cast<PoolEntryPtr>(EmptyBitPattern));
+ }
+
+ static SymbolStringPtr getTombstoneVal() {
+ return SymbolStringPtr(reinterpret_cast<PoolEntryPtr>(TombstoneBitPattern));
+ }
+
+ constexpr static uintptr_t EmptyBitPattern =
+ std::numeric_limits<uintptr_t>::max()
+ << PointerLikeTypeTraits<PoolEntryPtr>::NumLowBitsAvailable;
+
+ constexpr static uintptr_t TombstoneBitPattern =
+ (std::numeric_limits<uintptr_t>::max() - 1)
+ << PointerLikeTypeTraits<PoolEntryPtr>::NumLowBitsAvailable;
+
+ constexpr static uintptr_t InvalidPtrMask =
+ (std::numeric_limits<uintptr_t>::max() - 3)
+ << PointerLikeTypeTraits<PoolEntryPtr>::NumLowBitsAvailable;
+
+ PoolEntryPtr S = nullptr;
};
-inline bool operator==(const SymbolStringPtr &LHS, const SymbolStringPtr &RHS) {
- return LHS.S == RHS.S;
-}
-
-inline bool operator!=(const SymbolStringPtr &LHS, const SymbolStringPtr &RHS) {
- return !(LHS == RHS);
-}
-
-inline bool operator<(const SymbolStringPtr &LHS, const SymbolStringPtr &RHS) {
- return LHS.S < RHS.S;
-}
-
inline SymbolStringPool::~SymbolStringPool() {
#ifndef NDEBUG
clearDeadEntries();
@@ -150,16 +175,15 @@
struct DenseMapInfo<orc::SymbolStringPtr> {
static orc::SymbolStringPtr getEmptyKey() {
- return orc::SymbolStringPtr();
+ return orc::SymbolStringPtr::getEmptyVal();
}
static orc::SymbolStringPtr getTombstoneKey() {
- return orc::SymbolStringPtr(&orc::SymbolStringPtr::Tombstone);
+ return orc::SymbolStringPtr::getTombstoneVal();
}
- static unsigned getHashValue(orc::SymbolStringPtr V) {
- uintptr_t IV = reinterpret_cast<uintptr_t>(V.S);
- return unsigned(IV) ^ unsigned(IV >> 9);
+ static unsigned getHashValue(const orc::SymbolStringPtr &V) {
+ return DenseMapInfo<orc::SymbolStringPtr::PoolEntryPtr>::getHashValue(V.S);
}
static bool isEqual(const orc::SymbolStringPtr &LHS,
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/RuntimeDyld.h b/linux-x64/clang/include/llvm/ExecutionEngine/RuntimeDyld.h
index 2af9203..b2b4eba 100644
--- a/linux-x64/clang/include/llvm/ExecutionEngine/RuntimeDyld.h
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/RuntimeDyld.h
@@ -52,18 +52,19 @@
std::string ErrMsg;
};
-class RuntimeDyldCheckerImpl;
class RuntimeDyldImpl;
class RuntimeDyld {
- friend class RuntimeDyldCheckerImpl;
-
protected:
// Change the address associated with a section when resolving relocations.
// Any relocations already associated with the symbol will be re-resolved.
void reassignSectionAddress(unsigned SectionID, uint64_t Addr);
public:
+ using NotifyStubEmittedFunction = std::function<void(
+ StringRef FileName, StringRef SectionName, StringRef SymbolName,
+ unsigned SectionID, uint32_t StubOffset)>;
+
/// Information about the loaded object.
class LoadedObjectInfo : public llvm::LoadedObjectInfo {
friend class RuntimeDyldImpl;
@@ -184,6 +185,9 @@
/// and resolve relocatons based on where they put it).
void *getSymbolLocalAddress(StringRef Name) const;
+ /// Get the section ID for the section containing the given symbol.
+ unsigned getSymbolSectionID(StringRef Name) const;
+
/// Get the target address and flags for the named symbol.
/// This address is the one used for relocation.
JITEvaluatedSymbol getSymbol(StringRef Name) const;
@@ -204,6 +208,19 @@
/// This is the address which will be used for relocation resolution.
void mapSectionAddress(const void *LocalAddress, uint64_t TargetAddress);
+ /// Returns the section's working memory.
+ StringRef getSectionContent(unsigned SectionID) const;
+
+ /// If the section was loaded, return the section's load address,
+ /// otherwise return None.
+ uint64_t getSectionLoadAddress(unsigned SectionID) const;
+
+ /// Set the NotifyStubEmitted callback. This is used for debugging
+ /// purposes. A callback is made for each stub that is generated.
+ void setNotifyStubEmitted(NotifyStubEmittedFunction NotifyStubEmitted) {
+ this->NotifyStubEmitted = std::move(NotifyStubEmitted);
+ }
+
/// Register any EH frame sections that have been loaded but not previously
/// registered with the memory manager. Note, RuntimeDyld is responsible
/// for identifying the EH frame and calling the memory manager with the
@@ -265,7 +282,7 @@
MemoryManager &MemMgr;
JITSymbolResolver &Resolver;
bool ProcessAllSections;
- RuntimeDyldCheckerImpl *Checker;
+ NotifyStubEmittedFunction NotifyStubEmitted;
};
// Asynchronous JIT link for ORC.
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/RuntimeDyldChecker.h b/linux-x64/clang/include/llvm/ExecutionEngine/RuntimeDyldChecker.h
index ee925c2..93ea091 100644
--- a/linux-x64/clang/include/llvm/ExecutionEngine/RuntimeDyldChecker.h
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/RuntimeDyldChecker.h
@@ -9,7 +9,10 @@
#ifndef LLVM_EXECUTIONENGINE_RUNTIMEDYLDCHECKER_H
#define LLVM_EXECUTIONENGINE_RUNTIMEDYLDCHECKER_H
+#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/Optional.h"
+#include "llvm/ExecutionEngine/JITSymbol.h"
+#include "llvm/Support/Endian.h"
#include <cstdint>
#include <memory>
@@ -57,7 +60,8 @@
///
/// ident_expr = 'decode_operand' '(' symbol ',' operand-index ')'
/// | 'next_pc' '(' symbol ')'
-/// | 'stub_addr' '(' file-name ',' section-name ',' symbol ')'
+/// | 'stub_addr' '(' stub-container-name ',' symbol ')'
+/// | 'got_addr' '(' stub-container-name ',' symbol ')'
/// | symbol
///
/// binary_expr = expr '+' expr
@@ -69,16 +73,85 @@
///
class RuntimeDyldChecker {
public:
- RuntimeDyldChecker(RuntimeDyld &RTDyld, MCDisassembler *Disassembler,
- MCInstPrinter *InstPrinter, raw_ostream &ErrStream);
+ class MemoryRegionInfo {
+ public:
+ MemoryRegionInfo() = default;
+
+ /// Constructor for symbols/sections with content.
+ MemoryRegionInfo(StringRef Content, JITTargetAddress TargetAddress)
+ : ContentPtr(Content.data()), Size(Content.size()),
+ TargetAddress(TargetAddress) {}
+
+ /// Constructor for zero-fill symbols/sections.
+ MemoryRegionInfo(uint64_t Size, JITTargetAddress TargetAddress)
+ : Size(Size), TargetAddress(TargetAddress) {}
+
+ /// Returns true if this is a zero-fill symbol/section.
+ bool isZeroFill() const {
+ assert(Size && "setContent/setZeroFill must be called first");
+ return !ContentPtr;
+ }
+
+ /// Set the content for this memory region.
+ void setContent(StringRef Content) {
+ assert(!ContentPtr && !Size && "Content/zero-fill already set");
+ ContentPtr = Content.data();
+ Size = Content.size();
+ }
+
+ /// Set a zero-fill length for this memory region.
+ void setZeroFill(uint64_t Size) {
+ assert(!ContentPtr && !this->Size && "Content/zero-fill already set");
+ this->Size = Size;
+ }
+
+ /// Returns the content for this section if there is any.
+ StringRef getContent() const {
+ assert(!isZeroFill() && "Can't get content for a zero-fill section");
+ return StringRef(ContentPtr, static_cast<size_t>(Size));
+ }
+
+ /// Returns the zero-fill length for this section.
+ uint64_t getZeroFillLength() const {
+ assert(isZeroFill() && "Can't get zero-fill length for content section");
+ return Size;
+ }
+
+ /// Set the target address for this region.
+ void setTargetAddress(JITTargetAddress TargetAddress) {
+ assert(!this->TargetAddress && "TargetAddress already set");
+ this->TargetAddress = TargetAddress;
+ }
+
+ /// Return the target address for this region.
+ JITTargetAddress getTargetAddress() const { return TargetAddress; }
+
+ private:
+ const char *ContentPtr = 0;
+ uint64_t Size = 0;
+ JITTargetAddress TargetAddress = 0;
+ };
+
+ using IsSymbolValidFunction = std::function<bool(StringRef Symbol)>;
+ using GetSymbolInfoFunction =
+ std::function<Expected<MemoryRegionInfo>(StringRef SymbolName)>;
+ using GetSectionInfoFunction = std::function<Expected<MemoryRegionInfo>(
+ StringRef FileName, StringRef SectionName)>;
+ using GetStubInfoFunction = std::function<Expected<MemoryRegionInfo>(
+ StringRef StubContainer, StringRef TargetName)>;
+ using GetGOTInfoFunction = std::function<Expected<MemoryRegionInfo>(
+ StringRef GOTContainer, StringRef TargetName)>;
+
+ RuntimeDyldChecker(IsSymbolValidFunction IsSymbolValid,
+ GetSymbolInfoFunction GetSymbolInfo,
+ GetSectionInfoFunction GetSectionInfo,
+ GetStubInfoFunction GetStubInfo,
+ GetGOTInfoFunction GetGOTInfo,
+ support::endianness Endianness,
+ MCDisassembler *Disassembler, MCInstPrinter *InstPrinter,
+ raw_ostream &ErrStream);
~RuntimeDyldChecker();
- // Get the associated RTDyld instance.
- RuntimeDyld& getRTDyld();
-
- // Get the associated RTDyld instance.
- const RuntimeDyld& getRTDyld() const;
-
/// Check a single expression against the attached RuntimeDyld
/// instance.
bool check(StringRef CheckExpr) const;
@@ -99,7 +172,7 @@
bool LocalAddress);
/// If there is a section at the given local address, return its load
- /// address, otherwise return none.
+ /// address, otherwise return none.
Optional<uint64_t> getSectionLoadAddress(void *LocalAddress) const;
private: