161 lines
4.7 KiB
Go
161 lines
4.7 KiB
Go
//+build ignore
|
|
|
|
package main
|
|
|
|
// This file is the input to TestObjValueLookup in source_test.go,
|
|
// which ensures that each occurrence of an ident defining or
|
|
// referring to a func, var or const object can be mapped to its
|
|
// corresponding SSA Value.
|
|
//
|
|
// For every reference to a var object, we use annotations in comments
|
|
// to denote both the expected SSA Value kind, and whether to expect
|
|
// its value (x) or its address (&x).
|
|
//
|
|
// For const and func objects, the results don't vary by reference and
|
|
// are always values not addresses, so no annotations are needed. The
|
|
// declaration is enough.
|
|
|
|
import "fmt"
|
|
import "os"
|
|
|
|
type J int
|
|
|
|
func (*J) method() {}
|
|
|
|
const globalConst = 0
|
|
|
|
var globalVar int //@ ssa(globalVar,"&Global")
|
|
|
|
func globalFunc() {}
|
|
|
|
type I interface {
|
|
interfaceMethod()
|
|
}
|
|
|
|
type S struct {
|
|
x int //@ ssa(x,"nil")
|
|
}
|
|
|
|
func main() {
|
|
print(globalVar) //@ ssa(globalVar,"UnOp")
|
|
globalVar = 1 //@ ssa(globalVar,"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) //@ ssa(v0,"Phi")
|
|
|
|
// v1 is captured and thus implicitly address-taken.
|
|
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 //@ ssa(param,"Const")
|
|
println(param) //@ ssa(param,"Const")
|
|
}
|
|
|
|
f(0) //@ ssa(f,"MakeClosure")
|
|
|
|
var v2 int //@ ssa(v2,"Const") // implicitly zero-initialized local value spec
|
|
print(v2) //@ ssa(v2,"Const")
|
|
|
|
m := make(map[string]int) //@ ssa(m,"MakeMap")
|
|
|
|
// Local value spec with multi-valued RHS:
|
|
var v3, v4 = m[""] //@ ssa(v3,"Extract"), ssa(v4,"Extract"), ssa(m,"MakeMap")
|
|
print(v3) //@ ssa(v3,"Extract")
|
|
print(v4) //@ ssa(v4,"Extract")
|
|
|
|
v3++ //@ ssa(v3,"BinOp") // assign with op
|
|
v3 += 2 //@ ssa(v3,"BinOp") // assign with op
|
|
|
|
v5, v6 := false, "" //@ ssa(v5,"Const"), ssa(v6,"Const") // defining assignment
|
|
print(v5) //@ ssa(v5,"Const")
|
|
print(v6) //@ ssa(v6,"Const")
|
|
|
|
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 //@ 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) //@ ssa(v8a,"Slice")
|
|
v8a[0] = 0 //@ ssa(v8a,"Slice")
|
|
print(v8a[:]) //@ ssa(v8a,"Slice")
|
|
|
|
v9 := S{} //@ ssa(v9,"&Alloc")
|
|
|
|
v10 := &v9 //@ ssa(v10,"Alloc"), ssa(v9,"&Alloc")
|
|
_ = v10 //@ ssa(v10,"Alloc")
|
|
|
|
var v11 *J = nil //@ ssa(v11,"Const")
|
|
v11.method() //@ ssa(v11,"Const")
|
|
|
|
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 //@ ssa(v11,"Const")
|
|
_ = (*struct{ J }).method //@ ssa(J,"nil")
|
|
|
|
// These vars are not optimised away.
|
|
if false {
|
|
v13 := 0 //@ ssa(v13,"Const")
|
|
println(v13) //@ ssa(v13,"Const")
|
|
}
|
|
|
|
switch x := 1; x { //@ ssa(x,"Const")
|
|
case v0: //@ ssa(v0,"Phi")
|
|
}
|
|
|
|
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 { //@ ssa(y,"Const"), ssa(y,"Const")
|
|
}
|
|
|
|
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) //@ ssa(i,"Extract")
|
|
}
|
|
|
|
ch := make(chan int) //@ ssa(ch,"MakeChan")
|
|
select {
|
|
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 //@ 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 //@ 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")
|
|
}
|