]> Cypherpunks.ru repositories - gostls13.git/blobdiff - src/cmd/compile/internal/walk/order.go
cmd/compile: move FuncPC intrinsic handling to common helper
[gostls13.git] / src / cmd / compile / internal / walk / order.go
index 0300985a29f854d70f7fff18744d8cab6a15ee75..4d9b2fbee566ef79128cd1c61b4e9ed884b5e6e1 100644 (file)
@@ -44,7 +44,7 @@ type orderState struct {
        edit func(ir.Node) ir.Node // cached closure of o.exprNoLHS
 }
 
-// Order rewrites fn.Nbody to apply the ordering constraints
+// order rewrites fn.Nbody to apply the ordering constraints
 // described in the comment at the top of the file.
 func order(fn *ir.Func) {
        if base.Flag.W > 1 {
@@ -73,7 +73,7 @@ func (o *orderState) newTemp(t *types.Type, clear bool) *ir.Name {
                }
                o.free[key] = a[:len(a)-1]
        } else {
-               v = typecheck.Temp(t)
+               v = typecheck.TempAt(base.Pos, ir.CurFunc, t)
        }
        if clear {
                o.append(ir.NewAssignStmt(base.Pos, v, nil))
@@ -128,7 +128,7 @@ func (o *orderState) cheapExpr(n ir.Node) ir.Node {
                if l == n.X {
                        return n
                }
-               a := ir.SepCopy(n).(*ir.UnaryExpr)
+               a := ir.Copy(n).(*ir.UnaryExpr)
                a.X = l
                return typecheck.Expr(a)
        }
@@ -154,7 +154,7 @@ func (o *orderState) safeExpr(n ir.Node) ir.Node {
                if l == n.X {
                        return n
                }
-               a := ir.SepCopy(n).(*ir.UnaryExpr)
+               a := ir.Copy(n).(*ir.UnaryExpr)
                a.X = l
                return typecheck.Expr(a)
 
@@ -164,7 +164,7 @@ func (o *orderState) safeExpr(n ir.Node) ir.Node {
                if l == n.X {
                        return n
                }
-               a := ir.SepCopy(n).(*ir.SelectorExpr)
+               a := ir.Copy(n).(*ir.SelectorExpr)
                a.X = l
                return typecheck.Expr(a)
 
@@ -174,7 +174,7 @@ func (o *orderState) safeExpr(n ir.Node) ir.Node {
                if l == n.X {
                        return n
                }
-               a := ir.SepCopy(n).(*ir.SelectorExpr)
+               a := ir.Copy(n).(*ir.SelectorExpr)
                a.X = l
                return typecheck.Expr(a)
 
@@ -184,7 +184,7 @@ func (o *orderState) safeExpr(n ir.Node) ir.Node {
                if l == n.X {
                        return n
                }
-               a := ir.SepCopy(n).(*ir.StarExpr)
+               a := ir.Copy(n).(*ir.StarExpr)
                a.X = l
                return typecheck.Expr(a)
 
@@ -200,7 +200,7 @@ func (o *orderState) safeExpr(n ir.Node) ir.Node {
                if l == n.X && r == n.Index {
                        return n
                }
-               a := ir.SepCopy(n).(*ir.IndexExpr)
+               a := ir.Copy(n).(*ir.IndexExpr)
                a.X = l
                a.Index = r
                return typecheck.Expr(a)
@@ -303,7 +303,7 @@ func (o *orderState) mapKeyTemp(outerPos src.XPos, t *types.Type, n ir.Node) ir.
 // For:
 //
 //     x = m[string(k)]
-//     x = m[T1{... Tn{..., string(k), ...}]
+//     x = m[T1{... Tn{..., string(k), ...}}]
 //
 // where k is []byte, T1 to Tn is a nesting of struct and array literals,
 // the allocation of backing bytes for the string can be avoided
@@ -433,9 +433,9 @@ func (o *orderState) edge() {
        // freezes the counter when it reaches the value of 255. However, a range
        // of experiments showed that that decreases overall performance.
        o.append(ir.NewIfStmt(base.Pos,
-               ir.NewBinaryExpr(base.Pos, ir.OEQ, counter, ir.NewInt(0xff)),
-               []ir.Node{ir.NewAssignStmt(base.Pos, counter, ir.NewInt(1))},
-               []ir.Node{ir.NewAssignOpStmt(base.Pos, ir.OADD, counter, ir.NewInt(1))}))
+               ir.NewBinaryExpr(base.Pos, ir.OEQ, counter, ir.NewInt(base.Pos, 0xff)),
+               []ir.Node{ir.NewAssignStmt(base.Pos, counter, ir.NewInt(base.Pos, 1))},
+               []ir.Node{ir.NewAssignOpStmt(base.Pos, ir.OADD, counter, ir.NewInt(base.Pos, 1))}))
 }
 
 // orderBlock orders the block of statements in n into a new slice,
@@ -536,16 +536,16 @@ func (o *orderState) call(nn ir.Node) {
        }
 
        n := nn.(*ir.CallExpr)
-       typecheck.FixVariadicCall(n)
+       typecheck.AssertFixedCall(n)
 
-       if isFuncPCIntrinsic(n) && isIfaceOfFunc(n.Args[0]) {
+       if ir.IsFuncPCIntrinsic(n) && ir.IsIfaceOfFunc(n.Args[0]) != nil {
                // For internal/abi.FuncPCABIxxx(fn), if fn is a defined function,
                // do not introduce temporaries here, so it is easier to rewrite it
                // to symbol address reference later in walk.
                return
        }
 
-       n.X = o.expr(n.X, nil)
+       n.Fun = o.expr(n.Fun, nil)
        o.exprList(n.Args)
 }
 
@@ -597,7 +597,7 @@ func (o *orderState) stmt(n ir.Node) {
        default:
                base.Fatalf("order.stmt %v", n.Op())
 
-       case ir.OVARLIVE, ir.OINLMARK:
+       case ir.OINLMARK:
                o.out = append(o.out, n)
 
        case ir.OAS:
@@ -713,8 +713,6 @@ func (o *orderState) stmt(n ir.Node) {
        case ir.OBREAK,
                ir.OCONTINUE,
                ir.ODCL,
-               ir.ODCLCONST,
-               ir.ODCLTYPE,
                ir.OFALL,
                ir.OGOTO,
                ir.OLABEL,
@@ -740,7 +738,7 @@ func (o *orderState) stmt(n ir.Node) {
                        }
                }
 
-       case ir.OCHECKNIL, ir.OCLOSE, ir.OPANIC, ir.ORECV:
+       case ir.OCHECKNIL, ir.OCLEAR, ir.OCLOSE, ir.OPANIC, ir.ORECV:
                n := n.(*ir.UnaryExpr)
                t := o.markTemp()
                n.X = o.expr(n.X, nil)
@@ -755,7 +753,7 @@ func (o *orderState) stmt(n ir.Node) {
                o.out = append(o.out, n)
                o.popTemp(t)
 
-       case ir.OPRINT, ir.OPRINTN, ir.ORECOVERFP:
+       case ir.OPRINT, ir.OPRINTLN, ir.ORECOVERFP:
                n := n.(*ir.CallExpr)
                t := o.markTemp()
                o.call(n)
@@ -817,8 +815,14 @@ func (o *orderState) stmt(n ir.Node) {
                // Mark []byte(str) range expression to reuse string backing storage.
                // It is safe because the storage cannot be mutated.
                n := n.(*ir.RangeStmt)
-               if n.X.Op() == ir.OSTR2BYTES {
-                       n.X.(*ir.ConvExpr).SetOp(ir.OSTR2BYTESTMP)
+               if x, ok := n.X.(*ir.ConvExpr); ok {
+                       switch x.Op() {
+                       case ir.OSTR2BYTES:
+                               x.SetOp(ir.OSTR2BYTESTMP)
+                               fallthrough
+                       case ir.OSTR2BYTESTMP:
+                               x.MarkNonNil() // "range []byte(nil)" is fine
+                       }
                }
 
                t := o.markTemp()
@@ -826,11 +830,14 @@ func (o *orderState) stmt(n ir.Node) {
 
                orderBody := true
                xt := typecheck.RangeExprType(n.X.Type())
-               switch xt.Kind() {
+               switch k := xt.Kind(); {
                default:
                        base.Fatalf("order.stmt range %v", n.Type())
 
-               case types.TARRAY, types.TSLICE:
+               case types.IsInt[k]:
+                       // Used only once, no need to copy.
+
+               case k == types.TARRAY, k == types.TSLICE:
                        if n.Value == nil || ir.IsBlank(n.Value) {
                                // for i := range x will only use x once, to compute len(x).
                                // No need to copy it.
@@ -838,7 +845,7 @@ func (o *orderState) stmt(n ir.Node) {
                        }
                        fallthrough
 
-               case types.TCHAN, types.TSTRING:
+               case k == types.TCHAN, k == types.TSTRING:
                        // chan, string, slice, array ranges use value multiple times.
                        // make copy.
                        r := n.X
@@ -851,7 +858,7 @@ func (o *orderState) stmt(n ir.Node) {
 
                        n.X = o.copyExpr(r)
 
-               case types.TMAP:
+               case k == types.TMAP:
                        if isMapClear(n) {
                                // Preserve the body of the map clear pattern so it can
                                // be detected during walk. The loop body will not be used
@@ -868,7 +875,7 @@ func (o *orderState) stmt(n ir.Node) {
 
                        // n.Prealloc is the temp for the iterator.
                        // MapIterType contains pointers and needs to be zeroed.
-                       n.Prealloc = o.newTemp(reflectdata.MapIterType(xt), true)
+                       n.Prealloc = o.newTemp(reflectdata.MapIterType(), true)
                }
                n.Key = o.exprInPlace(n.Key)
                n.Value = o.exprInPlace(n.Value)
@@ -1160,7 +1167,7 @@ func (o *orderState) expr1(n, lhs ir.Node) ir.Node {
 
        // concrete type (not interface) argument might need an addressable
        // temporary to pass to the runtime conversion routine.
-       case ir.OCONVIFACE, ir.OCONVIDATA:
+       case ir.OCONVIFACE:
                n := n.(*ir.ConvExpr)
                n.X = o.expr(n.X, nil)
                if n.X.Type().IsInterface() {
@@ -1169,7 +1176,7 @@ func (o *orderState) expr1(n, lhs ir.Node) ir.Node {
                if _, _, needsaddr := dataWordFuncName(n.X.Type()); needsaddr || isStaticCompositeLiteral(n.X) {
                        // Need a temp if we need to pass the address to the conversion function.
                        // We also process static composite literal node here, making a named static global
-                       // whose address we can put directly in an interface (see OCONVIFACE/OCONVIDATA case in walk).
+                       // whose address we can put directly in an interface (see OCONVIFACE case in walk).
                        n.X = o.addrTemp(n.X)
                }
                return n
@@ -1247,6 +1254,8 @@ func (o *orderState) expr1(n, lhs ir.Node) ir.Node {
                ir.OMAKEMAP,
                ir.OMAKESLICE,
                ir.OMAKESLICECOPY,
+               ir.OMAX,
+               ir.OMIN,
                ir.ONEW,
                ir.OREAL,
                ir.ORECOVERFP,
@@ -1493,18 +1502,3 @@ func (o *orderState) as2ok(n *ir.AssignListStmt) {
        o.out = append(o.out, n)
        o.stmt(typecheck.Stmt(as))
 }
-
-// isFuncPCIntrinsic returns whether n is a direct call of internal/abi.FuncPCABIxxx functions.
-func isFuncPCIntrinsic(n *ir.CallExpr) bool {
-       if n.Op() != ir.OCALLFUNC || n.X.Op() != ir.ONAME {
-               return false
-       }
-       fn := n.X.(*ir.Name).Sym()
-       return (fn.Name == "FuncPCABI0" || fn.Name == "FuncPCABIInternal") &&
-               (fn.Pkg.Path == "internal/abi" || fn.Pkg == types.LocalPkg && base.Ctxt.Pkgpath == "internal/abi")
-}
-
-// isIfaceOfFunc returns whether n is an interface conversion from a direct reference of a func.
-func isIfaceOfFunc(n ir.Node) bool {
-       return n.Op() == ir.OCONVIFACE && n.(*ir.ConvExpr).X.Op() == ir.ONAME && n.(*ir.ConvExpr).X.(*ir.Name).Class == ir.PFUNC
-}