//===------------- JITLink.cpp - Core Run-time JIT linker APIs ------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "llvm/ExecutionEngine/JITLink/JITLink.h"

#include "llvm/BinaryFormat/Magic.h"
#include "llvm/ExecutionEngine/JITLink/MachO.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/raw_ostream.h"

using namespace llvm;
using namespace llvm::object;

#define DEBUG_TYPE "jitlink"

namespace {

enum JITLinkErrorCode { GenericJITLinkError = 1 };

// FIXME: This class is only here to support the transition to llvm::Error. It
// will be removed once this transition is complete. Clients should prefer to
// deal with the Error value directly, rather than converting to error_code.
class JITLinkerErrorCategory : public std::error_category {
public:
  const char *name() const noexcept override { return "runtimedyld"; }

  std::string message(int Condition) const override {
    switch (static_cast<JITLinkErrorCode>(Condition)) {
    case GenericJITLinkError:
      return "Generic JITLink error";
    }
    llvm_unreachable("Unrecognized JITLinkErrorCode");
  }
};

static ManagedStatic<JITLinkerErrorCategory> JITLinkerErrorCategory;

} // namespace

namespace llvm {
namespace jitlink {

char JITLinkError::ID = 0;

void JITLinkError::log(raw_ostream &OS) const { OS << ErrMsg << "\n"; }

std::error_code JITLinkError::convertToErrorCode() const {
  return std::error_code(GenericJITLinkError, *JITLinkerErrorCategory);
}

const char *getGenericEdgeKindName(Edge::Kind K) {
  switch (K) {
  case Edge::Invalid:
    return "INVALID RELOCATION";
  case Edge::KeepAlive:
    return "Keep-Alive";
  default:
    llvm_unreachable("Unrecognized relocation kind");
  }
}

const char *getLinkageName(Linkage L) {
  switch (L) {
  case Linkage::Strong:
    return "strong";
  case Linkage::Weak:
    return "weak";
  }
  llvm_unreachable("Unrecognized llvm.jitlink.Linkage enum");
}

const char *getScopeName(Scope S) {
  switch (S) {
  case Scope::Default:
    return "default";
  case Scope::Hidden:
    return "hidden";
  case Scope::Local:
    return "local";
  }
  llvm_unreachable("Unrecognized llvm.jitlink.Scope enum");
}

raw_ostream &operator<<(raw_ostream &OS, const Block &B) {
  return OS << formatv("{0:x16}", B.getAddress()) << " -- "
            << formatv("{0:x16}", B.getAddress() + B.getSize()) << ": "
            << (B.isZeroFill() ? "zero-fill" : "content")
            << ", align = " << B.getAlignment()
            << ", align-ofs = " << B.getAlignmentOffset()
            << ", section = " << B.getSection().getName();
}

raw_ostream &operator<<(raw_ostream &OS, const Symbol &Sym) {
  OS << "<";
  if (Sym.getName().empty())
    OS << "*anon*";
  else
    OS << Sym.getName();
  OS << ": flags = ";
  switch (Sym.getLinkage()) {
  case Linkage::Strong:
    OS << 'S';
    break;
  case Linkage::Weak:
    OS << 'W';
    break;
  }
  switch (Sym.getScope()) {
  case Scope::Default:
    OS << 'D';
    break;
  case Scope::Hidden:
    OS << 'H';
    break;
  case Scope::Local:
    OS << 'L';
    break;
  }
  OS << (Sym.isLive() ? '+' : '-')
     << ", size = " << formatv("{0:x8}", Sym.getSize())
     << ", addr = " << formatv("{0:x16}", Sym.getAddress()) << " ("
     << formatv("{0:x16}", Sym.getAddressable().getAddress()) << " + "
     << formatv("{0:x8}", Sym.getOffset());
  if (Sym.isDefined())
    OS << " " << Sym.getBlock().getSection().getName();
  OS << ")>";
  return OS;
}

void printEdge(raw_ostream &OS, const Block &B, const Edge &E,
               StringRef EdgeKindName) {
  OS << "edge@" << formatv("{0:x16}", B.getAddress() + E.getOffset()) << ": "
     << formatv("{0:x16}", B.getAddress()) << " + " << E.getOffset() << " -- "
     << EdgeKindName << " -> " << E.getTarget() << " + " << E.getAddend();
}

Section::~Section() {
  for (auto *Sym : Symbols)
    Sym->~Symbol();
  for (auto *B : Blocks)
    B->~Block();
}

Block &LinkGraph::splitBlock(Block &B, size_t SplitIndex,
                             SplitBlockCache *Cache) {

  assert(SplitIndex > 0 && "splitBlock can not be called with SplitIndex == 0");

  // If the split point covers all of B then just return B.
  if (SplitIndex == B.getSize())
    return B;

  assert(SplitIndex < B.getSize() && "SplitIndex out of range");

  // Create the new block covering [ 0, SplitIndex ).
  auto &NewBlock =
      B.isZeroFill()
          ? createZeroFillBlock(B.getSection(), SplitIndex, B.getAddress(),
                                B.getAlignment(), B.getAlignmentOffset())
          : createContentBlock(
                B.getSection(), B.getContent().substr(0, SplitIndex),
                B.getAddress(), B.getAlignment(), B.getAlignmentOffset());

  // Modify B to cover [ SplitIndex, B.size() ).
  B.setAddress(B.getAddress() + SplitIndex);
  B.setContent(B.getContent().substr(SplitIndex));
  B.setAlignmentOffset((B.getAlignmentOffset() + SplitIndex) %
                       B.getAlignment());

  // Handle edge transfer/update.
  {
    // Copy edges to NewBlock (recording their iterators so that we can remove
    // them from B), and update of Edges remaining on B.
    std::vector<Block::edge_iterator> EdgesToRemove;
    for (auto I = B.edges().begin(), E = B.edges().end(); I != E; ++I) {
      if (I->getOffset() < SplitIndex) {
        NewBlock.addEdge(*I);
        EdgesToRemove.push_back(I);
      } else
        I->setOffset(I->getOffset() - SplitIndex);
    }

    // Remove edges that were transfered to NewBlock from B.
    while (!EdgesToRemove.empty()) {
      B.removeEdge(EdgesToRemove.back());
      EdgesToRemove.pop_back();
    }
  }

  // Handle symbol transfer/update.
  {
    // Initialize the symbols cache if necessary.
    SplitBlockCache LocalBlockSymbolsCache;
    if (!Cache)
      Cache = &LocalBlockSymbolsCache;
    if (*Cache == None) {
      *Cache = SplitBlockCache::value_type();
      for (auto *Sym : B.getSection().symbols())
        if (&Sym->getBlock() == &B)
          (*Cache)->push_back(Sym);

      llvm::sort(**Cache, [](const Symbol *LHS, const Symbol *RHS) {
        return LHS->getOffset() > RHS->getOffset();
      });
    }
    auto &BlockSymbols = **Cache;

    // Transfer all symbols with offset less than SplitIndex to NewBlock.
    while (!BlockSymbols.empty() &&
           BlockSymbols.back()->getOffset() < SplitIndex) {
      BlockSymbols.back()->setBlock(NewBlock);
      BlockSymbols.pop_back();
    }

    // Update offsets for all remaining symbols in B.
    for (auto *Sym : BlockSymbols)
      Sym->setOffset(Sym->getOffset() - SplitIndex);
  }

  return NewBlock;
}

void LinkGraph::dump(raw_ostream &OS,
                     std::function<StringRef(Edge::Kind)> EdgeKindToName) {
  if (!EdgeKindToName)
    EdgeKindToName = [](Edge::Kind K) { return StringRef(); };

  OS << "Symbols:\n";
  for (auto *Sym : defined_symbols()) {
    OS << "  " << format("0x%016" PRIx64, Sym->getAddress()) << ": " << *Sym
       << "\n";
    if (Sym->isDefined()) {
      for (auto &E : Sym->getBlock().edges()) {
        OS << "    ";
        StringRef EdgeName = (E.getKind() < Edge::FirstRelocation
                                  ? getGenericEdgeKindName(E.getKind())
                                  : EdgeKindToName(E.getKind()));

        if (!EdgeName.empty())
          printEdge(OS, Sym->getBlock(), E, EdgeName);
        else {
          auto EdgeNumberString = std::to_string(E.getKind());
          printEdge(OS, Sym->getBlock(), E, EdgeNumberString);
        }
        OS << "\n";
      }
    }
  }

  OS << "Absolute symbols:\n";
  for (auto *Sym : absolute_symbols())
    OS << "  " << format("0x%016" PRIx64, Sym->getAddress()) << ": " << *Sym
       << "\n";

  OS << "External symbols:\n";
  for (auto *Sym : external_symbols())
    OS << "  " << format("0x%016" PRIx64, Sym->getAddress()) << ": " << *Sym
       << "\n";
}

raw_ostream &operator<<(raw_ostream &OS, const SymbolLookupFlags &LF) {
  switch (LF) {
  case SymbolLookupFlags::RequiredSymbol:
    return OS << "RequiredSymbol";
  case SymbolLookupFlags::WeaklyReferencedSymbol:
    return OS << "WeaklyReferencedSymbol";
  }
  llvm_unreachable("Unrecognized lookup flags");
}

void JITLinkAsyncLookupContinuation::anchor() {}

JITLinkContext::~JITLinkContext() {}

bool JITLinkContext::shouldAddDefaultTargetPasses(const Triple &TT) const {
  return true;
}

LinkGraphPassFunction JITLinkContext::getMarkLivePass(const Triple &TT) const {
  return LinkGraphPassFunction();
}

Error JITLinkContext::modifyPassConfig(const Triple &TT,
                                       PassConfiguration &Config) {
  return Error::success();
}

Error markAllSymbolsLive(LinkGraph &G) {
  for (auto *Sym : G.defined_symbols())
    Sym->setLive(true);
  return Error::success();
}

void jitLink(std::unique_ptr<JITLinkContext> Ctx) {
  auto Magic = identify_magic(Ctx->getObjectBuffer().getBuffer());
  switch (Magic) {
  case file_magic::macho_object:
    return jitLink_MachO(std::move(Ctx));
  default:
    Ctx->notifyFailed(make_error<JITLinkError>("Unsupported file format"));
  };
}

} // end namespace jitlink
} // end namespace llvm
