authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-03-01 19:10:36-08:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2021-03-01 19:10:36-08:00
logf9c9b9217551b98a1d25ff6462c035b8d3a99fe1
treeb6d6c9254b8f0e3d13e95ec565f6153a8f5c3c52
parenta20169a610b693794756bbc0139f0955c1294b48
parent448a28325c7517e6cd62ba7932a4b6c836250757
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #7946 from koachan/sparc64-framefixes

SPARCv9: Handle various stack frame related quirks.

2 files changed, 26 insertions(+), 4 deletions(-)

lib/std/debug.zig+17-3
......@@ -360,14 +360,24 @@ pub const StackIterator = struct {
360360 };
361361 }
362362
363 // Negative offset of the saved BP wrt the frame pointer.
363 // Offset of the saved BP wrt the frame pointer.
364364 const fp_offset = if (builtin.arch.isRISCV())
365365 // On RISC-V the frame pointer points to the top of the saved register
366366 // area, on pretty much every other architecture it points to the stack
367367 // slot where the previous frame pointer is saved.
368368 2 * @sizeOf(usize)
369 else if (builtin.arch.isSPARC())
370 // On SPARC the previous frame pointer is stored at 14 slots past %fp+BIAS.
371 14 * @sizeOf(usize)
369372 else
370373 0;
374
375 const fp_bias = if (builtin.arch.isSPARC())
376 // On SPARC frame pointers are biased by a constant.
377 2047
378 else
379 0;
380
371381 // Positive offset of the saved PC wrt the frame pointer.
372382 const pc_offset = if (builtin.arch == .powerpc64le)
373383 2 * @sizeOf(usize)
......@@ -388,13 +398,17 @@ pub const StackIterator = struct {
388398 }
389399
390400 fn next_internal(self: *StackIterator) ?usize {
391 const fp = math.sub(usize, self.fp, fp_offset) catch return null;
401 const fp = if (builtin.arch.isSPARC())
402 // On SPARC the offset is positive. (!)
403 math.add(usize, self.fp, fp_offset) catch return null
404 else
405 math.sub(usize, self.fp, fp_offset) catch return null;
392406
393407 // Sanity check.
394408 if (fp == 0 or !mem.isAligned(fp, @alignOf(usize)))
395409 return null;
396410
397 const new_fp = @intToPtr(*const usize, fp).*;
411 const new_fp = math.add(usize, @intToPtr(*const usize, fp).*, fp_bias) catch return null;
398412
399413 // Sanity check: the stack grows down thus all the parent frames must be
400414 // be at addresses that are greater (or equal) than the previous one.
src/stage1/codegen.cpp+9-1
......@@ -4153,7 +4153,15 @@ static LLVMValueRef gen_frame_size(CodeGen *g, LLVMValueRef fn_val) {
41534153 LLVMValueRef casted_fn_val = LLVMBuildBitCast(g->builder, fn_val, ptr_usize_llvm_type, "");
41544154 LLVMValueRef negative_one = LLVMConstInt(LLVMInt32Type(), -1, true);
41554155 LLVMValueRef prefix_ptr = LLVMBuildInBoundsGEP(g->builder, casted_fn_val, &negative_one, 1, "");
4156 return LLVMBuildLoad(g->builder, prefix_ptr, "");
4156 LLVMValueRef load_inst = LLVMBuildLoad(g->builder, prefix_ptr, "");
4157
4158 // Some architectures (e.g SPARCv9) has different alignment requirements between a
4159 // function/usize pointer and also require all loads to be aligned.
4160 // On those architectures, not explicitly setting the alignment will lead into @frameSize
4161 // generating usize-aligned load instruction that could crash if the function pointer
4162 // happens to be not usize-aligned.
4163 LLVMSetAlignment(load_inst, 1);
4164 return load_inst;
41574165}
41584166
41594167static void gen_init_stack_trace(CodeGen *g, LLVMValueRef trace_field_ptr, LLVMValueRef addrs_field_ptr) {