Source file src/go/types/gcsizes.go

     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  

View as plain text