fix(parser): fold a signed parenthesised displacement expression
Test / test (push) Failing after 2m21s
Test / test (push) Failing after 2m21s
Assisted-by: GLM 5.3 Flash
This commit is contained in:
+64
-6
@@ -5,6 +5,7 @@ package asm
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"sort"
|
||||
"strconv"
|
||||
|
||||
@@ -299,6 +300,10 @@ func AssembleFileRISCV(f *ast.File) (*Image, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// The pooled $i64 constants the wide MOV immediate loads refer to join
|
||||
// the declared data as read-only symbols, deduplicated across the file
|
||||
// (the toolchain synthesises the same symbols into its rodata).
|
||||
litSeen := map[string]bool{}
|
||||
|
||||
img := &Image{Symbols: map[string]int{}, SourcePath: f.Path}
|
||||
for _, d := range f.Decls {
|
||||
@@ -306,10 +311,23 @@ func AssembleFileRISCV(f *ast.File) (*Image, error) {
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
code, labels, relocs, lines, spadj, err := assembleRISCV(t)
|
||||
code, labels, relocs, lines, spadj, lits, err := assembleRISCV(t)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%s: %w", t.Name.Name, err)
|
||||
}
|
||||
for _, lit := range lits {
|
||||
if litSeen[lit.Name] {
|
||||
continue
|
||||
}
|
||||
litSeen[lit.Name] = true
|
||||
dataSyms = append(dataSyms, dataSym{
|
||||
name: lit.Name,
|
||||
buf: lit.Data,
|
||||
size: len(lit.Data),
|
||||
rodata: true,
|
||||
dupok: true,
|
||||
})
|
||||
}
|
||||
fl := FuncLayout{
|
||||
Name: t.Name.Name,
|
||||
Pkg: t.Name.Pkg,
|
||||
@@ -561,11 +579,6 @@ func collectData(f *ast.File) ([]dataSym, error) {
|
||||
return nil, fmt.Errorf("DATA %q: missing value", dd.Name.Name)
|
||||
}
|
||||
w := dd.Width
|
||||
switch w {
|
||||
case 1, 2, 4, 8:
|
||||
default:
|
||||
return nil, fmt.Errorf("DATA %q: invalid width %d (want 1, 2, 4 or 8)", dd.Name.Name, w)
|
||||
}
|
||||
off := dd.Name.Offset
|
||||
buf := syms[i].buf
|
||||
if off < 0 || off+int64(w) > int64(len(buf)) {
|
||||
@@ -587,9 +600,54 @@ func collectData(f *ast.File) ([]dataSym, error) {
|
||||
})
|
||||
continue
|
||||
}
|
||||
// A string or rune value ("DATA s+0(SB)/20, $"text"") writes its
|
||||
// bytes into the field and leaves the rest zero, the toolchain's
|
||||
// WriteString: the declared width must hold every byte, and any
|
||||
// width is legal.
|
||||
if s := dd.Value.Imm.Str; s != "" && !dd.Value.Imm.HasVal {
|
||||
text, err := strconv.Unquote(s)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("DATA %q: invalid string value %s", dd.Name.Name, s)
|
||||
}
|
||||
if len(text) > w {
|
||||
return nil, fmt.Errorf("DATA %q: string of %d bytes does not fit width %d", dd.Name.Name, len(text), w)
|
||||
}
|
||||
copy(buf[off:], text)
|
||||
continue
|
||||
}
|
||||
// A floating-point value stores its IEEE-754 bits: /4 the float32
|
||||
// rounding of the parsed double, /8 the full 64 bits, the
|
||||
// toolchain's WriteFloat32 and WriteFloat64.
|
||||
if f := dd.Value.Imm.Float; f != "" && !dd.Value.Imm.HasVal {
|
||||
num, err := strconv.ParseFloat(f, 64)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("DATA %q: invalid floating-point value %q", dd.Name.Name, f)
|
||||
}
|
||||
if dd.Value.Imm.Neg {
|
||||
num = -num
|
||||
}
|
||||
var v uint64
|
||||
switch w {
|
||||
case 4:
|
||||
v = uint64(math.Float32bits(float32(num)))
|
||||
case 8:
|
||||
v = math.Float64bits(num)
|
||||
default:
|
||||
return nil, fmt.Errorf("DATA %q: invalid width %d for a float (want 4 or 8)", dd.Name.Name, w)
|
||||
}
|
||||
for j := range w {
|
||||
buf[off+int64(j)] = byte(v >> (8 * j))
|
||||
}
|
||||
continue
|
||||
}
|
||||
if !dd.Value.Imm.HasVal {
|
||||
return nil, fmt.Errorf("DATA %q: value must be an integer immediate or a symbol address", dd.Name.Name)
|
||||
}
|
||||
switch w {
|
||||
case 1, 2, 4, 8:
|
||||
default:
|
||||
return nil, fmt.Errorf("DATA %q: invalid width %d (want 1, 2, 4 or 8)", dd.Name.Name, w)
|
||||
}
|
||||
v := dd.Value.Imm.Val
|
||||
if dd.Value.Imm.Neg {
|
||||
v = -v
|
||||
|
||||
Reference in New Issue
Block a user