aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2023-04-14 21:41:27 +0000
committerDimitry Andric <dim@FreeBSD.org>2023-06-22 18:20:56 +0000
commitbdd1243df58e60e85101c09001d9812a789b6bc4 (patch)
treea1ce621c7301dd47ba2ddc3b8eaa63b441389481 /contrib/llvm-project/llvm/lib/ExecutionEngine/Orc
parent781624ca2d054430052c828ba8d2c2eaf2d733e7 (diff)
parente3b557809604d036af6e00c60f012c2025b59a5e (diff)
Diffstat (limited to 'contrib/llvm-project/llvm/lib/ExecutionEngine/Orc')
-rw-r--r--contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/COFFPlatform.cpp902
-rw-r--r--contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/COFFVCRuntimeSupport.cpp184
-rw-r--r--contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/CompileOnDemandLayer.cpp16
-rw-r--r--contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/Core.cpp28
-rw-r--r--contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/DebugObjectManagerPlugin.cpp13
-rw-r--r--contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/DebuggerSupportPlugin.cpp8
-rw-r--r--contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/ELFNixPlatform.cpp7
-rw-r--r--contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/EPCDebugObjectRegistrar.cpp18
-rw-r--r--contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/EPCDynamicLibrarySearchGenerator.cpp2
-rw-r--r--contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/EPCEHFrameRegistrar.cpp18
-rw-r--r--contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/EPCGenericDylibManager.cpp2
-rw-r--r--contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/EPCGenericJITLinkMemoryManager.cpp3
-rw-r--r--contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/EPCGenericRTDyldMemoryManager.cpp56
-rw-r--r--contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/EPCIndirectionUtils.cpp3
-rw-r--r--contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/ExecutionUtils.cpp163
-rw-r--r--contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/ExecutorProcessControl.cpp34
-rw-r--r--contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/IndirectionUtils.cpp13
-rw-r--r--contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/LLJIT.cpp77
-rw-r--r--contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/Layer.cpp5
-rw-r--r--contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/LazyReexports.cpp4
-rw-r--r--contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/LookupAndRecordAddrs.cpp2
-rw-r--r--contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/MachOPlatform.cpp641
-rw-r--r--contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/MapperJITLinkMemoryManager.cpp146
-rw-r--r--contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/MemoryMapper.cpp78
-rw-r--r--contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/ObjectFileInterface.cpp34
-rw-r--r--contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/ObjectLinkingLayer.cpp56
-rw-r--r--contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/OrcABISupport.cpp153
-rw-r--r--contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/OrcV2CBindings.cpp115
-rw-r--r--contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.cpp107
-rw-r--r--contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/Shared/OrcError.cpp4
-rw-r--r--contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/Shared/OrcRTBridge.cpp4
-rw-r--r--contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/Shared/SimpleRemoteEPCUtils.cpp4
-rw-r--r--contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/SimpleRemoteEPC.cpp23
-rw-r--r--contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/SpeculateAnalyses.cpp10
-rw-r--r--contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/TargetProcess/ExecutorSharedMemoryMapperService.cpp72
-rw-r--r--contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/TargetProcess/OrcRTBootstrap.cpp25
-rw-r--r--contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/TargetProcess/SimpleExecutorDylibManager.cpp18
-rw-r--r--contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/TargetProcess/SimpleExecutorMemoryManager.cpp4
-rw-r--r--contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/TargetProcess/TargetExecutionUtils.cpp6
39 files changed, 2560 insertions, 498 deletions
diff --git a/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/COFFPlatform.cpp b/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/COFFPlatform.cpp
new file mode 100644
index 000000000000..40716a7f9b61
--- /dev/null
+++ b/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/COFFPlatform.cpp
@@ -0,0 +1,902 @@
+//===------- 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.
diff --git a/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/COFFVCRuntimeSupport.cpp b/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/COFFVCRuntimeSupport.cpp
new file mode 100644
index 000000000000..d9316fab2de3
--- /dev/null
+++ b/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/COFFVCRuntimeSupport.cpp
@@ -0,0 +1,184 @@
+//===------- COFFVCRuntimeSupport.cpp - VC runtime support 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/COFFVCRuntimeSupport.h"
+
+#include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"
+#include "llvm/ExecutionEngine/Orc/LookupAndRecordAddrs.h"
+#include "llvm/Support/VirtualFileSystem.h"
+#include "llvm/WindowsDriver/MSVCPaths.h"
+
+#define DEBUG_TYPE "orc"
+
+using namespace llvm;
+using namespace llvm::orc;
+using namespace llvm::orc::shared;
+
+Expected<std::unique_ptr<COFFVCRuntimeBootstrapper>>
+COFFVCRuntimeBootstrapper::Create(ExecutionSession &ES,
+ ObjectLinkingLayer &ObjLinkingLayer,
+ const char *RuntimePath) {
+ return std::unique_ptr<COFFVCRuntimeBootstrapper>(
+ new COFFVCRuntimeBootstrapper(ES, ObjLinkingLayer, RuntimePath));
+}
+
+COFFVCRuntimeBootstrapper::COFFVCRuntimeBootstrapper(
+ ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer,
+ const char *RuntimePath)
+ : ES(ES), ObjLinkingLayer(ObjLinkingLayer) {
+ if (RuntimePath)
+ this->RuntimePath = RuntimePath;
+}
+
+Expected<std::vector<std::string>>
+COFFVCRuntimeBootstrapper::loadStaticVCRuntime(JITDylib &JD,
+ bool DebugVersion) {
+ StringRef VCLibs[] = {"libvcruntime.lib", "libcmt.lib", "libcpmt.lib"};
+ StringRef UCRTLibs[] = {"libucrt.lib"};
+ std::vector<std::string> ImportedLibraries;
+ if (auto Err = loadVCRuntime(JD, ImportedLibraries, ArrayRef(VCLibs),
+ ArrayRef(UCRTLibs)))
+ return std::move(Err);
+ return ImportedLibraries;
+}
+
+Expected<std::vector<std::string>>
+COFFVCRuntimeBootstrapper::loadDynamicVCRuntime(JITDylib &JD,
+ bool DebugVersion) {
+ StringRef VCLibs[] = {"vcruntime.lib", "msvcrt.lib", "msvcprt.lib"};
+ StringRef UCRTLibs[] = {"ucrt.lib"};
+ std::vector<std::string> ImportedLibraries;
+ if (auto Err = loadVCRuntime(JD, ImportedLibraries, ArrayRef(VCLibs),
+ ArrayRef(UCRTLibs)))
+ return std::move(Err);
+ return ImportedLibraries;
+}
+
+Error COFFVCRuntimeBootstrapper::loadVCRuntime(
+ JITDylib &JD, std::vector<std::string> &ImportedLibraries,
+ ArrayRef<StringRef> VCLibs, ArrayRef<StringRef> UCRTLibs) {
+ MSVCToolchainPath Path;
+ if (!RuntimePath.empty()) {
+ Path.UCRTSdkLib = RuntimePath;
+ Path.VCToolchainLib = RuntimePath;
+ } else {
+ auto ToolchainPath = getMSVCToolchainPath();
+ if (!ToolchainPath)
+ return ToolchainPath.takeError();
+ Path = *ToolchainPath;
+ }
+ LLVM_DEBUG({
+ dbgs() << "Using VC toolchain pathes\n";
+ dbgs() << " VC toolchain path: " << Path.VCToolchainLib << "\n";
+ dbgs() << " UCRT path: " << Path.UCRTSdkLib << "\n";
+ });
+
+ auto LoadLibrary = [&](SmallString<256> LibPath, StringRef LibName) -> Error {
+ sys::path::append(LibPath, LibName);
+
+ auto G = StaticLibraryDefinitionGenerator::Load(ObjLinkingLayer,
+ LibPath.c_str());
+ if (!G)
+ return G.takeError();
+
+ for (auto &Lib : (*G)->getImportedDynamicLibraries())
+ ImportedLibraries.push_back(Lib);
+
+ JD.addGenerator(std::move(*G));
+
+ return Error::success();
+ };
+ for (auto &Lib : UCRTLibs)
+ if (auto Err = LoadLibrary(Path.UCRTSdkLib, Lib))
+ return Err;
+
+ for (auto &Lib : VCLibs)
+ if (auto Err = LoadLibrary(Path.VCToolchainLib, Lib))
+ return Err;
+ ImportedLibraries.push_back("ntdll.dll");
+ ImportedLibraries.push_back("Kernel32.dll");
+
+ return Error::success();
+}
+
+Error COFFVCRuntimeBootstrapper::initializeStaticVCRuntime(JITDylib &JD) {
+ ExecutorAddr jit_scrt_initialize, jit_scrt_dllmain_before_initialize_c,
+ jit_scrt_initialize_type_info,
+ jit_scrt_initialize_default_local_stdio_options;
+ if (auto Err = lookupAndRecordAddrs(
+ ES, LookupKind::Static, makeJITDylibSearchOrder(&JD),
+ {{ES.intern("__scrt_initialize_crt"), &jit_scrt_initialize},
+ {ES.intern("__scrt_dllmain_before_initialize_c"),
+ &jit_scrt_dllmain_before_initialize_c},
+ {ES.intern("?__scrt_initialize_type_info@@YAXXZ"),
+ &jit_scrt_initialize_type_info},
+ {ES.intern("__scrt_initialize_default_local_stdio_options"),
+ &jit_scrt_initialize_default_local_stdio_options}}))
+ return Err;
+
+ auto RunVoidInitFunc = [&](ExecutorAddr Addr) -> Error {
+ if (auto Res = ES.getExecutorProcessControl().runAsVoidFunction(Addr))
+ return Error::success();
+ else
+ return Res.takeError();
+ };
+
+ auto R =
+ ES.getExecutorProcessControl().runAsIntFunction(jit_scrt_initialize, 0);
+ if (!R)
+ return R.takeError();
+
+ if (auto Err = RunVoidInitFunc(jit_scrt_dllmain_before_initialize_c))
+ return Err;
+
+ if (auto Err = RunVoidInitFunc(jit_scrt_initialize_type_info))
+ return Err;
+
+ if (auto Err =
+ RunVoidInitFunc(jit_scrt_initialize_default_local_stdio_options))
+ return Err;
+
+ SymbolAliasMap Alias;
+ Alias[ES.intern("__run_after_c_init")] = {
+ ES.intern("__scrt_dllmain_after_initialize_c"), JITSymbolFlags::Exported};
+ if (auto Err = JD.define(symbolAliases(Alias)))
+ return Err;
+
+ return Error::success();
+}
+
+Expected<COFFVCRuntimeBootstrapper::MSVCToolchainPath>
+COFFVCRuntimeBootstrapper::getMSVCToolchainPath() {
+ std::string VCToolChainPath;
+ ToolsetLayout VSLayout;
+ IntrusiveRefCntPtr<vfs::FileSystem> VFS = vfs::getRealFileSystem();
+ if (!findVCToolChainViaCommandLine(*VFS, std::nullopt, std::nullopt,
+ std::nullopt, VCToolChainPath, VSLayout) &&
+ !findVCToolChainViaEnvironment(*VFS, VCToolChainPath, VSLayout) &&
+ !findVCToolChainViaSetupConfig(*VFS, VCToolChainPath, VSLayout) &&
+ !findVCToolChainViaRegistry(VCToolChainPath, VSLayout))
+ return make_error<StringError>("Couldn't find msvc toolchain.",
+ inconvertibleErrorCode());
+
+ std::string UniversalCRTSdkPath;
+ std::string UCRTVersion;
+ if (!getUniversalCRTSdkDir(*VFS, std::nullopt, std::nullopt, std::nullopt,
+ UniversalCRTSdkPath, UCRTVersion))
+ return make_error<StringError>("Couldn't find universal sdk.",
+ inconvertibleErrorCode());
+
+ MSVCToolchainPath ToolchainPath;
+ SmallString<256> VCToolchainLib(VCToolChainPath);
+ sys::path::append(VCToolchainLib, "lib", "x64");
+ ToolchainPath.VCToolchainLib = VCToolchainLib;
+
+ SmallString<256> UCRTSdkLib(UniversalCRTSdkPath);
+ sys::path::append(UCRTSdkLib, "Lib", UCRTVersion, "ucrt", "x64");
+ ToolchainPath.UCRTSdkLib = UCRTSdkLib;
+ return ToolchainPath;
+}
diff --git a/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/CompileOnDemandLayer.cpp b/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/CompileOnDemandLayer.cpp
index e2a0cadb6348..6448adaa0ceb 100644
--- a/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/CompileOnDemandLayer.cpp
+++ b/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/CompileOnDemandLayer.cpp
@@ -102,14 +102,14 @@ private:
CompileOnDemandLayer &Parent;
};
-Optional<CompileOnDemandLayer::GlobalValueSet>
+std::optional<CompileOnDemandLayer::GlobalValueSet>
CompileOnDemandLayer::compileRequested(GlobalValueSet Requested) {
return std::move(Requested);
}
-Optional<CompileOnDemandLayer::GlobalValueSet>
+std::optional<CompileOnDemandLayer::GlobalValueSet>
CompileOnDemandLayer::compileWholeModule(GlobalValueSet Requested) {
- return None;
+ return std::nullopt;
}
CompileOnDemandLayer::CompileOnDemandLayer(
@@ -237,7 +237,7 @@ void CompileOnDemandLayer::expandPartition(GlobalValueSet &Partition) {
bool ContainsGlobalVariables = false;
std::vector<const GlobalValue *> GVsToAdd;
- for (auto *GV : Partition)
+ for (const auto *GV : Partition)
if (isa<GlobalAlias>(GV))
GVsToAdd.push_back(
cast<GlobalValue>(cast<GlobalAlias>(GV)->getAliasee()));
@@ -252,7 +252,7 @@ void CompileOnDemandLayer::expandPartition(GlobalValueSet &Partition) {
for (auto &G : M.globals())
GVsToAdd.push_back(&G);
- for (auto *GV : GVsToAdd)
+ for (const auto *GV : GVsToAdd)
Partition.insert(GV);
}
@@ -287,7 +287,7 @@ void CompileOnDemandLayer::emitPartition(
// Take a 'None' partition to mean the whole module (as opposed to an empty
// partition, which means "materialize nothing"). Emit the whole module
// unmodified to the base layer.
- if (GVsToExtract == None) {
+ if (GVsToExtract == std::nullopt) {
Defs.clear();
BaseLayer.emit(std::move(R), std::move(TSM));
return;
@@ -336,13 +336,13 @@ void CompileOnDemandLayer::emitPartition(
{
std::vector<const GlobalValue*> HashGVs;
HashGVs.reserve(GVsToExtract->size());
- for (auto *GV : *GVsToExtract)
+ for (const auto *GV : *GVsToExtract)
HashGVs.push_back(GV);
llvm::sort(HashGVs, [](const GlobalValue *LHS, const GlobalValue *RHS) {
return LHS->getName() < RHS->getName();
});
hash_code HC(0);
- for (auto *GV : HashGVs) {
+ for (const auto *GV : HashGVs) {
assert(GV->hasName() && "All GVs to extract should be named by now");
auto GVName = GV->getName();
HC = hash_combine(HC, hash_combine_range(GVName.begin(), GVName.end()));
diff --git a/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/Core.cpp b/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/Core.cpp
index dd80630a33c1..4a9d0d470a8e 100644
--- a/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/Core.cpp
+++ b/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/Core.cpp
@@ -17,6 +17,7 @@
#include <condition_variable>
#include <future>
+#include <optional>
#define DEBUG_TYPE "orc"
@@ -970,10 +971,9 @@ Error JITDylib::resolve(MaterializationResponsibility &MR,
SymbolsInErrorState.insert(KV.first);
else {
auto Flags = KV.second.getFlags();
- Flags &= ~(JITSymbolFlags::Weak | JITSymbolFlags::Common);
+ Flags &= ~JITSymbolFlags::Common;
assert(Flags ==
- (SymI->second.getFlags() &
- ~(JITSymbolFlags::Weak | JITSymbolFlags::Common)) &&
+ (SymI->second.getFlags() & ~JITSymbolFlags::Common) &&
"Resolved flags should match the declared flags");
Worklist.push_back(
@@ -1482,8 +1482,8 @@ void JITDylib::dump(raw_ostream &OS) {
void JITDylib::MaterializingInfo::addQuery(
std::shared_ptr<AsynchronousSymbolQuery> Q) {
- auto I = std::lower_bound(
- PendingQueries.rbegin(), PendingQueries.rend(), Q->getRequiredState(),
+ auto I = llvm::lower_bound(
+ llvm::reverse(PendingQueries), Q->getRequiredState(),
[](const std::shared_ptr<AsynchronousSymbolQuery> &V, SymbolState S) {
return V->getRequiredState() <= S;
});
@@ -2244,8 +2244,8 @@ void ExecutionSession::dump(raw_ostream &OS) {
void ExecutionSession::dispatchOutstandingMUs() {
LLVM_DEBUG(dbgs() << "Dispatching MaterializationUnits...\n");
while (true) {
- Optional<std::pair<std::unique_ptr<MaterializationUnit>,
- std::unique_ptr<MaterializationResponsibility>>>
+ std::optional<std::pair<std::unique_ptr<MaterializationUnit>,
+ std::unique_ptr<MaterializationResponsibility>>>
JMU;
{
@@ -2285,9 +2285,10 @@ Error ExecutionSession::removeResourceTracker(ResourceTracker &RT) {
Error Err = Error::success();
+ auto &JD = RT.getJITDylib();
for (auto *L : reverse(CurrentResourceManagers))
- Err =
- joinErrors(std::move(Err), L->handleRemoveResources(RT.getKeyUnsafe()));
+ Err = joinErrors(std::move(Err),
+ L->handleRemoveResources(JD, RT.getKeyUnsafe()));
for (auto &Q : QueriesToFail)
Q->handleFailed(
@@ -2316,7 +2317,8 @@ void ExecutionSession::transferResourceTracker(ResourceTracker &DstRT,
auto &JD = DstRT.getJITDylib();
JD.transferTracker(DstRT, SrcRT);
for (auto *L : reverse(ResourceManagers))
- L->handleTransferResources(DstRT.getKeyUnsafe(), SrcRT.getKeyUnsafe());
+ L->handleTransferResources(JD, DstRT.getKeyUnsafe(),
+ SrcRT.getKeyUnsafe());
});
}
@@ -2427,7 +2429,7 @@ void ExecutionSession::OL_applyQueryPhase1(
// Add any non-candidates from the last JITDylib (if any) back on to the
// list of definition candidates for this JITDylib, reset definition
- // non-candiates to the empty set.
+ // non-candidates to the empty set.
SymbolLookupSet Tmp;
std::swap(IPLS->DefGeneratorNonCandidates, Tmp);
IPLS->DefGeneratorCandidates.append(std::move(Tmp));
@@ -2909,13 +2911,13 @@ Error ExecutionSession::OL_notifyResolved(MaterializationResponsibility &MR,
});
#ifndef NDEBUG
for (auto &KV : Symbols) {
- auto WeakFlags = JITSymbolFlags::Weak | JITSymbolFlags::Common;
auto I = MR.SymbolFlags.find(KV.first);
assert(I != MR.SymbolFlags.end() &&
"Resolving symbol outside this responsibility set");
assert(!I->second.hasMaterializationSideEffectsOnly() &&
"Can't resolve materialization-side-effects-only symbol");
- assert((KV.second.getFlags() & ~WeakFlags) == (I->second & ~WeakFlags) &&
+ assert((KV.second.getFlags() & ~JITSymbolFlags::Common) ==
+ (I->second & ~JITSymbolFlags::Common) &&
"Resolving symbol with incorrect flags");
}
#endif
diff --git a/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/DebugObjectManagerPlugin.cpp b/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/DebugObjectManagerPlugin.cpp
index 1e68ea1225e6..02c3e617df68 100644
--- a/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/DebugObjectManagerPlugin.cpp
+++ b/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/DebugObjectManagerPlugin.cpp
@@ -289,6 +289,9 @@ ELFDebugObject::CreateArchType(MemoryBufferRef Buffer,
continue;
HasDwarfSection |= isDwarfSection(*Name);
+ if (!(Header.sh_flags & ELF::SHF_ALLOC))
+ continue;
+
auto Wrapped = std::make_unique<ELFDebugObjectSection<ELFT>>(&Header);
if (Error Err = DebugObj->recordSection(*Name, std::move(Wrapped)))
return std::move(Err);
@@ -370,7 +373,9 @@ Error ELFDebugObject::recordSection(
return Err;
auto ItInserted = Sections.try_emplace(Name, std::move(Section));
if (!ItInserted.second)
- return make_error<StringError>("Duplicate section",
+ return make_error<StringError>("In " + Buffer->getBufferIdentifier() +
+ ", encountered duplicate section \"" +
+ Name + "\" while building debug object",
inconvertibleErrorCode());
return Error::success();
}
@@ -487,7 +492,8 @@ Error DebugObjectManagerPlugin::notifyFailed(
return Error::success();
}
-void DebugObjectManagerPlugin::notifyTransferringResources(ResourceKey DstKey,
+void DebugObjectManagerPlugin::notifyTransferringResources(JITDylib &JD,
+ ResourceKey DstKey,
ResourceKey SrcKey) {
// Debug objects are stored by ResourceKey only after registration.
// Thus, pending objects don't need to be updated here.
@@ -502,7 +508,8 @@ void DebugObjectManagerPlugin::notifyTransferringResources(ResourceKey DstKey,
}
}
-Error DebugObjectManagerPlugin::notifyRemovingResources(ResourceKey Key) {
+Error DebugObjectManagerPlugin::notifyRemovingResources(JITDylib &JD,
+ ResourceKey Key) {
// Removing the resource for a pending object fails materialization, so they
// get cleaned up in the notifyFailed() handler.
std::lock_guard<std::mutex> Lock(RegisteredObjsLock);
diff --git a/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/DebuggerSupportPlugin.cpp b/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/DebuggerSupportPlugin.cpp
index 3c44fe81b4a9..15e7ffb2f75a 100644
--- a/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/DebuggerSupportPlugin.cpp
+++ b/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/DebuggerSupportPlugin.cpp
@@ -137,7 +137,7 @@ public:
SmallVector<DebugSectionInfo, 12> DebugSecInfos;
size_t NumSections = 0;
for (auto &Sec : G.sections()) {
- if (llvm::empty(Sec.blocks()))
+ if (Sec.blocks().empty())
continue;
++NumSections;
@@ -189,7 +189,7 @@ public:
// Copy debug section blocks and symbols.
orc::ExecutorAddr NextBlockAddr(MachOContainerBlock->getSize());
for (auto &SI : DebugSecInfos) {
- assert(!llvm::empty(SI.Sec->blocks()) && "Empty debug info section?");
+ assert(!SI.Sec->blocks().empty() && "Empty debug info section?");
// Update addresses in debug section.
LLVM_DEBUG({
@@ -390,12 +390,12 @@ Error GDBJITDebugInfoRegistrationPlugin::notifyFailed(
}
Error GDBJITDebugInfoRegistrationPlugin::notifyRemovingResources(
- ResourceKey K) {
+ JITDylib &JD, ResourceKey K) {
return Error::success();
}
void GDBJITDebugInfoRegistrationPlugin::notifyTransferringResources(
- ResourceKey DstKey, ResourceKey SrcKey) {}
+ JITDylib &JD, ResourceKey DstKey, ResourceKey SrcKey) {}
void GDBJITDebugInfoRegistrationPlugin::modifyPassConfig(
MaterializationResponsibility &MR, LinkGraph &LG,
diff --git a/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/ELFNixPlatform.cpp b/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/ELFNixPlatform.cpp
index e7ca636c83e9..00032e4dca3f 100644
--- a/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/ELFNixPlatform.cpp
+++ b/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/ELFNixPlatform.cpp
@@ -16,6 +16,7 @@
#include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"
#include "llvm/Support/BinaryByteStream.h"
#include "llvm/Support/Debug.h"
+#include <optional>
#define DEBUG_TYPE "orc"
@@ -62,7 +63,7 @@ public:
"<DSOHandleMU>", TT, PointerSize, Endianness,
jitlink::getGenericEdgeKindName);
auto &DSOHandleSection =
- G->createSection(".data.__dso_handle", jitlink::MemProt::Read);
+ G->createSection(".data.__dso_handle", MemProt::Read);
auto &DSOHandleBlock = G->createContentBlock(
DSOHandleSection, getDSOHandleContent(PointerSize), orc::ExecutorAddr(),
8, 0);
@@ -110,7 +111,7 @@ Expected<std::unique_ptr<ELFNixPlatform>>
ELFNixPlatform::Create(ExecutionSession &ES,
ObjectLinkingLayer &ObjLinkingLayer,
JITDylib &PlatformJD, const char *OrcRuntimePath,
- Optional<SymbolAliasMap> RuntimeAliases) {
+ std::optional<SymbolAliasMap> RuntimeAliases) {
auto &EPC = ES.getExecutorProcessControl();
@@ -850,7 +851,7 @@ Error ELFNixPlatform::ELFNixPlatformPlugin::fixTLVSectionsAndEdges(
auto *TLSInfoEntrySection = G.findSectionByName("$__TLSINFO");
if (TLSInfoEntrySection) {
- Optional<uint64_t> Key;
+ std::optional<uint64_t> Key;
{
std::lock_guard<std::mutex> Lock(MP.PlatformMutex);
auto I = MP.JITDylibToPThreadKey.find(&JD);
diff --git a/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/EPCDebugObjectRegistrar.cpp b/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/EPCDebugObjectRegistrar.cpp
index c591acdd646b..30d641ee00cf 100644
--- a/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/EPCDebugObjectRegistrar.cpp
+++ b/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/EPCDebugObjectRegistrar.cpp
@@ -16,12 +16,17 @@
namespace llvm {
namespace orc {
-Expected<std::unique_ptr<EPCDebugObjectRegistrar>>
-createJITLoaderGDBRegistrar(ExecutionSession &ES) {
+Expected<std::unique_ptr<EPCDebugObjectRegistrar>> createJITLoaderGDBRegistrar(
+ ExecutionSession &ES,
+ std::optional<ExecutorAddr> RegistrationFunctionDylib) {
auto &EPC = ES.getExecutorProcessControl();
- auto ProcessHandle = EPC.loadDylib(nullptr);
- if (!ProcessHandle)
- return ProcessHandle.takeError();
+
+ if (!RegistrationFunctionDylib) {
+ if (auto D = EPC.loadDylib(nullptr))
+ RegistrationFunctionDylib = *D;
+ else
+ return D.takeError();
+ }
SymbolStringPtr RegisterFn =
EPC.getTargetTriple().isOSBinFormatMachO()
@@ -31,7 +36,8 @@ createJITLoaderGDBRegistrar(ExecutionSession &ES) {
SymbolLookupSet RegistrationSymbols;
RegistrationSymbols.add(RegisterFn);
- auto Result = EPC.lookupSymbols({{*ProcessHandle, RegistrationSymbols}});
+ auto Result =
+ EPC.lookupSymbols({{*RegistrationFunctionDylib, RegistrationSymbols}});
if (!Result)
return Result.takeError();
diff --git a/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/EPCDynamicLibrarySearchGenerator.cpp b/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/EPCDynamicLibrarySearchGenerator.cpp
index ba154aaecd1a..1adcc9156957 100644
--- a/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/EPCDynamicLibrarySearchGenerator.cpp
+++ b/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/EPCDynamicLibrarySearchGenerator.cpp
@@ -54,7 +54,7 @@ Error EPCDynamicLibrarySearchGenerator::tryToGenerate(
for (auto &KV : LookupSymbols) {
if (*ResultI)
NewSymbols[KV.first] =
- JITEvaluatedSymbol(*ResultI, JITSymbolFlags::Exported);
+ JITEvaluatedSymbol(ResultI->getValue(), JITSymbolFlags::Exported);
++ResultI;
}
diff --git a/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/EPCEHFrameRegistrar.cpp b/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/EPCEHFrameRegistrar.cpp
index 256ce94690f0..3aa94a7f43e2 100644
--- a/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/EPCEHFrameRegistrar.cpp
+++ b/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/EPCEHFrameRegistrar.cpp
@@ -16,17 +16,22 @@ using namespace llvm::orc::shared;
namespace llvm {
namespace orc {
-Expected<std::unique_ptr<EPCEHFrameRegistrar>>
-EPCEHFrameRegistrar::Create(ExecutionSession &ES) {
+Expected<std::unique_ptr<EPCEHFrameRegistrar>> EPCEHFrameRegistrar::Create(
+ ExecutionSession &ES,
+ std::optional<ExecutorAddr> RegistrationFunctionsDylib) {
// FIXME: Proper mangling here -- we really need to decouple linker mangling
// from DataLayout.
// Find the addresses of the registration/deregistration functions in the
// executor process.
auto &EPC = ES.getExecutorProcessControl();
- auto ProcessHandle = EPC.loadDylib(nullptr);
- if (!ProcessHandle)
- return ProcessHandle.takeError();
+
+ if (!RegistrationFunctionsDylib) {
+ if (auto D = EPC.loadDylib(nullptr))
+ RegistrationFunctionsDylib = *D;
+ else
+ return D.takeError();
+ }
std::string RegisterWrapperName, DeregisterWrapperName;
if (EPC.getTargetTriple().isOSBinFormatMachO()) {
@@ -40,7 +45,8 @@ EPCEHFrameRegistrar::Create(ExecutionSession &ES) {
RegistrationSymbols.add(EPC.intern(RegisterWrapperName));
RegistrationSymbols.add(EPC.intern(DeregisterWrapperName));
- auto Result = EPC.lookupSymbols({{*ProcessHandle, RegistrationSymbols}});
+ auto Result =
+ EPC.lookupSymbols({{*RegistrationFunctionsDylib, RegistrationSymbols}});
if (!Result)
return Result.takeError();
diff --git a/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/EPCGenericDylibManager.cpp b/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/EPCGenericDylibManager.cpp
index 6c47c5c5f7bb..e70749cdfab2 100644
--- a/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/EPCGenericDylibManager.cpp
+++ b/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/EPCGenericDylibManager.cpp
@@ -73,7 +73,7 @@ EPCGenericDylibManager::CreateWithDefaultBootstrapSymbols(
Expected<tpctypes::DylibHandle> EPCGenericDylibManager::open(StringRef Path,
uint64_t Mode) {
- Expected<tpctypes::DylibHandle> H(0);
+ Expected<tpctypes::DylibHandle> H((ExecutorAddr()));
if (auto Err =
EPC.callSPSWrapper<rt::SPSSimpleExecutorDylibManagerOpenSignature>(
SAs.Open, H, SAs.Instance, Path, Mode))
diff --git a/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/EPCGenericJITLinkMemoryManager.cpp b/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/EPCGenericJITLinkMemoryManager.cpp
index 75cc30753f41..a3d857c3bfc4 100644
--- a/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/EPCGenericJITLinkMemoryManager.cpp
+++ b/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/EPCGenericJITLinkMemoryManager.cpp
@@ -47,8 +47,7 @@ public:
for (auto &KV : Segs) {
assert(KV.second.ContentSize <= std::numeric_limits<size_t>::max());
FR.Segments.push_back(tpctypes::SegFinalizeRequest{
- tpctypes::toWireProtectionFlags(
- toSysMemoryProtectionFlags(KV.first.getMemProt())),
+ KV.first,
KV.second.Addr,
alignTo(KV.second.ContentSize + KV.second.ZeroFillSize,
Parent.EPC.getPageSize()),
diff --git a/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/EPCGenericRTDyldMemoryManager.cpp b/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/EPCGenericRTDyldMemoryManager.cpp
index cdac367e11a3..ec82081937e2 100644
--- a/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/EPCGenericRTDyldMemoryManager.cpp
+++ b/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/EPCGenericRTDyldMemoryManager.cpp
@@ -94,8 +94,8 @@ uint8_t *EPCGenericRTDyldMemoryManager::allocateDataSection(
}
void EPCGenericRTDyldMemoryManager::reserveAllocationSpace(
- uintptr_t CodeSize, uint32_t CodeAlign, uintptr_t RODataSize,
- uint32_t RODataAlign, uintptr_t RWDataSize, uint32_t RWDataAlign) {
+ uintptr_t CodeSize, Align CodeAlign, uintptr_t RODataSize,
+ Align RODataAlign, uintptr_t RWDataSize, Align RWDataAlign) {
{
std::lock_guard<std::mutex> Lock(M);
@@ -103,15 +103,15 @@ void EPCGenericRTDyldMemoryManager::reserveAllocationSpace(
if (!ErrMsg.empty())
return;
- if (!isPowerOf2_32(CodeAlign) || CodeAlign > EPC.getPageSize()) {
+ if (CodeAlign > EPC.getPageSize()) {
ErrMsg = "Invalid code alignment in reserveAllocationSpace";
return;
}
- if (!isPowerOf2_32(RODataAlign) || RODataAlign > EPC.getPageSize()) {
+ if (RODataAlign > EPC.getPageSize()) {
ErrMsg = "Invalid ro-data alignment in reserveAllocationSpace";
return;
}
- if (!isPowerOf2_32(RWDataAlign) || RWDataAlign > EPC.getPageSize()) {
+ if (RWDataAlign > EPC.getPageSize()) {
ErrMsg = "Invalid rw-data alignment in reserveAllocationSpace";
return;
}
@@ -142,7 +142,7 @@ void EPCGenericRTDyldMemoryManager::reserveAllocationSpace(
}
std::lock_guard<std::mutex> Lock(M);
- Unmapped.push_back(AllocGroup());
+ Unmapped.push_back(SectionAllocGroup());
Unmapped.back().RemoteCode = {
*TargetAllocAddr, ExecutorAddrDiff(alignTo(CodeSize, EPC.getPageSize()))};
Unmapped.back().RemoteROData = {
@@ -170,10 +170,11 @@ void EPCGenericRTDyldMemoryManager::registerEHFrames(uint8_t *Addr,
return;
ExecutorAddr LA(LoadAddr);
- for (auto &Alloc : llvm::reverse(Unfinalized)) {
- if (Alloc.RemoteCode.contains(LA) || Alloc.RemoteROData.contains(LA) ||
- Alloc.RemoteRWData.contains(LA)) {
- Alloc.UnfinalizedEHFrames.push_back({LA, Size});
+ for (auto &SecAllocGroup : llvm::reverse(Unfinalized)) {
+ if (SecAllocGroup.RemoteCode.contains(LA) ||
+ SecAllocGroup.RemoteROData.contains(LA) ||
+ SecAllocGroup.RemoteRWData.contains(LA)) {
+ SecAllocGroup.UnfinalizedEHFrames.push_back({LA, Size});
return;
}
}
@@ -204,35 +205,29 @@ bool EPCGenericRTDyldMemoryManager::finalizeMemory(std::string *ErrMsg) {
LLVM_DEBUG(dbgs() << "Allocator " << (void *)this << " finalizing:\n");
// If there's an error then bail out here.
- std::vector<AllocGroup> Allocs;
+ std::vector<SectionAllocGroup> SecAllocGroups;
{
std::lock_guard<std::mutex> Lock(M);
if (ErrMsg && !this->ErrMsg.empty()) {
*ErrMsg = std::move(this->ErrMsg);
return true;
}
- std::swap(Allocs, Unfinalized);
+ std::swap(SecAllocGroups, Unfinalized);
}
// Loop over unfinalized objects to make finalization requests.
- for (auto &ObjAllocs : Allocs) {
+ for (auto &SecAllocGroup : SecAllocGroups) {
- tpctypes::WireProtectionFlags SegProts[3] = {
- tpctypes::toWireProtectionFlags(
- static_cast<sys::Memory::ProtectionFlags>(sys::Memory::MF_READ |
- sys::Memory::MF_EXEC)),
- tpctypes::toWireProtectionFlags(sys::Memory::MF_READ),
- tpctypes::toWireProtectionFlags(
- static_cast<sys::Memory::ProtectionFlags>(sys::Memory::MF_READ |
- sys::Memory::MF_WRITE))};
+ MemProt SegMemProts[3] = {MemProt::Read | MemProt::Exec, MemProt::Read,
+ MemProt::Read | MemProt::Write};
- ExecutorAddrRange *RemoteAddrs[3] = {&ObjAllocs.RemoteCode,
- &ObjAllocs.RemoteROData,
- &ObjAllocs.RemoteRWData};
+ ExecutorAddrRange *RemoteAddrs[3] = {&SecAllocGroup.RemoteCode,
+ &SecAllocGroup.RemoteROData,
+ &SecAllocGroup.RemoteRWData};
- std::vector<Alloc> *SegSections[3] = {&ObjAllocs.CodeAllocs,
- &ObjAllocs.RODataAllocs,
- &ObjAllocs.RWDataAllocs};
+ std::vector<SectionAlloc> *SegSections[3] = {&SecAllocGroup.CodeAllocs,
+ &SecAllocGroup.RODataAllocs,
+ &SecAllocGroup.RWDataAllocs};
tpctypes::FinalizeRequest FR;
std::unique_ptr<char[]> AggregateContents[3];
@@ -240,7 +235,7 @@ bool EPCGenericRTDyldMemoryManager::finalizeMemory(std::string *ErrMsg) {
for (unsigned I = 0; I != 3; ++I) {
FR.Segments.push_back({});
auto &Seg = FR.Segments.back();
- Seg.Prot = SegProts[I];
+ Seg.AG = SegMemProts[I];
Seg.Addr = RemoteAddrs[I]->Start;
for (auto &SecAlloc : *SegSections[I]) {
Seg.Size = alignTo(Seg.Size, SecAlloc.Align);
@@ -261,7 +256,7 @@ bool EPCGenericRTDyldMemoryManager::finalizeMemory(std::string *ErrMsg) {
Seg.Content = {AggregateContents[I].get(), SecOffset};
}
- for (auto &Frame : ObjAllocs.UnfinalizedEHFrames)
+ for (auto &Frame : SecAllocGroup.UnfinalizedEHFrames)
FR.Actions.push_back(
{cantFail(
WrapperFunctionCall::Create<SPSArgList<SPSExecutorAddrRange>>(
@@ -297,7 +292,8 @@ bool EPCGenericRTDyldMemoryManager::finalizeMemory(std::string *ErrMsg) {
}
void EPCGenericRTDyldMemoryManager::mapAllocsToRemoteAddrs(
- RuntimeDyld &Dyld, std::vector<Alloc> &Allocs, ExecutorAddr NextAddr) {
+ RuntimeDyld &Dyld, std::vector<SectionAlloc> &Allocs,
+ ExecutorAddr NextAddr) {
for (auto &Alloc : Allocs) {
NextAddr.setValue(alignTo(NextAddr.getValue(), Alloc.Align));
LLVM_DEBUG({
diff --git a/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/EPCIndirectionUtils.cpp b/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/EPCIndirectionUtils.cpp
index 48aaab96e71f..ddfb30500c7b 100644
--- a/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/EPCIndirectionUtils.cpp
+++ b/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/EPCIndirectionUtils.cpp
@@ -250,6 +250,9 @@ EPCIndirectionUtils::Create(ExecutorProcessControl &EPC) {
case Triple::x86:
return CreateWithABI<OrcI386>(EPC);
+ case Triple::loongarch64:
+ return CreateWithABI<OrcLoongArch64>(EPC);
+
case Triple::mips:
return CreateWithABI<OrcMips32Be>(EPC);
diff --git a/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/ExecutionUtils.cpp b/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/ExecutionUtils.cpp
index 95cf89ec3f8b..377a59993eb0 100644
--- a/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/ExecutionUtils.cpp
+++ b/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/ExecutionUtils.cpp
@@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//
#include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"
+#include "llvm/ExecutionEngine/JITLink/x86_64.h"
#include "llvm/ExecutionEngine/Orc/Layer.h"
#include "llvm/ExecutionEngine/Orc/ObjectFileInterface.h"
#include "llvm/IR/Constants.h"
@@ -350,7 +351,6 @@ StaticLibraryDefinitionGenerator::Create(
Error StaticLibraryDefinitionGenerator::tryToGenerate(
LookupState &LS, LookupKind K, JITDylib &JD,
JITDylibLookupFlags JDLookupFlags, const SymbolLookupSet &Symbols) {
-
// Don't materialize symbols from static archives unless this is a static
// lookup.
if (K != LookupKind::Static)
@@ -364,16 +364,11 @@ Error StaticLibraryDefinitionGenerator::tryToGenerate(
for (const auto &KV : Symbols) {
const auto &Name = KV.first;
- auto Child = Archive->findSym(*Name);
- if (!Child)
- return Child.takeError();
- if (*Child == None)
+ if (!ObjectFilesMap.count(Name))
continue;
- auto ChildBuffer = (*Child)->getMemoryBufferRef();
- if (!ChildBuffer)
- return ChildBuffer.takeError();
+ auto ChildBuffer = ObjectFilesMap[Name];
ChildBufferInfos.insert(
- {ChildBuffer->getBuffer(), ChildBuffer->getBufferIdentifier()});
+ {ChildBuffer.getBuffer(), ChildBuffer.getBufferIdentifier()});
}
for (auto ChildBufferInfo : ChildBufferInfos) {
@@ -392,15 +387,163 @@ Error StaticLibraryDefinitionGenerator::tryToGenerate(
return Error::success();
}
+Error StaticLibraryDefinitionGenerator::buildObjectFilesMap() {
+ DenseMap<uint64_t, MemoryBufferRef> MemoryBuffers;
+ DenseSet<uint64_t> Visited;
+ DenseSet<uint64_t> Excluded;
+ for (auto &S : Archive->symbols()) {
+ StringRef SymName = S.getName();
+ auto Member = S.getMember();
+ if (!Member)
+ return Member.takeError();
+ auto DataOffset = Member->getDataOffset();
+ if (!Visited.count(DataOffset)) {
+ Visited.insert(DataOffset);
+ auto Child = Member->getAsBinary();
+ if (!Child)
+ return Child.takeError();
+ if ((*Child)->isCOFFImportFile()) {
+ ImportedDynamicLibraries.insert((*Child)->getFileName().str());
+ Excluded.insert(DataOffset);
+ continue;
+ }
+ MemoryBuffers[DataOffset] = (*Child)->getMemoryBufferRef();
+ }
+ if (!Excluded.count(DataOffset))
+ ObjectFilesMap[L.getExecutionSession().intern(SymName)] =
+ MemoryBuffers[DataOffset];
+ }
+
+ return Error::success();
+}
+
StaticLibraryDefinitionGenerator::StaticLibraryDefinitionGenerator(
ObjectLayer &L, std::unique_ptr<MemoryBuffer> ArchiveBuffer,
GetObjectFileInterface GetObjFileInterface, Error &Err)
: L(L), GetObjFileInterface(std::move(GetObjFileInterface)),
ArchiveBuffer(std::move(ArchiveBuffer)),
Archive(std::make_unique<object::Archive>(*this->ArchiveBuffer, Err)) {
-
+ ErrorAsOutParameter _(&Err);
if (!this->GetObjFileInterface)
this->GetObjFileInterface = getObjectFileInterface;
+ if (!Err)
+ Err = buildObjectFilesMap();
+}
+
+std::unique_ptr<DLLImportDefinitionGenerator>
+DLLImportDefinitionGenerator::Create(ExecutionSession &ES,
+ ObjectLinkingLayer &L) {
+ return std::unique_ptr<DLLImportDefinitionGenerator>(
+ new DLLImportDefinitionGenerator(ES, L));
+}
+
+Error DLLImportDefinitionGenerator::tryToGenerate(
+ LookupState &LS, LookupKind K, JITDylib &JD,
+ JITDylibLookupFlags JDLookupFlags, const SymbolLookupSet &Symbols) {
+ JITDylibSearchOrder LinkOrder;
+ JD.withLinkOrderDo([&](const JITDylibSearchOrder &LO) {
+ LinkOrder.reserve(LO.size());
+ for (auto &KV : LO) {
+ if (KV.first == &JD)
+ continue;
+ LinkOrder.push_back(KV);
+ }
+ });
+
+ // FIXME: if regular symbol name start with __imp_ we have to issue lookup of
+ // both __imp_ and stripped name and use the lookup information to resolve the
+ // real symbol name.
+ SymbolLookupSet LookupSet;
+ DenseMap<StringRef, SymbolLookupFlags> ToLookUpSymbols;
+ for (auto &KV : Symbols) {
+ StringRef Deinterned = *KV.first;
+ if (Deinterned.startswith(getImpPrefix()))
+ Deinterned = Deinterned.drop_front(StringRef(getImpPrefix()).size());
+ // Don't degrade the required state
+ if (ToLookUpSymbols.count(Deinterned) &&
+ ToLookUpSymbols[Deinterned] == SymbolLookupFlags::RequiredSymbol)
+ continue;
+ ToLookUpSymbols[Deinterned] = KV.second;
+ }
+
+ for (auto &KV : ToLookUpSymbols)
+ LookupSet.add(ES.intern(KV.first), KV.second);
+
+ auto Resolved =
+ ES.lookup(LinkOrder, LookupSet, LookupKind::DLSym, SymbolState::Resolved);
+ if (!Resolved)
+ return Resolved.takeError();
+
+ auto G = createStubsGraph(*Resolved);
+ if (!G)
+ return G.takeError();
+ return L.add(JD, std::move(*G));
+}
+
+Expected<unsigned>
+DLLImportDefinitionGenerator::getTargetPointerSize(const Triple &TT) {
+ switch (TT.getArch()) {
+ case Triple::x86_64:
+ return 8;
+ default:
+ return make_error<StringError>(
+ "architecture unsupported by DLLImportDefinitionGenerator",
+ inconvertibleErrorCode());
+ }
+}
+
+Expected<support::endianness>
+DLLImportDefinitionGenerator::getTargetEndianness(const Triple &TT) {
+ switch (TT.getArch()) {
+ case Triple::x86_64:
+ return support::endianness::little;
+ default:
+ return make_error<StringError>(
+ "architecture unsupported by DLLImportDefinitionGenerator",
+ inconvertibleErrorCode());
+ }
+}
+
+Expected<std::unique_ptr<jitlink::LinkGraph>>
+DLLImportDefinitionGenerator::createStubsGraph(const SymbolMap &Resolved) {
+ Triple TT = ES.getExecutorProcessControl().getTargetTriple();
+ auto PointerSize = getTargetEndianness(TT);
+ if (!PointerSize)
+ return PointerSize.takeError();
+ auto Endianness = getTargetEndianness(TT);
+ if (!Endianness)
+ return Endianness.takeError();
+
+ auto G = std::make_unique<jitlink::LinkGraph>(
+ "<DLLIMPORT_STUBS>", TT, *PointerSize, *Endianness,
+ jitlink::getGenericEdgeKindName);
+ jitlink::Section &Sec =
+ G->createSection(getSectionName(), MemProt::Read | MemProt::Exec);
+
+ for (auto &KV : Resolved) {
+ jitlink::Symbol &Target = G->addAbsoluteSymbol(
+ *KV.first, ExecutorAddr(KV.second.getAddress()), *PointerSize,
+ jitlink::Linkage::Strong, jitlink::Scope::Local, false);
+
+ // Create __imp_ symbol
+ jitlink::Symbol &Ptr =
+ jitlink::x86_64::createAnonymousPointer(*G, Sec, &Target);
+ auto NameCopy = G->allocateString(Twine(getImpPrefix()) + *KV.first);
+ StringRef NameCopyRef = StringRef(NameCopy.data(), NameCopy.size());
+ Ptr.setName(NameCopyRef);
+ Ptr.setLinkage(jitlink::Linkage::Strong);
+ Ptr.setScope(jitlink::Scope::Default);
+
+ // Create PLT stub
+ // FIXME: check PLT stub of data symbol is not accessed
+ jitlink::Block &StubBlock =
+ jitlink::x86_64::createPointerJumpStubBlock(*G, Sec, Ptr);
+ G->addDefinedSymbol(StubBlock, 0, *KV.first, StubBlock.getSize(),
+ jitlink::Linkage::Strong, jitlink::Scope::Default, true,
+ false);
+ }
+
+ return std::move(G);
}
} // End namespace orc.
diff --git a/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/ExecutorProcessControl.cpp b/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/ExecutorProcessControl.cpp
index 412b9f95ea62..361fcd4a2e9c 100644
--- a/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/ExecutorProcessControl.cpp
+++ b/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/ExecutorProcessControl.cpp
@@ -75,12 +75,10 @@ SelfExecutorProcessControl::Create(
Expected<tpctypes::DylibHandle>
SelfExecutorProcessControl::loadDylib(const char *DylibPath) {
std::string ErrMsg;
- auto Dylib = std::make_unique<sys::DynamicLibrary>(
- sys::DynamicLibrary::getPermanentLibrary(DylibPath, &ErrMsg));
- if (!Dylib->isValid())
+ auto Dylib = sys::DynamicLibrary::getPermanentLibrary(DylibPath, &ErrMsg);
+ if (!Dylib.isValid())
return make_error<StringError>(std::move(ErrMsg), inconvertibleErrorCode());
- DynamicLibraries.push_back(std::move(Dylib));
- return pointerToJITTargetAddress(DynamicLibraries.back().get());
+ return ExecutorAddr::fromPtr(Dylib.getOSSpecificHandle());
}
Expected<std::vector<tpctypes::LookupResult>>
@@ -88,26 +86,20 @@ SelfExecutorProcessControl::lookupSymbols(ArrayRef<LookupRequest> Request) {
std::vector<tpctypes::LookupResult> R;
for (auto &Elem : Request) {
- auto *Dylib = jitTargetAddressToPointer<sys::DynamicLibrary *>(Elem.Handle);
- assert(llvm::any_of(DynamicLibraries,
- [=](const std::unique_ptr<sys::DynamicLibrary> &DL) {
- return DL.get() == Dylib;
- }) &&
- "Invalid handle");
-
- R.push_back(std::vector<JITTargetAddress>());
+ sys::DynamicLibrary Dylib(Elem.Handle.toPtr<void *>());
+ R.push_back(std::vector<ExecutorAddr>());
for (auto &KV : Elem.Symbols) {
auto &Sym = KV.first;
std::string Tmp((*Sym).data() + !!GlobalManglingPrefix,
(*Sym).size() - !!GlobalManglingPrefix);
- void *Addr = Dylib->getAddressOfSymbol(Tmp.c_str());
+ void *Addr = Dylib.getAddressOfSymbol(Tmp.c_str());
if (!Addr && KV.second == SymbolLookupFlags::RequiredSymbol) {
// FIXME: Collect all failing symbols before erroring out.
SymbolNameVector MissingSymbols;
MissingSymbols.push_back(Sym);
return make_error<SymbolsNotFound>(SSP, std::move(MissingSymbols));
}
- R.back().push_back(pointerToJITTargetAddress(Addr));
+ R.back().push_back(ExecutorAddr::fromPtr(Addr));
}
}
@@ -121,6 +113,18 @@ SelfExecutorProcessControl::runAsMain(ExecutorAddr MainFnAddr,
return orc::runAsMain(MainFnAddr.toPtr<MainTy>(), Args);
}
+Expected<int32_t>
+SelfExecutorProcessControl::runAsVoidFunction(ExecutorAddr VoidFnAddr) {
+ using VoidTy = int (*)();
+ return orc::runAsVoidFunction(VoidFnAddr.toPtr<VoidTy>());
+}
+
+Expected<int32_t>
+SelfExecutorProcessControl::runAsIntFunction(ExecutorAddr IntFnAddr, int Arg) {
+ using IntTy = int (*)(int);
+ return orc::runAsIntFunction(IntFnAddr.toPtr<IntTy>(), Arg);
+}
+
void SelfExecutorProcessControl::callWrapperAsync(ExecutorAddr WrapperFnAddr,
IncomingWFRHandler SendResult,
ArrayRef<char> ArgBuffer) {
diff --git a/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/IndirectionUtils.cpp b/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/IndirectionUtils.cpp
index 38cab526704f..989bb094cc25 100644
--- a/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/IndirectionUtils.cpp
+++ b/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/IndirectionUtils.cpp
@@ -137,6 +137,11 @@ createLocalCompileCallbackManager(const Triple &T, ExecutionSession &ES,
return CCMgrT::Create(ES, ErrorHandlerAddress);
}
+ case Triple::loongarch64: {
+ typedef orc::LocalJITCompileCallbackManager<orc::OrcLoongArch64> CCMgrT;
+ return CCMgrT::Create(ES, ErrorHandlerAddress);
+ }
+
case Triple::mips: {
typedef orc::LocalJITCompileCallbackManager<orc::OrcMips32Be> CCMgrT;
return CCMgrT::Create(ES, ErrorHandlerAddress);
@@ -192,6 +197,12 @@ createLocalIndirectStubsManagerBuilder(const Triple &T) {
orc::LocalIndirectStubsManager<orc::OrcI386>>();
};
+ case Triple::loongarch64:
+ return []() {
+ return std::make_unique<
+ orc::LocalIndirectStubsManager<orc::OrcLoongArch64>>();
+ };
+
case Triple::mips:
return [](){
return std::make_unique<
@@ -407,7 +418,7 @@ Error addFunctionPointerRelocationsToCurrentSymbol(jitlink::Symbol &Sym,
auto SymStartInBlock =
(const uint8_t *)B.getContent().data() + Sym.getOffset();
auto SymSize = Sym.getSize() ? Sym.getSize() : B.getSize() - Sym.getOffset();
- auto Content = makeArrayRef(SymStartInBlock, SymSize);
+ auto Content = ArrayRef(SymStartInBlock, SymSize);
LLVM_DEBUG(dbgs() << "Adding self-relocations to " << Sym.getName() << "\n");
diff --git a/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/LLJIT.cpp b/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/LLJIT.cpp
index 1926ef1ecc72..bc84988e3254 100644
--- a/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/LLJIT.cpp
+++ b/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/LLJIT.cpp
@@ -9,12 +9,14 @@
#include "llvm/ExecutionEngine/Orc/LLJIT.h"
#include "llvm/ExecutionEngine/JITLink/EHFrameSupport.h"
#include "llvm/ExecutionEngine/JITLink/JITLinkMemoryManager.h"
+#include "llvm/ExecutionEngine/Orc/EPCEHFrameRegistrar.h"
#include "llvm/ExecutionEngine/Orc/ExecutorProcessControl.h"
#include "llvm/ExecutionEngine/Orc/MachOPlatform.h"
#include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h"
#include "llvm/ExecutionEngine/Orc/ObjectTransformLayer.h"
#include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h"
#include "llvm/ExecutionEngine/Orc/Shared/OrcError.h"
+#include "llvm/ExecutionEngine/Orc/TargetProcess/RegisterEHFrames.h"
#include "llvm/ExecutionEngine/SectionMemoryManager.h"
#include "llvm/IR/GlobalVariable.h"
#include "llvm/IR/IRBuilder.h"
@@ -81,6 +83,53 @@ Function *addHelperAndWrapper(Module &M, StringRef WrapperName,
return WrapperFn;
}
+class ORCPlatformSupport : public LLJIT::PlatformSupport {
+public:
+ ORCPlatformSupport(orc::LLJIT &J) : J(J) {}
+
+ Error initialize(orc::JITDylib &JD) override {
+ using llvm::orc::shared::SPSExecutorAddr;
+ using llvm::orc::shared::SPSString;
+ using SPSDLOpenSig = SPSExecutorAddr(SPSString, int32_t);
+ enum dlopen_mode : int32_t {
+ ORC_RT_RTLD_LAZY = 0x1,
+ ORC_RT_RTLD_NOW = 0x2,
+ ORC_RT_RTLD_LOCAL = 0x4,
+ ORC_RT_RTLD_GLOBAL = 0x8
+ };
+
+ if (auto WrapperAddr = J.lookup("__orc_rt_jit_dlopen_wrapper")) {
+ return J.getExecutionSession().callSPSWrapper<SPSDLOpenSig>(
+ *WrapperAddr, DSOHandles[&JD], JD.getName(),
+ int32_t(ORC_RT_RTLD_LAZY));
+ } else
+ return WrapperAddr.takeError();
+ }
+
+ Error deinitialize(orc::JITDylib &JD) override {
+ using llvm::orc::shared::SPSExecutorAddr;
+ using SPSDLCloseSig = int32_t(SPSExecutorAddr);
+
+ if (auto WrapperAddr = J.lookup("__orc_rt_jit_dlclose_wrapper")) {
+ int32_t result;
+ auto E = J.getExecutionSession().callSPSWrapper<SPSDLCloseSig>(
+ *WrapperAddr, result, DSOHandles[&JD]);
+ if (E)
+ return E;
+ else if (result)
+ return make_error<StringError>("dlclose failed",
+ inconvertibleErrorCode());
+ DSOHandles.erase(&JD);
+ } else
+ return WrapperAddr.takeError();
+ return Error::success();
+ }
+
+private:
+ orc::LLJIT &J;
+ DenseMap<orc::JITDylib *, orc::ExecutorAddr> DSOHandles;
+};
+
class GenericLLVMIRPlatformSupport;
/// orc::Platform component of Generic LLVM IR Platform support.
@@ -667,6 +716,7 @@ Error LLJITBuilderState::prepareForConstruction() {
if (!CreateObjectLinkingLayer) {
auto &TT = JTMB->getTargetTriple();
if (TT.getArch() == Triple::riscv64 ||
+ TT.getArch() == Triple::loongarch64 ||
(TT.isOSBinFormatMachO() &&
(TT.getArch() == Triple::aarch64 || TT.getArch() == Triple::x86_64))) {
@@ -676,8 +726,12 @@ Error LLJITBuilderState::prepareForConstruction() {
[](ExecutionSession &ES,
const Triple &) -> Expected<std::unique_ptr<ObjectLayer>> {
auto ObjLinkingLayer = std::make_unique<ObjectLinkingLayer>(ES);
- ObjLinkingLayer->addPlugin(std::make_unique<EHFrameRegistrationPlugin>(
- ES, std::make_unique<jitlink::InProcessEHFrameRegistrar>()));
+ if (auto EHFrameRegistrar = EPCEHFrameRegistrar::Create(ES))
+ ObjLinkingLayer->addPlugin(
+ std::make_unique<EHFrameRegistrationPlugin>(
+ ES, std::move(*EHFrameRegistrar)));
+ else
+ return EHFrameRegistrar.takeError();
return std::move(ObjLinkingLayer);
};
}
@@ -746,6 +800,11 @@ LLJIT::createObjectLinkingLayer(LLJITBuilderState &S, ExecutionSession &ES) {
Layer->setAutoClaimResponsibilityForObjectSymbols(true);
}
+ if (S.JTMB->getTargetTriple().isOSBinFormatELF() &&
+ (S.JTMB->getTargetTriple().getArch() == Triple::ArchType::ppc64 ||
+ S.JTMB->getTargetTriple().getArch() == Triple::ArchType::ppc64le))
+ Layer->setAutoClaimResponsibilityForObjectSymbols(true);
+
// FIXME: Explicit conversion to std::unique_ptr<ObjectLayer> added to silence
// errors from some GCC / libstdc++ bots. Remove this conversion (i.e.
// just return ObjLinkingLayer) once those bots are upgraded.
@@ -875,6 +934,13 @@ Error LLJIT::applyDataLayout(Module &M) {
return Error::success();
}
+Error setUpOrcPlatform(LLJIT& J) {
+ LLVM_DEBUG(
+ { dbgs() << "Setting up orc platform support for LLJIT\n"; });
+ J.setPlatformSupport(std::make_unique<ORCPlatformSupport>(J));
+ return Error::success();
+}
+
void setUpGenericLLVMIRPlatform(LLJIT &J) {
LLVM_DEBUG(
{ dbgs() << "Setting up GenericLLVMIRPlatform support for LLJIT\n"; });
@@ -950,5 +1016,12 @@ LLLazyJIT::LLLazyJIT(LLLazyJITBuilderState &S, Error &Err) : LLJIT(S, Err) {
CODLayer->setCloneToNewContextOnEmit(true);
}
+// In-process LLJIT uses eh-frame section wrappers via EPC, so we need to force
+// them to be linked in.
+LLVM_ATTRIBUTE_USED void linkComponents() {
+ errs() << (void *)&llvm_orc_registerEHFrameSectionWrapper
+ << (void *)&llvm_orc_deregisterEHFrameSectionWrapper;
+}
+
} // End namespace orc.
} // End namespace llvm.
diff --git a/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/Layer.cpp b/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/Layer.cpp
index 4a50f2d7a153..95380d912392 100644
--- a/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/Layer.cpp
+++ b/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/Layer.cpp
@@ -77,11 +77,14 @@ IRMaterializationUnit::IRMaterializationUnit(
// Otherwise we just need a normal linker mangling.
auto MangledName = Mangle(G.getName());
SymbolFlags[MangledName] = JITSymbolFlags::fromGlobalValue(G);
+ if (G.getComdat() &&
+ G.getComdat()->getSelectionKind() != Comdat::NoDeduplicate)
+ SymbolFlags[MangledName] |= JITSymbolFlags::Weak;
SymbolToDefinition[MangledName] = &G;
}
// If we need an init symbol for this module then create one.
- if (!llvm::empty(getStaticInitGVs(M))) {
+ if (!getStaticInitGVs(M).empty()) {
size_t Counter = 0;
do {
diff --git a/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/LazyReexports.cpp b/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/LazyReexports.cpp
index 20b655bdf4b1..c0a740d42dbd 100644
--- a/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/LazyReexports.cpp
+++ b/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/LazyReexports.cpp
@@ -119,6 +119,10 @@ createLocalLazyCallThroughManager(const Triple &T, ExecutionSession &ES,
case Triple::x86:
return LocalLazyCallThroughManager::Create<OrcI386>(ES, ErrorHandlerAddr);
+ case Triple::loongarch64:
+ return LocalLazyCallThroughManager::Create<OrcLoongArch64>(
+ ES, ErrorHandlerAddr);
+
case Triple::mips:
return LocalLazyCallThroughManager::Create<OrcMips32Be>(ES,
ErrorHandlerAddr);
diff --git a/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/LookupAndRecordAddrs.cpp b/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/LookupAndRecordAddrs.cpp
index 3452267e4df4..59c63d38458b 100644
--- a/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/LookupAndRecordAddrs.cpp
+++ b/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/LookupAndRecordAddrs.cpp
@@ -73,7 +73,7 @@ Error lookupAndRecordAddrs(
inconvertibleErrorCode());
for (unsigned I = 0; I != Pairs.size(); ++I)
- Pairs[I].second->setValue(Result->front()[I]);
+ *Pairs[I].second = Result->front()[I];
return Error::success();
}
diff --git a/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/MachOPlatform.cpp b/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/MachOPlatform.cpp
index d5274b06a76f..914a1b5afc71 100644
--- a/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/MachOPlatform.cpp
+++ b/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/MachOPlatform.cpp
@@ -15,6 +15,7 @@
#include "llvm/ExecutionEngine/Orc/LookupAndRecordAddrs.h"
#include "llvm/Support/BinaryByteStream.h"
#include "llvm/Support/Debug.h"
+#include <optional>
#define DEBUG_TYPE "orc"
@@ -57,6 +58,29 @@ public:
namespace {
+std::unique_ptr<jitlink::LinkGraph> createPlatformGraph(MachOPlatform &MOP,
+ std::string Name) {
+ unsigned PointerSize;
+ support::endianness Endianness;
+ const auto &TT =
+ MOP.getExecutionSession().getExecutorProcessControl().getTargetTriple();
+
+ switch (TT.getArch()) {
+ case Triple::aarch64:
+ case Triple::x86_64:
+ PointerSize = 8;
+ Endianness = support::endianness::little;
+ break;
+ default:
+ llvm_unreachable("Unrecognized architecture");
+ }
+
+ return std::make_unique<jitlink::LinkGraph>(std::move(Name), TT, PointerSize,
+ Endianness,
+ jitlink::getGenericEdgeKindName);
+}
+
+// Generates a MachO header.
class MachOHeaderMaterializationUnit : public MaterializationUnit {
public:
MachOHeaderMaterializationUnit(MachOPlatform &MOP,
@@ -67,41 +91,28 @@ public:
StringRef getName() const override { return "MachOHeaderMU"; }
void materialize(std::unique_ptr<MaterializationResponsibility> R) override {
- unsigned PointerSize;
- support::endianness Endianness;
- const auto &TT =
- MOP.getExecutionSession().getExecutorProcessControl().getTargetTriple();
+ auto G = createPlatformGraph(MOP, "<MachOHeaderMU>");
+ addMachOHeader(*G, MOP, R->getInitializerSymbol());
+ MOP.getObjectLinkingLayer().emit(std::move(R), std::move(G));
+ }
- switch (TT.getArch()) {
- case Triple::aarch64:
- case Triple::x86_64:
- PointerSize = 8;
- Endianness = support::endianness::little;
- break;
- default:
- llvm_unreachable("Unrecognized architecture");
- }
+ void discard(const JITDylib &JD, const SymbolStringPtr &Sym) override {}
- auto G = std::make_unique<jitlink::LinkGraph>(
- "<MachOHeaderMU>", TT, PointerSize, Endianness,
- jitlink::getGenericEdgeKindName);
- auto &HeaderSection = G->createSection("__header", jitlink::MemProt::Read);
- auto &HeaderBlock = createHeaderBlock(*G, HeaderSection);
+ static void addMachOHeader(jitlink::LinkGraph &G, MachOPlatform &MOP,
+ const SymbolStringPtr &InitializerSymbol) {
+ auto &HeaderSection = G.createSection("__header", MemProt::Read);
+ auto &HeaderBlock = createHeaderBlock(G, HeaderSection);
// Init symbol is header-start symbol.
- G->addDefinedSymbol(HeaderBlock, 0, *R->getInitializerSymbol(),
- HeaderBlock.getSize(), jitlink::Linkage::Strong,
- jitlink::Scope::Default, false, true);
+ G.addDefinedSymbol(HeaderBlock, 0, *InitializerSymbol,
+ HeaderBlock.getSize(), jitlink::Linkage::Strong,
+ jitlink::Scope::Default, false, true);
for (auto &HS : AdditionalHeaderSymbols)
- G->addDefinedSymbol(HeaderBlock, HS.Offset, HS.Name,
- HeaderBlock.getSize(), jitlink::Linkage::Strong,
- jitlink::Scope::Default, false, true);
-
- MOP.getObjectLinkingLayer().emit(std::move(R), std::move(G));
+ G.addDefinedSymbol(HeaderBlock, HS.Offset, HS.Name, HeaderBlock.getSize(),
+ jitlink::Linkage::Strong, jitlink::Scope::Default,
+ false, true);
}
- void discard(const JITDylib &JD, const SymbolStringPtr &Sym) override {}
-
private:
struct HeaderSymbol {
const char *Name;
@@ -163,7 +174,82 @@ private:
constexpr MachOHeaderMaterializationUnit::HeaderSymbol
MachOHeaderMaterializationUnit::AdditionalHeaderSymbols[];
+// Creates a Bootstrap-Complete LinkGraph to run deferred actions.
+class MachOPlatformCompleteBootstrapMaterializationUnit
+ : public MaterializationUnit {
+public:
+ MachOPlatformCompleteBootstrapMaterializationUnit(
+ MachOPlatform &MOP, StringRef PlatformJDName,
+ SymbolStringPtr CompleteBootstrapSymbol, shared::AllocActions DeferredAAs,
+ ExecutorAddr PlatformBootstrap, ExecutorAddr PlatformShutdown,
+ ExecutorAddr RegisterJITDylib, ExecutorAddr DeregisterJITDylib,
+ ExecutorAddr MachOHeaderAddr)
+ : MaterializationUnit(
+ {{{CompleteBootstrapSymbol, JITSymbolFlags::None}}, nullptr}),
+ MOP(MOP), PlatformJDName(PlatformJDName),
+ CompleteBootstrapSymbol(std::move(CompleteBootstrapSymbol)),
+ DeferredAAs(std::move(DeferredAAs)),
+ PlatformBootstrap(PlatformBootstrap),
+ PlatformShutdown(PlatformShutdown), RegisterJITDylib(RegisterJITDylib),
+ DeregisterJITDylib(DeregisterJITDylib),
+ MachOHeaderAddr(MachOHeaderAddr) {}
+
+ StringRef getName() const override {
+ return "MachOPlatformCompleteBootstrap";
+ }
+
+ void materialize(std::unique_ptr<MaterializationResponsibility> R) override {
+ using namespace jitlink;
+ auto G = createPlatformGraph(MOP, "<OrcRTCompleteBootstrap>");
+ auto &PlaceholderSection =
+ G->createSection("__orc_rt_cplt_bs", MemProt::Read);
+ auto &PlaceholderBlock =
+ G->createZeroFillBlock(PlaceholderSection, 1, ExecutorAddr(), 1, 0);
+ G->addDefinedSymbol(PlaceholderBlock, 0, *CompleteBootstrapSymbol, 1,
+ Linkage::Strong, Scope::Hidden, false, true);
+
+ // Reserve space for the stolen actions, plus two extras.
+ G->allocActions().reserve(DeferredAAs.size() + 2);
+
+ // 1. Bootstrap the platform support code.
+ G->allocActions().push_back(
+ {cantFail(WrapperFunctionCall::Create<SPSArgList<>>(PlatformBootstrap)),
+ cantFail(
+ WrapperFunctionCall::Create<SPSArgList<>>(PlatformShutdown))});
+
+ // 2. Register the platform JITDylib.
+ G->allocActions().push_back(
+ {cantFail(WrapperFunctionCall::Create<
+ SPSArgList<SPSString, SPSExecutorAddr>>(
+ RegisterJITDylib, PlatformJDName, MachOHeaderAddr)),
+ cantFail(WrapperFunctionCall::Create<SPSArgList<SPSExecutorAddr>>(
+ DeregisterJITDylib, MachOHeaderAddr))});
+
+ // 3. Add the deferred actions to the graph.
+ std::move(DeferredAAs.begin(), DeferredAAs.end(),
+ std::back_inserter(G->allocActions()));
+
+ MOP.getObjectLinkingLayer().emit(std::move(R), std::move(G));
+ }
+
+ void discard(const JITDylib &JD, const SymbolStringPtr &Sym) override {}
+
+private:
+ MachOPlatform &MOP;
+ StringRef PlatformJDName;
+ SymbolStringPtr CompleteBootstrapSymbol;
+ shared::AllocActions DeferredAAs;
+ ExecutorAddr PlatformBootstrap;
+ ExecutorAddr PlatformShutdown;
+ ExecutorAddr RegisterJITDylib;
+ ExecutorAddr DeregisterJITDylib;
+ ExecutorAddr MachOHeaderAddr;
+};
+
+StringRef DataCommonSectionName = "__DATA,__common";
+StringRef DataDataSectionName = "__DATA,__data";
StringRef EHFrameSectionName = "__TEXT,__eh_frame";
+StringRef CompactUnwindInfoSectionName = "__TEXT,__unwind_info";
StringRef ModInitFuncSectionName = "__DATA,__mod_init_func";
StringRef ObjCClassListSectionName = "__DATA,__objc_classlist";
StringRef ObjCImageInfoSectionName = "__DATA,__objc_image_info";
@@ -187,7 +273,7 @@ namespace orc {
Expected<std::unique_ptr<MachOPlatform>>
MachOPlatform::Create(ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer,
JITDylib &PlatformJD, const char *OrcRuntimePath,
- Optional<SymbolAliasMap> RuntimeAliases) {
+ std::optional<SymbolAliasMap> RuntimeAliases) {
auto &EPC = ES.getExecutorProcessControl();
@@ -335,52 +421,115 @@ MachOPlatform::MachOPlatform(
ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer,
JITDylib &PlatformJD,
std::unique_ptr<DefinitionGenerator> OrcRuntimeGenerator, Error &Err)
- : ES(ES), ObjLinkingLayer(ObjLinkingLayer),
- MachOHeaderStartSymbol(ES.intern("___dso_handle")) {
+ : ES(ES), PlatformJD(PlatformJD), ObjLinkingLayer(ObjLinkingLayer) {
ErrorAsOutParameter _(&Err);
-
ObjLinkingLayer.addPlugin(std::make_unique<MachOPlatformPlugin>(*this));
-
PlatformJD.addGenerator(std::move(OrcRuntimeGenerator));
- // Force linking of eh-frame registration functions.
- if (auto Err2 = lookupAndRecordAddrs(
- ES, LookupKind::Static, makeJITDylibSearchOrder(&PlatformJD),
- {{ES.intern("___orc_rt_macho_register_ehframe_section"),
- &orc_rt_macho_register_ehframe_section},
- {ES.intern("___orc_rt_macho_deregister_ehframe_section"),
- &orc_rt_macho_deregister_ehframe_section}})) {
- Err = std::move(Err2);
+ BootstrapInfo BI;
+ Bootstrap = &BI;
+
+ // Bootstrap process -- here be phase-ordering dragons.
+ //
+ // The MachOPlatform class uses allocation actions to register metadata
+ // sections with the ORC runtime, however the runtime contains metadata
+ // registration functions that have their own metadata that they need to
+ // register (e.g. the frame-info registration functions have frame-info).
+ // We can't use an ordinary lookup to find these registration functions
+ // because their address is needed during the link of the containing graph
+ // itself (to build the allocation actions that will call the registration
+ // functions). Further complicating the situation (a) the graph containing
+ // the registration functions is allowed to depend on other graphs (e.g. the
+ // graph containing the ORC runtime RTTI support) so we need to handle with
+ // an unknown set of dependencies during bootstrap, and (b) these graphs may
+ // be linked concurrently if the user has installed a concurrent dispatcher.
+ //
+ // We satisfy these constraint by implementing a bootstrap phase during which
+ // allocation actions generated by MachOPlatform are appended to a list of
+ // deferred allocation actions, rather than to the graphs themselves. At the
+ // end of the bootstrap process the deferred actions are attached to a final
+ // "complete-bootstrap" graph that causes them to be run.
+ //
+ // The bootstrap steps are as follows:
+ //
+ // 1. Request the graph containing the mach header. This graph is guaranteed
+ // not to have any metadata so the fact that the registration functions
+ // are not available yet is not a problem.
+ //
+ // 2. Look up the registration functions and discard the results. This will
+ // trigger linking of the graph containing these functions, and
+ // consequently any graphs that it depends on. We do not use the lookup
+ // result to find the addresses of the functions requested (as described
+ // above the lookup will return too late for that), instead we capture the
+ // addresses in a post-allocation pass injected by the platform runtime
+ // during bootstrap only.
+ //
+ // 3. During bootstrap the MachOPlatformPlugin keeps a count of the number of
+ // graphs being linked (potentially concurrently), and we block until all
+ // of these graphs have completed linking. This is to avoid a race on the
+ // deferred-actions vector: the lookup for the runtime registration
+ // functions may return while some functions (those that are being
+ // incidentally linked in, but aren't reachable via the runtime functions)
+ // are still being linked, and we need to capture any allocation actions
+ // for this incidental code before we proceed.
+ //
+ // 4. Once all active links are complete we transfer the deferred actions to
+ // a newly added CompleteBootstrap graph and then request a symbol from
+ // the CompleteBootstrap graph to trigger materialization. This will cause
+ // all deferred actions to be run, and once this lookup returns we can
+ // proceed.
+ //
+ // 5. Finally, we associate runtime support methods in MachOPlatform with
+ // the corresponding jit-dispatch tag variables in the ORC runtime to make
+ // the support methods callable. The bootstrap is now complete.
+
+ // Step (1) Add header materialization unit and request.
+ if ((Err = PlatformJD.define(std::make_unique<MachOHeaderMaterializationUnit>(
+ *this, MachOHeaderStartSymbol))))
return;
- }
-
- State = BootstrapPhase2;
-
- // Associate wrapper function tags with JIT-side function implementations.
- if (auto E2 = associateRuntimeSupportFunctions(PlatformJD)) {
- Err = std::move(E2);
+ if ((Err = ES.lookup(&PlatformJD, MachOHeaderStartSymbol).takeError()))
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 = bootstrapMachORuntime(PlatformJD)) {
- Err = std::move(E2);
+ // Step (2) Request runtime registration functions to trigger
+ // materialization..
+ if ((Err = ES.lookup(makeJITDylibSearchOrder(&PlatformJD),
+ SymbolLookupSet(
+ {PlatformBootstrap.Name, PlatformShutdown.Name,
+ RegisterJITDylib.Name, DeregisterJITDylib.Name,
+ RegisterObjectPlatformSections.Name,
+ DeregisterObjectPlatformSections.Name,
+ CreatePThreadKey.Name}))
+ .takeError()))
return;
+
+ // Step (3) Wait for any incidental linker work to complete.
+ {
+ std::unique_lock<std::mutex> Lock(BI.Mutex);
+ BI.CV.wait(Lock, [&]() { return BI.ActiveGraphs == 0; });
+ Bootstrap = nullptr;
}
- // 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);
+ // Step (4) Add complete-bootstrap materialization unit and request.
+ auto BootstrapCompleteSymbol = ES.intern("__orc_rt_macho_complete_bootstrap");
+ if ((Err = PlatformJD.define(
+ std::make_unique<MachOPlatformCompleteBootstrapMaterializationUnit>(
+ *this, PlatformJD.getName(), BootstrapCompleteSymbol,
+ std::move(BI.DeferredAAs), PlatformBootstrap.Addr,
+ PlatformShutdown.Addr, RegisterJITDylib.Addr,
+ DeregisterJITDylib.Addr, BI.MachOHeaderAddr))))
+ return;
+ if ((Err = ES.lookup(makeJITDylibSearchOrder(
+ &PlatformJD, JITDylibLookupFlags::MatchAllSymbols),
+ std::move(BootstrapCompleteSymbol))
+ .takeError()))
return;
- }
- State = Initialized;
+ // (5) Associate runtime support functions.
+ if ((Err = associateRuntimeSupportFunctions()))
+ return;
}
-Error MachOPlatform::associateRuntimeSupportFunctions(JITDylib &PlatformJD) {
+Error MachOPlatform::associateRuntimeSupportFunctions() {
ExecutionSession::JITDispatchHandlerAssociationMap WFs;
using PushInitializersSPSSig =
@@ -440,24 +589,17 @@ void MachOPlatform::pushInitializersLoop(
if (NewInitSymbols.empty()) {
// To make the list intelligible to the runtime we need to convert all
- // JITDylib pointers to their header addresses.
+ // JITDylib pointers to their header addresses. Only include JITDylibs
+ // that appear in the JITDylibToHeaderAddr map (i.e. those that have been
+ // through setupJITDylib) -- bare JITDylibs aren't managed by the platform.
DenseMap<JITDylib *, ExecutorAddr> HeaderAddrs;
HeaderAddrs.reserve(JDDepMap.size());
{
std::lock_guard<std::mutex> Lock(PlatformMutex);
for (auto &KV : JDDepMap) {
auto I = JITDylibToHeaderAddr.find(KV.first);
- if (I == JITDylibToHeaderAddr.end()) {
- // The header address should have been materialized by the previous
- // round, but we need to handle the pathalogical case where someone
- // removes the symbol on another thread while we're running.
- SendResult(
- make_error<StringError>("JITDylib " + KV.first->getName() +
- " has no registered header address",
- inconvertibleErrorCode()));
- return;
- }
- HeaderAddrs[KV.first] = I->second;
+ if (I != JITDylibToHeaderAddr.end())
+ HeaderAddrs[KV.first] = I->second;
}
}
@@ -465,12 +607,16 @@ void MachOPlatform::pushInitializersLoop(
MachOJITDylibDepInfoMap DIM;
DIM.reserve(JDDepMap.size());
for (auto &KV : JDDepMap) {
- assert(HeaderAddrs.count(KV.first) && "Missing header addr");
- auto H = HeaderAddrs[KV.first];
+ auto HI = HeaderAddrs.find(KV.first);
+ // Skip unmanaged JITDylibs.
+ if (HI == HeaderAddrs.end())
+ continue;
+ auto H = HI->second;
MachOJITDylibDepInfo DepInfo;
for (auto &Dep : KV.second) {
- assert(HeaderAddrs.count(Dep) && "Missing header addr");
- DepInfo.DepHeaders.push_back(HeaderAddrs[Dep]);
+ auto HJ = HeaderAddrs.find(Dep);
+ if (HJ != HeaderAddrs.end())
+ DepInfo.DepHeaders.push_back(HJ->second);
}
DIM.push_back(std::make_pair(H, std::move(DepInfo)));
}
@@ -480,7 +626,7 @@ void MachOPlatform::pushInitializersLoop(
// Otherwise issue a lookup and re-run this phase when it completes.
lookupInitSymbolsAsync(
- [this, SendResult = std::move(SendResult), &JD](Error Err) mutable {
+ [this, SendResult = std::move(SendResult), JD](Error Err) mutable {
if (Err)
SendResult(std::move(Err));
else
@@ -571,30 +717,8 @@ void MachOPlatform::rt_lookupSymbol(SendSymbolAddressFn SendResult,
RtLookupNotifyComplete(std::move(SendResult)), NoDependenciesToRegister);
}
-Error MachOPlatform::bootstrapMachORuntime(JITDylib &PlatformJD) {
- if (auto Err = lookupAndRecordAddrs(
- ES, LookupKind::Static, makeJITDylibSearchOrder(&PlatformJD),
- {{ES.intern("___orc_rt_macho_platform_bootstrap"),
- &orc_rt_macho_platform_bootstrap},
- {ES.intern("___orc_rt_macho_platform_shutdown"),
- &orc_rt_macho_platform_shutdown},
- {ES.intern("___orc_rt_macho_register_jitdylib"),
- &orc_rt_macho_register_jitdylib},
- {ES.intern("___orc_rt_macho_deregister_jitdylib"),
- &orc_rt_macho_deregister_jitdylib},
- {ES.intern("___orc_rt_macho_register_object_platform_sections"),
- &orc_rt_macho_register_object_platform_sections},
- {ES.intern("___orc_rt_macho_deregister_object_platform_sections"),
- &orc_rt_macho_deregister_object_platform_sections},
- {ES.intern("___orc_rt_macho_create_pthread_key"),
- &orc_rt_macho_create_pthread_key}}))
- return Err;
-
- return ES.callSPSWrapper<void()>(orc_rt_macho_platform_bootstrap);
-}
-
Expected<uint64_t> MachOPlatform::createPThreadKey() {
- if (!orc_rt_macho_create_pthread_key)
+ if (!CreatePThreadKey.Addr)
return make_error<StringError>(
"Attempting to create pthread key in target, but runtime support has "
"not been loaded yet",
@@ -602,7 +726,7 @@ Expected<uint64_t> MachOPlatform::createPThreadKey() {
Expected<uint64_t> Result(0);
if (auto Err = ES.callSPSWrapper<SPSExpected<uint64_t>(void)>(
- orc_rt_macho_create_pthread_key, Result))
+ CreatePThreadKey.Addr, Result))
return std::move(Err);
return Result;
}
@@ -611,7 +735,19 @@ void MachOPlatform::MachOPlatformPlugin::modifyPassConfig(
MaterializationResponsibility &MR, jitlink::LinkGraph &LG,
jitlink::PassConfiguration &Config) {
- auto PS = MP.State.load();
+ using namespace jitlink;
+
+ bool InBootstrapPhase =
+ &MR.getTargetJITDylib() == &MP.PlatformJD && MP.Bootstrap;
+
+ // If we're in the bootstrap phase then increment the active graphs.
+ if (InBootstrapPhase) {
+ Config.PrePrunePasses.push_back(
+ [this](LinkGraph &G) { return bootstrapPipelineStart(G); });
+ Config.PostAllocationPasses.push_back([this](LinkGraph &G) {
+ return bootstrapPipelineRecordRuntimeFunctions(G);
+ });
+ }
// --- Handle Initializers ---
if (auto InitSymbol = MR.getInitializerSymbol()) {
@@ -619,8 +755,8 @@ void MachOPlatform::MachOPlatformPlugin::modifyPassConfig(
// If the initializer symbol is the MachOHeader start symbol then just
// register it and then bail out -- the header materialization unit
// definitely doesn't need any other passes.
- if (InitSymbol == MP.MachOHeaderStartSymbol) {
- Config.PostAllocationPasses.push_back([this, &MR](jitlink::LinkGraph &G) {
+ if (InitSymbol == MP.MachOHeaderStartSymbol && !InBootstrapPhase) {
+ Config.PostAllocationPasses.push_back([this, &MR](LinkGraph &G) {
return associateJITDylibHeaderSymbol(G, MR);
});
return;
@@ -629,34 +765,33 @@ void MachOPlatform::MachOPlatformPlugin::modifyPassConfig(
// If the object contains an init symbol other than the header start symbol
// then add passes to preserve, process and register the init
// sections/symbols.
- Config.PrePrunePasses.push_back([this, &MR](jitlink::LinkGraph &G) {
+ Config.PrePrunePasses.push_back([this, &MR](LinkGraph &G) {
if (auto Err = preserveInitSections(G, MR))
return Err;
return processObjCImageInfo(G, MR);
});
}
- // --- Add passes for eh-frame and TLV support ---
- if (PS == MachOPlatform::BootstrapPhase1) {
- Config.PostFixupPasses.push_back(
- [this](jitlink::LinkGraph &G) { return registerEHSectionsPhase1(G); });
- return;
- }
-
// Insert TLV lowering at the start of the PostPrunePasses, since we want
// it to run before GOT/PLT lowering.
Config.PostPrunePasses.insert(
Config.PostPrunePasses.begin(),
- [this, &JD = MR.getTargetJITDylib()](jitlink::LinkGraph &G) {
+ [this, &JD = MR.getTargetJITDylib()](LinkGraph &G) {
return fixTLVSectionsAndEdges(G, JD);
});
// Add a pass to register the final addresses of any special sections in the
// object with the runtime.
Config.PostAllocationPasses.push_back(
- [this, &JD = MR.getTargetJITDylib()](jitlink::LinkGraph &G) {
- return registerObjectPlatformSections(G, JD);
+ [this, &JD = MR.getTargetJITDylib(), InBootstrapPhase](LinkGraph &G) {
+ return registerObjectPlatformSections(G, JD, InBootstrapPhase);
});
+
+ // If we're in the bootstrap phase then steal allocation actions and then
+ // decrement the active graphs.
+ if (InBootstrapPhase)
+ Config.PostFixupPasses.push_back(
+ [this](LinkGraph &G) { return bootstrapPipelineEnd(G); });
}
ObjectLinkingLayer::Plugin::SyntheticSymbolDependenciesMap
@@ -673,6 +808,73 @@ MachOPlatform::MachOPlatformPlugin::getSyntheticSymbolDependencies(
return SyntheticSymbolDependenciesMap();
}
+Error MachOPlatform::MachOPlatformPlugin::bootstrapPipelineStart(
+ jitlink::LinkGraph &G) {
+ // Increment the active graphs count in BootstrapInfo.
+ std::lock_guard<std::mutex> Lock(MP.Bootstrap.load()->Mutex);
+ ++MP.Bootstrap.load()->ActiveGraphs;
+ return Error::success();
+}
+
+Error MachOPlatform::MachOPlatformPlugin::
+ bootstrapPipelineRecordRuntimeFunctions(jitlink::LinkGraph &G) {
+ // Record bootstrap function names.
+ std::pair<StringRef, ExecutorAddr *> RuntimeSymbols[] = {
+ {*MP.MachOHeaderStartSymbol, &MP.Bootstrap.load()->MachOHeaderAddr},
+ {*MP.PlatformBootstrap.Name, &MP.PlatformBootstrap.Addr},
+ {*MP.PlatformShutdown.Name, &MP.PlatformShutdown.Addr},
+ {*MP.RegisterJITDylib.Name, &MP.RegisterJITDylib.Addr},
+ {*MP.DeregisterJITDylib.Name, &MP.DeregisterJITDylib.Addr},
+ {*MP.RegisterObjectPlatformSections.Name,
+ &MP.RegisterObjectPlatformSections.Addr},
+ {*MP.DeregisterObjectPlatformSections.Name,
+ &MP.DeregisterObjectPlatformSections.Addr},
+ {*MP.CreatePThreadKey.Name, &MP.CreatePThreadKey.Addr}};
+
+ bool RegisterMachOHeader = false;
+
+ for (auto *Sym : G.defined_symbols()) {
+ for (auto &RTSym : RuntimeSymbols) {
+ if (Sym->hasName() && Sym->getName() == RTSym.first) {
+ if (*RTSym.second)
+ return make_error<StringError>(
+ "Duplicate " + RTSym.first +
+ " detected during MachOPlatform bootstrap",
+ inconvertibleErrorCode());
+
+ if (Sym->getName() == *MP.MachOHeaderStartSymbol)
+ RegisterMachOHeader = true;
+
+ *RTSym.second = Sym->getAddress();
+ }
+ }
+ }
+
+ if (RegisterMachOHeader) {
+ // If this graph defines the macho header symbol then create the internal
+ // mapping between it and PlatformJD.
+ std::lock_guard<std::mutex> Lock(MP.PlatformMutex);
+ MP.JITDylibToHeaderAddr[&MP.PlatformJD] =
+ MP.Bootstrap.load()->MachOHeaderAddr;
+ MP.HeaderAddrToJITDylib[MP.Bootstrap.load()->MachOHeaderAddr] =
+ &MP.PlatformJD;
+ }
+
+ return Error::success();
+}
+
+Error MachOPlatform::MachOPlatformPlugin::bootstrapPipelineEnd(
+ jitlink::LinkGraph &G) {
+ std::lock_guard<std::mutex> Lock(MP.Bootstrap.load()->Mutex);
+ assert(MP.Bootstrap && "DeferredAAs reset before bootstrap completed");
+ --MP.Bootstrap.load()->ActiveGraphs;
+ // Notify Bootstrap->CV while holding the mutex because the mutex is
+ // also keeping Bootstrap->CV alive.
+ if (MP.Bootstrap.load()->ActiveGraphs == 0)
+ MP.Bootstrap.load()->CV.notify_all();
+ return Error::success();
+}
+
Error MachOPlatform::MachOPlatformPlugin::associateJITDylibHeaderSymbol(
jitlink::LinkGraph &G, MaterializationResponsibility &MR) {
auto I = llvm::find_if(G.defined_symbols(), [this](jitlink::Symbol *Sym) {
@@ -685,12 +887,14 @@ Error MachOPlatform::MachOPlatformPlugin::associateJITDylibHeaderSymbol(
auto HeaderAddr = (*I)->getAddress();
MP.JITDylibToHeaderAddr[&JD] = HeaderAddr;
MP.HeaderAddrToJITDylib[HeaderAddr] = &JD;
+ // We can unconditionally add these actions to the Graph because this pass
+ // isn't used during bootstrap.
G.allocActions().push_back(
{cantFail(
WrapperFunctionCall::Create<SPSArgList<SPSString, SPSExecutorAddr>>(
- MP.orc_rt_macho_register_jitdylib, JD.getName(), HeaderAddr)),
+ MP.RegisterJITDylib.Addr, JD.getName(), HeaderAddr)),
cantFail(WrapperFunctionCall::Create<SPSArgList<SPSExecutorAddr>>(
- MP.orc_rt_macho_deregister_jitdylib, HeaderAddr))});
+ MP.DeregisterJITDylib.Addr, HeaderAddr))});
return Error::success();
}
@@ -747,7 +951,7 @@ Error MachOPlatform::MachOPlatformPlugin::processObjCImageInfo(
auto ObjCImageInfoBlocks = ObjCImageInfo->blocks();
// Check that the section is not empty if present.
- if (llvm::empty(ObjCImageInfoBlocks))
+ if (ObjCImageInfoBlocks.empty())
return make_error<StringError>("Empty " + ObjCImageInfoSectionName +
" section in " + G.getName(),
inconvertibleErrorCode());
@@ -821,7 +1025,7 @@ Error MachOPlatform::MachOPlatformPlugin::fixTLVSectionsAndEdges(
// Store key in __thread_vars struct fields.
if (auto *ThreadDataSec = G.findSectionByName(ThreadVarsSectionName)) {
- Optional<uint64_t> Key;
+ std::optional<uint64_t> Key;
{
std::lock_guard<std::mutex> Lock(MP.PlatformMutex);
auto I = MP.JITDylibToPThreadKey.find(&JD);
@@ -865,22 +1069,84 @@ Error MachOPlatform::MachOPlatformPlugin::fixTLVSectionsAndEdges(
return Error::success();
}
-Error MachOPlatform::MachOPlatformPlugin::registerObjectPlatformSections(
- jitlink::LinkGraph &G, JITDylib &JD) {
+std::optional<MachOPlatform::MachOPlatformPlugin::UnwindSections>
+MachOPlatform::MachOPlatformPlugin::findUnwindSectionInfo(
+ jitlink::LinkGraph &G) {
+ using namespace jitlink;
- // Add an action to register the eh-frame.
- if (auto *EHFrameSection = G.findSectionByName(EHFrameSectionName)) {
- jitlink::SectionRange R(*EHFrameSection);
- if (!R.empty())
- G.allocActions().push_back(
- {cantFail(
- WrapperFunctionCall::Create<SPSArgList<SPSExecutorAddrRange>>(
- MP.orc_rt_macho_register_ehframe_section, R.getRange())),
- cantFail(
- WrapperFunctionCall::Create<SPSArgList<SPSExecutorAddrRange>>(
- MP.orc_rt_macho_deregister_ehframe_section, R.getRange()))});
+ UnwindSections US;
+
+ // ScanSection records a section range and adds any executable blocks that
+ // that section points to to the CodeBlocks vector.
+ SmallVector<Block *> CodeBlocks;
+ auto ScanUnwindInfoSection = [&](Section &Sec, ExecutorAddrRange &SecRange) {
+ if (Sec.blocks().empty())
+ return;
+ SecRange = (*Sec.blocks().begin())->getRange();
+ for (auto *B : Sec.blocks()) {
+ auto R = B->getRange();
+ SecRange.Start = std::min(SecRange.Start, R.Start);
+ SecRange.End = std::max(SecRange.End, R.End);
+ for (auto &E : B->edges()) {
+ if (!E.getTarget().isDefined())
+ continue;
+ auto &TargetBlock = E.getTarget().getBlock();
+ auto &TargetSection = TargetBlock.getSection();
+ if ((TargetSection.getMemProt() & MemProt::Exec) == MemProt::Exec)
+ CodeBlocks.push_back(&TargetBlock);
+ }
+ }
+ };
+
+ if (Section *EHFrameSec = G.findSectionByName(EHFrameSectionName))
+ ScanUnwindInfoSection(*EHFrameSec, US.DwarfSection);
+
+ if (Section *CUInfoSec = G.findSectionByName(CompactUnwindInfoSectionName))
+ ScanUnwindInfoSection(*CUInfoSec, US.CompactUnwindSection);
+
+ // If we didn't find any pointed-to code-blocks then there's no need to
+ // register any info.
+ if (CodeBlocks.empty())
+ return std::nullopt;
+
+ // We have info to register. Sort the code blocks into address order and
+ // build a list of contiguous address ranges covering them all.
+ llvm::sort(CodeBlocks, [](const Block *LHS, const Block *RHS) {
+ return LHS->getAddress() < RHS->getAddress();
+ });
+ for (auto *B : CodeBlocks) {
+ if (US.CodeRanges.empty() || US.CodeRanges.back().End != B->getAddress())
+ US.CodeRanges.push_back(B->getRange());
+ else
+ US.CodeRanges.back().End = B->getRange().End;
}
+ LLVM_DEBUG({
+ dbgs() << "MachOPlatform identified unwind info in " << G.getName() << ":\n"
+ << " DWARF: ";
+ if (US.DwarfSection.Start)
+ dbgs() << US.DwarfSection << "\n";
+ else
+ dbgs() << "none\n";
+ dbgs() << " Compact-unwind: ";
+ if (US.CompactUnwindSection.Start)
+ dbgs() << US.CompactUnwindSection << "\n";
+ else
+ dbgs() << "none\n"
+ << "for code ranges:\n";
+ for (auto &CR : US.CodeRanges)
+ dbgs() << " " << CR << "\n";
+ if (US.CodeRanges.size() >= G.sections_size())
+ dbgs() << "WARNING: High number of discontiguous code ranges! "
+ "Padding may be interfering with coalescing.\n";
+ });
+
+ return US;
+}
+
+Error MachOPlatform::MachOPlatformPlugin::registerObjectPlatformSections(
+ jitlink::LinkGraph &G, JITDylib &JD, bool InBootstrapPhase) {
+
// Get a pointer to the thread data section if there is one. It will be used
// below.
jitlink::Section *ThreadDataSection =
@@ -899,18 +1165,23 @@ Error MachOPlatform::MachOPlatformPlugin::registerObjectPlatformSections(
SmallVector<std::pair<StringRef, ExecutorAddrRange>, 8> MachOPlatformSecs;
+ // Collect data sections to register.
+ StringRef DataSections[] = {DataDataSectionName, DataCommonSectionName,
+ EHFrameSectionName};
+ for (auto &SecName : DataSections) {
+ if (auto *Sec = G.findSectionByName(SecName)) {
+ jitlink::SectionRange R(*Sec);
+ if (!R.empty())
+ MachOPlatformSecs.push_back({SecName, R.getRange()});
+ }
+ }
+
// Having merged thread BSS (if present) and thread data (if present),
// record the resulting section range.
if (ThreadDataSection) {
jitlink::SectionRange R(*ThreadDataSection);
- if (!R.empty()) {
- if (MP.State != MachOPlatform::Initialized)
- return make_error<StringError>("__thread_data section encountered, but "
- "MachOPlatform has not finished booting",
- inconvertibleErrorCode());
-
+ if (!R.empty())
MachOPlatformSecs.push_back({ThreadDataSectionName, R.getRange()});
- }
}
// If any platform sections were found then add an allocation action to call
@@ -933,19 +1204,23 @@ Error MachOPlatform::MachOPlatformPlugin::registerObjectPlatformSections(
MachOPlatformSecs.push_back({SecName, R.getRange()});
}
- if (!MachOPlatformSecs.empty()) {
- Optional<ExecutorAddr> HeaderAddr;
+ std::optional<std::tuple<SmallVector<ExecutorAddrRange>, ExecutorAddrRange,
+ ExecutorAddrRange>>
+ UnwindInfo;
+ if (auto UI = findUnwindSectionInfo(G))
+ UnwindInfo = std::make_tuple(std::move(UI->CodeRanges), UI->DwarfSection,
+ UI->CompactUnwindSection);
+
+ if (!MachOPlatformSecs.empty() || UnwindInfo) {
+ ExecutorAddr HeaderAddr;
{
std::lock_guard<std::mutex> Lock(MP.PlatformMutex);
auto I = MP.JITDylibToHeaderAddr.find(&JD);
- if (I != MP.JITDylibToHeaderAddr.end())
- HeaderAddr = I->second;
+ assert(I != MP.JITDylibToHeaderAddr.end() &&
+ "Missing header for JITDylib");
+ HeaderAddr = I->second;
}
- if (!HeaderAddr)
- return make_error<StringError>("Missing header for " + JD.getName(),
- inconvertibleErrorCode());
-
// Dump the scraped inits.
LLVM_DEBUG({
dbgs() << "MachOPlatform: Scraped " << G.getName() << " init sections:\n";
@@ -953,71 +1228,29 @@ Error MachOPlatform::MachOPlatformPlugin::registerObjectPlatformSections(
dbgs() << " " << KV.first << ": " << KV.second << "\n";
});
- using SPSRegisterObjectPlatformSectionsArgs =
- SPSArgList<SPSExecutorAddr,
- SPSSequence<SPSTuple<SPSString, SPSExecutorAddrRange>>>;
- G.allocActions().push_back(
+ using SPSRegisterObjectPlatformSectionsArgs = SPSArgList<
+ SPSExecutorAddr,
+ SPSOptional<SPSTuple<SPSSequence<SPSExecutorAddrRange>,
+ SPSExecutorAddrRange, SPSExecutorAddrRange>>,
+ SPSSequence<SPSTuple<SPSString, SPSExecutorAddrRange>>>;
+
+ shared::AllocActions &allocActions = LLVM_LIKELY(!InBootstrapPhase)
+ ? G.allocActions()
+ : MP.Bootstrap.load()->DeferredAAs;
+
+ allocActions.push_back(
{cantFail(
WrapperFunctionCall::Create<SPSRegisterObjectPlatformSectionsArgs>(
- MP.orc_rt_macho_register_object_platform_sections, *HeaderAddr,
+ MP.RegisterObjectPlatformSections.Addr, HeaderAddr, UnwindInfo,
MachOPlatformSecs)),
cantFail(
WrapperFunctionCall::Create<SPSRegisterObjectPlatformSectionsArgs>(
- MP.orc_rt_macho_deregister_object_platform_sections,
- *HeaderAddr, MachOPlatformSecs))});
+ MP.DeregisterObjectPlatformSections.Addr, HeaderAddr,
+ UnwindInfo, MachOPlatformSecs))});
}
return Error::success();
}
-Error MachOPlatform::MachOPlatformPlugin::registerEHSectionsPhase1(
- jitlink::LinkGraph &G) {
-
- // If there's no eh-frame there's nothing to do.
- auto *EHFrameSection = G.findSectionByName(EHFrameSectionName);
- if (!EHFrameSection)
- return Error::success();
-
- // If the eh-frame section is empty there's nothing to do.
- jitlink::SectionRange R(*EHFrameSection);
- if (R.empty())
- return Error::success();
-
- // Since we're linking the object containing the registration code now the
- // addresses won't be ready in the platform. We'll have to find them in this
- // graph instead.
- ExecutorAddr orc_rt_macho_register_ehframe_section;
- ExecutorAddr orc_rt_macho_deregister_ehframe_section;
- for (auto *Sym : G.defined_symbols()) {
- if (!Sym->hasName())
- continue;
- if (Sym->getName() == "___orc_rt_macho_register_ehframe_section")
- orc_rt_macho_register_ehframe_section = ExecutorAddr(Sym->getAddress());
- else if (Sym->getName() == "___orc_rt_macho_deregister_ehframe_section")
- orc_rt_macho_deregister_ehframe_section = ExecutorAddr(Sym->getAddress());
-
- if (orc_rt_macho_register_ehframe_section &&
- orc_rt_macho_deregister_ehframe_section)
- break;
- }
-
- // If we failed to find the required functions then bail out.
- if (!orc_rt_macho_register_ehframe_section ||
- !orc_rt_macho_deregister_ehframe_section)
- return make_error<StringError>("Could not find eh-frame registration "
- "functions during platform bootstrap",
- inconvertibleErrorCode());
-
- // Otherwise, add allocation actions to the graph to register eh-frames for
- // this object.
- G.allocActions().push_back(
- {cantFail(WrapperFunctionCall::Create<SPSArgList<SPSExecutorAddrRange>>(
- orc_rt_macho_register_ehframe_section, R.getRange())),
- cantFail(WrapperFunctionCall::Create<SPSArgList<SPSExecutorAddrRange>>(
- orc_rt_macho_deregister_ehframe_section, R.getRange()))});
-
- return Error::success();
-}
-
} // End namespace orc.
} // End namespace llvm.
diff --git a/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/MapperJITLinkMemoryManager.cpp b/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/MapperJITLinkMemoryManager.cpp
index c2e7baabb994..d099a251232e 100644
--- a/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/MapperJITLinkMemoryManager.cpp
+++ b/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/MapperJITLinkMemoryManager.cpp
@@ -8,11 +8,10 @@
#include "llvm/ExecutionEngine/Orc/MapperJITLinkMemoryManager.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/ExecutionEngine/JITLink/JITLink.h"
#include "llvm/Support/Process.h"
-#include <limits>
-
using namespace llvm::jitlink;
namespace llvm {
@@ -33,7 +32,8 @@ public:
std::swap(AI.Segments, Segs);
std::swap(AI.Actions, G.allocActions());
- Parent.Mapper->initialize(AI, [&](Expected<ExecutorAddr> Result) {
+ Parent.Mapper->initialize(AI, [OnFinalize = std::move(OnFinalize)](
+ Expected<ExecutorAddr> Result) mutable {
if (!Result) {
OnFinalize(Result.takeError());
return;
@@ -55,8 +55,9 @@ private:
};
MapperJITLinkMemoryManager::MapperJITLinkMemoryManager(
- std::unique_ptr<MemoryMapper> Mapper)
- : Mapper(std::move(Mapper)) {}
+ size_t ReservationGranularity, std::unique_ptr<MemoryMapper> Mapper)
+ : ReservationUnits(ReservationGranularity), AvailableMemory(AMAllocator),
+ Mapper(std::move(Mapper)) {}
void MapperJITLinkMemoryManager::allocate(const JITLinkDylib *JD, LinkGraph &G,
OnAllocatedFunction OnAllocated) {
@@ -69,55 +70,78 @@ void MapperJITLinkMemoryManager::allocate(const JITLinkDylib *JD, LinkGraph &G,
return;
}
- // Check if total size fits in address space
- if (SegsSizes->total() > std::numeric_limits<size_t>::max()) {
- OnAllocated(make_error<JITLinkError>(
- formatv("Total requested size {:x} for graph {} exceeds address space",
- SegsSizes->total(), G.getName())));
- return;
- }
+ auto TotalSize = SegsSizes->total();
+
+ auto CompleteAllocation = [this, &G, BL = std::move(BL),
+ OnAllocated = std::move(OnAllocated)](
+ Expected<ExecutorAddrRange> Result) mutable {
+ if (!Result) {
+ Mutex.unlock();
+ return OnAllocated(Result.takeError());
+ }
+
+ auto NextSegAddr = Result->Start;
+
+ std::vector<MemoryMapper::AllocInfo::SegInfo> SegInfos;
+
+ for (auto &KV : BL.segments()) {
+ auto &AG = KV.first;
+ auto &Seg = KV.second;
- Mapper->reserve(
- SegsSizes->total(),
- [this, &G, BL = std::move(BL), OnAllocated = std::move(OnAllocated)](
- Expected<ExecutorAddrRange> Result) mutable {
- if (!Result) {
- return OnAllocated(Result.takeError());
- }
+ auto TotalSize = Seg.ContentSize + Seg.ZeroFillSize;
- auto NextSegAddr = Result->Start;
+ Seg.Addr = NextSegAddr;
+ Seg.WorkingMem = Mapper->prepare(NextSegAddr, TotalSize);
- std::vector<MemoryMapper::AllocInfo::SegInfo> SegInfos;
+ NextSegAddr += alignTo(TotalSize, Mapper->getPageSize());
- for (auto &KV : BL.segments()) {
- auto &AG = KV.first;
- auto &Seg = KV.second;
+ MemoryMapper::AllocInfo::SegInfo SI;
+ SI.Offset = Seg.Addr - Result->Start;
+ SI.ContentSize = Seg.ContentSize;
+ SI.ZeroFillSize = Seg.ZeroFillSize;
+ SI.AG = AG;
+ SI.WorkingMem = Seg.WorkingMem;
- auto TotalSize = Seg.ContentSize + Seg.ZeroFillSize;
+ SegInfos.push_back(SI);
+ }
- Seg.Addr = NextSegAddr;
- Seg.WorkingMem = Mapper->prepare(NextSegAddr, TotalSize);
+ UsedMemory.insert({Result->Start, NextSegAddr - Result->Start});
- NextSegAddr += alignTo(TotalSize, Mapper->getPageSize());
+ if (NextSegAddr < Result->End) {
+ // Save the remaining memory for reuse in next allocation(s)
+ AvailableMemory.insert(NextSegAddr, Result->End - 1, true);
+ }
+ Mutex.unlock();
- MemoryMapper::AllocInfo::SegInfo SI;
- SI.Offset = Seg.Addr - Result->Start;
- SI.ContentSize = Seg.ContentSize;
- SI.ZeroFillSize = Seg.ZeroFillSize;
- SI.Prot = (toSysMemoryProtectionFlags(AG.getMemProt()));
- SI.WorkingMem = Seg.WorkingMem;
+ if (auto Err = BL.apply()) {
+ OnAllocated(std::move(Err));
+ return;
+ }
- SegInfos.push_back(SI);
- }
+ OnAllocated(std::make_unique<InFlightAlloc>(*this, G, Result->Start,
+ std::move(SegInfos)));
+ };
- if (auto Err = BL.apply()) {
- OnAllocated(std::move(Err));
- return;
- }
+ Mutex.lock();
- OnAllocated(std::make_unique<InFlightAlloc>(*this, G, Result->Start,
- std::move(SegInfos)));
- });
+ // find an already reserved range that is large enough
+ ExecutorAddrRange SelectedRange{};
+
+ for (AvailableMemoryMap::iterator It = AvailableMemory.begin();
+ It != AvailableMemory.end(); It++) {
+ if (It.stop() - It.start() + 1 >= TotalSize) {
+ SelectedRange = ExecutorAddrRange(It.start(), It.stop() + 1);
+ It.erase();
+ break;
+ }
+ }
+
+ if (SelectedRange.empty()) { // no already reserved range was found
+ auto TotalAllocation = alignTo(TotalSize, ReservationUnits);
+ Mapper->reserve(TotalAllocation, std::move(CompleteAllocation));
+ } else {
+ CompleteAllocation(SelectedRange);
+ }
}
void MapperJITLinkMemoryManager::deallocate(
@@ -125,10 +149,40 @@ void MapperJITLinkMemoryManager::deallocate(
std::vector<ExecutorAddr> Bases;
Bases.reserve(Allocs.size());
for (auto &FA : Allocs) {
- Bases.push_back(FA.getAddress());
- FA.release();
+ ExecutorAddr Addr = FA.getAddress();
+ Bases.push_back(Addr);
}
- Mapper->release(Bases, std::move(OnDeallocated));
+
+ Mapper->deinitialize(Bases, [this, Allocs = std::move(Allocs),
+ OnDeallocated = std::move(OnDeallocated)](
+ llvm::Error Err) mutable {
+ // TODO: How should we treat memory that we fail to deinitialize?
+ // We're currently bailing out and treating it as "burned" -- should we
+ // require that a failure to deinitialize still reset the memory so that
+ // we can reclaim it?
+ if (Err) {
+ for (auto &FA : Allocs)
+ FA.release();
+ OnDeallocated(std::move(Err));
+ return;
+ }
+
+ {
+ std::lock_guard<std::mutex> Lock(Mutex);
+
+ for (auto &FA : Allocs) {
+ ExecutorAddr Addr = FA.getAddress();
+ ExecutorAddrDiff Size = UsedMemory[Addr];
+
+ UsedMemory.erase(Addr);
+ AvailableMemory.insert(Addr, Addr + Size - 1, true);
+
+ FA.release();
+ }
+ }
+
+ OnDeallocated(Error::success());
+ });
}
} // end namespace orc
diff --git a/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/MemoryMapper.cpp b/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/MemoryMapper.cpp
index ee92e5191b50..b457c7297bed 100644
--- a/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/MemoryMapper.cpp
+++ b/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/MemoryMapper.cpp
@@ -11,6 +11,8 @@
#include "llvm/ExecutionEngine/Orc/Shared/OrcRTBridge.h"
#include "llvm/Support/WindowsError.h"
+#include <algorithm>
+
#if defined(LLVM_ON_UNIX) && !defined(__ANDROID__)
#include <fcntl.h>
#include <sys/mman.h>
@@ -60,7 +62,9 @@ char *InProcessMemoryMapper::prepare(ExecutorAddr Addr, size_t ContentSize) {
void InProcessMemoryMapper::initialize(MemoryMapper::AllocInfo &AI,
OnInitializedFunction OnInitialized) {
ExecutorAddr MinAddr(~0ULL);
+ ExecutorAddr MaxAddr(0);
+ // FIXME: Release finalize lifetime segments.
for (auto &Segment : AI.Segments) {
auto Base = AI.MappingBase + Segment.Offset;
auto Size = Segment.ContentSize + Segment.ZeroFillSize;
@@ -68,14 +72,18 @@ void InProcessMemoryMapper::initialize(MemoryMapper::AllocInfo &AI,
if (Base < MinAddr)
MinAddr = Base;
+ if (Base + Size > MaxAddr)
+ MaxAddr = Base + Size;
+
std::memset((Base + Segment.ContentSize).toPtr<void *>(), 0,
Segment.ZeroFillSize);
- if (auto EC = sys::Memory::protectMappedMemory({Base.toPtr<void *>(), Size},
- Segment.Prot)) {
+ if (auto EC = sys::Memory::protectMappedMemory(
+ {Base.toPtr<void *>(), Size},
+ toSysMemoryProtectionFlags(Segment.AG.getMemProt()))) {
return OnInitialized(errorCodeToError(EC));
}
- if (Segment.Prot & sys::Memory::MF_EXEC)
+ if ((Segment.AG.getMemProt() & MemProt::Exec) == MemProt::Exec)
sys::Memory::InvalidateInstructionCache(Base.toPtr<void *>(), Size);
}
@@ -85,6 +93,9 @@ void InProcessMemoryMapper::initialize(MemoryMapper::AllocInfo &AI,
{
std::lock_guard<std::mutex> Lock(Mutex);
+
+ // This is the maximum range whose permission have been possibly modified
+ Allocations[MinAddr].Size = MaxAddr - MinAddr;
Allocations[MinAddr].DeinitializationActions =
std::move(*DeinitializeActions);
Reservations[AI.MappingBase.toPtr<void *>()].Allocations.push_back(MinAddr);
@@ -101,13 +112,21 @@ void InProcessMemoryMapper::deinitialize(
{
std::lock_guard<std::mutex> Lock(Mutex);
- for (auto Base : Bases) {
+ for (auto Base : llvm::reverse(Bases)) {
if (Error Err = shared::runDeallocActions(
Allocations[Base].DeinitializationActions)) {
AllErr = joinErrors(std::move(AllErr), std::move(Err));
}
+ // Reset protections to read/write so the area can be reused
+ if (auto EC = sys::Memory::protectMappedMemory(
+ {Base.toPtr<void *>(), Allocations[Base].Size},
+ sys::Memory::ProtectionFlags::MF_READ |
+ sys::Memory::ProtectionFlags::MF_WRITE)) {
+ AllErr = joinErrors(std::move(AllErr), errorCodeToError(EC));
+ }
+
Allocations.erase(Base);
}
}
@@ -275,7 +294,7 @@ void SharedMemoryMapper::reserve(size_t NumBytes,
char *SharedMemoryMapper::prepare(ExecutorAddr Addr, size_t ContentSize) {
auto R = Reservations.upper_bound(Addr);
- assert(R != Reservations.begin() && "Attempt to prepare unknown range");
+ assert(R != Reservations.begin() && "Attempt to prepare unreserved range");
R--;
ExecutorAddrDiff Offset = Addr - R->first;
@@ -285,9 +304,11 @@ char *SharedMemoryMapper::prepare(ExecutorAddr Addr, size_t ContentSize) {
void SharedMemoryMapper::initialize(MemoryMapper::AllocInfo &AI,
OnInitializedFunction OnInitialized) {
- auto Reservation = Reservations.find(AI.MappingBase);
- assert(Reservation != Reservations.end() &&
- "Attempt to initialize unreserved range");
+ auto Reservation = Reservations.upper_bound(AI.MappingBase);
+ assert(Reservation != Reservations.begin() && "Attempt to initialize unreserved range");
+ Reservation--;
+
+ auto AllocationOffset = AI.MappingBase - Reservation->first;
tpctypes::SharedMemoryFinalizeRequest FR;
@@ -296,13 +317,12 @@ void SharedMemoryMapper::initialize(MemoryMapper::AllocInfo &AI,
FR.Segments.reserve(AI.Segments.size());
for (auto Segment : AI.Segments) {
- char *Base =
- static_cast<char *>(Reservation->second.LocalAddr) + Segment.Offset;
+ char *Base = static_cast<char *>(Reservation->second.LocalAddr) +
+ AllocationOffset + Segment.Offset;
std::memset(Base + Segment.ContentSize, 0, Segment.ZeroFillSize);
tpctypes::SharedMemorySegFinalizeRequest SegReq;
- SegReq.Prot = tpctypes::toWireProtectionFlags(
- static_cast<sys::Memory::ProtectionFlags>(Segment.Prot));
+ SegReq.AG = Segment.AG;
SegReq.Addr = AI.MappingBase + Segment.Offset;
SegReq.Size = Segment.ContentSize + Segment.ZeroFillSize;
@@ -321,7 +341,7 @@ void SharedMemoryMapper::initialize(MemoryMapper::AllocInfo &AI,
OnInitialized(std::move(Result));
},
- SAs.Instance, AI.MappingBase, std::move(FR));
+ SAs.Instance, Reservation->first, std::move(FR));
}
void SharedMemoryMapper::deinitialize(
@@ -392,23 +412,23 @@ void SharedMemoryMapper::release(ArrayRef<ExecutorAddr> Bases,
}
SharedMemoryMapper::~SharedMemoryMapper() {
- std::vector<ExecutorAddr> ReservationAddrs;
- if (!Reservations.empty()) {
- std::lock_guard<std::mutex> Lock(Mutex);
- {
- ReservationAddrs.reserve(Reservations.size());
- for (const auto &R : Reservations) {
- ReservationAddrs.push_back(R.first);
- }
- }
- }
+ std::lock_guard<std::mutex> Lock(Mutex);
+ for (const auto &R : Reservations) {
- std::promise<MSVCPError> P;
- auto F = P.get_future();
- release(ReservationAddrs, [&](Error Err) { P.set_value(std::move(Err)); });
- // FIXME: Release can actually fail. The error should be propagated.
- // Meanwhile, a better option is to explicitly call release().
- cantFail(F.get());
+#if defined(LLVM_ON_UNIX) && !defined(__ANDROID__)
+
+ munmap(R.second.LocalAddr, R.second.Size);
+
+#elif defined(_WIN32)
+
+ UnmapViewOfFile(R.second.LocalAddr);
+
+#else
+
+ (void)R;
+
+#endif
+ }
}
} // namespace orc
diff --git a/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/ObjectFileInterface.cpp b/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/ObjectFileInterface.cpp
index 3de15db3f1c6..0c3beba43a35 100644
--- a/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/ObjectFileInterface.cpp
+++ b/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/ObjectFileInterface.cpp
@@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//
#include "llvm/ExecutionEngine/Orc/ObjectFileInterface.h"
+#include "llvm/ExecutionEngine/Orc/COFFPlatform.h"
#include "llvm/ExecutionEngine/Orc/ELFNixPlatform.h"
#include "llvm/ExecutionEngine/Orc/MachOPlatform.h"
#include "llvm/Object/COFF.h"
@@ -14,6 +15,7 @@
#include "llvm/Object/MachO.h"
#include "llvm/Object/ObjectFile.h"
#include "llvm/Support/Debug.h"
+#include <optional>
#define DEBUG_TYPE "orc"
@@ -150,7 +152,7 @@ static Expected<MaterializationUnit::Interface>
getCOFFObjectFileSymbolInfo(ExecutionSession &ES,
const object::COFFObjectFile &Obj) {
MaterializationUnit::Interface I;
- std::vector<Optional<object::coff_aux_section_definition>> ComdatDefs(
+ std::vector<std::optional<object::coff_aux_section_definition>> ComdatDefs(
Obj.getNumberOfSections() + 1);
for (auto &Sym : Obj.symbols()) {
Expected<uint32_t> SymFlagsOrErr = Sym.getFlags();
@@ -177,7 +179,7 @@ getCOFFObjectFileSymbolInfo(ExecutionSession &ES,
if (Def->Selection != COFF::IMAGE_COMDAT_SELECT_NODUPLICATES) {
IsWeak = true;
}
- ComdatDefs[COFFSym.getSectionNumber()] = None;
+ ComdatDefs[COFFSym.getSectionNumber()] = std::nullopt;
} else {
// Skip symbols not defined in this object file.
if (*SymFlagsOrErr & object::BasicSymbolRef::SF_Undefined)
@@ -214,7 +216,16 @@ getCOFFObjectFileSymbolInfo(ExecutionSession &ES,
I.SymbolFlags[ES.intern(*Name)] = std::move(*SymFlags);
}
- // FIXME: handle init symbols
+ SymbolStringPtr InitSymbol;
+ for (auto &Sec : Obj.sections()) {
+ if (auto SecName = Sec.getName()) {
+ if (COFFPlatform::isInitializerSection(*SecName)) {
+ addInitSymbol(I, ES, Obj.getFileName());
+ break;
+ }
+ } else
+ return SecName.takeError();
+ }
return I;
}
@@ -276,5 +287,22 @@ getObjectFileInterface(ExecutionSession &ES, MemoryBufferRef ObjBuffer) {
return getGenericObjectFileSymbolInfo(ES, **Obj);
}
+bool hasInitializerSection(jitlink::LinkGraph &G) {
+ bool IsMachO = G.getTargetTriple().isOSBinFormatMachO();
+ bool IsElf = G.getTargetTriple().isOSBinFormatELF();
+ if (!IsMachO && !IsElf)
+ return false;
+
+ for (auto &Sec : G.sections()) {
+ if (IsMachO && std::apply(MachOPlatform::isInitializerSection,
+ Sec.getName().split(",")))
+ return true;
+ if (IsElf && ELFNixPlatform::isInitializerSection(Sec.getName()))
+ return true;
+ }
+
+ return false;
+}
+
} // End namespace orc.
} // End namespace llvm.
diff --git a/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/ObjectLinkingLayer.cpp b/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/ObjectLinkingLayer.cpp
index 5ddb35cbafd5..2b11c472e812 100644
--- a/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/ObjectLinkingLayer.cpp
+++ b/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/ObjectLinkingLayer.cpp
@@ -7,9 +7,9 @@
//===----------------------------------------------------------------------===//
#include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h"
-#include "llvm/ADT/Optional.h"
#include "llvm/ExecutionEngine/JITLink/EHFrameSupport.h"
#include "llvm/ExecutionEngine/Orc/DebugObjectManagerPlugin.h"
+#include "llvm/ExecutionEngine/Orc/ObjectFileInterface.h"
#include "llvm/Support/MemoryBuffer.h"
#include <string>
#include <vector>
@@ -58,35 +58,12 @@ private:
LGI.SymbolFlags[ES.intern(Sym->getName())] = Flags;
}
- if ((G.getTargetTriple().isOSBinFormatMachO() && hasMachOInitSection(G)) ||
- (G.getTargetTriple().isOSBinFormatELF() && hasELFInitSection(G)))
+ if (hasInitializerSection(G))
LGI.InitSymbol = makeInitSymbol(ES, G);
return LGI;
}
- static bool hasMachOInitSection(LinkGraph &G) {
- for (auto &Sec : G.sections())
- if (Sec.getName() == "__DATA,__obj_selrefs" ||
- Sec.getName() == "__DATA,__objc_classlist" ||
- Sec.getName() == "__TEXT,__swift5_protos" ||
- Sec.getName() == "__TEXT,__swift5_proto" ||
- Sec.getName() == "__TEXT,__swift5_types" ||
- Sec.getName() == "__DATA,__mod_init_func")
- return true;
- return false;
- }
-
- static bool hasELFInitSection(LinkGraph &G) {
- for (auto &Sec : G.sections()) {
- auto SecName = Sec.getName();
- if (SecName.consume_front(".init_array") &&
- (SecName.empty() || SecName[0] == '.'))
- return true;
- }
- return false;
- }
-
static SymbolStringPtr makeInitSymbol(ExecutionSession &ES, LinkGraph &G) {
std::string InitSymString;
raw_string_ostream(InitSymString)
@@ -218,6 +195,8 @@ public:
Flags |= JITSymbolFlags::Callable;
if (Sym->getScope() == Scope::Default)
Flags |= JITSymbolFlags::Exported;
+ if (Sym->getLinkage() == Linkage::Weak)
+ Flags |= JITSymbolFlags::Weak;
InternedResult[InternedName] =
JITEvaluatedSymbol(Sym->getAddress().getValue(), Flags);
@@ -447,9 +426,15 @@ private:
// claim, at which point we'll externalize that symbol.
cantFail(MR->defineMaterializing(std::move(NewSymbolsToClaim)));
- for (auto &KV : NameToSym)
- if (!MR->getSymbols().count(KV.first))
+ // Walk the list of symbols that we just tried to claim. Symbols that we're
+ // responsible for are marked live. Symbols that we're not responsible for
+ // are turned into external references.
+ for (auto &KV : NameToSym) {
+ if (MR->getSymbols().count(KV.first))
+ KV.second->setLive(true);
+ else
G.makeExternal(*KV.second);
+ }
return Error::success();
}
@@ -537,7 +522,8 @@ private:
for (auto *B : G.blocks()) {
auto &BI = BlockInfos[B];
for (auto &E : B->edges()) {
- if (E.getTarget().getScope() == Scope::Local) {
+ if (E.getTarget().getScope() == Scope::Local &&
+ !E.getTarget().isAbsolute()) {
auto &TgtB = E.getTarget().getBlock();
if (&TgtB != B) {
BI.Dependencies.insert(&TgtB);
@@ -694,12 +680,12 @@ Error ObjectLinkingLayer::notifyEmitted(MaterializationResponsibility &MR,
[&](ResourceKey K) { Allocs[K].push_back(std::move(FA)); });
}
-Error ObjectLinkingLayer::handleRemoveResources(ResourceKey K) {
+Error ObjectLinkingLayer::handleRemoveResources(JITDylib &JD, ResourceKey K) {
{
Error Err = Error::success();
for (auto &P : Plugins)
- Err = joinErrors(std::move(Err), P->notifyRemovingResources(K));
+ Err = joinErrors(std::move(Err), P->notifyRemovingResources(JD, K));
if (Err)
return Err;
}
@@ -719,7 +705,8 @@ Error ObjectLinkingLayer::handleRemoveResources(ResourceKey K) {
return MemMgr.deallocate(std::move(AllocsToRemove));
}
-void ObjectLinkingLayer::handleTransferResources(ResourceKey DstKey,
+void ObjectLinkingLayer::handleTransferResources(JITDylib &JD,
+ ResourceKey DstKey,
ResourceKey SrcKey) {
auto I = Allocs.find(SrcKey);
if (I != Allocs.end()) {
@@ -735,7 +722,7 @@ void ObjectLinkingLayer::handleTransferResources(ResourceKey DstKey,
}
for (auto &P : Plugins)
- P->notifyTransferringResources(DstKey, SrcKey);
+ P->notifyTransferringResources(JD, DstKey, SrcKey);
}
EHFrameRegistrationPlugin::EHFrameRegistrationPlugin(
@@ -787,7 +774,8 @@ Error EHFrameRegistrationPlugin::notifyFailed(
return Error::success();
}
-Error EHFrameRegistrationPlugin::notifyRemovingResources(ResourceKey K) {
+Error EHFrameRegistrationPlugin::notifyRemovingResources(JITDylib &JD,
+ ResourceKey K) {
std::vector<ExecutorAddrRange> RangesToRemove;
ES.runSessionLocked([&] {
@@ -811,7 +799,7 @@ Error EHFrameRegistrationPlugin::notifyRemovingResources(ResourceKey K) {
}
void EHFrameRegistrationPlugin::notifyTransferringResources(
- ResourceKey DstKey, ResourceKey SrcKey) {
+ JITDylib &JD, ResourceKey DstKey, ResourceKey SrcKey) {
auto SI = EHFrameRanges.find(SrcKey);
if (SI == EHFrameRanges.end())
return;
diff --git a/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/OrcABISupport.cpp b/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/OrcABISupport.cpp
index da8aaad08cad..48dd0df80415 100644
--- a/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/OrcABISupport.cpp
+++ b/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/OrcABISupport.cpp
@@ -1077,5 +1077,158 @@ void OrcRiscv64::writeIndirectStubsBlock(
}
}
+void OrcLoongArch64::writeResolverCode(char *ResolverWorkingMem,
+ JITTargetAddress ResolverTargetAddress,
+ JITTargetAddress ReentryFnAddr,
+ JITTargetAddress ReentryCtxAddr) {
+
+ LLVM_DEBUG({
+ dbgs() << "Writing resolver code to "
+ << formatv("{0:x16}", ResolverTargetAddress) << "\n";
+ });
+
+ const uint32_t ResolverCode[] = {
+ 0x02fde063, // 0x0: addi.d $sp, $sp, -136(0xf78)
+ 0x29c00061, // 0x4: st.d $ra, $sp, 0
+ 0x29c02064, // 0x8: st.d $a0, $sp, 8(0x8)
+ 0x29c04065, // 0xc: st.d $a1, $sp, 16(0x10)
+ 0x29c06066, // 0x10: st.d $a2, $sp, 24(0x18)
+ 0x29c08067, // 0x14: st.d $a3, $sp, 32(0x20)
+ 0x29c0a068, // 0x18: st.d $a4, $sp, 40(0x28)
+ 0x29c0c069, // 0x1c: st.d $a5, $sp, 48(0x30)
+ 0x29c0e06a, // 0x20: st.d $a6, $sp, 56(0x38)
+ 0x29c1006b, // 0x24: st.d $a7, $sp, 64(0x40)
+ 0x2bc12060, // 0x28: fst.d $fa0, $sp, 72(0x48)
+ 0x2bc14061, // 0x2c: fst.d $fa1, $sp, 80(0x50)
+ 0x2bc16062, // 0x30: fst.d $fa2, $sp, 88(0x58)
+ 0x2bc18063, // 0x34: fst.d $fa3, $sp, 96(0x60)
+ 0x2bc1a064, // 0x38: fst.d $fa4, $sp, 104(0x68)
+ 0x2bc1c065, // 0x3c: fst.d $fa5, $sp, 112(0x70)
+ 0x2bc1e066, // 0x40: fst.d $fa6, $sp, 120(0x78)
+ 0x2bc20067, // 0x44: fst.d $fa7, $sp, 128(0x80)
+ 0x1c000004, // 0x48: pcaddu12i $a0, 0
+ 0x28c1c084, // 0x4c: ld.d $a0, $a0, 112(0x70)
+ 0x001501a5, // 0x50: move $a1, $t1
+ 0x02ffd0a5, // 0x54: addi.d $a1, $a1, -12(0xff4)
+ 0x1c000006, // 0x58: pcaddu12i $a2, 0
+ 0x28c1a0c6, // 0x5c: ld.d $a2, $a2, 104(0x68)
+ 0x4c0000c1, // 0x60: jirl $ra, $a2, 0
+ 0x0015008c, // 0x64: move $t0, $a0
+ 0x2b820067, // 0x68: fld.d $fa7, $sp, 128(0x80)
+ 0x2b81e066, // 0x6c: fld.d $fa6, $sp, 120(0x78)
+ 0x2b81c065, // 0x70: fld.d $fa5, $sp, 112(0x70)
+ 0x2b81a064, // 0x74: fld.d $fa4, $sp, 104(0x68)
+ 0x2b818063, // 0x78: fld.d $fa3, $sp, 96(0x60)
+ 0x2b816062, // 0x7c: fld.d $fa2, $sp, 88(0x58)
+ 0x2b814061, // 0x80: fld.d $fa1, $sp, 80(0x50)
+ 0x2b812060, // 0x84: fld.d $fa0, $sp, 72(0x48)
+ 0x28c1006b, // 0x88: ld.d $a7, $sp, 64(0x40)
+ 0x28c0e06a, // 0x8c: ld.d $a6, $sp, 56(0x38)
+ 0x28c0c069, // 0x90: ld.d $a5, $sp, 48(0x30)
+ 0x28c0a068, // 0x94: ld.d $a4, $sp, 40(0x28)
+ 0x28c08067, // 0x98: ld.d $a3, $sp, 32(0x20)
+ 0x28c06066, // 0x9c: ld.d $a2, $sp, 24(0x18)
+ 0x28c04065, // 0xa0: ld.d $a1, $sp, 16(0x10)
+ 0x28c02064, // 0xa4: ld.d $a0, $sp, 8(0x8)
+ 0x28c00061, // 0xa8: ld.d $ra, $sp, 0
+ 0x02c22063, // 0xac: addi.d $sp, $sp, 136(0x88)
+ 0x4c000180, // 0xb0: jr $t0
+ 0x00000000, // 0xb4: padding to align at 8 bytes
+ 0x01234567, // 0xb8: Lreentry_ctx_ptr:
+ 0xdeedbeef, // 0xbc: .dword 0
+ 0x98765432, // 0xc0: Lreentry_fn_ptr:
+ 0xcafef00d, // 0xc4: .dword 0
+ };
+
+ const unsigned ReentryCtxAddrOffset = 0xb8;
+ const unsigned ReentryFnAddrOffset = 0xc0;
+
+ memcpy(ResolverWorkingMem, ResolverCode, sizeof(ResolverCode));
+ memcpy(ResolverWorkingMem + ReentryFnAddrOffset, &ReentryFnAddr,
+ sizeof(uint64_t));
+ memcpy(ResolverWorkingMem + ReentryCtxAddrOffset, &ReentryCtxAddr,
+ sizeof(uint64_t));
+}
+
+void OrcLoongArch64::writeTrampolines(
+ char *TrampolineBlockWorkingMem,
+ JITTargetAddress TrampolineBlockTargetAddress,
+ JITTargetAddress ResolverAddr, unsigned NumTrampolines) {
+
+ LLVM_DEBUG({
+ dbgs() << "Writing trampoline code to "
+ << formatv("{0:x16}", TrampolineBlockTargetAddress) << "\n";
+ });
+
+ unsigned OffsetToPtr = alignTo(NumTrampolines * TrampolineSize, 8);
+
+ memcpy(TrampolineBlockWorkingMem + OffsetToPtr, &ResolverAddr,
+ sizeof(uint64_t));
+
+ uint32_t *Trampolines =
+ reinterpret_cast<uint32_t *>(TrampolineBlockWorkingMem);
+ for (unsigned I = 0; I < NumTrampolines; ++I, OffsetToPtr -= TrampolineSize) {
+ uint32_t Hi20 = (OffsetToPtr + 0x800) & 0xfffff000;
+ uint32_t Lo12 = OffsetToPtr - Hi20;
+ Trampolines[4 * I + 0] =
+ 0x1c00000c |
+ (((Hi20 >> 12) & 0xfffff) << 5); // pcaddu12i $t0, %pc_hi20(Lptr)
+ Trampolines[4 * I + 1] =
+ 0x28c0018c | ((Lo12 & 0xfff) << 10); // ld.d $t0, $t0, %pc_lo12(Lptr)
+ Trampolines[4 * I + 2] = 0x4c00018d; // jirl $t1, $t0, 0
+ Trampolines[4 * I + 3] = 0x0; // padding
+ }
+}
+
+void OrcLoongArch64::writeIndirectStubsBlock(
+ char *StubsBlockWorkingMem, JITTargetAddress StubsBlockTargetAddress,
+ JITTargetAddress PointersBlockTargetAddress, unsigned NumStubs) {
+ // Stub format is:
+ //
+ // .section __orc_stubs
+ // stub1:
+ // pcaddu12i $t0, %pc_hi20(ptr1) ; PC-rel load of ptr1
+ // ld.d $t0, $t0, %pc_lo12(ptr1)
+ // jr $t0 ; Jump to resolver
+ // .dword 0 ; Pad to 16 bytes
+ // stub2:
+ // pcaddu12i $t0, %pc_hi20(ptr2) ; PC-rel load of ptr2
+ // ld.d $t0, $t0, %pc_lo12(ptr2)
+ // jr $t0 ; Jump to resolver
+ // .dword 0 ; Pad to 16 bytes
+ // ...
+ //
+ // .section __orc_ptrs
+ // ptr1:
+ // .dword 0x0
+ // ptr2:
+ // .dword 0x0
+ // ...
+ LLVM_DEBUG({
+ dbgs() << "Writing stubs code to "
+ << formatv("{0:x16}", StubsBlockTargetAddress) << "\n";
+ });
+ assert(stubAndPointerRangesOk<OrcLoongArch64>(
+ StubsBlockTargetAddress, PointersBlockTargetAddress, NumStubs) &&
+ "PointersBlock is out of range");
+
+ uint32_t *Stub = reinterpret_cast<uint32_t *>(StubsBlockWorkingMem);
+
+ for (unsigned I = 0; I < NumStubs; ++I) {
+ uint64_t PtrDisplacement =
+ PointersBlockTargetAddress - StubsBlockTargetAddress;
+ uint32_t Hi20 = (PtrDisplacement + 0x800) & 0xfffff000;
+ uint32_t Lo12 = PtrDisplacement - Hi20;
+ Stub[4 * I + 0] = 0x1c00000c | (((Hi20 >> 12) & 0xfffff)
+ << 5); // pcaddu12i $t0, %pc_hi20(Lptr)
+ Stub[4 * I + 1] =
+ 0x28c0018c | ((Lo12 & 0xfff) << 10); // ld.d $t0, $t0, %pc_lo12(Lptr)
+ Stub[4 * I + 2] = 0x4c000180; // jr $t0
+ Stub[4 * I + 3] = 0x0; // padding
+ PointersBlockTargetAddress += PointerSize;
+ StubsBlockTargetAddress += StubSize;
+ }
+}
+
} // End namespace orc.
} // End namespace llvm.
diff --git a/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/OrcV2CBindings.cpp b/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/OrcV2CBindings.cpp
index b7eab6b85ecf..b823197b404f 100644
--- a/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/OrcV2CBindings.cpp
+++ b/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/OrcV2CBindings.cpp
@@ -892,7 +892,10 @@ void LLVMOrcIRTransformLayerSetTransform(
assert(!TSMRef && "TSMRef was not reset to null on error");
return unwrap(Err);
}
- return std::move(*unwrap(TSMRef));
+ assert(TSMRef && "Transform succeeded, but TSMRef was set to null");
+ ThreadSafeModule Result = std::move(*unwrap(TSMRef));
+ LLVMOrcDisposeThreadSafeModule(TSMRef);
+ return std::move(Result);
});
}
@@ -1066,6 +1069,116 @@ LLVMOrcCreateRTDyldObjectLinkingLayerWithSectionMemoryManager(
*unwrap(ES), [] { return std::make_unique<SectionMemoryManager>(); }));
}
+LLVMOrcObjectLayerRef
+LLVMOrcCreateRTDyldObjectLinkingLayerWithMCJITMemoryManagerLikeCallbacks(
+ LLVMOrcExecutionSessionRef ES, void *CreateContextCtx,
+ LLVMMemoryManagerCreateContextCallback CreateContext,
+ LLVMMemoryManagerNotifyTerminatingCallback NotifyTerminating,
+ LLVMMemoryManagerAllocateCodeSectionCallback AllocateCodeSection,
+ LLVMMemoryManagerAllocateDataSectionCallback AllocateDataSection,
+ LLVMMemoryManagerFinalizeMemoryCallback FinalizeMemory,
+ LLVMMemoryManagerDestroyCallback Destroy) {
+
+ struct MCJITMemoryManagerLikeCallbacks {
+ MCJITMemoryManagerLikeCallbacks() = default;
+ MCJITMemoryManagerLikeCallbacks(
+ void *CreateContextCtx,
+ LLVMMemoryManagerCreateContextCallback CreateContext,
+ LLVMMemoryManagerNotifyTerminatingCallback NotifyTerminating,
+ LLVMMemoryManagerAllocateCodeSectionCallback AllocateCodeSection,
+ LLVMMemoryManagerAllocateDataSectionCallback AllocateDataSection,
+ LLVMMemoryManagerFinalizeMemoryCallback FinalizeMemory,
+ LLVMMemoryManagerDestroyCallback Destroy)
+ : CreateContextCtx(CreateContextCtx), CreateContext(CreateContext),
+ NotifyTerminating(NotifyTerminating),
+ AllocateCodeSection(AllocateCodeSection),
+ AllocateDataSection(AllocateDataSection),
+ FinalizeMemory(FinalizeMemory), Destroy(Destroy) {}
+
+ MCJITMemoryManagerLikeCallbacks(MCJITMemoryManagerLikeCallbacks &&Other) {
+ std::swap(CreateContextCtx, Other.CreateContextCtx);
+ std::swap(CreateContext, Other.CreateContext);
+ std::swap(NotifyTerminating, Other.NotifyTerminating);
+ std::swap(AllocateCodeSection, Other.AllocateCodeSection);
+ std::swap(AllocateDataSection, Other.AllocateDataSection);
+ std::swap(FinalizeMemory, Other.FinalizeMemory);
+ std::swap(Destroy, Other.Destroy);
+ }
+
+ ~MCJITMemoryManagerLikeCallbacks() {
+ if (NotifyTerminating)
+ NotifyTerminating(CreateContextCtx);
+ }
+
+ void *CreateContextCtx = nullptr;
+ LLVMMemoryManagerCreateContextCallback CreateContext = nullptr;
+ LLVMMemoryManagerNotifyTerminatingCallback NotifyTerminating = nullptr;
+ LLVMMemoryManagerAllocateCodeSectionCallback AllocateCodeSection = nullptr;
+ LLVMMemoryManagerAllocateDataSectionCallback AllocateDataSection = nullptr;
+ LLVMMemoryManagerFinalizeMemoryCallback FinalizeMemory = nullptr;
+ LLVMMemoryManagerDestroyCallback Destroy = nullptr;
+ };
+
+ class MCJITMemoryManagerLikeCallbacksMemMgr : public RTDyldMemoryManager {
+ public:
+ MCJITMemoryManagerLikeCallbacksMemMgr(
+ const MCJITMemoryManagerLikeCallbacks &CBs)
+ : CBs(CBs) {
+ Opaque = CBs.CreateContext(CBs.CreateContextCtx);
+ }
+ ~MCJITMemoryManagerLikeCallbacksMemMgr() override { CBs.Destroy(Opaque); }
+
+ uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment,
+ unsigned SectionID,
+ StringRef SectionName) override {
+ return CBs.AllocateCodeSection(Opaque, Size, Alignment, SectionID,
+ SectionName.str().c_str());
+ }
+
+ uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment,
+ unsigned SectionID, StringRef SectionName,
+ bool isReadOnly) override {
+ return CBs.AllocateDataSection(Opaque, Size, Alignment, SectionID,
+ SectionName.str().c_str(), isReadOnly);
+ }
+
+ bool finalizeMemory(std::string *ErrMsg) override {
+ char *ErrMsgCString = nullptr;
+ bool Result = CBs.FinalizeMemory(Opaque, &ErrMsgCString);
+ assert((Result || !ErrMsgCString) &&
+ "Did not expect an error message if FinalizeMemory succeeded");
+ if (ErrMsgCString) {
+ if (ErrMsg)
+ *ErrMsg = ErrMsgCString;
+ free(ErrMsgCString);
+ }
+ return Result;
+ }
+
+ private:
+ const MCJITMemoryManagerLikeCallbacks &CBs;
+ void *Opaque = nullptr;
+ };
+
+ assert(ES && "ES must not be null");
+ assert(CreateContext && "CreateContext must not be null");
+ assert(NotifyTerminating && "NotifyTerminating must not be null");
+ assert(AllocateCodeSection && "AllocateCodeSection must not be null");
+ assert(AllocateDataSection && "AllocateDataSection must not be null");
+ assert(FinalizeMemory && "FinalizeMemory must not be null");
+ assert(Destroy && "Destroy must not be null");
+
+ MCJITMemoryManagerLikeCallbacks CBs(
+ CreateContextCtx, CreateContext, NotifyTerminating, AllocateCodeSection,
+ AllocateDataSection, FinalizeMemory, Destroy);
+
+ return wrap(new RTDyldObjectLinkingLayer(*unwrap(ES), [CBs = std::move(CBs)] {
+ return std::make_unique<MCJITMemoryManagerLikeCallbacksMemMgr>(CBs);
+ }));
+
+ return nullptr;
+}
+
void LLVMOrcRTDyldObjectLinkingLayerRegisterJITEventListener(
LLVMOrcObjectLayerRef RTDyldObjLinkingLayer,
LLVMJITEventListenerRef Listener) {
diff --git a/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.cpp b/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.cpp
index 27044f66a55d..07b19b2e54f1 100644
--- a/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.cpp
+++ b/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.cpp
@@ -81,7 +81,7 @@ using BaseT = RTTIExtends<RTDyldObjectLinkingLayer, ObjectLayer>;
RTDyldObjectLinkingLayer::RTDyldObjectLinkingLayer(
ExecutionSession &ES, GetMemoryManagerFunction GetMemoryManager)
- : BaseT(ES), GetMemoryManager(GetMemoryManager) {
+ : BaseT(ES), GetMemoryManager(std::move(GetMemoryManager)) {
ES.registerResourceManager(*this);
}
@@ -108,6 +108,7 @@ void RTDyldObjectLinkingLayer::emit(
// filter these later.
auto InternalSymbols = std::make_shared<std::set<StringRef>>();
{
+ SymbolFlagsMap ExtraSymbolsToClaim;
for (auto &Sym : (*Obj)->symbols()) {
// Skip file symbols.
@@ -128,6 +129,33 @@ void RTDyldObjectLinkingLayer::emit(
return;
}
+ // Try to claim responsibility of weak symbols
+ // if AutoClaimObjectSymbols flag is set.
+ if (AutoClaimObjectSymbols &&
+ (*SymFlagsOrErr & object::BasicSymbolRef::SF_Weak)) {
+ auto SymName = Sym.getName();
+ if (!SymName) {
+ ES.reportError(SymName.takeError());
+ R->failMaterialization();
+ return;
+ }
+
+ // Already included in responsibility set, skip it
+ SymbolStringPtr SymbolName = ES.intern(*SymName);
+ if (R->getSymbols().count(SymbolName))
+ continue;
+
+ auto SymFlags = JITSymbolFlags::fromObjectSymbol(Sym);
+ if (!SymFlags) {
+ ES.reportError(SymFlags.takeError());
+ R->failMaterialization();
+ return;
+ }
+
+ ExtraSymbolsToClaim[SymbolName] = *SymFlags;
+ continue;
+ }
+
// Don't include symbols that aren't global.
if (!(*SymFlagsOrErr & object::BasicSymbolRef::SF_Global)) {
if (auto SymName = Sym.getName())
@@ -139,6 +167,13 @@ void RTDyldObjectLinkingLayer::emit(
}
}
}
+
+ if (!ExtraSymbolsToClaim.empty()) {
+ if (auto Err = R->defineMaterializing(ExtraSymbolsToClaim)) {
+ ES.reportError(std::move(Err));
+ R->failMaterialization();
+ }
+ }
}
auto MemMgr = GetMemoryManager();
@@ -224,6 +259,46 @@ Error RTDyldObjectLinkingLayer::onObjLoad(
if (COFFSec.Characteristics & COFF::IMAGE_SCN_LNK_COMDAT)
I->second.setFlags(I->second.getFlags() | JITSymbolFlags::Weak);
}
+
+ // Handle any aliases.
+ for (auto &Sym : COFFObj->symbols()) {
+ uint32_t SymFlags = cantFail(Sym.getFlags());
+ if (SymFlags & object::BasicSymbolRef::SF_Undefined)
+ continue;
+ auto Name = Sym.getName();
+ if (!Name)
+ return Name.takeError();
+ auto I = Resolved.find(*Name);
+
+ // Skip already-resolved symbols, and symbols that we're not responsible
+ // for.
+ if (I != Resolved.end() || !R.getSymbols().count(ES.intern(*Name)))
+ continue;
+
+ // Skip anything other than weak externals.
+ auto COFFSym = COFFObj->getCOFFSymbol(Sym);
+ if (!COFFSym.isWeakExternal())
+ continue;
+ auto *WeakExternal = COFFSym.getAux<object::coff_aux_weak_external>();
+ if (WeakExternal->Characteristics != COFF::IMAGE_WEAK_EXTERN_SEARCH_ALIAS)
+ continue;
+
+ // We found an alias. Reuse the resolution of the alias target for the
+ // alias itself.
+ Expected<object::COFFSymbolRef> TargetSymbol =
+ COFFObj->getSymbol(WeakExternal->TagIndex);
+ if (!TargetSymbol)
+ return TargetSymbol.takeError();
+ Expected<StringRef> TargetName = COFFObj->getSymbolName(*TargetSymbol);
+ if (!TargetName)
+ return TargetName.takeError();
+ auto J = Resolved.find(*TargetName);
+ if (J == Resolved.end())
+ return make_error<StringError>("Could alias target " + *TargetName +
+ " not resolved",
+ inconvertibleErrorCode());
+ Resolved[*Name] = J->second;
+ }
}
for (auto &KV : Resolved) {
@@ -235,17 +310,21 @@ Error RTDyldObjectLinkingLayer::onObjLoad(
auto InternedName = getExecutionSession().intern(KV.first);
auto Flags = KV.second.getFlags();
-
- // Override object flags and claim responsibility for symbols if
- // requested.
- if (OverrideObjectFlags || AutoClaimObjectSymbols) {
- auto I = R.getSymbols().find(InternedName);
-
- if (OverrideObjectFlags && I != R.getSymbols().end())
+ auto I = R.getSymbols().find(InternedName);
+ if (I != R.getSymbols().end()) {
+ // Override object flags and claim responsibility for symbols if
+ // requested.
+ if (OverrideObjectFlags)
Flags = I->second;
- else if (AutoClaimObjectSymbols && I == R.getSymbols().end())
- ExtraSymbolsToClaim[InternedName] = Flags;
- }
+ else {
+ // RuntimeDyld/MCJIT's weak tracking isn't compatible with ORC's. Even
+ // if we're not overriding flags in general we should set the weak flag
+ // according to the MaterializationResponsibility object symbol table.
+ if (I->second.isWeak())
+ Flags |= JITSymbolFlags::Weak;
+ }
+ } else if (AutoClaimObjectSymbols)
+ ExtraSymbolsToClaim[InternedName] = Flags;
Symbols[InternedName] = JITEvaluatedSymbol(KV.second.getAddress(), Flags);
}
@@ -311,7 +390,8 @@ void RTDyldObjectLinkingLayer::onObjEmit(
}
}
-Error RTDyldObjectLinkingLayer::handleRemoveResources(ResourceKey K) {
+Error RTDyldObjectLinkingLayer::handleRemoveResources(JITDylib &JD,
+ ResourceKey K) {
std::vector<MemoryManagerUP> MemMgrsToRemove;
@@ -335,7 +415,8 @@ Error RTDyldObjectLinkingLayer::handleRemoveResources(ResourceKey K) {
return Error::success();
}
-void RTDyldObjectLinkingLayer::handleTransferResources(ResourceKey DstKey,
+void RTDyldObjectLinkingLayer::handleTransferResources(JITDylib &JD,
+ ResourceKey DstKey,
ResourceKey SrcKey) {
auto I = MemMgrs.find(SrcKey);
if (I != MemMgrs.end()) {
diff --git a/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/Shared/OrcError.cpp b/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/Shared/OrcError.cpp
index 2cc2bddeb21a..ec53338570db 100644
--- a/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/Shared/OrcError.cpp
+++ b/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/Shared/OrcError.cpp
@@ -82,7 +82,7 @@ char DuplicateDefinition::ID = 0;
char JITSymbolNotFound::ID = 0;
std::error_code orcError(OrcErrorCode ErrCode) {
- typedef std::underlying_type<OrcErrorCode>::type UT;
+ typedef std::underlying_type_t<OrcErrorCode> UT;
return std::error_code(static_cast<UT>(ErrCode), getOrcErrCat());
}
@@ -105,7 +105,7 @@ JITSymbolNotFound::JITSymbolNotFound(std::string SymbolName)
: SymbolName(std::move(SymbolName)) {}
std::error_code JITSymbolNotFound::convertToErrorCode() const {
- typedef std::underlying_type<OrcErrorCode>::type UT;
+ typedef std::underlying_type_t<OrcErrorCode> UT;
return std::error_code(static_cast<UT>(OrcErrorCode::JITSymbolNotFound),
getOrcErrCat());
}
diff --git a/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/Shared/OrcRTBridge.cpp b/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/Shared/OrcRTBridge.cpp
index dfdd846c46a7..86e31c52100e 100644
--- a/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/Shared/OrcRTBridge.cpp
+++ b/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/Shared/OrcRTBridge.cpp
@@ -56,6 +56,10 @@ const char *DeregisterEHFrameSectionWrapperName =
"__llvm_orc_bootstrap_deregister_ehframe_section_wrapper";
const char *RunAsMainWrapperName = "__llvm_orc_bootstrap_run_as_main_wrapper";
+const char *RunAsVoidFunctionWrapperName =
+ "__llvm_orc_bootstrap_run_as_void_function_wrapper";
+const char *RunAsIntFunctionWrapperName =
+ "__llvm_orc_bootstrap_run_as_int_function_wrapper";
} // end namespace rt
} // end namespace orc
diff --git a/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/Shared/SimpleRemoteEPCUtils.cpp b/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/Shared/SimpleRemoteEPCUtils.cpp
index 2bb204e688fc..921ac47d421d 100644
--- a/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/Shared/SimpleRemoteEPCUtils.cpp
+++ b/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/Shared/SimpleRemoteEPCUtils.cpp
@@ -137,7 +137,7 @@ static Error makeUnexpectedEOFError() {
Error FDSimpleRemoteEPCTransport::readBytes(char *Dst, size_t Size,
bool *IsEOF) {
- assert(Dst && "Attempt to read into null.");
+ assert((Size == 0 || Dst) && "Attempt to read into null.");
ssize_t Completed = 0;
while (Completed < static_cast<ssize_t>(Size)) {
ssize_t Read = ::read(InFD, Dst + Completed, Size - Completed);
@@ -167,7 +167,7 @@ Error FDSimpleRemoteEPCTransport::readBytes(char *Dst, size_t Size,
}
int FDSimpleRemoteEPCTransport::writeBytes(const char *Src, size_t Size) {
- assert(Src && "Attempt to append from null.");
+ assert((Size == 0 || Src) && "Attempt to append from null.");
ssize_t Completed = 0;
while (Completed < static_cast<ssize_t>(Size)) {
ssize_t Written = ::write(OutFD, Src + Completed, Size - Completed);
diff --git a/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/SimpleRemoteEPC.cpp b/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/SimpleRemoteEPC.cpp
index 47364a92a451..1bd10c9c6c0e 100644
--- a/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/SimpleRemoteEPC.cpp
+++ b/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/SimpleRemoteEPC.cpp
@@ -38,7 +38,7 @@ SimpleRemoteEPC::lookupSymbols(ArrayRef<LookupRequest> Request) {
Result.push_back({});
Result.back().reserve(R->size());
for (auto Addr : *R)
- Result.back().push_back(Addr.getValue());
+ Result.back().push_back(Addr);
} else
return R.takeError();
}
@@ -54,6 +54,23 @@ Expected<int32_t> SimpleRemoteEPC::runAsMain(ExecutorAddr MainFnAddr,
return Result;
}
+Expected<int32_t> SimpleRemoteEPC::runAsVoidFunction(ExecutorAddr VoidFnAddr) {
+ int32_t Result = 0;
+ if (auto Err = callSPSWrapper<rt::SPSRunAsVoidFunctionSignature>(
+ RunAsVoidFunctionAddr, Result, ExecutorAddr(VoidFnAddr)))
+ return std::move(Err);
+ return Result;
+}
+
+Expected<int32_t> SimpleRemoteEPC::runAsIntFunction(ExecutorAddr IntFnAddr,
+ int Arg) {
+ int32_t Result = 0;
+ if (auto Err = callSPSWrapper<rt::SPSRunAsIntFunctionSignature>(
+ RunAsIntFunctionAddr, Result, ExecutorAddr(IntFnAddr), Arg))
+ return std::move(Err);
+ return Result;
+}
+
void SimpleRemoteEPC::callWrapperAsync(ExecutorAddr WrapperFnAddr,
IncomingWFRHandler OnComplete,
ArrayRef<char> ArgBuffer) {
@@ -312,7 +329,9 @@ Error SimpleRemoteEPC::setup(Setup S) {
if (auto Err = getBootstrapSymbols(
{{JDI.JITDispatchContext, ExecutorSessionObjectName},
{JDI.JITDispatchFunction, DispatchFnName},
- {RunAsMainAddr, rt::RunAsMainWrapperName}}))
+ {RunAsMainAddr, rt::RunAsMainWrapperName},
+ {RunAsVoidFunctionAddr, rt::RunAsVoidFunctionWrapperName},
+ {RunAsIntFunctionAddr, rt::RunAsIntFunctionWrapperName}}))
return Err;
if (auto DM =
diff --git a/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/SpeculateAnalyses.cpp b/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/SpeculateAnalyses.cpp
index c2fa4466eab6..0388725dfb63 100644
--- a/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/SpeculateAnalyses.cpp
+++ b/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/SpeculateAnalyses.cpp
@@ -67,7 +67,7 @@ void SpeculateQuery::findCalles(const BasicBlock *BB,
}
bool SpeculateQuery::isStraightLine(const Function &F) {
- return llvm::all_of(F.getBasicBlockList(), [](const BasicBlock &BB) {
+ return llvm::all_of(F, [](const BasicBlock &BB) {
return BB.getSingleSuccessor() != nullptr;
});
}
@@ -97,7 +97,7 @@ BlockFreqQuery::ResultTy BlockFreqQuery::operator()(Function &F) {
auto IBBs = findBBwithCalls(F);
if (IBBs.empty())
- return None;
+ return std::nullopt;
auto &BFI = FAM.getResult<BlockFrequencyAnalysis>(F);
@@ -136,7 +136,7 @@ SequenceBBQuery::BlockListTy
SequenceBBQuery::rearrangeBB(const Function &F, const BlockListTy &BBList) {
BlockListTy RearrangedBBSet;
- for (auto &Block : F.getBasicBlockList())
+ for (auto &Block : F)
if (llvm::is_contained(BBList, &Block))
RearrangedBBSet.push_back(&Block);
@@ -288,14 +288,14 @@ SpeculateQuery::ResultTy SequenceBBQuery::operator()(Function &F) {
CallerBlocks = findBBwithCalls(F);
if (CallerBlocks.empty())
- return None;
+ return std::nullopt;
if (isStraightLine(F))
SequencedBlocks = rearrangeBB(F, CallerBlocks);
else
SequencedBlocks = queryCFG(F, CallerBlocks);
- for (auto BB : SequencedBlocks)
+ for (const auto *BB : SequencedBlocks)
findCalles(BB, Calles);
CallerAndCalles.insert({F.getName(), std::move(Calles)});
diff --git a/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/TargetProcess/ExecutorSharedMemoryMapperService.cpp b/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/TargetProcess/ExecutorSharedMemoryMapperService.cpp
index caa191cea899..147f915f61d6 100644
--- a/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/TargetProcess/ExecutorSharedMemoryMapperService.cpp
+++ b/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/TargetProcess/ExecutorSharedMemoryMapperService.cpp
@@ -21,35 +21,30 @@
#include <unistd.h>
#endif
+namespace llvm {
+namespace orc {
+namespace rt_bootstrap {
+
#if defined(_WIN32)
-static DWORD getWindowsProtectionFlags(unsigned Flags) {
- switch (Flags & llvm::sys::Memory::MF_RWE_MASK) {
- case llvm::sys::Memory::MF_READ:
+static DWORD getWindowsProtectionFlags(MemProt MP) {
+ if (MP == MemProt::Read)
return PAGE_READONLY;
- case llvm::sys::Memory::MF_WRITE:
+ if (MP == MemProt::Write ||
+ MP == (MemProt::Write | MemProt::Read)) {
// Note: PAGE_WRITE is not supported by VirtualProtect
return PAGE_READWRITE;
- case llvm::sys::Memory::MF_READ | llvm::sys::Memory::MF_WRITE:
- return PAGE_READWRITE;
- case llvm::sys::Memory::MF_READ | llvm::sys::Memory::MF_EXEC:
+ }
+ if (MP == (MemProt::Read | MemProt::Exec))
return PAGE_EXECUTE_READ;
- case llvm::sys::Memory::MF_READ | llvm::sys::Memory::MF_WRITE |
- llvm::sys::Memory::MF_EXEC:
+ if (MP == (MemProt::Read | MemProt::Write | MemProt::Exec))
return PAGE_EXECUTE_READWRITE;
- case llvm::sys::Memory::MF_EXEC:
+ if (MP == MemProt::Exec)
return PAGE_EXECUTE;
- default:
- llvm_unreachable("Illegal memory protection flag specified!");
- }
- // Provide a default return value as required by some compilers.
+
return PAGE_NOACCESS;
}
#endif
-namespace llvm {
-namespace orc {
-namespace rt_bootstrap {
-
Expected<std::pair<ExecutorAddr, std::string>>
ExecutorSharedMemoryMapperService::reserve(uint64_t Size) {
#if (defined(LLVM_ON_UNIX) && !defined(__ANDROID__)) || defined(_WIN32)
@@ -137,11 +132,11 @@ Expected<ExecutorAddr> ExecutorSharedMemoryMapperService::initialize(
#if defined(LLVM_ON_UNIX)
int NativeProt = 0;
- if (Segment.Prot & tpctypes::WPF_Read)
+ if ((Segment.AG.getMemProt() & MemProt::Read) == MemProt::Read)
NativeProt |= PROT_READ;
- if (Segment.Prot & tpctypes::WPF_Write)
+ if ((Segment.AG.getMemProt() & MemProt::Write) == MemProt::Write)
NativeProt |= PROT_WRITE;
- if (Segment.Prot & tpctypes::WPF_Exec)
+ if ((Segment.AG.getMemProt() & MemProt::Exec) == MemProt::Exec)
NativeProt |= PROT_EXEC;
if (mprotect(Segment.Addr.toPtr<void *>(), Segment.Size, NativeProt))
@@ -150,7 +145,7 @@ Expected<ExecutorAddr> ExecutorSharedMemoryMapperService::initialize(
#elif defined(_WIN32)
DWORD NativeProt =
- getWindowsProtectionFlags(fromWireProtectionFlags(Segment.Prot));
+ getWindowsProtectionFlags(Segment.AG.getMemProt());
if (!VirtualProtect(Segment.Addr.toPtr<void *>(), Segment.Size, NativeProt,
&NativeProt))
@@ -158,7 +153,7 @@ Expected<ExecutorAddr> ExecutorSharedMemoryMapperService::initialize(
#endif
- if (Segment.Prot & tpctypes::WPF_Exec)
+ if ((Segment.AG.getMemProt() & MemProt::Exec) == MemProt::Exec)
sys::Memory::InvalidateInstructionCache(Segment.Addr.toPtr<void *>(),
Segment.Size);
}
@@ -192,12 +187,23 @@ Error ExecutorSharedMemoryMapperService::deinitialize(
{
std::lock_guard<std::mutex> Lock(Mutex);
- for (auto Base : Bases) {
+ for (auto Base : llvm::reverse(Bases)) {
if (Error Err = shared::runDeallocActions(
Allocations[Base].DeinitializationActions)) {
AllErr = joinErrors(std::move(AllErr), std::move(Err));
}
+ // Remove the allocation from the allocation list of its reservation
+ for (auto &Reservation : Reservations) {
+ auto AllocationIt =
+ std::find(Reservation.second.Allocations.begin(),
+ Reservation.second.Allocations.end(), Base);
+ if (AllocationIt != Reservation.second.Allocations.end()) {
+ Reservation.second.Allocations.erase(AllocationIt);
+ break;
+ }
+ }
+
Allocations.erase(Base);
}
}
@@ -264,19 +270,15 @@ Error ExecutorSharedMemoryMapperService::release(
}
Error ExecutorSharedMemoryMapperService::shutdown() {
+ if (Reservations.empty())
+ return Error::success();
+
std::vector<ExecutorAddr> ReservationAddrs;
- if (!Reservations.empty()) {
- std::lock_guard<std::mutex> Lock(Mutex);
- {
- ReservationAddrs.reserve(Reservations.size());
- for (const auto &R : Reservations) {
- ReservationAddrs.push_back(ExecutorAddr::fromPtr(R.getFirst()));
- }
- }
- }
- return release(ReservationAddrs);
+ ReservationAddrs.reserve(Reservations.size());
+ for (const auto &R : Reservations)
+ ReservationAddrs.push_back(ExecutorAddr::fromPtr(R.getFirst()));
- return Error::success();
+ return release(std::move(ReservationAddrs));
}
void ExecutorSharedMemoryMapperService::addBootstrapSymbols(
diff --git a/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/TargetProcess/OrcRTBootstrap.cpp b/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/TargetProcess/OrcRTBootstrap.cpp
index 909d47deef59..b38877955282 100644
--- a/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/TargetProcess/OrcRTBootstrap.cpp
+++ b/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/TargetProcess/OrcRTBootstrap.cpp
@@ -56,6 +56,27 @@ runAsMainWrapper(const char *ArgData, size_t ArgSize) {
.release();
}
+static llvm::orc::shared::CWrapperFunctionResult
+runAsVoidFunctionWrapper(const char *ArgData, size_t ArgSize) {
+ return WrapperFunction<rt::SPSRunAsVoidFunctionSignature>::handle(
+ ArgData, ArgSize,
+ [](ExecutorAddr MainAddr) -> int32_t {
+ return runAsVoidFunction(MainAddr.toPtr<int32_t (*)(void)>());
+ })
+ .release();
+}
+
+static llvm::orc::shared::CWrapperFunctionResult
+runAsIntFunctionWrapper(const char *ArgData, size_t ArgSize) {
+ return WrapperFunction<rt::SPSRunAsIntFunctionSignature>::handle(
+ ArgData, ArgSize,
+ [](ExecutorAddr MainAddr, int32_t Arg) -> int32_t {
+ return runAsIntFunction(MainAddr.toPtr<int32_t (*)(int32_t)>(),
+ Arg);
+ })
+ .release();
+}
+
void addTo(StringMap<ExecutorAddr> &M) {
M[rt::MemoryWriteUInt8sWrapperName] = ExecutorAddr::fromPtr(
&writeUIntsWrapper<tpctypes::UInt8Write,
@@ -76,6 +97,10 @@ void addTo(StringMap<ExecutorAddr> &M) {
M[rt::DeregisterEHFrameSectionWrapperName] =
ExecutorAddr::fromPtr(&llvm_orc_deregisterEHFrameSectionWrapper);
M[rt::RunAsMainWrapperName] = ExecutorAddr::fromPtr(&runAsMainWrapper);
+ M[rt::RunAsVoidFunctionWrapperName] =
+ ExecutorAddr::fromPtr(&runAsVoidFunctionWrapper);
+ M[rt::RunAsIntFunctionWrapperName] =
+ ExecutorAddr::fromPtr(&runAsIntFunctionWrapper);
}
} // end namespace rt_bootstrap
diff --git a/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/TargetProcess/SimpleExecutorDylibManager.cpp b/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/TargetProcess/SimpleExecutorDylibManager.cpp
index 3c9dd21b0832..cb11b68e2719 100644
--- a/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/TargetProcess/SimpleExecutorDylibManager.cpp
+++ b/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/TargetProcess/SimpleExecutorDylibManager.cpp
@@ -35,24 +35,18 @@ SimpleExecutorDylibManager::open(const std::string &Path, uint64_t Mode) {
return make_error<StringError>(std::move(ErrMsg), inconvertibleErrorCode());
std::lock_guard<std::mutex> Lock(M);
- Dylibs[NextId] = std::move(DL);
- return NextId++;
+ auto H = ExecutorAddr::fromPtr(DL.getOSSpecificHandle());
+ Dylibs.insert(DL.getOSSpecificHandle());
+ return H;
}
Expected<std::vector<ExecutorAddr>>
SimpleExecutorDylibManager::lookup(tpctypes::DylibHandle H,
const RemoteSymbolLookupSet &L) {
std::vector<ExecutorAddr> Result;
-
- std::lock_guard<std::mutex> Lock(M);
- auto I = Dylibs.find(H);
- if (I == Dylibs.end())
- return make_error<StringError>("No dylib for handle " + formatv("{0:x}", H),
- inconvertibleErrorCode());
- auto &DL = I->second;
+ auto DL = sys::DynamicLibrary(H.toPtr<void *>());
for (const auto &E : L) {
-
if (E.Name.empty()) {
if (E.Required)
return make_error<StringError>("Required address for empty symbol \"\"",
@@ -85,10 +79,10 @@ SimpleExecutorDylibManager::lookup(tpctypes::DylibHandle H,
Error SimpleExecutorDylibManager::shutdown() {
- DylibsMap DM;
+ DylibSet DS;
{
std::lock_guard<std::mutex> Lock(M);
- std::swap(DM, Dylibs);
+ std::swap(DS, Dylibs);
}
// There is no removal of dylibs at the moment, so nothing to do here.
diff --git a/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/TargetProcess/SimpleExecutorMemoryManager.cpp b/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/TargetProcess/SimpleExecutorMemoryManager.cpp
index c848dd65fa7e..ce94bf1e039a 100644
--- a/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/TargetProcess/SimpleExecutorMemoryManager.cpp
+++ b/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/TargetProcess/SimpleExecutorMemoryManager.cpp
@@ -132,9 +132,9 @@ Error SimpleExecutorMemoryManager::finalize(tpctypes::FinalizeRequest &FR) {
assert(Seg.Size <= std::numeric_limits<size_t>::max());
if (auto EC = sys::Memory::protectMappedMemory(
{Mem, static_cast<size_t>(Seg.Size)},
- tpctypes::fromWireProtectionFlags(Seg.Prot)))
+ toSysMemoryProtectionFlags(Seg.AG.getMemProt())))
return BailOut(errorCodeToError(EC));
- if (Seg.Prot & tpctypes::WPF_Exec)
+ if ((Seg.AG.getMemProt() & MemProt::Exec) == MemProt::Exec)
sys::Memory::InvalidateInstructionCache(Mem, Seg.Size);
}
diff --git a/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/TargetProcess/TargetExecutionUtils.cpp b/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/TargetProcess/TargetExecutionUtils.cpp
index a8e6c049cf4b..7546b3f8d0fa 100644
--- a/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/TargetProcess/TargetExecutionUtils.cpp
+++ b/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/TargetProcess/TargetExecutionUtils.cpp
@@ -14,7 +14,7 @@ namespace llvm {
namespace orc {
int runAsMain(int (*Main)(int, char *[]), ArrayRef<std::string> Args,
- Optional<StringRef> ProgramName) {
+ std::optional<StringRef> ProgramName) {
std::vector<std::unique_ptr<char[]>> ArgVStorage;
std::vector<char *> ArgV;
@@ -39,5 +39,9 @@ int runAsMain(int (*Main)(int, char *[]), ArrayRef<std::string> Args,
return Main(Args.size() + !!ProgramName, ArgV.data());
}
+int runAsVoidFunction(int (*Func)(void)) { return Func(); }
+
+int runAsIntFunction(int (*Func)(int), int Arg) { return Func(Arg); }
+
} // End namespace orc.
} // End namespace llvm.