@@ -258,3 +258,58 @@ let code = """
258258 @test occursin (" InterpreterIP in top-level CodeInfo for Main.A" , bt_str)
259259end
260260
261+ """
262+ withalloca(f, nbytes)
263+
264+ Call function `f` with a `ptr::Ptr{Cvoid}` pointing to `nbytes` bytes of a
265+ stack-allocated memory region.
266+
267+ NOTE: `f` and all functions reachable from `f` must not contain a yield point.
268+ """
269+ function withalloca (f, nbytes)
270+ function wrapper (int)
271+ f (Ptr {Cvoid} (int))
272+ nothing
273+ end
274+ closure = @cfunction ($ wrapper, Cvoid, (UInt64,))
275+ GC. @preserve closure begin
276+ Base. llvmcall (
277+ (
278+ """
279+ define void @entry(i64 %0, i64 %1) {
280+ top:
281+ %aptr = alloca i64, i64 %1
282+ %aint = ptrtoint i64* %aptr to i64
283+ %fptr = inttoptr i64 %0 to void (i64)*
284+ call void %fptr(i64 %aint)
285+ ret void
286+ }
287+ """ ,
288+ " entry" ,
289+ ),
290+ Cvoid,
291+ Tuple{Ptr{Cvoid},Int64},
292+ Base. unsafe_convert (Ptr{Cvoid}, closure),
293+ nbytes,
294+ )
295+ end
296+ end
297+
298+ function sandwiched_backtrace ()
299+ local ptr1, ptr2, bt
300+ withalloca (16 ) do p1
301+ ptr1 = p1
302+ bt = ccall (:jl_backtrace_from_here , Ref{Base. SimpleVector}, (Cint, Cint), true , 0 )
303+ withalloca (16 ) do p2
304+ ptr2 = p2
305+ end
306+ end
307+ return ptr1, ptr2, bt
308+ end
309+
310+ @testset " stack pointers" begin
311+ ptr1, ptr2, bt_data = sandwiched_backtrace ()
312+ sp = Base. _reformat_sp (bt_data... )
313+ @test ptr2 < sp[1 ] < ptr1
314+ @test all (diff (Int128 .(UInt .(sp))) .> 0 )
315+ end
0 commit comments