diff options
author | Russ Cox <rsc@golang.org> | 2020-12-21 01:55:44 -0500 |
---|---|---|
committer | Russ Cox <rsc@golang.org> | 2020-12-22 19:31:57 +0000 |
commit | 7c8f5356abd7aadf32b028ce76a8a76cd5438258 (patch) | |
tree | dfa0df9dcdca4864abb46bd1c81309f2c3a0f24b /src/cmd | |
parent | cb28c96be8b8010dd979e0723bf5a94b11962a93 (diff) | |
download | go-7c8f5356abd7aadf32b028ce76a8a76cd5438258.tar.gz go-7c8f5356abd7aadf32b028ce76a8a76cd5438258.zip |
[dev.regabi] cmd/compile: separate dowidth better
Having a global MaxWidth lets us avoid needing to
refer to thearch from split-out packages when all
they need is thearch.MAXWIDTH.
And make a couple interface changes to let dowidth
avoid importing package ir directly.
Then it can move into package types.
Change-Id: I2c12e8e22252597530e648848320e19bdd490a01
Reviewed-on: https://go-review.googlesource.com/c/go/+/279302
Trust: Russ Cox <rsc@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
Diffstat (limited to 'src/cmd')
-rw-r--r-- | src/cmd/compile/internal/gc/abiutils_test.go | 1 | ||||
-rw-r--r-- | src/cmd/compile/internal/gc/align.go | 29 | ||||
-rw-r--r-- | src/cmd/compile/internal/gc/main.go | 1 | ||||
-rw-r--r-- | src/cmd/compile/internal/gc/pgen.go | 2 | ||||
-rw-r--r-- | src/cmd/compile/internal/gc/reflect.go | 3 | ||||
-rw-r--r-- | src/cmd/compile/internal/gc/sinit.go | 2 | ||||
-rw-r--r-- | src/cmd/compile/internal/ir/name.go | 18 | ||||
-rw-r--r-- | src/cmd/compile/internal/types/type.go | 12 |
8 files changed, 51 insertions, 17 deletions
diff --git a/src/cmd/compile/internal/gc/abiutils_test.go b/src/cmd/compile/internal/gc/abiutils_test.go index 16bd787bea..14bd7ff097 100644 --- a/src/cmd/compile/internal/gc/abiutils_test.go +++ b/src/cmd/compile/internal/gc/abiutils_test.go @@ -29,6 +29,7 @@ func TestMain(m *testing.M) { thearch.LinkArch = &x86.Linkamd64 thearch.REGSP = x86.REGSP thearch.MAXWIDTH = 1 << 50 + MaxWidth = thearch.MAXWIDTH base.Ctxt = obj.Linknew(thearch.LinkArch) base.Ctxt.DiagFunc = base.Errorf base.Ctxt.DiagFlush = base.FlushErrors diff --git a/src/cmd/compile/internal/gc/align.go b/src/cmd/compile/internal/gc/align.go index 95a5dbef29..a9cf7fb50a 100644 --- a/src/cmd/compile/internal/gc/align.go +++ b/src/cmd/compile/internal/gc/align.go @@ -7,12 +7,14 @@ package gc import ( "bytes" "cmd/compile/internal/base" - "cmd/compile/internal/ir" "cmd/compile/internal/types" "fmt" "sort" ) +// MaxWidth is the maximum size of a value on the target architecture. +var MaxWidth int64 + // sizeCalculationDisabled indicates whether it is safe // to calculate Types' widths and alignments. See dowidth. var sizeCalculationDisabled bool @@ -84,7 +86,7 @@ func expandiface(t *types.Type) { sort.Sort(methcmp(methods)) - if int64(len(methods)) >= thearch.MAXWIDTH/int64(Widthptr) { + if int64(len(methods)) >= MaxWidth/int64(Widthptr) { base.ErrorfAt(typePos(t), "interface too large") } for i, m := range methods { @@ -118,8 +120,7 @@ func widstruct(errtype *types.Type, t *types.Type, o int64, flag int) int64 { o = Rnd(o, int64(f.Type.Align)) } f.Offset = o - if n := ir.AsNode(f.Nname); n != nil { - n := n.Name() + if f.Nname != nil { // addrescapes has similar code to update these offsets. // Usually addrescapes runs after widstruct, // in which case we could drop this, @@ -127,12 +128,7 @@ func widstruct(errtype *types.Type, t *types.Type, o int64, flag int) int64 { // NOTE(rsc): This comment may be stale. // It's possible the ordering has changed and this is // now the common case. I'm not sure. - if n.Name().Stackcopy != nil { - n.Name().Stackcopy.SetFrameOffset(o) - n.SetFrameOffset(0) - } else { - n.SetFrameOffset(o) - } + f.Nname.(types.VarObject).RecordFrameOffset(o) } w := f.Type.Width @@ -143,7 +139,7 @@ func widstruct(errtype *types.Type, t *types.Type, o int64, flag int) int64 { lastzero = o } o += w - maxwidth := thearch.MAXWIDTH + maxwidth := MaxWidth // On 32-bit systems, reflect tables impose an additional constraint // that each field start offset must fit in 31 bits. if maxwidth < 1<<32 { @@ -206,7 +202,7 @@ func findTypeLoop(t *types.Type, path *[]*types.Type) bool { } *path = append(*path, t) - if findTypeLoop(t.Obj().(*ir.Name).Ntype.Type(), path) { + if findTypeLoop(t.Obj().(types.TypeObject).TypeDefn(), path) { return true } *path = (*path)[:len(*path)-1] @@ -419,7 +415,7 @@ func dowidth(t *types.Type) { dowidth(t.Elem()) if t.Elem().Width != 0 { - cap := (uint64(thearch.MAXWIDTH) - 1) / uint64(t.Elem().Width) + cap := (uint64(MaxWidth) - 1) / uint64(t.Elem().Width) if uint64(t.NumElem()) > cap { base.ErrorfAt(typePos(t), "type %L larger than address space", t) } @@ -479,6 +475,13 @@ func dowidth(t *types.Type) { resumecheckwidth() } +// CalcStructSize calculates the size of s, +// filling in s.Width and s.Align, +// even if size calculation is otherwise disabled. +func CalcStructSize(s *types.Type) { + s.Width = widstruct(s, s, 0, 1) // sets align +} + // when a type's width should be known, we call checkwidth // to compute it. during a declaration like // diff --git a/src/cmd/compile/internal/gc/main.go b/src/cmd/compile/internal/gc/main.go index de2b3db36a..343ad9d1d9 100644 --- a/src/cmd/compile/internal/gc/main.go +++ b/src/cmd/compile/internal/gc/main.go @@ -208,6 +208,7 @@ func Main(archInit func(*Arch)) { Widthptr = thearch.LinkArch.PtrSize Widthreg = thearch.LinkArch.RegSize + MaxWidth = thearch.MAXWIDTH Target = new(ir.Package) diff --git a/src/cmd/compile/internal/gc/pgen.go b/src/cmd/compile/internal/gc/pgen.go index dae9d79147..8f7aa8e4e7 100644 --- a/src/cmd/compile/internal/gc/pgen.go +++ b/src/cmd/compile/internal/gc/pgen.go @@ -164,7 +164,7 @@ func (s *ssafn) AllocFrame(f *ssa.Func) { dowidth(n.Type()) w := n.Type().Width - if w >= thearch.MAXWIDTH || w < 0 { + if w >= MaxWidth || w < 0 { base.Fatalf("bad width") } if w == 0 && lastHasPtr { diff --git a/src/cmd/compile/internal/gc/reflect.go b/src/cmd/compile/internal/gc/reflect.go index 615b8bdbf1..8e2c6f62e1 100644 --- a/src/cmd/compile/internal/gc/reflect.go +++ b/src/cmd/compile/internal/gc/reflect.go @@ -331,8 +331,7 @@ func deferstruct(stksize int64) *types.Type { // build struct holding the above fields s := types.NewStruct(types.NoPkg, fields) s.SetNoalg(true) - s.Width = widstruct(s, s, 0, 1) - s.Align = uint8(Widthptr) + CalcStructSize(s) return s } diff --git a/src/cmd/compile/internal/gc/sinit.go b/src/cmd/compile/internal/gc/sinit.go index a845bc5d75..9ef2bd56eb 100644 --- a/src/cmd/compile/internal/gc/sinit.go +++ b/src/cmd/compile/internal/gc/sinit.go @@ -1019,7 +1019,7 @@ func stataddr(n ir.Node) (name *ir.Name, offset int64, ok bool) { } // Check for overflow. - if n.Type().Width != 0 && thearch.MAXWIDTH/n.Type().Width <= int64(l) { + if n.Type().Width != 0 && MaxWidth/n.Type().Width <= int64(l) { break } offset += int64(l) * n.Type().Width diff --git a/src/cmd/compile/internal/ir/name.go b/src/cmd/compile/internal/ir/name.go index b0b33cccfa..64c60b93d8 100644 --- a/src/cmd/compile/internal/ir/name.go +++ b/src/cmd/compile/internal/ir/name.go @@ -147,6 +147,24 @@ func (n *Name) isExpr() {} // Callers must use n.CloneName to make clear they intend to create a separate name. func (n *Name) CloneName() *Name { c := *n; return &c } +// TypeDefn returns the type definition for a named OTYPE. +// That is, given "type T Defn", it returns Defn. +// It is used by package types. +func (n *Name) TypeDefn() *types.Type { + return n.Ntype.Type() +} + +// RecordFrameOffset records the frame offset for the name. +// It is used by package types when laying out function arguments. +func (n *Name) RecordFrameOffset(offset int64) { + if n.Stackcopy != nil { + n.Stackcopy.SetFrameOffset(offset) + n.SetFrameOffset(0) + } else { + n.SetFrameOffset(offset) + } +} + // NewNameAt returns a new ONAME Node associated with symbol s at position pos. // The caller is responsible for setting Curfn. func NewNameAt(pos src.XPos, sym *types.Sym) *Name { diff --git a/src/cmd/compile/internal/types/type.go b/src/cmd/compile/internal/types/type.go index 4d1d30133c..752c268fa2 100644 --- a/src/cmd/compile/internal/types/type.go +++ b/src/cmd/compile/internal/types/type.go @@ -20,6 +20,18 @@ type Object interface { Type() *Type } +// A TypeObject is an Object representing a named type. +type TypeObject interface { + Object + TypeDefn() *Type // for "type T Defn", returns Defn +} + +// A VarObject is an Object representing a function argument, variable, or struct field. +type VarObject interface { + Object + RecordFrameOffset(int64) // save frame offset +} + //go:generate stringer -type EType -trimprefix T // EType describes a kind of type. |