github.com/euank/go@v0.0.0-20160829210321-495514729181/src/cmd/compile/internal/gc/testdata/addressed_ssa.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  }