inline fn init(opt_context_ptr: ?CpuContextPtr) StackIterator opt_context_ptr: ?CpuContextPtr954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988 inline fn init(opt_context_ptr: ?CpuContextPtr) StackIterator {
if (opt_context_ptr) |context_ptr| {
// Use `ctx_first` here so we report the PC in the context before unwinding any further.
return .{ .ctx_first = context_ptr };
}
// Otherwise, we're going to capture the current context or frame address, so we don't need
// `ctx_first`, because the first PC is in `std.debug` and we need to unwind before reaching
// a frame we want to report.
// Workaround the C backend being unable to use inline assembly on MSVC by disabling the
// call to `current`. This effectively constrains stack trace collection and dumping to FP
// unwinding when building with CBE for MSVC.
if (!(builtin.zig_backend == .stage2_c and builtin.target.abi == .msvc) and
SelfInfo != void and
SelfInfo.can_unwind and
cpu_context.Native != noreturn and
fp_usability != .ideal)
{
return .{ .di = .init(&.current()) };
}
return .{
// On SPARC, the frame pointer will point to the previous frame's save area,
// meaning we will read the previous return address and thus miss a frame.
// Instead, start at the stack pointer so we get the return address from the
// current frame's save area. The addition of the stack bias cannot fail here
// since we know we have a valid stack pointer.
.fp = if (native_arch.isSPARC()) sp: {
flushSparcWindows();
break :sp asm (""
: [_] "={o6}" (-> usize),
) + stack_bias;
} else @frameAddress(),
};
}