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 {...@@ -360,14 +360,24 @@ pub const StackIterator = struct {
360 };360 };
361 }361 }
362362
363 // Negative offset of the saved BP wrt the frame pointer.363 // Offset of the saved BP wrt the frame pointer.
364 const fp_offset = if (builtin.arch.isRISCV())364 const fp_offset = if (builtin.arch.isRISCV())
365 // On RISC-V the frame pointer points to the top of the saved register365 // On RISC-V the frame pointer points to the top of the saved register
366 // area, on pretty much every other architecture it points to the stack366 // area, on pretty much every other architecture it points to the stack
367 // slot where the previous frame pointer is saved.367 // slot where the previous frame pointer is saved.
368 2 * @sizeOf(usize)368 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)
369 else372 else
370 0;373 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
371 // Positive offset of the saved PC wrt the frame pointer.381 // Positive offset of the saved PC wrt the frame pointer.
372 const pc_offset = if (builtin.arch == .powerpc64le)382 const pc_offset = if (builtin.arch == .powerpc64le)
373 2 * @sizeOf(usize)383 2 * @sizeOf(usize)
...@@ -388,13 +398,17 @@ pub const StackIterator = struct {...@@ -388,13 +398,17 @@ pub const StackIterator = struct {
388 }398 }
389399
390 fn next_internal(self: *StackIterator) ?usize {400 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
393 // Sanity check.407 // Sanity check.
394 if (fp == 0 or !mem.isAligned(fp, @alignOf(usize)))408 if (fp == 0 or !mem.isAligned(fp, @alignOf(usize)))
395 return null;409 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
399 // Sanity check: the stack grows down thus all the parent frames must be413 // Sanity check: the stack grows down thus all the parent frames must be
400 // be at addresses that are greater (or equal) than the previous one.414 // 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) {...@@ -4153,7 +4153,15 @@ static LLVMValueRef gen_frame_size(CodeGen *g, LLVMValueRef fn_val) {
4153 LLVMValueRef casted_fn_val = LLVMBuildBitCast(g->builder, fn_val, ptr_usize_llvm_type, "");4153 LLVMValueRef casted_fn_val = LLVMBuildBitCast(g->builder, fn_val, ptr_usize_llvm_type, "");
4154 LLVMValueRef negative_one = LLVMConstInt(LLVMInt32Type(), -1, true);4154 LLVMValueRef negative_one = LLVMConstInt(LLVMInt32Type(), -1, true);
4155 LLVMValueRef prefix_ptr = LLVMBuildInBoundsGEP(g->builder, casted_fn_val, &negative_one, 1, "");4155 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;
4157}4165}
41584166
4159static void gen_init_stack_trace(CodeGen *g, LLVMValueRef trace_field_ptr, LLVMValueRef addrs_field_ptr) {4167static void gen_init_stack_trace(CodeGen *g, LLVMValueRef trace_field_ptr, LLVMValueRef addrs_field_ptr) {