[llvm] c8fc5e3 - [ORC] C API updates.

Lang Hames via llvm-commits llvm-commits at lists.llvm.org
Mon Apr 26 14:04:20 PDT 2021


Author: Lang Hames
Date: 2021-04-26T13:58:37-07:00
New Revision: c8fc5e3ba942057d6c4cdcd1faeae69a28e7b671

URL: https://github.com/llvm/llvm-project/commit/c8fc5e3ba942057d6c4cdcd1faeae69a28e7b671
DIFF: https://github.com/llvm/llvm-project/commit/c8fc5e3ba942057d6c4cdcd1faeae69a28e7b671.diff

LOG: [ORC] C API updates.

Adds support for creating custom MaterializationUnits in the C API with the new
LLVMOrcCreateCustomMaterializationUnit function.

Modifies ownership rules for LLVMOrcAbsoluteSymbols to make it consistent with
LLVMOrcCreateCustomMaterializationUnit. This is an ABI breaking change for any
clients of the LLVMOrcAbsoluteSymbols API.

Adds LLVMOrcLLJITGetObjLinkingLayer and LLVMOrcObjectLayerEmit functions to
allow clients to get a reference to an LLJIT instance's linking layer, then
emit an object file using it. This can be used to support construction of
custom materialization units in the common case where those units will
generate an object file that needs to be emitted to complete the
materialization.

Added: 
    

Modified: 
    llvm/include/llvm-c/LLJIT.h
    llvm/include/llvm-c/Orc.h
    llvm/lib/ExecutionEngine/Orc/OrcV2CBindings.cpp

Removed: 
    


################################################################################
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 @@ class OrcV2CAPIHelper {
   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 @@ class CAPIDefinitionGenerator final : public DefinitionGenerator {
 } // 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<MaterializationResponsibility> 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<MaterializationUnit> 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<MaterializationResponsibility>(unwrap(R)),
+      std::unique_ptr<MemoryBuffer>(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) {


        


More information about the llvm-commits mailing list