| 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 | } |
| 161 |
Members