gcsizes.go raw

   1  // Code generated by "go test -run=Generate -write=all"; DO NOT EDIT.
   2  // Source: ../../cmd/compile/internal/types2/gcsizes.go
   3  
   4  // Copyright 2023 The Go Authors. All rights reserved.
   5  // Use of this source code is governed by a BSD-style
   6  // license that can be found in the LICENSE file.
   7  
   8  package types
   9  
  10  type gcSizes struct {
  11  	WordSize int64 // word size in bytes - must be >= 4 (32bits)
  12  	MaxAlign int64 // maximum alignment in bytes - must be >= 1
  13  }
  14  
  15  func (s *gcSizes) Alignof(T Type) (result int64) {
  16  	defer func() {
  17  		assert(result >= 1)
  18  	}()
  19  
  20  	// For arrays and structs, alignment is defined in terms
  21  	// of alignment of the elements and fields, respectively.
  22  	switch t := under(T).(type) {
  23  	case *Array:
  24  		// spec: "For a variable x of array type: unsafe.Alignof(x)
  25  		// is the same as unsafe.Alignof(x[0]), but at least 1."
  26  		return s.Alignof(t.elem)
  27  	case *Struct:
  28  		if len(t.fields) == 0 && _IsSyncAtomicAlign64(T) {
  29  			// Special case: sync/atomic.align64 is an
  30  			// empty struct we recognize as a signal that
  31  			// the struct it contains must be
  32  			// 64-bit-aligned.
  33  			//
  34  			// This logic is equivalent to the logic in
  35  			// cmd/compile/internal/types/size.go:calcStructOffset
  36  			return 8
  37  		}
  38  
  39  		// spec: "For a variable x of struct type: unsafe.Alignof(x)
  40  		// is the largest of the values unsafe.Alignof(x.f) for each
  41  		// field f of x, but at least 1."
  42  		max := int64(1)
  43  		for _, f := range t.fields {
  44  			if a := s.Alignof(f.typ); a > max {
  45  				max = a
  46  			}
  47  		}
  48  		return max
  49  	case *Slice, *Interface:
  50  		// Multiword data structures are effectively structs
  51  		// in which each element has size WordSize.
  52  		// Type parameters lead to variable sizes/alignments;
  53  		// StdSizes.Alignof won't be called for them.
  54  		assert(!isTypeParam(T))
  55  		return s.WordSize
  56  	case *Basic:
  57  		// Strings are like slices and interfaces.
  58  		if t.Info()&IsString != 0 {
  59  			return s.WordSize
  60  		}
  61  	case *TypeParam, *Union:
  62  		panic("unreachable")
  63  	}
  64  	a := s.Sizeof(T) // may be 0 or negative
  65  	// spec: "For a variable x of any type: unsafe.Alignof(x) is at least 1."
  66  	if a < 1 {
  67  		return 1
  68  	}
  69  	// complex{64,128} are aligned like [2]float{32,64}.
  70  	if isComplex(T) {
  71  		a /= 2
  72  	}
  73  	if a > s.MaxAlign {
  74  		return s.MaxAlign
  75  	}
  76  	return a
  77  }
  78  
  79  func (s *gcSizes) Offsetsof(fields []*Var) []int64 {
  80  	offsets := make([]int64, len(fields))
  81  	var offs int64
  82  	for i, f := range fields {
  83  		if offs < 0 {
  84  			// all remaining offsets are too large
  85  			offsets[i] = -1
  86  			continue
  87  		}
  88  		// offs >= 0
  89  		a := s.Alignof(f.typ)
  90  		offs = align(offs, a) // possibly < 0 if align overflows
  91  		offsets[i] = offs
  92  		if d := s.Sizeof(f.typ); d >= 0 && offs >= 0 {
  93  			offs += d // ok to overflow to < 0
  94  		} else {
  95  			offs = -1 // f.typ or offs is too large
  96  		}
  97  	}
  98  	return offsets
  99  }
 100  
 101  func (s *gcSizes) Sizeof(T Type) int64 {
 102  	switch t := under(T).(type) {
 103  	case *Basic:
 104  		assert(isTyped(T))
 105  		k := t.kind
 106  		if int(k) < len(basicSizes) {
 107  			if s := basicSizes[k]; s > 0 {
 108  				return int64(s)
 109  			}
 110  		}
 111  		if k == String {
 112  			return s.WordSize * 2
 113  		}
 114  	case *Array:
 115  		n := t.len
 116  		if n <= 0 {
 117  			return 0
 118  		}
 119  		// n > 0
 120  		esize := s.Sizeof(t.elem)
 121  		if esize < 0 {
 122  			return -1 // element too large
 123  		}
 124  		if esize == 0 {
 125  			return 0 // 0-size element
 126  		}
 127  		// esize > 0
 128  		// Final size is esize * n; and size must be <= maxInt64.
 129  		const maxInt64 = 1<<63 - 1
 130  		if esize > maxInt64/n {
 131  			return -1 // esize * n overflows
 132  		}
 133  		return esize * n
 134  	case *Slice:
 135  		return s.WordSize * 3
 136  	case *Struct:
 137  		n := t.NumFields()
 138  		if n == 0 {
 139  			return 0
 140  		}
 141  		offsets := s.Offsetsof(t.fields)
 142  		offs := offsets[n-1]
 143  		size := s.Sizeof(t.fields[n-1].typ)
 144  		if offs < 0 || size < 0 {
 145  			return -1 // type too large
 146  		}
 147  		// gc: The last field of a non-zero-sized struct is not allowed to
 148  		// have size 0.
 149  		if offs > 0 && size == 0 {
 150  			size = 1
 151  		}
 152  		// gc: Size includes alignment padding.
 153  		return align(offs+size, s.Alignof(t)) // may overflow to < 0 which is ok
 154  	case *Interface:
 155  		// Type parameters lead to variable sizes/alignments;
 156  		// StdSizes.Sizeof won't be called for them.
 157  		assert(!isTypeParam(T))
 158  		return s.WordSize * 2
 159  	case *TypeParam, *Union:
 160  		panic("unreachable")
 161  	}
 162  	return s.WordSize // catch-all
 163  }
 164  
 165  // gcSizesFor returns the Sizes used by gc for an architecture.
 166  // The result is a nil *gcSizes pointer (which is not a valid types.Sizes)
 167  // if a compiler/architecture pair is not known.
 168  func gcSizesFor(compiler, arch string) *gcSizes {
 169  	if compiler != "gc" {
 170  		return nil
 171  	}
 172  	return gcArchSizes[arch]
 173  }
 174