//===------- COFFPlatform.cpp - Utilities for executing COFF in Orc -------===//
//
// 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
//
//===----------------------------------------------------------------------===//

#include "llvm/ExecutionEngine/Orc/COFFPlatform.h"
#include "llvm/ExecutionEngine/Orc/DebugUtils.h"
#include "llvm/ExecutionEngine/Orc/LookupAndRecordAddrs.h"
#include "llvm/ExecutionEngine/Orc/ObjectFileInterface.h"

#include "llvm/Object/COFF.h"

#include "llvm/ExecutionEngine/Orc/EPCDynamicLibrarySearchGenerator.h"

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

#define DEBUG_TYPE "orc"

using namespace llvm;
using namespace llvm::orc;
using namespace llvm::orc::shared;

namespace llvm {
namespace orc {
namespace shared {

using SPSCOFFJITDylibDepInfo = SPSSequence<SPSExecutorAddr>;
using SPSCOFFJITDylibDepInfoMap =
    SPSSequence<SPSTuple<SPSExecutorAddr, SPSCOFFJITDylibDepInfo>>;
using SPSCOFFObjectSectionsMap =
    SPSSequence<SPSTuple<SPSString, SPSExecutorAddrRange>>;
using SPSCOFFRegisterObjectSectionsArgs =
    SPSArgList<SPSExecutorAddr, SPSCOFFObjectSectionsMap, bool>;
using SPSCOFFDeregisterObjectSectionsArgs =
    SPSArgList<SPSExecutorAddr, SPSCOFFObjectSectionsMap>;

} // namespace shared
} // namespace orc
} // namespace llvm
namespace {

class COFFHeaderMaterializationUnit : public MaterializationUnit {
public:
  COFFHeaderMaterializationUnit(COFFPlatform &CP,
                                const SymbolStringPtr &HeaderStartSymbol)
      : MaterializationUnit(createHeaderInterface(CP, HeaderStartSymbol)),
        CP(CP) {}

  StringRef getName() const override { return "COFFHeaderMU"; }

  void materialize(std::unique_ptr<MaterializationResponsibility> R) override {
    unsigned PointerSize;
    support::endianness Endianness;
    const auto &TT =
        CP.getExecutionSession().getExecutorProcessControl().getTargetTriple();

    switch (TT.getArch()) {
    case Triple::x86_64:
      PointerSize = 8;
      Endianness = support::endianness::little;
      break;
    default:
      llvm_unreachable("Unrecognized architecture");
    }

    auto G = std::make_unique<jitlink::LinkGraph>(
        "<COFFHeaderMU>", TT, PointerSize, Endianness,
        jitlink::getGenericEdgeKindName);
    auto &HeaderSection = G->createSection("__header", MemProt::Read);
    auto &HeaderBlock = createHeaderBlock(*G, HeaderSection);

    // Init symbol is __ImageBase symbol.
    auto &ImageBaseSymbol = G->addDefinedSymbol(
        HeaderBlock, 0, *R->getInitializerSymbol(), HeaderBlock.getSize(),
        jitlink::Linkage::Strong, jitlink::Scope::Default, false, true);

    addImageBaseRelocationEdge(HeaderBlock, ImageBaseSymbol);

    CP.getObjectLinkingLayer().emit(std::move(R), std::move(G));
  }

  void discard(const JITDylib &JD, const SymbolStringPtr &Sym) override {}

private:
  struct HeaderSymbol {
    const char *Name;
    uint64_t Offset;
  };

  struct NTHeader {
    support::ulittle32_t PEMagic;
    object::coff_file_header FileHeader;
    struct PEHeader {
      object::pe32plus_header Header;
      object::data_directory DataDirectory[COFF::NUM_DATA_DIRECTORIES + 1];
    } OptionalHeader;
  };

  struct HeaderBlockContent {
    object::dos_header DOSHeader;
    COFFHeaderMaterializationUnit::NTHeader NTHeader;
  };

  static jitlink::Block &createHeaderBlock(jitlink::LinkGraph &G,
                                           jitlink::Section &HeaderSection) {
    HeaderBlockContent Hdr = {};

    // Set up magic
    Hdr.DOSHeader.Magic[0] = 'M';
    Hdr.DOSHeader.Magic[1] = 'Z';
    Hdr.DOSHeader.AddressOfNewExeHeader =
        offsetof(HeaderBlockContent, NTHeader);
    uint32_t PEMagic = *reinterpret_cast<const uint32_t *>(COFF::PEMagic);
    Hdr.NTHeader.PEMagic = PEMagic;
    Hdr.NTHeader.OptionalHeader.Header.Magic = COFF::PE32Header::PE32_PLUS;

    switch (G.getTargetTriple().getArch()) {
    case Triple::x86_64:
      Hdr.NTHeader.FileHeader.Machine = COFF::IMAGE_FILE_MACHINE_AMD64;
      break;
    default:
      llvm_unreachable("Unrecognized architecture");
    }

    auto HeaderContent = G.allocateString(
        StringRef(reinterpret_cast<const char *>(&Hdr), sizeof(Hdr)));

    return G.createContentBlock(HeaderSection, HeaderContent, ExecutorAddr(), 8,
                                0);
  }

  static void addImageBaseRelocationEdge(jitlink::Block &B,
                                         jitlink::Symbol &ImageBase) {
    auto ImageBaseOffset = offsetof(HeaderBlockContent, NTHeader) +
                           offsetof(NTHeader, OptionalHeader) +
                           offsetof(object::pe32plus_header, ImageBase);
    B.addEdge(jitlink::x86_64::Pointer64, ImageBaseOffset, ImageBase, 0);
  }

  static MaterializationUnit::Interface
  createHeaderInterface(COFFPlatform &MOP,
                        const SymbolStringPtr &HeaderStartSymbol) {
    SymbolFlagsMap HeaderSymbolFlags;

    HeaderSymbolFlags[HeaderStartSymbol] = JITSymbolFlags::Exported;

    return MaterializationUnit::Interface(std::move(HeaderSymbolFlags),
                                          HeaderStartSymbol);
  }

  COFFPlatform &CP;
};

} // end anonymous namespace

namespace llvm {
namespace orc {

Expected<std::unique_ptr<COFFPlatform>>
COFFPlatform::Create(ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer,
                     JITDylib &PlatformJD, const char *OrcRuntimePath,
                     LoadDynamicLibrary LoadDynLibrary, bool StaticVCRuntime,
                     const char *VCRuntimePath,
                     std::optional<SymbolAliasMap> RuntimeAliases) {
  auto &EPC = ES.getExecutorProcessControl();

  // If the target is not supported then bail out immediately.
  if (!supportedTarget(EPC.getTargetTriple()))
    return make_error<StringError>("Unsupported COFFPlatform triple: " +
                                       EPC.getTargetTriple().str(),
                                   inconvertibleErrorCode());

  // Create default aliases if the caller didn't supply any.
  if (!RuntimeAliases)
    RuntimeAliases = standardPlatformAliases(ES);

  // Define the aliases.
  if (auto Err = PlatformJD.define(symbolAliases(std::move(*RuntimeAliases))))
    return std::move(Err);

  auto &HostFuncJD = ES.createBareJITDylib("$<PlatformRuntimeHostFuncJD>");

  // Add JIT-dispatch function support symbols.
  if (auto Err = HostFuncJD.define(absoluteSymbols(
          {{ES.intern("__orc_rt_jit_dispatch"),
            {EPC.getJITDispatchInfo().JITDispatchFunction.getValue(),
             JITSymbolFlags::Exported}},
           {ES.intern("__orc_rt_jit_dispatch_ctx"),
            {EPC.getJITDispatchInfo().JITDispatchContext.getValue(),
             JITSymbolFlags::Exported}}})))
    return std::move(Err);

  PlatformJD.addToLinkOrder(HostFuncJD);

  // Create the instance.
  Error Err = Error::success();
  auto P = std::unique_ptr<COFFPlatform>(new COFFPlatform(
      ES, ObjLinkingLayer, PlatformJD, OrcRuntimePath,
      std::move(LoadDynLibrary), StaticVCRuntime, VCRuntimePath, Err));
  if (Err)
    return std::move(Err);
  return std::move(P);
}

Expected<MemoryBufferRef> COFFPlatform::getPerJDObjectFile() {
  auto PerJDObj = OrcRuntimeArchive->findSym("__orc_rt_coff_per_jd_marker");
  if (!PerJDObj)
    return PerJDObj.takeError();

  if (!*PerJDObj)
    return make_error<StringError>("Could not find per jd object file",
                                   inconvertibleErrorCode());

  auto Buffer = (*PerJDObj)->getAsBinary();
  if (!Buffer)
    return Buffer.takeError();

  return (*Buffer)->getMemoryBufferRef();
}

static void addAliases(ExecutionSession &ES, SymbolAliasMap &Aliases,
                       ArrayRef<std::pair<const char *, const char *>> AL) {
  for (auto &KV : AL) {
    auto AliasName = ES.intern(KV.first);
    assert(!Aliases.count(AliasName) && "Duplicate symbol name in alias map");
    Aliases[std::move(AliasName)] = {ES.intern(KV.second),
                                     JITSymbolFlags::Exported};
  }
}

Error COFFPlatform::setupJITDylib(JITDylib &JD) {
  if (auto Err = JD.define(std::make_unique<COFFHeaderMaterializationUnit>(
          *this, COFFHeaderStartSymbol)))
    return Err;

  if (auto Err = ES.lookup({&JD}, COFFHeaderStartSymbol).takeError())
    return Err;

  // Define the CXX aliases.
  SymbolAliasMap CXXAliases;
  addAliases(ES, CXXAliases, requiredCXXAliases());
  if (auto Err = JD.define(symbolAliases(std::move(CXXAliases))))
    return Err;

  auto PerJDObj = getPerJDObjectFile();
  if (!PerJDObj)
    return PerJDObj.takeError();

  auto I = getObjectFileInterface(ES, *PerJDObj);
  if (!I)
    return I.takeError();

  if (auto Err = ObjLinkingLayer.add(
          JD, MemoryBuffer::getMemBuffer(*PerJDObj, false), std::move(*I)))
    return Err;

  if (!Bootstrapping) {
    auto ImportedLibs = StaticVCRuntime
                            ? VCRuntimeBootstrap->loadStaticVCRuntime(JD)
                            : VCRuntimeBootstrap->loadDynamicVCRuntime(JD);
    if (!ImportedLibs)
      return ImportedLibs.takeError();
    for (auto &Lib : *ImportedLibs)
      if (auto Err = LoadDynLibrary(JD, Lib))
        return Err;
    if (StaticVCRuntime)
      if (auto Err = VCRuntimeBootstrap->initializeStaticVCRuntime(JD))
        return Err;
  }

  JD.addGenerator(DLLImportDefinitionGenerator::Create(ES, ObjLinkingLayer));
  return Error::success();
}

Error COFFPlatform::teardownJITDylib(JITDylib &JD) {
  std::lock_guard<std::mutex> Lock(PlatformMutex);
  auto I = JITDylibToHeaderAddr.find(&JD);
  if (I != JITDylibToHeaderAddr.end()) {
    assert(HeaderAddrToJITDylib.count(I->second) &&
           "HeaderAddrToJITDylib missing entry");
    HeaderAddrToJITDylib.erase(I->second);
    JITDylibToHeaderAddr.erase(I);
  }
  return Error::success();
}

Error COFFPlatform::notifyAdding(ResourceTracker &RT,
                                 const MaterializationUnit &MU) {
  auto &JD = RT.getJITDylib();
  const auto &InitSym = MU.getInitializerSymbol();
  if (!InitSym)
    return Error::success();

  RegisteredInitSymbols[&JD].add(InitSym,
                                 SymbolLookupFlags::WeaklyReferencedSymbol);

  LLVM_DEBUG({
    dbgs() << "COFFPlatform: Registered init symbol " << *InitSym << " for MU "
           << MU.getName() << "\n";
  });
  return Error::success();
}

Error COFFPlatform::notifyRemoving(ResourceTracker &RT) {
  llvm_unreachable("Not supported yet");
}

SymbolAliasMap COFFPlatform::standardPlatformAliases(ExecutionSession &ES) {
  SymbolAliasMap Aliases;
  addAliases(ES, Aliases, standardRuntimeUtilityAliases());
  return Aliases;
}

ArrayRef<std::pair<const char *, const char *>>
COFFPlatform::requiredCXXAliases() {
  static const std::pair<const char *, const char *> RequiredCXXAliases[] = {
      {"_CxxThrowException", "__orc_rt_coff_cxx_throw_exception"},
      {"_onexit", "__orc_rt_coff_onexit_per_jd"},
      {"atexit", "__orc_rt_coff_atexit_per_jd"}};

  return ArrayRef<std::pair<const char *, const char *>>(RequiredCXXAliases);
}

ArrayRef<std::pair<const char *, const char *>>
COFFPlatform::standardRuntimeUtilityAliases() {
  static const std::pair<const char *, const char *>
      StandardRuntimeUtilityAliases[] = {
          {"__orc_rt_run_program", "__orc_rt_coff_run_program"},
          {"__orc_rt_jit_dlerror", "__orc_rt_coff_jit_dlerror"},
          {"__orc_rt_jit_dlopen", "__orc_rt_coff_jit_dlopen"},
          {"__orc_rt_jit_dlclose", "__orc_rt_coff_jit_dlclose"},
          {"__orc_rt_jit_dlsym", "__orc_rt_coff_jit_dlsym"},
          {"__orc_rt_log_error", "__orc_rt_log_error_to_stderr"}};

  return ArrayRef<std::pair<const char *, const char *>>(
      StandardRuntimeUtilityAliases);
}

bool COFFPlatform::supportedTarget(const Triple &TT) {
  switch (TT.getArch()) {
  case Triple::x86_64:
    return true;
  default:
    return false;
  }
}

COFFPlatform::COFFPlatform(ExecutionSession &ES,
                           ObjectLinkingLayer &ObjLinkingLayer,
                           JITDylib &PlatformJD, const char *OrcRuntimePath,
                           LoadDynamicLibrary LoadDynLibrary,
                           bool StaticVCRuntime, const char *VCRuntimePath,
                           Error &Err)
    : ES(ES), ObjLinkingLayer(ObjLinkingLayer),
      LoadDynLibrary(std::move(LoadDynLibrary)),
      StaticVCRuntime(StaticVCRuntime),
      COFFHeaderStartSymbol(ES.intern("__ImageBase")) {
  ErrorAsOutParameter _(&Err);

  // Create a generator for the ORC runtime archive.
  auto OrcRuntimeArchiveGenerator =
      StaticLibraryDefinitionGenerator::Load(ObjLinkingLayer, OrcRuntimePath);
  if (!OrcRuntimeArchiveGenerator) {
    Err = OrcRuntimeArchiveGenerator.takeError();
    return;
  }

  auto ArchiveBuffer = MemoryBuffer::getFile(OrcRuntimePath);
  if (!ArchiveBuffer) {
    Err = createFileError(OrcRuntimePath, ArchiveBuffer.getError());
    return;
  }
  OrcRuntimeArchiveBuffer = std::move(*ArchiveBuffer);
  OrcRuntimeArchive =
      std::make_unique<object::Archive>(*OrcRuntimeArchiveBuffer, Err);
  if (Err)
    return;

  Bootstrapping.store(true);
  ObjLinkingLayer.addPlugin(std::make_unique<COFFPlatformPlugin>(*this));

  // Load vc runtime
  auto VCRT =
      COFFVCRuntimeBootstrapper::Create(ES, ObjLinkingLayer, VCRuntimePath);
  if (!VCRT) {
    Err = VCRT.takeError();
    return;
  }
  VCRuntimeBootstrap = std::move(*VCRT);

  for (auto &Lib : (*OrcRuntimeArchiveGenerator)->getImportedDynamicLibraries())
    DylibsToPreload.insert(Lib);

  auto ImportedLibs =
      StaticVCRuntime ? VCRuntimeBootstrap->loadStaticVCRuntime(PlatformJD)
                      : VCRuntimeBootstrap->loadDynamicVCRuntime(PlatformJD);
  if (!ImportedLibs) {
    Err = ImportedLibs.takeError();
    return;
  }

  for (auto &Lib : *ImportedLibs)
    DylibsToPreload.insert(Lib);

  PlatformJD.addGenerator(std::move(*OrcRuntimeArchiveGenerator));

  // PlatformJD hasn't been set up by the platform yet (since we're creating
  // the platform now), so set it up.
  if (auto E2 = setupJITDylib(PlatformJD)) {
    Err = std::move(E2);
    return;
  }

  for (auto& Lib : DylibsToPreload)
      if (auto E2 = LoadDynLibrary(PlatformJD, Lib)) {
          Err = std::move(E2);
          return;
      }

  if (StaticVCRuntime)
      if (auto E2 = VCRuntimeBootstrap->initializeStaticVCRuntime(PlatformJD)) {
          Err = std::move(E2);
          return;
      }

  // Associate wrapper function tags with JIT-side function implementations.
  if (auto E2 = associateRuntimeSupportFunctions(PlatformJD)) {
      Err = std::move(E2);
      return;
  }

  // Lookup addresses of runtime functions callable by the platform,
  // call the platform bootstrap function to initialize the platform-state
  // object in the executor.
  if (auto E2 = bootstrapCOFFRuntime(PlatformJD)) {
      Err = std::move(E2);
      return;
  }

  Bootstrapping.store(false);
  JDBootstrapStates.clear();
}

Expected<COFFPlatform::JITDylibDepMap>
COFFPlatform::buildJDDepMap(JITDylib &JD) {
  return ES.runSessionLocked([&]() -> Expected<JITDylibDepMap> {
    JITDylibDepMap JDDepMap;

    SmallVector<JITDylib *, 16> Worklist({&JD});
    while (!Worklist.empty()) {
      auto CurJD = Worklist.back();
      Worklist.pop_back();

      auto &DM = JDDepMap[CurJD];
      CurJD->withLinkOrderDo([&](const JITDylibSearchOrder &O) {
        DM.reserve(O.size());
        for (auto &KV : O) {
          if (KV.first == CurJD)
            continue;
          {
            // Bare jitdylibs not known to the platform
            std::lock_guard<std::mutex> Lock(PlatformMutex);
            if (!JITDylibToHeaderAddr.count(KV.first)) {
              LLVM_DEBUG({
                dbgs() << "JITDylib unregistered to COFFPlatform detected in "
                          "LinkOrder: "
                       << CurJD->getName() << "\n";
              });
              continue;
            }
          }
          DM.push_back(KV.first);
          // Push unvisited entry.
          if (!JDDepMap.count(KV.first)) {
            Worklist.push_back(KV.first);
            JDDepMap[KV.first] = {};
          }
        }
      });
    }
    return std::move(JDDepMap);
  });
}

void COFFPlatform::pushInitializersLoop(PushInitializersSendResultFn SendResult,
                                        JITDylibSP JD,
                                        JITDylibDepMap &JDDepMap) {
  SmallVector<JITDylib *, 16> Worklist({JD.get()});
  DenseSet<JITDylib *> Visited({JD.get()});
  DenseMap<JITDylib *, SymbolLookupSet> NewInitSymbols;
  ES.runSessionLocked([&]() {
    while (!Worklist.empty()) {
      auto CurJD = Worklist.back();
      Worklist.pop_back();

      auto RISItr = RegisteredInitSymbols.find(CurJD);
      if (RISItr != RegisteredInitSymbols.end()) {
        NewInitSymbols[CurJD] = std::move(RISItr->second);
        RegisteredInitSymbols.erase(RISItr);
      }

      for (auto *DepJD : JDDepMap[CurJD])
        if (!Visited.count(DepJD)) {
          Worklist.push_back(DepJD);
          Visited.insert(DepJD);
        }
    }
  });

  // If there are no further init symbols to look up then send the link order
  // (as a list of header addresses) to the caller.
  if (NewInitSymbols.empty()) {
    // Build the dep info map to return.
    COFFJITDylibDepInfoMap DIM;
    DIM.reserve(JDDepMap.size());
    for (auto &KV : JDDepMap) {
      std::lock_guard<std::mutex> Lock(PlatformMutex);
      COFFJITDylibDepInfo DepInfo;
      DepInfo.reserve(KV.second.size());
      for (auto &Dep : KV.second) {
        DepInfo.push_back(JITDylibToHeaderAddr[Dep]);
      }
      auto H = JITDylibToHeaderAddr[KV.first];
      DIM.push_back(std::make_pair(H, std::move(DepInfo)));
    }
    SendResult(DIM);
    return;
  }

  // Otherwise issue a lookup and re-run this phase when it completes.
  lookupInitSymbolsAsync(
      [this, SendResult = std::move(SendResult), &JD,
       JDDepMap = std::move(JDDepMap)](Error Err) mutable {
        if (Err)
          SendResult(std::move(Err));
        else
          pushInitializersLoop(std::move(SendResult), JD, JDDepMap);
      },
      ES, std::move(NewInitSymbols));
}

void COFFPlatform::rt_pushInitializers(PushInitializersSendResultFn SendResult,
                                       ExecutorAddr JDHeaderAddr) {
  JITDylibSP JD;
  {
    std::lock_guard<std::mutex> Lock(PlatformMutex);
    auto I = HeaderAddrToJITDylib.find(JDHeaderAddr);
    if (I != HeaderAddrToJITDylib.end())
      JD = I->second;
  }

  LLVM_DEBUG({
    dbgs() << "COFFPlatform::rt_pushInitializers(" << JDHeaderAddr << ") ";
    if (JD)
      dbgs() << "pushing initializers for " << JD->getName() << "\n";
    else
      dbgs() << "No JITDylib for header address.\n";
  });

  if (!JD) {
    SendResult(
        make_error<StringError>("No JITDylib with header addr " +
                                    formatv("{0:x}", JDHeaderAddr.getValue()),
                                inconvertibleErrorCode()));
    return;
  }

  auto JDDepMap = buildJDDepMap(*JD);
  if (!JDDepMap) {
    SendResult(JDDepMap.takeError());
    return;
  }

  pushInitializersLoop(std::move(SendResult), JD, *JDDepMap);
}

void COFFPlatform::rt_lookupSymbol(SendSymbolAddressFn SendResult,
                                   ExecutorAddr Handle, StringRef SymbolName) {
  LLVM_DEBUG({
    dbgs() << "COFFPlatform::rt_lookupSymbol(\""
           << formatv("{0:x}", Handle.getValue()) << "\")\n";
  });

  JITDylib *JD = nullptr;

  {
    std::lock_guard<std::mutex> Lock(PlatformMutex);
    auto I = HeaderAddrToJITDylib.find(Handle);
    if (I != HeaderAddrToJITDylib.end())
      JD = I->second;
  }

  if (!JD) {
    LLVM_DEBUG({
      dbgs() << "  No JITDylib for handle "
             << formatv("{0:x}", Handle.getValue()) << "\n";
    });
    SendResult(make_error<StringError>("No JITDylib associated with handle " +
                                           formatv("{0:x}", Handle.getValue()),
                                       inconvertibleErrorCode()));
    return;
  }

  // Use functor class to work around XL build compiler issue on AIX.
  class RtLookupNotifyComplete {
  public:
    RtLookupNotifyComplete(SendSymbolAddressFn &&SendResult)
        : SendResult(std::move(SendResult)) {}
    void operator()(Expected<SymbolMap> Result) {
      if (Result) {
        assert(Result->size() == 1 && "Unexpected result map count");
        SendResult(ExecutorAddr(Result->begin()->second.getAddress()));
      } else {
        SendResult(Result.takeError());
      }
    }

  private:
    SendSymbolAddressFn SendResult;
  };

  ES.lookup(
      LookupKind::DLSym, {{JD, JITDylibLookupFlags::MatchExportedSymbolsOnly}},
      SymbolLookupSet(ES.intern(SymbolName)), SymbolState::Ready,
      RtLookupNotifyComplete(std::move(SendResult)), NoDependenciesToRegister);
}

Error COFFPlatform::associateRuntimeSupportFunctions(JITDylib &PlatformJD) {
  ExecutionSession::JITDispatchHandlerAssociationMap WFs;

  using LookupSymbolSPSSig =
      SPSExpected<SPSExecutorAddr>(SPSExecutorAddr, SPSString);
  WFs[ES.intern("__orc_rt_coff_symbol_lookup_tag")] =
      ES.wrapAsyncWithSPS<LookupSymbolSPSSig>(this,
                                              &COFFPlatform::rt_lookupSymbol);
  using PushInitializersSPSSig =
      SPSExpected<SPSCOFFJITDylibDepInfoMap>(SPSExecutorAddr);
  WFs[ES.intern("__orc_rt_coff_push_initializers_tag")] =
      ES.wrapAsyncWithSPS<PushInitializersSPSSig>(
          this, &COFFPlatform::rt_pushInitializers);

  return ES.registerJITDispatchHandlers(PlatformJD, std::move(WFs));
}

Error COFFPlatform::runBootstrapInitializers(JDBootstrapState &BState) {
  llvm::sort(BState.Initializers);
  if (auto Err =
          runBootstrapSubsectionInitializers(BState, ".CRT$XIA", ".CRT$XIZ"))
    return Err;

  if (auto Err = runSymbolIfExists(*BState.JD, "__run_after_c_init"))
    return Err;

  if (auto Err =
          runBootstrapSubsectionInitializers(BState, ".CRT$XCA", ".CRT$XCZ"))
    return Err;
  return Error::success();
}

Error COFFPlatform::runBootstrapSubsectionInitializers(JDBootstrapState &BState,
                                                       StringRef Start,
                                                       StringRef End) {
  for (auto &Initializer : BState.Initializers)
    if (Initializer.first >= Start && Initializer.first <= End &&
        Initializer.second) {
      auto Res =
          ES.getExecutorProcessControl().runAsVoidFunction(Initializer.second);
      if (!Res)
        return Res.takeError();
    }
  return Error::success();
}

Error COFFPlatform::bootstrapCOFFRuntime(JITDylib &PlatformJD) {
  // Lookup of runtime symbols causes the collection of initializers if
  // it's static linking setting.
  if (auto Err = lookupAndRecordAddrs(
          ES, LookupKind::Static, makeJITDylibSearchOrder(&PlatformJD),
          {
              {ES.intern("__orc_rt_coff_platform_bootstrap"),
               &orc_rt_coff_platform_bootstrap},
              {ES.intern("__orc_rt_coff_platform_shutdown"),
               &orc_rt_coff_platform_shutdown},
              {ES.intern("__orc_rt_coff_register_jitdylib"),
               &orc_rt_coff_register_jitdylib},
              {ES.intern("__orc_rt_coff_deregister_jitdylib"),
               &orc_rt_coff_deregister_jitdylib},
              {ES.intern("__orc_rt_coff_register_object_sections"),
               &orc_rt_coff_register_object_sections},
              {ES.intern("__orc_rt_coff_deregister_object_sections"),
               &orc_rt_coff_deregister_object_sections},
          }))
    return Err;

  // Call bootstrap functions
  if (auto Err = ES.callSPSWrapper<void()>(orc_rt_coff_platform_bootstrap))
    return Err;

  // Do the pending jitdylib registration actions that we couldn't do
  // because orc runtime was not linked fully.
  for (auto KV : JDBootstrapStates) {
    auto &JDBState = KV.second;
    if (auto Err = ES.callSPSWrapper<void(SPSString, SPSExecutorAddr)>(
            orc_rt_coff_register_jitdylib, JDBState.JDName,
            JDBState.HeaderAddr))
      return Err;

    for (auto &ObjSectionMap : JDBState.ObjectSectionsMaps)
      if (auto Err = ES.callSPSWrapper<void(SPSExecutorAddr,
                                            SPSCOFFObjectSectionsMap, bool)>(
              orc_rt_coff_register_object_sections, JDBState.HeaderAddr,
              ObjSectionMap, false))
        return Err;
  }

  // Run static initializers collected in bootstrap stage.
  for (auto KV : JDBootstrapStates) {
    auto &JDBState = KV.second;
    if (auto Err = runBootstrapInitializers(JDBState))
      return Err;
  }

  return Error::success();
}

Error COFFPlatform::runSymbolIfExists(JITDylib &PlatformJD,
                                      StringRef SymbolName) {
  ExecutorAddr jit_function;
  auto AfterCLookupErr = lookupAndRecordAddrs(
      ES, LookupKind::Static, makeJITDylibSearchOrder(&PlatformJD),
      {{ES.intern(SymbolName), &jit_function}});
  if (!AfterCLookupErr) {
    auto Res = ES.getExecutorProcessControl().runAsVoidFunction(jit_function);
    if (!Res)
      return Res.takeError();
    return Error::success();
  }
  if (!AfterCLookupErr.isA<SymbolsNotFound>())
    return AfterCLookupErr;
  consumeError(std::move(AfterCLookupErr));
  return Error::success();
}

void COFFPlatform::COFFPlatformPlugin::modifyPassConfig(
    MaterializationResponsibility &MR, jitlink::LinkGraph &LG,
    jitlink::PassConfiguration &Config) {

  bool IsBootstrapping = CP.Bootstrapping.load();

  if (auto InitSymbol = MR.getInitializerSymbol()) {
    if (InitSymbol == CP.COFFHeaderStartSymbol) {
      Config.PostAllocationPasses.push_back(
          [this, &MR, IsBootstrapping](jitlink::LinkGraph &G) {
            return associateJITDylibHeaderSymbol(G, MR, IsBootstrapping);
          });
      return;
    }
    Config.PrePrunePasses.push_back([this, &MR](jitlink::LinkGraph &G) {
      return preserveInitializerSections(G, MR);
    });
  }

  if (!IsBootstrapping)
    Config.PostFixupPasses.push_back(
        [this, &JD = MR.getTargetJITDylib()](jitlink::LinkGraph &G) {
          return registerObjectPlatformSections(G, JD);
        });
  else
    Config.PostFixupPasses.push_back(
        [this, &JD = MR.getTargetJITDylib()](jitlink::LinkGraph &G) {
          return registerObjectPlatformSectionsInBootstrap(G, JD);
        });
}

ObjectLinkingLayer::Plugin::SyntheticSymbolDependenciesMap
COFFPlatform::COFFPlatformPlugin::getSyntheticSymbolDependencies(
    MaterializationResponsibility &MR) {
  std::lock_guard<std::mutex> Lock(PluginMutex);
  auto I = InitSymbolDeps.find(&MR);
  if (I != InitSymbolDeps.end()) {
    SyntheticSymbolDependenciesMap Result;
    Result[MR.getInitializerSymbol()] = std::move(I->second);
    InitSymbolDeps.erase(&MR);
    return Result;
  }
  return SyntheticSymbolDependenciesMap();
}

Error COFFPlatform::COFFPlatformPlugin::associateJITDylibHeaderSymbol(
    jitlink::LinkGraph &G, MaterializationResponsibility &MR,
    bool IsBootstraping) {
  auto I = llvm::find_if(G.defined_symbols(), [this](jitlink::Symbol *Sym) {
    return Sym->getName() == *CP.COFFHeaderStartSymbol;
  });
  assert(I != G.defined_symbols().end() && "Missing COFF header start symbol");

  auto &JD = MR.getTargetJITDylib();
  std::lock_guard<std::mutex> Lock(CP.PlatformMutex);
  auto HeaderAddr = (*I)->getAddress();
  CP.JITDylibToHeaderAddr[&JD] = HeaderAddr;
  CP.HeaderAddrToJITDylib[HeaderAddr] = &JD;
  if (!IsBootstraping) {
    G.allocActions().push_back(
        {cantFail(WrapperFunctionCall::Create<
                  SPSArgList<SPSString, SPSExecutorAddr>>(
             CP.orc_rt_coff_register_jitdylib, JD.getName(), HeaderAddr)),
         cantFail(WrapperFunctionCall::Create<SPSArgList<SPSExecutorAddr>>(
             CP.orc_rt_coff_deregister_jitdylib, HeaderAddr))});
  } else {
    G.allocActions().push_back(
        {{},
         cantFail(WrapperFunctionCall::Create<SPSArgList<SPSExecutorAddr>>(
             CP.orc_rt_coff_deregister_jitdylib, HeaderAddr))});
    JDBootstrapState BState;
    BState.JD = &JD;
    BState.JDName = JD.getName();
    BState.HeaderAddr = HeaderAddr;
    CP.JDBootstrapStates.emplace(&JD, BState);
  }

  return Error::success();
}

Error COFFPlatform::COFFPlatformPlugin::registerObjectPlatformSections(
    jitlink::LinkGraph &G, JITDylib &JD) {
  COFFObjectSectionsMap ObjSecs;
  auto HeaderAddr = CP.JITDylibToHeaderAddr[&JD];
  assert(HeaderAddr && "Must be registered jitdylib");
  for (auto &S : G.sections()) {
    jitlink::SectionRange Range(S);
    if (Range.getSize())
      ObjSecs.push_back(std::make_pair(S.getName().str(), Range.getRange()));
  }

  G.allocActions().push_back(
      {cantFail(WrapperFunctionCall::Create<SPSCOFFRegisterObjectSectionsArgs>(
           CP.orc_rt_coff_register_object_sections, HeaderAddr, ObjSecs, true)),
       cantFail(
           WrapperFunctionCall::Create<SPSCOFFDeregisterObjectSectionsArgs>(
               CP.orc_rt_coff_deregister_object_sections, HeaderAddr,
               ObjSecs))});

  return Error::success();
}

Error COFFPlatform::COFFPlatformPlugin::preserveInitializerSections(
    jitlink::LinkGraph &G, MaterializationResponsibility &MR) {
  JITLinkSymbolSet InitSectionSymbols;
  for (auto &Sec : G.sections())
    if (COFFPlatform::isInitializerSection(Sec.getName()))
      for (auto *B : Sec.blocks())
        if (!B->edges_empty())
          InitSectionSymbols.insert(
              &G.addAnonymousSymbol(*B, 0, 0, false, true));

  std::lock_guard<std::mutex> Lock(PluginMutex);
  InitSymbolDeps[&MR] = InitSectionSymbols;
  return Error::success();
}

Error COFFPlatform::COFFPlatformPlugin::
    registerObjectPlatformSectionsInBootstrap(jitlink::LinkGraph &G,
                                              JITDylib &JD) {
  std::lock_guard<std::mutex> Lock(CP.PlatformMutex);
  auto HeaderAddr = CP.JITDylibToHeaderAddr[&JD];
  COFFObjectSectionsMap ObjSecs;
  for (auto &S : G.sections()) {
    jitlink::SectionRange Range(S);
    if (Range.getSize())
      ObjSecs.push_back(std::make_pair(S.getName().str(), Range.getRange()));
  }

  G.allocActions().push_back(
      {{},
       cantFail(
           WrapperFunctionCall::Create<SPSCOFFDeregisterObjectSectionsArgs>(
               CP.orc_rt_coff_deregister_object_sections, HeaderAddr,
               ObjSecs))});

  auto &BState = CP.JDBootstrapStates[&JD];
  BState.ObjectSectionsMaps.push_back(std::move(ObjSecs));

  // Collect static initializers
  for (auto &S : G.sections())
    if (COFFPlatform::isInitializerSection(S.getName()))
      for (auto *B : S.blocks()) {
        if (B->edges_empty())
          continue;
        for (auto &E : B->edges())
          BState.Initializers.push_back(std::make_pair(
              S.getName().str(),
              ExecutorAddr(E.getTarget().getAddress() + E.getAddend())));
      }

  return Error::success();
}

} // End namespace orc.
} // End namespace llvm.
