github.com/stingnevermore/go@v0.0.0-20180120041312-3810f5bfed72/src/cmd/compile/internal/gc/testdata/addressed.go (about) 1 // Copyright 2015 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package main 6 7 import "fmt" 8 9 var output string 10 11 func mypanic(s string) { 12 fmt.Printf(output) 13 panic(s) 14 } 15 16 func assertEqual(x, y int) { 17 if x != y { 18 mypanic("assertEqual failed") 19 } 20 } 21 22 func main() { 23 x := f1_ssa(2, 3) 24 output += fmt.Sprintln("*x is", *x) 25 output += fmt.Sprintln("Gratuitously use some stack") 26 output += fmt.Sprintln("*x is", *x) 27 assertEqual(*x, 9) 28 29 w := f3a_ssa(6) 30 output += fmt.Sprintln("*w is", *w) 31 output += fmt.Sprintln("Gratuitously use some stack") 32 output += fmt.Sprintln("*w is", *w) 33 assertEqual(*w, 6) 34 35 y := f3b_ssa(12) 36 output += fmt.Sprintln("*y.(*int) is", *y.(*int)) 37 output += fmt.Sprintln("Gratuitously use some stack") 38 output += fmt.Sprintln("*y.(*int) is", *y.(*int)) 39 assertEqual(*y.(*int), 12) 40 41 z := f3c_ssa(8) 42 output += fmt.Sprintln("*z.(*int) is", *z.(*int)) 43 output += fmt.Sprintln("Gratuitously use some stack") 44 output += fmt.Sprintln("*z.(*int) is", *z.(*int)) 45 assertEqual(*z.(*int), 8) 46 47 args() 48 test_autos() 49 } 50 51 //go:noinline 52 func f1_ssa(x, y int) *int { 53 x = x*y + y 54 return &x 55 } 56 57 //go:noinline 58 func f3a_ssa(x int) *int { 59 return &x 60 } 61 62 //go:noinline 63 func f3b_ssa(x int) interface{} { // ./foo.go:15: internal error: f3b_ssa ~r1 (type interface {}) recorded as live on entry 64 return &x 65 } 66 67 //go:noinline 68 func f3c_ssa(y int) interface{} { 69 x := y 70 return &x 71 } 72 73 type V struct { 74 p *V 75 w, x int64 76 } 77 78 func args() { 79 v := V{p: nil, w: 1, x: 1} 80 a := V{p: &v, w: 2, x: 2} 81 b := V{p: &v, w: 0, x: 0} 82 i := v.args_ssa(a, b) 83 output += fmt.Sprintln("i=", i) 84 assertEqual(int(i), 2) 85 } 86 87 //go:noinline 88 func (v V) args_ssa(a, b V) int64 { 89 if v.w == 0 { 90 return v.x 91 } 92 if v.w == 1 { 93 return a.x 94 } 95 if v.w == 2 { 96 return b.x 97 } 98 b.p.p = &a // v.p in caller = &a 99 100 return -1 101 } 102 103 func test_autos() { 104 test(11) 105 test(12) 106 test(13) 107 test(21) 108 test(22) 109 test(23) 110 test(31) 111 test(32) 112 } 113 114 func test(which int64) { 115 output += fmt.Sprintln("test", which) 116 v1 := V{w: 30, x: 3, p: nil} 117 v2, v3 := v1.autos_ssa(which, 10, 1, 20, 2) 118 if which != v2.val() { 119 output += fmt.Sprintln("Expected which=", which, "got v2.val()=", v2.val()) 120 mypanic("Failure of expected V value") 121 } 122 if v2.p.val() != v3.val() { 123 output += fmt.Sprintln("Expected v2.p.val()=", v2.p.val(), "got v3.val()=", v3.val()) 124 mypanic("Failure of expected V.p value") 125 } 126 if which != v3.p.p.p.p.p.p.p.val() { 127 output += fmt.Sprintln("Expected which=", which, "got v3.p.p.p.p.p.p.p.val()=", v3.p.p.p.p.p.p.p.val()) 128 mypanic("Failure of expected V.p value") 129 } 130 } 131 132 func (v V) val() int64 { 133 return v.w + v.x 134 } 135 136 // autos_ssa uses contents of v and parameters w1, w2, x1, x2 137 // to initialize a bunch of locals, all of which have their 138 // address taken to force heap allocation, and then based on 139 // the value of which a pair of those locals are copied in 140 // various ways to the two results y, and z, which are also 141 // addressed. Which is expected to be one of 11-13, 21-23, 31, 32, 142 // and y.val() should be equal to which and y.p.val() should 143 // be equal to z.val(). Also, x(.p)**8 == x; that is, the 144 // autos are all linked into a ring. 145 //go:noinline 146 func (v V) autos_ssa(which, w1, x1, w2, x2 int64) (y, z V) { 147 fill_ssa(v.w, v.x, &v, v.p) // gratuitous no-op to force addressing 148 var a, b, c, d, e, f, g, h V 149 fill_ssa(w1, x1, &a, &b) 150 fill_ssa(w1, x2, &b, &c) 151 fill_ssa(w1, v.x, &c, &d) 152 fill_ssa(w2, x1, &d, &e) 153 fill_ssa(w2, x2, &e, &f) 154 fill_ssa(w2, v.x, &f, &g) 155 fill_ssa(v.w, x1, &g, &h) 156 fill_ssa(v.w, x2, &h, &a) 157 switch which { 158 case 11: 159 y = a 160 z.getsI(&b) 161 case 12: 162 y.gets(&b) 163 z = c 164 case 13: 165 y.gets(&c) 166 z = d 167 case 21: 168 y.getsI(&d) 169 z.gets(&e) 170 case 22: 171 y = e 172 z = f 173 case 23: 174 y.gets(&f) 175 z.getsI(&g) 176 case 31: 177 y = g 178 z.gets(&h) 179 case 32: 180 y.getsI(&h) 181 z = a 182 default: 183 184 panic("") 185 } 186 return 187 } 188 189 // gets is an address-mentioning way of implementing 190 // structure assignment. 191 //go:noinline 192 func (to *V) gets(from *V) { 193 *to = *from 194 } 195 196 // gets is an address-and-interface-mentioning way of 197 // implementing structure assignment. 198 //go:noinline 199 func (to *V) getsI(from interface{}) { 200 *to = *from.(*V) 201 } 202 203 // fill_ssa initializes r with V{w:w, x:x, p:p} 204 //go:noinline 205 func fill_ssa(w, x int64, r, p *V) { 206 *r = V{w: w, x: x, p: p} 207 }