cmd/compile: add framework for logging optimizer (non)actions to LSP
This is intended to allow IDEs to note where the optimizer
was not able to improve users' code. There may be other
applications for this, for example in studying effectiveness
of optimizer changes more quickly than running benchmarks,
or in verifying that code changes did not accidentally disable
optimizations in performance-critical code.
Logging of nilcheck (bad) for amd64 is implemented as
proof-of-concept. In general, the intent is that optimizations
that didn't happen are what will be logged, because that is
believed to be what IDE users want.
Added flag -json=version,dest
Check that version=0. (Future compilers will support a
few recent versions, I hope that version is always <=3.)
Dest is expected to be one of:
/path (or \path in Windows)
will create directory /path and fill it w/ json files
file://path
will create directory path, intended either for
I:\dont\know\enough\about\windows\paths
trustme_I_know_what_I_am_doing_probably_testing
Not passing an absolute path name usually leads to
json splattered all over source directories,
or failure when those directories are not writeable.
If you want a foot-gun, you have to ask for it.
The JSON output is directed to subdirectories of dest,
where each subdirectory is net/url.PathEscape of the
package name, and each for each foo.go in the package,
net/url.PathEscape(foo).json is created. The first line
of foo.json contains version and context information,
and subsequent lines contains LSP-conforming JSON
describing the missing optimizations.
Change-Id: Ib83176a53a8c177ee9081aefc5ae05604ccad8a0
Reviewed-on: https://go-review.googlesource.com/c/go/+/204338
Run-TryBot: David Chase <drchase@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
2019-10-24 13:48:17 -04:00
// Copyright 2019 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 logopt
import (
"internal/testenv"
"io/ioutil"
"os"
"os/exec"
"path/filepath"
"runtime"
"strings"
"testing"
)
const srcCode = ` package x
type pair struct { a , b int }
func bar ( y * pair ) * int {
return & y . b
}
2019-10-29 15:59:08 -04:00
var a [ ] int
cmd/compile: add framework for logging optimizer (non)actions to LSP
This is intended to allow IDEs to note where the optimizer
was not able to improve users' code. There may be other
applications for this, for example in studying effectiveness
of optimizer changes more quickly than running benchmarks,
or in verifying that code changes did not accidentally disable
optimizations in performance-critical code.
Logging of nilcheck (bad) for amd64 is implemented as
proof-of-concept. In general, the intent is that optimizations
that didn't happen are what will be logged, because that is
believed to be what IDE users want.
Added flag -json=version,dest
Check that version=0. (Future compilers will support a
few recent versions, I hope that version is always <=3.)
Dest is expected to be one of:
/path (or \path in Windows)
will create directory /path and fill it w/ json files
file://path
will create directory path, intended either for
I:\dont\know\enough\about\windows\paths
trustme_I_know_what_I_am_doing_probably_testing
Not passing an absolute path name usually leads to
json splattered all over source directories,
or failure when those directories are not writeable.
If you want a foot-gun, you have to ask for it.
The JSON output is directed to subdirectories of dest,
where each subdirectory is net/url.PathEscape of the
package name, and each for each foo.go in the package,
net/url.PathEscape(foo).json is created. The first line
of foo.json contains version and context information,
and subsequent lines contains LSP-conforming JSON
describing the missing optimizations.
Change-Id: Ib83176a53a8c177ee9081aefc5ae05604ccad8a0
Reviewed-on: https://go-review.googlesource.com/c/go/+/204338
Run-TryBot: David Chase <drchase@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
2019-10-24 13:48:17 -04:00
func foo ( w , z * pair ) * int {
if * bar ( w ) > 0 {
return bar ( z )
}
2019-10-29 15:59:08 -04:00
if a [ 1 ] > 0 {
a = a [ : 2 ]
}
return & a [ 0 ]
cmd/compile: add framework for logging optimizer (non)actions to LSP
This is intended to allow IDEs to note where the optimizer
was not able to improve users' code. There may be other
applications for this, for example in studying effectiveness
of optimizer changes more quickly than running benchmarks,
or in verifying that code changes did not accidentally disable
optimizations in performance-critical code.
Logging of nilcheck (bad) for amd64 is implemented as
proof-of-concept. In general, the intent is that optimizations
that didn't happen are what will be logged, because that is
believed to be what IDE users want.
Added flag -json=version,dest
Check that version=0. (Future compilers will support a
few recent versions, I hope that version is always <=3.)
Dest is expected to be one of:
/path (or \path in Windows)
will create directory /path and fill it w/ json files
file://path
will create directory path, intended either for
I:\dont\know\enough\about\windows\paths
trustme_I_know_what_I_am_doing_probably_testing
Not passing an absolute path name usually leads to
json splattered all over source directories,
or failure when those directories are not writeable.
If you want a foot-gun, you have to ask for it.
The JSON output is directed to subdirectories of dest,
where each subdirectory is net/url.PathEscape of the
package name, and each for each foo.go in the package,
net/url.PathEscape(foo).json is created. The first line
of foo.json contains version and context information,
and subsequent lines contains LSP-conforming JSON
describing the missing optimizations.
Change-Id: Ib83176a53a8c177ee9081aefc5ae05604ccad8a0
Reviewed-on: https://go-review.googlesource.com/c/go/+/204338
Run-TryBot: David Chase <drchase@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
2019-10-24 13:48:17 -04:00
}
2020-03-04 16:33:54 -05:00
// address taking prevents closure inlining
func n ( ) int {
foo := func ( ) int { return 1 }
bar := & foo
x := ( * bar ) ( ) + foo ( )
return x
}
cmd/compile: add framework for logging optimizer (non)actions to LSP
This is intended to allow IDEs to note where the optimizer
was not able to improve users' code. There may be other
applications for this, for example in studying effectiveness
of optimizer changes more quickly than running benchmarks,
or in verifying that code changes did not accidentally disable
optimizations in performance-critical code.
Logging of nilcheck (bad) for amd64 is implemented as
proof-of-concept. In general, the intent is that optimizations
that didn't happen are what will be logged, because that is
believed to be what IDE users want.
Added flag -json=version,dest
Check that version=0. (Future compilers will support a
few recent versions, I hope that version is always <=3.)
Dest is expected to be one of:
/path (or \path in Windows)
will create directory /path and fill it w/ json files
file://path
will create directory path, intended either for
I:\dont\know\enough\about\windows\paths
trustme_I_know_what_I_am_doing_probably_testing
Not passing an absolute path name usually leads to
json splattered all over source directories,
or failure when those directories are not writeable.
If you want a foot-gun, you have to ask for it.
The JSON output is directed to subdirectories of dest,
where each subdirectory is net/url.PathEscape of the
package name, and each for each foo.go in the package,
net/url.PathEscape(foo).json is created. The first line
of foo.json contains version and context information,
and subsequent lines contains LSP-conforming JSON
describing the missing optimizations.
Change-Id: Ib83176a53a8c177ee9081aefc5ae05604ccad8a0
Reviewed-on: https://go-review.googlesource.com/c/go/+/204338
Run-TryBot: David Chase <drchase@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
2019-10-24 13:48:17 -04:00
`
func want ( t * testing . T , out string , desired string ) {
cmd/compile: add explanations to escape-analysis JSON/LSP logging
For 1.15.
From the test:
{"range":{"start":{"line":7,"character":13},"end":{...},"severity":3,"code":"leaks","source":"go compiler","message":"parameter z leaks to ~r2 with derefs=0","relatedInformation":[
{"location":{"uri":"file://T/file.go","range":{"start":{"line":9,"character":13},"end":{...}},"message":"escflow: flow: y = z:"},
{"location":{"uri":"file://T/file.go","range":{"start":{"line":9,"character":13},"end":{...}},"message":"escflow: from y = \u003cN\u003e (assign-pair)"},
{"location":{"uri":"file://T/file.go","range":{"start":{"line":9,"character":13},"end":{...}},"message":"escflow: flow: ~r1 = y:"},
{"location":{"uri":"file://T/file.go","range":{"start":{"line":4,"character":11},"end":{...}},"message":"inlineLoc"},
{"location":{"uri":"file://T/file.go","range":{"start":{"line":9,"character":13},"end":{...}},"message":"escflow: from y.b (dot of pointer)"},
{"location":{"uri":"file://T/file.go","range":{"start":{"line":4,"character":11},"end":{...}},"message":"inlineLoc"},
{"location":{"uri":"file://T/file.go","range":{"start":{"line":9,"character":13},"end":{...}},"message":"escflow: from \u0026y.b (address-of)"},
{"location":{"uri":"file://T/file.go","range":{"start":{"line":4,"character":9},"end":...}},"message":"inlineLoc"},
{"location":{"uri":"file://T/file.go","range":{"start":{"line":9,"character":13},"end":{...}},"message":"escflow: from ~r1 = \u003cN\u003e (assign-pair)"},
{"location":{"uri":"file://T/file.go","range":{"start":{"line":9,"character":3},"end":...}},"message":"escflow: flow: ~r2 = ~r1:"},
{"location":{"uri":"file://T/file.go","range":{"start":{"line":9,"character":3},"end":...}},"message":"escflow: from return (*int)(~r1) (return)"}]}
Change-Id: Idf02438801f63e487c35a928cf5a0b6d3cc48674
Reviewed-on: https://go-review.googlesource.com/c/go/+/206658
Run-TryBot: David Chase <drchase@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
2019-11-11 13:18:38 -05:00
// On Windows, Unicode escapes in the JSON output end up "normalized" elsewhere to /u....,
// so "normalize" what we're looking for to match that.
s := strings . ReplaceAll ( desired , string ( os . PathSeparator ) , "/" )
if ! strings . Contains ( out , s ) {
t . Errorf ( "did not see phrase %s in \n%s" , s , out )
cmd/compile: add framework for logging optimizer (non)actions to LSP
This is intended to allow IDEs to note where the optimizer
was not able to improve users' code. There may be other
applications for this, for example in studying effectiveness
of optimizer changes more quickly than running benchmarks,
or in verifying that code changes did not accidentally disable
optimizations in performance-critical code.
Logging of nilcheck (bad) for amd64 is implemented as
proof-of-concept. In general, the intent is that optimizations
that didn't happen are what will be logged, because that is
believed to be what IDE users want.
Added flag -json=version,dest
Check that version=0. (Future compilers will support a
few recent versions, I hope that version is always <=3.)
Dest is expected to be one of:
/path (or \path in Windows)
will create directory /path and fill it w/ json files
file://path
will create directory path, intended either for
I:\dont\know\enough\about\windows\paths
trustme_I_know_what_I_am_doing_probably_testing
Not passing an absolute path name usually leads to
json splattered all over source directories,
or failure when those directories are not writeable.
If you want a foot-gun, you have to ask for it.
The JSON output is directed to subdirectories of dest,
where each subdirectory is net/url.PathEscape of the
package name, and each for each foo.go in the package,
net/url.PathEscape(foo).json is created. The first line
of foo.json contains version and context information,
and subsequent lines contains LSP-conforming JSON
describing the missing optimizations.
Change-Id: Ib83176a53a8c177ee9081aefc5ae05604ccad8a0
Reviewed-on: https://go-review.googlesource.com/c/go/+/204338
Run-TryBot: David Chase <drchase@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
2019-10-24 13:48:17 -04:00
}
}
2019-11-02 23:57:11 -04:00
func wantN ( t * testing . T , out string , desired string , n int ) {
if strings . Count ( out , desired ) != n {
t . Errorf ( "expected exactly %d occurences of %s in \n%s" , n , desired , out )
}
}
2020-09-25 13:30:51 -04:00
func TestPathStuff ( t * testing . T ) {
sep := string ( filepath . Separator )
if path , whine := parseLogPath ( "file:///c:foo" ) ; path != "c:foo" || whine != "" { // good path
t . Errorf ( "path='%s', whine='%s'" , path , whine )
}
if path , whine := parseLogPath ( "file:///foo" ) ; path != sep + "foo" || whine != "" { // good path
t . Errorf ( "path='%s', whine='%s'" , path , whine )
}
if path , whine := parseLogPath ( "foo" ) ; path != "" || whine == "" { // BAD path
t . Errorf ( "path='%s', whine='%s'" , path , whine )
}
if sep == "\\" { // On WINDOWS ONLY
if path , whine := parseLogPath ( "C:/foo" ) ; path != "C:\\foo" || whine != "" { // good path
t . Errorf ( "path='%s', whine='%s'" , path , whine )
}
if path , whine := parseLogPath ( "c:foo" ) ; path != "" || whine == "" { // BAD path
t . Errorf ( "path='%s', whine='%s'" , path , whine )
}
if path , whine := parseLogPath ( "/foo" ) ; path != "" || whine == "" { // BAD path
t . Errorf ( "path='%s', whine='%s'" , path , whine )
}
} else { // ON UNIX ONLY
if path , whine := parseLogPath ( "/foo" ) ; path != sep + "foo" || whine != "" { // good path
t . Errorf ( "path='%s', whine='%s'" , path , whine )
}
}
}
cmd/compile: add framework for logging optimizer (non)actions to LSP
This is intended to allow IDEs to note where the optimizer
was not able to improve users' code. There may be other
applications for this, for example in studying effectiveness
of optimizer changes more quickly than running benchmarks,
or in verifying that code changes did not accidentally disable
optimizations in performance-critical code.
Logging of nilcheck (bad) for amd64 is implemented as
proof-of-concept. In general, the intent is that optimizations
that didn't happen are what will be logged, because that is
believed to be what IDE users want.
Added flag -json=version,dest
Check that version=0. (Future compilers will support a
few recent versions, I hope that version is always <=3.)
Dest is expected to be one of:
/path (or \path in Windows)
will create directory /path and fill it w/ json files
file://path
will create directory path, intended either for
I:\dont\know\enough\about\windows\paths
trustme_I_know_what_I_am_doing_probably_testing
Not passing an absolute path name usually leads to
json splattered all over source directories,
or failure when those directories are not writeable.
If you want a foot-gun, you have to ask for it.
The JSON output is directed to subdirectories of dest,
where each subdirectory is net/url.PathEscape of the
package name, and each for each foo.go in the package,
net/url.PathEscape(foo).json is created. The first line
of foo.json contains version and context information,
and subsequent lines contains LSP-conforming JSON
describing the missing optimizations.
Change-Id: Ib83176a53a8c177ee9081aefc5ae05604ccad8a0
Reviewed-on: https://go-review.googlesource.com/c/go/+/204338
Run-TryBot: David Chase <drchase@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
2019-10-24 13:48:17 -04:00
func TestLogOpt ( t * testing . T ) {
t . Parallel ( )
testenv . MustHaveGoBuild ( t )
dir , err := ioutil . TempDir ( "" , "TestLogOpt" )
if err != nil {
2020-04-11 03:33:21 +00:00
t . Fatal ( err )
cmd/compile: add framework for logging optimizer (non)actions to LSP
This is intended to allow IDEs to note where the optimizer
was not able to improve users' code. There may be other
applications for this, for example in studying effectiveness
of optimizer changes more quickly than running benchmarks,
or in verifying that code changes did not accidentally disable
optimizations in performance-critical code.
Logging of nilcheck (bad) for amd64 is implemented as
proof-of-concept. In general, the intent is that optimizations
that didn't happen are what will be logged, because that is
believed to be what IDE users want.
Added flag -json=version,dest
Check that version=0. (Future compilers will support a
few recent versions, I hope that version is always <=3.)
Dest is expected to be one of:
/path (or \path in Windows)
will create directory /path and fill it w/ json files
file://path
will create directory path, intended either for
I:\dont\know\enough\about\windows\paths
trustme_I_know_what_I_am_doing_probably_testing
Not passing an absolute path name usually leads to
json splattered all over source directories,
or failure when those directories are not writeable.
If you want a foot-gun, you have to ask for it.
The JSON output is directed to subdirectories of dest,
where each subdirectory is net/url.PathEscape of the
package name, and each for each foo.go in the package,
net/url.PathEscape(foo).json is created. The first line
of foo.json contains version and context information,
and subsequent lines contains LSP-conforming JSON
describing the missing optimizations.
Change-Id: Ib83176a53a8c177ee9081aefc5ae05604ccad8a0
Reviewed-on: https://go-review.googlesource.com/c/go/+/204338
Run-TryBot: David Chase <drchase@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
2019-10-24 13:48:17 -04:00
}
defer os . RemoveAll ( dir )
dir = fixSlash ( dir ) // Normalize the directory name as much as possible, for Windows testing
src := filepath . Join ( dir , "file.go" )
if err := ioutil . WriteFile ( src , [ ] byte ( srcCode ) , 0644 ) ; err != nil {
t . Fatal ( err )
}
outfile := filepath . Join ( dir , "file.o" )
t . Run ( "JSON_fails" , func ( t * testing . T ) {
// Test malformed flag
out , err := testLogOpt ( t , "-json=foo" , src , outfile )
if err == nil {
t . Error ( "-json=foo succeeded unexpectedly" )
}
want ( t , out , "option should be" )
want ( t , out , "number" )
// Test a version number that is currently unsupported (and should remain unsupported for a while)
out , err = testLogOpt ( t , "-json=9,foo" , src , outfile )
if err == nil {
t . Error ( "-json=0,foo succeeded unexpectedly" )
}
want ( t , out , "version must be" )
} )
2019-11-02 23:57:11 -04:00
// replace d (dir) with t ("tmpdir") and convert path separators to '/'
normalize := func ( out [ ] byte , d , t string ) string {
s := string ( out )
s = strings . ReplaceAll ( s , d , t )
s = strings . ReplaceAll ( s , string ( os . PathSeparator ) , "/" )
return s
}
// Ensure that <128 byte copies are not reported and that 128-byte copies are.
// Check at both 1 and 8-byte alignments.
t . Run ( "Copy" , func ( t * testing . T ) {
const copyCode = ` package x
func s128a1 ( x * [ 128 ] int8 ) [ 128 ] int8 {
return * x
}
func s127a1 ( x * [ 127 ] int8 ) [ 127 ] int8 {
return * x
}
func s16a8 ( x * [ 16 ] int64 ) [ 16 ] int64 {
return * x
}
func s15a8 ( x * [ 15 ] int64 ) [ 15 ] int64 {
return * x
}
`
copy := filepath . Join ( dir , "copy.go" )
if err := ioutil . WriteFile ( copy , [ ] byte ( copyCode ) , 0644 ) ; err != nil {
t . Fatal ( err )
}
outcopy := filepath . Join ( dir , "copy.o" )
// On not-amd64, test the host architecture and os
arches := [ ] string { runtime . GOARCH }
goos0 := runtime . GOOS
if runtime . GOARCH == "amd64" { // Test many things with "linux" (wasm will get "js")
2020-04-13 02:47:11 +10:00
arches = [ ] string { "arm" , "arm64" , "386" , "amd64" , "mips" , "mips64" , "ppc64le" , "riscv64" , "s390x" , "wasm" }
2019-11-02 23:57:11 -04:00
goos0 = "linux"
}
for _ , arch := range arches {
t . Run ( arch , func ( t * testing . T ) {
goos := goos0
if arch == "wasm" {
goos = "js"
}
_ , err := testCopy ( t , dir , arch , goos , copy , outcopy )
if err != nil {
t . Error ( "-json=0,file://log/opt should have succeeded" )
}
logged , err := ioutil . ReadFile ( filepath . Join ( dir , "log" , "opt" , "x" , "copy.json" ) )
if err != nil {
t . Error ( "-json=0,file://log/opt missing expected log file" )
}
slogged := normalize ( logged , string ( uriIfy ( dir ) ) , string ( uriIfy ( "tmpdir" ) ) )
t . Logf ( "%s" , slogged )
want ( t , slogged , ` { "range": { "start": { "line":3,"character":2},"end": { "line":3,"character":2}},"severity":3,"code":"copy","source":"go compiler","message":"128 bytes"} ` )
want ( t , slogged , ` { "range": { "start": { "line":9,"character":2},"end": { "line":9,"character":2}},"severity":3,"code":"copy","source":"go compiler","message":"128 bytes"} ` )
wantN ( t , slogged , ` "code":"copy" ` , 2 )
} )
}
} )
cmd/compile: add framework for logging optimizer (non)actions to LSP
This is intended to allow IDEs to note where the optimizer
was not able to improve users' code. There may be other
applications for this, for example in studying effectiveness
of optimizer changes more quickly than running benchmarks,
or in verifying that code changes did not accidentally disable
optimizations in performance-critical code.
Logging of nilcheck (bad) for amd64 is implemented as
proof-of-concept. In general, the intent is that optimizations
that didn't happen are what will be logged, because that is
believed to be what IDE users want.
Added flag -json=version,dest
Check that version=0. (Future compilers will support a
few recent versions, I hope that version is always <=3.)
Dest is expected to be one of:
/path (or \path in Windows)
will create directory /path and fill it w/ json files
file://path
will create directory path, intended either for
I:\dont\know\enough\about\windows\paths
trustme_I_know_what_I_am_doing_probably_testing
Not passing an absolute path name usually leads to
json splattered all over source directories,
or failure when those directories are not writeable.
If you want a foot-gun, you have to ask for it.
The JSON output is directed to subdirectories of dest,
where each subdirectory is net/url.PathEscape of the
package name, and each for each foo.go in the package,
net/url.PathEscape(foo).json is created. The first line
of foo.json contains version and context information,
and subsequent lines contains LSP-conforming JSON
describing the missing optimizations.
Change-Id: Ib83176a53a8c177ee9081aefc5ae05604ccad8a0
Reviewed-on: https://go-review.googlesource.com/c/go/+/204338
Run-TryBot: David Chase <drchase@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
2019-10-24 13:48:17 -04:00
// Some architectures don't fault on nil dereference, so nilchecks are eliminated differently.
2019-11-02 23:57:11 -04:00
// The N-way copy test also doesn't need to run N-ways N times.
cmd/compile: add framework for logging optimizer (non)actions to LSP
This is intended to allow IDEs to note where the optimizer
was not able to improve users' code. There may be other
applications for this, for example in studying effectiveness
of optimizer changes more quickly than running benchmarks,
or in verifying that code changes did not accidentally disable
optimizations in performance-critical code.
Logging of nilcheck (bad) for amd64 is implemented as
proof-of-concept. In general, the intent is that optimizations
that didn't happen are what will be logged, because that is
believed to be what IDE users want.
Added flag -json=version,dest
Check that version=0. (Future compilers will support a
few recent versions, I hope that version is always <=3.)
Dest is expected to be one of:
/path (or \path in Windows)
will create directory /path and fill it w/ json files
file://path
will create directory path, intended either for
I:\dont\know\enough\about\windows\paths
trustme_I_know_what_I_am_doing_probably_testing
Not passing an absolute path name usually leads to
json splattered all over source directories,
or failure when those directories are not writeable.
If you want a foot-gun, you have to ask for it.
The JSON output is directed to subdirectories of dest,
where each subdirectory is net/url.PathEscape of the
package name, and each for each foo.go in the package,
net/url.PathEscape(foo).json is created. The first line
of foo.json contains version and context information,
and subsequent lines contains LSP-conforming JSON
describing the missing optimizations.
Change-Id: Ib83176a53a8c177ee9081aefc5ae05604ccad8a0
Reviewed-on: https://go-review.googlesource.com/c/go/+/204338
Run-TryBot: David Chase <drchase@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
2019-10-24 13:48:17 -04:00
if runtime . GOARCH != "amd64" {
return
}
t . Run ( "Success" , func ( t * testing . T ) {
// This test is supposed to succeed
// Note 'file://' is the I-Know-What-I-Am-Doing way of specifying a file, also to deal with corner cases for Windows.
_ , err := testLogOptDir ( t , dir , "-json=0,file://log/opt" , src , outfile )
if err != nil {
t . Error ( "-json=0,file://log/opt should have succeeded" )
}
logged , err := ioutil . ReadFile ( filepath . Join ( dir , "log" , "opt" , "x" , "file.json" ) )
if err != nil {
t . Error ( "-json=0,file://log/opt missing expected log file" )
}
// All this delicacy with uriIfy and filepath.Join is to get this test to work right on Windows.
slogged := normalize ( logged , string ( uriIfy ( dir ) ) , string ( uriIfy ( "tmpdir" ) ) )
t . Logf ( "%s" , slogged )
2020-03-04 16:33:54 -05:00
// below shows proper nilcheck
want ( t , slogged , ` { "range": { "start": { "line":9,"character":13},"end": { "line":9,"character":13}},"severity":3,"code":"nilcheck","source":"go compiler","message":"", ` +
` "relatedInformation":[ { "location": { "uri":"file://tmpdir/file.go","range": { "start": { "line":4,"character":11},"end": { "line":4,"character":11}}},"message":"inlineLoc"}]} ` )
2019-10-29 15:59:08 -04:00
want ( t , slogged , ` { "range": { "start": { "line":11,"character":6},"end": { "line":11,"character":6}},"severity":3,"code":"isInBounds","source":"go compiler","message":""} ` )
2019-10-29 17:25:56 -04:00
want ( t , slogged , ` { "range": { "start": { "line":7,"character":6},"end": { "line":7,"character":6}},"severity":3,"code":"canInlineFunction","source":"go compiler","message":"cost: 35"} ` )
cmd/compile: add explanations to escape-analysis JSON/LSP logging
For 1.15.
From the test:
{"range":{"start":{"line":7,"character":13},"end":{...},"severity":3,"code":"leaks","source":"go compiler","message":"parameter z leaks to ~r2 with derefs=0","relatedInformation":[
{"location":{"uri":"file://T/file.go","range":{"start":{"line":9,"character":13},"end":{...}},"message":"escflow: flow: y = z:"},
{"location":{"uri":"file://T/file.go","range":{"start":{"line":9,"character":13},"end":{...}},"message":"escflow: from y = \u003cN\u003e (assign-pair)"},
{"location":{"uri":"file://T/file.go","range":{"start":{"line":9,"character":13},"end":{...}},"message":"escflow: flow: ~r1 = y:"},
{"location":{"uri":"file://T/file.go","range":{"start":{"line":4,"character":11},"end":{...}},"message":"inlineLoc"},
{"location":{"uri":"file://T/file.go","range":{"start":{"line":9,"character":13},"end":{...}},"message":"escflow: from y.b (dot of pointer)"},
{"location":{"uri":"file://T/file.go","range":{"start":{"line":4,"character":11},"end":{...}},"message":"inlineLoc"},
{"location":{"uri":"file://T/file.go","range":{"start":{"line":9,"character":13},"end":{...}},"message":"escflow: from \u0026y.b (address-of)"},
{"location":{"uri":"file://T/file.go","range":{"start":{"line":4,"character":9},"end":...}},"message":"inlineLoc"},
{"location":{"uri":"file://T/file.go","range":{"start":{"line":9,"character":13},"end":{...}},"message":"escflow: from ~r1 = \u003cN\u003e (assign-pair)"},
{"location":{"uri":"file://T/file.go","range":{"start":{"line":9,"character":3},"end":...}},"message":"escflow: flow: ~r2 = ~r1:"},
{"location":{"uri":"file://T/file.go","range":{"start":{"line":9,"character":3},"end":...}},"message":"escflow: from return (*int)(~r1) (return)"}]}
Change-Id: Idf02438801f63e487c35a928cf5a0b6d3cc48674
Reviewed-on: https://go-review.googlesource.com/c/go/+/206658
Run-TryBot: David Chase <drchase@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
2019-11-11 13:18:38 -05:00
// escape analysis explanation
want ( t , slogged , ` { "range": { "start": { "line":7,"character":13},"end": { "line":7,"character":13}},"severity":3,"code":"leak","source":"go compiler","message":"parameter z leaks to ~r2 with derefs=0", ` +
` "relatedInformation":[ ` +
` { "location": { "uri":"file://tmpdir/file.go","range": { "start": { "line":9,"character":13},"end": { "line":9,"character":13}}},"message":"escflow: flow: y = z:"}, ` +
2020-09-21 21:24:00 -07:00
` { "location": { "uri":"file://tmpdir/file.go","range": { "start": { "line":9,"character":13},"end": { "line":9,"character":13}}},"message":"escflow: from y := z (assign-pair)"}, ` +
cmd/compile: add explanations to escape-analysis JSON/LSP logging
For 1.15.
From the test:
{"range":{"start":{"line":7,"character":13},"end":{...},"severity":3,"code":"leaks","source":"go compiler","message":"parameter z leaks to ~r2 with derefs=0","relatedInformation":[
{"location":{"uri":"file://T/file.go","range":{"start":{"line":9,"character":13},"end":{...}},"message":"escflow: flow: y = z:"},
{"location":{"uri":"file://T/file.go","range":{"start":{"line":9,"character":13},"end":{...}},"message":"escflow: from y = \u003cN\u003e (assign-pair)"},
{"location":{"uri":"file://T/file.go","range":{"start":{"line":9,"character":13},"end":{...}},"message":"escflow: flow: ~r1 = y:"},
{"location":{"uri":"file://T/file.go","range":{"start":{"line":4,"character":11},"end":{...}},"message":"inlineLoc"},
{"location":{"uri":"file://T/file.go","range":{"start":{"line":9,"character":13},"end":{...}},"message":"escflow: from y.b (dot of pointer)"},
{"location":{"uri":"file://T/file.go","range":{"start":{"line":4,"character":11},"end":{...}},"message":"inlineLoc"},
{"location":{"uri":"file://T/file.go","range":{"start":{"line":9,"character":13},"end":{...}},"message":"escflow: from \u0026y.b (address-of)"},
{"location":{"uri":"file://T/file.go","range":{"start":{"line":4,"character":9},"end":...}},"message":"inlineLoc"},
{"location":{"uri":"file://T/file.go","range":{"start":{"line":9,"character":13},"end":{...}},"message":"escflow: from ~r1 = \u003cN\u003e (assign-pair)"},
{"location":{"uri":"file://T/file.go","range":{"start":{"line":9,"character":3},"end":...}},"message":"escflow: flow: ~r2 = ~r1:"},
{"location":{"uri":"file://T/file.go","range":{"start":{"line":9,"character":3},"end":...}},"message":"escflow: from return (*int)(~r1) (return)"}]}
Change-Id: Idf02438801f63e487c35a928cf5a0b6d3cc48674
Reviewed-on: https://go-review.googlesource.com/c/go/+/206658
Run-TryBot: David Chase <drchase@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
2019-11-11 13:18:38 -05:00
` { "location": { "uri":"file://tmpdir/file.go","range": { "start": { "line":9,"character":13},"end": { "line":9,"character":13}}},"message":"escflow: flow: ~r1 = y:"}, ` +
` { "location": { "uri":"file://tmpdir/file.go","range": { "start": { "line":4,"character":11},"end": { "line":4,"character":11}}},"message":"inlineLoc"}, ` +
` { "location": { "uri":"file://tmpdir/file.go","range": { "start": { "line":9,"character":13},"end": { "line":9,"character":13}}},"message":"escflow: from y.b (dot of pointer)"}, ` +
` { "location": { "uri":"file://tmpdir/file.go","range": { "start": { "line":4,"character":11},"end": { "line":4,"character":11}}},"message":"inlineLoc"}, ` +
` { "location": { "uri":"file://tmpdir/file.go","range": { "start": { "line":9,"character":13},"end": { "line":9,"character":13}}},"message":"escflow: from \u0026y.b (address-of)"}, ` +
` { "location": { "uri":"file://tmpdir/file.go","range": { "start": { "line":4,"character":9},"end": { "line":4,"character":9}}},"message":"inlineLoc"}, ` +
` { "location": { "uri":"file://tmpdir/file.go","range": { "start": { "line":9,"character":13},"end": { "line":9,"character":13}}},"message":"escflow: from ~r1 = \u003cN\u003e (assign-pair)"}, ` +
` { "location": { "uri":"file://tmpdir/file.go","range": { "start": { "line":9,"character":3},"end": { "line":9,"character":3}}},"message":"escflow: flow: ~r2 = ~r1:"}, ` +
` { "location": { "uri":"file://tmpdir/file.go","range": { "start": { "line":9,"character":3},"end": { "line":9,"character":3}}},"message":"escflow: from return (*int)(~r1) (return)"}]} ` )
cmd/compile: add framework for logging optimizer (non)actions to LSP
This is intended to allow IDEs to note where the optimizer
was not able to improve users' code. There may be other
applications for this, for example in studying effectiveness
of optimizer changes more quickly than running benchmarks,
or in verifying that code changes did not accidentally disable
optimizations in performance-critical code.
Logging of nilcheck (bad) for amd64 is implemented as
proof-of-concept. In general, the intent is that optimizations
that didn't happen are what will be logged, because that is
believed to be what IDE users want.
Added flag -json=version,dest
Check that version=0. (Future compilers will support a
few recent versions, I hope that version is always <=3.)
Dest is expected to be one of:
/path (or \path in Windows)
will create directory /path and fill it w/ json files
file://path
will create directory path, intended either for
I:\dont\know\enough\about\windows\paths
trustme_I_know_what_I_am_doing_probably_testing
Not passing an absolute path name usually leads to
json splattered all over source directories,
or failure when those directories are not writeable.
If you want a foot-gun, you have to ask for it.
The JSON output is directed to subdirectories of dest,
where each subdirectory is net/url.PathEscape of the
package name, and each for each foo.go in the package,
net/url.PathEscape(foo).json is created. The first line
of foo.json contains version and context information,
and subsequent lines contains LSP-conforming JSON
describing the missing optimizations.
Change-Id: Ib83176a53a8c177ee9081aefc5ae05604ccad8a0
Reviewed-on: https://go-review.googlesource.com/c/go/+/204338
Run-TryBot: David Chase <drchase@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
2019-10-24 13:48:17 -04:00
} )
}
func testLogOpt ( t * testing . T , flag , src , outfile string ) ( string , error ) {
run := [ ] string { testenv . GoToolPath ( t ) , "tool" , "compile" , flag , "-o" , outfile , src }
t . Log ( run )
cmd := exec . Command ( run [ 0 ] , run [ 1 : ] ... )
out , err := cmd . CombinedOutput ( )
t . Logf ( "%s" , out )
return string ( out ) , err
}
func testLogOptDir ( t * testing . T , dir , flag , src , outfile string ) ( string , error ) {
// Notice the specified import path "x"
run := [ ] string { testenv . GoToolPath ( t ) , "tool" , "compile" , "-p" , "x" , flag , "-o" , outfile , src }
t . Log ( run )
cmd := exec . Command ( run [ 0 ] , run [ 1 : ] ... )
cmd . Dir = dir
out , err := cmd . CombinedOutput ( )
t . Logf ( "%s" , out )
return string ( out ) , err
}
2019-11-02 23:57:11 -04:00
func testCopy ( t * testing . T , dir , goarch , goos , src , outfile string ) ( string , error ) {
// Notice the specified import path "x"
run := [ ] string { testenv . GoToolPath ( t ) , "tool" , "compile" , "-p" , "x" , "-json=0,file://log/opt" , "-o" , outfile , src }
t . Log ( run )
cmd := exec . Command ( run [ 0 ] , run [ 1 : ] ... )
cmd . Dir = dir
2020-04-07 15:52:05 +03:00
cmd . Env = append ( os . Environ ( ) , "GOARCH=" + goarch , "GOOS=" + goos )
2019-11-02 23:57:11 -04:00
out , err := cmd . CombinedOutput ( )
t . Logf ( "%s" , out )
return string ( out ) , err
}