github.com/llvm-mirror/llgo@v0.0.0-20190322182713-bf6f0a60fce1/third_party/gofrontend/libgo/go/runtime/gcinfo_test.go (about)

     1  // Copyright 2014 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  // +build ignore
     6  
     7  package runtime_test
     8  
     9  import (
    10  	"bytes"
    11  	"runtime"
    12  	"testing"
    13  )
    14  
    15  const (
    16  	typeScalar  = 0
    17  	typePointer = 1
    18  )
    19  
    20  // TestGCInfo tests that various objects in heap, data and bss receive correct GC pointer type info.
    21  func TestGCInfo(t *testing.T) {
    22  	t.Skip("skipping on gccgo for now")
    23  
    24  	verifyGCInfo(t, "stack Ptr", new(Ptr), infoPtr)
    25  	verifyGCInfo(t, "stack ScalarPtr", new(ScalarPtr), infoScalarPtr)
    26  	verifyGCInfo(t, "stack PtrScalar", new(PtrScalar), infoPtrScalar)
    27  	verifyGCInfo(t, "stack BigStruct", new(BigStruct), infoBigStruct())
    28  	verifyGCInfo(t, "stack string", new(string), infoString)
    29  	verifyGCInfo(t, "stack slice", new([]string), infoSlice)
    30  	verifyGCInfo(t, "stack eface", new(interface{}), infoEface)
    31  	verifyGCInfo(t, "stack iface", new(Iface), infoIface)
    32  
    33  	for i := 0; i < 10; i++ {
    34  		verifyGCInfo(t, "heap Ptr", escape(new(Ptr)), trimDead(padDead(infoPtr)))
    35  		verifyGCInfo(t, "heap PtrSlice", escape(&make([]*byte, 10)[0]), trimDead(infoPtr10))
    36  		verifyGCInfo(t, "heap ScalarPtr", escape(new(ScalarPtr)), trimDead(infoScalarPtr))
    37  		verifyGCInfo(t, "heap ScalarPtrSlice", escape(&make([]ScalarPtr, 4)[0]), trimDead(infoScalarPtr4))
    38  		verifyGCInfo(t, "heap PtrScalar", escape(new(PtrScalar)), trimDead(infoPtrScalar))
    39  		verifyGCInfo(t, "heap BigStruct", escape(new(BigStruct)), trimDead(infoBigStruct()))
    40  		verifyGCInfo(t, "heap string", escape(new(string)), trimDead(infoString))
    41  		verifyGCInfo(t, "heap eface", escape(new(interface{})), trimDead(infoEface))
    42  		verifyGCInfo(t, "heap iface", escape(new(Iface)), trimDead(infoIface))
    43  	}
    44  }
    45  
    46  func verifyGCInfo(t *testing.T, name string, p interface{}, mask0 []byte) {
    47  	mask := runtime.GCMask(p)
    48  	if bytes.Compare(mask, mask0) != 0 {
    49  		t.Errorf("bad GC program for %v:\nwant %+v\ngot  %+v", name, mask0, mask)
    50  		return
    51  	}
    52  }
    53  
    54  func padDead(mask []byte) []byte {
    55  	// Because the dead bit isn't encoded until the third word,
    56  	// and because on 32-bit systems a one-word allocation
    57  	// uses a two-word block, the pointer info for a one-word
    58  	// object needs to be expanded to include an extra scalar
    59  	// on 32-bit systems to match the heap bitmap.
    60  	if runtime.PtrSize == 4 && len(mask) == 1 {
    61  		return []byte{mask[0], 0}
    62  	}
    63  	return mask
    64  }
    65  
    66  func trimDead(mask []byte) []byte {
    67  	for len(mask) > 2 && mask[len(mask)-1] == typeScalar {
    68  		mask = mask[:len(mask)-1]
    69  	}
    70  	return mask
    71  }
    72  
    73  var gcinfoSink interface{}
    74  
    75  func escape(p interface{}) interface{} {
    76  	gcinfoSink = p
    77  	return p
    78  }
    79  
    80  var infoPtr = []byte{typePointer}
    81  
    82  type Ptr struct {
    83  	*byte
    84  }
    85  
    86  var infoPtr10 = []byte{typePointer, typePointer, typePointer, typePointer, typePointer, typePointer, typePointer, typePointer, typePointer, typePointer}
    87  
    88  type ScalarPtr struct {
    89  	q int
    90  	w *int
    91  	e int
    92  	r *int
    93  	t int
    94  	y *int
    95  }
    96  
    97  var infoScalarPtr = []byte{typeScalar, typePointer, typeScalar, typePointer, typeScalar, typePointer}
    98  
    99  var infoScalarPtr4 = append(append(append(append([]byte(nil), infoScalarPtr...), infoScalarPtr...), infoScalarPtr...), infoScalarPtr...)
   100  
   101  type PtrScalar struct {
   102  	q *int
   103  	w int
   104  	e *int
   105  	r int
   106  	t *int
   107  	y int
   108  }
   109  
   110  var infoPtrScalar = []byte{typePointer, typeScalar, typePointer, typeScalar, typePointer, typeScalar}
   111  
   112  type BigStruct struct {
   113  	q *int
   114  	w byte
   115  	e [17]byte
   116  	r []byte
   117  	t int
   118  	y uint16
   119  	u uint64
   120  	i string
   121  }
   122  
   123  func infoBigStruct() []byte {
   124  	switch runtime.GOARCH {
   125  	case "386", "arm":
   126  		return []byte{
   127  			typePointer,                                                // q *int
   128  			typeScalar, typeScalar, typeScalar, typeScalar, typeScalar, // w byte; e [17]byte
   129  			typePointer, typeScalar, typeScalar, // r []byte
   130  			typeScalar, typeScalar, typeScalar, typeScalar, // t int; y uint16; u uint64
   131  			typePointer, typeScalar, // i string
   132  		}
   133  	case "arm64", "amd64", "ppc64", "ppc64le":
   134  		return []byte{
   135  			typePointer,                        // q *int
   136  			typeScalar, typeScalar, typeScalar, // w byte; e [17]byte
   137  			typePointer, typeScalar, typeScalar, // r []byte
   138  			typeScalar, typeScalar, typeScalar, // t int; y uint16; u uint64
   139  			typePointer, typeScalar, // i string
   140  		}
   141  	case "amd64p32":
   142  		return []byte{
   143  			typePointer,                                                // q *int
   144  			typeScalar, typeScalar, typeScalar, typeScalar, typeScalar, // w byte; e [17]byte
   145  			typePointer, typeScalar, typeScalar, // r []byte
   146  			typeScalar, typeScalar, typeScalar, typeScalar, typeScalar, // t int; y uint16; u uint64
   147  			typePointer, typeScalar, // i string
   148  		}
   149  	default:
   150  		panic("unknown arch")
   151  	}
   152  }
   153  
   154  type Iface interface {
   155  	f()
   156  }
   157  
   158  type IfaceImpl int
   159  
   160  func (IfaceImpl) f() {
   161  }
   162  
   163  var (
   164  	// BSS
   165  	bssPtr       Ptr
   166  	bssScalarPtr ScalarPtr
   167  	bssPtrScalar PtrScalar
   168  	bssBigStruct BigStruct
   169  	bssString    string
   170  	bssSlice     []string
   171  	bssEface     interface{}
   172  	bssIface     Iface
   173  
   174  	// DATA
   175  	dataPtr                   = Ptr{new(byte)}
   176  	dataScalarPtr             = ScalarPtr{q: 1}
   177  	dataPtrScalar             = PtrScalar{w: 1}
   178  	dataBigStruct             = BigStruct{w: 1}
   179  	dataString                = "foo"
   180  	dataSlice                 = []string{"foo"}
   181  	dataEface     interface{} = 42
   182  	dataIface     Iface       = IfaceImpl(42)
   183  
   184  	infoString = []byte{typePointer, typeScalar}
   185  	infoSlice  = []byte{typePointer, typeScalar, typeScalar}
   186  	infoEface  = []byte{typePointer, typePointer}
   187  	infoIface  = []byte{typePointer, typePointer}
   188  )