diff options
author | Matthew Dempsky <mdempsky@google.com> | 2020-12-01 02:58:41 -0800 |
---|---|---|
committer | Matthew Dempsky <mdempsky@google.com> | 2020-12-01 17:16:39 +0000 |
commit | a17c5e2fce9340ec19d4019490b38a7645f244df (patch) | |
tree | 104f9a32021d30d8cf1dfed0ad0b2b40c9e11377 /src | |
parent | f37aa5e4e26a7212b6300e2021b8e6ea7000979b (diff) | |
download | go-a17c5e2fce9340ec19d4019490b38a7645f244df.tar.gz go-a17c5e2fce9340ec19d4019490b38a7645f244df.zip |
[dev.regabi] cmd/compile: add NewBasic and cleanup universe
This CL introduces types.NewBasic, for creating the predeclared
universal types, and reorganizes how the universe is initialized so
that all predeclared types are uniformly constructed.
There are now a bunch of Type fields that are no longer assigned
outside of the package, so this CL also introduces some new accessor
methods that a subsequent CL will mechanically introduce uses of.
Change-Id: Ie7996c3d5f1ca46cd5bfe45ecc91ebfa6a7b6c7d
Reviewed-on: https://go-review.googlesource.com/c/go/+/274435
Trust: Matthew Dempsky <mdempsky@google.com>
Reviewed-by: Russ Cox <rsc@golang.org>
Diffstat (limited to 'src')
-rw-r--r-- | src/cmd/compile/internal/gc/universe.go | 194 | ||||
-rw-r--r-- | src/cmd/compile/internal/types/type.go | 21 |
2 files changed, 90 insertions, 125 deletions
diff --git a/src/cmd/compile/internal/gc/universe.go b/src/cmd/compile/internal/gc/universe.go index 31b49e05a5..b1492659b4 100644 --- a/src/cmd/compile/internal/gc/universe.go +++ b/src/cmd/compile/internal/gc/universe.go @@ -87,31 +87,80 @@ var unsafeFuncs = [...]struct { // initUniverse initializes the universe block. func initUniverse() { - lexinit() - typeinit() - lexinit1() -} + if Widthptr == 0 { + base.Fatalf("typeinit before betypeinit") + } -// lexinit initializes known symbols and the basic types. -func lexinit() { - for _, s := range &basicTypes { - etype := s.etype - if int(etype) >= len(types.Types) { - base.Fatalf("lexinit: %s bad etype", s.name) + slicePtrOffset = 0 + sliceLenOffset = Rnd(slicePtrOffset+int64(Widthptr), int64(Widthptr)) + sliceCapOffset = Rnd(sliceLenOffset+int64(Widthptr), int64(Widthptr)) + sizeofSlice = Rnd(sliceCapOffset+int64(Widthptr), int64(Widthptr)) + + // string is same as slice wo the cap + sizeofString = Rnd(sliceLenOffset+int64(Widthptr), int64(Widthptr)) + + for et := types.EType(0); et < types.NTYPE; et++ { + simtype[et] = et + } + + types.Types[types.TANY] = types.New(types.TANY) + types.Types[types.TINTER] = types.New(types.TINTER) // empty interface + + defBasic := func(kind types.EType, pkg *types.Pkg, name string) *types.Type { + sym := pkg.Lookup(name) + n := ir.NewNameAt(src.NoXPos, sym) + n.SetOp(ir.OTYPE) + t := types.NewBasic(kind, n) + n.SetType(t) + sym.Def = n + if kind != types.TANY { + dowidth(t) } - s2 := ir.BuiltinPkg.Lookup(s.name) - t := types.Types[etype] - if t == nil { - t = types.New(etype) - t.Sym = s2 - if etype != types.TANY && etype != types.TSTRING { - dowidth(t) - } - types.Types[etype] = t + return t + } + + for _, s := range &basicTypes { + types.Types[s.etype] = defBasic(s.etype, ir.BuiltinPkg, s.name) + } + + for _, s := range &typedefs { + sameas := s.sameas32 + if Widthptr == 8 { + sameas = s.sameas64 } - s2.Def = ir.TypeNode(t) + simtype[s.etype] = sameas + + types.Types[s.etype] = defBasic(s.etype, ir.BuiltinPkg, s.name) } + // We create separate byte and rune types for better error messages + // rather than just creating type alias *types.Sym's for the uint8 and + // int32 types. Hence, (bytetype|runtype).Sym.isAlias() is false. + // TODO(gri) Should we get rid of this special case (at the cost + // of less informative error messages involving bytes and runes)? + // (Alternatively, we could introduce an OTALIAS node representing + // type aliases, albeit at the cost of having to deal with it everywhere). + types.Bytetype = defBasic(types.TUINT8, ir.BuiltinPkg, "byte") + types.Runetype = defBasic(types.TINT32, ir.BuiltinPkg, "rune") + + // error type + s := ir.BuiltinPkg.Lookup("error") + n := ir.NewNameAt(src.NoXPos, s) + n.SetOp(ir.OTYPE) + types.Errortype = types.NewNamed(n) + types.Errortype.SetUnderlying(makeErrorInterface()) + n.SetType(types.Errortype) + s.Def = n + dowidth(types.Errortype) + + types.Types[types.TUNSAFEPTR] = defBasic(types.TUNSAFEPTR, unsafepkg, "Pointer") + + // simple aliases + simtype[types.TMAP] = types.TPTR + simtype[types.TCHAN] = types.TPTR + simtype[types.TFUNC] = types.TPTR + simtype[types.TUNSAFEPTR] = types.TPTR + for _, s := range &builtinFuncs { s2 := ir.BuiltinPkg.Lookup(s.name) s2.Def = NewName(s2) @@ -124,19 +173,13 @@ func lexinit() { ir.AsNode(s2.Def).SetSubOp(s.op) } - types.UntypedString = types.New(types.TSTRING) - types.UntypedBool = types.New(types.TBOOL) - types.Types[types.TANY] = types.New(types.TANY) - - s := ir.BuiltinPkg.Lookup("true") + s = ir.BuiltinPkg.Lookup("true") s.Def = nodbool(true) ir.AsNode(s.Def).SetSym(lookup("true")) - ir.AsNode(s.Def).SetType(types.UntypedBool) s = ir.BuiltinPkg.Lookup("false") s.Def = nodbool(false) ir.AsNode(s.Def).SetSym(lookup("false")) - ir.AsNode(s.Def).SetType(types.UntypedBool) s = lookup("_") s.Block = -100 @@ -160,28 +203,6 @@ func lexinit() { s = ir.BuiltinPkg.Lookup("iota") s.Def = ir.Nod(ir.OIOTA, nil, nil) ir.AsNode(s.Def).SetSym(s) -} - -func typeinit() { - if Widthptr == 0 { - base.Fatalf("typeinit before betypeinit") - } - - for et := types.EType(0); et < types.NTYPE; et++ { - simtype[et] = et - } - - types.Types[types.TPTR] = types.New(types.TPTR) - dowidth(types.Types[types.TPTR]) - - t := types.New(types.TUNSAFEPTR) - types.Types[types.TUNSAFEPTR] = t - t.Sym = unsafepkg.Lookup("Pointer") - n := ir.NewNameAt(src.NoXPos, t.Sym) // NewNameAt to get a package for use tracking - n.SetOp(ir.OTYPE) - n.SetType(t) - t.Sym.Def = n - dowidth(types.Types[types.TUNSAFEPTR]) for et := types.TINT8; et <= types.TUINT64; et++ { isInt[et] = true @@ -259,8 +280,7 @@ func typeinit() { okforcmp[types.TSTRING] = true - var i int - for i = 0; i < len(okfor); i++ { + for i := range okfor { okfor[i] = okfornone[:] } @@ -302,25 +322,6 @@ func typeinit() { iscmp[ir.OLE] = true iscmp[ir.OEQ] = true iscmp[ir.ONE] = true - - types.Types[types.TINTER] = types.New(types.TINTER) // empty interface - - // simple aliases - simtype[types.TMAP] = types.TPTR - simtype[types.TCHAN] = types.TPTR - simtype[types.TFUNC] = types.TPTR - simtype[types.TUNSAFEPTR] = types.TPTR - - slicePtrOffset = 0 - sliceLenOffset = Rnd(slicePtrOffset+int64(Widthptr), int64(Widthptr)) - sliceCapOffset = Rnd(sliceLenOffset+int64(Widthptr), int64(Widthptr)) - sizeofSlice = Rnd(sliceCapOffset+int64(Widthptr), int64(Widthptr)) - - // string is same as slice wo the cap - sizeofString = Rnd(sliceLenOffset+int64(Widthptr), int64(Widthptr)) - - dowidth(types.Types[types.TSTRING]) - dowidth(types.UntypedString) } func makeErrorInterface() *types.Type { @@ -335,59 +336,6 @@ func makeErrorInterface() *types.Type { return t } -func lexinit1() { - // error type - n := ir.NewNameAt(src.NoXPos, ir.BuiltinPkg.Lookup("error")) - types.Errortype = types.NewNamed(n) - types.Errortype.SetUnderlying(makeErrorInterface()) - n.SetOp(ir.OTYPE) - n.SetType(types.Errortype) - n.Sym().Def = n - dowidth(types.Errortype) - - // We create separate byte and rune types for better error messages - // rather than just creating type alias *types.Sym's for the uint8 and - // int32 types. Hence, (bytetype|runtype).Sym.isAlias() is false. - // TODO(gri) Should we get rid of this special case (at the cost - // of less informative error messages involving bytes and runes)? - // (Alternatively, we could introduce an OTALIAS node representing - // type aliases, albeit at the cost of having to deal with it everywhere). - - // byte alias - s := ir.BuiltinPkg.Lookup("byte") - types.Bytetype = types.New(types.TUINT8) - types.Bytetype.Sym = s - s.Def = ir.TypeNode(types.Bytetype) - dowidth(types.Bytetype) - - // rune alias - s = ir.BuiltinPkg.Lookup("rune") - types.Runetype = types.New(types.TINT32) - types.Runetype.Sym = s - s.Def = ir.TypeNode(types.Runetype) - dowidth(types.Runetype) - - // backend-dependent builtin types (e.g. int). - for _, s := range &typedefs { - s1 := ir.BuiltinPkg.Lookup(s.name) - - sameas := s.sameas32 - if Widthptr == 8 { - sameas = s.sameas64 - } - - simtype[s.etype] = sameas - - t := types.New(s.etype) - t.Sym = s1 - types.Types[s.etype] = t - s1.Def = ir.TypeNode(t) - s1.Origpkg = ir.BuiltinPkg - - dowidth(t) - } -} - // finishUniverse makes the universe block visible within the current package. func finishUniverse() { // Operationally, this is similar to a dot import of builtinpkg, except diff --git a/src/cmd/compile/internal/types/type.go b/src/cmd/compile/internal/types/type.go index d6d56426a5..f0211a67fb 100644 --- a/src/cmd/compile/internal/types/type.go +++ b/src/cmd/compile/internal/types/type.go @@ -110,8 +110,8 @@ var ( Errortype *Type // Types to represent untyped string and boolean constants. - UntypedString *Type - UntypedBool *Type + UntypedString = New(TSTRING) + UntypedBool = New(TBOOL) // Types to represent untyped numeric constants. UntypedInt = New(TIDEAL) @@ -184,6 +184,15 @@ func (t *Type) SetNoalg(b bool) { t.flags.set(typeNoalg, b) } func (t *Type) SetDeferwidth(b bool) { t.flags.set(typeDeferwidth, b) } func (t *Type) SetRecur(b bool) { t.flags.set(typeRecur, b) } +// Kind returns the kind of type t. +func (t *Type) Kind() EType { return t.Etype } + +// Sym returns the name of type t. +func (t *Type) GetSym() *Sym { return t.Sym } + +// Underlying returns the underlying type of type t. +func (t *Type) Underlying() *Type { return t.Orig } + // SetNod associates t with syntax node n. func (t *Type) SetNod(n IRNode) { // t.nod can be non-nil already @@ -1601,3 +1610,11 @@ func (t *Type) SetUnderlying(underlying *Type) { } } } + +// NewNamed returns a new basic type of the given kind. +func NewBasic(kind EType, obj IRNode) *Type { + t := New(kind) + t.Sym = obj.Sym() + t.nod = obj + return t +} |