diff --git a/src/cmd/compile/internal/noder/irgen.go b/src/cmd/compile/internal/noder/irgen.go index 6019c5986c..f7b6d191fb 100644 --- a/src/cmd/compile/internal/noder/irgen.go +++ b/src/cmd/compile/internal/noder/irgen.go @@ -6,6 +6,7 @@ package noder import ( "fmt" + "internal/buildcfg" "internal/types/errors" "regexp" "sort" @@ -51,7 +52,7 @@ func checkFiles(m posMap, noders []*noder) (*types2.Package, *types2.Info) { base.ErrorfAt(m.makeXPos(terr.Pos), terr.Code, "%s", msg) }, Importer: &importer, - Sizes: &gcSizes{}, + Sizes: types2.SizesFor("gc", buildcfg.GOARCH), } if base.Flag.ErrorURL { conf.ErrorURL = " [go.dev/e/%s]" diff --git a/src/cmd/compile/internal/noder/sizes.go b/src/cmd/compile/internal/noder/sizes.go deleted file mode 100644 index dff8d7bb9a..0000000000 --- a/src/cmd/compile/internal/noder/sizes.go +++ /dev/null @@ -1,185 +0,0 @@ -// Copyright 2021 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 noder - -import ( - "fmt" - - "cmd/compile/internal/types" - "cmd/compile/internal/types2" -) - -// Code below based on go/types.StdSizes. -// Intentional differences are marked with "gc:". - -type gcSizes struct{} - -func (s *gcSizes) Alignof(T types2.Type) int64 { - // For arrays and structs, alignment is defined in terms - // of alignment of the elements and fields, respectively. - switch t := T.Underlying().(type) { - case *types2.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 s.Alignof(t.Elem()) - case *types2.Struct: - if t.NumFields() == 0 && types2.IsSyncAtomicAlign64(T) { - // 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." - max := int64(1) - for i, nf := 0, t.NumFields(); i < nf; i++ { - if a := s.Alignof(t.Field(i).Type()); a > max { - max = a - } - } - return max - case *types2.Slice, *types2.Interface: - // Multiword data structures are effectively structs - // in which each element has size PtrSize. - return int64(types.PtrSize) - case *types2.Basic: - // Strings are like slices and interfaces. - if t.Info()&types2.IsString != 0 { - return int64(types.PtrSize) - } - } - a := s.Sizeof(T) // may be 0 - // spec: "For a variable x of any type: unsafe.Alignof(x) is at least 1." - if a < 1 { - return 1 - } - // complex{64,128} are aligned like [2]float{32,64}. - if isComplex(T) { - a /= 2 - } - if a > int64(types.RegSize) { - return int64(types.RegSize) - } - return a -} - -func isComplex(T types2.Type) bool { - basic, ok := T.Underlying().(*types2.Basic) - return ok && basic.Info()&types2.IsComplex != 0 -} - -func (s *gcSizes) Offsetsof(fields []*types2.Var) []int64 { - offsets := make([]int64, len(fields)) - var offs int64 - for i, f := range fields { - if offs < 0 { - // all remaining offsets are too large - offsets[i] = -1 - continue - } - // offs >= 0 - typ := f.Type() - a := s.Alignof(typ) - offs = types.RoundUp(offs, a) // possibly < 0 if align overflows - offsets[i] = offs - if d := s.Sizeof(typ); d >= 0 && offs >= 0 { - offs += d // ok to overflow to < 0 - } else { - offs = -1 - } - } - return offsets -} - -func (s *gcSizes) Sizeof(T types2.Type) int64 { - switch t := T.Underlying().(type) { - case *types2.Basic: - k := t.Kind() - if int(k) < len(basicSizes) { - if s := basicSizes[k]; s > 0 { - return int64(s) - } - } - switch k { - case types2.String: - return int64(types.PtrSize) * 2 - case types2.Int, types2.Uint, types2.Uintptr, types2.UnsafePointer: - return int64(types.PtrSize) - } - panic(fmt.Sprintf("unimplemented basic: %v (kind %v)", T, k)) - case *types2.Array: - n := t.Len() - if n <= 0 { - return 0 - } - // n > 0 - // gc: Size includes alignment padding. - esize := s.Sizeof(t.Elem()) - if esize < 0 { - return -1 // array element too large - } - if esize == 0 { - return 0 // 0-size element - } - // esize > 0 - // Final size is esize * n; and size must be <= maxInt64. - const maxInt64 = 1<<63 - 1 - if esize > maxInt64/n { - return -1 // esize * n overflows - } - return esize * n - case *types2.Slice: - return int64(types.PtrSize) * 3 - case *types2.Struct: - n := t.NumFields() - if n == 0 { - return 0 - } - fields := make([]*types2.Var, n) - for i := range fields { - fields[i] = t.Field(i) - } - offsets := s.Offsetsof(fields) - - // gc: The last field of a non-zero-sized struct is not allowed to - // have size 0. - last := s.Sizeof(fields[n-1].Type()) - if last == 0 && offsets[n-1] > 0 { - last = 1 - } - - // gc: Size includes alignment padding. - return types.RoundUp(offsets[n-1]+last, s.Alignof(t)) // may overflow to < 0 which is ok - case *types2.Interface: - return int64(types.PtrSize) * 2 - case *types2.Chan, *types2.Map, *types2.Pointer, *types2.Signature: - return int64(types.PtrSize) - default: - panic(fmt.Sprintf("unimplemented type: %T", t)) - } -} - -var basicSizes = [...]byte{ - types2.Invalid: 1, - types2.Bool: 1, - types2.Int8: 1, - types2.Int16: 2, - types2.Int32: 4, - types2.Int64: 8, - types2.Uint8: 1, - types2.Uint16: 2, - types2.Uint32: 4, - types2.Uint64: 8, - types2.Float32: 4, - types2.Float64: 8, - types2.Complex64: 8, - types2.Complex128: 16, -}