cmd/compile: extract function for splitting up x:(Foo) in rewrite rule fragments
We had three implementations.
Refactor, and document the shared implementation.
While we're here, improve the docs for func unbalanced.
Change-Id: I612cce79de15a864247afe377d3739d04a56b9bc
Reviewed-on: https://go-review.googlesource.com/c/go/+/216219
Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
Reviewed-by: Daniel Martà <mvdan@mvdan.cc>
diff --git a/src/cmd/compile/internal/ssa/gen/rulegen.go b/src/cmd/compile/internal/ssa/gen/rulegen.go
index b25f52a..f1cfa18 100644
--- a/src/cmd/compile/internal/ssa/gen/rulegen.go
+++ b/src/cmd/compile/internal/ssa/gen/rulegen.go
@@ -1059,13 +1059,9 @@
continue
}
// compound sexpr
- argname := fmt.Sprintf("%s_%d", v, i)
- colon := strings.Index(arg, ":")
- openparen := strings.Index(arg, "(")
- if colon >= 0 && openparen >= 0 && colon < openparen {
- // rule-specified name
- argname = arg[:colon]
- arg = arg[colon+1:]
+ argname, expr := splitNameExpr(arg)
+ if argname == "" {
+ argname = fmt.Sprintf("%s_%d", v, i)
}
if argname == "b" {
log.Fatalf("don't name args 'b', it is ambiguous with blocks")
@@ -1076,7 +1072,7 @@
}
bexpr := exprf("%s.Op != addLater", argname)
rr.add(&CondBreak{expr: bexpr})
- argPos, argCheckOp := genMatch0(rr, arch, arg, argname, cnt, false)
+ argPos, argCheckOp := genMatch0(rr, arch, expr, argname, cnt, false)
bexpr.(*ast.BinaryExpr).Y.(*ast.Ident).Name = argCheckOp
if argPos != "" {
@@ -1326,6 +1322,26 @@
return
}
+// splitNameExpr splits s-expr arg, possibly prefixed by "name:",
+// into name and the unprefixed expression.
+// For example, "x:(Foo)" yields "x", "(Foo)",
+// and "(Foo)" yields "", "(Foo)".
+func splitNameExpr(arg string) (name, expr string) {
+ colon := strings.Index(arg, ":")
+ if colon < 0 {
+ return "", arg
+ }
+ openparen := strings.Index(arg, "(")
+ if openparen < 0 {
+ log.Fatalf("splitNameExpr(%q): colon but no open parens", arg)
+ }
+ if colon > openparen {
+ // colon is inside the parens, such as in "(Foo x:(Bar))".
+ return "", arg
+ }
+ return arg[:colon], arg[colon+1:]
+}
+
func getBlockInfo(op string, arch arch) (name string, data blockData) {
for _, b := range genericBlocks {
if b.name == op {
@@ -1358,7 +1374,7 @@
}
}
-// unbalanced reports whether there aren't the same number of ( and ) in the string.
+// unbalanced reports whether there are a different number of ( and ) in the string.
func unbalanced(s string) bool {
balance := 0
for _, c := range s {
@@ -1467,14 +1483,14 @@
return
}
// Split up input.
- if i := strings.Index(m, ":"); i >= 0 && token.IsIdentifier(m[:i]) {
- cnt[m[:i]]++
- m = m[i+1:]
+ name, expr := splitNameExpr(m)
+ if name != "" {
+ cnt[name]++
}
- if m[0] != '(' || m[len(m)-1] != ')' {
- log.Fatalf("non-compound expr in commute1: %q", m)
+ if expr[0] != '(' || expr[len(expr)-1] != ')' {
+ log.Fatalf("non-compound expr in commute1: %q", expr)
}
- s := split(m[1 : len(m)-1])
+ s := split(expr[1 : len(expr)-1])
for _, arg := range s[1:] {
varCount1(arg, cnt)
}
@@ -1527,12 +1543,8 @@
s := new(strings.Builder)
fmt.Fprintf(s, "%s <%s> [%s] {%s}", op, typ, auxint, aux)
for _, arg := range args {
- var prefix string
- if i := strings.Index(arg, ":"); i >= 0 && token.IsIdentifier(arg[:i]) {
- prefix = arg[:i+1]
- arg = arg[i+1:]
- }
- fmt.Fprint(s, " ", prefix, normalizeMatch(arg, arch))
+ prefix, expr := splitNameExpr(arg)
+ fmt.Fprint(s, " ", prefix, normalizeMatch(expr, arch))
}
return s.String()
}