mirror of
https://github.com/golang/go.git
synced 2026-02-04 09:55:06 +03:00
[dev.simd] cmd/compile: keep track of multiple rule file names in ssa/_gen
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>
This commit is contained in:
117
src/cmd/compile/internal/ssa/_gen/multiscanner.go
Normal file
117
src/cmd/compile/internal/ssa/_gen/multiscanner.go
Normal file
@@ -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
|
||||
}
|
||||
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user