Skip to content

Commit 1c22f00

Browse files
committed
reconstruct map the hardway before 1.13
1 parent 2773ec1 commit 1c22f00

File tree

1 file changed

+69
-11
lines changed

1 file changed

+69
-11
lines changed

src/jlgen.jl

Lines changed: 69 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -672,6 +672,28 @@ end
672672
CompilationPolicyExtern = 1
673673
end
674674

675+
const AL_N_INLINE = 29
676+
# mirrows arraylist_t
677+
mutable struct ArrayList
678+
len::Csize_t
679+
max::Csize_t
680+
items::Ptr{Ptr{Cvoid}}
681+
_space::NTuple{AL_N_INLINE, Ptr{Cvoid}}
682+
683+
function ArrayList()
684+
list = new(0, AL_N_INLINE, Ptr{Ptr{Cvoid}}(C_NULL), ntuple(_->Ptr{Cvoid}(C_NULL), AL_N_INLINE))
685+
list.items = Base.pointer_from_objref(list) + fieldoffset(typeof(list), 4)
686+
687+
finalizer(list) do list
688+
if list.items != Base.pointer_from_objref(list) + fieldoffset(typeof(list), 4)
689+
Libc.free(list.items)
690+
end
691+
end
692+
return list
693+
end
694+
end
695+
696+
675697
"""
676698
precompile(job::CompilerJob)
677699
@@ -787,16 +809,17 @@ function compile_method_instance(@nospecialize(job::CompilerJob))
787809
end
788810

789811
gv_to_value = Dict{String, Any}()
790-
num_gvars = Ref{Csize_t}(0)
791-
@ccall jl_get_llvm_gvs(native_code::Ptr{Cvoid}, num_gvars::Ptr{Csize_t},
792-
C_NULL::Ptr{Cvoid})::Nothing
793-
gvs = Vector{Ptr{LLVM.API.LLVMOpaqueValue}}(undef, num_gvars[])
794-
@ccall jl_get_llvm_gvs(native_code::Ptr{Cvoid}, num_gvars::Ptr{Csize_t},
795-
gvs::Ptr{LLVM.API.LLVMOpaqueValue})::Nothing
796812

797813
if VERSION >= v"1.13.0-DEV.623"
798814
# Since Julia 1.13, the caller is responsible for initializing global variables that
799815
# point to global values or bindings with their address in memory.
816+
num_gvars = Ref{Csize_t}(0)
817+
@ccall jl_get_llvm_gvs(native_code::Ptr{Cvoid}, num_gvars::Ptr{Csize_t},
818+
C_NULL::Ptr{Cvoid})::Nothing
819+
gvs = Vector{Ptr{LLVM.API.LLVMOpaqueValue}}(undef, num_gvars[])
820+
@ccall jl_get_llvm_gvs(native_code::Ptr{Cvoid}, num_gvars::Ptr{Csize_t},
821+
gvs::Ptr{LLVM.API.LLVMOpaqueValue})::Nothing
822+
800823
inits = Vector{Ptr{Cvoid}}(undef, num_gvars[])
801824
@ccall jl_get_llvm_gv_inits(native_code::Ptr{Cvoid}, num_gvars::Ptr{Csize_t},
802825
inits::Ptr{Cvoid})::Nothing
@@ -807,15 +830,50 @@ function compile_method_instance(@nospecialize(job::CompilerJob))
807830
initializer!(gv, val)
808831

809832
# TODO: jl_binding_t?
833+
@show LLVM.name(gv), val
810834
gv_to_value[LLVM.name(gv)] = Base.unsafe_pointer_to_objref(val)
811835
end
812836
else
813-
for gv_ref in gvs
814-
gv = GlobalVariable(gv_ref)
815-
val = reinterpret(Ptr{Cvoid}, initializer(gv))
816-
# TODO: jl_binding_t?
817-
gv_to_value[LLVM.name(gv)] = Base.unsafe_pointer_to_objref(val)
837+
# Prior to this version of Julia we only had access to the values that the global variables
838+
# were initialized with, so we have to match them up manually.
839+
# get the global values
840+
if VERSION >= v"1.12.0-DEV.1703"
841+
num_gvars = Ref{Csize_t}(0)
842+
@ccall jl_get_llvm_gvs(native_code::Ptr{Cvoid}, num_gvars::Ptr{Csize_t},
843+
C_NULL::Ptr{Cvoid})::Nothing
844+
gvalues = Vector{Ptr{Cvoid}}(undef, num_gvars[])
845+
@ccall jl_get_llvm_gvs(native_code::Ptr{Cvoid}, num_gvars::Ptr{Csize_t},
846+
gvalues::Ptr{Cvoid})::Nothing
847+
else
848+
# Sigh on older version of Julia we have to use `arraylist_t` which doesn't have a Julia API.
849+
gvars = ArrayList()
850+
GC.@preserve gvars begin
851+
p_gvars = Base.pointer_from_objref(gvars)
852+
@ccall jl_get_llvm_gvs(native_code::Ptr{Cvoid}, p_gvars::Ptr{Cvoid})::Nothing
853+
gvalues = Vector{Ptr{Cvoid}}(undef, gvars.len)
854+
for i in 1:gvars.len
855+
gvalues[i] = unsafe_load(gvars.items, i)
856+
end
857+
end
858+
end
859+
gvalues = Set(gvalues)
860+
for gv in globals(llvm_mod)
861+
init = LLVM.initializer(gv)
862+
if init === nothing
863+
continue
864+
end
865+
if init isa LLVM.ConstantExpr && opcode(init) == LLVM.API.LLVMIntToPtr
866+
init = operands(init)[1]
867+
end
868+
if !(init isa LLVM.ConstantInt)
869+
continue
870+
end
871+
ptr = reinterpret(Ptr{Cvoid}, convert(UInt, init))
872+
if ptr in gvalues
873+
gv_to_value[LLVM.name(gv)] = Base.unsafe_pointer_to_objref(ptr)
874+
end
818875
end
876+
@assert length(gv_to_value) == length(gvalues)
819877
end
820878

821879
if VERSION >= v"1.13.0-DEV.1120"

0 commit comments

Comments
 (0)