Home | History | Annotate | Download | only in testdata
      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 	"runtime"
     10 	"unsafe"
     11 )
     12 
     13 // global pointer slot
     14 var a *[8]uint
     15 
     16 // unfoldable true
     17 var b = true
     18 
     19 // Test to make sure that a pointer value which is alive
     20 // across a call is retained, even when there are matching
     21 // conversions to/from uintptr around the call.
     22 // We arrange things very carefully to have to/from
     23 // conversions on either side of the call which cannot be
     24 // combined with any other conversions.
     25 func f_ssa() *[8]uint {
     26 	// Make x a uintptr pointing to where a points.
     27 	var x uintptr
     28 	if b {
     29 		x = uintptr(unsafe.Pointer(a))
     30 	} else {
     31 		x = 0
     32 	}
     33 	// Clobber the global pointer. The only live ref
     34 	// to the allocated object is now x.
     35 	a = nil
     36 
     37 	// Convert to pointer so it should hold
     38 	// the object live across GC call.
     39 	p := unsafe.Pointer(x)
     40 
     41 	// Call gc.
     42 	runtime.GC()
     43 
     44 	// Convert back to uintptr.
     45 	y := uintptr(p)
     46 
     47 	// Mess with y so that the subsequent cast
     48 	// to unsafe.Pointer can't be combined with the
     49 	// uintptr cast above.
     50 	var z uintptr
     51 	if b {
     52 		z = y
     53 	} else {
     54 		z = 0
     55 	}
     56 	return (*[8]uint)(unsafe.Pointer(z))
     57 }
     58 
     59 // g_ssa is the same as f_ssa, but with a bit of pointer
     60 // arithmetic for added insanity.
     61 func g_ssa() *[7]uint {
     62 	// Make x a uintptr pointing to where a points.
     63 	var x uintptr
     64 	if b {
     65 		x = uintptr(unsafe.Pointer(a))
     66 	} else {
     67 		x = 0
     68 	}
     69 	// Clobber the global pointer. The only live ref
     70 	// to the allocated object is now x.
     71 	a = nil
     72 
     73 	// Offset x by one int.
     74 	x += unsafe.Sizeof(int(0))
     75 
     76 	// Convert to pointer so it should hold
     77 	// the object live across GC call.
     78 	p := unsafe.Pointer(x)
     79 
     80 	// Call gc.
     81 	runtime.GC()
     82 
     83 	// Convert back to uintptr.
     84 	y := uintptr(p)
     85 
     86 	// Mess with y so that the subsequent cast
     87 	// to unsafe.Pointer can't be combined with the
     88 	// uintptr cast above.
     89 	var z uintptr
     90 	if b {
     91 		z = y
     92 	} else {
     93 		z = 0
     94 	}
     95 	return (*[7]uint)(unsafe.Pointer(z))
     96 }
     97 
     98 func testf() {
     99 	a = new([8]uint)
    100 	for i := 0; i < 8; i++ {
    101 		a[i] = 0xabcd
    102 	}
    103 	c := f_ssa()
    104 	for i := 0; i < 8; i++ {
    105 		if c[i] != 0xabcd {
    106 			fmt.Printf("%d:%x\n", i, c[i])
    107 			panic("bad c")
    108 		}
    109 	}
    110 }
    111 
    112 func testg() {
    113 	a = new([8]uint)
    114 	for i := 0; i < 8; i++ {
    115 		a[i] = 0xabcd
    116 	}
    117 	c := g_ssa()
    118 	for i := 0; i < 7; i++ {
    119 		if c[i] != 0xabcd {
    120 			fmt.Printf("%d:%x\n", i, c[i])
    121 			panic("bad c")
    122 		}
    123 	}
    124 }
    125 
    126 func alias_ssa(ui64 *uint64, ui32 *uint32) uint32 {
    127 	*ui32 = 0xffffffff
    128 	*ui64 = 0                  // store
    129 	ret := *ui32               // load from same address, should be zero
    130 	*ui64 = 0xffffffffffffffff // store
    131 	return ret
    132 }
    133 func testdse() {
    134 	x := int64(-1)
    135 	// construct two pointers that alias one another
    136 	ui64 := (*uint64)(unsafe.Pointer(&x))
    137 	ui32 := (*uint32)(unsafe.Pointer(&x))
    138 	if want, got := uint32(0), alias_ssa(ui64, ui32); got != want {
    139 		fmt.Printf("alias_ssa: wanted %d, got %d\n", want, got)
    140 		panic("alias_ssa")
    141 	}
    142 }
    143 
    144 func main() {
    145 	testf()
    146 	testg()
    147 	testdse()
    148 }
    149