2015-03-23 17:02:11 -07:00
|
|
|
// Copyright 2015 The Go Authors. All rights reserved.
|
|
|
|
|
// Use of this source code is governed by a BSD-style
|
|
|
|
|
// license that can be found in the LICENSE file.
|
|
|
|
|
|
2016-04-05 15:11:08 +10:00
|
|
|
// +build gen
|
|
|
|
|
|
2015-03-23 17:02:11 -07:00
|
|
|
// This program generates Go code that applies rewrite rules to a Value.
|
|
|
|
|
// The generated code implements a function of type func (v *Value) bool
|
|
|
|
|
// which returns true iff if did something.
|
|
|
|
|
// Ideas stolen from Swift: http://www.hpl.hp.com/techreports/Compaq-DEC/WRL-2000-2.html
|
|
|
|
|
|
|
|
|
|
package main
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"bufio"
|
|
|
|
|
"bytes"
|
2015-08-12 15:39:16 -07:00
|
|
|
"flag"
|
2015-03-23 17:02:11 -07:00
|
|
|
"fmt"
|
|
|
|
|
"go/format"
|
|
|
|
|
"io"
|
2015-03-26 10:49:03 -07:00
|
|
|
"io/ioutil"
|
2015-03-23 17:02:11 -07:00
|
|
|
"log"
|
|
|
|
|
"os"
|
2015-06-11 21:29:25 -07:00
|
|
|
"regexp"
|
2015-03-23 17:02:11 -07:00
|
|
|
"sort"
|
|
|
|
|
"strings"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
// rule syntax:
|
2015-10-13 11:08:08 -07:00
|
|
|
// sexpr [&& extra conditions] -> [@block] sexpr
|
2015-03-23 17:02:11 -07:00
|
|
|
//
|
|
|
|
|
// sexpr are s-expressions (lisp-like parenthesized groupings)
|
2017-03-29 18:06:04 +00:00
|
|
|
// sexpr ::= (opcode sexpr*)
|
2015-03-23 17:02:11 -07:00
|
|
|
// | variable
|
|
|
|
|
// | <type>
|
2015-06-11 21:29:25 -07:00
|
|
|
// | [auxint]
|
|
|
|
|
// | {aux}
|
2015-03-23 17:02:11 -07:00
|
|
|
//
|
|
|
|
|
// aux ::= variable | {code}
|
|
|
|
|
// type ::= variable | {code}
|
|
|
|
|
// variable ::= some token
|
2017-03-29 18:06:04 +00:00
|
|
|
// opcode ::= one of the opcodes from ../op.go (without the Op prefix)
|
2015-03-23 17:02:11 -07:00
|
|
|
|
2016-03-01 23:21:55 +00:00
|
|
|
// extra conditions is just a chunk of Go that evaluates to a boolean. It may use
|
|
|
|
|
// variables declared in the matching sexpr. The variable "v" is predefined to be
|
2015-03-23 17:02:11 -07:00
|
|
|
// the value matched by the entire rule.
|
|
|
|
|
|
|
|
|
|
// If multiple rules match, the first one in file order is selected.
|
|
|
|
|
|
2015-08-12 15:39:16 -07:00
|
|
|
var (
|
|
|
|
|
genLog = flag.Bool("log", false, "generate code that logs; for debugging only")
|
|
|
|
|
)
|
|
|
|
|
|
2015-08-12 13:54:04 -07:00
|
|
|
type Rule struct {
|
2016-04-20 11:17:41 -07:00
|
|
|
rule string
|
|
|
|
|
loc string // file name & line number
|
2015-08-12 13:54:04 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (r Rule) String() string {
|
2016-04-20 11:17:41 -07:00
|
|
|
return fmt.Sprintf("rule %q at %s", r.rule, r.loc)
|
2015-08-12 13:54:04 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// parse returns the matching part of the rule, additional conditions, and the result.
|
|
|
|
|
func (r Rule) parse() (match, cond, result string) {
|
|
|
|
|
s := strings.Split(r.rule, "->")
|
|
|
|
|
if len(s) != 2 {
|
|
|
|
|
log.Fatalf("no arrow in %s", r)
|
|
|
|
|
}
|
|
|
|
|
match = strings.TrimSpace(s[0])
|
|
|
|
|
result = strings.TrimSpace(s[1])
|
|
|
|
|
cond = ""
|
|
|
|
|
if i := strings.Index(match, "&&"); i >= 0 {
|
|
|
|
|
cond = strings.TrimSpace(match[i+2:])
|
|
|
|
|
match = strings.TrimSpace(match[:i])
|
|
|
|
|
}
|
|
|
|
|
return match, cond, result
|
|
|
|
|
}
|
|
|
|
|
|
2015-06-06 16:03:33 -07:00
|
|
|
func genRules(arch arch) {
|
2015-03-23 17:02:11 -07:00
|
|
|
// Open input file.
|
2015-06-06 16:03:33 -07:00
|
|
|
text, err := os.Open(arch.name + ".rules")
|
2015-03-23 17:02:11 -07:00
|
|
|
if err != nil {
|
|
|
|
|
log.Fatalf("can't read rule file: %v", err)
|
|
|
|
|
}
|
|
|
|
|
|
2015-05-28 16:45:33 -07:00
|
|
|
// oprules contains a list of rules for each block and opcode
|
2015-08-12 13:54:04 -07:00
|
|
|
blockrules := map[string][]Rule{}
|
|
|
|
|
oprules := map[string][]Rule{}
|
2015-03-23 17:02:11 -07:00
|
|
|
|
|
|
|
|
// read rule file
|
|
|
|
|
scanner := bufio.NewScanner(text)
|
2015-06-10 10:39:57 -07:00
|
|
|
rule := ""
|
2015-08-12 13:54:04 -07:00
|
|
|
var lineno int
|
2016-04-26 14:09:58 -07:00
|
|
|
var ruleLineno int // line number of "->"
|
2015-03-23 17:02:11 -07:00
|
|
|
for scanner.Scan() {
|
2015-08-12 13:54:04 -07:00
|
|
|
lineno++
|
2015-03-23 17:02:11 -07:00
|
|
|
line := scanner.Text()
|
|
|
|
|
if i := strings.Index(line, "//"); i >= 0 {
|
2016-03-01 23:21:55 +00:00
|
|
|
// Remove comments. Note that this isn't string safe, so
|
|
|
|
|
// it will truncate lines with // inside strings. Oh well.
|
2015-03-23 17:02:11 -07:00
|
|
|
line = line[:i]
|
|
|
|
|
}
|
2015-06-10 10:39:57 -07:00
|
|
|
rule += " " + line
|
|
|
|
|
rule = strings.TrimSpace(rule)
|
|
|
|
|
if rule == "" {
|
2015-03-23 17:02:11 -07:00
|
|
|
continue
|
|
|
|
|
}
|
2015-06-10 10:39:57 -07:00
|
|
|
if !strings.Contains(rule, "->") {
|
|
|
|
|
continue
|
|
|
|
|
}
|
2016-04-26 14:09:58 -07:00
|
|
|
if ruleLineno == 0 {
|
|
|
|
|
ruleLineno = lineno
|
|
|
|
|
}
|
2015-06-10 10:39:57 -07:00
|
|
|
if strings.HasSuffix(rule, "->") {
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
if unbalanced(rule) {
|
|
|
|
|
continue
|
|
|
|
|
}
|
[dev.ssa] cmd/compile: refactor out rulegen value parsing
Previously, genMatch0 and genResult0 contained
lots of duplication: locating the op, parsing
the value, validation, etc.
Parsing and validation was mixed in with code gen.
Extract a helper, parseValue. It is responsible
for parsing the value, locating the op, and doing
shared validation.
As a bonus (and possibly as my original motivation),
make op selection pay attention to the number
of args present.
This allows arch-specific ops to share a name
with generic ops as long as there is no ambiguity.
It also detects and reports unresolved ambiguity,
unlike before, where it would simply always
pick the generic op, with no warning.
Also use parseValue when generating the top-level
op dispatch, to ensure its opinion about ops
matches genMatch0 and genResult0.
The order of statements in the generated code used
to depend on the exact rule. It is now somewhat
independent of the rule. That is the source
of some of the generated code changes in this CL.
See rewritedec64 and rewritegeneric for examples.
It is a one-time change.
The op dispatch switch and functions used to be
sorted by opname without architecture. The sort
now includes the architecture, leading to further
generated code changes.
See rewriteARM and rewriteAMD64 for examples.
Again, it is a one-time change.
There are no functional changes.
Change-Id: I22c989183ad5651741ebdc0566349c5fd6c6b23c
Reviewed-on: https://go-review.googlesource.com/24649
Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: David Chase <drchase@google.com>
Reviewed-by: Keith Randall <khr@golang.org>
2016-07-01 11:05:29 -07:00
|
|
|
|
2016-04-26 14:09:58 -07:00
|
|
|
loc := fmt.Sprintf("%s.rules:%d", arch.name, ruleLineno)
|
2017-03-29 18:06:04 +00:00
|
|
|
r := Rule{rule: rule, loc: loc}
|
|
|
|
|
if rawop := strings.Split(rule, " ")[0][1:]; isBlock(rawop, arch) {
|
|
|
|
|
blockrules[rawop] = append(blockrules[rawop], r)
|
|
|
|
|
} else {
|
|
|
|
|
// Do fancier value op matching.
|
|
|
|
|
match, _, _ := r.parse()
|
|
|
|
|
op, oparch, _, _, _, _ := parseValue(match, arch, loc)
|
|
|
|
|
opname := fmt.Sprintf("Op%s%s", oparch, op.name)
|
|
|
|
|
oprules[opname] = append(oprules[opname], r)
|
2015-05-28 16:45:33 -07:00
|
|
|
}
|
2015-06-10 10:39:57 -07:00
|
|
|
rule = ""
|
2016-04-26 14:09:58 -07:00
|
|
|
ruleLineno = 0
|
2015-03-23 17:02:11 -07:00
|
|
|
}
|
|
|
|
|
if err := scanner.Err(); err != nil {
|
|
|
|
|
log.Fatalf("scanner failed: %v\n", err)
|
|
|
|
|
}
|
2015-08-12 13:54:04 -07:00
|
|
|
if unbalanced(rule) {
|
2016-04-20 11:17:41 -07:00
|
|
|
log.Fatalf("%s.rules:%d: unbalanced rule: %v\n", arch.name, lineno, rule)
|
2015-08-12 13:54:04 -07:00
|
|
|
}
|
2015-03-23 17:02:11 -07:00
|
|
|
|
2015-10-26 21:49:31 -07:00
|
|
|
// Order all the ops.
|
|
|
|
|
var ops []string
|
|
|
|
|
for op := range oprules {
|
|
|
|
|
ops = append(ops, op)
|
|
|
|
|
}
|
|
|
|
|
sort.Strings(ops)
|
|
|
|
|
|
2015-03-23 17:02:11 -07:00
|
|
|
// Start output buffer, write header.
|
|
|
|
|
w := new(bytes.Buffer)
|
2015-06-06 16:03:33 -07:00
|
|
|
fmt.Fprintf(w, "// autogenerated from gen/%s.rules: do not edit!\n", arch.name)
|
|
|
|
|
fmt.Fprintln(w, "// generated with: cd gen; go run *.go")
|
2016-03-01 10:58:06 -08:00
|
|
|
fmt.Fprintln(w)
|
2015-03-23 17:02:11 -07:00
|
|
|
fmt.Fprintln(w, "package ssa")
|
2015-08-28 14:24:10 -04:00
|
|
|
fmt.Fprintln(w, "import \"math\"")
|
2017-01-24 09:48:58 +00:00
|
|
|
fmt.Fprintln(w, "import \"cmd/internal/obj\"")
|
2015-08-28 14:24:10 -04:00
|
|
|
fmt.Fprintln(w, "var _ = math.MinInt8 // in case not otherwise used")
|
2017-01-24 09:48:58 +00:00
|
|
|
fmt.Fprintln(w, "var _ = obj.ANOP // in case not otherwise used")
|
2015-08-28 14:24:10 -04:00
|
|
|
|
2015-10-26 21:49:31 -07:00
|
|
|
// Main rewrite routine is a switch on v.Op.
|
2017-03-17 10:50:20 -07:00
|
|
|
fmt.Fprintf(w, "func rewriteValue%s(v *Value) bool {\n", arch.name)
|
2015-03-23 17:02:11 -07:00
|
|
|
fmt.Fprintf(w, "switch v.Op {\n")
|
|
|
|
|
for _, op := range ops {
|
[dev.ssa] cmd/compile: refactor out rulegen value parsing
Previously, genMatch0 and genResult0 contained
lots of duplication: locating the op, parsing
the value, validation, etc.
Parsing and validation was mixed in with code gen.
Extract a helper, parseValue. It is responsible
for parsing the value, locating the op, and doing
shared validation.
As a bonus (and possibly as my original motivation),
make op selection pay attention to the number
of args present.
This allows arch-specific ops to share a name
with generic ops as long as there is no ambiguity.
It also detects and reports unresolved ambiguity,
unlike before, where it would simply always
pick the generic op, with no warning.
Also use parseValue when generating the top-level
op dispatch, to ensure its opinion about ops
matches genMatch0 and genResult0.
The order of statements in the generated code used
to depend on the exact rule. It is now somewhat
independent of the rule. That is the source
of some of the generated code changes in this CL.
See rewritedec64 and rewritegeneric for examples.
It is a one-time change.
The op dispatch switch and functions used to be
sorted by opname without architecture. The sort
now includes the architecture, leading to further
generated code changes.
See rewriteARM and rewriteAMD64 for examples.
Again, it is a one-time change.
There are no functional changes.
Change-Id: I22c989183ad5651741ebdc0566349c5fd6c6b23c
Reviewed-on: https://go-review.googlesource.com/24649
Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: David Chase <drchase@google.com>
Reviewed-by: Keith Randall <khr@golang.org>
2016-07-01 11:05:29 -07:00
|
|
|
fmt.Fprintf(w, "case %s:\n", op)
|
2017-03-17 10:50:20 -07:00
|
|
|
fmt.Fprintf(w, "return rewriteValue%s_%s(v)\n", arch.name, op)
|
2015-10-26 21:49:31 -07:00
|
|
|
}
|
|
|
|
|
fmt.Fprintf(w, "}\n")
|
|
|
|
|
fmt.Fprintf(w, "return false\n")
|
|
|
|
|
fmt.Fprintf(w, "}\n")
|
|
|
|
|
|
2016-03-01 23:21:55 +00:00
|
|
|
// Generate a routine per op. Note that we don't make one giant routine
|
2015-10-26 21:49:31 -07:00
|
|
|
// because it is too big for some compilers.
|
|
|
|
|
for _, op := range ops {
|
2017-03-17 10:50:20 -07:00
|
|
|
buf := new(bytes.Buffer)
|
2016-04-29 09:02:27 -07:00
|
|
|
var canFail bool
|
|
|
|
|
for i, rule := range oprules[op] {
|
2015-08-12 13:54:04 -07:00
|
|
|
match, cond, result := rule.parse()
|
2017-03-17 10:50:20 -07:00
|
|
|
fmt.Fprintf(buf, "// match: %s\n", match)
|
|
|
|
|
fmt.Fprintf(buf, "// cond: %s\n", cond)
|
|
|
|
|
fmt.Fprintf(buf, "// result: %s\n", result)
|
2015-03-23 17:02:11 -07:00
|
|
|
|
2016-04-29 09:02:27 -07:00
|
|
|
canFail = false
|
2017-03-17 10:50:20 -07:00
|
|
|
fmt.Fprintf(buf, "for {\n")
|
|
|
|
|
if genMatch(buf, arch, match, rule.loc) {
|
2016-04-29 09:02:27 -07:00
|
|
|
canFail = true
|
|
|
|
|
}
|
2015-03-23 17:02:11 -07:00
|
|
|
|
|
|
|
|
if cond != "" {
|
2017-03-17 10:50:20 -07:00
|
|
|
fmt.Fprintf(buf, "if !(%s) {\nbreak\n}\n", cond)
|
2016-04-29 09:02:27 -07:00
|
|
|
canFail = true
|
|
|
|
|
}
|
|
|
|
|
if !canFail && i != len(oprules[op])-1 {
|
|
|
|
|
log.Fatalf("unconditional rule %s is followed by other rules", match)
|
2015-03-23 17:02:11 -07:00
|
|
|
}
|
|
|
|
|
|
2017-03-17 10:50:20 -07:00
|
|
|
genResult(buf, arch, result, rule.loc)
|
2015-08-12 15:39:16 -07:00
|
|
|
if *genLog {
|
2017-03-17 10:50:20 -07:00
|
|
|
fmt.Fprintf(buf, "logRule(\"%s\")\n", rule.loc)
|
2015-08-12 15:39:16 -07:00
|
|
|
}
|
2017-03-17 10:50:20 -07:00
|
|
|
fmt.Fprintf(buf, "return true\n")
|
2015-03-23 17:02:11 -07:00
|
|
|
|
2017-03-17 10:50:20 -07:00
|
|
|
fmt.Fprintf(buf, "}\n")
|
2015-03-23 17:02:11 -07:00
|
|
|
}
|
2016-04-29 09:02:27 -07:00
|
|
|
if canFail {
|
2017-03-17 10:50:20 -07:00
|
|
|
fmt.Fprintf(buf, "return false\n")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
body := buf.String()
|
2017-03-17 16:04:46 -07:00
|
|
|
// Do a rough match to predict whether we need b, config, fe, and/or types.
|
2017-03-17 10:50:20 -07:00
|
|
|
// It's not precise--thus the blank assignments--but it's good enough
|
|
|
|
|
// to avoid generating needless code and doing pointless nil checks.
|
|
|
|
|
hasb := strings.Contains(body, "b.")
|
2017-03-16 22:42:10 -07:00
|
|
|
hasconfig := strings.Contains(body, "config.") || strings.Contains(body, "config)")
|
2017-03-17 10:50:20 -07:00
|
|
|
hasfe := strings.Contains(body, "fe.")
|
2017-03-17 16:04:46 -07:00
|
|
|
hasts := strings.Contains(body, "types.")
|
2017-03-17 10:50:20 -07:00
|
|
|
fmt.Fprintf(w, "func rewriteValue%s_%s(v *Value) bool {\n", arch.name, op)
|
|
|
|
|
if hasb || hasconfig || hasfe {
|
|
|
|
|
fmt.Fprintln(w, "b := v.Block")
|
|
|
|
|
fmt.Fprintln(w, "_ = b")
|
|
|
|
|
}
|
2017-03-16 22:42:10 -07:00
|
|
|
if hasconfig {
|
2017-03-17 10:50:20 -07:00
|
|
|
fmt.Fprintln(w, "config := b.Func.Config")
|
|
|
|
|
fmt.Fprintln(w, "_ = config")
|
|
|
|
|
}
|
|
|
|
|
if hasfe {
|
2017-03-16 22:42:10 -07:00
|
|
|
fmt.Fprintln(w, "fe := b.Func.fe")
|
2017-03-17 10:50:20 -07:00
|
|
|
fmt.Fprintln(w, "_ = fe")
|
|
|
|
|
}
|
2017-03-17 16:04:46 -07:00
|
|
|
if hasts {
|
|
|
|
|
fmt.Fprintln(w, "types := &b.Func.Config.Types")
|
|
|
|
|
fmt.Fprintln(w, "_ = types")
|
|
|
|
|
}
|
2017-03-17 10:50:20 -07:00
|
|
|
fmt.Fprint(w, body)
|
2015-10-26 21:49:31 -07:00
|
|
|
fmt.Fprintf(w, "}\n")
|
2015-03-23 17:02:11 -07:00
|
|
|
}
|
|
|
|
|
|
2016-03-01 23:21:55 +00:00
|
|
|
// Generate block rewrite function. There are only a few block types
|
2015-10-26 21:49:31 -07:00
|
|
|
// so we can make this one function with a switch.
|
2017-03-17 10:50:20 -07:00
|
|
|
fmt.Fprintf(w, "func rewriteBlock%s(b *Block) bool {\n", arch.name)
|
|
|
|
|
fmt.Fprintln(w, "config := b.Func.Config")
|
|
|
|
|
fmt.Fprintln(w, "_ = config")
|
2017-03-16 22:42:10 -07:00
|
|
|
fmt.Fprintln(w, "fe := b.Func.fe")
|
2017-03-17 10:50:20 -07:00
|
|
|
fmt.Fprintln(w, "_ = fe")
|
2017-03-17 16:04:46 -07:00
|
|
|
fmt.Fprintln(w, "types := &config.Types")
|
|
|
|
|
fmt.Fprintln(w, "_ = types")
|
2015-05-28 16:45:33 -07:00
|
|
|
fmt.Fprintf(w, "switch b.Kind {\n")
|
|
|
|
|
ops = nil
|
|
|
|
|
for op := range blockrules {
|
|
|
|
|
ops = append(ops, op)
|
|
|
|
|
}
|
|
|
|
|
sort.Strings(ops)
|
|
|
|
|
for _, op := range ops {
|
2015-06-06 16:03:33 -07:00
|
|
|
fmt.Fprintf(w, "case %s:\n", blockName(op, arch))
|
2015-05-28 16:45:33 -07:00
|
|
|
for _, rule := range blockrules[op] {
|
2015-08-12 13:54:04 -07:00
|
|
|
match, cond, result := rule.parse()
|
2015-05-28 16:45:33 -07:00
|
|
|
fmt.Fprintf(w, "// match: %s\n", match)
|
|
|
|
|
fmt.Fprintf(w, "// cond: %s\n", cond)
|
|
|
|
|
fmt.Fprintf(w, "// result: %s\n", result)
|
|
|
|
|
|
2016-02-04 19:52:10 +01:00
|
|
|
fmt.Fprintf(w, "for {\n")
|
2015-08-12 13:54:04 -07:00
|
|
|
|
|
|
|
|
s := split(match[1 : len(match)-1]) // remove parens, then split
|
2015-05-28 16:45:33 -07:00
|
|
|
|
|
|
|
|
// check match of control value
|
|
|
|
|
if s[1] != "nil" {
|
|
|
|
|
fmt.Fprintf(w, "v := b.Control\n")
|
2016-03-21 16:18:45 -07:00
|
|
|
if strings.Contains(s[1], "(") {
|
2016-04-20 11:17:41 -07:00
|
|
|
genMatch0(w, arch, s[1], "v", map[string]struct{}{}, false, rule.loc)
|
2016-03-21 16:18:45 -07:00
|
|
|
} else {
|
2016-08-19 16:35:36 -04:00
|
|
|
fmt.Fprintf(w, "_ = v\n") // in case we don't use v
|
2016-03-21 16:18:45 -07:00
|
|
|
fmt.Fprintf(w, "%s := b.Control\n", s[1])
|
|
|
|
|
}
|
2015-05-28 16:45:33 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// assign successor names
|
|
|
|
|
succs := s[2:]
|
|
|
|
|
for i, a := range succs {
|
|
|
|
|
if a != "_" {
|
|
|
|
|
fmt.Fprintf(w, "%s := b.Succs[%d]\n", a, i)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if cond != "" {
|
2016-02-04 19:52:10 +01:00
|
|
|
fmt.Fprintf(w, "if !(%s) {\nbreak\n}\n", cond)
|
2015-05-28 16:45:33 -07:00
|
|
|
}
|
|
|
|
|
|
2016-03-01 23:21:55 +00:00
|
|
|
// Rule matches. Generate result.
|
2015-05-28 16:45:33 -07:00
|
|
|
t := split(result[1 : len(result)-1]) // remove parens, then split
|
|
|
|
|
newsuccs := t[2:]
|
|
|
|
|
|
2015-08-28 16:45:17 -07:00
|
|
|
// Check if newsuccs is the same set as succs.
|
2015-05-28 16:45:33 -07:00
|
|
|
m := map[string]bool{}
|
|
|
|
|
for _, succ := range succs {
|
|
|
|
|
if m[succ] {
|
|
|
|
|
log.Fatalf("can't have a repeat successor name %s in %s", succ, rule)
|
|
|
|
|
}
|
|
|
|
|
m[succ] = true
|
|
|
|
|
}
|
|
|
|
|
for _, succ := range newsuccs {
|
|
|
|
|
if !m[succ] {
|
|
|
|
|
log.Fatalf("unknown successor %s in %s", succ, rule)
|
|
|
|
|
}
|
|
|
|
|
delete(m, succ)
|
|
|
|
|
}
|
2015-08-28 16:45:17 -07:00
|
|
|
if len(m) != 0 {
|
|
|
|
|
log.Fatalf("unmatched successors %v in %s", m, rule)
|
|
|
|
|
}
|
2015-05-28 16:45:33 -07:00
|
|
|
|
2015-06-06 16:03:33 -07:00
|
|
|
fmt.Fprintf(w, "b.Kind = %s\n", blockName(t[0], arch))
|
2015-05-28 16:45:33 -07:00
|
|
|
if t[1] == "nil" {
|
2016-03-15 20:45:50 -07:00
|
|
|
fmt.Fprintf(w, "b.SetControl(nil)\n")
|
2015-05-28 16:45:33 -07:00
|
|
|
} else {
|
2016-04-20 11:17:41 -07:00
|
|
|
fmt.Fprintf(w, "b.SetControl(%s)\n", genResult0(w, arch, t[1], new(int), false, false, rule.loc))
|
2015-05-28 16:45:33 -07:00
|
|
|
}
|
2016-04-28 16:52:47 -07:00
|
|
|
|
|
|
|
|
succChanged := false
|
|
|
|
|
for i := 0; i < len(succs); i++ {
|
|
|
|
|
if succs[i] != newsuccs[i] {
|
|
|
|
|
succChanged = true
|
|
|
|
|
}
|
2015-05-28 16:45:33 -07:00
|
|
|
}
|
2016-04-28 16:52:47 -07:00
|
|
|
if succChanged {
|
|
|
|
|
if len(succs) != 2 {
|
|
|
|
|
log.Fatalf("changed successors, len!=2 in %s", rule)
|
|
|
|
|
}
|
|
|
|
|
if succs[0] != newsuccs[1] || succs[1] != newsuccs[0] {
|
|
|
|
|
log.Fatalf("can only handle swapped successors in %s", rule)
|
|
|
|
|
}
|
|
|
|
|
fmt.Fprintln(w, "b.swapSuccessors()")
|
2015-05-28 16:45:33 -07:00
|
|
|
}
|
2016-04-28 16:52:47 -07:00
|
|
|
for i := 0; i < len(succs); i++ {
|
|
|
|
|
fmt.Fprintf(w, "_ = %s\n", newsuccs[i])
|
2015-08-11 17:28:56 -07:00
|
|
|
}
|
2015-05-28 16:45:33 -07:00
|
|
|
|
2015-08-12 15:39:16 -07:00
|
|
|
if *genLog {
|
2016-05-24 15:43:25 -07:00
|
|
|
fmt.Fprintf(w, "logRule(\"%s\")\n", rule.loc)
|
2015-08-12 15:39:16 -07:00
|
|
|
}
|
2015-05-28 16:45:33 -07:00
|
|
|
fmt.Fprintf(w, "return true\n")
|
|
|
|
|
|
|
|
|
|
fmt.Fprintf(w, "}\n")
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
fmt.Fprintf(w, "}\n")
|
|
|
|
|
fmt.Fprintf(w, "return false\n")
|
|
|
|
|
fmt.Fprintf(w, "}\n")
|
|
|
|
|
|
2015-03-23 17:02:11 -07:00
|
|
|
// gofmt result
|
|
|
|
|
b := w.Bytes()
|
2015-08-12 15:39:16 -07:00
|
|
|
src, err := format.Source(b)
|
2015-03-23 17:02:11 -07:00
|
|
|
if err != nil {
|
2015-08-12 15:39:16 -07:00
|
|
|
fmt.Printf("%s\n", b)
|
2015-03-23 17:02:11 -07:00
|
|
|
panic(err)
|
|
|
|
|
}
|
|
|
|
|
|
2015-06-06 16:03:33 -07:00
|
|
|
// Write to file
|
2015-08-12 15:39:16 -07:00
|
|
|
err = ioutil.WriteFile("../rewrite"+arch.name+".go", src, 0666)
|
2015-03-26 10:49:03 -07:00
|
|
|
if err != nil {
|
2015-03-23 17:02:11 -07:00
|
|
|
log.Fatalf("can't write output: %v\n", err)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-04-29 09:02:27 -07:00
|
|
|
// genMatch returns true if the match can fail.
|
|
|
|
|
func genMatch(w io.Writer, arch arch, match string, loc string) bool {
|
|
|
|
|
return genMatch0(w, arch, match, "v", map[string]struct{}{}, true, loc)
|
2015-03-23 17:02:11 -07:00
|
|
|
}
|
|
|
|
|
|
2016-04-29 09:02:27 -07:00
|
|
|
func genMatch0(w io.Writer, arch arch, match, v string, m map[string]struct{}, top bool, loc string) bool {
|
2016-03-21 16:18:45 -07:00
|
|
|
if match[0] != '(' || match[len(match)-1] != ')' {
|
|
|
|
|
panic("non-compound expr in genMatch0: " + match)
|
2015-03-23 17:02:11 -07:00
|
|
|
}
|
2016-04-29 09:02:27 -07:00
|
|
|
canFail := false
|
2015-03-23 17:02:11 -07:00
|
|
|
|
[dev.ssa] cmd/compile: refactor out rulegen value parsing
Previously, genMatch0 and genResult0 contained
lots of duplication: locating the op, parsing
the value, validation, etc.
Parsing and validation was mixed in with code gen.
Extract a helper, parseValue. It is responsible
for parsing the value, locating the op, and doing
shared validation.
As a bonus (and possibly as my original motivation),
make op selection pay attention to the number
of args present.
This allows arch-specific ops to share a name
with generic ops as long as there is no ambiguity.
It also detects and reports unresolved ambiguity,
unlike before, where it would simply always
pick the generic op, with no warning.
Also use parseValue when generating the top-level
op dispatch, to ensure its opinion about ops
matches genMatch0 and genResult0.
The order of statements in the generated code used
to depend on the exact rule. It is now somewhat
independent of the rule. That is the source
of some of the generated code changes in this CL.
See rewritedec64 and rewritegeneric for examples.
It is a one-time change.
The op dispatch switch and functions used to be
sorted by opname without architecture. The sort
now includes the architecture, leading to further
generated code changes.
See rewriteARM and rewriteAMD64 for examples.
Again, it is a one-time change.
There are no functional changes.
Change-Id: I22c989183ad5651741ebdc0566349c5fd6c6b23c
Reviewed-on: https://go-review.googlesource.com/24649
Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: David Chase <drchase@google.com>
Reviewed-by: Keith Randall <khr@golang.org>
2016-07-01 11:05:29 -07:00
|
|
|
op, oparch, typ, auxint, aux, args := parseValue(match, arch, loc)
|
2016-04-20 11:17:41 -07:00
|
|
|
|
2015-03-23 17:02:11 -07:00
|
|
|
// check op
|
|
|
|
|
if !top {
|
[dev.ssa] cmd/compile: refactor out rulegen value parsing
Previously, genMatch0 and genResult0 contained
lots of duplication: locating the op, parsing
the value, validation, etc.
Parsing and validation was mixed in with code gen.
Extract a helper, parseValue. It is responsible
for parsing the value, locating the op, and doing
shared validation.
As a bonus (and possibly as my original motivation),
make op selection pay attention to the number
of args present.
This allows arch-specific ops to share a name
with generic ops as long as there is no ambiguity.
It also detects and reports unresolved ambiguity,
unlike before, where it would simply always
pick the generic op, with no warning.
Also use parseValue when generating the top-level
op dispatch, to ensure its opinion about ops
matches genMatch0 and genResult0.
The order of statements in the generated code used
to depend on the exact rule. It is now somewhat
independent of the rule. That is the source
of some of the generated code changes in this CL.
See rewritedec64 and rewritegeneric for examples.
It is a one-time change.
The op dispatch switch and functions used to be
sorted by opname without architecture. The sort
now includes the architecture, leading to further
generated code changes.
See rewriteARM and rewriteAMD64 for examples.
Again, it is a one-time change.
There are no functional changes.
Change-Id: I22c989183ad5651741ebdc0566349c5fd6c6b23c
Reviewed-on: https://go-review.googlesource.com/24649
Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: David Chase <drchase@google.com>
Reviewed-by: Keith Randall <khr@golang.org>
2016-07-01 11:05:29 -07:00
|
|
|
fmt.Fprintf(w, "if %s.Op != Op%s%s {\nbreak\n}\n", v, oparch, op.name)
|
2016-04-29 09:02:27 -07:00
|
|
|
canFail = true
|
2015-03-23 17:02:11 -07:00
|
|
|
}
|
|
|
|
|
|
[dev.ssa] cmd/compile: refactor out rulegen value parsing
Previously, genMatch0 and genResult0 contained
lots of duplication: locating the op, parsing
the value, validation, etc.
Parsing and validation was mixed in with code gen.
Extract a helper, parseValue. It is responsible
for parsing the value, locating the op, and doing
shared validation.
As a bonus (and possibly as my original motivation),
make op selection pay attention to the number
of args present.
This allows arch-specific ops to share a name
with generic ops as long as there is no ambiguity.
It also detects and reports unresolved ambiguity,
unlike before, where it would simply always
pick the generic op, with no warning.
Also use parseValue when generating the top-level
op dispatch, to ensure its opinion about ops
matches genMatch0 and genResult0.
The order of statements in the generated code used
to depend on the exact rule. It is now somewhat
independent of the rule. That is the source
of some of the generated code changes in this CL.
See rewritedec64 and rewritegeneric for examples.
It is a one-time change.
The op dispatch switch and functions used to be
sorted by opname without architecture. The sort
now includes the architecture, leading to further
generated code changes.
See rewriteARM and rewriteAMD64 for examples.
Again, it is a one-time change.
There are no functional changes.
Change-Id: I22c989183ad5651741ebdc0566349c5fd6c6b23c
Reviewed-on: https://go-review.googlesource.com/24649
Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: David Chase <drchase@google.com>
Reviewed-by: Keith Randall <khr@golang.org>
2016-07-01 11:05:29 -07:00
|
|
|
if typ != "" {
|
|
|
|
|
if !isVariable(typ) {
|
|
|
|
|
// code. We must match the results of this code.
|
|
|
|
|
fmt.Fprintf(w, "if %s.Type != %s {\nbreak\n}\n", v, typ)
|
|
|
|
|
canFail = true
|
|
|
|
|
} else {
|
|
|
|
|
// variable
|
|
|
|
|
if _, ok := m[typ]; ok {
|
|
|
|
|
// must match previous variable
|
|
|
|
|
fmt.Fprintf(w, "if %s.Type != %s {\nbreak\n}\n", v, typ)
|
2016-04-29 09:02:27 -07:00
|
|
|
canFail = true
|
2015-03-23 17:02:11 -07:00
|
|
|
} else {
|
[dev.ssa] cmd/compile: refactor out rulegen value parsing
Previously, genMatch0 and genResult0 contained
lots of duplication: locating the op, parsing
the value, validation, etc.
Parsing and validation was mixed in with code gen.
Extract a helper, parseValue. It is responsible
for parsing the value, locating the op, and doing
shared validation.
As a bonus (and possibly as my original motivation),
make op selection pay attention to the number
of args present.
This allows arch-specific ops to share a name
with generic ops as long as there is no ambiguity.
It also detects and reports unresolved ambiguity,
unlike before, where it would simply always
pick the generic op, with no warning.
Also use parseValue when generating the top-level
op dispatch, to ensure its opinion about ops
matches genMatch0 and genResult0.
The order of statements in the generated code used
to depend on the exact rule. It is now somewhat
independent of the rule. That is the source
of some of the generated code changes in this CL.
See rewritedec64 and rewritegeneric for examples.
It is a one-time change.
The op dispatch switch and functions used to be
sorted by opname without architecture. The sort
now includes the architecture, leading to further
generated code changes.
See rewriteARM and rewriteAMD64 for examples.
Again, it is a one-time change.
There are no functional changes.
Change-Id: I22c989183ad5651741ebdc0566349c5fd6c6b23c
Reviewed-on: https://go-review.googlesource.com/24649
Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: David Chase <drchase@google.com>
Reviewed-by: Keith Randall <khr@golang.org>
2016-07-01 11:05:29 -07:00
|
|
|
m[typ] = struct{}{}
|
|
|
|
|
fmt.Fprintf(w, "%s := %s.Type\n", typ, v)
|
2015-03-23 17:02:11 -07:00
|
|
|
}
|
[dev.ssa] cmd/compile: refactor out rulegen value parsing
Previously, genMatch0 and genResult0 contained
lots of duplication: locating the op, parsing
the value, validation, etc.
Parsing and validation was mixed in with code gen.
Extract a helper, parseValue. It is responsible
for parsing the value, locating the op, and doing
shared validation.
As a bonus (and possibly as my original motivation),
make op selection pay attention to the number
of args present.
This allows arch-specific ops to share a name
with generic ops as long as there is no ambiguity.
It also detects and reports unresolved ambiguity,
unlike before, where it would simply always
pick the generic op, with no warning.
Also use parseValue when generating the top-level
op dispatch, to ensure its opinion about ops
matches genMatch0 and genResult0.
The order of statements in the generated code used
to depend on the exact rule. It is now somewhat
independent of the rule. That is the source
of some of the generated code changes in this CL.
See rewritedec64 and rewritegeneric for examples.
It is a one-time change.
The op dispatch switch and functions used to be
sorted by opname without architecture. The sort
now includes the architecture, leading to further
generated code changes.
See rewriteARM and rewriteAMD64 for examples.
Again, it is a one-time change.
There are no functional changes.
Change-Id: I22c989183ad5651741ebdc0566349c5fd6c6b23c
Reviewed-on: https://go-review.googlesource.com/24649
Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: David Chase <drchase@google.com>
Reviewed-by: Keith Randall <khr@golang.org>
2016-07-01 11:05:29 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if auxint != "" {
|
|
|
|
|
if !isVariable(auxint) {
|
|
|
|
|
// code
|
|
|
|
|
fmt.Fprintf(w, "if %s.AuxInt != %s {\nbreak\n}\n", v, auxint)
|
|
|
|
|
canFail = true
|
|
|
|
|
} else {
|
|
|
|
|
// variable
|
|
|
|
|
if _, ok := m[auxint]; ok {
|
|
|
|
|
fmt.Fprintf(w, "if %s.AuxInt != %s {\nbreak\n}\n", v, auxint)
|
2016-04-29 09:02:27 -07:00
|
|
|
canFail = true
|
2015-06-11 21:29:25 -07:00
|
|
|
} else {
|
[dev.ssa] cmd/compile: refactor out rulegen value parsing
Previously, genMatch0 and genResult0 contained
lots of duplication: locating the op, parsing
the value, validation, etc.
Parsing and validation was mixed in with code gen.
Extract a helper, parseValue. It is responsible
for parsing the value, locating the op, and doing
shared validation.
As a bonus (and possibly as my original motivation),
make op selection pay attention to the number
of args present.
This allows arch-specific ops to share a name
with generic ops as long as there is no ambiguity.
It also detects and reports unresolved ambiguity,
unlike before, where it would simply always
pick the generic op, with no warning.
Also use parseValue when generating the top-level
op dispatch, to ensure its opinion about ops
matches genMatch0 and genResult0.
The order of statements in the generated code used
to depend on the exact rule. It is now somewhat
independent of the rule. That is the source
of some of the generated code changes in this CL.
See rewritedec64 and rewritegeneric for examples.
It is a one-time change.
The op dispatch switch and functions used to be
sorted by opname without architecture. The sort
now includes the architecture, leading to further
generated code changes.
See rewriteARM and rewriteAMD64 for examples.
Again, it is a one-time change.
There are no functional changes.
Change-Id: I22c989183ad5651741ebdc0566349c5fd6c6b23c
Reviewed-on: https://go-review.googlesource.com/24649
Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: David Chase <drchase@google.com>
Reviewed-by: Keith Randall <khr@golang.org>
2016-07-01 11:05:29 -07:00
|
|
|
m[auxint] = struct{}{}
|
|
|
|
|
fmt.Fprintf(w, "%s := %s.AuxInt\n", auxint, v)
|
2015-06-11 21:29:25 -07:00
|
|
|
}
|
[dev.ssa] cmd/compile: refactor out rulegen value parsing
Previously, genMatch0 and genResult0 contained
lots of duplication: locating the op, parsing
the value, validation, etc.
Parsing and validation was mixed in with code gen.
Extract a helper, parseValue. It is responsible
for parsing the value, locating the op, and doing
shared validation.
As a bonus (and possibly as my original motivation),
make op selection pay attention to the number
of args present.
This allows arch-specific ops to share a name
with generic ops as long as there is no ambiguity.
It also detects and reports unresolved ambiguity,
unlike before, where it would simply always
pick the generic op, with no warning.
Also use parseValue when generating the top-level
op dispatch, to ensure its opinion about ops
matches genMatch0 and genResult0.
The order of statements in the generated code used
to depend on the exact rule. It is now somewhat
independent of the rule. That is the source
of some of the generated code changes in this CL.
See rewritedec64 and rewritegeneric for examples.
It is a one-time change.
The op dispatch switch and functions used to be
sorted by opname without architecture. The sort
now includes the architecture, leading to further
generated code changes.
See rewriteARM and rewriteAMD64 for examples.
Again, it is a one-time change.
There are no functional changes.
Change-Id: I22c989183ad5651741ebdc0566349c5fd6c6b23c
Reviewed-on: https://go-review.googlesource.com/24649
Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: David Chase <drchase@google.com>
Reviewed-by: Keith Randall <khr@golang.org>
2016-07-01 11:05:29 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if aux != "" {
|
|
|
|
|
|
|
|
|
|
if !isVariable(aux) {
|
|
|
|
|
// code
|
|
|
|
|
fmt.Fprintf(w, "if %s.Aux != %s {\nbreak\n}\n", v, aux)
|
|
|
|
|
canFail = true
|
|
|
|
|
} else {
|
|
|
|
|
// variable
|
|
|
|
|
if _, ok := m[aux]; ok {
|
|
|
|
|
fmt.Fprintf(w, "if %s.Aux != %s {\nbreak\n}\n", v, aux)
|
2016-04-29 09:02:27 -07:00
|
|
|
canFail = true
|
2015-03-23 17:02:11 -07:00
|
|
|
} else {
|
[dev.ssa] cmd/compile: refactor out rulegen value parsing
Previously, genMatch0 and genResult0 contained
lots of duplication: locating the op, parsing
the value, validation, etc.
Parsing and validation was mixed in with code gen.
Extract a helper, parseValue. It is responsible
for parsing the value, locating the op, and doing
shared validation.
As a bonus (and possibly as my original motivation),
make op selection pay attention to the number
of args present.
This allows arch-specific ops to share a name
with generic ops as long as there is no ambiguity.
It also detects and reports unresolved ambiguity,
unlike before, where it would simply always
pick the generic op, with no warning.
Also use parseValue when generating the top-level
op dispatch, to ensure its opinion about ops
matches genMatch0 and genResult0.
The order of statements in the generated code used
to depend on the exact rule. It is now somewhat
independent of the rule. That is the source
of some of the generated code changes in this CL.
See rewritedec64 and rewritegeneric for examples.
It is a one-time change.
The op dispatch switch and functions used to be
sorted by opname without architecture. The sort
now includes the architecture, leading to further
generated code changes.
See rewriteARM and rewriteAMD64 for examples.
Again, it is a one-time change.
There are no functional changes.
Change-Id: I22c989183ad5651741ebdc0566349c5fd6c6b23c
Reviewed-on: https://go-review.googlesource.com/24649
Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: David Chase <drchase@google.com>
Reviewed-by: Keith Randall <khr@golang.org>
2016-07-01 11:05:29 -07:00
|
|
|
m[aux] = struct{}{}
|
|
|
|
|
fmt.Fprintf(w, "%s := %s.Aux\n", aux, v)
|
2015-03-23 17:02:11 -07:00
|
|
|
}
|
[dev.ssa] cmd/compile: refactor out rulegen value parsing
Previously, genMatch0 and genResult0 contained
lots of duplication: locating the op, parsing
the value, validation, etc.
Parsing and validation was mixed in with code gen.
Extract a helper, parseValue. It is responsible
for parsing the value, locating the op, and doing
shared validation.
As a bonus (and possibly as my original motivation),
make op selection pay attention to the number
of args present.
This allows arch-specific ops to share a name
with generic ops as long as there is no ambiguity.
It also detects and reports unresolved ambiguity,
unlike before, where it would simply always
pick the generic op, with no warning.
Also use parseValue when generating the top-level
op dispatch, to ensure its opinion about ops
matches genMatch0 and genResult0.
The order of statements in the generated code used
to depend on the exact rule. It is now somewhat
independent of the rule. That is the source
of some of the generated code changes in this CL.
See rewritedec64 and rewritegeneric for examples.
It is a one-time change.
The op dispatch switch and functions used to be
sorted by opname without architecture. The sort
now includes the architecture, leading to further
generated code changes.
See rewriteARM and rewriteAMD64 for examples.
Again, it is a one-time change.
There are no functional changes.
Change-Id: I22c989183ad5651741ebdc0566349c5fd6c6b23c
Reviewed-on: https://go-review.googlesource.com/24649
Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: David Chase <drchase@google.com>
Reviewed-by: Keith Randall <khr@golang.org>
2016-07-01 11:05:29 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for i, arg := range args {
|
|
|
|
|
if arg == "_" {
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
if !strings.Contains(arg, "(") {
|
2016-03-21 16:18:45 -07:00
|
|
|
// leaf variable
|
[dev.ssa] cmd/compile: refactor out rulegen value parsing
Previously, genMatch0 and genResult0 contained
lots of duplication: locating the op, parsing
the value, validation, etc.
Parsing and validation was mixed in with code gen.
Extract a helper, parseValue. It is responsible
for parsing the value, locating the op, and doing
shared validation.
As a bonus (and possibly as my original motivation),
make op selection pay attention to the number
of args present.
This allows arch-specific ops to share a name
with generic ops as long as there is no ambiguity.
It also detects and reports unresolved ambiguity,
unlike before, where it would simply always
pick the generic op, with no warning.
Also use parseValue when generating the top-level
op dispatch, to ensure its opinion about ops
matches genMatch0 and genResult0.
The order of statements in the generated code used
to depend on the exact rule. It is now somewhat
independent of the rule. That is the source
of some of the generated code changes in this CL.
See rewritedec64 and rewritegeneric for examples.
It is a one-time change.
The op dispatch switch and functions used to be
sorted by opname without architecture. The sort
now includes the architecture, leading to further
generated code changes.
See rewriteARM and rewriteAMD64 for examples.
Again, it is a one-time change.
There are no functional changes.
Change-Id: I22c989183ad5651741ebdc0566349c5fd6c6b23c
Reviewed-on: https://go-review.googlesource.com/24649
Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: David Chase <drchase@google.com>
Reviewed-by: Keith Randall <khr@golang.org>
2016-07-01 11:05:29 -07:00
|
|
|
if _, ok := m[arg]; ok {
|
2016-03-21 16:18:45 -07:00
|
|
|
// variable already has a definition. Check whether
|
|
|
|
|
// the old definition and the new definition match.
|
|
|
|
|
// For example, (add x x). Equality is just pointer equality
|
|
|
|
|
// on Values (so cse is important to do before lowering).
|
[dev.ssa] cmd/compile: refactor out rulegen value parsing
Previously, genMatch0 and genResult0 contained
lots of duplication: locating the op, parsing
the value, validation, etc.
Parsing and validation was mixed in with code gen.
Extract a helper, parseValue. It is responsible
for parsing the value, locating the op, and doing
shared validation.
As a bonus (and possibly as my original motivation),
make op selection pay attention to the number
of args present.
This allows arch-specific ops to share a name
with generic ops as long as there is no ambiguity.
It also detects and reports unresolved ambiguity,
unlike before, where it would simply always
pick the generic op, with no warning.
Also use parseValue when generating the top-level
op dispatch, to ensure its opinion about ops
matches genMatch0 and genResult0.
The order of statements in the generated code used
to depend on the exact rule. It is now somewhat
independent of the rule. That is the source
of some of the generated code changes in this CL.
See rewritedec64 and rewritegeneric for examples.
It is a one-time change.
The op dispatch switch and functions used to be
sorted by opname without architecture. The sort
now includes the architecture, leading to further
generated code changes.
See rewriteARM and rewriteAMD64 for examples.
Again, it is a one-time change.
There are no functional changes.
Change-Id: I22c989183ad5651741ebdc0566349c5fd6c6b23c
Reviewed-on: https://go-review.googlesource.com/24649
Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: David Chase <drchase@google.com>
Reviewed-by: Keith Randall <khr@golang.org>
2016-07-01 11:05:29 -07:00
|
|
|
fmt.Fprintf(w, "if %s != %s.Args[%d] {\nbreak\n}\n", arg, v, i)
|
2016-04-29 09:02:27 -07:00
|
|
|
canFail = true
|
2016-03-21 16:18:45 -07:00
|
|
|
} else {
|
|
|
|
|
// remember that this variable references the given value
|
[dev.ssa] cmd/compile: refactor out rulegen value parsing
Previously, genMatch0 and genResult0 contained
lots of duplication: locating the op, parsing
the value, validation, etc.
Parsing and validation was mixed in with code gen.
Extract a helper, parseValue. It is responsible
for parsing the value, locating the op, and doing
shared validation.
As a bonus (and possibly as my original motivation),
make op selection pay attention to the number
of args present.
This allows arch-specific ops to share a name
with generic ops as long as there is no ambiguity.
It also detects and reports unresolved ambiguity,
unlike before, where it would simply always
pick the generic op, with no warning.
Also use parseValue when generating the top-level
op dispatch, to ensure its opinion about ops
matches genMatch0 and genResult0.
The order of statements in the generated code used
to depend on the exact rule. It is now somewhat
independent of the rule. That is the source
of some of the generated code changes in this CL.
See rewritedec64 and rewritegeneric for examples.
It is a one-time change.
The op dispatch switch and functions used to be
sorted by opname without architecture. The sort
now includes the architecture, leading to further
generated code changes.
See rewriteARM and rewriteAMD64 for examples.
Again, it is a one-time change.
There are no functional changes.
Change-Id: I22c989183ad5651741ebdc0566349c5fd6c6b23c
Reviewed-on: https://go-review.googlesource.com/24649
Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: David Chase <drchase@google.com>
Reviewed-by: Keith Randall <khr@golang.org>
2016-07-01 11:05:29 -07:00
|
|
|
m[arg] = struct{}{}
|
|
|
|
|
fmt.Fprintf(w, "%s := %s.Args[%d]\n", arg, v, i)
|
2016-03-21 16:18:45 -07:00
|
|
|
}
|
[dev.ssa] cmd/compile: refactor out rulegen value parsing
Previously, genMatch0 and genResult0 contained
lots of duplication: locating the op, parsing
the value, validation, etc.
Parsing and validation was mixed in with code gen.
Extract a helper, parseValue. It is responsible
for parsing the value, locating the op, and doing
shared validation.
As a bonus (and possibly as my original motivation),
make op selection pay attention to the number
of args present.
This allows arch-specific ops to share a name
with generic ops as long as there is no ambiguity.
It also detects and reports unresolved ambiguity,
unlike before, where it would simply always
pick the generic op, with no warning.
Also use parseValue when generating the top-level
op dispatch, to ensure its opinion about ops
matches genMatch0 and genResult0.
The order of statements in the generated code used
to depend on the exact rule. It is now somewhat
independent of the rule. That is the source
of some of the generated code changes in this CL.
See rewritedec64 and rewritegeneric for examples.
It is a one-time change.
The op dispatch switch and functions used to be
sorted by opname without architecture. The sort
now includes the architecture, leading to further
generated code changes.
See rewriteARM and rewriteAMD64 for examples.
Again, it is a one-time change.
There are no functional changes.
Change-Id: I22c989183ad5651741ebdc0566349c5fd6c6b23c
Reviewed-on: https://go-review.googlesource.com/24649
Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: David Chase <drchase@google.com>
Reviewed-by: Keith Randall <khr@golang.org>
2016-07-01 11:05:29 -07:00
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
// compound sexpr
|
|
|
|
|
var argname string
|
|
|
|
|
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:]
|
2015-03-23 17:02:11 -07:00
|
|
|
} else {
|
[dev.ssa] cmd/compile: refactor out rulegen value parsing
Previously, genMatch0 and genResult0 contained
lots of duplication: locating the op, parsing
the value, validation, etc.
Parsing and validation was mixed in with code gen.
Extract a helper, parseValue. It is responsible
for parsing the value, locating the op, and doing
shared validation.
As a bonus (and possibly as my original motivation),
make op selection pay attention to the number
of args present.
This allows arch-specific ops to share a name
with generic ops as long as there is no ambiguity.
It also detects and reports unresolved ambiguity,
unlike before, where it would simply always
pick the generic op, with no warning.
Also use parseValue when generating the top-level
op dispatch, to ensure its opinion about ops
matches genMatch0 and genResult0.
The order of statements in the generated code used
to depend on the exact rule. It is now somewhat
independent of the rule. That is the source
of some of the generated code changes in this CL.
See rewritedec64 and rewritegeneric for examples.
It is a one-time change.
The op dispatch switch and functions used to be
sorted by opname without architecture. The sort
now includes the architecture, leading to further
generated code changes.
See rewriteARM and rewriteAMD64 for examples.
Again, it is a one-time change.
There are no functional changes.
Change-Id: I22c989183ad5651741ebdc0566349c5fd6c6b23c
Reviewed-on: https://go-review.googlesource.com/24649
Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: David Chase <drchase@google.com>
Reviewed-by: Keith Randall <khr@golang.org>
2016-07-01 11:05:29 -07:00
|
|
|
// autogenerated name
|
|
|
|
|
argname = fmt.Sprintf("%s_%d", v, i)
|
|
|
|
|
}
|
|
|
|
|
fmt.Fprintf(w, "%s := %s.Args[%d]\n", argname, v, i)
|
|
|
|
|
if genMatch0(w, arch, arg, argname, m, false, loc) {
|
|
|
|
|
canFail = true
|
2015-03-23 17:02:11 -07:00
|
|
|
}
|
|
|
|
|
}
|
[dev.ssa] cmd/compile: refactor out rulegen value parsing
Previously, genMatch0 and genResult0 contained
lots of duplication: locating the op, parsing
the value, validation, etc.
Parsing and validation was mixed in with code gen.
Extract a helper, parseValue. It is responsible
for parsing the value, locating the op, and doing
shared validation.
As a bonus (and possibly as my original motivation),
make op selection pay attention to the number
of args present.
This allows arch-specific ops to share a name
with generic ops as long as there is no ambiguity.
It also detects and reports unresolved ambiguity,
unlike before, where it would simply always
pick the generic op, with no warning.
Also use parseValue when generating the top-level
op dispatch, to ensure its opinion about ops
matches genMatch0 and genResult0.
The order of statements in the generated code used
to depend on the exact rule. It is now somewhat
independent of the rule. That is the source
of some of the generated code changes in this CL.
See rewritedec64 and rewritegeneric for examples.
It is a one-time change.
The op dispatch switch and functions used to be
sorted by opname without architecture. The sort
now includes the architecture, leading to further
generated code changes.
See rewriteARM and rewriteAMD64 for examples.
Again, it is a one-time change.
There are no functional changes.
Change-Id: I22c989183ad5651741ebdc0566349c5fd6c6b23c
Reviewed-on: https://go-review.googlesource.com/24649
Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: David Chase <drchase@google.com>
Reviewed-by: Keith Randall <khr@golang.org>
2016-07-01 11:05:29 -07:00
|
|
|
|
2016-04-20 11:17:41 -07:00
|
|
|
if op.argLength == -1 {
|
[dev.ssa] cmd/compile: refactor out rulegen value parsing
Previously, genMatch0 and genResult0 contained
lots of duplication: locating the op, parsing
the value, validation, etc.
Parsing and validation was mixed in with code gen.
Extract a helper, parseValue. It is responsible
for parsing the value, locating the op, and doing
shared validation.
As a bonus (and possibly as my original motivation),
make op selection pay attention to the number
of args present.
This allows arch-specific ops to share a name
with generic ops as long as there is no ambiguity.
It also detects and reports unresolved ambiguity,
unlike before, where it would simply always
pick the generic op, with no warning.
Also use parseValue when generating the top-level
op dispatch, to ensure its opinion about ops
matches genMatch0 and genResult0.
The order of statements in the generated code used
to depend on the exact rule. It is now somewhat
independent of the rule. That is the source
of some of the generated code changes in this CL.
See rewritedec64 and rewritegeneric for examples.
It is a one-time change.
The op dispatch switch and functions used to be
sorted by opname without architecture. The sort
now includes the architecture, leading to further
generated code changes.
See rewriteARM and rewriteAMD64 for examples.
Again, it is a one-time change.
There are no functional changes.
Change-Id: I22c989183ad5651741ebdc0566349c5fd6c6b23c
Reviewed-on: https://go-review.googlesource.com/24649
Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: David Chase <drchase@google.com>
Reviewed-by: Keith Randall <khr@golang.org>
2016-07-01 11:05:29 -07:00
|
|
|
fmt.Fprintf(w, "if len(%s.Args) != %d {\nbreak\n}\n", v, len(args))
|
2016-04-29 09:02:27 -07:00
|
|
|
canFail = true
|
2016-02-09 19:46:26 +01:00
|
|
|
}
|
2016-04-29 09:02:27 -07:00
|
|
|
return canFail
|
2015-03-23 17:02:11 -07:00
|
|
|
}
|
|
|
|
|
|
2016-04-20 11:17:41 -07:00
|
|
|
func genResult(w io.Writer, arch arch, result string, loc string) {
|
2016-02-24 10:29:27 -08:00
|
|
|
move := false
|
2015-10-13 11:08:08 -07:00
|
|
|
if result[0] == '@' {
|
|
|
|
|
// parse @block directive
|
|
|
|
|
s := strings.SplitN(result[1:], " ", 2)
|
2016-02-24 10:29:27 -08:00
|
|
|
fmt.Fprintf(w, "b = %s\n", s[0])
|
2015-10-13 11:08:08 -07:00
|
|
|
result = s[1]
|
2016-02-24 10:29:27 -08:00
|
|
|
move = true
|
2015-10-13 11:08:08 -07:00
|
|
|
}
|
2016-04-20 11:17:41 -07:00
|
|
|
genResult0(w, arch, result, new(int), true, move, loc)
|
2015-03-23 17:02:11 -07:00
|
|
|
}
|
2016-04-20 11:17:41 -07:00
|
|
|
func genResult0(w io.Writer, arch arch, result string, alloc *int, top, move bool, loc string) string {
|
2016-02-28 15:51:11 -08:00
|
|
|
// TODO: when generating a constant result, use f.constVal to avoid
|
|
|
|
|
// introducing copies just to clean them up again.
|
2015-03-23 17:02:11 -07:00
|
|
|
if result[0] != '(' {
|
|
|
|
|
// variable
|
2015-05-18 16:44:20 -07:00
|
|
|
if top {
|
2015-08-05 10:33:09 -07:00
|
|
|
// It in not safe in general to move a variable between blocks
|
|
|
|
|
// (and particularly not a phi node).
|
|
|
|
|
// Introduce a copy.
|
2016-02-04 17:21:57 +01:00
|
|
|
fmt.Fprintf(w, "v.reset(OpCopy)\n")
|
2015-08-05 10:33:09 -07:00
|
|
|
fmt.Fprintf(w, "v.Type = %s.Type\n", result)
|
|
|
|
|
fmt.Fprintf(w, "v.AddArg(%s)\n", result)
|
2015-05-18 16:44:20 -07:00
|
|
|
}
|
2015-03-23 17:02:11 -07:00
|
|
|
return result
|
|
|
|
|
}
|
|
|
|
|
|
[dev.ssa] cmd/compile: refactor out rulegen value parsing
Previously, genMatch0 and genResult0 contained
lots of duplication: locating the op, parsing
the value, validation, etc.
Parsing and validation was mixed in with code gen.
Extract a helper, parseValue. It is responsible
for parsing the value, locating the op, and doing
shared validation.
As a bonus (and possibly as my original motivation),
make op selection pay attention to the number
of args present.
This allows arch-specific ops to share a name
with generic ops as long as there is no ambiguity.
It also detects and reports unresolved ambiguity,
unlike before, where it would simply always
pick the generic op, with no warning.
Also use parseValue when generating the top-level
op dispatch, to ensure its opinion about ops
matches genMatch0 and genResult0.
The order of statements in the generated code used
to depend on the exact rule. It is now somewhat
independent of the rule. That is the source
of some of the generated code changes in this CL.
See rewritedec64 and rewritegeneric for examples.
It is a one-time change.
The op dispatch switch and functions used to be
sorted by opname without architecture. The sort
now includes the architecture, leading to further
generated code changes.
See rewriteARM and rewriteAMD64 for examples.
Again, it is a one-time change.
There are no functional changes.
Change-Id: I22c989183ad5651741ebdc0566349c5fd6c6b23c
Reviewed-on: https://go-review.googlesource.com/24649
Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: David Chase <drchase@google.com>
Reviewed-by: Keith Randall <khr@golang.org>
2016-07-01 11:05:29 -07:00
|
|
|
op, oparch, typ, auxint, aux, args := parseValue(result, arch, loc)
|
2016-04-20 11:17:41 -07:00
|
|
|
|
2016-02-03 20:50:12 +01:00
|
|
|
// Find the type of the variable.
|
[dev.ssa] cmd/compile: refactor out rulegen value parsing
Previously, genMatch0 and genResult0 contained
lots of duplication: locating the op, parsing
the value, validation, etc.
Parsing and validation was mixed in with code gen.
Extract a helper, parseValue. It is responsible
for parsing the value, locating the op, and doing
shared validation.
As a bonus (and possibly as my original motivation),
make op selection pay attention to the number
of args present.
This allows arch-specific ops to share a name
with generic ops as long as there is no ambiguity.
It also detects and reports unresolved ambiguity,
unlike before, where it would simply always
pick the generic op, with no warning.
Also use parseValue when generating the top-level
op dispatch, to ensure its opinion about ops
matches genMatch0 and genResult0.
The order of statements in the generated code used
to depend on the exact rule. It is now somewhat
independent of the rule. That is the source
of some of the generated code changes in this CL.
See rewritedec64 and rewritegeneric for examples.
It is a one-time change.
The op dispatch switch and functions used to be
sorted by opname without architecture. The sort
now includes the architecture, leading to further
generated code changes.
See rewriteARM and rewriteAMD64 for examples.
Again, it is a one-time change.
There are no functional changes.
Change-Id: I22c989183ad5651741ebdc0566349c5fd6c6b23c
Reviewed-on: https://go-review.googlesource.com/24649
Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: David Chase <drchase@google.com>
Reviewed-by: Keith Randall <khr@golang.org>
2016-07-01 11:05:29 -07:00
|
|
|
typeOverride := typ != ""
|
|
|
|
|
if typ == "" && op.typ != "" {
|
|
|
|
|
typ = typeName(op.typ)
|
2016-02-03 20:50:12 +01:00
|
|
|
}
|
[dev.ssa] cmd/compile: refactor out rulegen value parsing
Previously, genMatch0 and genResult0 contained
lots of duplication: locating the op, parsing
the value, validation, etc.
Parsing and validation was mixed in with code gen.
Extract a helper, parseValue. It is responsible
for parsing the value, locating the op, and doing
shared validation.
As a bonus (and possibly as my original motivation),
make op selection pay attention to the number
of args present.
This allows arch-specific ops to share a name
with generic ops as long as there is no ambiguity.
It also detects and reports unresolved ambiguity,
unlike before, where it would simply always
pick the generic op, with no warning.
Also use parseValue when generating the top-level
op dispatch, to ensure its opinion about ops
matches genMatch0 and genResult0.
The order of statements in the generated code used
to depend on the exact rule. It is now somewhat
independent of the rule. That is the source
of some of the generated code changes in this CL.
See rewritedec64 and rewritegeneric for examples.
It is a one-time change.
The op dispatch switch and functions used to be
sorted by opname without architecture. The sort
now includes the architecture, leading to further
generated code changes.
See rewriteARM and rewriteAMD64 for examples.
Again, it is a one-time change.
There are no functional changes.
Change-Id: I22c989183ad5651741ebdc0566349c5fd6c6b23c
Reviewed-on: https://go-review.googlesource.com/24649
Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: David Chase <drchase@google.com>
Reviewed-by: Keith Randall <khr@golang.org>
2016-07-01 11:05:29 -07:00
|
|
|
|
2015-03-23 17:02:11 -07:00
|
|
|
var v string
|
2016-02-24 10:29:27 -08:00
|
|
|
if top && !move {
|
2015-03-23 17:02:11 -07:00
|
|
|
v = "v"
|
[dev.ssa] cmd/compile: refactor out rulegen value parsing
Previously, genMatch0 and genResult0 contained
lots of duplication: locating the op, parsing
the value, validation, etc.
Parsing and validation was mixed in with code gen.
Extract a helper, parseValue. It is responsible
for parsing the value, locating the op, and doing
shared validation.
As a bonus (and possibly as my original motivation),
make op selection pay attention to the number
of args present.
This allows arch-specific ops to share a name
with generic ops as long as there is no ambiguity.
It also detects and reports unresolved ambiguity,
unlike before, where it would simply always
pick the generic op, with no warning.
Also use parseValue when generating the top-level
op dispatch, to ensure its opinion about ops
matches genMatch0 and genResult0.
The order of statements in the generated code used
to depend on the exact rule. It is now somewhat
independent of the rule. That is the source
of some of the generated code changes in this CL.
See rewritedec64 and rewritegeneric for examples.
It is a one-time change.
The op dispatch switch and functions used to be
sorted by opname without architecture. The sort
now includes the architecture, leading to further
generated code changes.
See rewriteARM and rewriteAMD64 for examples.
Again, it is a one-time change.
There are no functional changes.
Change-Id: I22c989183ad5651741ebdc0566349c5fd6c6b23c
Reviewed-on: https://go-review.googlesource.com/24649
Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: David Chase <drchase@google.com>
Reviewed-by: Keith Randall <khr@golang.org>
2016-07-01 11:05:29 -07:00
|
|
|
fmt.Fprintf(w, "v.reset(Op%s%s)\n", oparch, op.name)
|
2016-02-03 20:50:12 +01:00
|
|
|
if typeOverride {
|
[dev.ssa] cmd/compile: refactor out rulegen value parsing
Previously, genMatch0 and genResult0 contained
lots of duplication: locating the op, parsing
the value, validation, etc.
Parsing and validation was mixed in with code gen.
Extract a helper, parseValue. It is responsible
for parsing the value, locating the op, and doing
shared validation.
As a bonus (and possibly as my original motivation),
make op selection pay attention to the number
of args present.
This allows arch-specific ops to share a name
with generic ops as long as there is no ambiguity.
It also detects and reports unresolved ambiguity,
unlike before, where it would simply always
pick the generic op, with no warning.
Also use parseValue when generating the top-level
op dispatch, to ensure its opinion about ops
matches genMatch0 and genResult0.
The order of statements in the generated code used
to depend on the exact rule. It is now somewhat
independent of the rule. That is the source
of some of the generated code changes in this CL.
See rewritedec64 and rewritegeneric for examples.
It is a one-time change.
The op dispatch switch and functions used to be
sorted by opname without architecture. The sort
now includes the architecture, leading to further
generated code changes.
See rewriteARM and rewriteAMD64 for examples.
Again, it is a one-time change.
There are no functional changes.
Change-Id: I22c989183ad5651741ebdc0566349c5fd6c6b23c
Reviewed-on: https://go-review.googlesource.com/24649
Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: David Chase <drchase@google.com>
Reviewed-by: Keith Randall <khr@golang.org>
2016-07-01 11:05:29 -07:00
|
|
|
fmt.Fprintf(w, "v.Type = %s\n", typ)
|
2016-02-03 20:50:12 +01:00
|
|
|
}
|
2015-03-23 17:02:11 -07:00
|
|
|
} else {
|
[dev.ssa] cmd/compile: refactor out rulegen value parsing
Previously, genMatch0 and genResult0 contained
lots of duplication: locating the op, parsing
the value, validation, etc.
Parsing and validation was mixed in with code gen.
Extract a helper, parseValue. It is responsible
for parsing the value, locating the op, and doing
shared validation.
As a bonus (and possibly as my original motivation),
make op selection pay attention to the number
of args present.
This allows arch-specific ops to share a name
with generic ops as long as there is no ambiguity.
It also detects and reports unresolved ambiguity,
unlike before, where it would simply always
pick the generic op, with no warning.
Also use parseValue when generating the top-level
op dispatch, to ensure its opinion about ops
matches genMatch0 and genResult0.
The order of statements in the generated code used
to depend on the exact rule. It is now somewhat
independent of the rule. That is the source
of some of the generated code changes in this CL.
See rewritedec64 and rewritegeneric for examples.
It is a one-time change.
The op dispatch switch and functions used to be
sorted by opname without architecture. The sort
now includes the architecture, leading to further
generated code changes.
See rewriteARM and rewriteAMD64 for examples.
Again, it is a one-time change.
There are no functional changes.
Change-Id: I22c989183ad5651741ebdc0566349c5fd6c6b23c
Reviewed-on: https://go-review.googlesource.com/24649
Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: David Chase <drchase@google.com>
Reviewed-by: Keith Randall <khr@golang.org>
2016-07-01 11:05:29 -07:00
|
|
|
if typ == "" {
|
|
|
|
|
log.Fatalf("sub-expression %s (op=Op%s%s) must have a type", result, oparch, op.name)
|
2016-02-03 20:50:12 +01:00
|
|
|
}
|
2015-03-23 17:02:11 -07:00
|
|
|
v = fmt.Sprintf("v%d", *alloc)
|
|
|
|
|
*alloc++
|
2016-12-07 18:14:35 -08:00
|
|
|
fmt.Fprintf(w, "%s := b.NewValue0(v.Pos, Op%s%s, %s)\n", v, oparch, op.name, typ)
|
2016-03-15 20:45:50 -07:00
|
|
|
if move && top {
|
2015-10-13 11:08:08 -07:00
|
|
|
// Rewrite original into a copy
|
2016-02-04 17:21:57 +01:00
|
|
|
fmt.Fprintf(w, "v.reset(OpCopy)\n")
|
2015-10-13 11:08:08 -07:00
|
|
|
fmt.Fprintf(w, "v.AddArg(%s)\n", v)
|
|
|
|
|
}
|
2015-03-23 17:02:11 -07:00
|
|
|
}
|
[dev.ssa] cmd/compile: refactor out rulegen value parsing
Previously, genMatch0 and genResult0 contained
lots of duplication: locating the op, parsing
the value, validation, etc.
Parsing and validation was mixed in with code gen.
Extract a helper, parseValue. It is responsible
for parsing the value, locating the op, and doing
shared validation.
As a bonus (and possibly as my original motivation),
make op selection pay attention to the number
of args present.
This allows arch-specific ops to share a name
with generic ops as long as there is no ambiguity.
It also detects and reports unresolved ambiguity,
unlike before, where it would simply always
pick the generic op, with no warning.
Also use parseValue when generating the top-level
op dispatch, to ensure its opinion about ops
matches genMatch0 and genResult0.
The order of statements in the generated code used
to depend on the exact rule. It is now somewhat
independent of the rule. That is the source
of some of the generated code changes in this CL.
See rewritedec64 and rewritegeneric for examples.
It is a one-time change.
The op dispatch switch and functions used to be
sorted by opname without architecture. The sort
now includes the architecture, leading to further
generated code changes.
See rewriteARM and rewriteAMD64 for examples.
Again, it is a one-time change.
There are no functional changes.
Change-Id: I22c989183ad5651741ebdc0566349c5fd6c6b23c
Reviewed-on: https://go-review.googlesource.com/24649
Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: David Chase <drchase@google.com>
Reviewed-by: Keith Randall <khr@golang.org>
2016-07-01 11:05:29 -07:00
|
|
|
|
|
|
|
|
if auxint != "" {
|
|
|
|
|
fmt.Fprintf(w, "%s.AuxInt = %s\n", v, auxint)
|
2015-03-23 17:02:11 -07:00
|
|
|
}
|
[dev.ssa] cmd/compile: refactor out rulegen value parsing
Previously, genMatch0 and genResult0 contained
lots of duplication: locating the op, parsing
the value, validation, etc.
Parsing and validation was mixed in with code gen.
Extract a helper, parseValue. It is responsible
for parsing the value, locating the op, and doing
shared validation.
As a bonus (and possibly as my original motivation),
make op selection pay attention to the number
of args present.
This allows arch-specific ops to share a name
with generic ops as long as there is no ambiguity.
It also detects and reports unresolved ambiguity,
unlike before, where it would simply always
pick the generic op, with no warning.
Also use parseValue when generating the top-level
op dispatch, to ensure its opinion about ops
matches genMatch0 and genResult0.
The order of statements in the generated code used
to depend on the exact rule. It is now somewhat
independent of the rule. That is the source
of some of the generated code changes in this CL.
See rewritedec64 and rewritegeneric for examples.
It is a one-time change.
The op dispatch switch and functions used to be
sorted by opname without architecture. The sort
now includes the architecture, leading to further
generated code changes.
See rewriteARM and rewriteAMD64 for examples.
Again, it is a one-time change.
There are no functional changes.
Change-Id: I22c989183ad5651741ebdc0566349c5fd6c6b23c
Reviewed-on: https://go-review.googlesource.com/24649
Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: David Chase <drchase@google.com>
Reviewed-by: Keith Randall <khr@golang.org>
2016-07-01 11:05:29 -07:00
|
|
|
if aux != "" {
|
|
|
|
|
fmt.Fprintf(w, "%s.Aux = %s\n", v, aux)
|
|
|
|
|
}
|
|
|
|
|
for _, arg := range args {
|
|
|
|
|
x := genResult0(w, arch, arg, alloc, false, move, loc)
|
|
|
|
|
fmt.Fprintf(w, "%s.AddArg(%s)\n", v, x)
|
2016-04-20 11:17:41 -07:00
|
|
|
}
|
2016-02-03 20:50:12 +01:00
|
|
|
|
2015-03-23 17:02:11 -07:00
|
|
|
return v
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func split(s string) []string {
|
|
|
|
|
var r []string
|
|
|
|
|
|
|
|
|
|
outer:
|
|
|
|
|
for s != "" {
|
2015-05-18 16:44:20 -07:00
|
|
|
d := 0 // depth of ({[<
|
|
|
|
|
var open, close byte // opening and closing markers ({[< or )}]>
|
|
|
|
|
nonsp := false // found a non-space char so far
|
2015-03-23 17:02:11 -07:00
|
|
|
for i := 0; i < len(s); i++ {
|
2015-05-18 16:44:20 -07:00
|
|
|
switch {
|
|
|
|
|
case d == 0 && s[i] == '(':
|
|
|
|
|
open, close = '(', ')'
|
2015-03-23 17:02:11 -07:00
|
|
|
d++
|
2015-05-18 16:44:20 -07:00
|
|
|
case d == 0 && s[i] == '<':
|
|
|
|
|
open, close = '<', '>'
|
|
|
|
|
d++
|
|
|
|
|
case d == 0 && s[i] == '[':
|
|
|
|
|
open, close = '[', ']'
|
|
|
|
|
d++
|
|
|
|
|
case d == 0 && s[i] == '{':
|
|
|
|
|
open, close = '{', '}'
|
|
|
|
|
d++
|
|
|
|
|
case d == 0 && (s[i] == ' ' || s[i] == '\t'):
|
|
|
|
|
if nonsp {
|
2015-03-23 17:02:11 -07:00
|
|
|
r = append(r, strings.TrimSpace(s[:i]))
|
|
|
|
|
s = s[i:]
|
|
|
|
|
continue outer
|
|
|
|
|
}
|
2015-05-18 16:44:20 -07:00
|
|
|
case d > 0 && s[i] == open:
|
|
|
|
|
d++
|
|
|
|
|
case d > 0 && s[i] == close:
|
|
|
|
|
d--
|
2015-03-23 17:02:11 -07:00
|
|
|
default:
|
|
|
|
|
nonsp = true
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if d != 0 {
|
|
|
|
|
panic("imbalanced expression: " + s)
|
|
|
|
|
}
|
|
|
|
|
if nonsp {
|
|
|
|
|
r = append(r, strings.TrimSpace(s))
|
|
|
|
|
}
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
return r
|
|
|
|
|
}
|
2015-06-06 16:03:33 -07:00
|
|
|
|
|
|
|
|
// isBlock returns true if this op is a block opcode.
|
|
|
|
|
func isBlock(name string, arch arch) bool {
|
|
|
|
|
for _, b := range genericBlocks {
|
|
|
|
|
if b.name == name {
|
|
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
for _, b := range arch.blocks {
|
|
|
|
|
if b.name == name {
|
|
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
|
[dev.ssa] cmd/compile: refactor out rulegen value parsing
Previously, genMatch0 and genResult0 contained
lots of duplication: locating the op, parsing
the value, validation, etc.
Parsing and validation was mixed in with code gen.
Extract a helper, parseValue. It is responsible
for parsing the value, locating the op, and doing
shared validation.
As a bonus (and possibly as my original motivation),
make op selection pay attention to the number
of args present.
This allows arch-specific ops to share a name
with generic ops as long as there is no ambiguity.
It also detects and reports unresolved ambiguity,
unlike before, where it would simply always
pick the generic op, with no warning.
Also use parseValue when generating the top-level
op dispatch, to ensure its opinion about ops
matches genMatch0 and genResult0.
The order of statements in the generated code used
to depend on the exact rule. It is now somewhat
independent of the rule. That is the source
of some of the generated code changes in this CL.
See rewritedec64 and rewritegeneric for examples.
It is a one-time change.
The op dispatch switch and functions used to be
sorted by opname without architecture. The sort
now includes the architecture, leading to further
generated code changes.
See rewriteARM and rewriteAMD64 for examples.
Again, it is a one-time change.
There are no functional changes.
Change-Id: I22c989183ad5651741ebdc0566349c5fd6c6b23c
Reviewed-on: https://go-review.googlesource.com/24649
Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: David Chase <drchase@google.com>
Reviewed-by: Keith Randall <khr@golang.org>
2016-07-01 11:05:29 -07:00
|
|
|
// parseValue parses a parenthesized value from a rule.
|
|
|
|
|
// The value can be from the match or the result side.
|
|
|
|
|
// It returns the op and unparsed strings for typ, auxint, and aux restrictions and for all args.
|
|
|
|
|
// oparch is the architecture that op is located in, or "" for generic.
|
|
|
|
|
func parseValue(val string, arch arch, loc string) (op opData, oparch string, typ string, auxint string, aux string, args []string) {
|
|
|
|
|
val = val[1 : len(val)-1] // remove ()
|
|
|
|
|
|
|
|
|
|
// Split val up into regions.
|
|
|
|
|
// Split by spaces/tabs, except those contained in (), {}, [], or <>.
|
|
|
|
|
s := split(val)
|
|
|
|
|
|
|
|
|
|
// Extract restrictions and args.
|
|
|
|
|
for _, a := range s[1:] {
|
|
|
|
|
switch a[0] {
|
|
|
|
|
case '<':
|
|
|
|
|
typ = a[1 : len(a)-1] // remove <>
|
|
|
|
|
case '[':
|
|
|
|
|
auxint = a[1 : len(a)-1] // remove []
|
|
|
|
|
case '{':
|
|
|
|
|
aux = a[1 : len(a)-1] // remove {}
|
|
|
|
|
default:
|
|
|
|
|
args = append(args, a)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Resolve the op.
|
|
|
|
|
|
|
|
|
|
// match reports whether x is a good op to select.
|
|
|
|
|
// If strict is true, rule generation might succeed.
|
|
|
|
|
// If strict is false, rule generation has failed,
|
|
|
|
|
// but we're trying to generate a useful error.
|
|
|
|
|
// Doing strict=true then strict=false allows
|
|
|
|
|
// precise op matching while retaining good error messages.
|
|
|
|
|
match := func(x opData, strict bool, archname string) bool {
|
|
|
|
|
if x.name != s[0] {
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
if x.argLength != -1 && int(x.argLength) != len(args) {
|
|
|
|
|
if strict {
|
|
|
|
|
return false
|
|
|
|
|
} else {
|
2016-09-07 12:06:43 -04:00
|
|
|
log.Printf("%s: op %s (%s) should have %d args, has %d", loc, s[0], archname, x.argLength, len(args))
|
[dev.ssa] cmd/compile: refactor out rulegen value parsing
Previously, genMatch0 and genResult0 contained
lots of duplication: locating the op, parsing
the value, validation, etc.
Parsing and validation was mixed in with code gen.
Extract a helper, parseValue. It is responsible
for parsing the value, locating the op, and doing
shared validation.
As a bonus (and possibly as my original motivation),
make op selection pay attention to the number
of args present.
This allows arch-specific ops to share a name
with generic ops as long as there is no ambiguity.
It also detects and reports unresolved ambiguity,
unlike before, where it would simply always
pick the generic op, with no warning.
Also use parseValue when generating the top-level
op dispatch, to ensure its opinion about ops
matches genMatch0 and genResult0.
The order of statements in the generated code used
to depend on the exact rule. It is now somewhat
independent of the rule. That is the source
of some of the generated code changes in this CL.
See rewritedec64 and rewritegeneric for examples.
It is a one-time change.
The op dispatch switch and functions used to be
sorted by opname without architecture. The sort
now includes the architecture, leading to further
generated code changes.
See rewriteARM and rewriteAMD64 for examples.
Again, it is a one-time change.
There are no functional changes.
Change-Id: I22c989183ad5651741ebdc0566349c5fd6c6b23c
Reviewed-on: https://go-review.googlesource.com/24649
Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: David Chase <drchase@google.com>
Reviewed-by: Keith Randall <khr@golang.org>
2016-07-01 11:05:29 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for _, x := range genericOps {
|
|
|
|
|
if match(x, true, "generic") {
|
|
|
|
|
op = x
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if arch.name != "generic" {
|
|
|
|
|
for _, x := range arch.ops {
|
|
|
|
|
if match(x, true, arch.name) {
|
|
|
|
|
if op.name != "" {
|
|
|
|
|
log.Fatalf("%s: matches for op %s found in both generic and %s", loc, op.name, arch.name)
|
|
|
|
|
}
|
|
|
|
|
op = x
|
|
|
|
|
oparch = arch.name
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if op.name == "" {
|
|
|
|
|
// Failed to find the op.
|
|
|
|
|
// Run through everything again with strict=false
|
|
|
|
|
// to generate useful diagnosic messages before failing.
|
|
|
|
|
for _, x := range genericOps {
|
|
|
|
|
match(x, false, "generic")
|
|
|
|
|
}
|
|
|
|
|
for _, x := range arch.ops {
|
|
|
|
|
match(x, false, arch.name)
|
|
|
|
|
}
|
|
|
|
|
log.Fatalf("%s: unknown op %s", loc, s)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Sanity check aux, auxint.
|
|
|
|
|
if auxint != "" {
|
|
|
|
|
switch op.aux {
|
2017-03-13 21:51:08 -04:00
|
|
|
case "Bool", "Int8", "Int16", "Int32", "Int64", "Int128", "Float32", "Float64", "SymOff", "SymValAndOff", "SymInt32", "TypSize":
|
[dev.ssa] cmd/compile: refactor out rulegen value parsing
Previously, genMatch0 and genResult0 contained
lots of duplication: locating the op, parsing
the value, validation, etc.
Parsing and validation was mixed in with code gen.
Extract a helper, parseValue. It is responsible
for parsing the value, locating the op, and doing
shared validation.
As a bonus (and possibly as my original motivation),
make op selection pay attention to the number
of args present.
This allows arch-specific ops to share a name
with generic ops as long as there is no ambiguity.
It also detects and reports unresolved ambiguity,
unlike before, where it would simply always
pick the generic op, with no warning.
Also use parseValue when generating the top-level
op dispatch, to ensure its opinion about ops
matches genMatch0 and genResult0.
The order of statements in the generated code used
to depend on the exact rule. It is now somewhat
independent of the rule. That is the source
of some of the generated code changes in this CL.
See rewritedec64 and rewritegeneric for examples.
It is a one-time change.
The op dispatch switch and functions used to be
sorted by opname without architecture. The sort
now includes the architecture, leading to further
generated code changes.
See rewriteARM and rewriteAMD64 for examples.
Again, it is a one-time change.
There are no functional changes.
Change-Id: I22c989183ad5651741ebdc0566349c5fd6c6b23c
Reviewed-on: https://go-review.googlesource.com/24649
Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: David Chase <drchase@google.com>
Reviewed-by: Keith Randall <khr@golang.org>
2016-07-01 11:05:29 -07:00
|
|
|
default:
|
|
|
|
|
log.Fatalf("%s: op %s %s can't have auxint", loc, op.name, op.aux)
|
2015-06-06 16:03:33 -07:00
|
|
|
}
|
|
|
|
|
}
|
[dev.ssa] cmd/compile: refactor out rulegen value parsing
Previously, genMatch0 and genResult0 contained
lots of duplication: locating the op, parsing
the value, validation, etc.
Parsing and validation was mixed in with code gen.
Extract a helper, parseValue. It is responsible
for parsing the value, locating the op, and doing
shared validation.
As a bonus (and possibly as my original motivation),
make op selection pay attention to the number
of args present.
This allows arch-specific ops to share a name
with generic ops as long as there is no ambiguity.
It also detects and reports unresolved ambiguity,
unlike before, where it would simply always
pick the generic op, with no warning.
Also use parseValue when generating the top-level
op dispatch, to ensure its opinion about ops
matches genMatch0 and genResult0.
The order of statements in the generated code used
to depend on the exact rule. It is now somewhat
independent of the rule. That is the source
of some of the generated code changes in this CL.
See rewritedec64 and rewritegeneric for examples.
It is a one-time change.
The op dispatch switch and functions used to be
sorted by opname without architecture. The sort
now includes the architecture, leading to further
generated code changes.
See rewriteARM and rewriteAMD64 for examples.
Again, it is a one-time change.
There are no functional changes.
Change-Id: I22c989183ad5651741ebdc0566349c5fd6c6b23c
Reviewed-on: https://go-review.googlesource.com/24649
Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: David Chase <drchase@google.com>
Reviewed-by: Keith Randall <khr@golang.org>
2016-07-01 11:05:29 -07:00
|
|
|
if aux != "" {
|
|
|
|
|
switch op.aux {
|
2017-03-13 21:51:08 -04:00
|
|
|
case "String", "Sym", "SymOff", "SymValAndOff", "SymInt32", "Typ", "TypSize":
|
[dev.ssa] cmd/compile: refactor out rulegen value parsing
Previously, genMatch0 and genResult0 contained
lots of duplication: locating the op, parsing
the value, validation, etc.
Parsing and validation was mixed in with code gen.
Extract a helper, parseValue. It is responsible
for parsing the value, locating the op, and doing
shared validation.
As a bonus (and possibly as my original motivation),
make op selection pay attention to the number
of args present.
This allows arch-specific ops to share a name
with generic ops as long as there is no ambiguity.
It also detects and reports unresolved ambiguity,
unlike before, where it would simply always
pick the generic op, with no warning.
Also use parseValue when generating the top-level
op dispatch, to ensure its opinion about ops
matches genMatch0 and genResult0.
The order of statements in the generated code used
to depend on the exact rule. It is now somewhat
independent of the rule. That is the source
of some of the generated code changes in this CL.
See rewritedec64 and rewritegeneric for examples.
It is a one-time change.
The op dispatch switch and functions used to be
sorted by opname without architecture. The sort
now includes the architecture, leading to further
generated code changes.
See rewriteARM and rewriteAMD64 for examples.
Again, it is a one-time change.
There are no functional changes.
Change-Id: I22c989183ad5651741ebdc0566349c5fd6c6b23c
Reviewed-on: https://go-review.googlesource.com/24649
Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: David Chase <drchase@google.com>
Reviewed-by: Keith Randall <khr@golang.org>
2016-07-01 11:05:29 -07:00
|
|
|
default:
|
|
|
|
|
log.Fatalf("%s: op %s %s can't have aux", loc, op.name, op.aux)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return
|
2015-06-06 16:03:33 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func blockName(name string, arch arch) string {
|
|
|
|
|
for _, b := range genericBlocks {
|
|
|
|
|
if b.name == name {
|
|
|
|
|
return "Block" + name
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return "Block" + arch.name + name
|
|
|
|
|
}
|
2015-06-10 10:39:57 -07:00
|
|
|
|
2015-09-01 09:16:58 -07:00
|
|
|
// typeName returns the string to use to generate a type.
|
|
|
|
|
func typeName(typ string) string {
|
[dev.ssa] cmd/compile: decompose 64-bit integer on ARM
Introduce dec64 rules to (generically) decompose 64-bit integer on
32-bit architectures. 64-bit integer is composed/decomposed with
Int64Make/Hi/Lo ops, as for complex types.
The idea of dealing with Add64 is the following:
(Add64 (Int64Make xh xl) (Int64Make yh yl))
->
(Int64Make
(Add32withcarry xh yh (Select0 (Add32carry xl yl)))
(Select1 (Add32carry xl yl)))
where Add32carry returns a tuple (flags,uint32). Select0 and Select1
read the first and the second component of the tuple, respectively.
The two Add32carry will be CSE'd.
Similarly for multiplication, Mul32uhilo returns a tuple (hi, lo).
Also add support of KeepAlive, to fix build after merge.
Tests addressed_ssa.go, array_ssa.go, break_ssa.go, chan_ssa.go,
cmp_ssa.go, ctl_ssa.go, map_ssa.go, and string_ssa.go in
cmd/compile/internal/gc/testdata passed.
Progress on SSA for ARM. Still not complete.
Updates #15365.
Change-Id: I7867c76785a456312de5d8398a6b3f7ca5a4f7ec
Reviewed-on: https://go-review.googlesource.com/23213
Reviewed-by: Keith Randall <khr@golang.org>
2016-05-18 18:14:36 -04:00
|
|
|
if typ[0] == '(' {
|
|
|
|
|
ts := strings.Split(typ[1:len(typ)-1], ",")
|
|
|
|
|
if len(ts) != 2 {
|
|
|
|
|
panic("Tuple expect 2 arguments")
|
|
|
|
|
}
|
|
|
|
|
return "MakeTuple(" + typeName(ts[0]) + ", " + typeName(ts[1]) + ")"
|
|
|
|
|
}
|
2015-09-01 09:16:58 -07:00
|
|
|
switch typ {
|
2015-10-21 17:18:07 -07:00
|
|
|
case "Flags", "Mem", "Void", "Int128":
|
2015-09-01 09:16:58 -07:00
|
|
|
return "Type" + typ
|
|
|
|
|
default:
|
2017-03-17 16:04:46 -07:00
|
|
|
return "types." + typ
|
2015-09-01 09:16:58 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-06-10 10:39:57 -07:00
|
|
|
// unbalanced returns true if there aren't the same number of ( and ) in the string.
|
|
|
|
|
func unbalanced(s string) bool {
|
|
|
|
|
var left, right int
|
|
|
|
|
for _, c := range s {
|
|
|
|
|
if c == '(' {
|
|
|
|
|
left++
|
|
|
|
|
}
|
|
|
|
|
if c == ')' {
|
|
|
|
|
right++
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return left != right
|
|
|
|
|
}
|
2015-06-11 21:29:25 -07:00
|
|
|
|
|
|
|
|
// isVariable reports whether s is a single Go alphanumeric identifier.
|
|
|
|
|
func isVariable(s string) bool {
|
2015-08-18 10:28:58 -07:00
|
|
|
b, err := regexp.MatchString("^[A-Za-z_][A-Za-z_0-9]*$", s)
|
2015-06-11 21:29:25 -07:00
|
|
|
if err != nil {
|
|
|
|
|
panic("bad variable regexp")
|
|
|
|
|
}
|
|
|
|
|
return b
|
|
|
|
|
}
|