@@ -296,18 +296,49 @@ TBD: absolute symbols, aliases, off-the-shelf layers.
296296Laziness
297297========
298298
299- Laziness in ORC is provided by a utility called "lazy-reexports". The aim of
300- this utility is to re-use the synchronization provided by the symbol lookup
301- mechanism to make it safe to lazily compile functions, even if calls to the
302- stub occur simultaneously on multiple threads of JIT'd code. It does this by
303- reducing lazy compilation to symbol lookup: The lazy stub performs a lookup of
304- its underlying definition on first call, updating the function body pointer
305- once the definition is available. If additional calls arrive on other threads
306- while compilation is ongoing they will be safely blocked by the normal lookup
307- synchronization guarantee (no result until the result is safe) and can also
308- proceed as soon as compilation completes.
309-
310- TBD: Usage example.
299+ Laziness in ORC is provided by a utility called "lazy reexports". A lazy
300+ reexport is similar to a regular reexport or alias: It provides a new name for
301+ an existing symbol. Unlike regular reexports however, lookups of lazy reexports
302+ do not trigger immediate materialization of the reexported symbol. Instead, they
303+ only trigger materialization of a function stub. This function stub is
304+ initialized to point at a *lazy call-through *, which provides reentry into the
305+ JIT. If the stub is called at runtime then the lazy call-through will look up
306+ the reexported symbol (triggering materialization for it if necessary), update
307+ the stub (to call directly to the reexported symbol on subsequent calls), and
308+ then return via the reexported symbol. By re-using the existing symbol lookup
309+ mechanism, lazy reexports inherit the same concurrency guarantees: calls to lazy
310+ reexports can be made from multiple threads concurrently, and the reexported
311+ symbol can be any state of compilation (uncompiled, already in the process of
312+ being compiled, or already compiled) and the call will succeed. This allows
313+ laziness to be safely mixed with features like remote compilation, concurrent
314+ compilation, concurrent JIT'd code, and speculative compilation.
315+
316+ There is one other key difference between regular reexports and lazy reexports
317+ that some clients must be aware of: The address of a lazy reexport will be
318+ *different * from the address of the reexported symbol (whereas a regular
319+ reexport is guaranteed to have the same address as the reexported symbol).
320+ Clients who care about pointer equality will generally want to use the address
321+ of the reexport as the canonical address of the reexported symbol. This will
322+ allow the address to be taken without forcing materialization of the reexport.
323+
324+ Usage example:
325+
326+ If JITDylib ``JD `` contains definitions for symbols ``foo_body `` and
327+ ``bar_body ``, we can create lazy entry points ``Foo `` and ``Bar `` in JITDylib
328+ ``JD2 `` by calling:
329+
330+ .. code-block :: c++
331+
332+ auto ReexportFlags = JITSymbolFlags::Exported | JITSymbolFlags::Callable;
333+ JD2.define(
334+ lazyReexports(CallThroughMgr, StubsMgr, JD,
335+ SymbolAliasMap({
336+ { Mangle("foo"), { Mangle("foo_body"), ReexportedFlags } },
337+ { Mangle("bar"), { Mangle("bar_body"), ReexportedFlags } }
338+ }));
339+
340+ A full example of how to use lazyReexports with the LLJIT class can be found at
341+ ``llvm_project/llvm/examples/LLJITExamples/LLJITWithLazyReexports ``.
311342
312343Supporting Custom Compilers
313344===========================
0 commit comments