feat(asm): emit RISC-V GOOBJ with the shared emitter

Assisted-by: DeepSeek V4 Pro
This commit is contained in:
2026-08-13 12:07:29 +02:00
parent 31ee8e7941
commit 9b5c878f9e
9 changed files with 358 additions and 383 deletions
+15 -14
View File
@@ -91,9 +91,12 @@ func assembleRISCV(t *ast.Text) ([]byte, map[string]int, []Reloc, error) {
code = []byte{byte(c16), byte(c16 >> 8)}
}
// Make newly added relocation offsets absolute (subtract prologue to make
// them function-relative, then the caller adds fn.Offset).
// them function-relative, then the caller adds fn.Offset). After
// points just past the AUIPC+second-instruction pair, which is
// always 8 bytes wide for these static-symbol references.
for j := preCount; j < len(relocs); j++ {
relocs[j].Off += pc - len(prologue)
relocs[j].After = relocs[j].Off + 8
}
preCount = len(relocs)
out = append(out, code...)
@@ -608,39 +611,37 @@ func encodeRISCVLoadImm(rd int, imm int32) []byte {
}
// encodeRISCVSBAddr emits AUIPC + ADDI to load the address of a static
// symbol into rd. Records R_RISCV_PCREL_HI20 + R_RISCV_PCREL_LO12_I relocs.
// symbol into rd, recording the single R_RISCV_PCREL_ITYPE relocation the Go
// toolchain uses for the pair (the object-file emitters expand or map it).
func encodeRISCVSBAddr(sym *ast.Symbol, rd int, relocs *[]Reloc) []byte {
name := sym.Name
if relocs != nil {
*relocs = append(*relocs, Reloc{Off: 0, After: 0, Name: name, Kind: RelPCRelHI20})
*relocs = append(*relocs, Reloc{Off: 4, After: 4, Name: name, Kind: RelPCRelLO12})
*relocs = append(*relocs, Reloc{Off: 0, After: 8, Name: name, Kind: RelRISCVPCRELIType, Addend: sym.Offset})
}
auipc := riscvUType(riscvEnc{0x17, 0x0, 0x00}, rd, 0)
addi := riscvIType(riscvEnc{0x13, 0x0, 0x00}, rd, rd, 0)
return append(wordLE(auipc), wordLE(addi)...)
}
// encodeRISCVSBLoad emits AUIPC + LD to load from a static symbol into rd.
// Records R_RISCV_PCREL_HI20 + R_RISCV_PCREL_LO12_I relocs.
// encodeRISCVSBLoad emits AUIPC + LD to load from a static symbol into rd,
// recording the single R_RISCV_PCREL_ITYPE relocation for the pair.
func encodeRISCVSBLoad(sym *ast.Symbol, rd int, relocs *[]Reloc) []byte {
name := sym.Name
if relocs != nil {
*relocs = append(*relocs, Reloc{Off: 0, After: 0, Name: name, Kind: RelPCRelHI20})
*relocs = append(*relocs, Reloc{Off: 4, After: 4, Name: name, Kind: RelPCRelLO12})
*relocs = append(*relocs, Reloc{Off: 0, After: 8, Name: name, Kind: RelRISCVPCRELIType, Addend: sym.Offset})
}
auipc := riscvUType(riscvEnc{0x17, 0x0, 0x00}, rd, 0)
ld := riscvIType(riscvEnc{0x03, 0x3, 0x00}, rd, rd, 0)
return append(wordLE(auipc), wordLE(ld)...)
}
// encodeRISCVSBStore emits AUIPC + SD to store a register into a static symbol.
// Records R_RISCV_PCREL_HI20 + R_RISCV_PCREL_LO12_S relocs.
// encodeRISCVSBStore emits AUIPC + SD to store a register into a static symbol,
// recording the single R_RISCV_PCREL_STYPE relocation for the pair.
func encodeRISCVSBStore(sym *ast.Symbol, rs2 int, relocs *[]Reloc) []byte {
tmp := 31 // X31 = T6
name := sym.Name
if relocs != nil {
*relocs = append(*relocs, Reloc{Off: 0, After: 0, Name: name, Kind: RelPCRelHI20})
*relocs = append(*relocs, Reloc{Off: 4, After: 4, Name: name, Kind: RelPCRelLO12S})
*relocs = append(*relocs, Reloc{Off: 0, After: 8, Name: name, Kind: RelRISCVPCRELSType, Addend: sym.Offset})
}
auipc := riscvUType(riscvEnc{0x17, 0x0, 0x00}, tmp, 0)
sd := riscvSType(riscvEnc{0x23, 0x3, 0x00}, tmp, rs2, 0)
@@ -687,8 +688,8 @@ func tryCompressRVC(instr *ast.Instr, fi riscvFrameInfo) (uint16, bool) {
switch mnem {
case "RET":
// RET = JALR X0, 0(X1) → C.JR RA (CR-type: funct4=0x8, rd=0, rs2=1)
return rvcCR(0x8, 0, 1), true
// RET = JALR X0, 0(X1) → C.JR RA (CR-type: funct4=0x8, rs1=ra, rs2=0).
return rvcCR(0x8, 1, 0), true
case "LD", "MOV":
// LD rd, offset(SP) → C.LDSP when rd≠0 and uimm[8:3] fits.