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