Skip to content

Commit c8fc5e3

Browse files
committed
[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.
1 parent 8d718a0 commit c8fc5e3

File tree

3 files changed

+240
-16
lines changed

3 files changed

+240
-16
lines changed

llvm/include/llvm-c/LLJIT.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,11 @@ LLVMErrorRef LLVMOrcLLJITLookup(LLVMOrcLLJITRef J,
208208
LLVMOrcJITTargetAddress *Result,
209209
const char *Name);
210210

211+
/**
212+
* Returns a non-owning reference to the LLJIT instance's object linking layer.
213+
*/
214+
LLVMOrcObjectLayerRef LLVMOrcLLJITGetObjLinkingLayer(LLVMOrcLLJITRef J);
215+
211216
LLVM_C_EXTERN_C_END
212217

213218
#endif /* LLVM_C_LLJIT_H */

llvm/include/llvm-c/Orc.h

Lines changed: 129 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,9 @@ typedef uint64_t LLVMOrcJITTargetAddress;
4343
*/
4444
typedef enum {
4545
LLVMJITSymbolGenericFlagsExported = 1U << 0,
46-
LLVMJITSymbolGenericFlagsWeak = 1U << 1
46+
LLVMJITSymbolGenericFlagsWeak = 1U << 1,
47+
LLVMJITSymbolGenericFlagsCallable = 1U << 2,
48+
LLVMJITSymbolGenericFlagsMaterializationSideEffectsOnly = 1U << 3
4749
} LLVMJITSymbolGenericFlags;
4850

4951
/**
@@ -88,6 +90,20 @@ typedef struct LLVMOrcOpaqueSymbolStringPool *LLVMOrcSymbolStringPoolRef;
8890
typedef struct LLVMOrcOpaqueSymbolStringPoolEntry
8991
*LLVMOrcSymbolStringPoolEntryRef;
9092

93+
/**
94+
* Represents a pair of a symbol name and LLVMJITSymbolFlags.
95+
*/
96+
typedef struct {
97+
LLVMOrcSymbolStringPoolEntryRef Name;
98+
LLVMJITSymbolFlags Flags;
99+
} LLVMOrcCSymbolFlagsMapPair;
100+
101+
/**
102+
* Represents a list of (SymbolStringPtr, JITSymbolFlags) pairs that can be used
103+
* to construct a SymbolFlagsMap.
104+
*/
105+
typedef LLVMOrcCSymbolFlagsMapPair *LLVMOrcCSymbolFlagsMapPairs;
106+
91107
/**
92108
* Represents a pair of a symbol name and an evaluated symbol.
93109
*/
@@ -155,15 +171,54 @@ typedef struct {
155171
typedef LLVMOrcCLookupSetElement *LLVMOrcCLookupSet;
156172

157173
/**
158-
* A reference to an orc::MaterializationUnit.
174+
* A reference to a uniquely owned orc::MaterializationUnit instance.
159175
*/
160176
typedef struct LLVMOrcOpaqueMaterializationUnit *LLVMOrcMaterializationUnitRef;
161177

178+
/**
179+
* A reference to a uniquely owned orc::MaterializationResponsibility instance.
180+
*
181+
* Ownership must be passed to a lower-level layer in a JIT stack.
182+
*/
183+
typedef struct LLVMOrcOpaqueMaterializationResponsibility
184+
*LLVMOrcMaterializationResponsibilityRef;
185+
162186
/**
163187
* A reference to an orc::JITDylib instance.
164188
*/
165189
typedef struct LLVMOrcOpaqueJITDylib *LLVMOrcJITDylibRef;
166190

191+
/**
192+
* A MaterializationUnit materialize callback.
193+
*
194+
* Ownership of the Ctx and MR arguments passes to the callback which must
195+
* adhere to the LLVMOrcMaterializationResponsibilityRef contract (see comment
196+
* for that type).
197+
*
198+
* If this callback is called then the LLVMOrcMaterializationUnitDestroy
199+
* callback will NOT be called.
200+
*/
201+
typedef void (*LLVMOrcMaterializationUnitMaterializeFunction)(
202+
void *Ctx, LLVMOrcMaterializationResponsibilityRef MR);
203+
204+
/**
205+
* A MaterializationUnit discard callback.
206+
*
207+
* Ownership of JD and Symbol remain with the caller: These arguments should
208+
* not be disposed of or released.
209+
*/
210+
typedef void (*LLVMOrcMaterializationUnitDiscardFunction)(
211+
void *Ctx, LLVMOrcJITDylibRef JD, LLVMOrcSymbolStringPoolEntryRef Symbol);
212+
213+
/**
214+
* A MaterializationUnit destruction callback.
215+
*
216+
* If a custom MaterializationUnit is destroyed before its Materialize
217+
* function is called then this function will be called to provide an
218+
* opportunity for the underlying program representation to be destroyed.
219+
*/
220+
typedef void (*LLVMOrcMaterializationUnitDestroyFunction)(void *Ctx);
221+
167222
/**
168223
* A reference to an orc::ResourceTracker instance.
169224
*/
@@ -255,6 +310,11 @@ typedef struct LLVMOrcOpaqueJITTargetMachineBuilder
255310
*/
256311
typedef struct LLVMOrcOpaqueObjectLayer *LLVMOrcObjectLayerRef;
257312

313+
/**
314+
* A reference to an orc::ObjectLinkingLayer instance.
315+
*/
316+
typedef struct LLVMOrcOpaqueObjectLinkingLayer *LLVMOrcObjectLinkingLayerRef;
317+
258318
/**
259319
* Attach a custom error reporter function to the ExecutionSession.
260320
*
@@ -346,9 +406,66 @@ void LLVMOrcDisposeDefinitionGenerator(LLVMOrcDefinitionGeneratorRef DG);
346406
*/
347407
void LLVMOrcDisposeMaterializationUnit(LLVMOrcMaterializationUnitRef MU);
348408

409+
/**
410+
* Create a custom MaterializationUnit.
411+
*
412+
* Name is a name for this MaterializationUnit to be used for identification
413+
* and logging purposes (e.g. if this MaterializationUnit produces an
414+
* object buffer then the name of that buffer will be derived from this name).
415+
*
416+
* The Syms list contains the names and linkages of the symbols provided by this
417+
* unit. This function takes ownership of the elements of the Syms array. The
418+
* Name fields of the array elements are taken to have been retained for this
419+
* function. The client should *not* release the elements of the array, but is
420+
* still responsible for destroyingthe array itself.
421+
*
422+
* The InitSym argument indicates whether or not this MaterializationUnit
423+
* contains static initializers. If three are no static initializers (the common
424+
* case) then this argument should be null. If there are static initializers
425+
* then InitSym should be set to a unique name that also appears in the Syms
426+
* list with the LLVMJITSymbolGenericFlagsMaterializationSideEffectsOnly flag
427+
* set. This function takes ownership of the InitSym, which should have been
428+
* retained twice on behalf of this function: once for the Syms entry and once
429+
* for InitSym. If clients wish to use the InitSym value after this function
430+
* returns they must retain it once more for themselves.
431+
*
432+
* If any of the symbols in the Syms list is looked up then the Materialize
433+
* function will be called.
434+
*
435+
* If any of the symbols in the Syms list is overridden then the Discard
436+
* function will be called.
437+
*
438+
* The caller owns the underling MaterializationUnit and is responsible for
439+
* either passing it to a JITDylib (via LLVMOrcJITDylibDefine) or disposing
440+
* of it by calling LLVMOrcDisposeMaterializationUnit.
441+
*/
442+
LLVMOrcMaterializationUnitRef LLVMOrcCreateCustomMaterializationUnit(
443+
const char *Name, void *Ctx, LLVMOrcCSymbolFlagsMapPairs Syms,
444+
size_t NumSyms, LLVMOrcSymbolStringPoolEntryRef InitSym,
445+
LLVMOrcMaterializationUnitMaterializeFunction Materialize,
446+
LLVMOrcMaterializationUnitDiscardFunction Discard,
447+
LLVMOrcMaterializationUnitDestroyFunction Destroy);
448+
349449
/**
350450
* Create a MaterializationUnit to define the given symbols as pointing to
351451
* the corresponding raw addresses.
452+
*
453+
* This function takes ownership of the elements of the Syms array. The Name
454+
* fields of the array elements are taken to have been retained for this
455+
* function. This allows the following pattern...
456+
*
457+
* size_t NumPairs;
458+
* LLVMOrcCSymbolMapPairs Sym;
459+
* -- Build Syms array --
460+
* LLVMOrcMaterializationUnitRef MU =
461+
* LLVMOrcAbsoluteSymbols(Syms, NumPairs);
462+
*
463+
* ... without requiring cleanup of the elements of the Sym array afterwards.
464+
*
465+
* The client is still responsible for deleting the Sym array itself.
466+
*
467+
* If a client wishes to reuse elements of the Sym array after this call they
468+
* must explicitly retain each of the elements for themselves.
352469
*/
353470
LLVMOrcMaterializationUnitRef
354471
LLVMOrcAbsoluteSymbols(LLVMOrcCSymbolMapPairs Syms, size_t NumPairs);
@@ -529,6 +646,16 @@ LLVMOrcJITTargetMachineBuilderCreateFromTargetMachine(LLVMTargetMachineRef TM);
529646
void LLVMOrcDisposeJITTargetMachineBuilder(
530647
LLVMOrcJITTargetMachineBuilderRef JTMB);
531648

649+
/**
650+
* Emit an object buffer to an ObjectLayer.
651+
*
652+
* Ownership of the responsibility object and object buffer pass to this
653+
* function. The client is not responsible for cleanup.
654+
*/
655+
void LLVMOrcObjectLayerEmit(LLVMOrcObjectLayerRef ObjLayer,
656+
LLVMOrcMaterializationResponsibilityRef R,
657+
LLVMMemoryBufferRef ObjBuffer);
658+
532659
/**
533660
* Dispose of an ObjectLayer.
534661
*/

llvm/lib/ExecutionEngine/Orc/OrcV2CBindings.cpp

Lines changed: 106 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,22 @@ class OrcV2CAPIHelper {
2929
using PoolEntry = SymbolStringPtr::PoolEntry;
3030
using PoolEntryPtr = SymbolStringPtr::PoolEntryPtr;
3131

32-
static PoolEntryPtr releaseSymbolStringPtr(SymbolStringPtr S) {
32+
// Move from SymbolStringPtr to PoolEntryPtr (no change in ref count).
33+
static PoolEntryPtr moveFromSymbolStringPtr(SymbolStringPtr S) {
3334
PoolEntryPtr Result = nullptr;
3435
std::swap(Result, S.S);
3536
return Result;
3637
}
3738

38-
static SymbolStringPtr retainSymbolStringPtr(PoolEntryPtr P) {
39+
// Move from a PoolEntryPtr to a SymbolStringPtr (no change in ref count).
40+
static SymbolStringPtr moveToSymbolStringPtr(PoolEntryPtr P) {
41+
SymbolStringPtr S;
42+
S.S = P;
43+
return S;
44+
}
45+
46+
// Copy a pool entry to a SymbolStringPtr (increments ref count).
47+
static SymbolStringPtr copyToSymbolStringPtr(PoolEntryPtr P) {
3948
return SymbolStringPtr(P);
4049
}
4150

@@ -71,6 +80,8 @@ DEFINE_SIMPLE_CONVERSION_FUNCTIONS(OrcV2CAPIHelper::PoolEntry,
7180
LLVMOrcSymbolStringPoolEntryRef)
7281
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(MaterializationUnit,
7382
LLVMOrcMaterializationUnitRef)
83+
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(MaterializationResponsibility,
84+
LLVMOrcMaterializationResponsibilityRef)
7485
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(JITDylib, LLVMOrcJITDylibRef)
7586
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(ResourceTracker, LLVMOrcResourceTrackerRef)
7687
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(DefinitionGenerator,
@@ -163,6 +174,66 @@ class CAPIDefinitionGenerator final : public DefinitionGenerator {
163174
} // end namespace orc
164175
} // end namespace llvm
165176

177+
namespace {
178+
179+
class OrcCAPIMaterializationUnit : public llvm::orc::MaterializationUnit {
180+
public:
181+
OrcCAPIMaterializationUnit(
182+
std::string Name, SymbolFlagsMap InitialSymbolFlags,
183+
SymbolStringPtr InitSymbol, void *Ctx,
184+
LLVMOrcMaterializationUnitMaterializeFunction Materialize,
185+
LLVMOrcMaterializationUnitDiscardFunction Discard,
186+
LLVMOrcMaterializationUnitDestroyFunction Destroy)
187+
: llvm::orc::MaterializationUnit(std::move(InitialSymbolFlags),
188+
std::move(InitSymbol)),
189+
Name(std::move(Name)), Ctx(Ctx), Materialize(Materialize),
190+
Discard(Discard), Destroy(Destroy) {}
191+
192+
~OrcCAPIMaterializationUnit() {
193+
if (Ctx)
194+
Destroy(Ctx);
195+
}
196+
197+
StringRef getName() const override { return Name; }
198+
199+
void materialize(std::unique_ptr<MaterializationResponsibility> R) override {
200+
void *Tmp = Ctx;
201+
Ctx = nullptr;
202+
Materialize(Tmp, wrap(R.release()));
203+
}
204+
205+
private:
206+
void discard(const JITDylib &JD, const SymbolStringPtr &Name) override {
207+
Discard(Ctx, wrap(&JD), wrap(OrcV2CAPIHelper::getRawPoolEntryPtr(Name)));
208+
}
209+
210+
std::string Name;
211+
void *Ctx = nullptr;
212+
LLVMOrcMaterializationUnitMaterializeFunction Materialize = nullptr;
213+
LLVMOrcMaterializationUnitDiscardFunction Discard = nullptr;
214+
LLVMOrcMaterializationUnitDestroyFunction Destroy = nullptr;
215+
};
216+
217+
static JITSymbolFlags toJITSymbolFlags(LLVMJITSymbolFlags F) {
218+
219+
JITSymbolFlags JSF;
220+
221+
if (F.GenericFlags & LLVMJITSymbolGenericFlagsExported)
222+
JSF |= JITSymbolFlags::Exported;
223+
if (F.GenericFlags & LLVMJITSymbolGenericFlagsWeak)
224+
JSF |= JITSymbolFlags::Weak;
225+
if (F.GenericFlags & LLVMJITSymbolGenericFlagsCallable)
226+
JSF |= JITSymbolFlags::Callable;
227+
if (F.GenericFlags & LLVMJITSymbolGenericFlagsMaterializationSideEffectsOnly)
228+
JSF |= JITSymbolFlags::MaterializationSideEffectsOnly;
229+
230+
JSF.getTargetFlags() = F.TargetFlags;
231+
232+
return JSF;
233+
}
234+
235+
} // end anonymous namespace
236+
166237
void LLVMOrcExecutionSessionSetErrorReporter(
167238
LLVMOrcExecutionSessionRef ES, LLVMOrcErrorReporterFunction ReportError,
168239
void *Ctx) {
@@ -182,7 +253,7 @@ void LLVMOrcSymbolStringPoolClearDeadEntries(LLVMOrcSymbolStringPoolRef SSP) {
182253
LLVMOrcSymbolStringPoolEntryRef
183254
LLVMOrcExecutionSessionIntern(LLVMOrcExecutionSessionRef ES, const char *Name) {
184255
return wrap(
185-
OrcV2CAPIHelper::releaseSymbolStringPtr(unwrap(ES)->intern(Name)));
256+
OrcV2CAPIHelper::moveFromSymbolStringPtr(unwrap(ES)->intern(Name)));
186257
}
187258

188259
void LLVMOrcRetainSymbolStringPoolEntry(LLVMOrcSymbolStringPoolEntryRef S) {
@@ -236,20 +307,29 @@ void LLVMOrcDisposeMaterializationUnit(LLVMOrcMaterializationUnitRef MU) {
236307
std::unique_ptr<MaterializationUnit> TmpMU(unwrap(MU));
237308
}
238309

310+
LLVMOrcMaterializationUnitRef LLVMOrcCreateCustomMaterializationUnit(
311+
const char *Name, void *Ctx, LLVMOrcCSymbolFlagsMapPairs Syms,
312+
size_t NumSyms, LLVMOrcSymbolStringPoolEntryRef InitSym,
313+
LLVMOrcMaterializationUnitMaterializeFunction Materialize,
314+
LLVMOrcMaterializationUnitDiscardFunction Discard,
315+
LLVMOrcMaterializationUnitDestroyFunction Destroy) {
316+
SymbolFlagsMap SFM;
317+
for (size_t I = 0; I != NumSyms; ++I)
318+
SFM[OrcV2CAPIHelper::moveToSymbolStringPtr(unwrap(Syms[I].Name))] =
319+
toJITSymbolFlags(Syms[I].Flags);
320+
321+
auto IS = OrcV2CAPIHelper::moveToSymbolStringPtr(unwrap(InitSym));
322+
323+
return wrap(new OrcCAPIMaterializationUnit(
324+
Name, std::move(SFM), std::move(IS), Ctx, Materialize, Discard, Destroy));
325+
}
326+
239327
LLVMOrcMaterializationUnitRef
240328
LLVMOrcAbsoluteSymbols(LLVMOrcCSymbolMapPairs Syms, size_t NumPairs) {
241329
SymbolMap SM;
242330
for (size_t I = 0; I != NumPairs; ++I) {
243-
JITSymbolFlags Flags;
244-
245-
if (Syms[I].Sym.Flags.GenericFlags & LLVMJITSymbolGenericFlagsExported)
246-
Flags |= JITSymbolFlags::Exported;
247-
if (Syms[I].Sym.Flags.GenericFlags & LLVMJITSymbolGenericFlagsWeak)
248-
Flags |= JITSymbolFlags::Weak;
249-
250-
Flags.getTargetFlags() = Syms[I].Sym.Flags.TargetFlags;
251-
252-
SM[OrcV2CAPIHelper::retainSymbolStringPtr(unwrap(Syms[I].Name))] =
331+
JITSymbolFlags Flags = toJITSymbolFlags(Syms[I].Sym.Flags);
332+
SM[OrcV2CAPIHelper::moveToSymbolStringPtr(unwrap(Syms[I].Name))] =
253333
JITEvaluatedSymbol(Syms[I].Sym.Address, Flags);
254334
}
255335

@@ -393,6 +473,14 @@ void LLVMOrcDisposeJITTargetMachineBuilder(
393473
delete unwrap(JTMB);
394474
}
395475

476+
void LLVMOrcObjectLayerEmit(LLVMOrcObjectLayerRef ObjLayer,
477+
LLVMOrcMaterializationResponsibilityRef R,
478+
LLVMMemoryBufferRef ObjBuffer) {
479+
unwrap(ObjLayer)->emit(
480+
std::unique_ptr<MaterializationResponsibility>(unwrap(R)),
481+
std::unique_ptr<MemoryBuffer>(unwrap(ObjBuffer)));
482+
}
483+
396484
void LLVMOrcDisposeObjectLayer(LLVMOrcObjectLayerRef ObjLayer) {
397485
delete unwrap(ObjLayer);
398486
}
@@ -463,7 +551,7 @@ char LLVMOrcLLJITGetGlobalPrefix(LLVMOrcLLJITRef J) {
463551

464552
LLVMOrcSymbolStringPoolEntryRef
465553
LLVMOrcLLJITMangleAndIntern(LLVMOrcLLJITRef J, const char *UnmangledName) {
466-
return wrap(OrcV2CAPIHelper::releaseSymbolStringPtr(
554+
return wrap(OrcV2CAPIHelper::moveFromSymbolStringPtr(
467555
unwrap(J)->mangleAndIntern(UnmangledName)));
468556
}
469557

@@ -511,6 +599,10 @@ LLVMErrorRef LLVMOrcLLJITLookup(LLVMOrcLLJITRef J,
511599
return LLVMErrorSuccess;
512600
}
513601

602+
LLVMOrcObjectLayerRef LLVMOrcLLJITGetObjLinkingLayer(LLVMOrcLLJITRef J) {
603+
return wrap(&unwrap(J)->getObjLinkingLayer());
604+
}
605+
514606
LLVMOrcObjectLayerRef
515607
LLVMOrcCreateRTDyldObjectLinkingLayerWithSectionMemoryManager(
516608
LLVMOrcExecutionSessionRef ES) {

0 commit comments

Comments
 (0)