@@ -258,3 +258,88 @@ let code = """
258258 @test occursin (" InterpreterIP in top-level CodeInfo for Main.A" , bt_str)
259259end
260260
261+ """
262+ _reformat_sp(bt_data...) -> sp::Vector{Ptr{Cvoid}}
263+
264+ Convert the output `bt_data` of `jl_backtrace_from_here` with `returnsp` flag set to a
265+ vector of valid stack pointers `sp`; i.e., `sp` is a subset of `bt_data[3]`.
266+
267+ See also `Base._reformat_bt`.
268+ """
269+ function _reformat_sp (
270+ bt_raw:: Array{Ptr{Cvoid},1} ,
271+ bt2:: Array{Any,1} ,
272+ sp_raw:: Array{Ptr{Cvoid},1} ,
273+ )
274+ bt = Base. _reformat_bt (bt_raw, bt2)
275+ sp = empty! (similar (sp_raw))
276+ i = j = 0
277+ while true
278+ # Advance `i` such that `bt[i] isa Ptr{Cvoid}` (native pointer).
279+ local ip
280+ while true
281+ if i == lastindex (bt)
282+ return sp
283+ end
284+ i += 1
285+ x = bt[i]
286+ if x isa Ptr{Cvoid}
287+ ip = x
288+ break
289+ end
290+ end
291+ # Advance `j` such that `bt_raw[j] == bt[i]` to find a valid stack pointer.
292+ while true
293+ if j == lastindex (bt_raw)
294+ return sp
295+ end
296+ j += 1
297+ if bt_raw[j] == ip
298+ push! (sp, sp_raw[j])
299+ break
300+ end
301+ end
302+ end
303+ end
304+
305+ """
306+ withframeaddress(f)
307+
308+ Call function `f` with an address `ptr::Ptr{Cvoid}` of an independent frame
309+ immediately outer to `f`.
310+ """
311+ withframeaddress
312+ @eval @noinline function withframeaddress (f)
313+ sp = Core. Intrinsics. llvmcall (
314+ ($ """
315+ declare i8* @llvm.frameaddress(i32)
316+ define private i$(Sys. WORD_SIZE) @frameaddr() {
317+ %1 = call i8* @llvm.frameaddress(i32 0)
318+ %2 = ptrtoint i8* %1 to i$(Sys. WORD_SIZE)
319+ ret i$(Sys. WORD_SIZE) %2
320+ }""" , " frameaddr" ),
321+ UInt,
322+ Tuple{},
323+ )
324+ @noinline f (Ptr {Cvoid} (sp))
325+ end
326+
327+ function sandwiched_backtrace ()
328+ local ptr1, ptr2, bt
329+ withframeaddress () do p1
330+ ptr1 = p1
331+ bt = ccall (:jl_backtrace_from_here , Ref{Base. SimpleVector}, (Cint, Cint), true , 0 )
332+ withframeaddress () do p2
333+ ptr2 = p2
334+ end
335+ end
336+ return ptr1, ptr2, bt
337+ end
338+
339+ @testset " stack pointers" begin
340+ ptr1, ptr2, bt_data = sandwiched_backtrace ()
341+ sp = _reformat_sp (bt_data... )
342+ @test ptr2 < sp[2 ]
343+ @test sp[1 ] < ptr1
344+ @test all (diff (Int128 .(UInt .(sp))) .> 0 )
345+ end
0 commit comments