Source file src/cmd/compile/internal/typebits/typebits.go

     1  // Copyright 2013 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 typebits
     6  
     7  import (
     8  	"cmd/compile/internal/base"
     9  	"cmd/compile/internal/bitvec"
    10  	"cmd/compile/internal/types"
    11  )
    12  
    13  // NOTE: The bitmap for a specific type t could be cached in t after
    14  // the first run and then simply copied into bv at the correct offset
    15  // on future calls with the same type t.
    16  func Set(t *types.Type, off int64, bv bitvec.BitVec) {
    17  	set(t, off, bv, false)
    18  }
    19  
    20  // SetNoCheck is like Set, but do not check for alignment.
    21  func SetNoCheck(t *types.Type, off int64, bv bitvec.BitVec) {
    22  	set(t, off, bv, true)
    23  }
    24  
    25  func set(t *types.Type, off int64, bv bitvec.BitVec, skip bool) {
    26  	if !skip && uint8(t.Alignment()) > 0 && off&int64(uint8(t.Alignment())-1) != 0 {
    27  		base.Fatalf("typebits.Set: invalid initial alignment: type %v has alignment %d, but offset is %v", t, uint8(t.Alignment()), off)
    28  	}
    29  	if !t.HasPointers() {
    30  		// Note: this case ensures that pointers to not-in-heap types
    31  		// are not considered pointers by garbage collection and stack copying.
    32  		return
    33  	}
    34  
    35  	switch t.Kind() {
    36  	case types.TPTR, types.TUNSAFEPTR, types.TFUNC, types.TCHAN, types.TMAP:
    37  		if off&int64(types.PtrSize-1) != 0 {
    38  			base.Fatalf("typebits.Set: invalid alignment, %v", t)
    39  		}
    40  		bv.Set(int32(off / int64(types.PtrSize))) // pointer
    41  
    42  	case types.TSTRING:
    43  		// struct { byte *str; intgo len; }
    44  		if off&int64(types.PtrSize-1) != 0 {
    45  			base.Fatalf("typebits.Set: invalid alignment, %v", t)
    46  		}
    47  		bv.Set(int32(off / int64(types.PtrSize))) //pointer in first slot
    48  
    49  	case types.TINTER:
    50  		// struct { Itab *tab;	void *data; }
    51  		// or, when isnilinter(t)==true:
    52  		// struct { Type *type; void *data; }
    53  		if off&int64(types.PtrSize-1) != 0 {
    54  			base.Fatalf("typebits.Set: invalid alignment, %v", t)
    55  		}
    56  		// The first word of an interface is a pointer, but we don't
    57  		// treat it as such.
    58  		// 1. If it is a non-empty interface, the pointer points to an itab
    59  		//    which is always in persistentalloc space.
    60  		// 2. If it is an empty interface, the pointer points to a _type.
    61  		//   a. If it is a compile-time-allocated type, it points into
    62  		//      the read-only data section.
    63  		//   b. If it is a reflect-allocated type, it points into the Go heap.
    64  		//      Reflect is responsible for keeping a reference to
    65  		//      the underlying type so it won't be GCd.
    66  		// If we ever have a moving GC, we need to change this for 2b (as
    67  		// well as scan itabs to update their itab._type fields).
    68  		bv.Set(int32(off/int64(types.PtrSize) + 1)) // pointer in second slot
    69  
    70  	case types.TSLICE:
    71  		// struct { byte *array; uintgo len; uintgo cap; }
    72  		if off&int64(types.PtrSize-1) != 0 {
    73  			base.Fatalf("typebits.Set: invalid TARRAY alignment, %v", t)
    74  		}
    75  		bv.Set(int32(off / int64(types.PtrSize))) // pointer in first slot (BitsPointer)
    76  
    77  	case types.TARRAY:
    78  		elt := t.Elem()
    79  		if elt.Size() == 0 {
    80  			// Short-circuit for #20739.
    81  			break
    82  		}
    83  		for i := int64(0); i < t.NumElem(); i++ {
    84  			set(elt, off, bv, skip)
    85  			off += elt.Size()
    86  		}
    87  
    88  	case types.TSTRUCT:
    89  		for _, f := range t.Fields() {
    90  			set(f.Type, off+f.Offset, bv, skip)
    91  		}
    92  
    93  	default:
    94  		base.Fatalf("typebits.Set: unexpected type, %v", t)
    95  	}
    96  }
    97  

View as plain text