1
0
mirror of https://github.com/golang/go synced 2024-11-18 18:54:42 -07:00

go/ssa: convert the objlookup tests to the new marker syntax

Change-Id: I5df3a3cc3d3ab236a6ad964914393a2ccb29803b
Reviewed-on: https://go-review.googlesource.com/c/145637
Run-TryBot: Ian Cottrell <iancottrell@google.com>
Run-TryBot: Michael Matloob <matloob@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Michael Matloob <matloob@golang.org>
This commit is contained in:
Ian Cottrell 2018-10-29 16:10:42 -04:00
parent 7529026f5b
commit c779628d65
2 changed files with 116 additions and 88 deletions

View File

@ -13,8 +13,8 @@ import (
"go/parser"
"go/token"
"go/types"
"io/ioutil"
"os"
"regexp"
"runtime"
"strings"
"testing"
@ -32,10 +32,14 @@ func TestObjValueLookup(t *testing.T) {
}
conf := loader.Config{ParserMode: parser.ParseComments}
f, err := conf.ParseFile("testdata/objlookup.go", nil)
src, err := ioutil.ReadFile("testdata/objlookup.go")
if err != nil {
t.Error(err)
return
t.Fatal(err)
}
readFile := func(filename string) ([]byte, error) { return src, nil }
f, err := conf.ParseFile("testdata/objlookup.go", src)
if err != nil {
t.Fatal(err)
}
conf.CreateFromFiles("main", f)
@ -43,16 +47,40 @@ func TestObjValueLookup(t *testing.T) {
// kind of ssa.Value we expect (represented "Constant", "&Alloc").
expectations := make(map[string]string)
// Find all annotations of form x::BinOp, &y::Alloc, etc.
re := regexp.MustCompile(`(\b|&)?(\w*)::(\w*)\b`)
for _, c := range f.Comments {
text := c.Text()
pos := conf.Fset.Position(c.Pos())
for _, m := range re.FindAllStringSubmatch(text, -1) {
key := fmt.Sprintf("%s:%d", m[2], pos.Line)
value := m[1] + m[3]
expectations[key] = value
// Each note of the form @ssa(x, "BinOp") in testdata/objlookup.go
// specifies an expectation that an object named x declared on the
// same line is associated with an an ssa.Value of type *ssa.BinOp.
notes, err := expect.Extract(conf.Fset, f)
if err != nil {
t.Fatal(err)
}
for _, n := range notes {
if n.Name != "ssa" {
t.Errorf("%v: unexpected note type %q, want \"ssa\"", conf.Fset.Position(n.Pos), n.Name)
continue
}
if len(n.Args) != 2 {
t.Errorf("%v: ssa has %d args, want 2", conf.Fset.Position(n.Pos), len(n.Args))
continue
}
ident, ok := n.Args[0].(expect.Identifier)
if !ok {
t.Errorf("%v: got %v for arg 1, want identifier", conf.Fset.Position(n.Pos), n.Args[0])
continue
}
exp, ok := n.Args[1].(string)
if !ok {
t.Errorf("%v: got %v for arg 2, want string", conf.Fset.Position(n.Pos), n.Args[1])
continue
}
p, _, err := expect.MatchBefore(conf.Fset, readFile, n.Pos, string(ident))
if err != nil {
t.Error(err)
continue
}
pos := conf.Fset.Position(p)
key := fmt.Sprintf("%s:%d", ident, pos.Line)
expectations[key] = exp
}
iprog, err := conf.Load()

View File

@ -24,7 +24,7 @@ func (*J) method() {}
const globalConst = 0
var globalVar int // &globalVar::Global
var globalVar int //@ ssa(globalVar,"&Global")
func globalFunc() {}
@ -33,128 +33,128 @@ type I interface {
}
type S struct {
x int // x::nil
x int //@ ssa(x,"nil")
}
func main() {
print(globalVar) // globalVar::UnOp
globalVar = 1 // globalVar::Const
print(globalVar) //@ ssa(globalVar,"UnOp")
globalVar = 1 //@ ssa(globalVar,"Const")
var v0 int = 1 // v0::Const (simple local value spec)
if v0 > 0 { // v0::Const
v0 = 2 // v0::Const
var v0 int = 1 //@ ssa(v0,"Const") // simple local value spec
if v0 > 0 { //@ ssa(v0,"Const")
v0 = 2 //@ ssa(v0,"Const")
}
print(v0) // v0::Phi
print(v0) //@ ssa(v0,"Phi")
// v1 is captured and thus implicitly address-taken.
var v1 int = 1 // v1::Const
v1 = 2 // v1::Const
fmt.Println(v1) // v1::UnOp (load)
f := func(param int) { // f::MakeClosure param::Parameter
if y := 1; y > 0 { // y::Const
print(v1, param) // v1::UnOp (load) param::Parameter
var v1 int = 1 //@ ssa(v1,"Const")
v1 = 2 //@ ssa(v1,"Const")
fmt.Println(v1) //@ ssa(v1,"UnOp") // load
f := func(param int) { //@ ssa(f,"MakeClosure"), ssa(param,"Parameter")
if y := 1; y > 0 { //@ ssa(y,"Const")
print(v1, param) //@ ssa(v1,"UnOp") /*load*/, ssa(param,"Parameter")
}
param = 2 // param::Const
println(param) // param::Const
param = 2 //@ ssa(param,"Const")
println(param) //@ ssa(param,"Const")
}
f(0) // f::MakeClosure
f(0) //@ ssa(f,"MakeClosure")
var v2 int // v2::Const (implicitly zero-initialized local value spec)
print(v2) // v2::Const
var v2 int //@ ssa(v2,"Const") // implicitly zero-initialized local value spec
print(v2) //@ ssa(v2,"Const")
m := make(map[string]int) // m::MakeMap
m := make(map[string]int) //@ ssa(m,"MakeMap")
// Local value spec with multi-valued RHS:
var v3, v4 = m[""] // v3::Extract v4::Extract m::MakeMap
print(v3) // v3::Extract
print(v4) // v4::Extract
var v3, v4 = m[""] //@ ssa(v3,"Extract"), ssa(v4,"Extract"), ssa(m,"MakeMap")
print(v3) //@ ssa(v3,"Extract")
print(v4) //@ ssa(v4,"Extract")
v3++ // v3::BinOp (assign with op)
v3 += 2 // v3::BinOp (assign with op)
v3++ //@ ssa(v3,"BinOp") // assign with op
v3 += 2 //@ ssa(v3,"BinOp") // assign with op
v5, v6 := false, "" // v5::Const v6::Const (defining assignment)
print(v5) // v5::Const
print(v6) // v6::Const
v5, v6 := false, "" //@ ssa(v5,"Const"), ssa(v6,"Const") // defining assignment
print(v5) //@ ssa(v5,"Const")
print(v6) //@ ssa(v6,"Const")
var v7 S // &v7::Alloc
v7.x = 1 // &v7::Alloc &x::FieldAddr
print(v7.x) // &v7::Alloc &x::FieldAddr
var v7 S //@ ssa(v7,"&Alloc")
v7.x = 1 //@ ssa(v7,"&Alloc"), ssa(x,"&FieldAddr")
print(v7.x) //@ ssa(v7,"&Alloc"), ssa(x,"&FieldAddr")
var v8 [1]int // &v8::Alloc
v8[0] = 0 // &v8::Alloc
print(v8[:]) // &v8::Alloc
_ = v8[0] // &v8::Alloc
_ = v8[:][0] // &v8::Alloc
v8ptr := &v8 // v8ptr::Alloc &v8::Alloc
_ = v8ptr[0] // v8ptr::Alloc
_ = *v8ptr // v8ptr::Alloc
var v8 [1]int //@ ssa(v8,"&Alloc")
v8[0] = 0 //@ ssa(v8,"&Alloc")
print(v8[:]) //@ ssa(v8,"&Alloc")
_ = v8[0] //@ ssa(v8,"&Alloc")
_ = v8[:][0] //@ ssa(v8,"&Alloc")
v8ptr := &v8 //@ ssa(v8ptr,"Alloc"), ssa(v8,"&Alloc")
_ = v8ptr[0] //@ ssa(v8ptr,"Alloc")
_ = *v8ptr //@ ssa(v8ptr,"Alloc")
v8a := make([]int, 1) // v8a::Slice
v8a[0] = 0 // v8a::Slice
print(v8a[:]) // v8a::Slice
v8a := make([]int, 1) //@ ssa(v8a,"Slice")
v8a[0] = 0 //@ ssa(v8a,"Slice")
print(v8a[:]) //@ ssa(v8a,"Slice")
v9 := S{} // &v9::Alloc
v9 := S{} //@ ssa(v9,"&Alloc")
v10 := &v9 // v10::Alloc &v9::Alloc
_ = v10 // v10::Alloc
v10 := &v9 //@ ssa(v10,"Alloc"), ssa(v9,"&Alloc")
_ = v10 //@ ssa(v10,"Alloc")
var v11 *J = nil // v11::Const
v11.method() // v11::Const
var v11 *J = nil //@ ssa(v11,"Const")
v11.method() //@ ssa(v11,"Const")
var v12 J // &v12::Alloc
v12.method() // &v12::Alloc (implicitly address-taken)
var v12 J //@ ssa(v12,"&Alloc")
v12.method() //@ ssa(v12,"&Alloc") // implicitly address-taken
// NB, in the following, 'method' resolves to the *types.Func
// of (*J).method, so it doesn't help us locate the specific
// ssa.Values here: a bound-method closure and a promotion
// wrapper.
_ = v11.method // v11::Const
_ = (*struct{ J }).method // J::nil
_ = v11.method //@ ssa(v11,"Const")
_ = (*struct{ J }).method //@ ssa(J,"nil")
// These vars are not optimised away.
if false {
v13 := 0 // v13::Const
println(v13) // v13::Const
v13 := 0 //@ ssa(v13,"Const")
println(v13) //@ ssa(v13,"Const")
}
switch x := 1; x { // x::Const
case v0: // v0::Phi
switch x := 1; x { //@ ssa(x,"Const")
case v0: //@ ssa(v0,"Phi")
}
for k, v := range m { // k::Extract v::Extract m::MakeMap
_ = k // k::Extract
v++ // v::BinOp
for k, v := range m { //@ ssa(k,"Extract"), ssa(v,"Extract"), ssa(m,"MakeMap")
_ = k //@ ssa(k,"Extract")
v++ //@ ssa(v,"BinOp")
}
if y := 0; y > 1 { // y::Const y::Const
if y := 0; y > 1 { //@ ssa(y,"Const"), ssa(y,"Const")
}
var i interface{} // i::Const (nil interface)
i = 1 // i::MakeInterface
switch i := i.(type) { // i::MakeInterface i::MakeInterface
var i interface{} //@ ssa(i,"Const") // nil interface
i = 1 //@ ssa(i,"MakeInterface")
switch i := i.(type) { //@ ssa(i,"MakeInterface"), ssa(i,"MakeInterface")
case int:
println(i) // i::Extract
println(i) //@ ssa(i,"Extract")
}
ch := make(chan int) // ch::MakeChan
ch := make(chan int) //@ ssa(ch,"MakeChan")
select {
case x := <-ch: // x::UnOp (receive) ch::MakeChan
_ = x // x::UnOp
case x := <-ch: //@ ssa(x,"UnOp") /*receive*/, ssa(ch,"MakeChan")
_ = x //@ ssa(x,"UnOp")
}
// .Op is an inter-package FieldVal-selection.
var err os.PathError // &err::Alloc
_ = err.Op // &err::Alloc &Op::FieldAddr
_ = &err.Op // &err::Alloc &Op::FieldAddr
var err os.PathError //@ ssa(err,"&Alloc")
_ = err.Op //@ ssa(err,"&Alloc"), ssa(Op,"&FieldAddr")
_ = &err.Op //@ ssa(err,"&Alloc"), ssa(Op,"&FieldAddr")
// Exercise corner-cases of lvalues vs rvalues.
// (Guessing IsAddr from the 'pointerness' won't cut it here.)
type N *N
var n N // n::Const
n1 := n // n1::Const n::Const
n2 := &n1 // n2::Alloc &n1::Alloc
n3 := *n2 // n3::UnOp n2::Alloc
n4 := **n3 // n4::UnOp n3::UnOp
_ = n4 // n4::UnOp
var n N //@ ssa(n,"Const")
n1 := n //@ ssa(n1,"Const"), ssa(n,"Const")
n2 := &n1 //@ ssa(n2,"Alloc"), ssa(n1,"&Alloc")
n3 := *n2 //@ ssa(n3,"UnOp"), ssa(n2,"Alloc")
n4 := **n3 //@ ssa(n4,"UnOp"), ssa(n3,"UnOp")
_ = n4 //@ ssa(n4,"UnOp")
}