//===------------ 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
