1
2
3
4
5 package noder
6
7 import (
8 "fmt"
9
10 "cmd/compile/internal/types"
11 "cmd/compile/internal/types2"
12 )
13
14
15
16
17 type gcSizes struct{}
18
19 func (s *gcSizes) Alignof(T types2.Type) int64 {
20
21
22 switch t := T.Underlying().(type) {
23 case *types2.Array:
24
25
26 return s.Alignof(t.Elem())
27 case *types2.Struct:
28
29
30
31 max := int64(1)
32 for i, nf := 0, t.NumFields(); i < nf; i++ {
33 if a := s.Alignof(t.Field(i).Type()); a > max {
34 max = a
35 }
36 }
37 return max
38 case *types2.Slice, *types2.Interface:
39
40
41 return int64(types.PtrSize)
42 case *types2.Basic:
43
44 if t.Info()&types2.IsString != 0 {
45 return int64(types.PtrSize)
46 }
47 }
48 a := s.Sizeof(T)
49
50 if a < 1 {
51 return 1
52 }
53
54 if isComplex(T) {
55 a /= 2
56 }
57 if a > int64(types.RegSize) {
58 return int64(types.RegSize)
59 }
60 return a
61 }
62
63 func isComplex(T types2.Type) bool {
64 basic, ok := T.Underlying().(*types2.Basic)
65 return ok && basic.Info()&types2.IsComplex != 0
66 }
67
68 func (s *gcSizes) Offsetsof(fields []*types2.Var) []int64 {
69 offsets := make([]int64, len(fields))
70 var o int64
71 for i, f := range fields {
72 typ := f.Type()
73 a := s.Alignof(typ)
74 o = types.Rnd(o, a)
75 offsets[i] = o
76 o += s.Sizeof(typ)
77 }
78 return offsets
79 }
80
81 func (s *gcSizes) Sizeof(T types2.Type) int64 {
82 switch t := T.Underlying().(type) {
83 case *types2.Basic:
84 k := t.Kind()
85 if int(k) < len(basicSizes) {
86 if s := basicSizes[k]; s > 0 {
87 return int64(s)
88 }
89 }
90 switch k {
91 case types2.String:
92 return int64(types.PtrSize) * 2
93 case types2.Int, types2.Uint, types2.Uintptr, types2.UnsafePointer:
94 return int64(types.PtrSize)
95 }
96 panic(fmt.Sprintf("unimplemented basic: %v (kind %v)", T, k))
97 case *types2.Array:
98 n := t.Len()
99 if n <= 0 {
100 return 0
101 }
102
103
104 return s.Sizeof(t.Elem()) * n
105 case *types2.Slice:
106 return int64(types.PtrSize) * 3
107 case *types2.Struct:
108 n := t.NumFields()
109 if n == 0 {
110 return 0
111 }
112 fields := make([]*types2.Var, n)
113 for i := range fields {
114 fields[i] = t.Field(i)
115 }
116 offsets := s.Offsetsof(fields)
117
118
119
120 last := s.Sizeof(fields[n-1].Type())
121 if last == 0 && offsets[n-1] > 0 {
122 last = 1
123 }
124
125
126 return types.Rnd(offsets[n-1]+last, s.Alignof(t))
127 case *types2.Interface:
128 return int64(types.PtrSize) * 2
129 case *types2.Chan, *types2.Map, *types2.Pointer, *types2.Signature:
130 return int64(types.PtrSize)
131 default:
132 panic(fmt.Sprintf("unimplemented type: %T", t))
133 }
134 }
135
136 var basicSizes = [...]byte{
137 types2.Bool: 1,
138 types2.Int8: 1,
139 types2.Int16: 2,
140 types2.Int32: 4,
141 types2.Int64: 8,
142 types2.Uint8: 1,
143 types2.Uint16: 2,
144 types2.Uint32: 4,
145 types2.Uint64: 8,
146 types2.Float32: 4,
147 types2.Float64: 8,
148 types2.Complex64: 8,
149 types2.Complex128: 16,
150 }
151
View as plain text