// 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.typeSizesinterface {// Alignof returns the alignment of a variable of type T. // Alignof must implement the alignment guarantees required by the spec.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.Offsetsof(fields []*Var) []int64// Sizeof returns the size of a variable of type T. // Sizeof must implement the size guarantees required by the spec.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.//typeStdSizesstruct {WordSizeint64// word size in bytes - must be >= 4 (32bits)MaxAlignint64// maximum alignment in bytes - must be >= 1}func ( *StdSizes) ( Type) int64 {// 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:// 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); > { = } }returncase *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 .WordSizecase *Basic:// Strings are like slices and interfaces.if .Info()&IsString != 0 {return .WordSize }case *TypeParam, *Union:unreachable() } := .Sizeof() // may be 0// spec: "For a variable x of any type: unsafe.Alignof(x) is at least 1."if < 1 {return1 }// complex{64,128} are aligned like [2]float{32,64}.ifisComplex() { /= 2 }if > .MaxAlign {return .MaxAlign }return}func ( *StdSizes) ( []*Var) []int64 { := make([]int64, len())varint64for , := range { := .Alignof(.typ) = align(, ) [] = += .Sizeof(.typ) }return}varbasicSizes = [...]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()) := .kindifint() < len(basicSizes) {if := basicSizes[]; > 0 {returnint64() } }if == String {return .WordSize * 2 }case *Array: := .lenif <= 0 {return0 }// n > 0 := .Alignof(.elem) := .(.elem)returnalign(, )*(-1) + case *Slice:return .WordSize * 3case *Struct: := .NumFields()if == 0 {return0 } := .Offsetsof(.fields)return [-1] + .(.fields[-1].typ)case *Interface:// Type parameters lead to variable sizes/alignments; // StdSizes.Sizeof won't be called for them.assert(!isTypeParam())return .WordSize * 2case *TypeParam, *Union:unreachable() }return .WordSize// catch-all}// common architecture word sizes and alignmentsvargcArchSizes = map[string]*StdSizes{"386": {4, 4},"arm": {4, 4},"arm64": {8, 8},"amd64": {8, 8},"amd64p32": {4, 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", "arm", "arm64", "amd64", "amd64p32", "mips", "mipsle",// "mips64", "mips64le", "ppc64", "ppc64le", "riscv64", "s390x", "sparc64", "wasm".func (, string) Sizes {varmap[string]*StdSizesswitch {case"gc": = gcArchSizescase"gccgo": = gccgoArchSizesdefault:returnnil } , := []if ! {returnnil }return}// stdSizes is used if Config.Sizes == nil.varstdSizes = SizesFor("gc", "amd64")func ( *Config) ( Type) int64 {if := .Sizes; != nil {if := .Alignof(); >= 1 {return }panic("Config.Sizes.Alignof returned an alignment < 1") }returnstdSizes.Alignof()}func ( *Config) ( *Struct) []int64 {var []int64if .NumFields() > 0 {// compute offsets on demandif := .Sizes; != nil { = .Offsetsof(.fields)// sanity checksiflen() != .NumFields() {panic("Config.Sizes.Offsetsof returned the wrong number of offsets") }for , := range {if < 0 {panic("Config.Sizes.Offsetsof returned an offset < 0") } } } else { = stdSizes.Offsetsof(.fields) } }return}// offsetof returns the offset of the field specified via// the index sequence relative to typ. All embedded fields// must be structs (rather than pointer to structs).func ( *Config) ( Type, []int) int64 {varint64for , := range { := under().(*Struct) += .offsetsof()[] = .fields[].typ }return}func ( *Config) ( Type) int64 {if := .Sizes; != nil {if := .Sizeof(); >= 0 {return }panic("Config.Sizes.Sizeof returned a size < 0") }returnstdSizes.Sizeof()}// align returns the smallest y >= x such that y % a == 0.func (, int64) int64 { := + - 1return - %}
The pages are generated with Goldsv0.4.9. (GOOS=linux GOARCH=amd64)