@@ -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