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