diff options
Diffstat (limited to 'src/cmd/compile/internal/noder')
| -rw-r--r-- | src/cmd/compile/internal/noder/expr.go | 2 | ||||
| -rw-r--r-- | src/cmd/compile/internal/noder/helpers.go | 56 | ||||
| -rw-r--r-- | src/cmd/compile/internal/noder/stencil.go | 23 | ||||
| -rw-r--r-- | src/cmd/compile/internal/noder/stmt.go | 29 |
4 files changed, 86 insertions, 24 deletions
diff --git a/src/cmd/compile/internal/noder/expr.go b/src/cmd/compile/internal/noder/expr.go index 989ebf236e..1ca5552879 100644 --- a/src/cmd/compile/internal/noder/expr.go +++ b/src/cmd/compile/internal/noder/expr.go @@ -135,7 +135,7 @@ func (g *irgen) expr0(typ types2.Type, expr syntax.Expr) ir.Node { index := g.expr(expr.Index) if index.Op() != ir.OTYPE { // This is just a normal index expression - return Index(pos, g.expr(expr.X), index) + return Index(pos, g.typ(typ), g.expr(expr.X), index) } // This is generic function instantiation with a single type targs = []ir.Node{index} diff --git a/src/cmd/compile/internal/noder/helpers.go b/src/cmd/compile/internal/noder/helpers.go index cf7a3e22b3..1210d4b58c 100644 --- a/src/cmd/compile/internal/noder/helpers.go +++ b/src/cmd/compile/internal/noder/helpers.go @@ -83,11 +83,12 @@ func Binary(pos src.XPos, op ir.Op, x, y ir.Node) ir.Node { } func Call(pos src.XPos, typ *types.Type, fun ir.Node, args []ir.Node, dots bool) ir.Node { - // TODO(mdempsky): This should not be so difficult. + n := ir.NewCallExpr(pos, ir.OCALL, fun, args) + n.IsDDD = dots + if fun.Op() == ir.OTYPE { // Actually a type conversion, not a function call. - n := ir.NewCallExpr(pos, ir.OCALL, fun, args) - if fun.Type().Kind() == types.TTYPEPARAM { + if fun.Type().HasTParam() || args[0].Type().HasTParam() { // For type params, don't typecheck until we actually know // the type. return typed(typ, n) @@ -96,9 +97,34 @@ func Call(pos src.XPos, typ *types.Type, fun ir.Node, args []ir.Node, dots bool) } if fun, ok := fun.(*ir.Name); ok && fun.BuiltinOp != 0 { - // Call to a builtin function. - n := ir.NewCallExpr(pos, ir.OCALL, fun, args) - n.IsDDD = dots + // For Builtin ops, we currently stay with using the old + // typechecker to transform the call to a more specific expression + // and possibly use more specific ops. However, for a bunch of the + // ops, we delay doing the old typechecker if any of the args have + // type params, for a variety of reasons: + // + // OMAKE: hard to choose specific ops OMAKESLICE, etc. until arg type is known + // OREAL/OIMAG: can't determine type float32/float64 until arg type know + // OLEN/OCAP: old typechecker will complain if arg is not obviously a slice/array. + // OAPPEND: old typechecker will complain if arg is not obviously slice, etc. + // + // We will eventually break out the transforming functionality + // needed for builtin's, and call it here or during stenciling, as + // appropriate. + switch fun.BuiltinOp { + case ir.OMAKE, ir.OREAL, ir.OIMAG, ir.OLEN, ir.OCAP, ir.OAPPEND: + hasTParam := false + for _, arg := range args { + if arg.Type().HasTParam() { + hasTParam = true + break + } + } + if hasTParam { + return typed(typ, n) + } + } + switch fun.BuiltinOp { case ir.OCLOSE, ir.ODELETE, ir.OPANIC, ir.OPRINT, ir.OPRINTN: return typecheck.Stmt(n) @@ -124,9 +150,6 @@ func Call(pos src.XPos, typ *types.Type, fun ir.Node, args []ir.Node, dots bool) } } - n := ir.NewCallExpr(pos, ir.OCALL, fun, args) - n.IsDDD = dots - if fun.Op() == ir.OXDOT { if !fun.(*ir.SelectorExpr).X.Type().HasTParam() { base.FatalfAt(pos, "Expecting type param receiver in %v", fun) @@ -230,9 +253,18 @@ func method(typ *types.Type, index int) *types.Field { return types.ReceiverBaseType(typ).Methods().Index(index) } -func Index(pos src.XPos, x, index ir.Node) ir.Node { - // TODO(mdempsky): Avoid typecheck.Expr (which will call tcIndex) - return typecheck.Expr(ir.NewIndexExpr(pos, x, index)) +func Index(pos src.XPos, typ *types.Type, x, index ir.Node) ir.Node { + n := ir.NewIndexExpr(pos, x, index) + // TODO(danscales): Temporary fix. Need to separate out the + // transformations done by the old typechecker (in tcIndex()), to be + // called here or after stenciling. + if x.Type().HasTParam() && x.Type().Kind() != types.TMAP && + x.Type().Kind() != types.TSLICE && x.Type().Kind() != types.TARRAY { + // Old typechecker will complain if arg is not obviously a slice/array/map. + typed(typ, n) + return n + } + return typecheck.Expr(n) } func Slice(pos src.XPos, x, low, high, max ir.Node) ir.Node { diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index 64b3a942e2..55aee9b6ff 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -330,8 +330,13 @@ func (subst *subster) node(n ir.Node) ir.Node { m.SetIsClosureVar(true) } t := x.Type() - newt := subst.typ(t) - m.SetType(newt) + if t == nil { + assert(name.BuiltinOp != 0) + } else { + newt := subst.typ(t) + m.SetType(newt) + } + m.BuiltinOp = name.BuiltinOp m.Curfn = subst.newf m.Class = name.Class m.Func = name.Func @@ -396,11 +401,23 @@ func (subst *subster) node(n ir.Node) ir.Node { // that the OXDOT was resolved. call.SetTypecheck(0) typecheck.Call(call) + } else if name := call.X.Name(); name != nil { + switch name.BuiltinOp { + case ir.OMAKE, ir.OREAL, ir.OIMAG, ir.OLEN, ir.OCAP, ir.OAPPEND: + // Call old typechecker (to do any + // transformations) now that we know the + // type of the args. + m.SetTypecheck(0) + m = typecheck.Expr(m) + default: + base.FatalfAt(call.Pos(), "Unexpected builtin op") + } + } else if call.X.Op() != ir.OFUNCINST { // A call with an OFUNCINST will get typechecked // in stencil() once we have created & attached the // instantiation to be called. - base.FatalfAt(call.Pos(), "Expecting OCALLPART or OTYPE or OFUNCINST with CALL") + base.FatalfAt(call.Pos(), "Expecting OCALLPART or OTYPE or OFUNCINST or builtin with CALL") } } diff --git a/src/cmd/compile/internal/noder/stmt.go b/src/cmd/compile/internal/noder/stmt.go index 1775116f41..31c6bfe5c8 100644 --- a/src/cmd/compile/internal/noder/stmt.go +++ b/src/cmd/compile/internal/noder/stmt.go @@ -28,7 +28,11 @@ func (g *irgen) stmts(stmts []syntax.Stmt) []ir.Node { func (g *irgen) stmt(stmt syntax.Stmt) ir.Node { // TODO(mdempsky): Remove dependency on typecheck. - return typecheck.Stmt(g.stmt0(stmt)) + n := g.stmt0(stmt) + if n != nil { + n.SetTypecheck(1) + } + return n } func (g *irgen) stmt0(stmt syntax.Stmt) ir.Node { @@ -46,17 +50,20 @@ func (g *irgen) stmt0(stmt syntax.Stmt) ir.Node { } return x case *syntax.SendStmt: - return ir.NewSendStmt(g.pos(stmt), g.expr(stmt.Chan), g.expr(stmt.Value)) + n := ir.NewSendStmt(g.pos(stmt), g.expr(stmt.Chan), g.expr(stmt.Value)) + // Need to do the AssignConv() in tcSend(). + return typecheck.Stmt(n) case *syntax.DeclStmt: return ir.NewBlockStmt(g.pos(stmt), g.decls(stmt.DeclList)) case *syntax.AssignStmt: if stmt.Op != 0 && stmt.Op != syntax.Def { op := g.op(stmt.Op, binOps[:]) + // May need to insert ConvExpr nodes on the args in tcArith if stmt.Rhs == nil { - return IncDec(g.pos(stmt), op, g.expr(stmt.Lhs)) + return typecheck.Stmt(IncDec(g.pos(stmt), op, g.expr(stmt.Lhs))) } - return ir.NewAssignOpStmt(g.pos(stmt), op, g.expr(stmt.Lhs), g.expr(stmt.Rhs)) + return typecheck.Stmt(ir.NewAssignOpStmt(g.pos(stmt), op, g.expr(stmt.Lhs), g.expr(stmt.Rhs))) } names, lhs := g.assignList(stmt.Lhs, stmt.Op == syntax.Def) @@ -65,25 +72,31 @@ func (g *irgen) stmt0(stmt syntax.Stmt) ir.Node { if len(lhs) == 1 && len(rhs) == 1 { n := ir.NewAssignStmt(g.pos(stmt), lhs[0], rhs[0]) n.Def = initDefn(n, names) - return n + // Need to set Assigned in checkassign for maps + return typecheck.Stmt(n) } n := ir.NewAssignListStmt(g.pos(stmt), ir.OAS2, lhs, rhs) n.Def = initDefn(n, names) - return n + // Need to do tcAssignList(). + return typecheck.Stmt(n) case *syntax.BranchStmt: return ir.NewBranchStmt(g.pos(stmt), g.tokOp(int(stmt.Tok), branchOps[:]), g.name(stmt.Label)) case *syntax.CallStmt: return ir.NewGoDeferStmt(g.pos(stmt), g.tokOp(int(stmt.Tok), callOps[:]), g.expr(stmt.Call)) case *syntax.ReturnStmt: - return ir.NewReturnStmt(g.pos(stmt), g.exprList(stmt.Results)) + n := ir.NewReturnStmt(g.pos(stmt), g.exprList(stmt.Results)) + // Need to do typecheckaste() for multiple return values + return typecheck.Stmt(n) case *syntax.IfStmt: return g.ifStmt(stmt) case *syntax.ForStmt: return g.forStmt(stmt) case *syntax.SelectStmt: - return g.selectStmt(stmt) + n := g.selectStmt(stmt) + // Need to convert assignments to OSELRECV2 in tcSelect() + return typecheck.Stmt(n) case *syntax.SwitchStmt: return g.switchStmt(stmt) |
