feat(parser): read the TEXT and GLOBL operands the toolchain counts them

Assisted-by: GLM 5.3 Flash
This commit is contained in:
petrbalvin committed 2026-10-07 21:50:20 +02:00
1 parent cea5db6964
commit 431d0d9b0b
3 files changed
+262 -31

No files matched your search

+31 -16
View File
@@ -251,22 +251,35 @@ func (p *state) parseText(line []token.Token) {
text.Name = sym
rest = rest[n:]
// Consume the flags operand: everything between the symbol and the
// frame '$' is one operand, which the toolchain evaluates to a single
// integer (identifiers joined by '|', each a known textflag.h name,
// literals and constant arithmetic beside them). A single trailing
// comma is the separator that stood before the '$'.
// The tail splits into the toolchain's comma-separated operands: with
// two, the first is the flags expression and the last the frame; with
// three or more, the toolchain's own complaint. One operand is the
// frame alone, whatever it starts with, so a malformed frame takes the
// frame diagnostic and never reads as flags.
rest = skipComma(rest)
text.Flags, text.FlagVal = p.evalFlags(flagsRun(rest), false)
for len(rest) > 0 && rest[0].Kind != token.Dollar {
rest = rest[1:]
ops := splitOperands(rest)
var frame []token.Token
switch {
case len(ops) >= 2:
text.Flags, text.FlagVal = p.evalFlags(flagsRun(ops[0]), false)
frame = ops[1]
if len(ops) > 2 {
p.errorf(line[0].Pos, "expect two or three operands for TEXT")
}
case len(ops) == 1:
frame = ops[0]
}
if len(frame) > 0 && frame[0].Kind != token.Dollar {
p.errorf(line[0].Pos, "TEXT frame size must be an immediate constant")
frame = nil
}
// Frame: $[-]number ; optional args: -number. The Go runtime writes
// zero frames with an explicit sign ("$-0-24"), so the number may carry
// one. Whatever remains after the header is the body and is parsed by
// the caller.
if len(rest) > 0 && rest[0].Kind == token.Dollar {
if len(frame) > 0 && frame[0].Kind == token.Dollar {
rest = frame
n := 1
neg := false
if n < len(rest) && (rest[n].Kind == token.Minus || rest[n].Kind == token.Plus) {
@@ -337,13 +350,15 @@ func (p *state) parseGlobl(line []token.Token) *ast.Globl {
// operand as one constant expression, so every name is validated here
// and the whole operand folds to g.FlagVal; Flags keeps the atoms as
// written, the numeric spellings being data-side combinations the
// link layer reads back.
g.Flags, g.FlagVal = p.evalFlags(flagsRun(rest), true)
for i, t := range rest {
if t.Kind == token.Dollar {
g.Size = parseOperand(rest[i:], false)
break
}
// link layer reads back. The size is the last operand; a third
// operand's excess is the toolchain's own silence.
ops := splitOperands(rest)
switch {
case len(ops) >= 2:
g.Flags, g.FlagVal = p.evalFlags(flagsRun(ops[0]), true)
g.Size = parseOperand(ops[1], false)
case len(ops) == 1:
g.Size = parseOperand(ops[0], false)
}
return g
}