]> Cypherpunks repositories - gostls13.git/commitdiff
[dev.simd] cmd/compile: keep track of multiple rule file names in ssa/_gen
authorDavid Chase <drchase@google.com>
Fri, 8 Aug 2025 20:49:17 +0000 (16:49 -0400)
committerDavid Chase <drchase@google.com>
Mon, 11 Aug 2025 18:12:55 +0000 (11:12 -0700)
This was a long-standing "we need to fix this"
for simd work, this fixes it.  I expect that
simd peephole rule files will be coming soon
and there will be more errors and we will be
happier to have this.

Change-Id: Iefffc43e3e2110939f8d406f6e5da7e9e2d55bd9
Reviewed-on: https://go-review.googlesource.com/c/go/+/694455
Reviewed-by: Cherry Mui <cherryyz@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>

src/cmd/compile/internal/ssa/_gen/multiscanner.go [new file with mode: 0644]
src/cmd/compile/internal/ssa/_gen/rulegen.go

diff --git a/src/cmd/compile/internal/ssa/_gen/multiscanner.go b/src/cmd/compile/internal/ssa/_gen/multiscanner.go
new file mode 100644 (file)
index 0000000..1c7520c
--- /dev/null
@@ -0,0 +1,117 @@
+// Copyright 2025 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.
+
+package main
+
+import (
+       "bufio"
+       "io"
+)
+
+// NamedScanner is a simple struct to pair a name with a Scanner.
+type NamedScanner struct {
+       Name    string
+       Scanner *bufio.Scanner
+}
+
+// NamedReader is a simple struct to pair a name with a Reader,
+// which will be converted to a Scanner using bufio.NewScanner.
+type NamedReader struct {
+       Name   string
+       Reader io.Reader
+}
+
+// MultiScanner scans over multiple bufio.Scanners as if they were a single stream.
+// It also keeps track of the name of the current scanner and the line number.
+type MultiScanner struct {
+       scanners   []NamedScanner
+       scannerIdx int
+       line       int
+       totalLine  int
+       err        error
+}
+
+// NewMultiScanner creates a new MultiScanner from slice of NamedScanners.
+func NewMultiScanner(scanners []NamedScanner) *MultiScanner {
+       return &MultiScanner{
+               scanners:   scanners,
+               scannerIdx: -1, // Start before the first scanner
+       }
+}
+
+// MultiScannerFromReaders creates a new MultiScanner from a slice of NamedReaders.
+func MultiScannerFromReaders(readers []NamedReader) *MultiScanner {
+       var scanners []NamedScanner
+       for _, r := range readers {
+               scanners = append(scanners, NamedScanner{
+                       Name:    r.Name,
+                       Scanner: bufio.NewScanner(r.Reader),
+               })
+       }
+       return NewMultiScanner(scanners)
+}
+
+// Scan advances the scanner to the next token, which will then be
+// available through the Text method. It returns false when the scan stops,
+// either by reaching the end of the input or an error.
+// After Scan returns false, the Err method will return any error that
+// occurred during scanning, except that if it was io.EOF, Err
+// will return nil.
+func (ms *MultiScanner) Scan() bool {
+       if ms.scannerIdx == -1 {
+               ms.scannerIdx = 0
+       }
+
+       for ms.scannerIdx < len(ms.scanners) {
+               current := ms.scanners[ms.scannerIdx]
+               if current.Scanner.Scan() {
+                       ms.line++
+                       ms.totalLine++
+                       return true
+               }
+               if err := current.Scanner.Err(); err != nil {
+                       ms.err = err
+                       return false
+               }
+               // Move to the next scanner
+               ms.scannerIdx++
+               ms.line = 0
+       }
+
+       return false
+}
+
+// Text returns the most recent token generated by a call to Scan.
+func (ms *MultiScanner) Text() string {
+       if ms.scannerIdx < 0 || ms.scannerIdx >= len(ms.scanners) {
+               return ""
+       }
+       return ms.scanners[ms.scannerIdx].Scanner.Text()
+}
+
+// Err returns the first non-EOF error that was encountered by the MultiScanner.
+func (ms *MultiScanner) Err() error {
+       return ms.err
+}
+
+// Name returns the name of the current scanner.
+func (ms *MultiScanner) Name() string {
+       if ms.scannerIdx < 0 {
+               return "<before first>"
+       }
+       if ms.scannerIdx >= len(ms.scanners) {
+               return "<after last>"
+       }
+       return ms.scanners[ms.scannerIdx].Name
+}
+
+// Line returns the current line number within the current scanner.
+func (ms *MultiScanner) Line() int {
+       return ms.line
+}
+
+// TotalLine returns the total number of lines scanned across all scanners.
+func (ms *MultiScanner) TotalLine() int {
+       return ms.totalLine
+}
index 57fd2b05943c78716740e491adb2f32f99b29d3b..d4ca1aef22279f4cecd74bb761ed795e55179007 100644 (file)
@@ -94,9 +94,11 @@ func genSplitLoadRules(arch arch) { genRulesSuffix(arch, "splitload") }
 func genLateLowerRules(arch arch) { genRulesSuffix(arch, "latelower") }
 
 func genRulesSuffix(arch arch, suff string) {
+       var readers []NamedReader
        // Open input file.
        var text io.Reader
-       text, err := os.Open(arch.name + suff + ".rules")
+       name := arch.name + suff + ".rules"
+       text, err := os.Open(name)
        if err != nil {
                if suff == "" {
                        // All architectures must have a plain rules file.
@@ -105,12 +107,14 @@ func genRulesSuffix(arch arch, suff string) {
                // Some architectures have bonus rules files that others don't share. That's fine.
                return
        }
+       readers = append(readers, NamedReader{name, text})
 
        // Check for file of SIMD rules to add
        if suff == "" {
-               simdtext, err := os.Open("simd" + arch.name + ".rules")
+               simdname := "simd" + arch.name + ".rules"
+               simdtext, err := os.Open(simdname)
                if err == nil {
-                       text = io.MultiReader(text, simdtext)
+                       readers = append(readers, NamedReader{simdname, simdtext})
                }
        }
 
@@ -119,12 +123,12 @@ func genRulesSuffix(arch arch, suff string) {
        oprules := map[string][]Rule{}
 
        // read rule file
-       scanner := bufio.NewScanner(text)
+       scanner := MultiScannerFromReaders(readers)
        rule := ""
        var lineno int
        var ruleLineno int // line number of "=>"
        for scanner.Scan() {
-               lineno++
+               lineno = scanner.Line()
                line := scanner.Text()
                if i := strings.Index(line, "//"); i >= 0 {
                        // Remove comments. Note that this isn't string safe, so
@@ -151,7 +155,7 @@ func genRulesSuffix(arch arch, suff string) {
                        break // continuing the line can't help, and it will only make errors worse
                }
 
-               loc := fmt.Sprintf("%s%s.rules:%d", arch.name, suff, ruleLineno)
+               loc := fmt.Sprintf("%s:%d", scanner.Name(), ruleLineno)
                for _, rule2 := range expandOr(rule) {
                        r := Rule{Rule: rule2, Loc: loc}
                        if rawop := strings.Split(rule2, " ")[0][1:]; isBlock(rawop, arch) {
@@ -171,7 +175,7 @@ func genRulesSuffix(arch arch, suff string) {
                log.Fatalf("scanner failed: %v\n", err)
        }
        if balance(rule) != 0 {
-               log.Fatalf("%s.rules:%d: unbalanced rule: %v\n", arch.name, lineno, rule)
+               log.Fatalf("%s:%d: unbalanced rule: %v\n", scanner.Name(), lineno, rule)
        }
 
        // Order all the ops.