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