+++ /dev/null
-// Copyright 2013 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Package gcsizes provides a types.Sizes implementation that adheres
-// to the rules used by the gc compiler.
-package gcsizes // import "honnef.co/go/tools/gcsizes"
-
-import (
- "go/build"
- "go/types"
-)
-
-type Sizes struct {
- WordSize int64
- MaxAlign int64
-}
-
-// ForArch returns a correct Sizes for the given architecture.
-func ForArch(arch string) *Sizes {
- wordSize := int64(8)
- maxAlign := int64(8)
- switch build.Default.GOARCH {
- case "386", "arm":
- wordSize, maxAlign = 4, 4
- case "amd64p32":
- wordSize = 4
- }
- return &Sizes{WordSize: wordSize, MaxAlign: maxAlign}
-}
-
-func (s *Sizes) Alignof(T types.Type) int64 {
- switch t := T.Underlying().(type) {
- case *types.Array:
- return s.Alignof(t.Elem())
- case *types.Struct:
- max := int64(1)
- n := t.NumFields()
- var fields []*types.Var
- for i := 0; i < n; i++ {
- fields = append(fields, t.Field(i))
- }
- for _, f := range fields {
- if a := s.Alignof(f.Type()); a > max {
- max = a
- }
- }
- return max
- }
- a := s.Sizeof(T) // may be 0
- if a < 1 {
- return 1
- }
- if a > s.MaxAlign {
- return s.MaxAlign
- }
- return a
-}
-
-func (s *Sizes) Offsetsof(fields []*types.Var) []int64 {
- offsets := make([]int64, len(fields))
- var o int64
- for i, f := range fields {
- a := s.Alignof(f.Type())
- o = align(o, a)
- offsets[i] = o
- o += s.Sizeof(f.Type())
- }
- return offsets
-}
-
-var basicSizes = [...]byte{
- types.Bool: 1,
- types.Int8: 1,
- types.Int16: 2,
- types.Int32: 4,
- types.Int64: 8,
- types.Uint8: 1,
- types.Uint16: 2,
- types.Uint32: 4,
- types.Uint64: 8,
- types.Float32: 4,
- types.Float64: 8,
- types.Complex64: 8,
- types.Complex128: 16,
-}
-
-func (s *Sizes) Sizeof(T types.Type) int64 {
- switch t := T.Underlying().(type) {
- case *types.Basic:
- k := t.Kind()
- if int(k) < len(basicSizes) {
- if s := basicSizes[k]; s > 0 {
- return int64(s)
- }
- }
- if k == types.String {
- return s.WordSize * 2
- }
- case *types.Array:
- n := t.Len()
- if n == 0 {
- return 0
- }
- a := s.Alignof(t.Elem())
- z := s.Sizeof(t.Elem())
- return align(z, a)*(n-1) + z
- case *types.Slice:
- return s.WordSize * 3
- case *types.Struct:
- n := t.NumFields()
- if n == 0 {
- return 0
- }
-
- var fields []*types.Var
- for i := 0; i < n; i++ {
- fields = append(fields, t.Field(i))
- }
- offsets := s.Offsetsof(fields)
- a := s.Alignof(T)
- lsz := s.Sizeof(fields[n-1].Type())
- if lsz == 0 {
- lsz = 1
- }
- z := offsets[n-1] + lsz
- return align(z, a)
- case *types.Interface:
- return s.WordSize * 2
- }
- return s.WordSize // catch-all
-}
-
-// align returns the smallest y >= x such that y % a == 0.
-func align(x, a int64) int64 {
- y := x + a - 1
- return y - y%a
-}