feat(asm): emit the riscv64 stack-split guard and fix large-frame addressing
This commit is contained in:
+19
-6
@@ -15,14 +15,16 @@ import (
|
||||
func assembleRISCV(t *ast.Text) ([]byte, map[string]int, []Reloc, []LineEntry, []SpadjStep, error) {
|
||||
fi := riscvComputeFrame(t)
|
||||
prologue := riscvPrologue(fi)
|
||||
guardLen := riscvGuardLen(fi)
|
||||
|
||||
var relocs []Reloc
|
||||
var spadj []SpadjStep
|
||||
|
||||
// The prologue raises the SP delta by autosize; the boundary is reported
|
||||
// at the pc just past its ADDI, exactly as the toolchain's pctospadj does.
|
||||
// The guard prefix shifts its PC.
|
||||
if fi.autosize != 0 {
|
||||
spadj = append(spadj, SpadjStep{PC: riscvPrologueSpadjPC(fi), Value: fi.autosize})
|
||||
spadj = append(spadj, SpadjStep{PC: guardLen + riscvPrologueSpadjPC(fi), Value: fi.autosize})
|
||||
}
|
||||
|
||||
// Pass 1: collect instructions and compute label offsets assuming 4 bytes
|
||||
@@ -34,7 +36,7 @@ func assembleRISCV(t *ast.Text) ([]byte, map[string]int, []Reloc, []LineEntry, [
|
||||
}
|
||||
var recs []instrRec
|
||||
offsets := map[string]int{}
|
||||
pos := len(prologue)
|
||||
pos := guardLen + len(prologue)
|
||||
for _, stmt := range t.Body {
|
||||
switch s := stmt.(type) {
|
||||
case *ast.Label:
|
||||
@@ -66,7 +68,7 @@ func assembleRISCV(t *ast.Text) ([]byte, map[string]int, []Reloc, []LineEntry, [
|
||||
|
||||
// Pass 4: recompute offsets with actual sizes.
|
||||
offsets = map[string]int{}
|
||||
pos = len(prologue)
|
||||
pos = guardLen + len(prologue)
|
||||
for _, stmt := range t.Body {
|
||||
switch s := stmt.(type) {
|
||||
case *ast.Label:
|
||||
@@ -82,9 +84,17 @@ func assembleRISCV(t *ast.Text) ([]byte, map[string]int, []Reloc, []LineEntry, [
|
||||
}
|
||||
|
||||
// Pass 5: re-encode branches with corrected offsets. Record relocations
|
||||
// during this final pass (relocation offsets are relative to instruction start).
|
||||
out := append([]byte(nil), prologue...)
|
||||
pc = len(prologue)
|
||||
// during this final pass (relocation offsets are relative to instruction
|
||||
// start). The guard prefix precedes the prologue; its branches target
|
||||
// the morestack block at the end of the function, which the previous
|
||||
// passes have sized.
|
||||
var out []byte
|
||||
guardBytes, guardReloc := riscvGuard(fi)
|
||||
if fi.needSplit {
|
||||
out = append(out, guardBytes...)
|
||||
}
|
||||
out = append(out, prologue...)
|
||||
pc = guardLen + len(prologue)
|
||||
preCount := len(relocs)
|
||||
var lines []LineEntry
|
||||
for _, r := range recs {
|
||||
@@ -119,6 +129,9 @@ func assembleRISCV(t *ast.Text) ([]byte, map[string]int, []Reloc, []LineEntry, [
|
||||
pc += len(code)
|
||||
}
|
||||
}
|
||||
if fi.needSplit {
|
||||
relocs = append(relocs, guardReloc)
|
||||
}
|
||||
return out, offsets, relocs, lines, spadj, nil
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user