diff --git a/llvm/include/llvm-c/LLJIT.h b/llvm/include/llvm-c/LLJIT.h index 28eb8bbff96b..976fda22bc48 100644 --- a/llvm/include/llvm-c/LLJIT.h +++ b/llvm/include/llvm-c/LLJIT.h @@ -208,6 +208,11 @@ LLVMErrorRef LLVMOrcLLJITLookup(LLVMOrcLLJITRef J, LLVMOrcJITTargetAddress *Result, const char *Name); +/** + * Returns a non-owning reference to the LLJIT instance's object linking layer. + */ +LLVMOrcObjectLayerRef LLVMOrcLLJITGetObjLinkingLayer(LLVMOrcLLJITRef J); + LLVM_C_EXTERN_C_END #endif /* LLVM_C_LLJIT_H */ diff --git a/llvm/include/llvm-c/Orc.h b/llvm/include/llvm-c/Orc.h index 84dfec4c1c32..ac20986233f1 100644 --- a/llvm/include/llvm-c/Orc.h +++ b/llvm/include/llvm-c/Orc.h @@ -43,7 +43,9 @@ typedef uint64_t LLVMOrcJITTargetAddress; */ typedef enum { LLVMJITSymbolGenericFlagsExported = 1U << 0, - LLVMJITSymbolGenericFlagsWeak = 1U << 1 + LLVMJITSymbolGenericFlagsWeak = 1U << 1, + LLVMJITSymbolGenericFlagsCallable = 1U << 2, + LLVMJITSymbolGenericFlagsMaterializationSideEffectsOnly = 1U << 3 } LLVMJITSymbolGenericFlags; /** @@ -88,6 +90,20 @@ typedef struct LLVMOrcOpaqueSymbolStringPool *LLVMOrcSymbolStringPoolRef; typedef struct LLVMOrcOpaqueSymbolStringPoolEntry *LLVMOrcSymbolStringPoolEntryRef; +/** + * Represents a pair of a symbol name and LLVMJITSymbolFlags. + */ +typedef struct { + LLVMOrcSymbolStringPoolEntryRef Name; + LLVMJITSymbolFlags Flags; +} LLVMOrcCSymbolFlagsMapPair; + +/** + * Represents a list of (SymbolStringPtr, JITSymbolFlags) pairs that can be used + * to construct a SymbolFlagsMap. + */ +typedef LLVMOrcCSymbolFlagsMapPair *LLVMOrcCSymbolFlagsMapPairs; + /** * Represents a pair of a symbol name and an evaluated symbol. */ @@ -155,15 +171,54 @@ typedef struct { typedef LLVMOrcCLookupSetElement *LLVMOrcCLookupSet; /** - * A reference to an orc::MaterializationUnit. + * A reference to a uniquely owned orc::MaterializationUnit instance. */ typedef struct LLVMOrcOpaqueMaterializationUnit *LLVMOrcMaterializationUnitRef; +/** + * A reference to a uniquely owned orc::MaterializationResponsibility instance. + * + * Ownership must be passed to a lower-level layer in a JIT stack. + */ +typedef struct LLVMOrcOpaqueMaterializationResponsibility + *LLVMOrcMaterializationResponsibilityRef; + /** * A reference to an orc::JITDylib instance. */ typedef struct LLVMOrcOpaqueJITDylib *LLVMOrcJITDylibRef; +/** + * A MaterializationUnit materialize callback. + * + * Ownership of the Ctx and MR arguments passes to the callback which must + * adhere to the LLVMOrcMaterializationResponsibilityRef contract (see comment + * for that type). + * + * If this callback is called then the LLVMOrcMaterializationUnitDestroy + * callback will NOT be called. + */ +typedef void (*LLVMOrcMaterializationUnitMaterializeFunction)( + void *Ctx, LLVMOrcMaterializationResponsibilityRef MR); + +/** + * A MaterializationUnit discard callback. + * + * Ownership of JD and Symbol remain with the caller: These arguments should + * not be disposed of or released. + */ +typedef void (*LLVMOrcMaterializationUnitDiscardFunction)( + void *Ctx, LLVMOrcJITDylibRef JD, LLVMOrcSymbolStringPoolEntryRef Symbol); + +/** + * A MaterializationUnit destruction callback. + * + * If a custom MaterializationUnit is destroyed before its Materialize + * function is called then this function will be called to provide an + * opportunity for the underlying program representation to be destroyed. + */ +typedef void (*LLVMOrcMaterializationUnitDestroyFunction)(void *Ctx); + /** * A reference to an orc::ResourceTracker instance. */ @@ -255,6 +310,11 @@ typedef struct LLVMOrcOpaqueJITTargetMachineBuilder */ typedef struct LLVMOrcOpaqueObjectLayer *LLVMOrcObjectLayerRef; +/** + * A reference to an orc::ObjectLinkingLayer instance. + */ +typedef struct LLVMOrcOpaqueObjectLinkingLayer *LLVMOrcObjectLinkingLayerRef; + /** * Attach a custom error reporter function to the ExecutionSession. * @@ -346,9 +406,66 @@ void LLVMOrcDisposeDefinitionGenerator(LLVMOrcDefinitionGeneratorRef DG); */ void LLVMOrcDisposeMaterializationUnit(LLVMOrcMaterializationUnitRef MU); +/** + * Create a custom MaterializationUnit. + * + * Name is a name for this MaterializationUnit to be used for identification + * and logging purposes (e.g. if this MaterializationUnit produces an + * object buffer then the name of that buffer will be derived from this name). + * + * The Syms list contains the names and linkages of the symbols provided by this + * unit. This function takes ownership of the elements of the Syms array. The + * Name fields of the array elements are taken to have been retained for this + * function. The client should *not* release the elements of the array, but is + * still responsible for destroyingthe array itself. + * + * The InitSym argument indicates whether or not this MaterializationUnit + * contains static initializers. If three are no static initializers (the common + * case) then this argument should be null. If there are static initializers + * then InitSym should be set to a unique name that also appears in the Syms + * list with the LLVMJITSymbolGenericFlagsMaterializationSideEffectsOnly flag + * set. This function takes ownership of the InitSym, which should have been + * retained twice on behalf of this function: once for the Syms entry and once + * for InitSym. If clients wish to use the InitSym value after this function + * returns they must retain it once more for themselves. + * + * If any of the symbols in the Syms list is looked up then the Materialize + * function will be called. + * + * If any of the symbols in the Syms list is overridden then the Discard + * function will be called. + * + * The caller owns the underling MaterializationUnit and is responsible for + * either passing it to a JITDylib (via LLVMOrcJITDylibDefine) or disposing + * of it by calling LLVMOrcDisposeMaterializationUnit. + */ +LLVMOrcMaterializationUnitRef LLVMOrcCreateCustomMaterializationUnit( + const char *Name, void *Ctx, LLVMOrcCSymbolFlagsMapPairs Syms, + size_t NumSyms, LLVMOrcSymbolStringPoolEntryRef InitSym, + LLVMOrcMaterializationUnitMaterializeFunction Materialize, + LLVMOrcMaterializationUnitDiscardFunction Discard, + LLVMOrcMaterializationUnitDestroyFunction Destroy); + /** * Create a MaterializationUnit to define the given symbols as pointing to * the corresponding raw addresses. + * + * This function takes ownership of the elements of the Syms array. The Name + * fields of the array elements are taken to have been retained for this + * function. This allows the following pattern... + * + * size_t NumPairs; + * LLVMOrcCSymbolMapPairs Sym; + * -- Build Syms array -- + * LLVMOrcMaterializationUnitRef MU = + * LLVMOrcAbsoluteSymbols(Syms, NumPairs); + * + * ... without requiring cleanup of the elements of the Sym array afterwards. + * + * The client is still responsible for deleting the Sym array itself. + * + * If a client wishes to reuse elements of the Sym array after this call they + * must explicitly retain each of the elements for themselves. */ LLVMOrcMaterializationUnitRef LLVMOrcAbsoluteSymbols(LLVMOrcCSymbolMapPairs Syms, size_t NumPairs); @@ -529,6 +646,16 @@ LLVMOrcJITTargetMachineBuilderCreateFromTargetMachine(LLVMTargetMachineRef TM); void LLVMOrcDisposeJITTargetMachineBuilder( LLVMOrcJITTargetMachineBuilderRef JTMB); +/** + * Emit an object buffer to an ObjectLayer. + * + * Ownership of the responsibility object and object buffer pass to this + * function. The client is not responsible for cleanup. + */ +void LLVMOrcObjectLayerEmit(LLVMOrcObjectLayerRef ObjLayer, + LLVMOrcMaterializationResponsibilityRef R, + LLVMMemoryBufferRef ObjBuffer); + /** * Dispose of an ObjectLayer. */ diff --git a/llvm/lib/ExecutionEngine/Orc/OrcV2CBindings.cpp b/llvm/lib/ExecutionEngine/Orc/OrcV2CBindings.cpp index 834d4cc8f514..796daf58d9bb 100644 --- a/llvm/lib/ExecutionEngine/Orc/OrcV2CBindings.cpp +++ b/llvm/lib/ExecutionEngine/Orc/OrcV2CBindings.cpp @@ -29,13 +29,22 @@ public: using PoolEntry = SymbolStringPtr::PoolEntry; using PoolEntryPtr = SymbolStringPtr::PoolEntryPtr; - static PoolEntryPtr releaseSymbolStringPtr(SymbolStringPtr S) { + // Move from SymbolStringPtr to PoolEntryPtr (no change in ref count). + static PoolEntryPtr moveFromSymbolStringPtr(SymbolStringPtr S) { PoolEntryPtr Result = nullptr; std::swap(Result, S.S); return Result; } - static SymbolStringPtr retainSymbolStringPtr(PoolEntryPtr P) { + // Move from a PoolEntryPtr to a SymbolStringPtr (no change in ref count). + static SymbolStringPtr moveToSymbolStringPtr(PoolEntryPtr P) { + SymbolStringPtr S; + S.S = P; + return S; + } + + // Copy a pool entry to a SymbolStringPtr (increments ref count). + static SymbolStringPtr copyToSymbolStringPtr(PoolEntryPtr P) { return SymbolStringPtr(P); } @@ -71,6 +80,8 @@ DEFINE_SIMPLE_CONVERSION_FUNCTIONS(OrcV2CAPIHelper::PoolEntry, LLVMOrcSymbolStringPoolEntryRef) DEFINE_SIMPLE_CONVERSION_FUNCTIONS(MaterializationUnit, LLVMOrcMaterializationUnitRef) +DEFINE_SIMPLE_CONVERSION_FUNCTIONS(MaterializationResponsibility, + LLVMOrcMaterializationResponsibilityRef) DEFINE_SIMPLE_CONVERSION_FUNCTIONS(JITDylib, LLVMOrcJITDylibRef) DEFINE_SIMPLE_CONVERSION_FUNCTIONS(ResourceTracker, LLVMOrcResourceTrackerRef) DEFINE_SIMPLE_CONVERSION_FUNCTIONS(DefinitionGenerator, @@ -163,6 +174,66 @@ private: } // end namespace orc } // end namespace llvm +namespace { + +class OrcCAPIMaterializationUnit : public llvm::orc::MaterializationUnit { +public: + OrcCAPIMaterializationUnit( + std::string Name, SymbolFlagsMap InitialSymbolFlags, + SymbolStringPtr InitSymbol, void *Ctx, + LLVMOrcMaterializationUnitMaterializeFunction Materialize, + LLVMOrcMaterializationUnitDiscardFunction Discard, + LLVMOrcMaterializationUnitDestroyFunction Destroy) + : llvm::orc::MaterializationUnit(std::move(InitialSymbolFlags), + std::move(InitSymbol)), + Name(std::move(Name)), Ctx(Ctx), Materialize(Materialize), + Discard(Discard), Destroy(Destroy) {} + + ~OrcCAPIMaterializationUnit() { + if (Ctx) + Destroy(Ctx); + } + + StringRef getName() const override { return Name; } + + void materialize(std::unique_ptr R) override { + void *Tmp = Ctx; + Ctx = nullptr; + Materialize(Tmp, wrap(R.release())); + } + +private: + void discard(const JITDylib &JD, const SymbolStringPtr &Name) override { + Discard(Ctx, wrap(&JD), wrap(OrcV2CAPIHelper::getRawPoolEntryPtr(Name))); + } + + std::string Name; + void *Ctx = nullptr; + LLVMOrcMaterializationUnitMaterializeFunction Materialize = nullptr; + LLVMOrcMaterializationUnitDiscardFunction Discard = nullptr; + LLVMOrcMaterializationUnitDestroyFunction Destroy = nullptr; +}; + +static JITSymbolFlags toJITSymbolFlags(LLVMJITSymbolFlags F) { + + JITSymbolFlags JSF; + + if (F.GenericFlags & LLVMJITSymbolGenericFlagsExported) + JSF |= JITSymbolFlags::Exported; + if (F.GenericFlags & LLVMJITSymbolGenericFlagsWeak) + JSF |= JITSymbolFlags::Weak; + if (F.GenericFlags & LLVMJITSymbolGenericFlagsCallable) + JSF |= JITSymbolFlags::Callable; + if (F.GenericFlags & LLVMJITSymbolGenericFlagsMaterializationSideEffectsOnly) + JSF |= JITSymbolFlags::MaterializationSideEffectsOnly; + + JSF.getTargetFlags() = F.TargetFlags; + + return JSF; +} + +} // end anonymous namespace + void LLVMOrcExecutionSessionSetErrorReporter( LLVMOrcExecutionSessionRef ES, LLVMOrcErrorReporterFunction ReportError, void *Ctx) { @@ -182,7 +253,7 @@ void LLVMOrcSymbolStringPoolClearDeadEntries(LLVMOrcSymbolStringPoolRef SSP) { LLVMOrcSymbolStringPoolEntryRef LLVMOrcExecutionSessionIntern(LLVMOrcExecutionSessionRef ES, const char *Name) { return wrap( - OrcV2CAPIHelper::releaseSymbolStringPtr(unwrap(ES)->intern(Name))); + OrcV2CAPIHelper::moveFromSymbolStringPtr(unwrap(ES)->intern(Name))); } void LLVMOrcRetainSymbolStringPoolEntry(LLVMOrcSymbolStringPoolEntryRef S) { @@ -236,20 +307,29 @@ void LLVMOrcDisposeMaterializationUnit(LLVMOrcMaterializationUnitRef MU) { std::unique_ptr TmpMU(unwrap(MU)); } +LLVMOrcMaterializationUnitRef LLVMOrcCreateCustomMaterializationUnit( + const char *Name, void *Ctx, LLVMOrcCSymbolFlagsMapPairs Syms, + size_t NumSyms, LLVMOrcSymbolStringPoolEntryRef InitSym, + LLVMOrcMaterializationUnitMaterializeFunction Materialize, + LLVMOrcMaterializationUnitDiscardFunction Discard, + LLVMOrcMaterializationUnitDestroyFunction Destroy) { + SymbolFlagsMap SFM; + for (size_t I = 0; I != NumSyms; ++I) + SFM[OrcV2CAPIHelper::moveToSymbolStringPtr(unwrap(Syms[I].Name))] = + toJITSymbolFlags(Syms[I].Flags); + + auto IS = OrcV2CAPIHelper::moveToSymbolStringPtr(unwrap(InitSym)); + + return wrap(new OrcCAPIMaterializationUnit( + Name, std::move(SFM), std::move(IS), Ctx, Materialize, Discard, Destroy)); +} + LLVMOrcMaterializationUnitRef LLVMOrcAbsoluteSymbols(LLVMOrcCSymbolMapPairs Syms, size_t NumPairs) { SymbolMap SM; for (size_t I = 0; I != NumPairs; ++I) { - JITSymbolFlags Flags; - - if (Syms[I].Sym.Flags.GenericFlags & LLVMJITSymbolGenericFlagsExported) - Flags |= JITSymbolFlags::Exported; - if (Syms[I].Sym.Flags.GenericFlags & LLVMJITSymbolGenericFlagsWeak) - Flags |= JITSymbolFlags::Weak; - - Flags.getTargetFlags() = Syms[I].Sym.Flags.TargetFlags; - - SM[OrcV2CAPIHelper::retainSymbolStringPtr(unwrap(Syms[I].Name))] = + JITSymbolFlags Flags = toJITSymbolFlags(Syms[I].Sym.Flags); + SM[OrcV2CAPIHelper::moveToSymbolStringPtr(unwrap(Syms[I].Name))] = JITEvaluatedSymbol(Syms[I].Sym.Address, Flags); } @@ -393,6 +473,14 @@ void LLVMOrcDisposeJITTargetMachineBuilder( delete unwrap(JTMB); } +void LLVMOrcObjectLayerEmit(LLVMOrcObjectLayerRef ObjLayer, + LLVMOrcMaterializationResponsibilityRef R, + LLVMMemoryBufferRef ObjBuffer) { + unwrap(ObjLayer)->emit( + std::unique_ptr(unwrap(R)), + std::unique_ptr(unwrap(ObjBuffer))); +} + void LLVMOrcDisposeObjectLayer(LLVMOrcObjectLayerRef ObjLayer) { delete unwrap(ObjLayer); } @@ -463,7 +551,7 @@ char LLVMOrcLLJITGetGlobalPrefix(LLVMOrcLLJITRef J) { LLVMOrcSymbolStringPoolEntryRef LLVMOrcLLJITMangleAndIntern(LLVMOrcLLJITRef J, const char *UnmangledName) { - return wrap(OrcV2CAPIHelper::releaseSymbolStringPtr( + return wrap(OrcV2CAPIHelper::moveFromSymbolStringPtr( unwrap(J)->mangleAndIntern(UnmangledName))); } @@ -511,6 +599,10 @@ LLVMErrorRef LLVMOrcLLJITLookup(LLVMOrcLLJITRef J, return LLVMErrorSuccess; } +LLVMOrcObjectLayerRef LLVMOrcLLJITGetObjLinkingLayer(LLVMOrcLLJITRef J) { + return wrap(&unwrap(J)->getObjLinkingLayer()); +} + LLVMOrcObjectLayerRef LLVMOrcCreateRTDyldObjectLinkingLayerWithSectionMemoryManager( LLVMOrcExecutionSessionRef ES) {