Merge pull request #7946 from koachan/sparc64-framefixes

SPARCv9: Handle various stack frame related quirks.
This commit is contained in:
Andrew Kelley
2021-03-01 19:10:36 -08:00
committed by GitHub
2 changed files with 26 additions and 4 deletions

View File

@@ -360,14 +360,24 @@ pub const StackIterator = struct {
};
}
// Negative offset of the saved BP wrt the frame pointer.
// Offset of the saved BP wrt the frame pointer.
const fp_offset = if (builtin.arch.isRISCV())
// On RISC-V the frame pointer points to the top of the saved register
// area, on pretty much every other architecture it points to the stack
// slot where the previous frame pointer is saved.
2 * @sizeOf(usize)
else if (builtin.arch.isSPARC())
// On SPARC the previous frame pointer is stored at 14 slots past %fp+BIAS.
14 * @sizeOf(usize)
else
0;
const fp_bias = if (builtin.arch.isSPARC())
// On SPARC frame pointers are biased by a constant.
2047
else
0;
// Positive offset of the saved PC wrt the frame pointer.
const pc_offset = if (builtin.arch == .powerpc64le)
2 * @sizeOf(usize)
@@ -388,13 +398,17 @@ pub const StackIterator = struct {
}
fn next_internal(self: *StackIterator) ?usize {
const fp = math.sub(usize, self.fp, fp_offset) catch return null;
const fp = if (builtin.arch.isSPARC())
// On SPARC the offset is positive. (!)
math.add(usize, self.fp, fp_offset) catch return null
else
math.sub(usize, self.fp, fp_offset) catch return null;
// Sanity check.
if (fp == 0 or !mem.isAligned(fp, @alignOf(usize)))
return null;
const new_fp = @intToPtr(*const usize, fp).*;
const new_fp = math.add(usize, @intToPtr(*const usize, fp).*, fp_bias) catch return null;
// Sanity check: the stack grows down thus all the parent frames must be
// be at addresses that are greater (or equal) than the previous one.

View File

@@ -4153,7 +4153,15 @@ static LLVMValueRef gen_frame_size(CodeGen *g, LLVMValueRef fn_val) {
LLVMValueRef casted_fn_val = LLVMBuildBitCast(g->builder, fn_val, ptr_usize_llvm_type, "");
LLVMValueRef negative_one = LLVMConstInt(LLVMInt32Type(), -1, true);
LLVMValueRef prefix_ptr = LLVMBuildInBoundsGEP(g->builder, casted_fn_val, &negative_one, 1, "");
return LLVMBuildLoad(g->builder, prefix_ptr, "");
LLVMValueRef load_inst = LLVMBuildLoad(g->builder, prefix_ptr, "");
// Some architectures (e.g SPARCv9) has different alignment requirements between a
// function/usize pointer and also require all loads to be aligned.
// On those architectures, not explicitly setting the alignment will lead into @frameSize
// generating usize-aligned load instruction that could crash if the function pointer
// happens to be not usize-aligned.
LLVMSetAlignment(load_inst, 1);
return load_inst;
}
static void gen_init_stack_trace(CodeGen *g, LLVMValueRef trace_field_ptr, LLVMValueRef addrs_field_ptr) {