1
0
mirror of https://github.com/golang/go synced 2024-11-11 19:51:37 -07:00

[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>
This commit is contained in:
Russ Cox 2020-12-21 01:55:44 -05:00
parent cb28c96be8
commit 7c8f5356ab
8 changed files with 51 additions and 17 deletions

View 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

View 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
//

View 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)

View 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 {

View 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
}

View 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

View 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 {

View 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.