Source file
src/go/types/gcsizes.go
1
2
3
4
5
6
7
8 package types
9
10 type gcSizes struct {
11 WordSize int64
12 MaxAlign int64
13 }
14
15 func (s *gcSizes) Alignof(T Type) (result int64) {
16 defer func() {
17 assert(result >= 1)
18 }()
19
20
21
22 switch t := under(T).(type) {
23 case *Array:
24
25
26 return s.Alignof(t.elem)
27 case *Struct:
28 if len(t.fields) == 0 && _IsSyncAtomicAlign64(T) {
29
30
31
32
33
34
35
36 return 8
37 }
38
39
40
41
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
51
52
53
54 assert(!isTypeParam(T))
55 return s.WordSize
56 case *Basic:
57
58 if t.Info()&IsString != 0 {
59 return s.WordSize
60 }
61 case *TypeParam, *Union:
62 panic("unreachable")
63 }
64 a := s.Sizeof(T)
65
66 if a < 1 {
67 return 1
68 }
69
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
85 offsets[i] = -1
86 continue
87 }
88
89 a := s.Alignof(f.typ)
90 offs = align(offs, a)
91 offsets[i] = offs
92 if d := s.Sizeof(f.typ); d >= 0 && offs >= 0 {
93 offs += d
94 } else {
95 offs = -1
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
120 esize := s.Sizeof(t.elem)
121 if esize < 0 {
122 return -1
123 }
124 if esize == 0 {
125 return 0
126 }
127
128
129 const maxInt64 = 1<<63 - 1
130 if esize > maxInt64/n {
131 return -1
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
146 }
147
148
149 if offs > 0 && size == 0 {
150 size = 1
151 }
152
153 return align(offs+size, s.Alignof(t))
154 case *Interface:
155
156
157 assert(!isTypeParam(T))
158 return s.WordSize * 2
159 case *TypeParam, *Union:
160 panic("unreachable")
161 }
162 return s.WordSize
163 }
164
165
166
167
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