fix(asm): encode RISC-V CALL sym(SB) as JAL
Assisted-by: DeepSeek V4 Pro
This commit is contained in:
@@ -4,6 +4,7 @@
|
||||
package asm
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"testing"
|
||||
|
||||
"sourcedock.dev/petrbalvin/gasm-devkit/ast"
|
||||
@@ -720,19 +721,43 @@ TEXT ·badfp(SB), NOSPLIT, $0
|
||||
}
|
||||
|
||||
func TestRISCV_CALL(t *testing.T) {
|
||||
// CALL target → AUIPC + JALR (8 bytes).
|
||||
// CALL sym(SB) → JAL X1, sym(SB) with a single R_RISCV_JAL relocation.
|
||||
fn := firstTextRISCV(t, `#include "textflag.h"
|
||||
TEXT ·calltest(SB), NOSPLIT, $0
|
||||
CALL sub
|
||||
done:
|
||||
CALL ext(SB)
|
||||
RET
|
||||
`)
|
||||
code, _, relocs, _, _, err := assembleRISCV(fn)
|
||||
if err != nil {
|
||||
t.Fatalf("assemble: %v", err)
|
||||
}
|
||||
// prologue (8) + JAL (4) + epilogue+JALR (8) = 20
|
||||
if len(code) != 20 {
|
||||
t.Fatalf("expected 20 bytes with CALL sym(SB), got %d", len(code))
|
||||
}
|
||||
if len(relocs) != 1 {
|
||||
t.Fatalf("relocs = %d, want 1", len(relocs))
|
||||
}
|
||||
r := relocs[0]
|
||||
if r.Kind != RelRISCVJal || r.Name != "ext" || r.Off != 8 || r.After != 12 || r.Addend != 0 {
|
||||
t.Errorf("reloc = {kind %v off %d after %d name %q addend %d}", r.Kind, r.Off, r.After, r.Name, r.Addend)
|
||||
}
|
||||
// The JAL instruction itself is JAL X1, 0 at function offset 8.
|
||||
wantJAL := wordLE(riscvJType(1, 0))
|
||||
if !bytes.Equal(code[8:12], wantJAL) {
|
||||
t.Errorf("JAL = % x, want % x", code[8:12], wantJAL)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRISCV_CALL_local_error(t *testing.T) {
|
||||
fn := firstTextRISCV(t, `#include "textflag.h"
|
||||
TEXT ·calllocal(SB), NOSPLIT, $0
|
||||
CALL sub
|
||||
sub:
|
||||
RET
|
||||
`)
|
||||
code := assembleRISCVHelper(t, fn)
|
||||
// A zero-frame non-leaf function saves LR: prologue (8) + CALL (8) +
|
||||
// two framed RETs (8 each) = 32.
|
||||
if len(code) != 32 {
|
||||
t.Errorf("expected 32 bytes with CALL, got %d", len(code))
|
||||
_, _, _, _, _, err := assembleRISCV(fn)
|
||||
if err == nil {
|
||||
t.Error("expected error for CALL to local label, got nil")
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user