]> Cypherpunks repositories - gostls13.git/commitdiff
[dev.regabi] cmd/compile: separate dowidth better
authorRuss Cox <rsc@golang.org>
Mon, 21 Dec 2020 06:55:44 +0000 (01:55 -0500)
committerRuss Cox <rsc@golang.org>
Tue, 22 Dec 2020 19:31:57 +0000 (19:31 +0000)
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>
src/cmd/compile/internal/gc/abiutils_test.go
src/cmd/compile/internal/gc/align.go
src/cmd/compile/internal/gc/main.go
src/cmd/compile/internal/gc/pgen.go
src/cmd/compile/internal/gc/reflect.go
src/cmd/compile/internal/gc/sinit.go
src/cmd/compile/internal/ir/name.go
src/cmd/compile/internal/types/type.go

index 16bd787bea922d4aa6c8fbf55146f3502c833022..14bd7ff0970b965d38cee09d71c1eebe16de8005 100644 (file)
@@ -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
index 95a5dbef29f24152dace735956a557bb53b53f37..a9cf7fb50aa05cceec6b2a8cb579dd2f138b53b0 100644 (file)
@@ -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
 //
index de2b3db36aa7fd84dc0d4f348c95bf152c6d728d..343ad9d1d9b32dc2c1f0478a07ba4c26e57ea4cc 100644 (file)
@@ -208,6 +208,7 @@ func Main(archInit func(*Arch)) {
 
        Widthptr = thearch.LinkArch.PtrSize
        Widthreg = thearch.LinkArch.RegSize
+       MaxWidth = thearch.MAXWIDTH
 
        Target = new(ir.Package)
 
index dae9d79147599e82279cf8111ca44fffcd425bc2..8f7aa8e4e74d6f8645997299f6dc2792e3117e7e 100644 (file)
@@ -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 {
index 615b8bdbf1edf01e61cb12bd516ebff5d49847e3..8e2c6f62e11dcc4f9e5ee4f6607339b57e8d72f8 100644 (file)
@@ -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
 }
 
index a845bc5d75a2b0baca2165e4844d02d01683e147..9ef2bd56ebabefd9e02eb24628f434d94c07f805 100644 (file)
@@ -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
index b0b33cccfaefba5357e97ff8a7976574af3c20fd..64c60b93d8f57908ff7e6fd648e8837c279ca1bb 100644 (file)
@@ -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 {
index 4d1d30133c8cf05b441f290162d1ff9cda759c8b..752c268fa2ad2a26a07e7a6b671bcd9d270cc610 100644 (file)
@@ -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.