cmd/compile: abstract type type+value obtained from types2

In preparation for encoding it in a more efficient way.

Change-Id: I299dd2befc3d07107a1b7b49225bbb9f2e48a343
Reviewed-on: https://go-review.googlesource.com/c/go/+/432896
Reviewed-by: Cherry Mui <cherryyz@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Keith Randall <khr@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
This commit is contained in:
Keith Randall 2022-09-02 13:50:10 -07:00
parent dcb90152a4
commit b52783c1e9
4 changed files with 52 additions and 50 deletions

View file

@ -27,10 +27,7 @@ func (g *irgen) expr(expr syntax.Expr) ir.Node {
return ir.BlankNode
}
tv, ok := g.info.Types[expr]
if !ok {
base.FatalfAt(g.pos(expr), "missing type for %v (%T)", expr, expr)
}
tv := g.typeAndValue(expr)
switch {
case tv.IsBuiltin():
// Qualified builtins, such as unsafe.Add and unsafe.Slice.
@ -105,8 +102,7 @@ func (g *irgen) expr0(typ types2.Type, expr syntax.Expr) ir.Node {
case *syntax.IndexExpr:
args := unpackListExpr(expr.Index)
if len(args) == 1 {
tv, ok := g.info.Types[args[0]]
assert(ok)
tv := g.typeAndValue(args[0])
if tv.IsValue() {
// This is just a normal index expression
n := Index(pos, g.typ(typ), g.expr(expr.X), g.expr(args[0]))

View file

@ -390,3 +390,19 @@ func (g *irgen) unhandled(what string, p poser) {
func (g *irgen) delayTransform() bool {
return g.topFuncIsGeneric
}
func (g *irgen) typeAndValue(x syntax.Expr) types2.TypeAndValue {
tv, ok := g.info.Types[x]
if !ok {
base.FatalfAt(g.pos(x), "missing type for %v (%T)", x, x)
}
return tv
}
func (g *irgen) type2(x syntax.Expr) types2.Type {
tv, ok := g.info.Types[x]
if !ok {
base.FatalfAt(g.pos(x), "missing type for %v (%T)", x, x)
}
return tv.Type
}

View file

@ -53,7 +53,7 @@ func (g *irgen) match(t1 *types.Type, t2 types2.Type, hasOK bool) bool {
func (g *irgen) validate(n syntax.Node) {
switch n := n.(type) {
case *syntax.CallExpr:
tv := g.info.Types[n.Fun]
tv := g.typeAndValue(n.Fun)
if tv.IsBuiltin() {
fun := n.Fun
for {
@ -81,7 +81,7 @@ func (g *irgen) validateBuiltin(name string, call *syntax.CallExpr) {
// Check that types2+gcSizes calculates sizes the same
// as cmd/compile does.
tv := g.info.Types[call]
tv := g.typeAndValue(call)
if !tv.IsValue() {
base.FatalfAt(g.pos(call), "expected a value")
}
@ -106,9 +106,9 @@ func (g *irgen) validateBuiltin(name string, call *syntax.CallExpr) {
func (g *irgen) unsafeExpr(name string, arg syntax.Expr) int64 {
switch name {
case "Alignof":
return g.typ(g.info.Types[arg].Type).Alignment()
return g.typ(g.type2(arg)).Alignment()
case "Sizeof":
return g.typ(g.info.Types[arg].Type).Size()
return g.typ(g.type2(arg)).Size()
}
// Offsetof
@ -116,7 +116,7 @@ func (g *irgen) unsafeExpr(name string, arg syntax.Expr) int64 {
sel := arg.(*syntax.SelectorExpr)
selection := g.info.Selections[sel]
typ := g.typ(g.info.Types[sel.X].Type)
typ := g.typ(g.type2(sel.X))
typ = deref(typ)
var offset int64

View file

@ -120,12 +120,21 @@ func (pw *pkgWriter) unexpected(what string, p poser) {
pw.fatalf(p, "unexpected %s: %v (%T)", what, p, p)
}
func (pw *pkgWriter) typeAndValue(x syntax.Expr) types2.TypeAndValue {
tv, ok := pw.info.Types[x]
if !ok {
pw.fatalf(x, "missing Types entry: %v", syntax.String(x))
}
return tv
}
func (pw *pkgWriter) maybeTypeAndValue(x syntax.Expr) (types2.TypeAndValue, bool) {
tv, ok := pw.info.Types[x]
return tv, ok
}
// typeOf returns the Type of the given value expression.
func (pw *pkgWriter) typeOf(expr syntax.Expr) types2.Type {
tv, ok := pw.info.Types[expr]
if !ok {
pw.fatalf(expr, "missing Types entry: %v", syntax.String(expr))
}
tv := pw.typeAndValue(expr)
if !tv.IsValue() {
pw.fatalf(expr, "expected value: %v", syntax.String(expr))
}
@ -811,8 +820,7 @@ func (w *writer) doObj(wext *writer, obj types2.Object) pkgbits.CodeObj {
//
// TODO(mdempsky): Document how this differs from exprType.
func (w *writer) typExpr(expr syntax.Expr) {
tv, ok := w.p.info.Types[expr]
assert(ok)
tv := w.p.typeAndValue(expr)
assert(tv.IsType())
w.typ(tv.Type)
}
@ -1533,7 +1541,7 @@ func (w *writer) switchStmt(stmt *syntax.SwitchStmt) {
if iface != nil {
w.Len(len(cases))
for _, cas := range cases {
if w.Bool(isNil(w.p.info, cas)) {
if w.Bool(isNil(w.p, cas)) {
continue
}
w.exprType(iface, cas)
@ -1598,10 +1606,10 @@ func (w *writer) expr(expr syntax.Expr) {
expr = unparen(expr) // skip parens; unneeded after typecheck
obj, inst := lookupObj(w.p.info, expr)
obj, inst := lookupObj(w.p, expr)
targs := inst.TypeArgs
if tv, ok := w.p.info.Types[expr]; ok {
if tv, ok := w.p.maybeTypeAndValue(expr); ok {
if tv.IsType() {
w.p.fatalf(expr, "unexpected type expression %v", syntax.String(expr))
}
@ -1698,8 +1706,7 @@ func (w *writer) expr(expr syntax.Expr) {
case types2.MethodExpr:
w.Code(exprMethodExpr)
tv, ok := w.p.info.Types[expr.X]
assert(ok)
tv := w.p.typeAndValue(expr.X)
assert(tv.IsType())
index := sel.Index()
@ -1793,8 +1800,7 @@ func (w *writer) expr(expr syntax.Expr) {
w.implicitConvExpr(commonType, expr.Y)
case *syntax.CallExpr:
tv, ok := w.p.info.Types[expr.Fun]
assert(ok)
tv := w.p.typeAndValue(expr.Fun)
if tv.IsType() {
assert(len(expr.ArgList) == 1)
assert(!expr.HasDots)
@ -1804,7 +1810,7 @@ func (w *writer) expr(expr syntax.Expr) {
var rtype types2.Type
if tv.IsBuiltin() {
switch obj, _ := lookupObj(w.p.info, expr.Fun); obj.Name() {
switch obj, _ := lookupObj(w.p, expr.Fun); obj.Name() {
case "make":
assert(len(expr.ArgList) >= 1)
assert(!expr.HasDots)
@ -1870,7 +1876,7 @@ func (w *writer) expr(expr syntax.Expr) {
w.Bool(false) // not a method call (i.e., normal function call)
if obj, inst := lookupObj(w.p.info, fun); w.Bool(obj != nil && inst.TypeArgs.Len() != 0) {
if obj, inst := lookupObj(w.p, fun); w.Bool(obj != nil && inst.TypeArgs.Len() != 0) {
obj := obj.(*types2.Func)
w.pos(fun)
@ -2244,8 +2250,7 @@ func (w *writer) convRTTI(src, dst types2.Type) {
func (w *writer) exprType(iface types2.Type, typ syntax.Expr) {
base.Assertf(iface == nil || isInterface(iface), "%v must be nil or an interface type", iface)
tv, ok := w.p.info.Types[typ]
assert(ok)
tv := w.p.typeAndValue(typ)
assert(tv.IsType())
w.Sync(pkgbits.SyncExprType)
@ -2597,12 +2602,11 @@ func isGlobal(obj types2.Object) bool {
// lookupObj returns the object that expr refers to, if any. If expr
// is an explicit instantiation of a generic object, then the instance
// object is returned as well.
func lookupObj(info *types2.Info, expr syntax.Expr) (obj types2.Object, inst types2.Instance) {
func lookupObj(p *pkgWriter, expr syntax.Expr) (obj types2.Object, inst types2.Instance) {
if index, ok := expr.(*syntax.IndexExpr); ok {
args := unpackListExpr(index.Index)
if len(args) == 1 {
tv, ok := info.Types[args[0]]
assert(ok)
tv := p.typeAndValue(args[0])
if tv.IsValue() {
return // normal index expression
}
@ -2613,15 +2617,15 @@ func lookupObj(info *types2.Info, expr syntax.Expr) (obj types2.Object, inst typ
// Strip package qualifier, if present.
if sel, ok := expr.(*syntax.SelectorExpr); ok {
if !isPkgQual(info, sel) {
if !isPkgQual(p.info, sel) {
return // normal selector expression
}
expr = sel.Sel
}
if name, ok := expr.(*syntax.Name); ok {
obj = info.Uses[name]
inst = info.Instances[name]
obj = p.info.Uses[name]
inst = p.info.Instances[name]
}
return
}
@ -2636,24 +2640,10 @@ func isPkgQual(info *types2.Info, sel *syntax.SelectorExpr) bool {
return false
}
// isMultiValueExpr reports whether expr is a function call expression
// that yields multiple values.
func isMultiValueExpr(info *types2.Info, expr syntax.Expr) bool {
tv, ok := info.Types[expr]
assert(ok)
assert(tv.IsValue())
if tuple, ok := tv.Type.(*types2.Tuple); ok {
assert(tuple.Len() > 1)
return true
}
return false
}
// isNil reports whether expr is a (possibly parenthesized) reference
// to the predeclared nil value.
func isNil(info *types2.Info, expr syntax.Expr) bool {
tv, ok := info.Types[expr]
assert(ok)
func isNil(p *pkgWriter, expr syntax.Expr) bool {
tv := p.typeAndValue(expr)
return tv.IsNil()
}