mirror of
https://github.com/golang/go
synced 2024-11-19 06:24:41 -07:00
138 lines
3.9 KiB
Go
138 lines
3.9 KiB
Go
|
// run
|
||
|
// +build !nacl
|
||
|
|
||
|
// Copyright 2016 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.
|
||
|
|
||
|
// Runs a build -S to capture the assembly language
|
||
|
// output, checks that the line numbers associated with
|
||
|
// the stream of instructions do not change "too much".
|
||
|
// The changes that fixes this (that reduces the amount
|
||
|
// of change) does so by treating register spill, reload,
|
||
|
// copy, and rematerializations as being "unimportant" and
|
||
|
// just assigns them the line numbers of whatever "real"
|
||
|
// instructions preceded them.
|
||
|
|
||
|
// nacl is excluded because this runs a compiler.
|
||
|
|
||
|
package main
|
||
|
|
||
|
import (
|
||
|
"bufio"
|
||
|
"bytes"
|
||
|
"fmt"
|
||
|
"os"
|
||
|
"os/exec"
|
||
|
"strconv"
|
||
|
"strings"
|
||
|
)
|
||
|
|
||
|
// updateEnv modifies env to ensure that key=val
|
||
|
func updateEnv(env *[]string, key, val string) {
|
||
|
if val != "" {
|
||
|
var found bool
|
||
|
key = key + "="
|
||
|
for i, kv := range *env {
|
||
|
if strings.HasPrefix(kv, key) {
|
||
|
(*env)[i] = key + val
|
||
|
found = true
|
||
|
break
|
||
|
}
|
||
|
}
|
||
|
if !found {
|
||
|
*env = append(*env, key+val)
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func main() {
|
||
|
testarch := os.Getenv("TESTARCH") // Targets other platform in test compilation.
|
||
|
debug := os.Getenv("TESTDEBUG") != "" // Output the relevant assembly language.
|
||
|
|
||
|
cmd := exec.Command("go", "build", "-gcflags", "-S", "fixedbugs/issue18902b.go")
|
||
|
var buf bytes.Buffer
|
||
|
cmd.Stdout = &buf
|
||
|
cmd.Stderr = &buf
|
||
|
cmd.Env = os.Environ()
|
||
|
|
||
|
updateEnv(&cmd.Env, "GOARCH", testarch)
|
||
|
|
||
|
err := cmd.Run()
|
||
|
if err != nil {
|
||
|
fmt.Printf("%s\n%s", err, buf.Bytes())
|
||
|
return
|
||
|
}
|
||
|
begin := "\"\".(*gcSortBuf).flush" // Text at beginning of relevant dissassembly.
|
||
|
s := buf.String()
|
||
|
i := strings.Index(s, begin)
|
||
|
if i < 0 {
|
||
|
fmt.Printf("Failed to find expected symbol %s in output\n%s\n", begin, s)
|
||
|
return
|
||
|
}
|
||
|
s = s[i:]
|
||
|
r := strings.NewReader(s)
|
||
|
scanner := bufio.NewScanner(r)
|
||
|
first := true // The first line after the begin text will be skipped
|
||
|
beforeLineNumber := "issue18902b.go:" // Text preceding line number in each line.
|
||
|
lbln := len(beforeLineNumber)
|
||
|
|
||
|
var scannedCount, changes, sumdiffs float64
|
||
|
|
||
|
prevVal := 0
|
||
|
for scanner.Scan() {
|
||
|
line := scanner.Text()
|
||
|
if first {
|
||
|
first = false
|
||
|
continue
|
||
|
}
|
||
|
i = strings.Index(line, beforeLineNumber)
|
||
|
if i < 0 {
|
||
|
// Done reading lines
|
||
|
if scannedCount < 200 { // When test was written, 251 lines observed on amd64
|
||
|
fmt.Printf("Scanned only %d lines, was expecting more than 200", scannedCount)
|
||
|
return
|
||
|
}
|
||
|
// Note: when test was written, before changes=92, after=50 (was 62 w/o rematerialization NoXPos in *Value.copyInto())
|
||
|
// and before sumdiffs=784, after=180 (was 446 w/o rematerialization NoXPos in *Value.copyInto())
|
||
|
// Set the dividing line between pass and fail at the midpoint.
|
||
|
// Normalize against instruction count in case we unroll loops, etc.
|
||
|
if changes/scannedCount >= (50+92)/(2*scannedCount) || sumdiffs/scannedCount >= (180+784)/(2*scannedCount) {
|
||
|
fmt.Printf("Line numbers change too much, # of changes=%.f, sumdiffs=%.f, # of instructions=%.f\n", changes, sumdiffs, scannedCount)
|
||
|
}
|
||
|
return
|
||
|
}
|
||
|
scannedCount++
|
||
|
i += lbln
|
||
|
lineVal, err := strconv.Atoi(line[i : i+3])
|
||
|
if err != nil {
|
||
|
fmt.Printf("Expected 3-digit line number after %s in %s\n", beforeLineNumber, line)
|
||
|
}
|
||
|
if prevVal == 0 {
|
||
|
prevVal = lineVal
|
||
|
}
|
||
|
diff := lineVal - prevVal
|
||
|
if diff < 0 {
|
||
|
diff = -diff
|
||
|
}
|
||
|
if diff != 0 {
|
||
|
changes++
|
||
|
sumdiffs += float64(diff)
|
||
|
}
|
||
|
// If things change too much, set environment variable TESTDEBUG to help figure out what's up.
|
||
|
// The "before" behavior can be recreated in DebugFriendlySetPosFrom (currently in gc/ssa.go)
|
||
|
// by inserting unconditional
|
||
|
// s.SetPos(v.Pos)
|
||
|
// at the top of the function.
|
||
|
|
||
|
if debug {
|
||
|
fmt.Printf("%d %.f %.f %s\n", lineVal, changes, sumdiffs, line)
|
||
|
}
|
||
|
prevVal = lineVal
|
||
|
}
|
||
|
if err := scanner.Err(); err != nil {
|
||
|
fmt.Println("Reading standard input:", err)
|
||
|
return
|
||
|
}
|
||
|
}
|