Source file src/go/types/gcsizes.go

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

View as plain text