Merge pull request #7946 from koachan/sparc64-framefixes
SPARCv9: Handle various stack frame related quirks.
This commit is contained in:
@@ -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.
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user