github.com/jd-ly/tools@v0.5.7/go/ssa/testdata/objlookup.go (about) 1 // +build ignore 2 3 package main 4 5 // This file is the input to TestObjValueLookup in source_test.go, 6 // which ensures that each occurrence of an ident defining or 7 // referring to a func, var or const object can be mapped to its 8 // corresponding SSA Value. 9 // 10 // For every reference to a var object, we use annotations in comments 11 // to denote both the expected SSA Value kind, and whether to expect 12 // its value (x) or its address (&x). 13 // 14 // For const and func objects, the results don't vary by reference and 15 // are always values not addresses, so no annotations are needed. The 16 // declaration is enough. 17 18 import "fmt" 19 import "os" 20 21 type J int 22 23 func (*J) method() {} 24 25 const globalConst = 0 26 27 var globalVar int //@ ssa(globalVar,"&Global") 28 29 func globalFunc() {} 30 31 type I interface { 32 interfaceMethod() 33 } 34 35 type S struct { 36 x int //@ ssa(x,"nil") 37 } 38 39 func main() { 40 print(globalVar) //@ ssa(globalVar,"UnOp") 41 globalVar = 1 //@ ssa(globalVar,"Const") 42 43 var v0 int = 1 //@ ssa(v0,"Const") // simple local value spec 44 if v0 > 0 { //@ ssa(v0,"Const") 45 v0 = 2 //@ ssa(v0,"Const") 46 } 47 print(v0) //@ ssa(v0,"Phi") 48 49 // v1 is captured and thus implicitly address-taken. 50 var v1 int = 1 //@ ssa(v1,"Const") 51 v1 = 2 //@ ssa(v1,"Const") 52 fmt.Println(v1) //@ ssa(v1,"UnOp") // load 53 f := func(param int) { //@ ssa(f,"MakeClosure"), ssa(param,"Parameter") 54 if y := 1; y > 0 { //@ ssa(y,"Const") 55 print(v1, param) //@ ssa(v1,"UnOp") /*load*/, ssa(param,"Parameter") 56 } 57 param = 2 //@ ssa(param,"Const") 58 println(param) //@ ssa(param,"Const") 59 } 60 61 f(0) //@ ssa(f,"MakeClosure") 62 63 var v2 int //@ ssa(v2,"Const") // implicitly zero-initialized local value spec 64 print(v2) //@ ssa(v2,"Const") 65 66 m := make(map[string]int) //@ ssa(m,"MakeMap") 67 68 // Local value spec with multi-valued RHS: 69 var v3, v4 = m[""] //@ ssa(v3,"Extract"), ssa(v4,"Extract"), ssa(m,"MakeMap") 70 print(v3) //@ ssa(v3,"Extract") 71 print(v4) //@ ssa(v4,"Extract") 72 73 v3++ //@ ssa(v3,"BinOp") // assign with op 74 v3 += 2 //@ ssa(v3,"BinOp") // assign with op 75 76 v5, v6 := false, "" //@ ssa(v5,"Const"), ssa(v6,"Const") // defining assignment 77 print(v5) //@ ssa(v5,"Const") 78 print(v6) //@ ssa(v6,"Const") 79 80 var v7 S //@ ssa(v7,"&Alloc") 81 v7.x = 1 //@ ssa(v7,"&Alloc"), ssa(x,"&FieldAddr") 82 print(v7.x) //@ ssa(v7,"&Alloc"), ssa(x,"&FieldAddr") 83 84 var v8 [1]int //@ ssa(v8,"&Alloc") 85 v8[0] = 0 //@ ssa(v8,"&Alloc") 86 print(v8[:]) //@ ssa(v8,"&Alloc") 87 _ = v8[0] //@ ssa(v8,"&Alloc") 88 _ = v8[:][0] //@ ssa(v8,"&Alloc") 89 v8ptr := &v8 //@ ssa(v8ptr,"Alloc"), ssa(v8,"&Alloc") 90 _ = v8ptr[0] //@ ssa(v8ptr,"Alloc") 91 _ = *v8ptr //@ ssa(v8ptr,"Alloc") 92 93 v8a := make([]int, 1) //@ ssa(v8a,"Slice") 94 v8a[0] = 0 //@ ssa(v8a,"Slice") 95 print(v8a[:]) //@ ssa(v8a,"Slice") 96 97 v9 := S{} //@ ssa(v9,"&Alloc") 98 99 v10 := &v9 //@ ssa(v10,"Alloc"), ssa(v9,"&Alloc") 100 _ = v10 //@ ssa(v10,"Alloc") 101 102 var v11 *J = nil //@ ssa(v11,"Const") 103 v11.method() //@ ssa(v11,"Const") 104 105 var v12 J //@ ssa(v12,"&Alloc") 106 v12.method() //@ ssa(v12,"&Alloc") // implicitly address-taken 107 108 // NB, in the following, 'method' resolves to the *types.Func 109 // of (*J).method, so it doesn't help us locate the specific 110 // ssa.Values here: a bound-method closure and a promotion 111 // wrapper. 112 _ = v11.method //@ ssa(v11,"Const") 113 _ = (*struct{ J }).method //@ ssa(J,"nil") 114 115 // These vars are not optimised away. 116 if false { 117 v13 := 0 //@ ssa(v13,"Const") 118 println(v13) //@ ssa(v13,"Const") 119 } 120 121 switch x := 1; x { //@ ssa(x,"Const") 122 case v0: //@ ssa(v0,"Phi") 123 } 124 125 for k, v := range m { //@ ssa(k,"Extract"), ssa(v,"Extract"), ssa(m,"MakeMap") 126 _ = k //@ ssa(k,"Extract") 127 v++ //@ ssa(v,"BinOp") 128 } 129 130 if y := 0; y > 1 { //@ ssa(y,"Const"), ssa(y,"Const") 131 } 132 133 var i interface{} //@ ssa(i,"Const") // nil interface 134 i = 1 //@ ssa(i,"MakeInterface") 135 switch i := i.(type) { //@ ssa(i,"MakeInterface"), ssa(i,"MakeInterface") 136 case int: 137 println(i) //@ ssa(i,"Extract") 138 } 139 140 ch := make(chan int) //@ ssa(ch,"MakeChan") 141 select { 142 case x := <-ch: //@ ssa(x,"UnOp") /*receive*/, ssa(ch,"MakeChan") 143 _ = x //@ ssa(x,"UnOp") 144 } 145 146 // .Op is an inter-package FieldVal-selection. 147 var err os.PathError //@ ssa(err,"&Alloc") 148 _ = err.Op //@ ssa(err,"&Alloc"), ssa(Op,"&FieldAddr") 149 _ = &err.Op //@ ssa(err,"&Alloc"), ssa(Op,"&FieldAddr") 150 151 // Exercise corner-cases of lvalues vs rvalues. 152 // (Guessing IsAddr from the 'pointerness' won't cut it here.) 153 type N *N 154 var n N //@ ssa(n,"Const") 155 n1 := n //@ ssa(n1,"Const"), ssa(n,"Const") 156 n2 := &n1 //@ ssa(n2,"Alloc"), ssa(n1,"&Alloc") 157 n3 := *n2 //@ ssa(n3,"UnOp"), ssa(n2,"Alloc") 158 n4 := **n3 //@ ssa(n4,"UnOp"), ssa(n3,"UnOp") 159 _ = n4 //@ ssa(n4,"UnOp") 160 }