| 94 | } |
| 95 | |
| 96 | func (s *stdSizes) Sizeof(T types.Type) int64 { |
| 97 | switch t := T.Underlying().(type) { |
| 98 | case *types.Basic: |
| 99 | k := t.Kind() |
| 100 | if int(k) < len(basicSizes) { |
| 101 | if s := basicSizes[k]; s > 0 { |
| 102 | return int64(s) |
| 103 | } |
| 104 | } |
| 105 | if k == types.String { |
| 106 | return s.PtrSize * 2 |
| 107 | } |
| 108 | if k == types.Int || k == types.Uint { |
| 109 | return s.IntSize |
| 110 | } |
| 111 | if k == types.Uintptr { |
| 112 | return s.PtrSize |
| 113 | } |
| 114 | if k == types.UnsafePointer { |
| 115 | return s.PtrSize |
| 116 | } |
| 117 | if k == types.Invalid { |
| 118 | return 0 // only relevant when there is a type error somewhere |
| 119 | } |
| 120 | panic("unknown basic type: " + t.String()) |
| 121 | case *types.Array: |
| 122 | n := t.Len() |
| 123 | if n <= 0 { |
| 124 | return 0 |
| 125 | } |
| 126 | // n > 0 |
| 127 | a := s.Alignof(t.Elem()) |
| 128 | z := s.Sizeof(t.Elem()) |
| 129 | return align(z, a)*(n-1) + z |
| 130 | case *types.Slice: |
| 131 | return s.PtrSize * 3 |
| 132 | case *types.Struct: |
| 133 | n := t.NumFields() |
| 134 | if n == 0 { |
| 135 | return 0 |
| 136 | } |
| 137 | fields := make([]*types.Var, t.NumFields()) |
| 138 | maxAlign := int64(1) |
| 139 | for i := range fields { |
| 140 | field := t.Field(i) |
| 141 | fields[i] = field |
| 142 | al := s.Alignof(field.Type()) |
| 143 | if al > maxAlign { |
| 144 | maxAlign = al |
| 145 | } |
| 146 | } |
| 147 | // Pick the size that fits this struct and add some alignment. Some |
| 148 | // structs have some extra padding at the end which should also be taken |
| 149 | // care of: |
| 150 | // struct { int32 n; byte b } |
| 151 | offsets := s.Offsetsof(fields) |
| 152 | return align(offsets[n-1]+s.Sizeof(fields[n-1].Type()), maxAlign) |
| 153 | case *types.Interface: |