@@ -108,12 +108,37 @@ end
108108"""
109109Returns `nothing` if the value could not be resolved statically.
110110"""
111- function resolve_static_jl_value_t (val:: LLVM.Value )
111+ function resolve_static_uint (val:: LLVM.Value )
112112 val = unwrap_ptr_casts (val)
113113 val = look_through_loads (val)
114114 ! isa (val, ConstantInt) && return nothing
115- ptr = reinterpret (Ptr{Cvoid}, convert (UInt, val))
116- return Base. unsafe_pointer_to_objref (ptr)
115+ return convert (UInt, val)
116+ end
117+
118+ """
119+ Returns `nothing` if the value could not be resolved statically.
120+ """
121+ function resolve_static_jl_value (val:: LLVM.Value )
122+ addr = resolve_static_uint (val)
123+ addr === nothing && return nothing
124+ return Base. unsafe_pointer_to_objref (Ptr {Cvoid} (addr))
125+ end
126+
127+ """
128+ Returns `nothing` if the value could not be resolved statically.
129+ """
130+ function resolve_static_type_tag (val:: LLVM.Value )
131+ type_tag = resolve_static_uint (val)
132+ type_tag === nothing && return nothing
133+ type_addr = if type_tag < (JL_MAX_TAGS << 4 )
134+ # "small" type tags are indices into a special array
135+ jl_small_typeof = Ptr {Ptr{Cvoid}} (cglobal (:jl_small_typeof ))
136+ type_idx = type_tag ÷ Core. sizeof (Ptr{Cvoid})
137+ unsafe_load (jl_small_typeof, type_idx + 1 )
138+ else
139+ Ptr {Cvoid} (type_tag)
140+ end
141+ return Base. unsafe_pointer_to_objref (type_addr)
117142end
118143
119144function transitive_uses (inst:: LLVM.Instruction ; unwrap = (use)-> false )
@@ -128,6 +153,8 @@ function transitive_uses(inst::LLVM.Instruction; unwrap = (use)->false)
128153 return uses_
129154end
130155
156+ const JL_MAX_TAGS = 64 # see `enum jl_small_typeof_tags` in julia.h
157+
131158"""
132159Returns `nothing` if the type could not be resolved statically.
133160"""
@@ -144,10 +171,10 @@ function resolve_allocations(call::LLVM.Value)
144171 name = match_[2 ]
145172
146173 if name in (" gc_pool_alloc_instrumented" , " gc_small_alloc_instrumented" , " gc_big_alloc_instrumented" , " gc_alloc_typed" )
147- type = resolve_static_jl_value_t (operands (call)[end - 1 ])
174+ type = resolve_static_type_tag (operands (call)[end - 1 ])
148175 return type != = nothing ? [(call, type)] : nothing
149176 elseif name in (" alloc_array_1d" , " alloc_array_2d" , " alloc_array_3d" )
150- type = resolve_static_jl_value_t (operands (call)[1 ])
177+ type = resolve_static_jl_value (operands (call)[1 ])
151178 return type!= = nothing ? [(call, type)] : nothing
152179 elseif name == " alloc_string"
153180 return [(call, String)]
@@ -160,10 +187,10 @@ function resolve_allocations(call::LLVM.Value)
160187 @assert VERSION > v " 1.11.0-DEV.753"
161188 return [(call, Memory{UInt8})]
162189 elseif name == " alloc_genericmemory"
163- type = resolve_static_jl_value_t (operands (call)[1 ])
190+ type = resolve_static_jl_value (operands (call)[1 ])
164191 return [(call, type != = nothing ? type : Memory)]
165192 elseif name == " alloc_genericmemory_unchecked"
166- type = resolve_static_jl_value_t (operands (call)[3 ])
193+ type = resolve_static_jl_value (operands (call)[3 ])
167194 return [(call, type != = nothing ? type : Memory)]
168195 elseif occursin (r" ^box_(.*)" , name)
169196 typestr = match (r" ^box_(.*)" , name). captures[end ]
@@ -207,8 +234,7 @@ function resolve_allocations(call::LLVM.Value)
207234 # It is possible for the optimizer to merge multiple distinct `gc_pool_alloc`
208235 # allocations which actually have distinct types, so here we count each type
209236 # tag store as a separate allocation.
210- type_tag = operands (store)[1 ]
211- type = resolve_static_jl_value_t (type_tag)
237+ type = resolve_static_type_tag (operands (store)[1 ])
212238 if type === nothing
213239 type = Any
214240 end
0 commit comments