Skip to content

Commit e2fb67b

Browse files
committed
Clarify and publish the host-reference interface
1 parent 5dbc851 commit e2fb67b

4 files changed

Lines changed: 52 additions & 14 deletions

File tree

src/interface.jl

Lines changed: 43 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -429,19 +429,43 @@ the check-and-compile sequence (all back-ends already do, e.g. `mtlfunction_lock
429429
"""
430430
function cached_results end
431431

432-
# Host-reference metadata belongs to the compiler pipeline rather than a particular result
433-
# cache. Julia 1.10 keeps results in a process-local cache, while newer Julias can persist
434-
# them in package images, but both versions need the same representation while compiling.
432+
"""
433+
JuliaValueRef(value)
434+
435+
A Julia value used as the serializable identity of a host reference. Resolve it in the active
436+
session with [`resolve_host_reference`](@ref); a loader that writes the resulting address into
437+
device storage must keep `value` rooted for as long as that storage remains reachable.
438+
"""
435439
struct JuliaValueRef
436440
value::Any
437441
end
438442

439-
struct RuntimeGlobalRef
440-
name::Symbol
443+
"""
444+
CGlobalRef(symbol)
445+
446+
A libjulia C data global. Resolving this reference calls `jl_cglobal` for `symbol` and loads
447+
the word stored at that address.
448+
"""
449+
struct CGlobalRef
450+
symbol::Symbol
441451
end
442452

443-
const HostReference = Union{JuliaValueRef,RuntimeGlobalRef}
453+
"""
454+
HostReference
444455
456+
A serializable source for a host-derived word: either a [`JuliaValueRef`](@ref) or a
457+
[`CGlobalRef`](@ref).
458+
"""
459+
const HostReference = Union{JuliaValueRef,CGlobalRef}
460+
461+
"""
462+
HostReferences(slots, embedded_pointer)
463+
464+
Host-reference metadata accompanying a module. `slots` maps each object-code symbol to the
465+
source of the word that must be written there. `embedded_pointer` conservatively records that
466+
an unavoidable session pointer has been embedded, so the artifact cannot be serialized into a
467+
package image even if `slots` is empty.
468+
"""
445469
mutable struct HostReferences
446470
slots::Dict{String,HostReference}
447471
embedded_pointer::Bool
@@ -452,13 +476,19 @@ copy_host_references(refs::HostReferences) =
452476
HostReferences(copy(refs.slots), refs.embedded_pointer)
453477

454478
same_host_reference(a::JuliaValueRef, b::JuliaValueRef) = a.value === b.value
455-
same_host_reference(a::RuntimeGlobalRef, b::RuntimeGlobalRef) = a.name === b.name
479+
same_host_reference(a::CGlobalRef, b::CGlobalRef) = a.symbol === b.symbol
456480
same_host_reference(::HostReference, ::HostReference) = false
457481

482+
"""
483+
resolve_host_reference(ref) -> UInt
484+
485+
Resolve `ref` to its current-session word. Loader-based backends use this after loading the
486+
object and before exposing a callable function.
487+
"""
458488
resolve_host_reference(ref::JuliaValueRef) =
459489
UInt(ccall(:jl_value_ptr, Ptr{Cvoid}, (Any,), ref.value))
460-
function resolve_host_reference(ref::RuntimeGlobalRef)
461-
address = ccall(:jl_cglobal, Any, (Any, Any), String(ref.name), UInt)
490+
function resolve_host_reference(ref::CGlobalRef)
491+
address = ccall(:jl_cglobal, Any, (Any, Any), String(ref.symbol), UInt)
462492
return unsafe_load(address)
463493
end
464494

@@ -467,8 +497,8 @@ end
467497
468498
Lower compiler-managed Julia value globals and Julia runtime globals for `job`'s final
469499
backend representation. The default lowering resolves every live reference in the current
470-
Julia session. Backends with a loader relocation mechanism may leave word-sized slots for
471-
their loader instead.
500+
Julia session. Backends with a loader relocation mechanism may call
501+
[`emit_host_reference_slots!`](@ref) instead, then resolve and patch those slots after loading.
472502
"""
473503
function lower_host_references!(@nospecialize(job::CompilerJob), mod::LLVM.Module,
474504
refs::HostReferences)
@@ -596,6 +626,8 @@ end
596626
end # HAS_INTEGRATED_CACHE
597627

598628
@public GPUCompilerCacheToken, cache_owner, cached_results
629+
@public JuliaValueRef, CGlobalRef, HostReference, HostReferences
630+
@public lower_host_references!, emit_host_reference_slots!, resolve_host_reference
599631

600632
# the method table to use
601633
#

src/jlgen.jl

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -834,6 +834,12 @@ function resolve_host_reference_slots!(mod::LLVM.Module, refs::HostReferences)
834834
return
835835
end
836836

837+
"""
838+
emit_host_reference_slots!(mod, refs)
839+
840+
Prepare the globals named by `refs.slots` for loader-based lowering. Each remains a writable,
841+
word-sized external symbol that the loader must resolve and patch after loading the object.
842+
"""
837843
function emit_host_reference_slots!(mod::LLVM.Module, refs::HostReferences)
838844
check_host_reference_slots!(mod, refs)
839845
mod_gvs = globals(mod)

src/mcgen.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ function (self::CollectRuntimeGlobalReferences)(mod::LLVM.Module)
5757
actual_name = LLVM.name(slot)
5858
haskey(self.refs.slots, actual_name) &&
5959
error("Duplicate Julia runtime global slot '$actual_name'")
60-
self.refs.slots[actual_name] = RuntimeGlobalRef(Symbol(fn))
60+
self.refs.slots[actual_name] = CGlobalRef(Symbol(fn))
6161
end
6262
slot
6363
end

test/native.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -765,7 +765,7 @@ end
765765
refs = GPUCompiler.HostReferences()
766766
@test GPUCompiler.collect_runtime_global_references!(job, mod, refs)
767767
name = only(keys(refs.slots))
768-
@test refs.slots[name] == GPUCompiler.RuntimeGlobalRef(:jl_float32_type)
768+
@test refs.slots[name] == GPUCompiler.CGlobalRef(:jl_float32_type)
769769
@test occursin("externally_initialized global i64 0", string(mod))
770770

771771
mod = parse(LLVM.Module, """
@@ -778,7 +778,7 @@ end
778778
refs = GPUCompiler.HostReferences()
779779
@test GPUCompiler.collect_runtime_global_references!(job, mod, refs)
780780
name = only(keys(refs.slots))
781-
@test refs.slots[name] == GPUCompiler.RuntimeGlobalRef(:jl_float32_type)
781+
@test refs.slots[name] == GPUCompiler.CGlobalRef(:jl_float32_type)
782782
@test occursin("externally_initialized global i64 0", string(mod))
783783
end
784784
end

0 commit comments

Comments
 (0)