diff options
Diffstat (limited to 'src/cmd/compile/internal/noder/helpers.go')
-rw-r--r-- | src/cmd/compile/internal/noder/helpers.go | 129 |
1 files changed, 22 insertions, 107 deletions
diff --git a/src/cmd/compile/internal/noder/helpers.go b/src/cmd/compile/internal/noder/helpers.go index e4a1a54fe8..82428daa4a 100644 --- a/src/cmd/compile/internal/noder/helpers.go +++ b/src/cmd/compile/internal/noder/helpers.go @@ -67,31 +67,6 @@ func Assert(pos src.XPos, x ir.Node, typ *types.Type) ir.Node { return typed(typ, ir.NewTypeAssertExpr(pos, x, nil)) } -// transformAdd transforms an addition operation (currently just addition of -// strings). Equivalent to the "binary operators" case in typecheck.typecheck1. -func transformAdd(n *ir.BinaryExpr) ir.Node { - l := n.X - if l.Type().IsString() { - var add *ir.AddStringExpr - if l.Op() == ir.OADDSTR { - add = l.(*ir.AddStringExpr) - add.SetPos(n.Pos()) - } else { - add = ir.NewAddStringExpr(n.Pos(), []ir.Node{l}) - } - r := n.Y - if r.Op() == ir.OADDSTR { - r := r.(*ir.AddStringExpr) - add.List.Append(r.List.Take()...) - } else { - add.List.Append(r) - } - add.SetType(l.Type()) - return add - } - return n -} - func Binary(pos src.XPos, op ir.Op, typ *types.Type, x, y ir.Node) ir.Node { switch op { case ir.OANDAND, ir.OOROR: @@ -124,7 +99,9 @@ func Call(pos src.XPos, typ *types.Type, fun ir.Node, args []ir.Node, dots bool) // the type. return typed(typ, n) } - return typecheck.Expr(n) + n1 := transformConvCall(n) + n1.SetTypecheck(1) + return n1 } if fun, ok := fun.(*ir.Name); ok && fun.BuiltinOp != 0 { @@ -181,6 +158,11 @@ func Call(pos src.XPos, typ *types.Type, fun ir.Node, args []ir.Node, dots bool) } } + n.Use = ir.CallUseExpr + if fun.Type().NumResults() == 0 { + n.Use = ir.CallUseStmt + } + if fun.Op() == ir.OXDOT { if !fun.(*ir.SelectorExpr).X.Type().HasTParam() { base.FatalfAt(pos, "Expecting type param receiver in %v", fun) @@ -192,63 +174,18 @@ func Call(pos src.XPos, typ *types.Type, fun ir.Node, args []ir.Node, dots bool) return n } if fun.Op() != ir.OFUNCINST { - // If no type params, do normal typechecking, since we're - // still missing some things done by tcCall (mainly - // typecheckaste/assignconvfn - implementing assignability of args - // to params). This will convert OCALL to OCALLFUNC. - typecheck.Call(n) + // If no type params, do the normal call transformations. This + // will convert OCALL to OCALLFUNC. + transformCall(n) + typed(typ, n) return n } // Leave the op as OCALL, which indicates the call still needs typechecking. - n.Use = ir.CallUseExpr - if fun.Type().NumResults() == 0 { - n.Use = ir.CallUseStmt - } typed(typ, n) return n } -// transformCompare transforms a compare operation (currently just equals/not -// equals). Equivalent to the "comparison operators" case in -// typecheck.typecheck1, including tcArith. -func transformCompare(n *ir.BinaryExpr) { - if (n.Op() == ir.OEQ || n.Op() == ir.ONE) && !types.Identical(n.X.Type(), n.Y.Type()) { - // Comparison is okay as long as one side is assignable to the - // other. The only allowed case where the conversion is not CONVNOP is - // "concrete == interface". In that case, check comparability of - // the concrete type. The conversion allocates, so only do it if - // the concrete type is huge. - l, r := n.X, n.Y - lt, rt := l.Type(), r.Type() - converted := false - if rt.Kind() != types.TBLANK { - aop, _ := typecheck.Assignop(lt, rt) - if aop != ir.OXXX { - types.CalcSize(lt) - if rt.IsInterface() == lt.IsInterface() || lt.Width >= 1<<16 { - l = ir.NewConvExpr(base.Pos, aop, rt, l) - l.SetTypecheck(1) - } - - converted = true - } - } - - if !converted && lt.Kind() != types.TBLANK { - aop, _ := typecheck.Assignop(rt, lt) - if aop != ir.OXXX { - types.CalcSize(rt) - if rt.IsInterface() == lt.IsInterface() || rt.Width >= 1<<16 { - r = ir.NewConvExpr(base.Pos, aop, lt, r) - r.SetTypecheck(1) - } - } - } - n.X, n.Y = l, r - } -} - func Compare(pos src.XPos, typ *types.Type, op ir.Op, x, y ir.Node) ir.Node { n := ir.NewBinaryExpr(pos, op, x, y) if x.Type().HasTParam() || y.Type().HasTParam() { @@ -330,38 +267,16 @@ func method(typ *types.Type, index int) *types.Field { 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) + if x.Type().HasTParam() { + // transformIndex needs to know exact type + n.SetType(typ) + n.SetTypecheck(3) return n } - return typecheck.Expr(n) -} - -// transformSlice transforms a slice operation. Equivalent to typecheck.tcSlice. -func transformSlice(n *ir.SliceExpr) { - l := n.X - if l.Type().IsArray() { - addr := typecheck.NodAddr(n.X) - addr.SetImplicit(true) - typed(types.NewPtr(n.X.Type()), addr) - n.X = addr - l = addr - } - t := l.Type() - if t.IsString() { - n.SetOp(ir.OSLICESTR) - } else if t.IsPtr() && t.Elem().IsArray() { - if n.Op().IsSlice3() { - n.SetOp(ir.OSLICE3ARR) - } else { - n.SetOp(ir.OSLICEARR) - } - } + typed(typ, n) + // transformIndex will modify n.Type() for OINDEXMAP. + transformIndex(n) + return n } func Slice(pos src.XPos, typ *types.Type, x, low, high, max ir.Node) ir.Node { @@ -399,7 +314,7 @@ func Unary(pos src.XPos, op ir.Op, x ir.Node) ir.Node { var one = constant.MakeInt64(1) -func IncDec(pos src.XPos, op ir.Op, x ir.Node) ir.Node { - x = typecheck.AssignExpr(x) +func IncDec(pos src.XPos, op ir.Op, x ir.Node) *ir.AssignOpStmt { + assert(x.Type() != nil) return ir.NewAssignOpStmt(pos, op, x, typecheck.DefaultLit(ir.NewBasicLit(pos, one), x.Type())) } |