Source File
sizes.go
Belonging Package
go/types
// Code generated by "go test -run=Generate -write=all"; DO NOT EDIT.
// Source: ../../cmd/compile/internal/types2/sizes.go
// 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.
// This file implements Sizes.
package types
// Sizes defines the sizing functions for package unsafe.
type Sizes interface {
// Alignof returns the alignment of a variable of type T.
// Alignof must implement the alignment guarantees required by the spec.
// The result must be >= 1.
Alignof(T Type) int64
// Offsetsof returns the offsets of the given struct fields, in bytes.
// Offsetsof must implement the offset guarantees required by the spec.
// A negative entry in the result indicates that the struct is too large.
Offsetsof(fields []*Var) []int64
// Sizeof returns the size of a variable of type T.
// Sizeof must implement the size guarantees required by the spec.
// A negative result indicates that T is too large.
Sizeof(T Type) int64
}
// StdSizes is a convenience type for creating commonly used Sizes.
// It makes the following simplifying assumptions:
//
// - The size of explicitly sized basic types (int16, etc.) is the
// specified size.
// - The size of strings and interfaces is 2*WordSize.
// - The size of slices is 3*WordSize.
// - The size of an array of n elements corresponds to the size of
// a struct of n consecutive fields of the array's element type.
// - The size of a struct is the offset of the last field plus that
// field's size. As with all element types, if the struct is used
// in an array its size must first be aligned to a multiple of the
// struct's alignment.
// - All other types have size WordSize.
// - Arrays and structs are aligned per spec definition; all other
// types are naturally aligned with a maximum alignment MaxAlign.
//
// *StdSizes implements Sizes.
type StdSizes struct {
WordSize int64 // word size in bytes - must be >= 4 (32bits)
MaxAlign int64 // maximum alignment in bytes - must be >= 1
}
func ( *StdSizes) ( Type) ( int64) {
defer func() {
assert( >= 1)
}()
// For arrays and structs, alignment is defined in terms
// of alignment of the elements and fields, respectively.
switch t := under().(type) {
case *Array:
// spec: "For a variable x of array type: unsafe.Alignof(x)
// is the same as unsafe.Alignof(x[0]), but at least 1."
return .(.elem)
case *Struct:
if len(.fields) == 0 && _IsSyncAtomicAlign64() {
// Special case: sync/atomic.align64 is an
// empty struct we recognize as a signal that
// the struct it contains must be
// 64-bit-aligned.
//
// This logic is equivalent to the logic in
// cmd/compile/internal/types/size.go:calcStructOffset
return 8
}
// spec: "For a variable x of struct type: unsafe.Alignof(x)
// is the largest of the values unsafe.Alignof(x.f) for each
// field f of x, but at least 1."
:= int64(1)
for , := range .fields {
if := .(.typ); > {
=
}
}
return
case *Slice, *Interface:
// Multiword data structures are effectively structs
// in which each element has size WordSize.
// Type parameters lead to variable sizes/alignments;
// StdSizes.Alignof won't be called for them.
assert(!isTypeParam())
return .WordSize
case *Basic:
// Strings are like slices and interfaces.
if .Info()&IsString != 0 {
return .WordSize
}
case *TypeParam, *Union:
panic("unreachable")
}
:= .Sizeof() // may be 0 or negative
// spec: "For a variable x of any type: unsafe.Alignof(x) is at least 1."
if < 1 {
return 1
}
// complex{64,128} are aligned like [2]float{32,64}.
if isComplex() {
/= 2
}
if > .MaxAlign {
return .MaxAlign
}
return
}
func ( Type) bool {
:= asNamed()
if == nil {
return false
}
:= .Obj()
return .Name() == "align64" &&
.Pkg() != nil &&
(.Pkg().Path() == "sync/atomic" ||
.Pkg().Path() == "internal/runtime/atomic")
}
func ( *StdSizes) ( []*Var) []int64 {
:= make([]int64, len())
var int64
for , := range {
if < 0 {
// all remaining offsets are too large
[] = -1
continue
}
// offs >= 0
:= .Alignof(.typ)
= align(, ) // possibly < 0 if align overflows
[] =
if := .Sizeof(.typ); >= 0 && >= 0 {
+= // ok to overflow to < 0
} else {
= -1 // f.typ or offs is too large
}
}
return
}
var basicSizes = [...]byte{
Bool: 1,
Int8: 1,
Int16: 2,
Int32: 4,
Int64: 8,
Uint8: 1,
Uint16: 2,
Uint32: 4,
Uint64: 8,
Float32: 4,
Float64: 8,
Complex64: 8,
Complex128: 16,
}
func ( *StdSizes) ( Type) int64 {
switch t := under().(type) {
case *Basic:
assert(isTyped())
:= .kind
if int() < len(basicSizes) {
if := basicSizes[]; > 0 {
return int64()
}
}
if == String {
return .WordSize * 2
}
case *Array:
:= .len
if <= 0 {
return 0
}
// n > 0
:= .(.elem)
if < 0 {
return -1 // element too large
}
if == 0 {
return 0 // 0-size element
}
// esize > 0
:= .Alignof(.elem)
:= align(, ) // possibly < 0 if align overflows
if < 0 {
return -1
}
// ea >= 1
:= - 1 // n1 >= 0
// Final size is ea*n1 + esize; and size must be <= maxInt64.
const = 1<<63 - 1
if > 0 && > / {
return -1 // ea*n1 overflows
}
return * + // may still overflow to < 0 which is ok
case *Slice:
return .WordSize * 3
case *Struct:
:= .NumFields()
if == 0 {
return 0
}
:= .Offsetsof(.fields)
:= [-1]
:= .(.fields[-1].typ)
if < 0 || < 0 {
return -1 // type too large
}
return + // may overflow to < 0 which is ok
case *Interface:
// Type parameters lead to variable sizes/alignments;
// StdSizes.Sizeof won't be called for them.
assert(!isTypeParam())
return .WordSize * 2
case *TypeParam, *Union:
panic("unreachable")
}
return .WordSize // catch-all
}
// common architecture word sizes and alignments
var gcArchSizes = map[string]*gcSizes{
"386": {4, 4},
"amd64": {8, 8},
"amd64p32": {4, 8},
"arm": {4, 4},
"arm64": {8, 8},
"loong64": {8, 8},
"mips": {4, 4},
"mipsle": {4, 4},
"mips64": {8, 8},
"mips64le": {8, 8},
"ppc64": {8, 8},
"ppc64le": {8, 8},
"riscv64": {8, 8},
"s390x": {8, 8},
"sparc64": {8, 8},
"wasm": {8, 8},
// When adding more architectures here,
// update the doc string of SizesFor below.
}
// SizesFor returns the Sizes used by a compiler for an architecture.
// The result is nil if a compiler/architecture pair is not known.
//
// Supported architectures for compiler "gc":
// "386", "amd64", "amd64p32", "arm", "arm64", "loong64", "mips", "mipsle",
// "mips64", "mips64le", "ppc64", "ppc64le", "riscv64", "s390x", "sparc64", "wasm".
func (, string) Sizes {
switch {
case "gc":
if := gcSizesFor(, ); != nil {
return Sizes()
}
case "gccgo":
if , := gccgoArchSizes[]; {
return Sizes()
}
}
return nil
}
// stdSizes is used if Config.Sizes == nil.
var stdSizes = SizesFor("gc", "amd64")
func ( *Config) ( Type) int64 {
:= stdSizes.Alignof
if .Sizes != nil {
= .Sizes.Alignof
}
if := (); >= 1 {
return
}
panic("implementation of alignof returned an alignment < 1")
}
func ( *Config) ( *Struct) []int64 {
var []int64
if .NumFields() > 0 {
// compute offsets on demand
:= stdSizes.Offsetsof
if .Sizes != nil {
= .Sizes.Offsetsof
}
= (.fields)
// sanity checks
if len() != .NumFields() {
panic("implementation of offsetsof returned the wrong number of offsets")
}
}
return
}
// offsetof returns the offset of the field specified via
// the index sequence relative to T. All embedded fields
// must be structs (rather than pointers to structs).
// If the offset is too large (because T is too large),
// the result is negative.
func ( *Config) ( Type, []int) int64 {
var int64
for , := range {
:= under().(*Struct)
:= .offsetsof()[]
if < 0 {
return -1
}
+=
if < 0 {
return -1
}
= .fields[].typ
}
return
}
// sizeof returns the size of T.
// If T is too large, the result is negative.
func ( *Config) ( Type) int64 {
:= stdSizes.Sizeof
if .Sizes != nil {
= .Sizes.Sizeof
}
return ()
}
// align returns the smallest y >= x such that y % a == 0.
// a must be within 1 and 8 and it must be a power of 2.
// The result may be negative due to overflow.
func (, int64) int64 {
assert( >= 0 && 1 <= && <= 8 && &(-1) == 0)
return ( + - 1) &^ ( - 1)
}
The pages are generated with Golds v0.7.6. (GOOS=linux GOARCH=amd64)