Giant blob of minor changes
[dotfiles/.git] / .config / coc / extensions / coc-go-data / tools / pkg / mod / honnef.co / go / tools@v0.0.1-2020.1.5 / gcsizes / sizes.go
1 // Copyright 2013 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4
5 // Package gcsizes provides a types.Sizes implementation that adheres
6 // to the rules used by the gc compiler.
7 package gcsizes // import "honnef.co/go/tools/gcsizes"
8
9 import (
10         "go/build"
11         "go/types"
12 )
13
14 type Sizes struct {
15         WordSize int64
16         MaxAlign int64
17 }
18
19 // ForArch returns a correct Sizes for the given architecture.
20 func ForArch(arch string) *Sizes {
21         wordSize := int64(8)
22         maxAlign := int64(8)
23         switch build.Default.GOARCH {
24         case "386", "arm":
25                 wordSize, maxAlign = 4, 4
26         case "amd64p32":
27                 wordSize = 4
28         }
29         return &Sizes{WordSize: wordSize, MaxAlign: maxAlign}
30 }
31
32 func (s *Sizes) Alignof(T types.Type) int64 {
33         switch t := T.Underlying().(type) {
34         case *types.Array:
35                 return s.Alignof(t.Elem())
36         case *types.Struct:
37                 max := int64(1)
38                 n := t.NumFields()
39                 var fields []*types.Var
40                 for i := 0; i < n; i++ {
41                         fields = append(fields, t.Field(i))
42                 }
43                 for _, f := range fields {
44                         if a := s.Alignof(f.Type()); a > max {
45                                 max = a
46                         }
47                 }
48                 return max
49         }
50         a := s.Sizeof(T) // may be 0
51         if a < 1 {
52                 return 1
53         }
54         if a > s.MaxAlign {
55                 return s.MaxAlign
56         }
57         return a
58 }
59
60 func (s *Sizes) Offsetsof(fields []*types.Var) []int64 {
61         offsets := make([]int64, len(fields))
62         var o int64
63         for i, f := range fields {
64                 a := s.Alignof(f.Type())
65                 o = align(o, a)
66                 offsets[i] = o
67                 o += s.Sizeof(f.Type())
68         }
69         return offsets
70 }
71
72 var basicSizes = [...]byte{
73         types.Bool:       1,
74         types.Int8:       1,
75         types.Int16:      2,
76         types.Int32:      4,
77         types.Int64:      8,
78         types.Uint8:      1,
79         types.Uint16:     2,
80         types.Uint32:     4,
81         types.Uint64:     8,
82         types.Float32:    4,
83         types.Float64:    8,
84         types.Complex64:  8,
85         types.Complex128: 16,
86 }
87
88 func (s *Sizes) Sizeof(T types.Type) int64 {
89         switch t := T.Underlying().(type) {
90         case *types.Basic:
91                 k := t.Kind()
92                 if int(k) < len(basicSizes) {
93                         if s := basicSizes[k]; s > 0 {
94                                 return int64(s)
95                         }
96                 }
97                 if k == types.String {
98                         return s.WordSize * 2
99                 }
100         case *types.Array:
101                 n := t.Len()
102                 if n == 0 {
103                         return 0
104                 }
105                 a := s.Alignof(t.Elem())
106                 z := s.Sizeof(t.Elem())
107                 return align(z, a)*(n-1) + z
108         case *types.Slice:
109                 return s.WordSize * 3
110         case *types.Struct:
111                 n := t.NumFields()
112                 if n == 0 {
113                         return 0
114                 }
115
116                 var fields []*types.Var
117                 for i := 0; i < n; i++ {
118                         fields = append(fields, t.Field(i))
119                 }
120                 offsets := s.Offsetsof(fields)
121                 a := s.Alignof(T)
122                 lsz := s.Sizeof(fields[n-1].Type())
123                 if lsz == 0 {
124                         lsz = 1
125                 }
126                 z := offsets[n-1] + lsz
127                 return align(z, a)
128         case *types.Interface:
129                 return s.WordSize * 2
130         }
131         return s.WordSize // catch-all
132 }
133
134 // align returns the smallest y >= x such that y % a == 0.
135 func align(x, a int64) int64 {
136         y := x + a - 1
137         return y - y%a
138 }