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  }