go.tools/go/ssa: simplify builder.exprN now that go/types emits correct types.
(Follow-up to fix of issue 7060.) Also: comment fixes. R=gri CC=golang-codereviews https://golang.org/cl/47670043
This commit is contained in:
parent
2d6b34a0f5
commit
2845638157
|
|
@ -185,8 +185,7 @@ func (b *builder) logicalBinop(fn *Function, e *ast.BinaryExpr) Value {
|
||||||
// is token.ARROW).
|
// is token.ARROW).
|
||||||
//
|
//
|
||||||
func (b *builder) exprN(fn *Function, e ast.Expr) Value {
|
func (b *builder) exprN(fn *Function, e ast.Expr) Value {
|
||||||
var typ types.Type
|
typ := fn.Pkg.typeOf(e).(*types.Tuple)
|
||||||
var tuple Value
|
|
||||||
switch e := e.(type) {
|
switch e := e.(type) {
|
||||||
case *ast.ParenExpr:
|
case *ast.ParenExpr:
|
||||||
return b.exprN(fn, e.X)
|
return b.exprN(fn, e.X)
|
||||||
|
|
@ -197,49 +196,34 @@ func (b *builder) exprN(fn *Function, e ast.Expr) Value {
|
||||||
// cases for single-valued CallExpr.
|
// cases for single-valued CallExpr.
|
||||||
var c Call
|
var c Call
|
||||||
b.setCall(fn, e, &c.Call)
|
b.setCall(fn, e, &c.Call)
|
||||||
c.typ = fn.Pkg.typeOf(e)
|
c.typ = typ
|
||||||
return fn.emit(&c)
|
return fn.emit(&c)
|
||||||
|
|
||||||
case *ast.IndexExpr:
|
case *ast.IndexExpr:
|
||||||
mapt := fn.Pkg.typeOf(e.X).Underlying().(*types.Map)
|
mapt := fn.Pkg.typeOf(e.X).Underlying().(*types.Map)
|
||||||
typ = mapt.Elem()
|
|
||||||
lookup := &Lookup{
|
lookup := &Lookup{
|
||||||
X: b.expr(fn, e.X),
|
X: b.expr(fn, e.X),
|
||||||
Index: emitConv(fn, b.expr(fn, e.Index), mapt.Key()),
|
Index: emitConv(fn, b.expr(fn, e.Index), mapt.Key()),
|
||||||
CommaOk: true,
|
CommaOk: true,
|
||||||
}
|
}
|
||||||
|
lookup.setType(typ)
|
||||||
lookup.setPos(e.Lbrack)
|
lookup.setPos(e.Lbrack)
|
||||||
tuple = fn.emit(lookup)
|
return fn.emit(lookup)
|
||||||
|
|
||||||
case *ast.TypeAssertExpr:
|
case *ast.TypeAssertExpr:
|
||||||
t := fn.Pkg.typeOf(e).(*types.Tuple).At(0).Type()
|
return emitTypeTest(fn, b.expr(fn, e.X), typ.At(0).Type(), e.Lparen)
|
||||||
return emitTypeTest(fn, b.expr(fn, e.X), t, e.Lparen)
|
|
||||||
|
|
||||||
case *ast.UnaryExpr: // must be receive <-
|
case *ast.UnaryExpr: // must be receive <-
|
||||||
typ = fn.Pkg.typeOf(e.X).Underlying().(*types.Chan).Elem()
|
|
||||||
unop := &UnOp{
|
unop := &UnOp{
|
||||||
Op: token.ARROW,
|
Op: token.ARROW,
|
||||||
X: b.expr(fn, e.X),
|
X: b.expr(fn, e.X),
|
||||||
CommaOk: true,
|
CommaOk: true,
|
||||||
}
|
}
|
||||||
|
unop.setType(typ)
|
||||||
unop.setPos(e.OpPos)
|
unop.setPos(e.OpPos)
|
||||||
tuple = fn.emit(unop)
|
return fn.emit(unop)
|
||||||
|
|
||||||
default:
|
|
||||||
panic(fmt.Sprintf("unexpected exprN: %T", e))
|
|
||||||
}
|
}
|
||||||
|
panic(fmt.Sprintf("exprN(%T) in %s", e, fn))
|
||||||
// The typechecker sets the type of the expression to just the
|
|
||||||
// asserted type in the "value, ok" form, not to *types.Tuple
|
|
||||||
// (though it includes the valueOk operand in its error messages).
|
|
||||||
|
|
||||||
tuple.(interface {
|
|
||||||
setType(types.Type)
|
|
||||||
}).setType(types.NewTuple(
|
|
||||||
newVar("value", typ),
|
|
||||||
varOk,
|
|
||||||
))
|
|
||||||
return tuple
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// builtin emits to fn SSA instructions to implement a call to the
|
// builtin emits to fn SSA instructions to implement a call to the
|
||||||
|
|
@ -1133,8 +1117,8 @@ func (b *builder) compLit(fn *Function, addr Value, e *ast.CompositeLit) {
|
||||||
//
|
//
|
||||||
func (b *builder) switchStmt(fn *Function, s *ast.SwitchStmt, label *lblock) {
|
func (b *builder) switchStmt(fn *Function, s *ast.SwitchStmt, label *lblock) {
|
||||||
// We treat SwitchStmt like a sequential if-else chain.
|
// We treat SwitchStmt like a sequential if-else chain.
|
||||||
// More efficient strategies (e.g. multiway dispatch)
|
// Multiway dispatch can be recovered later by ssautil.Switches()
|
||||||
// are possible if all cases are free of side effects.
|
// to those cases that are free of side effects.
|
||||||
if s.Init != nil {
|
if s.Init != nil {
|
||||||
b.stmt(fn, s.Init)
|
b.stmt(fn, s.Init)
|
||||||
}
|
}
|
||||||
|
|
@ -1180,7 +1164,7 @@ func (b *builder) switchStmt(fn *Function, s *ast.SwitchStmt, label *lblock) {
|
||||||
for _, cond := range cc.List {
|
for _, cond := range cc.List {
|
||||||
nextCond = fn.newBasicBlock("switch.next")
|
nextCond = fn.newBasicBlock("switch.next")
|
||||||
// TODO(adonovan): opt: when tag==vTrue, we'd
|
// TODO(adonovan): opt: when tag==vTrue, we'd
|
||||||
// get better much code if we use b.cond(cond)
|
// get better code if we use b.cond(cond)
|
||||||
// instead of BinOp(EQL, tag, b.expr(cond))
|
// instead of BinOp(EQL, tag, b.expr(cond))
|
||||||
// followed by If. Don't forget conversions
|
// followed by If. Don't forget conversions
|
||||||
// though.
|
// though.
|
||||||
|
|
@ -1218,9 +1202,8 @@ func (b *builder) switchStmt(fn *Function, s *ast.SwitchStmt, label *lblock) {
|
||||||
// labelled by label.
|
// labelled by label.
|
||||||
//
|
//
|
||||||
func (b *builder) typeSwitchStmt(fn *Function, s *ast.TypeSwitchStmt, label *lblock) {
|
func (b *builder) typeSwitchStmt(fn *Function, s *ast.TypeSwitchStmt, label *lblock) {
|
||||||
// We treat TypeSwitchStmt like a sequential if-else
|
// We treat TypeSwitchStmt like a sequential if-else chain.
|
||||||
// chain. More efficient strategies (e.g. multiway
|
// Multiway dispatch can be recovered later by ssautil.Switches().
|
||||||
// dispatch) are possible.
|
|
||||||
|
|
||||||
// Typeswitch lowering:
|
// Typeswitch lowering:
|
||||||
//
|
//
|
||||||
|
|
|
||||||
|
|
@ -47,6 +47,13 @@ func h() (i interface{}, ok bool) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func h2() (i interface{}, ok bool) {
|
||||||
|
ch := make(chan string, 1)
|
||||||
|
ch <- "hi"
|
||||||
|
i, ok = <-ch // string->interface{} conversion within multi-valued expression
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
f1v(g())
|
f1v(g())
|
||||||
f2(g())
|
f2(g())
|
||||||
|
|
@ -61,4 +68,8 @@ func main() {
|
||||||
if !ok || i.(string) != "hi" {
|
if !ok || i.(string) != "hi" {
|
||||||
panic(i)
|
panic(i)
|
||||||
}
|
}
|
||||||
|
i, ok = h2()
|
||||||
|
if !ok || i.(string) != "hi" {
|
||||||
|
panic(i)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue