case '5':
if !arch.ARMConditionCodes(prog, cond) {
p.errorf("unrecognized condition code .%q", cond)
+ return
}
case '7':
if !arch.ARM64Suffix(prog, cond) {
p.errorf("unrecognized suffix .%q", cond)
+ return
}
default:
p.errorf("unrecognized suffix .%q", cond)
+ return
}
}
if p.firstProg == nil {
for _, label := range p.pendingLabels {
if p.labels[label] != nil {
p.errorf("label %q multiply defined", label)
+ return
}
p.labels[label] = prog
}
func (p *Parser) validateSymbol(pseudo string, addr *obj.Addr, offsetOk bool) {
if addr.Name != obj.NAME_EXTERN && addr.Name != obj.NAME_STATIC || addr.Scale != 0 || addr.Reg != 0 {
p.errorf("%s symbol %q must be a symbol(SB)", pseudo, symbolName(addr))
- }
- if !offsetOk && addr.Offset != 0 {
+ } else if !offsetOk && addr.Offset != 0 {
p.errorf("%s symbol %q must not be offset from SB", pseudo, symbolName(addr))
}
}
// There is an argument size. It must be a minus sign followed by a non-negative integer literal.
if len(op) != 2 || op[0].ScanToken != '-' || op[1].ScanToken != scanner.Int {
p.errorf("TEXT %s: argument size must be of form -integer", name)
+ return
}
argSize = p.positiveAtoi(op[1].String())
}
// OK
default:
p.errorf("DATA value must be an immediate constant or address")
+ return
}
// The addresses must not overlap. Easiest test: require monotonicity.
if lastAddr, ok := p.dataAddr[name]; ok && nameAddr.Offset < lastAddr {
p.errorf("overlapping DATA entry for %s", name)
+ return
}
p.dataAddr[name] = nameAddr.Offset + int64(scale)
reg, ok := p.arch.RegisterNumber("R", int16(reg))
if !ok {
p.errorf("bad register number %d", reg)
+ return
}
prog.Reg = reg
break
prog.To = a[0]
default:
p.errorf("cannot assemble jump %+v", target)
+ return
}
p.append(prog, cond, true)
targetProg := p.labels[patch.label]
if targetProg == nil {
p.errorf("undefined label %s", patch.label)
- } else {
- p.branch(patch.prog, targetProg)
+ return
}
+ p.branch(patch.prog, targetProg)
}
p.toPatch = p.toPatch[:0]
}
break
}
p.errorf("unrecognized addressing for %s", obj.Aconv(op))
+ return
}
if arch.IsARMFloatCmp(op) {
prog.From = a[0]
prog.To = a[1]
if a[2].Type != obj.TYPE_REG {
p.errorf("invalid addressing modes for third operand to %s instruction, must be register", obj.Aconv(op))
+ return
}
prog.RegTo2 = a[2].Reg
break
prog.To = a[2]
default:
p.errorf("invalid addressing modes for %s instruction", obj.Aconv(op))
+ return
}
default:
p.errorf("TODO: implement three-operand instructions for this architecture")
+ return
}
case 4:
if p.arch.Thechar == '5' && arch.IsARMMULA(op) {
break
}
p.errorf("can't handle %s instruction with 4 operands", obj.Aconv(op))
+ return
case 5:
if p.arch.Thechar == '9' && arch.IsPPC64RLD(op) {
// Always reg, reg, con, con, reg. (con, con is a 'mask').
break
}
p.errorf("can't handle %s instruction with 5 operands", obj.Aconv(op))
+ return
case 6:
if p.arch.Thechar == '5' && arch.IsARMMRC(op) {
// Strange special case: MCR, MRC.
fallthrough
default:
p.errorf("can't handle %s instruction with %d operands", obj.Aconv(op), len(a))
+ return
}
p.append(prog, cond, true)
// Remember this location so we can swap the operands below.
if colon >= 0 {
p.errorf("invalid ':' in operand")
+ return true
}
colon = len(operands)
}
case scanner.Int, scanner.Float, scanner.String, scanner.Char, '+', '-', '~':
haveConstant = true
case '(':
- // Could be parenthesized expression or (R).
- rname := p.next().String()
+ // Could be parenthesized expression or (R). Must be something, though.
+ tok := p.next()
+ if tok.ScanToken == scanner.EOF {
+ p.errorf("missing right parenthesis")
+ return false
+ }
+ rname := tok.String()
p.back()
haveConstant = !p.atStartOfRegister(rname)
if !haveConstant {
if p.have(scanner.String) {
if prefix != '$' {
p.errorf("string constant must be an immediate")
+ return false
}
str, err := strconv.Unquote(p.get(scanner.String).String())
if err != nil {
}
func (p *Parser) back() {
- p.inputPos--
+ if p.inputPos == 0 {
+ p.errorf("internal error: backing up before BOL")
+ } else {
+ p.inputPos--
+ }
}
func (p *Parser) peek() lex.ScanToken {
{"TEXT", "%", "expect two or three operands for TEXT"},
{"TEXT", "1, 1", "TEXT symbol \"<erroneous symbol>\" must be a symbol(SB)"},
{"TEXT", "$\"foo\", 0, $1", "TEXT symbol \"<erroneous symbol>\" must be a symbol(SB)"},
+ {"TEXT", "$0É:0, 0, $1", "expected EOF, found É"}, // Issue #12467.
+ {"TEXT", "$:0:(SB, 0, $1", "expected '(', found 0"}, // Issue 12468.
{"FUNCDATA", "", "expect two operands for FUNCDATA"},
{"FUNCDATA", "(SB ", "expect two operands for FUNCDATA"},
{"DATA", "", "expect two operands for DATA"},