isFuncSym := strings.HasSuffix(test.input, "(SB)") &&
// Ignore static symbols.
- !strings.Contains(test.input, "<>") &&
- // Ignore symbols with offsets.
- !strings.Contains(test.input, "+")
+ !strings.Contains(test.input, "<>")
wantName := ""
if isFuncSym {
- // Strip $|* and (SB).
+ // Strip $|* and (SB) and +Int.
wantName = test.output[:len(test.output)-4]
if strings.HasPrefix(wantName, "$") || strings.HasPrefix(wantName, "*") {
wantName = wantName[1:]
}
+ if i := strings.Index(wantName, "+"); i >= 0 {
+ wantName = wantName[:i]
+ }
}
if ok != isFuncSym || name != wantName {
t.Errorf("fail at %s as function address: got %s, %v; expected %s, %v", test.input, name, ok, wantName, isFuncSym)
// funcAddress parses an external function address. This is a
// constrained form of the operand syntax that's always SB-based,
-// non-static, and has no additional offsets:
+// non-static, and has at most a simple integer offset:
//
-// [$|*]sym(SB)
+// [$|*]sym[+Int](SB)
func (p *Parser) funcAddress() (string, bool) {
switch p.peek() {
case '$', '*':
if tok.ScanToken != scanner.Ident || p.atStartOfRegister(name) {
return "", false
}
- if p.next().ScanToken != '(' {
+ tok = p.next()
+ if tok.ScanToken == '+' {
+ if p.next().ScanToken != scanner.Int {
+ return "", false
+ }
+ tok = p.next()
+ }
+ if tok.ScanToken != '(' {
return "", false
}
if reg := p.next(); reg.ScanToken != scanner.Ident || reg.String() != "SB" {