//===-- MCJIT.cpp - MC-based Just-in-Time Compiler ------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "MCJIT.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ExecutionEngine/GenericValue.h"
#include "llvm/ExecutionEngine/JITEventListener.h"
#include "llvm/ExecutionEngine/MCJIT.h"
#include "llvm/ExecutionEngine/SectionMemoryManager.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/IR/Mangler.h"
#include "llvm/IR/Module.h"
#include "llvm/Object/Archive.h"
#include "llvm/Object/ObjectFile.h"
#include "llvm/Support/DynamicLibrary.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/MutexGuard.h"

using namespace llvm;

namespace {

static struct RegisterJIT {
  RegisterJIT() { MCJIT::Register(); }
} JITRegistrator;

}

extern "C" void LLVMLinkInMCJIT() {
}

ExecutionEngine *
MCJIT::createJIT(std::unique_ptr<Module> M, std::string *ErrorStr,
                 std::shared_ptr<MCJITMemoryManager> MemMgr,
                 std::shared_ptr<LegacyJITSymbolResolver> Resolver,
                 std::unique_ptr<TargetMachine> TM) {
  // Try to register the program as a source of symbols to resolve against.
  //
  // FIXME: Don't do this here.
  sys::DynamicLibrary::LoadLibraryPermanently(nullptr, nullptr);

  if (!MemMgr || !Resolver) {
    auto RTDyldMM = std::make_shared<SectionMemoryManager>();
    if (!MemMgr)
      MemMgr = RTDyldMM;
    if (!Resolver)
      Resolver = RTDyldMM;
  }

  return new MCJIT(std::move(M), std::move(TM), std::move(MemMgr),
                   std::move(Resolver));
}

MCJIT::MCJIT(std::unique_ptr<Module> M, std::unique_ptr<TargetMachine> TM,
             std::shared_ptr<MCJITMemoryManager> MemMgr,
             std::shared_ptr<LegacyJITSymbolResolver> Resolver)
    : ExecutionEngine(TM->createDataLayout(), std::move(M)), TM(std::move(TM)),
      Ctx(nullptr), MemMgr(std::move(MemMgr)),
      Resolver(*this, std::move(Resolver)), Dyld(*this->MemMgr, this->Resolver),
      ObjCache(nullptr) {
  // FIXME: We are managing our modules, so we do not want the base class
  // ExecutionEngine to manage them as well. To avoid double destruction
  // of the first (and only) module added in ExecutionEngine constructor
  // we remove it from EE and will destruct it ourselves.
  //
  // It may make sense to move our module manager (based on SmallStPtr) back
  // into EE if the JIT and Interpreter can live with it.
  // If so, additional functions: addModule, removeModule, FindFunctionNamed,
  // runStaticConstructorsDestructors could be moved back to EE as well.
  //
  std::unique_ptr<Module> First = std::move(Modules[0]);
  Modules.clear();

  if (First->getDataLayout().isDefault())
    First->setDataLayout(getDataLayout());

  OwnedModules.addModule(std::move(First));
  RegisterJITEventListener(JITEventListener::createGDBRegistrationListener());
}

MCJIT::~MCJIT() {
  MutexGuard locked(lock);

  Dyld.deregisterEHFrames();

  for (auto &Obj : LoadedObjects)
    if (Obj)
      NotifyFreeingObject(*Obj);

  Archives.clear();
}

void MCJIT::addModule(std::unique_ptr<Module> M) {
  MutexGuard locked(lock);

  if (M->getDataLayout().isDefault())
    M->setDataLayout(getDataLayout());

  OwnedModules.addModule(std::move(M));
}

bool MCJIT::removeModule(Module *M) {
  MutexGuard locked(lock);
  return OwnedModules.removeModule(M);
}

void MCJIT::addObjectFile(std::unique_ptr<object::ObjectFile> Obj) {
  std::unique_ptr<RuntimeDyld::LoadedObjectInfo> L = Dyld.loadObject(*Obj);
  if (Dyld.hasError())
    report_fatal_error(Dyld.getErrorString());

  NotifyObjectEmitted(*Obj, *L);

  LoadedObjects.push_back(std::move(Obj));
}

void MCJIT::addObjectFile(object::OwningBinary<object::ObjectFile> Obj) {
  std::unique_ptr<object::ObjectFile> ObjFile;
  std::unique_ptr<MemoryBuffer> MemBuf;
  std::tie(ObjFile, MemBuf) = Obj.takeBinary();
  addObjectFile(std::move(ObjFile));
  Buffers.push_back(std::move(MemBuf));
}

void MCJIT::addArchive(object::OwningBinary<object::Archive> A) {
  Archives.push_back(std::move(A));
}

void MCJIT::setObjectCache(ObjectCache* NewCache) {
  MutexGuard locked(lock);
  ObjCache = NewCache;
}

std::unique_ptr<MemoryBuffer> MCJIT::emitObject(Module *M) {
  assert(M && "Can not emit a null module");

  MutexGuard locked(lock);

  // Materialize all globals in the module if they have not been
  // materialized already.
  cantFail(M->materializeAll());

  // This must be a module which has already been added but not loaded to this
  // MCJIT instance, since these conditions are tested by our caller,
  // generateCodeForModule.

  legacy::PassManager PM;

  // The RuntimeDyld will take ownership of this shortly
  SmallVector<char, 4096> ObjBufferSV;
  raw_svector_ostream ObjStream(ObjBufferSV);

  // Turn the machine code intermediate representation into bytes in memory
  // that may be executed.
  if (TM->addPassesToEmitMC(PM, Ctx, ObjStream, !getVerifyModules()))
    report_fatal_error("Target does not support MC emission!");

  // Initialize passes.
  PM.run(*M);
  // Flush the output buffer to get the generated code into memory

  std::unique_ptr<MemoryBuffer> CompiledObjBuffer(
      new SmallVectorMemoryBuffer(std::move(ObjBufferSV)));

  // If we have an object cache, tell it about the new object.
  // Note that we're using the compiled image, not the loaded image (as below).
  if (ObjCache) {
    // MemoryBuffer is a thin wrapper around the actual memory, so it's OK
    // to create a temporary object here and delete it after the call.
    MemoryBufferRef MB = CompiledObjBuffer->getMemBufferRef();
    ObjCache->notifyObjectCompiled(M, MB);
  }

  return CompiledObjBuffer;
}

void MCJIT::generateCodeForModule(Module *M) {
  // Get a thread lock to make sure we aren't trying to load multiple times
  MutexGuard locked(lock);

  // This must be a module which has already been added to this MCJIT instance.
  assert(OwnedModules.ownsModule(M) &&
         "MCJIT::generateCodeForModule: Unknown module.");

  // Re-compilation is not supported
  if (OwnedModules.hasModuleBeenLoaded(M))
    return;

  std::unique_ptr<MemoryBuffer> ObjectToLoad;
  // Try to load the pre-compiled object from cache if possible
  if (ObjCache)
    ObjectToLoad = ObjCache->getObject(M);

  assert(M->getDataLayout() == getDataLayout() && "DataLayout Mismatch");

  // If the cache did not contain a suitable object, compile the object
  if (!ObjectToLoad) {
    ObjectToLoad = emitObject(M);
    assert(ObjectToLoad && "Compilation did not produce an object.");
  }

  // Load the object into the dynamic linker.
  // MCJIT now owns the ObjectImage pointer (via its LoadedObjects list).
  Expected<std::unique_ptr<object::ObjectFile>> LoadedObject =
    object::ObjectFile::createObjectFile(ObjectToLoad->getMemBufferRef());
  if (!LoadedObject) {
    std::string Buf;
    raw_string_ostream OS(Buf);
    logAllUnhandledErrors(LoadedObject.takeError(), OS, "");
    OS.flush();
    report_fatal_error(Buf);
  }
  std::unique_ptr<RuntimeDyld::LoadedObjectInfo> L =
    Dyld.loadObject(*LoadedObject.get());

  if (Dyld.hasError())
    report_fatal_error(Dyld.getErrorString());

  NotifyObjectEmitted(*LoadedObject.get(), *L);

  Buffers.push_back(std::move(ObjectToLoad));
  LoadedObjects.push_back(std::move(*LoadedObject));

  OwnedModules.markModuleAsLoaded(M);
}

void MCJIT::finalizeLoadedModules() {
  MutexGuard locked(lock);

  // Resolve any outstanding relocations.
  Dyld.resolveRelocations();

  OwnedModules.markAllLoadedModulesAsFinalized();

  // Register EH frame data for any module we own which has been loaded
  Dyld.registerEHFrames();

  // Set page permissions.
  MemMgr->finalizeMemory();
}

// FIXME: Rename this.
void MCJIT::finalizeObject() {
  MutexGuard locked(lock);

  // Generate code for module is going to move objects out of the 'added' list,
  // so we need to copy that out before using it:
  SmallVector<Module*, 16> ModsToAdd;
  for (auto M : OwnedModules.added())
    ModsToAdd.push_back(M);

  for (auto M : ModsToAdd)
    generateCodeForModule(M);

  finalizeLoadedModules();
}

void MCJIT::finalizeModule(Module *M) {
  MutexGuard locked(lock);

  // This must be a module which has already been added to this MCJIT instance.
  assert(OwnedModules.ownsModule(M) && "MCJIT::finalizeModule: Unknown module.");

  // If the module hasn't been compiled, just do that.
  if (!OwnedModules.hasModuleBeenLoaded(M))
    generateCodeForModule(M);

  finalizeLoadedModules();
}

JITSymbol MCJIT::findExistingSymbol(const std::string &Name) {
  if (void *Addr = getPointerToGlobalIfAvailable(Name))
    return JITSymbol(static_cast<uint64_t>(
                         reinterpret_cast<uintptr_t>(Addr)),
                     JITSymbolFlags::Exported);

  return Dyld.getSymbol(Name);
}

Module *MCJIT::findModuleForSymbol(const std::string &Name,
                                   bool CheckFunctionsOnly) {
  StringRef DemangledName = Name;
  if (DemangledName[0] == getDataLayout().getGlobalPrefix())
    DemangledName = DemangledName.substr(1);

  MutexGuard locked(lock);

  // If it hasn't already been generated, see if it's in one of our modules.
  for (ModulePtrSet::iterator I = OwnedModules.begin_added(),
                              E = OwnedModules.end_added();
       I != E; ++I) {
    Module *M = *I;
    Function *F = M->getFunction(DemangledName);
    if (F && !F->isDeclaration())
      return M;
    if (!CheckFunctionsOnly) {
      GlobalVariable *G = M->getGlobalVariable(DemangledName);
      if (G && !G->isDeclaration())
        return M;
      // FIXME: Do we need to worry about global aliases?
    }
  }
  // We didn't find the symbol in any of our modules.
  return nullptr;
}

uint64_t MCJIT::getSymbolAddress(const std::string &Name,
                                 bool CheckFunctionsOnly) {
  std::string MangledName;
  {
    raw_string_ostream MangledNameStream(MangledName);
    Mangler::getNameWithPrefix(MangledNameStream, Name, getDataLayout());
  }
  if (auto Sym = findSymbol(MangledName, CheckFunctionsOnly)) {
    if (auto AddrOrErr = Sym.getAddress())
      return *AddrOrErr;
    else
      report_fatal_error(AddrOrErr.takeError());
  } else
    report_fatal_error(Sym.takeError());
}

JITSymbol MCJIT::findSymbol(const std::string &Name,
                            bool CheckFunctionsOnly) {
  MutexGuard locked(lock);

  // First, check to see if we already have this symbol.
  if (auto Sym = findExistingSymbol(Name))
    return Sym;

  for (object::OwningBinary<object::Archive> &OB : Archives) {
    object::Archive *A = OB.getBinary();
    // Look for our symbols in each Archive
    auto OptionalChildOrErr = A->findSym(Name);
    if (!OptionalChildOrErr)
      report_fatal_error(OptionalChildOrErr.takeError());
    auto &OptionalChild = *OptionalChildOrErr;
    if (OptionalChild) {
      // FIXME: Support nested archives?
      Expected<std::unique_ptr<object::Binary>> ChildBinOrErr =
          OptionalChild->getAsBinary();
      if (!ChildBinOrErr) {
        // TODO: Actually report errors helpfully.
        consumeError(ChildBinOrErr.takeError());
        continue;
      }
      std::unique_ptr<object::Binary> &ChildBin = ChildBinOrErr.get();
      if (ChildBin->isObject()) {
        std::unique_ptr<object::ObjectFile> OF(
            static_cast<object::ObjectFile *>(ChildBin.release()));
        // This causes the object file to be loaded.
        addObjectFile(std::move(OF));
        // The address should be here now.
        if (auto Sym = findExistingSymbol(Name))
          return Sym;
      }
    }
  }

  // If it hasn't already been generated, see if it's in one of our modules.
  Module *M = findModuleForSymbol(Name, CheckFunctionsOnly);
  if (M) {
    generateCodeForModule(M);

    // Check the RuntimeDyld table again, it should be there now.
    return findExistingSymbol(Name);
  }

  // If a LazyFunctionCreator is installed, use it to get/create the function.
  // FIXME: Should we instead have a LazySymbolCreator callback?
  if (LazyFunctionCreator) {
    auto Addr = static_cast<uint64_t>(
                  reinterpret_cast<uintptr_t>(LazyFunctionCreator(Name)));
    return JITSymbol(Addr, JITSymbolFlags::Exported);
  }

  return nullptr;
}

uint64_t MCJIT::getGlobalValueAddress(const std::string &Name) {
  MutexGuard locked(lock);
  uint64_t Result = getSymbolAddress(Name, false);
  if (Result != 0)
    finalizeLoadedModules();
  return Result;
}

uint64_t MCJIT::getFunctionAddress(const std::string &Name) {
  MutexGuard locked(lock);
  uint64_t Result = getSymbolAddress(Name, true);
  if (Result != 0)
    finalizeLoadedModules();
  return Result;
}

// Deprecated.  Use getFunctionAddress instead.
void *MCJIT::getPointerToFunction(Function *F) {
  MutexGuard locked(lock);

  Mangler Mang;
  SmallString<128> Name;
  TM->getNameWithPrefix(Name, F, Mang);

  if (F->isDeclaration() || F->hasAvailableExternallyLinkage()) {
    bool AbortOnFailure = !F->hasExternalWeakLinkage();
    void *Addr = getPointerToNamedFunction(Name, AbortOnFailure);
    updateGlobalMapping(F, Addr);
    return Addr;
  }

  Module *M = F->getParent();
  bool HasBeenAddedButNotLoaded = OwnedModules.hasModuleBeenAddedButNotLoaded(M);

  // Make sure the relevant module has been compiled and loaded.
  if (HasBeenAddedButNotLoaded)
    generateCodeForModule(M);
  else if (!OwnedModules.hasModuleBeenLoaded(M)) {
    // If this function doesn't belong to one of our modules, we're done.
    // FIXME: Asking for the pointer to a function that hasn't been registered,
    //        and isn't a declaration (which is handled above) should probably
    //        be an assertion.
    return nullptr;
  }

  // FIXME: Should the Dyld be retaining module information? Probably not.
  //
  // This is the accessor for the target address, so make sure to check the
  // load address of the symbol, not the local address.
  return (void*)Dyld.getSymbol(Name).getAddress();
}

void MCJIT::runStaticConstructorsDestructorsInModulePtrSet(
    bool isDtors, ModulePtrSet::iterator I, ModulePtrSet::iterator E) {
  for (; I != E; ++I) {
    ExecutionEngine::runStaticConstructorsDestructors(**I, isDtors);
  }
}

void MCJIT::runStaticConstructorsDestructors(bool isDtors) {
  // Execute global ctors/dtors for each module in the program.
  runStaticConstructorsDestructorsInModulePtrSet(
      isDtors, OwnedModules.begin_added(), OwnedModules.end_added());
  runStaticConstructorsDestructorsInModulePtrSet(
      isDtors, OwnedModules.begin_loaded(), OwnedModules.end_loaded());
  runStaticConstructorsDestructorsInModulePtrSet(
      isDtors, OwnedModules.begin_finalized(), OwnedModules.end_finalized());
}

Function *MCJIT::FindFunctionNamedInModulePtrSet(StringRef FnName,
                                                 ModulePtrSet::iterator I,
                                                 ModulePtrSet::iterator E) {
  for (; I != E; ++I) {
    Function *F = (*I)->getFunction(FnName);
    if (F && !F->isDeclaration())
      return F;
  }
  return nullptr;
}

GlobalVariable *MCJIT::FindGlobalVariableNamedInModulePtrSet(StringRef Name,
                                                             bool AllowInternal,
                                                             ModulePtrSet::iterator I,
                                                             ModulePtrSet::iterator E) {
  for (; I != E; ++I) {
    GlobalVariable *GV = (*I)->getGlobalVariable(Name, AllowInternal);
    if (GV && !GV->isDeclaration())
      return GV;
  }
  return nullptr;
}


Function *MCJIT::FindFunctionNamed(StringRef FnName) {
  Function *F = FindFunctionNamedInModulePtrSet(
      FnName, OwnedModules.begin_added(), OwnedModules.end_added());
  if (!F)
    F = FindFunctionNamedInModulePtrSet(FnName, OwnedModules.begin_loaded(),
                                        OwnedModules.end_loaded());
  if (!F)
    F = FindFunctionNamedInModulePtrSet(FnName, OwnedModules.begin_finalized(),
                                        OwnedModules.end_finalized());
  return F;
}

GlobalVariable *MCJIT::FindGlobalVariableNamed(StringRef Name, bool AllowInternal) {
  GlobalVariable *GV = FindGlobalVariableNamedInModulePtrSet(
      Name, AllowInternal, OwnedModules.begin_added(), OwnedModules.end_added());
  if (!GV)
    GV = FindGlobalVariableNamedInModulePtrSet(Name, AllowInternal, OwnedModules.begin_loaded(),
                                        OwnedModules.end_loaded());
  if (!GV)
    GV = FindGlobalVariableNamedInModulePtrSet(Name, AllowInternal, OwnedModules.begin_finalized(),
                                        OwnedModules.end_finalized());
  return GV;
}

GenericValue MCJIT::runFunction(Function *F, ArrayRef<GenericValue> ArgValues) {
  assert(F && "Function *F was null at entry to run()");

  void *FPtr = getPointerToFunction(F);
  finalizeModule(F->getParent());
  assert(FPtr && "Pointer to fn's code was null after getPointerToFunction");
  FunctionType *FTy = F->getFunctionType();
  Type *RetTy = FTy->getReturnType();

  assert((FTy->getNumParams() == ArgValues.size() ||
          (FTy->isVarArg() && FTy->getNumParams() <= ArgValues.size())) &&
         "Wrong number of arguments passed into function!");
  assert(FTy->getNumParams() == ArgValues.size() &&
         "This doesn't support passing arguments through varargs (yet)!");

  // Handle some common cases first.  These cases correspond to common `main'
  // prototypes.
  if (RetTy->isIntegerTy(32) || RetTy->isVoidTy()) {
    switch (ArgValues.size()) {
    case 3:
      if (FTy->getParamType(0)->isIntegerTy(32) &&
          FTy->getParamType(1)->isPointerTy() &&
          FTy->getParamType(2)->isPointerTy()) {
        int (*PF)(int, char **, const char **) =
          (int(*)(int, char **, const char **))(intptr_t)FPtr;

        // Call the function.
        GenericValue rv;
        rv.IntVal = APInt(32, PF(ArgValues[0].IntVal.getZExtValue(),
                                 (char **)GVTOP(ArgValues[1]),
                                 (const char **)GVTOP(ArgValues[2])));
        return rv;
      }
      break;
    case 2:
      if (FTy->getParamType(0)->isIntegerTy(32) &&
          FTy->getParamType(1)->isPointerTy()) {
        int (*PF)(int, char **) = (int(*)(int, char **))(intptr_t)FPtr;

        // Call the function.
        GenericValue rv;
        rv.IntVal = APInt(32, PF(ArgValues[0].IntVal.getZExtValue(),
                                 (char **)GVTOP(ArgValues[1])));
        return rv;
      }
      break;
    case 1:
      if (FTy->getNumParams() == 1 &&
          FTy->getParamType(0)->isIntegerTy(32)) {
        GenericValue rv;
        int (*PF)(int) = (int(*)(int))(intptr_t)FPtr;
        rv.IntVal = APInt(32, PF(ArgValues[0].IntVal.getZExtValue()));
        return rv;
      }
      break;
    }
  }

  // Handle cases where no arguments are passed first.
  if (ArgValues.empty()) {
    GenericValue rv;
    switch (RetTy->getTypeID()) {
    default: llvm_unreachable("Unknown return type for function call!");
    case Type::IntegerTyID: {
      unsigned BitWidth = cast<IntegerType>(RetTy)->getBitWidth();
      if (BitWidth == 1)
        rv.IntVal = APInt(BitWidth, ((bool(*)())(intptr_t)FPtr)());
      else if (BitWidth <= 8)
        rv.IntVal = APInt(BitWidth, ((char(*)())(intptr_t)FPtr)());
      else if (BitWidth <= 16)
        rv.IntVal = APInt(BitWidth, ((short(*)())(intptr_t)FPtr)());
      else if (BitWidth <= 32)
        rv.IntVal = APInt(BitWidth, ((int(*)())(intptr_t)FPtr)());
      else if (BitWidth <= 64)
        rv.IntVal = APInt(BitWidth, ((int64_t(*)())(intptr_t)FPtr)());
      else
        llvm_unreachable("Integer types > 64 bits not supported");
      return rv;
    }
    case Type::VoidTyID:
      rv.IntVal = APInt(32, ((int(*)())(intptr_t)FPtr)());
      return rv;
    case Type::FloatTyID:
      rv.FloatVal = ((float(*)())(intptr_t)FPtr)();
      return rv;
    case Type::DoubleTyID:
      rv.DoubleVal = ((double(*)())(intptr_t)FPtr)();
      return rv;
    case Type::X86_FP80TyID:
    case Type::FP128TyID:
    case Type::PPC_FP128TyID:
      llvm_unreachable("long double not supported yet");
    case Type::PointerTyID:
      return PTOGV(((void*(*)())(intptr_t)FPtr)());
    }
  }

  report_fatal_error("MCJIT::runFunction does not support full-featured "
                     "argument passing. Please use "
                     "ExecutionEngine::getFunctionAddress and cast the result "
                     "to the desired function pointer type.");
}

void *MCJIT::getPointerToNamedFunction(StringRef Name, bool AbortOnFailure) {
  if (!isSymbolSearchingDisabled()) {
    if (auto Sym = Resolver.findSymbol(Name)) {
      if (auto AddrOrErr = Sym.getAddress())
        return reinterpret_cast<void*>(
                 static_cast<uintptr_t>(*AddrOrErr));
    } else if (auto Err = Sym.takeError())
      report_fatal_error(std::move(Err));
  }

  /// If a LazyFunctionCreator is installed, use it to get/create the function.
  if (LazyFunctionCreator)
    if (void *RP = LazyFunctionCreator(Name))
      return RP;

  if (AbortOnFailure) {
    report_fatal_error("Program used external function '"+Name+
                       "' which could not be resolved!");
  }
  return nullptr;
}

void MCJIT::RegisterJITEventListener(JITEventListener *L) {
  if (!L)
    return;
  MutexGuard locked(lock);
  EventListeners.push_back(L);
}

void MCJIT::UnregisterJITEventListener(JITEventListener *L) {
  if (!L)
    return;
  MutexGuard locked(lock);
  auto I = find(reverse(EventListeners), L);
  if (I != EventListeners.rend()) {
    std::swap(*I, EventListeners.back());
    EventListeners.pop_back();
  }
}

void MCJIT::NotifyObjectEmitted(const object::ObjectFile& Obj,
                                const RuntimeDyld::LoadedObjectInfo &L) {
  MutexGuard locked(lock);
  MemMgr->notifyObjectLoaded(this, Obj);
  for (unsigned I = 0, S = EventListeners.size(); I < S; ++I) {
    EventListeners[I]->NotifyObjectEmitted(Obj, L);
  }
}

void MCJIT::NotifyFreeingObject(const object::ObjectFile& Obj) {
  MutexGuard locked(lock);
  for (JITEventListener *L : EventListeners)
    L->NotifyFreeingObject(Obj);
}

JITSymbol
LinkingSymbolResolver::findSymbol(const std::string &Name) {
  auto Result = ParentEngine.findSymbol(Name, false);
  if (Result)
    return Result;
  if (ParentEngine.isSymbolSearchingDisabled())
    return nullptr;
  return ClientResolver->findSymbol(Name);
}

void LinkingSymbolResolver::anchor() {}
