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