From bdb480fd623e58d0d1d0689a3755367379ea57bc Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Tue, 8 Sep 2020 15:28:43 +0700 Subject: cmd/compile: fix mishandling of unsafe-uintptr arguments in go/defer Currently, the statement: go g(uintptr(f())) gets rewritten into: tmp := f() newproc(8, g, uintptr(tmp)) runtime.KeepAlive(tmp) which doesn't guarantee that tmp is still alive by time the g call is scheduled to run. This CL fixes the issue, by wrapping g call in a closure: go func(p unsafe.Pointer) { g(uintptr(p)) }(f()) then this will be rewritten into: tmp := f() go func(p unsafe.Pointer) { g(uintptr(p)) runtime.KeepAlive(p) }(tmp) runtime.KeepAlive(tmp) // superfluous, but harmless So the unsafe.Pointer p will be kept alive at the time g call runs. Updates #24491 Change-Id: Ic10821251cbb1b0073daec92b82a866c6ebaf567 Reviewed-on: https://go-review.googlesource.com/c/go/+/253457 Run-TryBot: Cuong Manh Le Reviewed-by: Matthew Dempsky TryBot-Result: Gobot Gobot --- src/cmd/compile/internal/gc/order.go | 1 + src/cmd/compile/internal/gc/syntax.go | 41 +++++++++++++++++--------- src/cmd/compile/internal/gc/walk.go | 54 ++++++++++++++++++++++++++++------- 3 files changed, 72 insertions(+), 24 deletions(-) (limited to 'src/cmd/compile/internal') diff --git a/src/cmd/compile/internal/gc/order.go b/src/cmd/compile/internal/gc/order.go index aa91160e5c..412f073a8d 100644 --- a/src/cmd/compile/internal/gc/order.go +++ b/src/cmd/compile/internal/gc/order.go @@ -502,6 +502,7 @@ func (o *Order) call(n *Node) { x := o.copyExpr(arg.Left, arg.Left.Type, false) x.Name.SetKeepalive(true) arg.Left = x + n.SetNeedsWrapper(true) } } diff --git a/src/cmd/compile/internal/gc/syntax.go b/src/cmd/compile/internal/gc/syntax.go index 47e5e59156..5580f789c5 100644 --- a/src/cmd/compile/internal/gc/syntax.go +++ b/src/cmd/compile/internal/gc/syntax.go @@ -141,19 +141,20 @@ const ( nodeInitorder, _ // tracks state during init1; two bits _, _ // second nodeInitorder bit _, nodeHasBreak - _, nodeNoInline // used internally by inliner to indicate that a function call should not be inlined; set for OCALLFUNC and OCALLMETH only - _, nodeImplicit // implicit OADDR or ODEREF; ++/-- statement represented as OASOP; or ANDNOT lowered to OAND - _, nodeIsDDD // is the argument variadic - _, nodeDiag // already printed error about this - _, nodeColas // OAS resulting from := - _, nodeNonNil // guaranteed to be non-nil - _, nodeTransient // storage can be reused immediately after this statement - _, nodeBounded // bounds check unnecessary - _, nodeHasCall // expression contains a function call - _, nodeLikely // if statement condition likely - _, nodeHasVal // node.E contains a Val - _, nodeHasOpt // node.E contains an Opt - _, nodeEmbedded // ODCLFIELD embedded type + _, nodeNoInline // used internally by inliner to indicate that a function call should not be inlined; set for OCALLFUNC and OCALLMETH only + _, nodeImplicit // implicit OADDR or ODEREF; ++/-- statement represented as OASOP; or ANDNOT lowered to OAND + _, nodeIsDDD // is the argument variadic + _, nodeDiag // already printed error about this + _, nodeColas // OAS resulting from := + _, nodeNonNil // guaranteed to be non-nil + _, nodeTransient // storage can be reused immediately after this statement + _, nodeBounded // bounds check unnecessary + _, nodeHasCall // expression contains a function call + _, nodeLikely // if statement condition likely + _, nodeHasVal // node.E contains a Val + _, nodeHasOpt // node.E contains an Opt + _, nodeEmbedded // ODCLFIELD embedded type + _, nodeNeedsWrapper // OCALLxxx node that needs to be wrapped ) func (n *Node) Class() Class { return Class(n.flags.get3(nodeClass)) } @@ -286,6 +287,20 @@ func (n *Node) SetIota(x int64) { n.Xoffset = x } +func (n *Node) NeedsWrapper() bool { + return n.flags&nodeNeedsWrapper != 0 +} + +// SetNeedsWrapper indicates that OCALLxxx node needs to be wrapped by a closure. +func (n *Node) SetNeedsWrapper(b bool) { + switch n.Op { + case OCALLFUNC, OCALLMETH, OCALLINTER: + default: + Fatalf("Node.SetNeedsWrapper %v", n.Op) + } + n.flags.set(nodeNeedsWrapper, b) +} + // mayBeShared reports whether n may occur in multiple places in the AST. // Extra care must be taken when mutating such a node. func (n *Node) mayBeShared() bool { diff --git a/src/cmd/compile/internal/gc/walk.go b/src/cmd/compile/internal/gc/walk.go index 0158af8700..ab7f857031 100644 --- a/src/cmd/compile/internal/gc/walk.go +++ b/src/cmd/compile/internal/gc/walk.go @@ -232,7 +232,11 @@ func walkstmt(n *Node) *Node { n.Left = copyany(n.Left, &n.Ninit, true) default: - n.Left = walkexpr(n.Left, &n.Ninit) + if n.Left.NeedsWrapper() { + n.Left = wrapCall(n.Left, &n.Ninit) + } else { + n.Left = walkexpr(n.Left, &n.Ninit) + } } case OFOR, OFORUNTIL: @@ -3857,6 +3861,14 @@ func candiscard(n *Node) bool { // builtin(a1, a2, a3) // }(x, y, z) // for print, println, and delete. +// +// Rewrite +// go f(x, y, uintptr(unsafe.Pointer(z))) +// into +// go func(a1, a2, a3) { +// builtin(a1, a2, uintptr(a3)) +// }(x, y, unsafe.Pointer(z)) +// for function contains unsafe-uintptr arguments. var wrapCall_prgen int @@ -3868,9 +3880,17 @@ func wrapCall(n *Node, init *Nodes) *Node { init.AppendNodes(&n.Ninit) } + isBuiltinCall := n.Op != OCALLFUNC && n.Op != OCALLMETH && n.Op != OCALLINTER + // origArgs keeps track of what argument is uintptr-unsafe/unsafe-uintptr conversion. + origArgs := make([]*Node, n.List.Len()) t := nod(OTFUNC, nil, nil) for i, arg := range n.List.Slice() { s := lookupN("a", i) + if !isBuiltinCall && arg.Op == OCONVNOP && arg.Type.Etype == TUINTPTR && arg.Left.Type.Etype == TUNSAFEPTR { + origArgs[i] = arg + arg = arg.Left + n.List.SetIndex(i, arg) + } t.List.Append(symfield(s, arg.Type)) } @@ -3878,10 +3898,22 @@ func wrapCall(n *Node, init *Nodes) *Node { sym := lookupN("wrap·", wrapCall_prgen) fn := dclfunc(sym, t) - a := nod(n.Op, nil, nil) - a.List.Set(paramNnames(t.Type)) - a = typecheck(a, ctxStmt) - fn.Nbody.Set1(a) + args := paramNnames(t.Type) + for i, origArg := range origArgs { + if origArg == nil { + continue + } + arg := nod(origArg.Op, args[i], nil) + arg.Type = origArg.Type + args[i] = arg + } + call := nod(n.Op, nil, nil) + if !isBuiltinCall { + call.Op = OCALL + call.Left = n.Left + } + call.List.Set(args) + fn.Nbody.Set1(call) funcbody() @@ -3889,12 +3921,12 @@ func wrapCall(n *Node, init *Nodes) *Node { typecheckslice(fn.Nbody.Slice(), ctxStmt) xtop = append(xtop, fn) - a = nod(OCALL, nil, nil) - a.Left = fn.Func.Nname - a.List.Set(n.List.Slice()) - a = typecheck(a, ctxStmt) - a = walkexpr(a, init) - return a + call = nod(OCALL, nil, nil) + call.Left = fn.Func.Nname + call.List.Set(n.List.Slice()) + call = typecheck(call, ctxStmt) + call = walkexpr(call, init) + return call } // substArgTypes substitutes the given list of types for -- cgit v1.3 From 9cf88333e8255155be4e136c572883bb5ad546bd Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Wed, 9 Sep 2020 12:06:18 +0700 Subject: cmd/compile: consistently use Type.IsUnsafePtr() Passes toolstash-check. Change-Id: Iaeae7cc20e26af733642c7c8c7ca0a059e5b07b2 Reviewed-on: https://go-review.googlesource.com/c/go/+/253657 Run-TryBot: Cuong Manh Le TryBot-Result: Gobot Gobot Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/gc/escape.go | 6 +++--- src/cmd/compile/internal/gc/ssa.go | 2 +- src/cmd/compile/internal/gc/subr.go | 4 ++-- src/cmd/compile/internal/gc/walk.go | 10 +++++----- 4 files changed, 11 insertions(+), 11 deletions(-) (limited to 'src/cmd/compile/internal') diff --git a/src/cmd/compile/internal/gc/escape.go b/src/cmd/compile/internal/gc/escape.go index d5cca4a38b..dc469e276c 100644 --- a/src/cmd/compile/internal/gc/escape.go +++ b/src/cmd/compile/internal/gc/escape.go @@ -485,7 +485,7 @@ func (e *Escape) exprSkipInit(k EscHole, n *Node) { e.discard(max) case OCONV, OCONVNOP: - if checkPtr(e.curfn, 2) && n.Type.Etype == TUNSAFEPTR && n.Left.Type.IsPtr() { + if checkPtr(e.curfn, 2) && n.Type.IsUnsafePtr() && n.Left.Type.IsPtr() { // When -d=checkptr=2 is enabled, treat // conversions to unsafe.Pointer as an // escaping operation. This allows better @@ -493,7 +493,7 @@ func (e *Escape) exprSkipInit(k EscHole, n *Node) { // easily detect object boundaries on the heap // than the stack. e.assignHeap(n.Left, "conversion to unsafe.Pointer", n) - } else if n.Type.Etype == TUNSAFEPTR && n.Left.Type.Etype == TUINTPTR { + } else if n.Type.IsUnsafePtr() && n.Left.Type.Etype == TUINTPTR { e.unsafeValue(k, n.Left) } else { e.expr(k, n.Left) @@ -625,7 +625,7 @@ func (e *Escape) unsafeValue(k EscHole, n *Node) { switch n.Op { case OCONV, OCONVNOP: - if n.Left.Type.Etype == TUNSAFEPTR { + if n.Left.Type.IsUnsafePtr() { e.expr(k, n.Left) } else { e.discard(n.Left) diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go index 52083d999e..89644cd3f2 100644 --- a/src/cmd/compile/internal/gc/ssa.go +++ b/src/cmd/compile/internal/gc/ssa.go @@ -2113,7 +2113,7 @@ func (s *state) expr(n *Node) *ssa.Value { } // unsafe.Pointer <--> *T - if to.Etype == TUNSAFEPTR && from.IsPtrShaped() || from.Etype == TUNSAFEPTR && to.IsPtrShaped() { + if to.IsUnsafePtr() && from.IsPtrShaped() || from.IsUnsafePtr() && to.IsPtrShaped() { return v } diff --git a/src/cmd/compile/internal/gc/subr.go b/src/cmd/compile/internal/gc/subr.go index 8fa3fca50f..6d0a40c287 100644 --- a/src/cmd/compile/internal/gc/subr.go +++ b/src/cmd/compile/internal/gc/subr.go @@ -781,12 +781,12 @@ func convertop(srcConstant bool, src, dst *types.Type, why *string) Op { } // 8. src is a pointer or uintptr and dst is unsafe.Pointer. - if (src.IsPtr() || src.Etype == TUINTPTR) && dst.Etype == TUNSAFEPTR { + if (src.IsPtr() || src.Etype == TUINTPTR) && dst.IsUnsafePtr() { return OCONVNOP } // 9. src is unsafe.Pointer and dst is a pointer or uintptr. - if src.Etype == TUNSAFEPTR && (dst.IsPtr() || dst.Etype == TUINTPTR) { + if src.IsUnsafePtr() && (dst.IsPtr() || dst.Etype == TUINTPTR) { return OCONVNOP } diff --git a/src/cmd/compile/internal/gc/walk.go b/src/cmd/compile/internal/gc/walk.go index ab7f857031..a9fefb3ddd 100644 --- a/src/cmd/compile/internal/gc/walk.go +++ b/src/cmd/compile/internal/gc/walk.go @@ -958,11 +958,11 @@ opswitch: case OCONV, OCONVNOP: n.Left = walkexpr(n.Left, init) if n.Op == OCONVNOP && checkPtr(Curfn, 1) { - if n.Type.IsPtr() && n.Left.Type.Etype == TUNSAFEPTR { // unsafe.Pointer to *T + if n.Type.IsPtr() && n.Left.Type.IsUnsafePtr() { // unsafe.Pointer to *T n = walkCheckPtrAlignment(n, init, nil) break } - if n.Type.Etype == TUNSAFEPTR && n.Left.Type.Etype == TUINTPTR { // uintptr to unsafe.Pointer + if n.Type.IsUnsafePtr() && n.Left.Type.Etype == TUINTPTR { // uintptr to unsafe.Pointer n = walkCheckPtrArithmetic(n, init) break } @@ -1127,7 +1127,7 @@ opswitch: n.List.SetSecond(walkexpr(n.List.Second(), init)) case OSLICE, OSLICEARR, OSLICESTR, OSLICE3, OSLICE3ARR: - checkSlice := checkPtr(Curfn, 1) && n.Op == OSLICE3ARR && n.Left.Op == OCONVNOP && n.Left.Left.Type.Etype == TUNSAFEPTR + checkSlice := checkPtr(Curfn, 1) && n.Op == OSLICE3ARR && n.Left.Op == OCONVNOP && n.Left.Left.Type.IsUnsafePtr() if checkSlice { n.Left.Left = walkexpr(n.Left.Left, init) } else { @@ -3886,7 +3886,7 @@ func wrapCall(n *Node, init *Nodes) *Node { t := nod(OTFUNC, nil, nil) for i, arg := range n.List.Slice() { s := lookupN("a", i) - if !isBuiltinCall && arg.Op == OCONVNOP && arg.Type.Etype == TUINTPTR && arg.Left.Type.Etype == TUNSAFEPTR { + if !isBuiltinCall && arg.Op == OCONVNOP && arg.Type.Etype == TUINTPTR && arg.Left.Type.IsUnsafePtr() { origArgs[i] = arg arg = arg.Left n.List.SetIndex(i, arg) @@ -4041,7 +4041,7 @@ func walkCheckPtrArithmetic(n *Node, init *Nodes) *Node { walk(n.Left) } case OCONVNOP: - if n.Left.Type.Etype == TUNSAFEPTR { + if n.Left.Type.IsUnsafePtr() { n.Left = cheapexpr(n.Left, init) originals = append(originals, convnop(n.Left, types.Types[TUNSAFEPTR])) } -- cgit v1.3 From 518369601ca2499cea68af86451f17d2856895f8 Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Wed, 9 Sep 2020 12:09:26 +0700 Subject: cmd/compile: add Type.IsUintptr() to detect type is an uintptr Passes toolstash-check. Change-Id: I7051d45eafbfd4dea73a3d4b5ea6cff39d76cbc1 Reviewed-on: https://go-review.googlesource.com/c/go/+/253658 Run-TryBot: Cuong Manh Le TryBot-Result: Gobot Gobot Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/gc/esc.go | 6 +++--- src/cmd/compile/internal/gc/escape.go | 2 +- src/cmd/compile/internal/gc/subr.go | 4 ++-- src/cmd/compile/internal/gc/walk.go | 4 ++-- src/cmd/compile/internal/types/type.go | 5 +++++ 5 files changed, 13 insertions(+), 8 deletions(-) (limited to 'src/cmd/compile/internal') diff --git a/src/cmd/compile/internal/gc/esc.go b/src/cmd/compile/internal/gc/esc.go index 4b843aba35..375331d1f5 100644 --- a/src/cmd/compile/internal/gc/esc.go +++ b/src/cmd/compile/internal/gc/esc.go @@ -377,7 +377,7 @@ func (e *Escape) paramTag(fn *Node, narg int, f *types.Field) string { // This really doesn't have much to do with escape analysis per se, // but we are reusing the ability to annotate an individual function // argument and pass those annotations along to importing code. - if f.Type.Etype == TUINTPTR { + if f.Type.IsUintptr() { if Debug['m'] != 0 { Warnl(f.Pos, "assuming %v is unsafe uintptr", name()) } @@ -407,13 +407,13 @@ func (e *Escape) paramTag(fn *Node, narg int, f *types.Field) string { } if fn.Func.Pragma&UintptrEscapes != 0 { - if f.Type.Etype == TUINTPTR { + if f.Type.IsUintptr() { if Debug['m'] != 0 { Warnl(f.Pos, "marking %v as escaping uintptr", name()) } return uintptrEscapesTag } - if f.IsDDD() && f.Type.Elem().Etype == TUINTPTR { + if f.IsDDD() && f.Type.Elem().IsUintptr() { // final argument is ...uintptr. if Debug['m'] != 0 { Warnl(f.Pos, "marking %v as escaping ...uintptr", name()) diff --git a/src/cmd/compile/internal/gc/escape.go b/src/cmd/compile/internal/gc/escape.go index dc469e276c..75da439bb7 100644 --- a/src/cmd/compile/internal/gc/escape.go +++ b/src/cmd/compile/internal/gc/escape.go @@ -493,7 +493,7 @@ func (e *Escape) exprSkipInit(k EscHole, n *Node) { // easily detect object boundaries on the heap // than the stack. e.assignHeap(n.Left, "conversion to unsafe.Pointer", n) - } else if n.Type.IsUnsafePtr() && n.Left.Type.Etype == TUINTPTR { + } else if n.Type.IsUnsafePtr() && n.Left.Type.IsUintptr() { e.unsafeValue(k, n.Left) } else { e.expr(k, n.Left) diff --git a/src/cmd/compile/internal/gc/subr.go b/src/cmd/compile/internal/gc/subr.go index 6d0a40c287..d3ba53ff0c 100644 --- a/src/cmd/compile/internal/gc/subr.go +++ b/src/cmd/compile/internal/gc/subr.go @@ -781,12 +781,12 @@ func convertop(srcConstant bool, src, dst *types.Type, why *string) Op { } // 8. src is a pointer or uintptr and dst is unsafe.Pointer. - if (src.IsPtr() || src.Etype == TUINTPTR) && dst.IsUnsafePtr() { + if (src.IsPtr() || src.IsUintptr()) && dst.IsUnsafePtr() { return OCONVNOP } // 9. src is unsafe.Pointer and dst is a pointer or uintptr. - if src.IsUnsafePtr() && (dst.IsPtr() || dst.Etype == TUINTPTR) { + if src.IsUnsafePtr() && (dst.IsPtr() || dst.IsUintptr()) { return OCONVNOP } diff --git a/src/cmd/compile/internal/gc/walk.go b/src/cmd/compile/internal/gc/walk.go index a9fefb3ddd..361de7e0f3 100644 --- a/src/cmd/compile/internal/gc/walk.go +++ b/src/cmd/compile/internal/gc/walk.go @@ -962,7 +962,7 @@ opswitch: n = walkCheckPtrAlignment(n, init, nil) break } - if n.Type.IsUnsafePtr() && n.Left.Type.Etype == TUINTPTR { // uintptr to unsafe.Pointer + if n.Type.IsUnsafePtr() && n.Left.Type.IsUintptr() { // uintptr to unsafe.Pointer n = walkCheckPtrArithmetic(n, init) break } @@ -3886,7 +3886,7 @@ func wrapCall(n *Node, init *Nodes) *Node { t := nod(OTFUNC, nil, nil) for i, arg := range n.List.Slice() { s := lookupN("a", i) - if !isBuiltinCall && arg.Op == OCONVNOP && arg.Type.Etype == TUINTPTR && arg.Left.Type.IsUnsafePtr() { + if !isBuiltinCall && arg.Op == OCONVNOP && arg.Type.IsUintptr() && arg.Left.Type.IsUnsafePtr() { origArgs[i] = arg arg = arg.Left n.List.SetIndex(i, arg) diff --git a/src/cmd/compile/internal/types/type.go b/src/cmd/compile/internal/types/type.go index e4b3d885d9..a777a5fd90 100644 --- a/src/cmd/compile/internal/types/type.go +++ b/src/cmd/compile/internal/types/type.go @@ -1230,6 +1230,11 @@ func (t *Type) IsUnsafePtr() bool { return t.Etype == TUNSAFEPTR } +// IsUintptr reports whether t is an uintptr. +func (t *Type) IsUintptr() bool { + return t.Etype == TUINTPTR +} + // IsPtrShaped reports whether t is represented by a single machine pointer. // In addition to regular Go pointer types, this includes map, channel, and // function types and unsafe.Pointer. It does not include array or struct types -- cgit v1.3 From 2c95e3a6a8377ca9c72608c25b4cf2506baf782f Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Wed, 9 Sep 2020 11:09:01 +0700 Subject: cmd/compile: use clearer error message for stuct literal This CL changes "T literal.M" error message to "T{...}.M". It's clearer expression and focusing user on actual issue. Updates #38745 Change-Id: I84b455a86742f37e0bde5bf390aa02984eecc3c9 Reviewed-on: https://go-review.googlesource.com/c/go/+/253677 Run-TryBot: Cuong Manh Le TryBot-Result: Gobot Gobot Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/gc/fmt.go | 11 ++- test/alias2.go | 10 +-- test/ddd1.go | 2 +- test/escape2.go | 56 ++++++------- test/escape2n.go | 56 ++++++------- test/escape_calls.go | 2 +- test/escape_field.go | 6 +- test/escape_iface.go | 50 ++++++------ test/escape_indir.go | 34 ++++---- test/escape_map.go | 26 +++--- test/escape_param.go | 60 +++++++------- test/escape_slice.go | 14 ++-- test/escape_struct_param1.go | 158 ++++++++++++++++++------------------- test/escape_struct_param2.go | 158 ++++++++++++++++++------------------- test/fixedbugs/issue12006.go | 4 +- test/fixedbugs/issue13799.go | 4 +- test/fixedbugs/issue17645.go | 2 +- test/fixedbugs/issue21709.go | 4 +- test/fixedbugs/issue23732.go | 6 +- test/fixedbugs/issue26855.go | 4 +- test/fixedbugs/issue30898.go | 2 +- test/fixedbugs/issue31573.go | 24 +++--- test/fixedbugs/issue38745.go | 19 +++++ test/fixedbugs/issue39292.go | 6 +- test/fixedbugs/issue41247.go | 2 +- test/fixedbugs/issue7921.go | 10 +-- test/inline_variadic.go | 2 +- 27 files changed, 379 insertions(+), 353 deletions(-) create mode 100644 test/fixedbugs/issue38745.go (limited to 'src/cmd/compile/internal') diff --git a/src/cmd/compile/internal/gc/fmt.go b/src/cmd/compile/internal/gc/fmt.go index 866cd0a714..43e501deaf 100644 --- a/src/cmd/compile/internal/gc/fmt.go +++ b/src/cmd/compile/internal/gc/fmt.go @@ -1407,7 +1407,7 @@ func (n *Node) exprfmt(s fmt.State, prec int, mode fmtMode) { return } if n.Right != nil { - mode.Fprintf(s, "%v literal", n.Right) + mode.Fprintf(s, "%v{%s}", n.Right, ellipsisIf(n.List.Len() != 0)) return } @@ -1421,7 +1421,7 @@ func (n *Node) exprfmt(s fmt.State, prec int, mode fmtMode) { case OSTRUCTLIT, OARRAYLIT, OSLICELIT, OMAPLIT: if mode == FErr { - mode.Fprintf(s, "%v literal", n.Type) + mode.Fprintf(s, "%v{%s}", n.Type, ellipsisIf(n.List.Len() != 0)) return } mode.Fprintf(s, "(%v{ %.v })", n.Type, n.List) @@ -1934,3 +1934,10 @@ func indent(s fmt.State) { fmt.Fprint(s, ". ") } } + +func ellipsisIf(b bool) string { + if b { + return "..." + } + return "" +} diff --git a/test/alias2.go b/test/alias2.go index 7ea1b2908d..1c141ac490 100644 --- a/test/alias2.go +++ b/test/alias2.go @@ -46,8 +46,8 @@ var _ A0 = T0{} var _ T0 = A0{} // But aliases and original types cannot be used with new types based on them. -var _ N0 = T0{} // ERROR "cannot use T0 literal \(type T0\) as type N0 in assignment|incompatible type" -var _ N0 = A0{} // ERROR "cannot use T0 literal \(type T0\) as type N0 in assignment|incompatible type" +var _ N0 = T0{} // ERROR "cannot use T0{} \(type T0\) as type N0 in assignment|incompatible type" +var _ N0 = A0{} // ERROR "cannot use T0{} \(type T0\) as type N0 in assignment|incompatible type" var _ A5 = Value{} @@ -82,10 +82,10 @@ func _() { var _ A0 = T0{} var _ T0 = A0{} - var _ N0 = T0{} // ERROR "cannot use T0 literal \(type T0\) as type N0 in assignment|incompatible type" - var _ N0 = A0{} // ERROR "cannot use T0 literal \(type T0\) as type N0 in assignment|incompatible type" + var _ N0 = T0{} // ERROR "cannot use T0{} \(type T0\) as type N0 in assignment|incompatible type" + var _ N0 = A0{} // ERROR "cannot use T0{} \(type T0\) as type N0 in assignment|incompatible type" - var _ A5 = Value{} // ERROR "cannot use reflect\.Value literal \(type reflect.Value\) as type A5 in assignment|incompatible type" + var _ A5 = Value{} // ERROR "cannot use reflect\.Value{} \(type reflect.Value\) as type A5 in assignment|incompatible type" } // Invalid type alias declarations. diff --git a/test/ddd1.go b/test/ddd1.go index b582f221b7..2c7e83e374 100644 --- a/test/ddd1.go +++ b/test/ddd1.go @@ -19,7 +19,7 @@ var ( _ = sum(1.0, 2.0) _ = sum(1.5) // ERROR "integer" _ = sum("hello") // ERROR ".hello. .type untyped string. as type int|incompatible" - _ = sum([]int{1}) // ERROR "\[\]int literal.*as type int|incompatible" + _ = sum([]int{1}) // ERROR "\[\]int{...}.*as type int|incompatible" ) func sum3(int, int, int) int { return 0 } diff --git a/test/escape2.go b/test/escape2.go index cf24f4bebc..5c6eb559fa 100644 --- a/test/escape2.go +++ b/test/escape2.go @@ -118,15 +118,15 @@ type Bar struct { } func NewBar() *Bar { - return &Bar{42, nil} // ERROR "&Bar literal escapes to heap$" + return &Bar{42, nil} // ERROR "&Bar{...} escapes to heap$" } func NewBarp(x *int) *Bar { // ERROR "leaking param: x$" - return &Bar{42, x} // ERROR "&Bar literal escapes to heap$" + return &Bar{42, x} // ERROR "&Bar{...} escapes to heap$" } func NewBarp2(x *int) *Bar { // ERROR "x does not escape$" - return &Bar{*x, nil} // ERROR "&Bar literal escapes to heap$" + return &Bar{*x, nil} // ERROR "&Bar{...} escapes to heap$" } func (b *Bar) NoLeak() int { // ERROR "b does not escape$" @@ -173,7 +173,7 @@ type Bar2 struct { } func NewBar2() *Bar2 { - return &Bar2{[12]int{42}, nil} // ERROR "&Bar2 literal escapes to heap$" + return &Bar2{[12]int{42}, nil} // ERROR "&Bar2{...} escapes to heap$" } func (b *Bar2) NoLeak() int { // ERROR "b does not escape$" @@ -539,7 +539,7 @@ func foo72b() [10]*int { // issue 2145 func foo73() { - s := []int{3, 2, 1} // ERROR "\[\]int literal does not escape$" + s := []int{3, 2, 1} // ERROR "\[\]int{...} does not escape$" for _, v := range s { vv := v // actually just escapes its scope @@ -550,7 +550,7 @@ func foo73() { } func foo731() { - s := []int{3, 2, 1} // ERROR "\[\]int literal does not escape$" + s := []int{3, 2, 1} // ERROR "\[\]int{...} does not escape$" for _, v := range s { vv := v // ERROR "moved to heap: vv$" // actually just escapes its scope @@ -562,7 +562,7 @@ func foo731() { } func foo74() { - s := []int{3, 2, 1} // ERROR "\[\]int literal does not escape$" + s := []int{3, 2, 1} // ERROR "\[\]int{...} does not escape$" for _, v := range s { vv := v // actually just escapes its scope @@ -574,7 +574,7 @@ func foo74() { } func foo74a() { - s := []int{3, 2, 1} // ERROR "\[\]int literal does not escape$" + s := []int{3, 2, 1} // ERROR "\[\]int{...} does not escape$" for _, v := range s { vv := v // ERROR "moved to heap: vv$" // actually just escapes its scope @@ -589,7 +589,7 @@ func foo74a() { // issue 3975 func foo74b() { var array [3]func() - s := []int{3, 2, 1} // ERROR "\[\]int literal does not escape$" + s := []int{3, 2, 1} // ERROR "\[\]int{...} does not escape$" for i, v := range s { vv := v // actually just escapes its scope @@ -601,7 +601,7 @@ func foo74b() { func foo74c() { var array [3]func() - s := []int{3, 2, 1} // ERROR "\[\]int literal does not escape$" + s := []int{3, 2, 1} // ERROR "\[\]int{...} does not escape$" for i, v := range s { vv := v // ERROR "moved to heap: vv$" // actually just escapes its scope @@ -759,15 +759,15 @@ type LimitedFooer struct { } func LimitFooer(r Fooer, n int64) Fooer { // ERROR "leaking param: r$" - return &LimitedFooer{r, n} // ERROR "&LimitedFooer literal escapes to heap$" + return &LimitedFooer{r, n} // ERROR "&LimitedFooer{...} escapes to heap$" } func foo90(x *int) map[*int]*int { // ERROR "leaking param: x$" - return map[*int]*int{nil: x} // ERROR "map\[\*int\]\*int literal escapes to heap$" + return map[*int]*int{nil: x} // ERROR "map\[\*int\]\*int{...} escapes to heap$" } func foo91(x *int) map[*int]*int { // ERROR "leaking param: x$" - return map[*int]*int{x: nil} // ERROR "map\[\*int\]\*int literal escapes to heap$" + return map[*int]*int{x: nil} // ERROR "map\[\*int\]\*int{...} escapes to heap$" } func foo92(x *int) [2]*int { // ERROR "leaking param: x to result ~r1 level=0$" @@ -870,15 +870,15 @@ func foo106(x *int) { // ERROR "leaking param: x$" } func foo107(x *int) map[*int]*int { // ERROR "leaking param: x$" - return map[*int]*int{x: nil} // ERROR "map\[\*int\]\*int literal escapes to heap$" + return map[*int]*int{x: nil} // ERROR "map\[\*int\]\*int{...} escapes to heap$" } func foo108(x *int) map[*int]*int { // ERROR "leaking param: x$" - return map[*int]*int{nil: x} // ERROR "map\[\*int\]\*int literal escapes to heap$" + return map[*int]*int{nil: x} // ERROR "map\[\*int\]\*int{...} escapes to heap$" } func foo109(x *int) *int { // ERROR "leaking param: x$" - m := map[*int]*int{x: nil} // ERROR "map\[\*int\]\*int literal does not escape$" + m := map[*int]*int{x: nil} // ERROR "map\[\*int\]\*int{...} does not escape$" for k, _ := range m { return k } @@ -886,12 +886,12 @@ func foo109(x *int) *int { // ERROR "leaking param: x$" } func foo110(x *int) *int { // ERROR "leaking param: x$" - m := map[*int]*int{nil: x} // ERROR "map\[\*int\]\*int literal does not escape$" + m := map[*int]*int{nil: x} // ERROR "map\[\*int\]\*int{...} does not escape$" return m[nil] } func foo111(x *int) *int { // ERROR "leaking param: x to result ~r1 level=0" - m := []*int{x} // ERROR "\[\]\*int literal does not escape$" + m := []*int{x} // ERROR "\[\]\*int{...} does not escape$" return m[0] } @@ -906,7 +906,7 @@ func foo113(x *int) *int { // ERROR "leaking param: x to result ~r1 level=0$" } func foo114(x *int) *int { // ERROR "leaking param: x to result ~r1 level=0$" - m := &Bar{ii: x} // ERROR "&Bar literal does not escape$" + m := &Bar{ii: x} // ERROR "&Bar{...} does not escape$" return m.ii } @@ -1343,8 +1343,8 @@ func foo140() interface{} { X string T *T } - t := &T{} // ERROR "&T literal escapes to heap$" - return U{ // ERROR "U literal escapes to heap$" + t := &T{} // ERROR "&T{} escapes to heap$" + return U{ // ERROR "U{...} escapes to heap$" X: t.X, T: t, } @@ -1530,7 +1530,7 @@ type V struct { } func NewV(u U) *V { // ERROR "leaking param: u$" - return &V{u.String()} // ERROR "&V literal escapes to heap$" + return &V{u.String()} // ERROR "&V{...} escapes to heap$" } func foo152() { @@ -1571,21 +1571,21 @@ type Lit struct { func ptrlitNoescape() { // Both literal and element do not escape. i := 0 - x := &Lit{&i} // ERROR "&Lit literal does not escape$" + x := &Lit{&i} // ERROR "&Lit{...} does not escape$" _ = x } func ptrlitNoEscape2() { // Literal does not escape, but element does. i := 0 // ERROR "moved to heap: i$" - x := &Lit{&i} // ERROR "&Lit literal does not escape$" + x := &Lit{&i} // ERROR "&Lit{...} does not escape$" sink = *x } func ptrlitEscape() { // Both literal and element escape. i := 0 // ERROR "moved to heap: i$" - x := &Lit{&i} // ERROR "&Lit literal escapes to heap$" + x := &Lit{&i} // ERROR "&Lit{...} escapes to heap$" sink = x } @@ -1760,18 +1760,18 @@ func stringtoslicerune2() { } func slicerunetostring0() { - r := []rune{1, 2, 3} // ERROR "\[\]rune literal does not escape$" + r := []rune{1, 2, 3} // ERROR "\[\]rune{...} does not escape$" s := string(r) // ERROR "string\(r\) does not escape$" _ = s } func slicerunetostring1() string { - r := []rune{1, 2, 3} // ERROR "\[\]rune literal does not escape$" + r := []rune{1, 2, 3} // ERROR "\[\]rune{...} does not escape$" return string(r) // ERROR "string\(r\) escapes to heap$" } func slicerunetostring2() { - r := []rune{1, 2, 3} // ERROR "\[\]rune literal does not escape$" + r := []rune{1, 2, 3} // ERROR "\[\]rune{...} does not escape$" sink = string(r) // ERROR "string\(r\) escapes to heap$" } diff --git a/test/escape2n.go b/test/escape2n.go index f771e0aef2..46e58f8566 100644 --- a/test/escape2n.go +++ b/test/escape2n.go @@ -118,15 +118,15 @@ type Bar struct { } func NewBar() *Bar { - return &Bar{42, nil} // ERROR "&Bar literal escapes to heap$" + return &Bar{42, nil} // ERROR "&Bar{...} escapes to heap$" } func NewBarp(x *int) *Bar { // ERROR "leaking param: x$" - return &Bar{42, x} // ERROR "&Bar literal escapes to heap$" + return &Bar{42, x} // ERROR "&Bar{...} escapes to heap$" } func NewBarp2(x *int) *Bar { // ERROR "x does not escape$" - return &Bar{*x, nil} // ERROR "&Bar literal escapes to heap$" + return &Bar{*x, nil} // ERROR "&Bar{...} escapes to heap$" } func (b *Bar) NoLeak() int { // ERROR "b does not escape$" @@ -173,7 +173,7 @@ type Bar2 struct { } func NewBar2() *Bar2 { - return &Bar2{[12]int{42}, nil} // ERROR "&Bar2 literal escapes to heap$" + return &Bar2{[12]int{42}, nil} // ERROR "&Bar2{...} escapes to heap$" } func (b *Bar2) NoLeak() int { // ERROR "b does not escape$" @@ -539,7 +539,7 @@ func foo72b() [10]*int { // issue 2145 func foo73() { - s := []int{3, 2, 1} // ERROR "\[\]int literal does not escape$" + s := []int{3, 2, 1} // ERROR "\[\]int{...} does not escape$" for _, v := range s { vv := v // actually just escapes its scope @@ -550,7 +550,7 @@ func foo73() { } func foo731() { - s := []int{3, 2, 1} // ERROR "\[\]int literal does not escape$" + s := []int{3, 2, 1} // ERROR "\[\]int{...} does not escape$" for _, v := range s { vv := v // ERROR "moved to heap: vv$" // actually just escapes its scope @@ -562,7 +562,7 @@ func foo731() { } func foo74() { - s := []int{3, 2, 1} // ERROR "\[\]int literal does not escape$" + s := []int{3, 2, 1} // ERROR "\[\]int{...} does not escape$" for _, v := range s { vv := v // actually just escapes its scope @@ -574,7 +574,7 @@ func foo74() { } func foo74a() { - s := []int{3, 2, 1} // ERROR "\[\]int literal does not escape$" + s := []int{3, 2, 1} // ERROR "\[\]int{...} does not escape$" for _, v := range s { vv := v // ERROR "moved to heap: vv$" // actually just escapes its scope @@ -589,7 +589,7 @@ func foo74a() { // issue 3975 func foo74b() { var array [3]func() - s := []int{3, 2, 1} // ERROR "\[\]int literal does not escape$" + s := []int{3, 2, 1} // ERROR "\[\]int{...} does not escape$" for i, v := range s { vv := v // actually just escapes its scope @@ -601,7 +601,7 @@ func foo74b() { func foo74c() { var array [3]func() - s := []int{3, 2, 1} // ERROR "\[\]int literal does not escape$" + s := []int{3, 2, 1} // ERROR "\[\]int{...} does not escape$" for i, v := range s { vv := v // ERROR "moved to heap: vv$" // actually just escapes its scope @@ -759,15 +759,15 @@ type LimitedFooer struct { } func LimitFooer(r Fooer, n int64) Fooer { // ERROR "leaking param: r$" - return &LimitedFooer{r, n} // ERROR "&LimitedFooer literal escapes to heap$" + return &LimitedFooer{r, n} // ERROR "&LimitedFooer{...} escapes to heap$" } func foo90(x *int) map[*int]*int { // ERROR "leaking param: x$" - return map[*int]*int{nil: x} // ERROR "map\[\*int\]\*int literal escapes to heap$" + return map[*int]*int{nil: x} // ERROR "map\[\*int\]\*int{...} escapes to heap$" } func foo91(x *int) map[*int]*int { // ERROR "leaking param: x$" - return map[*int]*int{x: nil} // ERROR "map\[\*int\]\*int literal escapes to heap$" + return map[*int]*int{x: nil} // ERROR "map\[\*int\]\*int{...} escapes to heap$" } func foo92(x *int) [2]*int { // ERROR "leaking param: x to result ~r1 level=0$" @@ -870,15 +870,15 @@ func foo106(x *int) { // ERROR "leaking param: x$" } func foo107(x *int) map[*int]*int { // ERROR "leaking param: x$" - return map[*int]*int{x: nil} // ERROR "map\[\*int\]\*int literal escapes to heap$" + return map[*int]*int{x: nil} // ERROR "map\[\*int\]\*int{...} escapes to heap$" } func foo108(x *int) map[*int]*int { // ERROR "leaking param: x$" - return map[*int]*int{nil: x} // ERROR "map\[\*int\]\*int literal escapes to heap$" + return map[*int]*int{nil: x} // ERROR "map\[\*int\]\*int{...} escapes to heap$" } func foo109(x *int) *int { // ERROR "leaking param: x$" - m := map[*int]*int{x: nil} // ERROR "map\[\*int\]\*int literal does not escape$" + m := map[*int]*int{x: nil} // ERROR "map\[\*int\]\*int{...} does not escape$" for k, _ := range m { return k } @@ -886,12 +886,12 @@ func foo109(x *int) *int { // ERROR "leaking param: x$" } func foo110(x *int) *int { // ERROR "leaking param: x$" - m := map[*int]*int{nil: x} // ERROR "map\[\*int\]\*int literal does not escape$" + m := map[*int]*int{nil: x} // ERROR "map\[\*int\]\*int{...} does not escape$" return m[nil] } func foo111(x *int) *int { // ERROR "leaking param: x to result ~r1 level=0" - m := []*int{x} // ERROR "\[\]\*int literal does not escape$" + m := []*int{x} // ERROR "\[\]\*int{...} does not escape$" return m[0] } @@ -906,7 +906,7 @@ func foo113(x *int) *int { // ERROR "leaking param: x to result ~r1 level=0$" } func foo114(x *int) *int { // ERROR "leaking param: x to result ~r1 level=0$" - m := &Bar{ii: x} // ERROR "&Bar literal does not escape$" + m := &Bar{ii: x} // ERROR "&Bar{...} does not escape$" return m.ii } @@ -1343,8 +1343,8 @@ func foo140() interface{} { X string T *T } - t := &T{} // ERROR "&T literal escapes to heap$" - return U{ // ERROR "U literal escapes to heap$" + t := &T{} // ERROR "&T{} escapes to heap$" + return U{ // ERROR "U{...} escapes to heap$" X: t.X, T: t, } @@ -1530,7 +1530,7 @@ type V struct { } func NewV(u U) *V { // ERROR "leaking param: u$" - return &V{u.String()} // ERROR "&V literal escapes to heap$" + return &V{u.String()} // ERROR "&V{...} escapes to heap$" } func foo152() { @@ -1571,21 +1571,21 @@ type Lit struct { func ptrlitNoescape() { // Both literal and element do not escape. i := 0 - x := &Lit{&i} // ERROR "&Lit literal does not escape$" + x := &Lit{&i} // ERROR "&Lit{...} does not escape$" _ = x } func ptrlitNoEscape2() { // Literal does not escape, but element does. i := 0 // ERROR "moved to heap: i$" - x := &Lit{&i} // ERROR "&Lit literal does not escape$" + x := &Lit{&i} // ERROR "&Lit{...} does not escape$" sink = *x } func ptrlitEscape() { // Both literal and element escape. i := 0 // ERROR "moved to heap: i$" - x := &Lit{&i} // ERROR "&Lit literal escapes to heap$" + x := &Lit{&i} // ERROR "&Lit{...} escapes to heap$" sink = x } @@ -1760,18 +1760,18 @@ func stringtoslicerune2() { } func slicerunetostring0() { - r := []rune{1, 2, 3} // ERROR "\[\]rune literal does not escape$" + r := []rune{1, 2, 3} // ERROR "\[\]rune{...} does not escape$" s := string(r) // ERROR "string\(r\) does not escape$" _ = s } func slicerunetostring1() string { - r := []rune{1, 2, 3} // ERROR "\[\]rune literal does not escape$" + r := []rune{1, 2, 3} // ERROR "\[\]rune{...} does not escape$" return string(r) // ERROR "string\(r\) escapes to heap$" } func slicerunetostring2() { - r := []rune{1, 2, 3} // ERROR "\[\]rune literal does not escape$" + r := []rune{1, 2, 3} // ERROR "\[\]rune{...} does not escape$" sink = string(r) // ERROR "string\(r\) escapes to heap$" } diff --git a/test/escape_calls.go b/test/escape_calls.go index 2dbfee1558..9e1db5426e 100644 --- a/test/escape_calls.go +++ b/test/escape_calls.go @@ -50,5 +50,5 @@ func bar() { f := prototype f = func(ss []string) { got = append(got, ss) } // ERROR "leaking param: ss" "func literal does not escape" s := "string" - f([]string{s}) // ERROR "\[\]string literal escapes to heap" + f([]string{s}) // ERROR "\[\]string{...} escapes to heap" } diff --git a/test/escape_field.go b/test/escape_field.go index bf1dfb18ff..95d0784d91 100644 --- a/test/escape_field.go +++ b/test/escape_field.go @@ -127,20 +127,20 @@ func field12() { func field13() { i := 0 // ERROR "moved to heap: i$" - x := &X{p1: &i} // ERROR "&X literal does not escape$" + x := &X{p1: &i} // ERROR "&X{...} does not escape$" sink = x.p1 } func field14() { i := 0 // ERROR "moved to heap: i$" // BAD: &i should not escape - x := &X{p1: &i} // ERROR "&X literal does not escape$" + x := &X{p1: &i} // ERROR "&X{...} does not escape$" sink = x.p2 } func field15() { i := 0 // ERROR "moved to heap: i$" - x := &X{p1: &i} // ERROR "&X literal escapes to heap$" + x := &X{p1: &i} // ERROR "&X{...} escapes to heap$" sink = x } diff --git a/test/escape_iface.go b/test/escape_iface.go index 118ed3c56f..7b0914cadb 100644 --- a/test/escape_iface.go +++ b/test/escape_iface.go @@ -37,7 +37,7 @@ func efaceEscape0() { _ = x } { - i := 0 // ERROR "moved to heap: i" + i := 0 // ERROR "moved to heap: i" v := M0{&i} var x M = v sink = x @@ -50,7 +50,7 @@ func efaceEscape0() { _ = v1 } { - i := 0 // ERROR "moved to heap: i" + i := 0 // ERROR "moved to heap: i" v := M0{&i} // BAD: v does not escape to heap here var x M = v @@ -58,14 +58,14 @@ func efaceEscape0() { sink = v1 } { - i := 0 // ERROR "moved to heap: i" + i := 0 // ERROR "moved to heap: i" v := M0{&i} // BAD: v does not escape to heap here var x M = v x.M() } { - i := 0 // ERROR "moved to heap: i" + i := 0 // ERROR "moved to heap: i" v := M0{&i} var x M = v mescapes(x) @@ -91,46 +91,46 @@ func efaceEscape1() { { i := 0 v := M1{&i, 0} - var x M = v // ERROR "v does not escape" + var x M = v // ERROR "v does not escape" _ = x } { - i := 0 // ERROR "moved to heap: i" + i := 0 // ERROR "moved to heap: i" v := M1{&i, 0} - var x M = v // ERROR "v escapes to heap" + var x M = v // ERROR "v escapes to heap" sink = x } { i := 0 v := M1{&i, 0} - var x M = v // ERROR "v does not escape" + var x M = v // ERROR "v does not escape" v1 := x.(M1) _ = v1 } { - i := 0 // ERROR "moved to heap: i" + i := 0 // ERROR "moved to heap: i" v := M1{&i, 0} var x M = v // ERROR "v does not escape" v1 := x.(M1) sink = v1 // ERROR "v1 escapes to heap" } { - i := 0 // ERROR "moved to heap: i" + i := 0 // ERROR "moved to heap: i" v := M1{&i, 0} // BAD: v does not escape to heap here var x M = v // ERROR "v escapes to heap" x.M() } { - i := 0 // ERROR "moved to heap: i" + i := 0 // ERROR "moved to heap: i" v := M1{&i, 0} - var x M = v // ERROR "v escapes to heap" + var x M = v // ERROR "v escapes to heap" mescapes(x) } { i := 0 v := M1{&i, 0} - var x M = v // ERROR "v does not escape" + var x M = v // ERROR "v does not escape" mdoesnotescape(x) } } @@ -146,26 +146,26 @@ func (*M2) M() { func efaceEscape2() { { i := 0 - v := &M2{&i} // ERROR "&M2 literal does not escape" + v := &M2{&i} // ERROR "&M2{...} does not escape" var x M = v _ = x } { i := 0 // ERROR "moved to heap: i" - v := &M2{&i} // ERROR "&M2 literal escapes to heap" + v := &M2{&i} // ERROR "&M2{...} escapes to heap" var x M = v sink = x } { i := 0 - v := &M2{&i} // ERROR "&M2 literal does not escape" + v := &M2{&i} // ERROR "&M2{...} does not escape" var x M = v v1 := x.(*M2) _ = v1 } { i := 0 // ERROR "moved to heap: i" - v := &M2{&i} // ERROR "&M2 literal escapes to heap" + v := &M2{&i} // ERROR "&M2{...} escapes to heap" // BAD: v does not escape to heap here var x M = v v1 := x.(*M2) @@ -173,7 +173,7 @@ func efaceEscape2() { } { i := 0 // ERROR "moved to heap: i" - v := &M2{&i} // ERROR "&M2 literal does not escape" + v := &M2{&i} // ERROR "&M2{...} does not escape" // BAD: v does not escape to heap here var x M = v v1 := x.(*M2) @@ -181,7 +181,7 @@ func efaceEscape2() { } { i := 0 // ERROR "moved to heap: i" - v := &M2{&i} // ERROR "&M2 literal does not escape" + v := &M2{&i} // ERROR "&M2{...} does not escape" // BAD: v does not escape to heap here var x M = v v1, ok := x.(*M2) @@ -190,20 +190,20 @@ func efaceEscape2() { } { i := 0 // ERROR "moved to heap: i" - v := &M2{&i} // ERROR "&M2 literal escapes to heap" + v := &M2{&i} // ERROR "&M2{...} escapes to heap" // BAD: v does not escape to heap here var x M = v x.M() } { i := 0 // ERROR "moved to heap: i" - v := &M2{&i} // ERROR "&M2 literal escapes to heap" + v := &M2{&i} // ERROR "&M2{...} escapes to heap" var x M = v mescapes(x) } { i := 0 - v := &M2{&i} // ERROR "&M2 literal does not escape" + v := &M2{&i} // ERROR "&M2{...} does not escape" var x M = v mdoesnotescape(x) } @@ -219,8 +219,8 @@ type T2 struct { func dotTypeEscape() *T2 { // #11931 var x interface{} - x = &T1{p: new(int)} // ERROR "new\(int\) escapes to heap" "&T1 literal does not escape" - return &T2{ // ERROR "&T2 literal escapes to heap" + x = &T1{p: new(int)} // ERROR "new\(int\) escapes to heap" "&T1{...} does not escape" + return &T2{ // ERROR "&T2{...} escapes to heap" T1: *(x.(*T1)), } } @@ -244,7 +244,7 @@ func dotTypeEscape2() { // #13805, #15796 var x interface{} = i // ERROR "i does not escape" var y interface{} = j // ERROR "j does not escape" - sink = x.(int) // ERROR "x.\(int\) escapes to heap" + sink = x.(int) // ERROR "x.\(int\) escapes to heap" sink, *(&ok) = y.(int) } { diff --git a/test/escape_indir.go b/test/escape_indir.go index 19889f259f..12005e35f9 100644 --- a/test/escape_indir.go +++ b/test/escape_indir.go @@ -23,7 +23,7 @@ type ConstPtr2 struct { func constptr0() { i := 0 // ERROR "moved to heap: i" - x := &ConstPtr{} // ERROR "&ConstPtr literal does not escape" + x := &ConstPtr{} // ERROR "&ConstPtr{} does not escape" // BAD: i should not escape here x.p = &i _ = x @@ -31,55 +31,55 @@ func constptr0() { func constptr01() *ConstPtr { i := 0 // ERROR "moved to heap: i" - x := &ConstPtr{} // ERROR "&ConstPtr literal escapes to heap" + x := &ConstPtr{} // ERROR "&ConstPtr{} escapes to heap" x.p = &i return x } func constptr02() ConstPtr { i := 0 // ERROR "moved to heap: i" - x := &ConstPtr{} // ERROR "&ConstPtr literal does not escape" + x := &ConstPtr{} // ERROR "&ConstPtr{} does not escape" x.p = &i return *x } func constptr03() **ConstPtr { i := 0 // ERROR "moved to heap: i" - x := &ConstPtr{} // ERROR "&ConstPtr literal escapes to heap" "moved to heap: x" + x := &ConstPtr{} // ERROR "&ConstPtr{} escapes to heap" "moved to heap: x" x.p = &i return &x } func constptr1() { i := 0 // ERROR "moved to heap: i" - x := &ConstPtr{} // ERROR "&ConstPtr literal escapes to heap" + x := &ConstPtr{} // ERROR "&ConstPtr{} escapes to heap" x.p = &i sink = x } func constptr2() { i := 0 // ERROR "moved to heap: i" - x := &ConstPtr{} // ERROR "&ConstPtr literal does not escape" + x := &ConstPtr{} // ERROR "&ConstPtr{} does not escape" x.p = &i - sink = *x // ERROR "\*x escapes to heap" + sink = *x // ERROR "\*x escapes to heap" } func constptr4() *ConstPtr { p := new(ConstPtr) // ERROR "new\(ConstPtr\) escapes to heap" - *p = *&ConstPtr{} // ERROR "&ConstPtr literal does not escape" + *p = *&ConstPtr{} // ERROR "&ConstPtr{} does not escape" return p } func constptr5() *ConstPtr { p := new(ConstPtr) // ERROR "new\(ConstPtr\) escapes to heap" - p1 := &ConstPtr{} // ERROR "&ConstPtr literal does not escape" + p1 := &ConstPtr{} // ERROR "&ConstPtr{} does not escape" *p = *p1 return p } // BAD: p should not escape here func constptr6(p *ConstPtr) { // ERROR "leaking param content: p" - p1 := &ConstPtr{} // ERROR "&ConstPtr literal does not escape" + p1 := &ConstPtr{} // ERROR "&ConstPtr{} does not escape" *p1 = *p _ = p1 } @@ -102,17 +102,17 @@ func constptr8() *ConstPtr { func constptr9() ConstPtr { p := new(ConstPtr) // ERROR "new\(ConstPtr\) does not escape" var p1 ConstPtr2 - i := 0 // ERROR "moved to heap: i" + i := 0 // ERROR "moved to heap: i" p1.p = &i p.c = p1 return *p } func constptr10() ConstPtr { - x := &ConstPtr{} // ERROR "moved to heap: x" "&ConstPtr literal escapes to heap" + x := &ConstPtr{} // ERROR "moved to heap: x" "&ConstPtr{} escapes to heap" i := 0 // ERROR "moved to heap: i" var p *ConstPtr - p = &ConstPtr{p: &i, x: &x} // ERROR "&ConstPtr literal does not escape" + p = &ConstPtr{p: &i, x: &x} // ERROR "&ConstPtr{...} does not escape" var pp **ConstPtr pp = &p return **pp @@ -121,7 +121,7 @@ func constptr10() ConstPtr { func constptr11() *ConstPtr { i := 0 // ERROR "moved to heap: i" p := new(ConstPtr) // ERROR "new\(ConstPtr\) escapes to heap" - p1 := &ConstPtr{} // ERROR "&ConstPtr literal does not escape" + p1 := &ConstPtr{} // ERROR "&ConstPtr{} does not escape" p1.p = &i *p = *p1 return p @@ -134,7 +134,7 @@ func foo(p **int) { // ERROR "p does not escape" } func foo1(p *int) { // ERROR "p does not escape" - i := 0 // ERROR "moved to heap: i" + i := 0 // ERROR "moved to heap: i" y := &p *y = &i } @@ -148,13 +148,13 @@ func foo2() { var z Z z.f = &x p := z.f - i := 0 // ERROR "moved to heap: i" + i := 0 // ERROR "moved to heap: i" *p = &i } var global *byte func f() { - var x byte // ERROR "moved to heap: x" + var x byte // ERROR "moved to heap: x" global = &*&x } diff --git a/test/escape_map.go b/test/escape_map.go index 0e9896a9fc..23abaa1e0c 100644 --- a/test/escape_map.go +++ b/test/escape_map.go @@ -15,7 +15,7 @@ func map0() { // BAD: i should not escape i := 0 // ERROR "moved to heap: i" // BAD: j should not escape - j := 0 // ERROR "moved to heap: j" + j := 0 // ERROR "moved to heap: j" m[&i] = &j _ = m } @@ -23,8 +23,8 @@ func map0() { func map1() *int { m := make(map[*int]*int) // ERROR "make\(map\[\*int\]\*int\) does not escape" // BAD: i should not escape - i := 0 // ERROR "moved to heap: i" - j := 0 // ERROR "moved to heap: j" + i := 0 // ERROR "moved to heap: i" + j := 0 // ERROR "moved to heap: j" m[&i] = &j return m[&i] } @@ -41,7 +41,7 @@ func map3() []*int { m := make(map[*int]*int) // ERROR "make\(map\[\*int\]\*int\) does not escape" i := 0 // ERROR "moved to heap: i" // BAD: j should not escape - j := 0 // ERROR "moved to heap: j" + j := 0 // ERROR "moved to heap: j" m[&i] = &j var r []*int for k := range m { @@ -53,8 +53,8 @@ func map3() []*int { func map4() []*int { m := make(map[*int]*int) // ERROR "make\(map\[\*int\]\*int\) does not escape" // BAD: i should not escape - i := 0 // ERROR "moved to heap: i" - j := 0 // ERROR "moved to heap: j" + i := 0 // ERROR "moved to heap: i" + j := 0 // ERROR "moved to heap: j" m[&i] = &j var r []*int for k, v := range m { @@ -68,8 +68,8 @@ func map4() []*int { } func map5(m map[*int]*int) { // ERROR "m does not escape" - i := 0 // ERROR "moved to heap: i" - j := 0 // ERROR "moved to heap: j" + i := 0 // ERROR "moved to heap: i" + j := 0 // ERROR "moved to heap: j" m[&i] = &j } @@ -77,8 +77,8 @@ func map6(m map[*int]*int) { // ERROR "m does not escape" if m != nil { m = make(map[*int]*int) // ERROR "make\(map\[\*int\]\*int\) does not escape" } - i := 0 // ERROR "moved to heap: i" - j := 0 // ERROR "moved to heap: j" + i := 0 // ERROR "moved to heap: i" + j := 0 // ERROR "moved to heap: j" m[&i] = &j } @@ -87,14 +87,14 @@ func map7() { i := 0 // ERROR "moved to heap: i" // BAD: j should not escape j := 0 // ERROR "moved to heap: j" - m := map[*int]*int{&i: &j} // ERROR "literal does not escape" + m := map[*int]*int{&i: &j} // ERROR "map\[\*int\]\*int{...} does not escape" _ = m } func map8() { i := 0 // ERROR "moved to heap: i" j := 0 // ERROR "moved to heap: j" - m := map[*int]*int{&i: &j} // ERROR "literal escapes to heap" + m := map[*int]*int{&i: &j} // ERROR "map\[\*int\]\*int{...} escapes to heap" sink = m } @@ -102,6 +102,6 @@ func map9() *int { // BAD: i should not escape i := 0 // ERROR "moved to heap: i" j := 0 // ERROR "moved to heap: j" - m := map[*int]*int{&i: &j} // ERROR "literal does not escape" + m := map[*int]*int{&i: &j} // ERROR "map\[\*int\]\*int{...} does not escape" return m[nil] } diff --git a/test/escape_param.go b/test/escape_param.go index d8fafc53f8..993e914e1d 100644 --- a/test/escape_param.go +++ b/test/escape_param.go @@ -26,7 +26,7 @@ func caller0a() { } func caller0b() { - i := 0 // ERROR "moved to heap: i$" + i := 0 // ERROR "moved to heap: i$" sink = param0(&i) } @@ -150,11 +150,11 @@ func caller3a() { } func caller3b() { - i := 0 // ERROR "moved to heap: i$" - j := 0 // ERROR "moved to heap: j$" + i := 0 // ERROR "moved to heap: i$" + j := 0 // ERROR "moved to heap: j$" p := Pair{&i, &j} param3(&p) - sink = p // ERROR "p escapes to heap$" + sink = p // ERROR "p escapes to heap$" } // in -> rcvr @@ -173,7 +173,7 @@ func caller4b() { i := 0 // ERROR "moved to heap: i$" p := Pair{} p.param4(&i) - sink = p // ERROR "p escapes to heap$" + sink = p // ERROR "p escapes to heap$" } // in -> heap @@ -182,7 +182,7 @@ func param5(i *int) { // ERROR "leaking param: i$" } func caller5() { - i := 0 // ERROR "moved to heap: i$" + i := 0 // ERROR "moved to heap: i$" param5(&i) } @@ -192,8 +192,8 @@ func param6(i ***int) { // ERROR "leaking param content: i$" } func caller6a() { - i := 0 // ERROR "moved to heap: i$" - p := &i // ERROR "moved to heap: p$" + i := 0 // ERROR "moved to heap: i$" + p := &i // ERROR "moved to heap: p$" p2 := &p param6(&p2) } @@ -204,7 +204,7 @@ func param7(i ***int) { // ERROR "leaking param content: i$" } func caller7() { - i := 0 // ERROR "moved to heap: i$" + i := 0 // ERROR "moved to heap: i$" p := &i p2 := &p param7(&p2) @@ -234,8 +234,8 @@ func caller9a() { } func caller9b() { - i := 0 // ERROR "moved to heap: i$" - p := &i // ERROR "moved to heap: p$" + i := 0 // ERROR "moved to heap: i$" + p := &i // ERROR "moved to heap: p$" p2 := &p sink = param9(&p2) } @@ -253,7 +253,7 @@ func caller10a() { } func caller10b() { - i := 0 // ERROR "moved to heap: i$" + i := 0 // ERROR "moved to heap: i$" p := &i p2 := &p sink = param10(&p2) @@ -265,26 +265,26 @@ func param11(i **int) ***int { // ERROR "moved to heap: i$" } func caller11a() { - i := 0 // ERROR "moved to heap: i" - p := &i // ERROR "moved to heap: p" + i := 0 // ERROR "moved to heap: i" + p := &i // ERROR "moved to heap: p" _ = param11(&p) } func caller11b() { - i := 0 // ERROR "moved to heap: i$" - p := &i // ERROR "moved to heap: p$" + i := 0 // ERROR "moved to heap: i$" + p := &i // ERROR "moved to heap: p$" sink = param11(&p) } func caller11c() { // GOOD - i := 0 // ERROR "moved to heap: i$" - p := &i // ERROR "moved to heap: p" + i := 0 // ERROR "moved to heap: i$" + p := &i // ERROR "moved to heap: p" sink = *param11(&p) } func caller11d() { - i := 0 // ERROR "moved to heap: i$" - p := &i // ERROR "moved to heap: p" + i := 0 // ERROR "moved to heap: i$" + p := &i // ERROR "moved to heap: p" p2 := &p sink = param11(p2) } @@ -309,7 +309,7 @@ func caller12a() { func caller12b() { i := 0 // ERROR "moved to heap: i$" p := &i // ERROR "moved to heap: p$" - r := &Indir{} // ERROR "&Indir literal does not escape$" + r := &Indir{} // ERROR "&Indir{} does not escape$" r.param12(&p) _ = r } @@ -359,7 +359,7 @@ func caller13b() { func caller13c() { i := 0 // ERROR "moved to heap: i$" var p *int - v := &Val{&p} // ERROR "&Val literal does not escape$" + v := &Val{&p} // ERROR "&Val{...} does not escape$" v.param13(&i) _ = v } @@ -374,8 +374,8 @@ func caller13d() { } func caller13e() { - i := 0 // ERROR "moved to heap: i$" - var p *int // ERROR "moved to heap: p$" + i := 0 // ERROR "moved to heap: i$" + var p *int // ERROR "moved to heap: p$" v := Val{&p} v.param13(&i) sink = v @@ -384,7 +384,7 @@ func caller13e() { func caller13f() { i := 0 // ERROR "moved to heap: i$" var p *int // ERROR "moved to heap: p$" - v := &Val{&p} // ERROR "&Val literal escapes to heap$" + v := &Val{&p} // ERROR "&Val{...} escapes to heap$" v.param13(&i) sink = v } @@ -400,9 +400,9 @@ func caller13g() { func caller13h() { i := 0 // ERROR "moved to heap: i$" var p *int - v := &Val{&p} // ERROR "&Val literal does not escape$" + v := &Val{&p} // ERROR "&Val{...} does not escape$" v.param13(&i) - sink = **v.p // ERROR "\* \(\*v\.p\) escapes to heap" + sink = **v.p // ERROR "\* \(\*v\.p\) escapes to heap" } type Node struct { @@ -412,15 +412,15 @@ type Node struct { var Sink *Node func f(x *Node) { // ERROR "leaking param content: x" - Sink = &Node{x.p} // ERROR "&Node literal escapes to heap" + Sink = &Node{x.p} // ERROR "&Node{...} escapes to heap" } func g(x *Node) *Node { // ERROR "leaking param content: x" - return &Node{x.p} // ERROR "&Node literal escapes to heap" + return &Node{x.p} // ERROR "&Node{...} escapes to heap" } func h(x *Node) { // ERROR "leaking param: x" - y := &Node{x} // ERROR "&Node literal does not escape" + y := &Node{x} // ERROR "&Node{...} does not escape" Sink = g(y) f(y) } diff --git a/test/escape_slice.go b/test/escape_slice.go index d2cdaa6a01..6ce852e9c5 100644 --- a/test/escape_slice.go +++ b/test/escape_slice.go @@ -77,19 +77,19 @@ func slice7() *int { func slice8() { i := 0 - s := []*int{&i} // ERROR "literal does not escape" + s := []*int{&i} // ERROR "\[\]\*int{...} does not escape" _ = s } func slice9() *int { i := 0 // ERROR "moved to heap: i" - s := []*int{&i} // ERROR "literal does not escape" + s := []*int{&i} // ERROR "\[\]\*int{...} does not escape" return s[0] } func slice10() []*int { i := 0 // ERROR "moved to heap: i" - s := []*int{&i} // ERROR "literal escapes to heap" + s := []*int{&i} // ERROR "\[\]\*int{...} escapes to heap" return s } @@ -103,7 +103,7 @@ func slice11() { func envForDir(dir string) []string { // ERROR "dir does not escape" env := os.Environ() - return mergeEnvLists([]string{"PWD=" + dir}, env) // ERROR ".PWD=. \+ dir escapes to heap" "\[\]string literal does not escape" + return mergeEnvLists([]string{"PWD=" + dir}, env) // ERROR ".PWD=. \+ dir escapes to heap" "\[\]string{...} does not escape" } func mergeEnvLists(in, out []string) []string { // ERROR "leaking param content: in" "leaking param content: out" "leaking param: out to result ~r2 level=0" @@ -160,14 +160,14 @@ var resolveIPAddrTests = []resolveIPAddrTest{ func setupTestData() { resolveIPAddrTests = append(resolveIPAddrTests, - []resolveIPAddrTest{ // ERROR "\[\]resolveIPAddrTest literal does not escape" + []resolveIPAddrTest{ // ERROR "\[\]resolveIPAddrTest{...} does not escape" {"ip", "localhost", - &IPAddr{IP: IPv4(127, 0, 0, 1)}, // ERROR "&IPAddr literal escapes to heap" + &IPAddr{IP: IPv4(127, 0, 0, 1)}, // ERROR "&IPAddr{...} escapes to heap" nil}, {"ip4", "localhost", - &IPAddr{IP: IPv4(127, 0, 0, 1)}, // ERROR "&IPAddr literal escapes to heap" + &IPAddr{IP: IPv4(127, 0, 0, 1)}, // ERROR "&IPAddr{...} escapes to heap" nil}, }...) } diff --git a/test/escape_struct_param1.go b/test/escape_struct_param1.go index 70b36191ab..496172c166 100644 --- a/test/escape_struct_param1.go +++ b/test/escape_struct_param1.go @@ -35,27 +35,27 @@ func (u *U) SPPi() *string { // ERROR "leaking param: u to result ~r0 level=2$" } func tSPPi() { - s := "cat" // ERROR "moved to heap: s$" + s := "cat" // ERROR "moved to heap: s$" ps := &s pps := &ps - pu := &U{ps, pps} // ERROR "&U literal does not escape$" + pu := &U{ps, pps} // ERROR "&U{...} does not escape$" Ssink = pu.SPPi() } func tiSPP() { - s := "cat" // ERROR "moved to heap: s$" + s := "cat" // ERROR "moved to heap: s$" ps := &s pps := &ps - pu := &U{ps, pps} // ERROR "&U literal does not escape$" + pu := &U{ps, pps} // ERROR "&U{...} does not escape$" Ssink = *pu.SPP() } // BAD: need fine-grained (field-sensitive) analysis to avoid spurious escape of ps func tSP() { - s := "cat" // ERROR "moved to heap: s$" - ps := &s // ERROR "moved to heap: ps$" + s := "cat" // ERROR "moved to heap: s$" + ps := &s // ERROR "moved to heap: ps$" pps := &ps - pu := &U{ps, pps} // ERROR "&U literal does not escape$" + pu := &U{ps, pps} // ERROR "&U{...} does not escape$" Ssink = pu.SP() } @@ -114,72 +114,72 @@ func (v *V) UPiSPd() *string { // ERROR "leaking param: v to result ~r0 level=2$ // BAD: need fine-grained (field-sensitive) analysis to avoid spurious escape of all but &s3 func tUPiSPa() { s1 := "ant" - s2 := "bat" // ERROR "moved to heap: s2$" - s3 := "cat" // ERROR "moved to heap: s3$" - s4 := "dog" // ERROR "moved to heap: s4$" - s5 := "emu" // ERROR "moved to heap: s5$" - s6 := "fox" // ERROR "moved to heap: s6$" + s2 := "bat" // ERROR "moved to heap: s2$" + s3 := "cat" // ERROR "moved to heap: s3$" + s4 := "dog" // ERROR "moved to heap: s4$" + s5 := "emu" // ERROR "moved to heap: s5$" + s6 := "fox" // ERROR "moved to heap: s6$" ps2 := &s2 - ps4 := &s4 // ERROR "moved to heap: ps4$" - ps6 := &s6 // ERROR "moved to heap: ps6$" + ps4 := &s4 // ERROR "moved to heap: ps4$" + ps6 := &s6 // ERROR "moved to heap: ps6$" u1 := U{&s1, &ps2} - u2 := &U{&s3, &ps4} // ERROR "&U literal does not escape$" - u3 := &U{&s5, &ps6} // ERROR "&U literal escapes to heap$" - v := &V{u1, u2, &u3} // ERROR "&V literal does not escape$" + u2 := &U{&s3, &ps4} // ERROR "&U{...} does not escape$" + u3 := &U{&s5, &ps6} // ERROR "&U{...} escapes to heap$" + v := &V{u1, u2, &u3} // ERROR "&V{...} does not escape$" Ssink = v.UPiSPa() // Ssink = &s3 (only &s3 really escapes) } // BAD: need fine-grained (field-sensitive) analysis to avoid spurious escape of all but &s3 func tUPiSPb() { s1 := "ant" - s2 := "bat" // ERROR "moved to heap: s2$" - s3 := "cat" // ERROR "moved to heap: s3$" - s4 := "dog" // ERROR "moved to heap: s4$" - s5 := "emu" // ERROR "moved to heap: s5$" - s6 := "fox" // ERROR "moved to heap: s6$" + s2 := "bat" // ERROR "moved to heap: s2$" + s3 := "cat" // ERROR "moved to heap: s3$" + s4 := "dog" // ERROR "moved to heap: s4$" + s5 := "emu" // ERROR "moved to heap: s5$" + s6 := "fox" // ERROR "moved to heap: s6$" ps2 := &s2 - ps4 := &s4 // ERROR "moved to heap: ps4$" - ps6 := &s6 // ERROR "moved to heap: ps6$" + ps4 := &s4 // ERROR "moved to heap: ps4$" + ps6 := &s6 // ERROR "moved to heap: ps6$" u1 := U{&s1, &ps2} - u2 := &U{&s3, &ps4} // ERROR "&U literal does not escape$" - u3 := &U{&s5, &ps6} // ERROR "&U literal escapes to heap$" - v := &V{u1, u2, &u3} // ERROR "&V literal does not escape$" + u2 := &U{&s3, &ps4} // ERROR "&U{...} does not escape$" + u3 := &U{&s5, &ps6} // ERROR "&U{...} escapes to heap$" + v := &V{u1, u2, &u3} // ERROR "&V{...} does not escape$" Ssink = v.UPiSPb() // Ssink = &s3 (only &s3 really escapes) } // BAD: need fine-grained (field-sensitive) analysis to avoid spurious escape of all but &s3 func tUPiSPc() { s1 := "ant" - s2 := "bat" // ERROR "moved to heap: s2$" - s3 := "cat" // ERROR "moved to heap: s3$" - s4 := "dog" // ERROR "moved to heap: s4$" - s5 := "emu" // ERROR "moved to heap: s5$" - s6 := "fox" // ERROR "moved to heap: s6$" + s2 := "bat" // ERROR "moved to heap: s2$" + s3 := "cat" // ERROR "moved to heap: s3$" + s4 := "dog" // ERROR "moved to heap: s4$" + s5 := "emu" // ERROR "moved to heap: s5$" + s6 := "fox" // ERROR "moved to heap: s6$" ps2 := &s2 - ps4 := &s4 // ERROR "moved to heap: ps4$" - ps6 := &s6 // ERROR "moved to heap: ps6$" + ps4 := &s4 // ERROR "moved to heap: ps4$" + ps6 := &s6 // ERROR "moved to heap: ps6$" u1 := U{&s1, &ps2} - u2 := &U{&s3, &ps4} // ERROR "&U literal does not escape$" - u3 := &U{&s5, &ps6} // ERROR "&U literal escapes to heap$" - v := &V{u1, u2, &u3} // ERROR "&V literal does not escape$" + u2 := &U{&s3, &ps4} // ERROR "&U{...} does not escape$" + u3 := &U{&s5, &ps6} // ERROR "&U{...} escapes to heap$" + v := &V{u1, u2, &u3} // ERROR "&V{...} does not escape$" Ssink = v.UPiSPc() // Ssink = &s3 (only &s3 really escapes) } // BAD: need fine-grained (field-sensitive) analysis to avoid spurious escape of all but &s3 func tUPiSPd() { s1 := "ant" - s2 := "bat" // ERROR "moved to heap: s2$" - s3 := "cat" // ERROR "moved to heap: s3$" - s4 := "dog" // ERROR "moved to heap: s4$" - s5 := "emu" // ERROR "moved to heap: s5$" - s6 := "fox" // ERROR "moved to heap: s6$" + s2 := "bat" // ERROR "moved to heap: s2$" + s3 := "cat" // ERROR "moved to heap: s3$" + s4 := "dog" // ERROR "moved to heap: s4$" + s5 := "emu" // ERROR "moved to heap: s5$" + s6 := "fox" // ERROR "moved to heap: s6$" ps2 := &s2 - ps4 := &s4 // ERROR "moved to heap: ps4$" - ps6 := &s6 // ERROR "moved to heap: ps6$" + ps4 := &s4 // ERROR "moved to heap: ps4$" + ps6 := &s6 // ERROR "moved to heap: ps6$" u1 := U{&s1, &ps2} - u2 := &U{&s3, &ps4} // ERROR "&U literal does not escape$" - u3 := &U{&s5, &ps6} // ERROR "&U literal escapes to heap$" - v := &V{u1, u2, &u3} // ERROR "&V literal does not escape$" + u2 := &U{&s3, &ps4} // ERROR "&U{...} does not escape$" + u3 := &U{&s5, &ps6} // ERROR "&U{...} escapes to heap$" + v := &V{u1, u2, &u3} // ERROR "&V{...} does not escape$" Ssink = v.UPiSPd() // Ssink = &s3 (only &s3 really escapes) } @@ -204,16 +204,16 @@ func tUPiSPPia() { s1 := "ant" s2 := "bat" s3 := "cat" - s4 := "dog" // ERROR "moved to heap: s4$" - s5 := "emu" // ERROR "moved to heap: s5$" - s6 := "fox" // ERROR "moved to heap: s6$" + s4 := "dog" // ERROR "moved to heap: s4$" + s5 := "emu" // ERROR "moved to heap: s5$" + s6 := "fox" // ERROR "moved to heap: s6$" ps2 := &s2 ps4 := &s4 - ps6 := &s6 // ERROR "moved to heap: ps6$" + ps6 := &s6 // ERROR "moved to heap: ps6$" u1 := U{&s1, &ps2} - u2 := &U{&s3, &ps4} // ERROR "&U literal does not escape$" - u3 := &U{&s5, &ps6} // ERROR "&U literal does not escape$" - v := &V{u1, u2, &u3} // ERROR "&V literal does not escape$" + u2 := &U{&s3, &ps4} // ERROR "&U{...} does not escape$" + u3 := &U{&s5, &ps6} // ERROR "&U{...} does not escape$" + v := &V{u1, u2, &u3} // ERROR "&V{...} does not escape$" Ssink = v.UPiSPPia() // Ssink = *&ps4 = &s4 (only &s4 really escapes) } @@ -222,16 +222,16 @@ func tUPiSPPib() { s1 := "ant" s2 := "bat" s3 := "cat" - s4 := "dog" // ERROR "moved to heap: s4$" - s5 := "emu" // ERROR "moved to heap: s5$" - s6 := "fox" // ERROR "moved to heap: s6$" + s4 := "dog" // ERROR "moved to heap: s4$" + s5 := "emu" // ERROR "moved to heap: s5$" + s6 := "fox" // ERROR "moved to heap: s6$" ps2 := &s2 ps4 := &s4 - ps6 := &s6 // ERROR "moved to heap: ps6$" + ps6 := &s6 // ERROR "moved to heap: ps6$" u1 := U{&s1, &ps2} - u2 := &U{&s3, &ps4} // ERROR "&U literal does not escape$" - u3 := &U{&s5, &ps6} // ERROR "&U literal does not escape$" - v := &V{u1, u2, &u3} // ERROR "&V literal does not escape$" + u2 := &U{&s3, &ps4} // ERROR "&U{...} does not escape$" + u3 := &U{&s5, &ps6} // ERROR "&U{...} does not escape$" + v := &V{u1, u2, &u3} // ERROR "&V{...} does not escape$" Ssink = v.UPiSPPib() // Ssink = *&ps4 = &s4 (only &s4 really escapes) } @@ -240,16 +240,16 @@ func tUPiSPPic() { s1 := "ant" s2 := "bat" s3 := "cat" - s4 := "dog" // ERROR "moved to heap: s4$" - s5 := "emu" // ERROR "moved to heap: s5$" - s6 := "fox" // ERROR "moved to heap: s6$" + s4 := "dog" // ERROR "moved to heap: s4$" + s5 := "emu" // ERROR "moved to heap: s5$" + s6 := "fox" // ERROR "moved to heap: s6$" ps2 := &s2 ps4 := &s4 - ps6 := &s6 // ERROR "moved to heap: ps6$" + ps6 := &s6 // ERROR "moved to heap: ps6$" u1 := U{&s1, &ps2} - u2 := &U{&s3, &ps4} // ERROR "&U literal does not escape$" - u3 := &U{&s5, &ps6} // ERROR "&U literal does not escape$" - v := &V{u1, u2, &u3} // ERROR "&V literal does not escape$" + u2 := &U{&s3, &ps4} // ERROR "&U{...} does not escape$" + u3 := &U{&s5, &ps6} // ERROR "&U{...} does not escape$" + v := &V{u1, u2, &u3} // ERROR "&V{...} does not escape$" Ssink = v.UPiSPPic() // Ssink = *&ps4 = &s4 (only &s4 really escapes) } @@ -258,16 +258,16 @@ func tUPiSPPid() { s1 := "ant" s2 := "bat" s3 := "cat" - s4 := "dog" // ERROR "moved to heap: s4$" - s5 := "emu" // ERROR "moved to heap: s5$" - s6 := "fox" // ERROR "moved to heap: s6$" + s4 := "dog" // ERROR "moved to heap: s4$" + s5 := "emu" // ERROR "moved to heap: s5$" + s6 := "fox" // ERROR "moved to heap: s6$" ps2 := &s2 ps4 := &s4 - ps6 := &s6 // ERROR "moved to heap: ps6$" + ps6 := &s6 // ERROR "moved to heap: ps6$" u1 := U{&s1, &ps2} - u2 := &U{&s3, &ps4} // ERROR "&U literal does not escape$" - u3 := &U{&s5, &ps6} // ERROR "&U literal does not escape$" - v := &V{u1, u2, &u3} // ERROR "&V literal does not escape$" + u2 := &U{&s3, &ps4} // ERROR "&U{...} does not escape$" + u3 := &U{&s5, &ps6} // ERROR "&U{...} does not escape$" + v := &V{u1, u2, &u3} // ERROR "&V{...} does not escape$" Ssink = v.UPiSPPid() // Ssink = *&ps4 = &s4 (only &s4 really escapes) } @@ -286,13 +286,13 @@ func tUPPiSPPia() { s3 := "cat" s4 := "dog" s5 := "emu" - s6 := "fox" // ERROR "moved to heap: s6$" + s6 := "fox" // ERROR "moved to heap: s6$" ps2 := &s2 ps4 := &s4 ps6 := &s6 u1 := U{&s1, &ps2} - u2 := &U{&s3, &ps4} // ERROR "&U literal does not escape$" - u3 := &U{&s5, &ps6} // ERROR "&U literal does not escape$" - v := &V{u1, u2, &u3} // ERROR "&V literal does not escape$" + u2 := &U{&s3, &ps4} // ERROR "&U{...} does not escape$" + u3 := &U{&s5, &ps6} // ERROR "&U{...} does not escape$" + v := &V{u1, u2, &u3} // ERROR "&V{...} does not escape$" Ssink = v.UPPiSPPia() // Ssink = *&ps6 = &s6 (only &s6 really escapes) } diff --git a/test/escape_struct_param2.go b/test/escape_struct_param2.go index e42be79793..946397ea9f 100644 --- a/test/escape_struct_param2.go +++ b/test/escape_struct_param2.go @@ -35,27 +35,27 @@ func (u U) SPPi() *string { // ERROR "leaking param: u to result ~r0 level=1$" } func tSPPi() { - s := "cat" // ERROR "moved to heap: s$" + s := "cat" // ERROR "moved to heap: s$" ps := &s pps := &ps - pu := &U{ps, pps} // ERROR "&U literal does not escape$" + pu := &U{ps, pps} // ERROR "&U{...} does not escape$" Ssink = pu.SPPi() } func tiSPP() { - s := "cat" // ERROR "moved to heap: s$" + s := "cat" // ERROR "moved to heap: s$" ps := &s pps := &ps - pu := &U{ps, pps} // ERROR "&U literal does not escape$" + pu := &U{ps, pps} // ERROR "&U{...} does not escape$" Ssink = *pu.SPP() } // BAD: need fine-grained analysis to avoid spurious escape of ps func tSP() { - s := "cat" // ERROR "moved to heap: s$" - ps := &s // ERROR "moved to heap: ps$" + s := "cat" // ERROR "moved to heap: s$" + ps := &s // ERROR "moved to heap: ps$" pps := &ps - pu := &U{ps, pps} // ERROR "&U literal does not escape$" + pu := &U{ps, pps} // ERROR "&U{...} does not escape$" Ssink = pu.SP() } @@ -114,72 +114,72 @@ func (v V) UPiSPd() *string { // ERROR "leaking param: v to result ~r0 level=1$" // BAD: need fine-grained (field-sensitive) analysis to avoid spurious escape of all but &s3 func tUPiSPa() { s1 := "ant" - s2 := "bat" // ERROR "moved to heap: s2$" - s3 := "cat" // ERROR "moved to heap: s3$" - s4 := "dog" // ERROR "moved to heap: s4$" - s5 := "emu" // ERROR "moved to heap: s5$" - s6 := "fox" // ERROR "moved to heap: s6$" + s2 := "bat" // ERROR "moved to heap: s2$" + s3 := "cat" // ERROR "moved to heap: s3$" + s4 := "dog" // ERROR "moved to heap: s4$" + s5 := "emu" // ERROR "moved to heap: s5$" + s6 := "fox" // ERROR "moved to heap: s6$" ps2 := &s2 - ps4 := &s4 // ERROR "moved to heap: ps4$" - ps6 := &s6 // ERROR "moved to heap: ps6$" + ps4 := &s4 // ERROR "moved to heap: ps4$" + ps6 := &s6 // ERROR "moved to heap: ps6$" u1 := U{&s1, &ps2} - u2 := &U{&s3, &ps4} // ERROR "&U literal does not escape$" - u3 := &U{&s5, &ps6} // ERROR "&U literal escapes to heap$" - v := &V{u1, u2, &u3} // ERROR "&V literal does not escape$" + u2 := &U{&s3, &ps4} // ERROR "&U{...} does not escape$" + u3 := &U{&s5, &ps6} // ERROR "&U{...} escapes to heap$" + v := &V{u1, u2, &u3} // ERROR "&V{...} does not escape$" Ssink = v.UPiSPa() // Ssink = &s3 (only &s3 really escapes) } // BAD: need fine-grained (field-sensitive) analysis to avoid spurious escape of all but &s3 func tUPiSPb() { s1 := "ant" - s2 := "bat" // ERROR "moved to heap: s2$" - s3 := "cat" // ERROR "moved to heap: s3$" - s4 := "dog" // ERROR "moved to heap: s4$" - s5 := "emu" // ERROR "moved to heap: s5$" - s6 := "fox" // ERROR "moved to heap: s6$" + s2 := "bat" // ERROR "moved to heap: s2$" + s3 := "cat" // ERROR "moved to heap: s3$" + s4 := "dog" // ERROR "moved to heap: s4$" + s5 := "emu" // ERROR "moved to heap: s5$" + s6 := "fox" // ERROR "moved to heap: s6$" ps2 := &s2 - ps4 := &s4 // ERROR "moved to heap: ps4$" - ps6 := &s6 // ERROR "moved to heap: ps6$" + ps4 := &s4 // ERROR "moved to heap: ps4$" + ps6 := &s6 // ERROR "moved to heap: ps6$" u1 := U{&s1, &ps2} - u2 := &U{&s3, &ps4} // ERROR "&U literal does not escape$" - u3 := &U{&s5, &ps6} // ERROR "&U literal escapes to heap$" - v := &V{u1, u2, &u3} // ERROR "&V literal does not escape$" + u2 := &U{&s3, &ps4} // ERROR "&U{...} does not escape$" + u3 := &U{&s5, &ps6} // ERROR "&U{...} escapes to heap$" + v := &V{u1, u2, &u3} // ERROR "&V{...} does not escape$" Ssink = v.UPiSPb() // Ssink = &s3 (only &s3 really escapes) } // BAD: need fine-grained (field-sensitive) analysis to avoid spurious escape of all but &s3 func tUPiSPc() { s1 := "ant" - s2 := "bat" // ERROR "moved to heap: s2$" - s3 := "cat" // ERROR "moved to heap: s3$" - s4 := "dog" // ERROR "moved to heap: s4$" - s5 := "emu" // ERROR "moved to heap: s5$" - s6 := "fox" // ERROR "moved to heap: s6$" + s2 := "bat" // ERROR "moved to heap: s2$" + s3 := "cat" // ERROR "moved to heap: s3$" + s4 := "dog" // ERROR "moved to heap: s4$" + s5 := "emu" // ERROR "moved to heap: s5$" + s6 := "fox" // ERROR "moved to heap: s6$" ps2 := &s2 - ps4 := &s4 // ERROR "moved to heap: ps4$" - ps6 := &s6 // ERROR "moved to heap: ps6$" + ps4 := &s4 // ERROR "moved to heap: ps4$" + ps6 := &s6 // ERROR "moved to heap: ps6$" u1 := U{&s1, &ps2} - u2 := &U{&s3, &ps4} // ERROR "&U literal does not escape$" - u3 := &U{&s5, &ps6} // ERROR "&U literal escapes to heap$" - v := &V{u1, u2, &u3} // ERROR "&V literal does not escape$" + u2 := &U{&s3, &ps4} // ERROR "&U{...} does not escape$" + u3 := &U{&s5, &ps6} // ERROR "&U{...} escapes to heap$" + v := &V{u1, u2, &u3} // ERROR "&V{...} does not escape$" Ssink = v.UPiSPc() // Ssink = &s3 (only &s3 really escapes) } // BAD: need fine-grained (field-sensitive) analysis to avoid spurious escape of all but &s3 func tUPiSPd() { s1 := "ant" - s2 := "bat" // ERROR "moved to heap: s2$" - s3 := "cat" // ERROR "moved to heap: s3$" - s4 := "dog" // ERROR "moved to heap: s4$" - s5 := "emu" // ERROR "moved to heap: s5$" - s6 := "fox" // ERROR "moved to heap: s6$" + s2 := "bat" // ERROR "moved to heap: s2$" + s3 := "cat" // ERROR "moved to heap: s3$" + s4 := "dog" // ERROR "moved to heap: s4$" + s5 := "emu" // ERROR "moved to heap: s5$" + s6 := "fox" // ERROR "moved to heap: s6$" ps2 := &s2 - ps4 := &s4 // ERROR "moved to heap: ps4$" - ps6 := &s6 // ERROR "moved to heap: ps6$" + ps4 := &s4 // ERROR "moved to heap: ps4$" + ps6 := &s6 // ERROR "moved to heap: ps6$" u1 := U{&s1, &ps2} - u2 := &U{&s3, &ps4} // ERROR "&U literal does not escape$" - u3 := &U{&s5, &ps6} // ERROR "&U literal escapes to heap$" - v := &V{u1, u2, &u3} // ERROR "&V literal does not escape$" + u2 := &U{&s3, &ps4} // ERROR "&U{...} does not escape$" + u3 := &U{&s5, &ps6} // ERROR "&U{...} escapes to heap$" + v := &V{u1, u2, &u3} // ERROR "&V{...} does not escape$" Ssink = v.UPiSPd() // Ssink = &s3 (only &s3 really escapes) } @@ -204,16 +204,16 @@ func tUPiSPPia() { s1 := "ant" s2 := "bat" s3 := "cat" - s4 := "dog" // ERROR "moved to heap: s4$" - s5 := "emu" // ERROR "moved to heap: s5$" - s6 := "fox" // ERROR "moved to heap: s6$" + s4 := "dog" // ERROR "moved to heap: s4$" + s5 := "emu" // ERROR "moved to heap: s5$" + s6 := "fox" // ERROR "moved to heap: s6$" ps2 := &s2 ps4 := &s4 - ps6 := &s6 // ERROR "moved to heap: ps6$" + ps6 := &s6 // ERROR "moved to heap: ps6$" u1 := U{&s1, &ps2} - u2 := &U{&s3, &ps4} // ERROR "&U literal does not escape$" - u3 := &U{&s5, &ps6} // ERROR "&U literal does not escape$" - v := &V{u1, u2, &u3} // ERROR "&V literal does not escape$" + u2 := &U{&s3, &ps4} // ERROR "&U{...} does not escape$" + u3 := &U{&s5, &ps6} // ERROR "&U{...} does not escape$" + v := &V{u1, u2, &u3} // ERROR "&V{...} does not escape$" Ssink = v.UPiSPPia() // Ssink = *&ps4 = &s4 (only &s4 really escapes) } @@ -222,16 +222,16 @@ func tUPiSPPib() { s1 := "ant" s2 := "bat" s3 := "cat" - s4 := "dog" // ERROR "moved to heap: s4$" - s5 := "emu" // ERROR "moved to heap: s5$" - s6 := "fox" // ERROR "moved to heap: s6$" + s4 := "dog" // ERROR "moved to heap: s4$" + s5 := "emu" // ERROR "moved to heap: s5$" + s6 := "fox" // ERROR "moved to heap: s6$" ps2 := &s2 ps4 := &s4 - ps6 := &s6 // ERROR "moved to heap: ps6$" + ps6 := &s6 // ERROR "moved to heap: ps6$" u1 := U{&s1, &ps2} - u2 := &U{&s3, &ps4} // ERROR "&U literal does not escape$" - u3 := &U{&s5, &ps6} // ERROR "&U literal does not escape$" - v := &V{u1, u2, &u3} // ERROR "&V literal does not escape$" + u2 := &U{&s3, &ps4} // ERROR "&U{...} does not escape$" + u3 := &U{&s5, &ps6} // ERROR "&U{...} does not escape$" + v := &V{u1, u2, &u3} // ERROR "&V{...} does not escape$" Ssink = v.UPiSPPib() // Ssink = *&ps4 = &s4 (only &s4 really escapes) } @@ -240,16 +240,16 @@ func tUPiSPPic() { s1 := "ant" s2 := "bat" s3 := "cat" - s4 := "dog" // ERROR "moved to heap: s4$" - s5 := "emu" // ERROR "moved to heap: s5$" - s6 := "fox" // ERROR "moved to heap: s6$" + s4 := "dog" // ERROR "moved to heap: s4$" + s5 := "emu" // ERROR "moved to heap: s5$" + s6 := "fox" // ERROR "moved to heap: s6$" ps2 := &s2 ps4 := &s4 - ps6 := &s6 // ERROR "moved to heap: ps6$" + ps6 := &s6 // ERROR "moved to heap: ps6$" u1 := U{&s1, &ps2} - u2 := &U{&s3, &ps4} // ERROR "&U literal does not escape$" - u3 := &U{&s5, &ps6} // ERROR "&U literal does not escape$" - v := &V{u1, u2, &u3} // ERROR "&V literal does not escape$" + u2 := &U{&s3, &ps4} // ERROR "&U{...} does not escape$" + u3 := &U{&s5, &ps6} // ERROR "&U{...} does not escape$" + v := &V{u1, u2, &u3} // ERROR "&V{...} does not escape$" Ssink = v.UPiSPPic() // Ssink = *&ps4 = &s4 (only &s4 really escapes) } @@ -258,16 +258,16 @@ func tUPiSPPid() { s1 := "ant" s2 := "bat" s3 := "cat" - s4 := "dog" // ERROR "moved to heap: s4$" - s5 := "emu" // ERROR "moved to heap: s5$" - s6 := "fox" // ERROR "moved to heap: s6$" + s4 := "dog" // ERROR "moved to heap: s4$" + s5 := "emu" // ERROR "moved to heap: s5$" + s6 := "fox" // ERROR "moved to heap: s6$" ps2 := &s2 ps4 := &s4 - ps6 := &s6 // ERROR "moved to heap: ps6$" + ps6 := &s6 // ERROR "moved to heap: ps6$" u1 := U{&s1, &ps2} - u2 := &U{&s3, &ps4} // ERROR "&U literal does not escape$" - u3 := &U{&s5, &ps6} // ERROR "&U literal does not escape$" - v := &V{u1, u2, &u3} // ERROR "&V literal does not escape$" + u2 := &U{&s3, &ps4} // ERROR "&U{...} does not escape$" + u3 := &U{&s5, &ps6} // ERROR "&U{...} does not escape$" + v := &V{u1, u2, &u3} // ERROR "&V{...} does not escape$" Ssink = v.UPiSPPid() // Ssink = *&ps4 = &s4 (only &s4 really escapes) } @@ -286,13 +286,13 @@ func tUPPiSPPia() { // This test is sensitive to the level cap in function summa s3 := "cat" s4 := "dog" s5 := "emu" - s6 := "fox" // ERROR "moved to heap: s6$" + s6 := "fox" // ERROR "moved to heap: s6$" ps2 := &s2 ps4 := &s4 ps6 := &s6 u1 := U{&s1, &ps2} - u2 := &U{&s3, &ps4} // ERROR "&U literal does not escape$" - u3 := &U{&s5, &ps6} // ERROR "&U literal does not escape$" - v := &V{u1, u2, &u3} // ERROR "&V literal does not escape$" + u2 := &U{&s3, &ps4} // ERROR "&U{...} does not escape$" + u3 := &U{&s5, &ps6} // ERROR "&U{...} does not escape$" + v := &V{u1, u2, &u3} // ERROR "&V{...} does not escape$" Ssink = v.UPPiSPPia() // Ssink = *&ps6 = &s6 (only &s6 really escapes) } diff --git a/test/fixedbugs/issue12006.go b/test/fixedbugs/issue12006.go index c44f2e5547..0a2ef8dad0 100644 --- a/test/fixedbugs/issue12006.go +++ b/test/fixedbugs/issue12006.go @@ -144,7 +144,7 @@ func TFooK2() { a := int32(1) // ERROR "moved to heap: a" b := "cat" c := &a - fs := fakeSlice{3, &[4]interface{}{a, b, c, nil}} // ERROR "a escapes to heap" "b escapes to heap" "&\[4\]interface {} literal does not escape" + fs := fakeSlice{3, &[4]interface{}{a, b, c, nil}} // ERROR "a escapes to heap" "b escapes to heap" "&\[4\]interface {}{...} does not escape" isink = FooK(fs) } @@ -169,6 +169,6 @@ func TFooL2() { a := int32(1) // ERROR "moved to heap: a" b := "cat" c := &a - s := []interface{}{a, b, c} // ERROR "a escapes to heap" "b escapes to heap" "\[\]interface {} literal does not escape" + s := []interface{}{a, b, c} // ERROR "a escapes to heap" "b escapes to heap" "\[\]interface {}{...} does not escape" isink = FooL(s) } diff --git a/test/fixedbugs/issue13799.go b/test/fixedbugs/issue13799.go index 5c57494777..fbdd4c32bc 100644 --- a/test/fixedbugs/issue13799.go +++ b/test/fixedbugs/issue13799.go @@ -162,7 +162,7 @@ func test5(iter int) { var fn *str for i := 0; i < maxI; i++ { // var fn *str // this makes it work, because fn stays off heap - fn = &str{m} // ERROR "&str literal escapes to heap" + fn = &str{m} // ERROR "&str{...} escapes to heap" recur1(0, fn) } @@ -180,7 +180,7 @@ func test6(iter int) { // var fn *str for i := 0; i < maxI; i++ { var fn *str // this makes it work, because fn stays off heap - fn = &str{m} // ERROR "&str literal does not escape" + fn = &str{m} // ERROR "&str{...} does not escape" recur1(0, fn) } diff --git a/test/fixedbugs/issue17645.go b/test/fixedbugs/issue17645.go index af785eae2a..95fcecd1e0 100644 --- a/test/fixedbugs/issue17645.go +++ b/test/fixedbugs/issue17645.go @@ -12,5 +12,5 @@ type Foo struct { func main() { var s []int - var _ string = append(s, Foo{""}) // ERROR "cannot use .. \(type untyped string\) as type int in field value" "cannot use Foo literal \(type Foo\) as type int in append" "cannot use append\(s\, Foo literal\) \(type \[\]int\) as type string in assignment" + var _ string = append(s, Foo{""}) // ERROR "cannot use .. \(type untyped string\) as type int in field value" "cannot use Foo{...} \(type Foo\) as type int in append" "cannot use append\(s\, Foo{...}\) \(type \[\]int\) as type string in assignment" } diff --git a/test/fixedbugs/issue21709.go b/test/fixedbugs/issue21709.go index cc5896ab53..20be10e792 100644 --- a/test/fixedbugs/issue21709.go +++ b/test/fixedbugs/issue21709.go @@ -16,7 +16,7 @@ var N int func F1() { var s S for i := 0; i < N; i++ { - fs := []func(){ // ERROR "\[\]func\(\) literal does not escape" + fs := []func(){ // ERROR "\[\]func\(\){...} does not escape" s.Inc, // ERROR "s.Inc does not escape" } for _, f := range fs { @@ -28,7 +28,7 @@ func F1() { func F2() { var s S for i := 0; i < N; i++ { - for _, f := range []func(){ // ERROR "\[\]func\(\) literal does not escape" + for _, f := range []func(){ // ERROR "\[\]func\(\){...} does not escape" s.Inc, // ERROR "s.Inc does not escape" } { f() diff --git a/test/fixedbugs/issue23732.go b/test/fixedbugs/issue23732.go index be17bf4f61..5e63eb2074 100644 --- a/test/fixedbugs/issue23732.go +++ b/test/fixedbugs/issue23732.go @@ -24,19 +24,19 @@ func main() { _ = Foo{ 1, 2, - 3, // ERROR "too few values in Foo literal" + 3, // ERROR "too few values in Foo{...}" } _ = Foo{ 1, 2, 3, - Bar{"A", "B"}, // ERROR "too many values in Bar literal" + Bar{"A", "B"}, // ERROR "too many values in Bar{...}" } _ = Foo{ 1, 2, - Bar{"A", "B"}, // ERROR "too many values in Bar literal" "too few values in Foo literal" + Bar{"A", "B"}, // ERROR "too many values in Bar{...}" "too few values in Foo{...}" } } diff --git a/test/fixedbugs/issue26855.go b/test/fixedbugs/issue26855.go index d5b95ddbf1..144e4415f7 100644 --- a/test/fixedbugs/issue26855.go +++ b/test/fixedbugs/issue26855.go @@ -20,9 +20,9 @@ type P struct { type T struct{} var _ = S{ - f: &T{}, // ERROR "cannot use &T literal" + f: &T{}, // ERROR "cannot use &T{}" } var _ = P{ - f: T{}, // ERROR "cannot use T literal" + f: T{}, // ERROR "cannot use T{}" } diff --git a/test/fixedbugs/issue30898.go b/test/fixedbugs/issue30898.go index 012d5a2634..b6376d3f9e 100644 --- a/test/fixedbugs/issue30898.go +++ b/test/fixedbugs/issue30898.go @@ -15,5 +15,5 @@ func debugf(format string, args ...interface{}) { // ERROR "can inline debugf" " func bar() { // ERROR "can inline bar" value := 10 - debugf("value is %d", value) // ERROR "inlining call to debugf" "value does not escape" "\[\]interface {} literal does not escape" + debugf("value is %d", value) // ERROR "inlining call to debugf" "value does not escape" "\[\]interface {}{...} does not escape" } diff --git a/test/fixedbugs/issue31573.go b/test/fixedbugs/issue31573.go index c9ea84bbae..005910e00d 100644 --- a/test/fixedbugs/issue31573.go +++ b/test/fixedbugs/issue31573.go @@ -14,18 +14,18 @@ func g() { defer f(new(int), new(int)) // ERROR "... argument does not escape$" "new\(int\) does not escape$" defer f(nil...) - defer f([]*int{}...) // ERROR "\[\]\*int literal does not escape$" - defer f([]*int{new(int)}...) // ERROR "\[\]\*int literal does not escape$" "new\(int\) does not escape$" - defer f([]*int{new(int), new(int)}...) // ERROR "\[\]\*int literal does not escape$" "new\(int\) does not escape$" + defer f([]*int{}...) // ERROR "\[\]\*int{} does not escape$" + defer f([]*int{new(int)}...) // ERROR "\[\]\*int{...} does not escape$" "new\(int\) does not escape$" + defer f([]*int{new(int), new(int)}...) // ERROR "\[\]\*int{...} does not escape$" "new\(int\) does not escape$" go f() go f(new(int)) // ERROR "... argument escapes to heap$" "new\(int\) escapes to heap$" go f(new(int), new(int)) // ERROR "... argument escapes to heap$" "new\(int\) escapes to heap$" go f(nil...) - go f([]*int{}...) // ERROR "\[\]\*int literal escapes to heap$" - go f([]*int{new(int)}...) // ERROR "\[\]\*int literal escapes to heap$" "new\(int\) escapes to heap$" - go f([]*int{new(int), new(int)}...) // ERROR "\[\]\*int literal escapes to heap$" "new\(int\) escapes to heap$" + go f([]*int{}...) // ERROR "\[\]\*int{} escapes to heap$" + go f([]*int{new(int)}...) // ERROR "\[\]\*int{...} escapes to heap$" "new\(int\) escapes to heap$" + go f([]*int{new(int), new(int)}...) // ERROR "\[\]\*int{...} escapes to heap$" "new\(int\) escapes to heap$" for { defer f() @@ -33,17 +33,17 @@ func g() { defer f(new(int), new(int)) // ERROR "... argument escapes to heap$" "new\(int\) escapes to heap$" defer f(nil...) - defer f([]*int{}...) // ERROR "\[\]\*int literal escapes to heap$" - defer f([]*int{new(int)}...) // ERROR "\[\]\*int literal escapes to heap$" "new\(int\) escapes to heap$" - defer f([]*int{new(int), new(int)}...) // ERROR "\[\]\*int literal escapes to heap$" "new\(int\) escapes to heap$" + defer f([]*int{}...) // ERROR "\[\]\*int{} escapes to heap$" + defer f([]*int{new(int)}...) // ERROR "\[\]\*int{...} escapes to heap$" "new\(int\) escapes to heap$" + defer f([]*int{new(int), new(int)}...) // ERROR "\[\]\*int{...} escapes to heap$" "new\(int\) escapes to heap$" go f() go f(new(int)) // ERROR "... argument escapes to heap$" "new\(int\) escapes to heap$" go f(new(int), new(int)) // ERROR "... argument escapes to heap$" "new\(int\) escapes to heap$" go f(nil...) - go f([]*int{}...) // ERROR "\[\]\*int literal escapes to heap$" - go f([]*int{new(int)}...) // ERROR "\[\]\*int literal escapes to heap$" "new\(int\) escapes to heap$" - go f([]*int{new(int), new(int)}...) // ERROR "\[\]\*int literal escapes to heap$" "new\(int\) escapes to heap$" + go f([]*int{}...) // ERROR "\[\]\*int{} escapes to heap$" + go f([]*int{new(int)}...) // ERROR "\[\]\*int{...} escapes to heap$" "new\(int\) escapes to heap$" + go f([]*int{new(int), new(int)}...) // ERROR "\[\]\*int{...} escapes to heap$" "new\(int\) escapes to heap$" } } diff --git a/test/fixedbugs/issue38745.go b/test/fixedbugs/issue38745.go new file mode 100644 index 0000000000..21bd1ff3a7 --- /dev/null +++ b/test/fixedbugs/issue38745.go @@ -0,0 +1,19 @@ +// errorcheck + +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +type t struct{ x int } + +func f1() { + t{}.M() // ERROR "t{}.M undefined \(type t has no field or method M\)" + t{x: 1}.M() // ERROR "t{...}.M undefined \(type t has no field or method M\)" +} + +func f2() (*t, error) { + // BAD: should report undefined error only. + return t{}.M() // ERROR "t{}.M undefined \(type t has no field or method M\)" "not enough arguments to return" +} diff --git a/test/fixedbugs/issue39292.go b/test/fixedbugs/issue39292.go index 1be88653e9..7dac2e5fc6 100644 --- a/test/fixedbugs/issue39292.go +++ b/test/fixedbugs/issue39292.go @@ -12,18 +12,18 @@ func (t) f() { } func x() { - x := t{}.f // ERROR "t literal.f escapes to heap" + x := t{}.f // ERROR "t{}.f escapes to heap" x() } func y() { var i int // ERROR "moved to heap: i" - y := (&t{&i}).f // ERROR "\(&t literal\).f escapes to heap" "&t literal escapes to heap" + y := (&t{&i}).f // ERROR "\(&t{...}\).f escapes to heap" "&t{...} escapes to heap" y() } func z() { var i int // ERROR "moved to heap: i" - z := t{&i}.f // ERROR "t literal.f escapes to heap" + z := t{&i}.f // ERROR "t{...}.f escapes to heap" z() } diff --git a/test/fixedbugs/issue41247.go b/test/fixedbugs/issue41247.go index 2df919c9e6..b8bd81274f 100644 --- a/test/fixedbugs/issue41247.go +++ b/test/fixedbugs/issue41247.go @@ -7,5 +7,5 @@ package p func f() [2]int { - return [...]int{2: 0} // ERROR "cannot use \[\.\.\.\]int literal \(type \[3\]int\)" + return [...]int{2: 0} // ERROR "cannot use \[\.\.\.\]int{...} \(type \[3\]int\)" } diff --git a/test/fixedbugs/issue7921.go b/test/fixedbugs/issue7921.go index a8efc8dd9e..5dce557ca3 100644 --- a/test/fixedbugs/issue7921.go +++ b/test/fixedbugs/issue7921.go @@ -18,12 +18,12 @@ func bufferNotEscape() string { // can be stack-allocated. var b bytes.Buffer b.WriteString("123") - b.Write([]byte{'4'}) // ERROR "\[\]byte literal does not escape$" + b.Write([]byte{'4'}) // ERROR "\[\]byte{...} does not escape$" return b.String() // ERROR "inlining call to bytes.\(\*Buffer\).String$" "string\(bytes.b.buf\[bytes.b.off:\]\) escapes to heap$" } func bufferNoEscape2(xs []string) int { // ERROR "xs does not escape$" - b := bytes.NewBuffer(make([]byte, 0, 64)) // ERROR "&bytes.Buffer literal does not escape$" "make\(\[\]byte, 0, 64\) does not escape$" "inlining call to bytes.NewBuffer$" + b := bytes.NewBuffer(make([]byte, 0, 64)) // ERROR "&bytes.Buffer{...} does not escape$" "make\(\[\]byte, 0, 64\) does not escape$" "inlining call to bytes.NewBuffer$" for _, x := range xs { b.WriteString(x) } @@ -31,7 +31,7 @@ func bufferNoEscape2(xs []string) int { // ERROR "xs does not escape$" } func bufferNoEscape3(xs []string) string { // ERROR "xs does not escape$" - b := bytes.NewBuffer(make([]byte, 0, 64)) // ERROR "&bytes.Buffer literal does not escape$" "make\(\[\]byte, 0, 64\) does not escape$" "inlining call to bytes.NewBuffer$" + b := bytes.NewBuffer(make([]byte, 0, 64)) // ERROR "&bytes.Buffer{...} does not escape$" "make\(\[\]byte, 0, 64\) does not escape$" "inlining call to bytes.NewBuffer$" for _, x := range xs { b.WriteString(x) b.WriteByte(',') @@ -41,13 +41,13 @@ func bufferNoEscape3(xs []string) string { // ERROR "xs does not escape$" func bufferNoEscape4() []byte { var b bytes.Buffer - b.Grow(64) // ERROR "bufferNoEscape4 ignoring self-assignment in bytes.b.buf = bytes.b.buf\[:bytes.m·3\]$" "inlining call to bytes.\(\*Buffer\).Grow$" + b.Grow(64) // ERROR "bufferNoEscape4 ignoring self-assignment in bytes.b.buf = bytes.b.buf\[:bytes.m·3\]$" "inlining call to bytes.\(\*Buffer\).Grow$" useBuffer(&b) return b.Bytes() // ERROR "inlining call to bytes.\(\*Buffer\).Bytes$" } func bufferNoEscape5() { // ERROR "can inline bufferNoEscape5$" - b := bytes.NewBuffer(make([]byte, 0, 128)) // ERROR "&bytes.Buffer literal does not escape$" "make\(\[\]byte, 0, 128\) does not escape$" "inlining call to bytes.NewBuffer$" + b := bytes.NewBuffer(make([]byte, 0, 128)) // ERROR "&bytes.Buffer{...} does not escape$" "make\(\[\]byte, 0, 128\) does not escape$" "inlining call to bytes.NewBuffer$" useBuffer(b) } diff --git a/test/inline_variadic.go b/test/inline_variadic.go index fcc1cff1e8..687048a192 100644 --- a/test/inline_variadic.go +++ b/test/inline_variadic.go @@ -14,6 +14,6 @@ func head(xs ...string) string { // ERROR "can inline head" "leaking param: xs t } func f() string { // ERROR "can inline f" - x := head("hello", "world") // ERROR "inlining call to head" "\[\]string literal does not escape" + x := head("hello", "world") // ERROR "inlining call to head" "\[\]string{...} does not escape" return x } -- cgit v1.3 From 806f478499b57c5167fb5301101961b7563903d2 Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Wed, 9 Sep 2020 16:25:48 +0700 Subject: cmd/compile: don't report not enough args error if call is undefined Fixes #38745 Change-Id: I2fbd8b512a8cf911b81a087162c74416116efea5 Reviewed-on: https://go-review.googlesource.com/c/go/+/253678 Run-TryBot: Cuong Manh Le TryBot-Result: Gobot Gobot Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/gc/typecheck.go | 2 +- test/ddd1.go | 2 +- test/fixedbugs/issue38745.go | 3 +-- 3 files changed, 3 insertions(+), 4 deletions(-) (limited to 'src/cmd/compile/internal') diff --git a/src/cmd/compile/internal/gc/typecheck.go b/src/cmd/compile/internal/gc/typecheck.go index dec4b96fc4..fb169cfec8 100644 --- a/src/cmd/compile/internal/gc/typecheck.go +++ b/src/cmd/compile/internal/gc/typecheck.go @@ -2667,7 +2667,7 @@ func typecheckaste(op Op, call *Node, isddd bool, tstruct *types.Type, nl Nodes, return notenough: - if n == nil || !n.Diag() { + if n == nil || (!n.Diag() && n.Type != nil) { details := errorDetails(nl, tstruct, isddd) if call != nil { // call is the expression being called, not the overall call. diff --git a/test/ddd1.go b/test/ddd1.go index 2c7e83e374..9857814648 100644 --- a/test/ddd1.go +++ b/test/ddd1.go @@ -29,7 +29,7 @@ var ( _ = sum(tuple()) _ = sum(tuple()...) // ERROR "multiple-value" _ = sum3(tuple()) - _ = sum3(tuple()...) // ERROR "multiple-value" "not enough" + _ = sum3(tuple()...) // ERROR "multiple-value" ) type T []T diff --git a/test/fixedbugs/issue38745.go b/test/fixedbugs/issue38745.go index 21bd1ff3a7..83a3bc6fad 100644 --- a/test/fixedbugs/issue38745.go +++ b/test/fixedbugs/issue38745.go @@ -14,6 +14,5 @@ func f1() { } func f2() (*t, error) { - // BAD: should report undefined error only. - return t{}.M() // ERROR "t{}.M undefined \(type t has no field or method M\)" "not enough arguments to return" + return t{}.M() // ERROR "t{}.M undefined \(type t has no field or method M\)" } -- cgit v1.3 From 1f4521669416a2e14fb0b84481447f4a93f19878 Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Sat, 12 Sep 2020 01:57:27 +0700 Subject: cmd/compile: attach OVARLIVE nodes to OCALLxxx So we can insert theses OVARLIVE nodes right after OpStaticCall in SSA. This helps fixing issue that unsafe-uintptr arguments are not kept alive during return statement, or can be kept alive longer than expected. Fixes #24491 Change-Id: Ic04a5d1bbb5c90dcfae65bd95cdd1da393a66800 Reviewed-on: https://go-review.googlesource.com/c/go/+/254397 Run-TryBot: Cuong Manh Le TryBot-Result: Gobot Gobot Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/gc/order.go | 14 +++------ src/cmd/compile/internal/gc/ssa.go | 2 ++ src/cmd/compile/internal/gc/syntax.go | 4 +-- test/fixedbugs/issue24491.go | 45 ----------------------------- test/fixedbugs/issue24491a.go | 54 +++++++++++++++++++++++++++++++++++ test/fixedbugs/issue24491b.go | 46 +++++++++++++++++++++++++++++ 6 files changed, 107 insertions(+), 58 deletions(-) delete mode 100644 test/fixedbugs/issue24491.go create mode 100644 test/fixedbugs/issue24491a.go create mode 100644 test/fixedbugs/issue24491b.go (limited to 'src/cmd/compile/internal') diff --git a/src/cmd/compile/internal/gc/order.go b/src/cmd/compile/internal/gc/order.go index 412f073a8d..341f4ee66f 100644 --- a/src/cmd/compile/internal/gc/order.go +++ b/src/cmd/compile/internal/gc/order.go @@ -288,20 +288,13 @@ func (o *Order) popTemp(mark ordermarker) { o.temp = o.temp[:mark] } -// cleanTempNoPop emits VARKILL and if needed VARLIVE instructions -// to *out for each temporary above the mark on the temporary stack. +// cleanTempNoPop emits VARKILL instructions to *out +// for each temporary above the mark on the temporary stack. // It does not pop the temporaries from the stack. func (o *Order) cleanTempNoPop(mark ordermarker) []*Node { var out []*Node for i := len(o.temp) - 1; i >= int(mark); i-- { n := o.temp[i] - if n.Name.Keepalive() { - n.Name.SetKeepalive(false) - n.Name.SetAddrtaken(true) // ensure SSA keeps the n variable - live := nod(OVARLIVE, n, nil) - live = typecheck(live, ctxStmt) - out = append(out, live) - } kill := nod(OVARKILL, n, nil) kill = typecheck(kill, ctxStmt) out = append(out, kill) @@ -500,8 +493,9 @@ func (o *Order) call(n *Node) { // still alive when we pop the temp stack. if arg.Op == OCONVNOP && arg.Left.Type.IsUnsafePtr() { x := o.copyExpr(arg.Left, arg.Left.Type, false) - x.Name.SetKeepalive(true) arg.Left = x + x.Name.SetAddrtaken(true) // ensure SSA keeps the x variable + n.Nbody.Append(typecheck(nod(OVARLIVE, x, nil), ctxStmt)) n.SetNeedsWrapper(true) } } diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go index 89644cd3f2..3bdb5b0b9f 100644 --- a/src/cmd/compile/internal/gc/ssa.go +++ b/src/cmd/compile/internal/gc/ssa.go @@ -4498,6 +4498,8 @@ func (s *state) call(n *Node, k callKind) *ssa.Value { call.AuxInt = stksize // Call operations carry the argsize of the callee along with them } s.vars[&memVar] = call + // Insert OVARLIVE nodes + s.stmtList(n.Nbody) // Finish block for defers if k == callDefer || k == callDeferStack { diff --git a/src/cmd/compile/internal/gc/syntax.go b/src/cmd/compile/internal/gc/syntax.go index 5580f789c5..9592b7484c 100644 --- a/src/cmd/compile/internal/gc/syntax.go +++ b/src/cmd/compile/internal/gc/syntax.go @@ -374,7 +374,6 @@ const ( nameReadonly nameByval // is the variable captured by value or by reference nameNeedzero // if it contains pointers, needs to be zeroed on function entry - nameKeepalive // mark value live across unknown assembly call nameAutoTemp // is the variable a temporary (implies no dwarf info. reset if escapes to heap) nameUsed // for variable declared and not used error nameIsClosureVar // PAUTOHEAP closure pseudo-variable; original at n.Name.Defn @@ -391,7 +390,6 @@ func (n *Name) Captured() bool { return n.flags&nameCaptured != 0 } func (n *Name) Readonly() bool { return n.flags&nameReadonly != 0 } func (n *Name) Byval() bool { return n.flags&nameByval != 0 } func (n *Name) Needzero() bool { return n.flags&nameNeedzero != 0 } -func (n *Name) Keepalive() bool { return n.flags&nameKeepalive != 0 } func (n *Name) AutoTemp() bool { return n.flags&nameAutoTemp != 0 } func (n *Name) Used() bool { return n.flags&nameUsed != 0 } func (n *Name) IsClosureVar() bool { return n.flags&nameIsClosureVar != 0 } @@ -407,7 +405,6 @@ func (n *Name) SetCaptured(b bool) { n.flags.set(nameCaptured, b) } func (n *Name) SetReadonly(b bool) { n.flags.set(nameReadonly, b) } func (n *Name) SetByval(b bool) { n.flags.set(nameByval, b) } func (n *Name) SetNeedzero(b bool) { n.flags.set(nameNeedzero, b) } -func (n *Name) SetKeepalive(b bool) { n.flags.set(nameKeepalive, b) } func (n *Name) SetAutoTemp(b bool) { n.flags.set(nameAutoTemp, b) } func (n *Name) SetUsed(b bool) { n.flags.set(nameUsed, b) } func (n *Name) SetIsClosureVar(b bool) { n.flags.set(nameIsClosureVar, b) } @@ -707,6 +704,7 @@ const ( // Prior to walk, they are: Left(List), where List is all regular arguments. // After walk, List is a series of assignments to temporaries, // and Rlist is an updated set of arguments. + // Nbody is all OVARLIVE nodes that are attached to OCALLxxx. // TODO(josharian/khr): Use Ninit instead of List for the assignments to temporaries. See CL 114797. OCALLFUNC // Left(List/Rlist) (function call f(args)) OCALLMETH // Left(List/Rlist) (direct method call x.Method(args)) diff --git a/test/fixedbugs/issue24491.go b/test/fixedbugs/issue24491.go deleted file mode 100644 index 4703368793..0000000000 --- a/test/fixedbugs/issue24491.go +++ /dev/null @@ -1,45 +0,0 @@ -// run - -// Copyright 2020 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// This test makes sure unsafe-uintptr arguments are handled correctly. - -package main - -import ( - "runtime" - "unsafe" -) - -var done = make(chan bool, 1) - -func setup() unsafe.Pointer { - s := "ok" - runtime.SetFinalizer(&s, func(p *string) { *p = "FAIL" }) - return unsafe.Pointer(&s) -} - -//go:noinline -//go:uintptrescapes -func test(s string, p uintptr) { - runtime.GC() - if *(*string)(unsafe.Pointer(p)) != "ok" { - panic(s + " return unexpected result") - } - done <- true -} - -func main() { - test("normal", uintptr(setup())) - <-done - - go test("go", uintptr(setup())) - <-done - - func() { - defer test("defer", uintptr(setup())) - }() - <-done -} diff --git a/test/fixedbugs/issue24491a.go b/test/fixedbugs/issue24491a.go new file mode 100644 index 0000000000..148134d187 --- /dev/null +++ b/test/fixedbugs/issue24491a.go @@ -0,0 +1,54 @@ +// run + +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// This test makes sure unsafe-uintptr arguments are handled correctly. + +package main + +import ( + "runtime" + "unsafe" +) + +var done = make(chan bool, 1) + +func setup() unsafe.Pointer { + s := "ok" + runtime.SetFinalizer(&s, func(p *string) { *p = "FAIL" }) + return unsafe.Pointer(&s) +} + +//go:noinline +//go:uintptrescapes +func test(s string, p uintptr) int { + runtime.GC() + if *(*string)(unsafe.Pointer(p)) != "ok" { + panic(s + " return unexpected result") + } + done <- true + return 0 +} + +//go:noinline +func f() int { + return test("return", uintptr(setup())) +} + +func main() { + test("normal", uintptr(setup())) + <-done + + go test("go", uintptr(setup())) + <-done + + func() { + defer test("defer", uintptr(setup())) + }() + <-done + + f() + <-done +} diff --git a/test/fixedbugs/issue24491b.go b/test/fixedbugs/issue24491b.go new file mode 100644 index 0000000000..5f4a2f233e --- /dev/null +++ b/test/fixedbugs/issue24491b.go @@ -0,0 +1,46 @@ +// run + +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// This test makes sure unsafe-uintptr arguments are not +// kept alive longer than expected. + +package main + +import ( + "runtime" + "sync/atomic" + "unsafe" +) + +var done uint32 + +func setup() unsafe.Pointer { + s := "ok" + runtime.SetFinalizer(&s, func(p *string) { atomic.StoreUint32(&done, 1) }) + return unsafe.Pointer(&s) +} + +//go:noinline +//go:uintptrescapes +func before(p uintptr) int { + runtime.GC() + if atomic.LoadUint32(&done) != 0 { + panic("GC early") + } + return 0 +} + +func after() int { + runtime.GC() + if atomic.LoadUint32(&done) == 0 { + panic("GC late") + } + return 0 +} + +func main() { + _ = before(uintptr(setup())) + after() +} -- cgit v1.3 From 5f1b12bfbeb04ca6dbecbf064f5e5a42d8ba4b5a Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Sat, 12 Sep 2020 07:19:22 +0700 Subject: cmd/compile: remove nodeNeedsWrapper flag CL 254397 attached OVARLIVE nodes to OCALLxxx nodes Nbody. The NeedsWrapper flag is now redundant with n.Nbody.Len() > 0 condition, so use that condition instead and remove the flag. Passes toolstash-check. Change-Id: Iebc3e674d3c0040a876ca4be05025943d2b4fb31 Reviewed-on: https://go-review.googlesource.com/c/go/+/254398 Run-TryBot: Cuong Manh Le TryBot-Result: Gobot Gobot Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/gc/order.go | 1 - src/cmd/compile/internal/gc/syntax.go | 41 +++++++++++------------------------ src/cmd/compile/internal/gc/walk.go | 7 ++++-- 3 files changed, 18 insertions(+), 31 deletions(-) (limited to 'src/cmd/compile/internal') diff --git a/src/cmd/compile/internal/gc/order.go b/src/cmd/compile/internal/gc/order.go index 341f4ee66f..75da154fe2 100644 --- a/src/cmd/compile/internal/gc/order.go +++ b/src/cmd/compile/internal/gc/order.go @@ -496,7 +496,6 @@ func (o *Order) call(n *Node) { arg.Left = x x.Name.SetAddrtaken(true) // ensure SSA keeps the x variable n.Nbody.Append(typecheck(nod(OVARLIVE, x, nil), ctxStmt)) - n.SetNeedsWrapper(true) } } diff --git a/src/cmd/compile/internal/gc/syntax.go b/src/cmd/compile/internal/gc/syntax.go index 9592b7484c..14d2710da4 100644 --- a/src/cmd/compile/internal/gc/syntax.go +++ b/src/cmd/compile/internal/gc/syntax.go @@ -141,20 +141,19 @@ const ( nodeInitorder, _ // tracks state during init1; two bits _, _ // second nodeInitorder bit _, nodeHasBreak - _, nodeNoInline // used internally by inliner to indicate that a function call should not be inlined; set for OCALLFUNC and OCALLMETH only - _, nodeImplicit // implicit OADDR or ODEREF; ++/-- statement represented as OASOP; or ANDNOT lowered to OAND - _, nodeIsDDD // is the argument variadic - _, nodeDiag // already printed error about this - _, nodeColas // OAS resulting from := - _, nodeNonNil // guaranteed to be non-nil - _, nodeTransient // storage can be reused immediately after this statement - _, nodeBounded // bounds check unnecessary - _, nodeHasCall // expression contains a function call - _, nodeLikely // if statement condition likely - _, nodeHasVal // node.E contains a Val - _, nodeHasOpt // node.E contains an Opt - _, nodeEmbedded // ODCLFIELD embedded type - _, nodeNeedsWrapper // OCALLxxx node that needs to be wrapped + _, nodeNoInline // used internally by inliner to indicate that a function call should not be inlined; set for OCALLFUNC and OCALLMETH only + _, nodeImplicit // implicit OADDR or ODEREF; ++/-- statement represented as OASOP; or ANDNOT lowered to OAND + _, nodeIsDDD // is the argument variadic + _, nodeDiag // already printed error about this + _, nodeColas // OAS resulting from := + _, nodeNonNil // guaranteed to be non-nil + _, nodeTransient // storage can be reused immediately after this statement + _, nodeBounded // bounds check unnecessary + _, nodeHasCall // expression contains a function call + _, nodeLikely // if statement condition likely + _, nodeHasVal // node.E contains a Val + _, nodeHasOpt // node.E contains an Opt + _, nodeEmbedded // ODCLFIELD embedded type ) func (n *Node) Class() Class { return Class(n.flags.get3(nodeClass)) } @@ -287,20 +286,6 @@ func (n *Node) SetIota(x int64) { n.Xoffset = x } -func (n *Node) NeedsWrapper() bool { - return n.flags&nodeNeedsWrapper != 0 -} - -// SetNeedsWrapper indicates that OCALLxxx node needs to be wrapped by a closure. -func (n *Node) SetNeedsWrapper(b bool) { - switch n.Op { - case OCALLFUNC, OCALLMETH, OCALLINTER: - default: - Fatalf("Node.SetNeedsWrapper %v", n.Op) - } - n.flags.set(nodeNeedsWrapper, b) -} - // mayBeShared reports whether n may occur in multiple places in the AST. // Extra care must be taken when mutating such a node. func (n *Node) mayBeShared() bool { diff --git a/src/cmd/compile/internal/gc/walk.go b/src/cmd/compile/internal/gc/walk.go index 361de7e0f3..2d29366880 100644 --- a/src/cmd/compile/internal/gc/walk.go +++ b/src/cmd/compile/internal/gc/walk.go @@ -231,12 +231,15 @@ func walkstmt(n *Node) *Node { case OCOPY: n.Left = copyany(n.Left, &n.Ninit, true) - default: - if n.Left.NeedsWrapper() { + case OCALLFUNC, OCALLMETH, OCALLINTER: + if n.Left.Nbody.Len() > 0 { n.Left = wrapCall(n.Left, &n.Ninit) } else { n.Left = walkexpr(n.Left, &n.Ninit) } + + default: + n.Left = walkexpr(n.Left, &n.Ninit) } case OFOR, OFORUNTIL: -- cgit v1.3 From 237410547bb81ae3c58e9c5bf0cf59edc989e243 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Mon, 14 Sep 2020 12:53:36 -0700 Subject: cmd/compile: better dclcontext handling in func{hdr,body} funchdr and funcbody currently assume that either (1) Curfn == nil && dclcontext == PEXTERN, or (2) Curfn != nil && dclcontext == PAUTO. This is a reasonable assumption during parsing. However, these functions end up getting used in other contexts, and not all callers are so disciplined about Curfn/dclcontext handling. This CL changes them to save/restore arbitrary Curfn/dclcontext pairs instead. This is necessary for the followup CL, which pushes fninit earlier. Otherwise, Curfn/dclcontext fall out of sync, and funchdr panics. Passes toolstash-check. Updates #33485. Change-Id: I19b1be23db1bad6475345ae5c81bbdc66291a3a7 Reviewed-on: https://go-review.googlesource.com/c/go/+/254838 Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Keith Randall Trust: Matthew Dempsky --- src/cmd/compile/internal/gc/dcl.go | 28 +++++++++++++--------------- src/cmd/compile/internal/gc/main.go | 3 +++ 2 files changed, 16 insertions(+), 15 deletions(-) (limited to 'src/cmd/compile/internal') diff --git a/src/cmd/compile/internal/gc/dcl.go b/src/cmd/compile/internal/gc/dcl.go index 69eb13f607..a362d1a643 100644 --- a/src/cmd/compile/internal/gc/dcl.go +++ b/src/cmd/compile/internal/gc/dcl.go @@ -382,14 +382,11 @@ func ifacedcl(n *Node) { // returns in auto-declaration context. func funchdr(n *Node) { // change the declaration context from extern to auto - if Curfn == nil && dclcontext != PEXTERN { - Fatalf("funchdr: dclcontext = %d", dclcontext) - } - + funcStack = append(funcStack, funcStackEnt{Curfn, dclcontext}) + Curfn = n dclcontext = PAUTO + types.Markdcl() - funcstack = append(funcstack, Curfn) - Curfn = n if n.Func.Nname != nil { funcargs(n.Func.Nname.Name.Param.Ntype) @@ -497,21 +494,22 @@ func funcarg2(f *types.Field, ctxt Class) { declare(n, ctxt) } -var funcstack []*Node // stack of previous values of Curfn +var funcStack []funcStackEnt // stack of previous values of Curfn/dclcontext + +type funcStackEnt struct { + curfn *Node + dclcontext Class +} // finish the body. // called in auto-declaration context. // returns in extern-declaration context. func funcbody() { - // change the declaration context from auto to extern - if dclcontext != PAUTO { - Fatalf("funcbody: unexpected dclcontext %d", dclcontext) - } + // change the declaration context from auto to previous context types.Popdcl() - funcstack, Curfn = funcstack[:len(funcstack)-1], funcstack[len(funcstack)-1] - if Curfn == nil { - dclcontext = PEXTERN - } + var e funcStackEnt + funcStack, e = funcStack[:len(funcStack)-1], funcStack[len(funcStack)-1] + Curfn, dclcontext = e.curfn, e.dclcontext } // structs, functions, and methods. diff --git a/src/cmd/compile/internal/gc/main.go b/src/cmd/compile/internal/gc/main.go index eedfc4bb25..9bce6cf8cb 100644 --- a/src/cmd/compile/internal/gc/main.go +++ b/src/cmd/compile/internal/gc/main.go @@ -809,6 +809,9 @@ func Main(archInit func(*Arch)) { } } + if len(funcStack) != 0 { + Fatalf("funcStack is non-empty: %v", len(funcStack)) + } if len(compilequeue) != 0 { Fatalf("%d uncompiled functions", len(compilequeue)) } -- cgit v1.3 From f4936d09fd5a1fff890d63ee2ab9543243dc4da6 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Mon, 14 Sep 2020 12:56:37 -0700 Subject: cmd/compile: call fninit earlier This allows the global initializers function to go through normal mid-end optimizations (e.g., inlining, escape analysis) like any other function. Updates #33485. Change-Id: I9bcfe98b8628d1aca09b4c238d8d3b74c69010a5 Reviewed-on: https://go-review.googlesource.com/c/go/+/254839 Reviewed-by: Keith Randall Trust: Matthew Dempsky --- src/cmd/compile/internal/gc/init.go | 8 +++----- src/cmd/compile/internal/gc/main.go | 6 ++---- test/inline.go | 2 +- 3 files changed, 6 insertions(+), 10 deletions(-) (limited to 'src/cmd/compile/internal') diff --git a/src/cmd/compile/internal/gc/init.go b/src/cmd/compile/internal/gc/init.go index 94cbcf9846..ec9cc4bddc 100644 --- a/src/cmd/compile/internal/gc/init.go +++ b/src/cmd/compile/internal/gc/init.go @@ -59,7 +59,7 @@ func fninit(n []*Node) { Curfn = fn typecheckslice(nf, ctxStmt) Curfn = nil - funccompile(fn) + xtop = append(xtop, fn) fns = append(fns, initializers.Linksym()) } if dummyInitFn.Func.Dcl != nil { @@ -68,16 +68,14 @@ func fninit(n []*Node) { // something's weird if we get here. Fatalf("dummyInitFn still has declarations") } + dummyInitFn = nil // Record user init functions. for i := 0; i < renameinitgen; i++ { s := lookupN("init.", i) fn := asNode(s.Def).Name.Defn // Skip init functions with empty bodies. - // noder.go doesn't allow external init functions, and - // order.go has already removed any OEMPTY nodes, so - // checking Len() == 0 is sufficient here. - if fn.Nbody.Len() == 0 { + if fn.Nbody.Len() == 1 && fn.Nbody.First().Op == OEMPTY { continue } fns = append(fns, s.Linksym()) diff --git a/src/cmd/compile/internal/gc/main.go b/src/cmd/compile/internal/gc/main.go index 9bce6cf8cb..8783cb4e46 100644 --- a/src/cmd/compile/internal/gc/main.go +++ b/src/cmd/compile/internal/gc/main.go @@ -642,6 +642,8 @@ func Main(archInit func(*Arch)) { errorexit() } + fninit(xtop) + // Phase 4: Decide how to capture closed variables. // This needs to run before escape analysis, // because variables captured by value do not escape. @@ -751,10 +753,6 @@ func Main(archInit func(*Arch)) { } timings.AddEvent(fcount, "funcs") - if nsavederrors+nerrors == 0 { - fninit(xtop) - } - compileFunctions() if nowritebarrierrecCheck != nil { diff --git a/test/inline.go b/test/inline.go index 0b3ad55d46..1c5c1bc8d3 100644 --- a/test/inline.go +++ b/test/inline.go @@ -50,7 +50,7 @@ func j(x int) int { // ERROR "can inline j" } } -var somethingWrong error = errors.New("something went wrong") +var somethingWrong error = errors.New("something went wrong") // ERROR "can inline init" "inlining call to errors.New" "errors.errorString.* escapes to heap" // local closures can be inlined func l(x, y int) (int, int, error) { -- cgit v1.3 From d20298e1c7d1df794a11ce7768e027c6759df2a4 Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Mon, 14 Sep 2020 10:38:45 +0700 Subject: cmd/compile: make funccompile non-reentrant Currently, there's awkward reentrancy issue with funccompile: funccompile -> compile -> dtypesym -> geneq/genhash/genwrapper -> funccompile Though it's not a problem at this moment, some attempts by @mdempsky to move order/walk/instrument into buildssa was failed, due to SSA cache corruption. This commit fixes that reentrancy issue, by making generated functions to be pumped through the same compile workqueue that normal functions are compiled. We do this by adding them to xtop, instead of calling funccompile directly in geneq/genhash/genwrapper. In dumpdata, we look for uncompiled functions in xtop instead of compilequeue, then finish compiling them. Updates #38463 Fixes #33485 Change-Id: Ic9f0ce45b56ae2ff3862f17fd979253ddc144bb5 Reviewed-on: https://go-review.googlesource.com/c/go/+/254617 Run-TryBot: Cuong Manh Le Reviewed-by: Matthew Dempsky TryBot-Result: Go Bot Trust: Keith Randall Trust: Cuong Manh Le --- src/cmd/compile/internal/gc/alg.go | 4 ++-- src/cmd/compile/internal/gc/obj.go | 26 +++++++++++++++++++++++++- src/cmd/compile/internal/gc/subr.go | 2 +- 3 files changed, 28 insertions(+), 4 deletions(-) (limited to 'src/cmd/compile/internal') diff --git a/src/cmd/compile/internal/gc/alg.go b/src/cmd/compile/internal/gc/alg.go index c9d71ea00b..6302b88f59 100644 --- a/src/cmd/compile/internal/gc/alg.go +++ b/src/cmd/compile/internal/gc/alg.go @@ -392,7 +392,7 @@ func genhash(t *types.Type) *obj.LSym { } fn.Func.SetNilCheckDisabled(true) - funccompile(fn) + xtop = append(xtop, fn) // Build closure. It doesn't close over any variables, so // it contains just the function pointer. @@ -754,7 +754,7 @@ func geneq(t *types.Type) *obj.LSym { // neither of which can be nil, and our comparisons // are shallow. fn.Func.SetNilCheckDisabled(true) - funccompile(fn) + xtop = append(xtop, fn) // Generate a closure which points at the function we just generated. dsymptr(closure, 0, sym.Linksym(), 0) diff --git a/src/cmd/compile/internal/gc/obj.go b/src/cmd/compile/internal/gc/obj.go index af5037c5a8..b55331a948 100644 --- a/src/cmd/compile/internal/gc/obj.go +++ b/src/cmd/compile/internal/gc/obj.go @@ -113,12 +113,16 @@ func dumpCompilerObj(bout *bio.Writer) { func dumpdata() { externs := len(externdcl) + xtops := len(xtop) dumpglobls() addptabs() + exportlistLen := len(exportlist) addsignats(externdcl) dumpsignats() dumptabs() + ptabsLen := len(ptabs) + itabsLen := len(itabs) dumpimportstrings() dumpbasictypes() @@ -129,9 +133,19 @@ func dumpdata() { // number of types in a finite amount of code. // In the typical case, we loop 0 or 1 times. // It was not until issue 24761 that we found any code that required a loop at all. - for len(compilequeue) > 0 { + for { + for i := xtops; i < len(xtop); i++ { + n := xtop[i] + if n.Op == ODCLFUNC { + funccompile(n) + } + } + xtops = len(xtop) compileFunctions() dumpsignats() + if xtops == len(xtop) { + break + } } // Dump extra globals. @@ -149,6 +163,16 @@ func dumpdata() { } addGCLocals() + + if exportlistLen != len(exportlist) { + Fatalf("exportlist changed after compile functions loop") + } + if ptabsLen != len(ptabs) { + Fatalf("ptabs changed after compile functions loop") + } + if itabsLen != len(itabs) { + Fatalf("itabs changed after compile functions loop") + } } func dumpLinkerObj(bout *bio.Writer) { diff --git a/src/cmd/compile/internal/gc/subr.go b/src/cmd/compile/internal/gc/subr.go index d3ba53ff0c..5a5833d19f 100644 --- a/src/cmd/compile/internal/gc/subr.go +++ b/src/cmd/compile/internal/gc/subr.go @@ -1615,7 +1615,7 @@ func genwrapper(rcvr *types.Type, method *types.Field, newnam *types.Sym) { escapeFuncs([]*Node{fn}, false) Curfn = nil - funccompile(fn) + xtop = append(xtop, fn) } func paramNnames(ft *types.Type) []*Node { -- cgit v1.3 From ea33523877e4c7a136f2db94a8b5bc4e40220be2 Mon Sep 17 00:00:00 2001 From: Xiangdong Ji Date: Tue, 8 Sep 2020 09:55:20 +0000 Subject: cmd/compile: rewrite some ARM64 rules to use typed aux Passes toolstash-check -all. Change-Id: I7ec36bc048f3031c8201107e6fc5d1257271dbf1 Reviewed-on: https://go-review.googlesource.com/c/go/+/234379 Run-TryBot: Alberto Donizetti TryBot-Result: Go Bot Trust: Alberto Donizetti Reviewed-by: Keith Randall --- src/cmd/compile/internal/ssa/gen/ARM64.rules | 496 +++++++-------- src/cmd/compile/internal/ssa/rewriteARM64.go | 912 +++++++++++++-------------- 2 files changed, 704 insertions(+), 704 deletions(-) (limited to 'src/cmd/compile/internal') diff --git a/src/cmd/compile/internal/ssa/gen/ARM64.rules b/src/cmd/compile/internal/ssa/gen/ARM64.rules index 311067e87a..c4a3532632 100644 --- a/src/cmd/compile/internal/ssa/gen/ARM64.rules +++ b/src/cmd/compile/internal/ssa/gen/ARM64.rules @@ -1116,280 +1116,280 @@ // if a register move has only 1 use, just use the same register without emitting instruction // MOVDnop doesn't emit instruction, only for ensuring the type. -(MOVDreg x) && x.Uses == 1 -> (MOVDnop x) +(MOVDreg x) && x.Uses == 1 => (MOVDnop x) // fold constant into arithmatic ops -(ADD x (MOVDconst [c])) -> (ADDconst [c] x) -(SUB x (MOVDconst [c])) -> (SUBconst [c] x) -(AND x (MOVDconst [c])) -> (ANDconst [c] x) -(OR x (MOVDconst [c])) -> (ORconst [c] x) -(XOR x (MOVDconst [c])) -> (XORconst [c] x) -(TST x (MOVDconst [c])) -> (TSTconst [c] x) -(TSTW x (MOVDconst [c])) -> (TSTWconst [c] x) -(CMN x (MOVDconst [c])) -> (CMNconst [c] x) -(CMNW x (MOVDconst [c])) -> (CMNWconst [c] x) -(BIC x (MOVDconst [c])) -> (ANDconst [^c] x) -(EON x (MOVDconst [c])) -> (XORconst [^c] x) -(ORN x (MOVDconst [c])) -> (ORconst [^c] x) - -(SLL x (MOVDconst [c])) -> (SLLconst x [c&63]) // Note: I don't think we ever generate bad constant shifts (i.e. c>=64) -(SRL x (MOVDconst [c])) -> (SRLconst x [c&63]) -(SRA x (MOVDconst [c])) -> (SRAconst x [c&63]) - -(CMP x (MOVDconst [c])) -> (CMPconst [c] x) -(CMP (MOVDconst [c]) x) -> (InvertFlags (CMPconst [c] x)) +(ADD x (MOVDconst [c])) => (ADDconst [c] x) +(SUB x (MOVDconst [c])) => (SUBconst [c] x) +(AND x (MOVDconst [c])) => (ANDconst [c] x) +(OR x (MOVDconst [c])) => (ORconst [c] x) +(XOR x (MOVDconst [c])) => (XORconst [c] x) +(TST x (MOVDconst [c])) => (TSTconst [c] x) +(TSTW x (MOVDconst [c])) => (TSTWconst [int32(c)] x) +(CMN x (MOVDconst [c])) => (CMNconst [c] x) +(CMNW x (MOVDconst [c])) => (CMNWconst [int32(c)] x) +(BIC x (MOVDconst [c])) => (ANDconst [^c] x) +(EON x (MOVDconst [c])) => (XORconst [^c] x) +(ORN x (MOVDconst [c])) => (ORconst [^c] x) + +(SLL x (MOVDconst [c])) => (SLLconst x [c&63]) // Note: I don't think we ever generate bad constant shifts (i.e. c>=64) +(SRL x (MOVDconst [c])) => (SRLconst x [c&63]) +(SRA x (MOVDconst [c])) => (SRAconst x [c&63]) + +(CMP x (MOVDconst [c])) => (CMPconst [c] x) +(CMP (MOVDconst [c]) x) => (InvertFlags (CMPconst [c] x)) (CMPW x (MOVDconst [c])) => (CMPWconst [int32(c)] x) (CMPW (MOVDconst [c]) x) => (InvertFlags (CMPWconst [int32(c)] x)) // Canonicalize the order of arguments to comparisons - helps with CSE. -((CMP|CMPW) x y) && x.ID > y.ID -> (InvertFlags ((CMP|CMPW) y x)) +((CMP|CMPW) x y) && x.ID > y.ID => (InvertFlags ((CMP|CMPW) y x)) -// mul-neg -> mneg -(NEG (MUL x y)) -> (MNEG x y) -(NEG (MULW x y)) -> (MNEGW x y) -(MUL (NEG x) y) -> (MNEG x y) -(MULW (NEG x) y) -> (MNEGW x y) +// mul-neg => mneg +(NEG (MUL x y)) => (MNEG x y) +(NEG (MULW x y)) => (MNEGW x y) +(MUL (NEG x) y) => (MNEG x y) +(MULW (NEG x) y) => (MNEGW x y) // madd/msub -(ADD a l:(MUL x y)) && l.Uses==1 && clobber(l) -> (MADD a x y) -(SUB a l:(MUL x y)) && l.Uses==1 && clobber(l) -> (MSUB a x y) -(ADD a l:(MNEG x y)) && l.Uses==1 && clobber(l) -> (MSUB a x y) -(SUB a l:(MNEG x y)) && l.Uses==1 && clobber(l) -> (MADD a x y) +(ADD a l:(MUL x y)) && l.Uses==1 && clobber(l) => (MADD a x y) +(SUB a l:(MUL x y)) && l.Uses==1 && clobber(l) => (MSUB a x y) +(ADD a l:(MNEG x y)) && l.Uses==1 && clobber(l) => (MSUB a x y) +(SUB a l:(MNEG x y)) && l.Uses==1 && clobber(l) => (MADD a x y) -(ADD a l:(MULW x y)) && a.Type.Size() != 8 && l.Uses==1 && clobber(l) -> (MADDW a x y) -(SUB a l:(MULW x y)) && a.Type.Size() != 8 && l.Uses==1 && clobber(l) -> (MSUBW a x y) -(ADD a l:(MNEGW x y)) && a.Type.Size() != 8 && l.Uses==1 && clobber(l) -> (MSUBW a x y) -(SUB a l:(MNEGW x y)) && a.Type.Size() != 8 && l.Uses==1 && clobber(l) -> (MADDW a x y) +(ADD a l:(MULW x y)) && a.Type.Size() != 8 && l.Uses==1 && clobber(l) => (MADDW a x y) +(SUB a l:(MULW x y)) && a.Type.Size() != 8 && l.Uses==1 && clobber(l) => (MSUBW a x y) +(ADD a l:(MNEGW x y)) && a.Type.Size() != 8 && l.Uses==1 && clobber(l) => (MSUBW a x y) +(SUB a l:(MNEGW x y)) && a.Type.Size() != 8 && l.Uses==1 && clobber(l) => (MADDW a x y) // optimize ADCSflags, SBCSflags and friends -(ADCSflags x y (Select1 (ADDSconstflags [-1] (ADCzerocarry c)))) -> (ADCSflags x y c) -(ADCSflags x y (Select1 (ADDSconstflags [-1] (MOVDconst [0])))) -> (ADDSflags x y) -(SBCSflags x y (Select1 (NEGSflags (NEG (NGCzerocarry bo))))) -> (SBCSflags x y bo) -(SBCSflags x y (Select1 (NEGSflags (MOVDconst [0])))) -> (SUBSflags x y) +(ADCSflags x y (Select1 (ADDSconstflags [-1] (ADCzerocarry c)))) => (ADCSflags x y c) +(ADCSflags x y (Select1 (ADDSconstflags [-1] (MOVDconst [0])))) => (ADDSflags x y) +(SBCSflags x y (Select1 (NEGSflags (NEG (NGCzerocarry bo))))) => (SBCSflags x y bo) +(SBCSflags x y (Select1 (NEGSflags (MOVDconst [0])))) => (SUBSflags x y) // mul by constant -(MUL x (MOVDconst [-1])) -> (NEG x) -(MUL _ (MOVDconst [0])) -> (MOVDconst [0]) -(MUL x (MOVDconst [1])) -> x -(MUL x (MOVDconst [c])) && isPowerOfTwo(c) -> (SLLconst [log2(c)] x) -(MUL x (MOVDconst [c])) && isPowerOfTwo(c-1) && c >= 3 -> (ADDshiftLL x x [log2(c-1)]) -(MUL x (MOVDconst [c])) && isPowerOfTwo(c+1) && c >= 7 -> (ADDshiftLL (NEG x) x [log2(c+1)]) -(MUL x (MOVDconst [c])) && c%3 == 0 && isPowerOfTwo(c/3) -> (SLLconst [log2(c/3)] (ADDshiftLL x x [1])) -(MUL x (MOVDconst [c])) && c%5 == 0 && isPowerOfTwo(c/5) -> (SLLconst [log2(c/5)] (ADDshiftLL x x [2])) -(MUL x (MOVDconst [c])) && c%7 == 0 && isPowerOfTwo(c/7) -> (SLLconst [log2(c/7)] (ADDshiftLL (NEG x) x [3])) -(MUL x (MOVDconst [c])) && c%9 == 0 && isPowerOfTwo(c/9) -> (SLLconst [log2(c/9)] (ADDshiftLL x x [3])) - -(MULW x (MOVDconst [c])) && int32(c)==-1 -> (NEG x) -(MULW _ (MOVDconst [c])) && int32(c)==0 -> (MOVDconst [0]) -(MULW x (MOVDconst [c])) && int32(c)==1 -> x -(MULW x (MOVDconst [c])) && isPowerOfTwo(c) -> (SLLconst [log2(c)] x) -(MULW x (MOVDconst [c])) && isPowerOfTwo(c-1) && int32(c) >= 3 -> (ADDshiftLL x x [log2(c-1)]) -(MULW x (MOVDconst [c])) && isPowerOfTwo(c+1) && int32(c) >= 7 -> (ADDshiftLL (NEG x) x [log2(c+1)]) -(MULW x (MOVDconst [c])) && c%3 == 0 && isPowerOfTwo(c/3) && is32Bit(c) -> (SLLconst [log2(c/3)] (ADDshiftLL x x [1])) -(MULW x (MOVDconst [c])) && c%5 == 0 && isPowerOfTwo(c/5) && is32Bit(c) -> (SLLconst [log2(c/5)] (ADDshiftLL x x [2])) -(MULW x (MOVDconst [c])) && c%7 == 0 && isPowerOfTwo(c/7) && is32Bit(c) -> (SLLconst [log2(c/7)] (ADDshiftLL (NEG x) x [3])) -(MULW x (MOVDconst [c])) && c%9 == 0 && isPowerOfTwo(c/9) && is32Bit(c) -> (SLLconst [log2(c/9)] (ADDshiftLL x x [3])) +(MUL x (MOVDconst [-1])) => (NEG x) +(MUL _ (MOVDconst [0])) => (MOVDconst [0]) +(MUL x (MOVDconst [1])) => x +(MUL x (MOVDconst [c])) && isPowerOfTwo(c) => (SLLconst [log2(c)] x) +(MUL x (MOVDconst [c])) && isPowerOfTwo(c-1) && c >= 3 => (ADDshiftLL x x [log2(c-1)]) +(MUL x (MOVDconst [c])) && isPowerOfTwo(c+1) && c >= 7 => (ADDshiftLL (NEG x) x [log2(c+1)]) +(MUL x (MOVDconst [c])) && c%3 == 0 && isPowerOfTwo(c/3) => (SLLconst [log2(c/3)] (ADDshiftLL x x [1])) +(MUL x (MOVDconst [c])) && c%5 == 0 && isPowerOfTwo(c/5) => (SLLconst [log2(c/5)] (ADDshiftLL x x [2])) +(MUL x (MOVDconst [c])) && c%7 == 0 && isPowerOfTwo(c/7) => (SLLconst [log2(c/7)] (ADDshiftLL (NEG x) x [3])) +(MUL x (MOVDconst [c])) && c%9 == 0 && isPowerOfTwo(c/9) => (SLLconst [log2(c/9)] (ADDshiftLL x x [3])) + +(MULW x (MOVDconst [c])) && int32(c)==-1 => (NEG x) +(MULW _ (MOVDconst [c])) && int32(c)==0 => (MOVDconst [0]) +(MULW x (MOVDconst [c])) && int32(c)==1 => x +(MULW x (MOVDconst [c])) && isPowerOfTwo(c) => (SLLconst [log2(c)] x) +(MULW x (MOVDconst [c])) && isPowerOfTwo(c-1) && int32(c) >= 3 => (ADDshiftLL x x [log2(c-1)]) +(MULW x (MOVDconst [c])) && isPowerOfTwo(c+1) && int32(c) >= 7 => (ADDshiftLL (NEG x) x [log2(c+1)]) +(MULW x (MOVDconst [c])) && c%3 == 0 && isPowerOfTwo(c/3) && is32Bit(c) => (SLLconst [log2(c/3)] (ADDshiftLL x x [1])) +(MULW x (MOVDconst [c])) && c%5 == 0 && isPowerOfTwo(c/5) && is32Bit(c) => (SLLconst [log2(c/5)] (ADDshiftLL x x [2])) +(MULW x (MOVDconst [c])) && c%7 == 0 && isPowerOfTwo(c/7) && is32Bit(c) => (SLLconst [log2(c/7)] (ADDshiftLL (NEG x) x [3])) +(MULW x (MOVDconst [c])) && c%9 == 0 && isPowerOfTwo(c/9) && is32Bit(c) => (SLLconst [log2(c/9)] (ADDshiftLL x x [3])) // mneg by constant -(MNEG x (MOVDconst [-1])) -> x -(MNEG _ (MOVDconst [0])) -> (MOVDconst [0]) -(MNEG x (MOVDconst [1])) -> (NEG x) -(MNEG x (MOVDconst [c])) && isPowerOfTwo(c) -> (NEG (SLLconst [log2(c)] x)) -(MNEG x (MOVDconst [c])) && isPowerOfTwo(c-1) && c >= 3 -> (NEG (ADDshiftLL x x [log2(c-1)])) -(MNEG x (MOVDconst [c])) && isPowerOfTwo(c+1) && c >= 7 -> (NEG (ADDshiftLL (NEG x) x [log2(c+1)])) -(MNEG x (MOVDconst [c])) && c%3 == 0 && isPowerOfTwo(c/3) -> (SLLconst [log2(c/3)] (SUBshiftLL x x [2])) -(MNEG x (MOVDconst [c])) && c%5 == 0 && isPowerOfTwo(c/5) -> (NEG (SLLconst [log2(c/5)] (ADDshiftLL x x [2]))) -(MNEG x (MOVDconst [c])) && c%7 == 0 && isPowerOfTwo(c/7) -> (SLLconst [log2(c/7)] (SUBshiftLL x x [3])) -(MNEG x (MOVDconst [c])) && c%9 == 0 && isPowerOfTwo(c/9) -> (NEG (SLLconst [log2(c/9)] (ADDshiftLL x x [3]))) - -(MNEGW x (MOVDconst [c])) && int32(c)==-1 -> x -(MNEGW _ (MOVDconst [c])) && int32(c)==0 -> (MOVDconst [0]) -(MNEGW x (MOVDconst [c])) && int32(c)==1 -> (NEG x) -(MNEGW x (MOVDconst [c])) && isPowerOfTwo(c) -> (NEG (SLLconst [log2(c)] x)) -(MNEGW x (MOVDconst [c])) && isPowerOfTwo(c-1) && int32(c) >= 3 -> (NEG (ADDshiftLL x x [log2(c-1)])) -(MNEGW x (MOVDconst [c])) && isPowerOfTwo(c+1) && int32(c) >= 7 -> (NEG (ADDshiftLL (NEG x) x [log2(c+1)])) -(MNEGW x (MOVDconst [c])) && c%3 == 0 && isPowerOfTwo(c/3) && is32Bit(c) -> (SLLconst [log2(c/3)] (SUBshiftLL x x [2])) -(MNEGW x (MOVDconst [c])) && c%5 == 0 && isPowerOfTwo(c/5) && is32Bit(c) -> (NEG (SLLconst [log2(c/5)] (ADDshiftLL x x [2]))) -(MNEGW x (MOVDconst [c])) && c%7 == 0 && isPowerOfTwo(c/7) && is32Bit(c) -> (SLLconst [log2(c/7)] (SUBshiftLL x x [3])) -(MNEGW x (MOVDconst [c])) && c%9 == 0 && isPowerOfTwo(c/9) && is32Bit(c) -> (NEG (SLLconst [log2(c/9)] (ADDshiftLL x x [3]))) - -(MADD a x (MOVDconst [-1])) -> (SUB a x) -(MADD a _ (MOVDconst [0])) -> a -(MADD a x (MOVDconst [1])) -> (ADD a x) -(MADD a x (MOVDconst [c])) && isPowerOfTwo(c) -> (ADDshiftLL a x [log2(c)]) -(MADD a x (MOVDconst [c])) && isPowerOfTwo(c-1) && c>=3 -> (ADD a (ADDshiftLL x x [log2(c-1)])) -(MADD a x (MOVDconst [c])) && isPowerOfTwo(c+1) && c>=7 -> (SUB a (SUBshiftLL x x [log2(c+1)])) -(MADD a x (MOVDconst [c])) && c%3 == 0 && isPowerOfTwo(c/3) -> (SUBshiftLL a (SUBshiftLL x x [2]) [log2(c/3)]) -(MADD a x (MOVDconst [c])) && c%5 == 0 && isPowerOfTwo(c/5) -> (ADDshiftLL a (ADDshiftLL x x [2]) [log2(c/5)]) -(MADD a x (MOVDconst [c])) && c%7 == 0 && isPowerOfTwo(c/7) -> (SUBshiftLL a (SUBshiftLL x x [3]) [log2(c/7)]) -(MADD a x (MOVDconst [c])) && c%9 == 0 && isPowerOfTwo(c/9) -> (ADDshiftLL a (ADDshiftLL x x [3]) [log2(c/9)]) - -(MADD a (MOVDconst [-1]) x) -> (SUB a x) -(MADD a (MOVDconst [0]) _) -> a -(MADD a (MOVDconst [1]) x) -> (ADD a x) -(MADD a (MOVDconst [c]) x) && isPowerOfTwo(c) -> (ADDshiftLL a x [log2(c)]) -(MADD a (MOVDconst [c]) x) && isPowerOfTwo(c-1) && c>=3 -> (ADD a (ADDshiftLL x x [log2(c-1)])) -(MADD a (MOVDconst [c]) x) && isPowerOfTwo(c+1) && c>=7 -> (SUB a (SUBshiftLL x x [log2(c+1)])) -(MADD a (MOVDconst [c]) x) && c%3 == 0 && isPowerOfTwo(c/3) -> (SUBshiftLL a (SUBshiftLL x x [2]) [log2(c/3)]) -(MADD a (MOVDconst [c]) x) && c%5 == 0 && isPowerOfTwo(c/5) -> (ADDshiftLL a (ADDshiftLL x x [2]) [log2(c/5)]) -(MADD a (MOVDconst [c]) x) && c%7 == 0 && isPowerOfTwo(c/7) -> (SUBshiftLL a (SUBshiftLL x x [3]) [log2(c/7)]) -(MADD a (MOVDconst [c]) x) && c%9 == 0 && isPowerOfTwo(c/9) -> (ADDshiftLL a (ADDshiftLL x x [3]) [log2(c/9)]) - -(MADDW a x (MOVDconst [c])) && int32(c)==-1 -> (SUB a x) -(MADDW a _ (MOVDconst [c])) && int32(c)==0 -> a -(MADDW a x (MOVDconst [c])) && int32(c)==1 -> (ADD a x) -(MADDW a x (MOVDconst [c])) && isPowerOfTwo(c) -> (ADDshiftLL a x [log2(c)]) -(MADDW a x (MOVDconst [c])) && isPowerOfTwo(c-1) && int32(c)>=3 -> (ADD a (ADDshiftLL x x [log2(c-1)])) -(MADDW a x (MOVDconst [c])) && isPowerOfTwo(c+1) && int32(c)>=7 -> (SUB a (SUBshiftLL x x [log2(c+1)])) -(MADDW a x (MOVDconst [c])) && c%3 == 0 && isPowerOfTwo(c/3) && is32Bit(c) -> (SUBshiftLL a (SUBshiftLL x x [2]) [log2(c/3)]) -(MADDW a x (MOVDconst [c])) && c%5 == 0 && isPowerOfTwo(c/5) && is32Bit(c) -> (ADDshiftLL a (ADDshiftLL x x [2]) [log2(c/5)]) -(MADDW a x (MOVDconst [c])) && c%7 == 0 && isPowerOfTwo(c/7) && is32Bit(c) -> (SUBshiftLL a (SUBshiftLL x x [3]) [log2(c/7)]) -(MADDW a x (MOVDconst [c])) && c%9 == 0 && isPowerOfTwo(c/9) && is32Bit(c) -> (ADDshiftLL a (ADDshiftLL x x [3]) [log2(c/9)]) - -(MADDW a (MOVDconst [c]) x) && int32(c)==-1 -> (SUB a x) -(MADDW a (MOVDconst [c]) _) && int32(c)==0 -> a -(MADDW a (MOVDconst [c]) x) && int32(c)==1 -> (ADD a x) -(MADDW a (MOVDconst [c]) x) && isPowerOfTwo(c) -> (ADDshiftLL a x [log2(c)]) -(MADDW a (MOVDconst [c]) x) && isPowerOfTwo(c-1) && int32(c)>=3 -> (ADD a (ADDshiftLL x x [log2(c-1)])) -(MADDW a (MOVDconst [c]) x) && isPowerOfTwo(c+1) && int32(c)>=7 -> (SUB a (SUBshiftLL x x [log2(c+1)])) -(MADDW a (MOVDconst [c]) x) && c%3 == 0 && isPowerOfTwo(c/3) && is32Bit(c) -> (SUBshiftLL a (SUBshiftLL x x [2]) [log2(c/3)]) -(MADDW a (MOVDconst [c]) x) && c%5 == 0 && isPowerOfTwo(c/5) && is32Bit(c) -> (ADDshiftLL a (ADDshiftLL x x [2]) [log2(c/5)]) -(MADDW a (MOVDconst [c]) x) && c%7 == 0 && isPowerOfTwo(c/7) && is32Bit(c) -> (SUBshiftLL a (SUBshiftLL x x [3]) [log2(c/7)]) -(MADDW a (MOVDconst [c]) x) && c%9 == 0 && isPowerOfTwo(c/9) && is32Bit(c) -> (ADDshiftLL a (ADDshiftLL x x [3]) [log2(c/9)]) - -(MSUB a x (MOVDconst [-1])) -> (ADD a x) -(MSUB a _ (MOVDconst [0])) -> a -(MSUB a x (MOVDconst [1])) -> (SUB a x) -(MSUB a x (MOVDconst [c])) && isPowerOfTwo(c) -> (SUBshiftLL a x [log2(c)]) -(MSUB a x (MOVDconst [c])) && isPowerOfTwo(c-1) && c>=3 -> (SUB a (ADDshiftLL x x [log2(c-1)])) -(MSUB a x (MOVDconst [c])) && isPowerOfTwo(c+1) && c>=7 -> (ADD a (SUBshiftLL x x [log2(c+1)])) -(MSUB a x (MOVDconst [c])) && c%3 == 0 && isPowerOfTwo(c/3) -> (ADDshiftLL a (SUBshiftLL x x [2]) [log2(c/3)]) -(MSUB a x (MOVDconst [c])) && c%5 == 0 && isPowerOfTwo(c/5) -> (SUBshiftLL a (ADDshiftLL x x [2]) [log2(c/5)]) -(MSUB a x (MOVDconst [c])) && c%7 == 0 && isPowerOfTwo(c/7) -> (ADDshiftLL a (SUBshiftLL x x [3]) [log2(c/7)]) -(MSUB a x (MOVDconst [c])) && c%9 == 0 && isPowerOfTwo(c/9) -> (SUBshiftLL a (ADDshiftLL x x [3]) [log2(c/9)]) - -(MSUB a (MOVDconst [-1]) x) -> (ADD a x) -(MSUB a (MOVDconst [0]) _) -> a -(MSUB a (MOVDconst [1]) x) -> (SUB a x) -(MSUB a (MOVDconst [c]) x) && isPowerOfTwo(c) -> (SUBshiftLL a x [log2(c)]) -(MSUB a (MOVDconst [c]) x) && isPowerOfTwo(c-1) && c>=3 -> (SUB a (ADDshiftLL x x [log2(c-1)])) -(MSUB a (MOVDconst [c]) x) && isPowerOfTwo(c+1) && c>=7 -> (ADD a (SUBshiftLL x x [log2(c+1)])) -(MSUB a (MOVDconst [c]) x) && c%3 == 0 && isPowerOfTwo(c/3) -> (ADDshiftLL a (SUBshiftLL x x [2]) [log2(c/3)]) -(MSUB a (MOVDconst [c]) x) && c%5 == 0 && isPowerOfTwo(c/5) -> (SUBshiftLL a (ADDshiftLL x x [2]) [log2(c/5)]) -(MSUB a (MOVDconst [c]) x) && c%7 == 0 && isPowerOfTwo(c/7) -> (ADDshiftLL a (SUBshiftLL x x [3]) [log2(c/7)]) -(MSUB a (MOVDconst [c]) x) && c%9 == 0 && isPowerOfTwo(c/9) -> (SUBshiftLL a (ADDshiftLL x x [3]) [log2(c/9)]) - -(MSUBW a x (MOVDconst [c])) && int32(c)==-1 -> (ADD a x) -(MSUBW a _ (MOVDconst [c])) && int32(c)==0 -> a -(MSUBW a x (MOVDconst [c])) && int32(c)==1 -> (SUB a x) -(MSUBW a x (MOVDconst [c])) && isPowerOfTwo(c) -> (SUBshiftLL a x [log2(c)]) -(MSUBW a x (MOVDconst [c])) && isPowerOfTwo(c-1) && int32(c)>=3 -> (SUB a (ADDshiftLL x x [log2(c-1)])) -(MSUBW a x (MOVDconst [c])) && isPowerOfTwo(c+1) && int32(c)>=7 -> (ADD a (SUBshiftLL x x [log2(c+1)])) -(MSUBW a x (MOVDconst [c])) && c%3 == 0 && isPowerOfTwo(c/3) && is32Bit(c) -> (ADDshiftLL a (SUBshiftLL x x [2]) [log2(c/3)]) -(MSUBW a x (MOVDconst [c])) && c%5 == 0 && isPowerOfTwo(c/5) && is32Bit(c) -> (SUBshiftLL a (ADDshiftLL x x [2]) [log2(c/5)]) -(MSUBW a x (MOVDconst [c])) && c%7 == 0 && isPowerOfTwo(c/7) && is32Bit(c) -> (ADDshiftLL a (SUBshiftLL x x [3]) [log2(c/7)]) -(MSUBW a x (MOVDconst [c])) && c%9 == 0 && isPowerOfTwo(c/9) && is32Bit(c) -> (SUBshiftLL a (ADDshiftLL x x [3]) [log2(c/9)]) - -(MSUBW a (MOVDconst [c]) x) && int32(c)==-1 -> (ADD a x) -(MSUBW a (MOVDconst [c]) _) && int32(c)==0 -> a -(MSUBW a (MOVDconst [c]) x) && int32(c)==1 -> (SUB a x) -(MSUBW a (MOVDconst [c]) x) && isPowerOfTwo(c) -> (SUBshiftLL a x [log2(c)]) -(MSUBW a (MOVDconst [c]) x) && isPowerOfTwo(c-1) && int32(c)>=3 -> (SUB a (ADDshiftLL x x [log2(c-1)])) -(MSUBW a (MOVDconst [c]) x) && isPowerOfTwo(c+1) && int32(c)>=7 -> (ADD a (SUBshiftLL x x [log2(c+1)])) -(MSUBW a (MOVDconst [c]) x) && c%3 == 0 && isPowerOfTwo(c/3) && is32Bit(c) -> (ADDshiftLL a (SUBshiftLL x x [2]) [log2(c/3)]) -(MSUBW a (MOVDconst [c]) x) && c%5 == 0 && isPowerOfTwo(c/5) && is32Bit(c) -> (SUBshiftLL a (ADDshiftLL x x [2]) [log2(c/5)]) -(MSUBW a (MOVDconst [c]) x) && c%7 == 0 && isPowerOfTwo(c/7) && is32Bit(c) -> (ADDshiftLL a (SUBshiftLL x x [3]) [log2(c/7)]) -(MSUBW a (MOVDconst [c]) x) && c%9 == 0 && isPowerOfTwo(c/9) && is32Bit(c) -> (SUBshiftLL a (ADDshiftLL x x [3]) [log2(c/9)]) +(MNEG x (MOVDconst [-1])) => x +(MNEG _ (MOVDconst [0])) => (MOVDconst [0]) +(MNEG x (MOVDconst [1])) => (NEG x) +(MNEG x (MOVDconst [c])) && isPowerOfTwo(c) => (NEG (SLLconst [log2(c)] x)) +(MNEG x (MOVDconst [c])) && isPowerOfTwo(c-1) && c >= 3 => (NEG (ADDshiftLL x x [log2(c-1)])) +(MNEG x (MOVDconst [c])) && isPowerOfTwo(c+1) && c >= 7 => (NEG (ADDshiftLL (NEG x) x [log2(c+1)])) +(MNEG x (MOVDconst [c])) && c%3 == 0 && isPowerOfTwo(c/3) => (SLLconst [log2(c/3)] (SUBshiftLL x x [2])) +(MNEG x (MOVDconst [c])) && c%5 == 0 && isPowerOfTwo(c/5) => (NEG (SLLconst [log2(c/5)] (ADDshiftLL x x [2]))) +(MNEG x (MOVDconst [c])) && c%7 == 0 && isPowerOfTwo(c/7) => (SLLconst [log2(c/7)] (SUBshiftLL x x [3])) +(MNEG x (MOVDconst [c])) && c%9 == 0 && isPowerOfTwo(c/9) => (NEG (SLLconst [log2(c/9)] (ADDshiftLL x x [3]))) + +(MNEGW x (MOVDconst [c])) && int32(c)==-1 => x +(MNEGW _ (MOVDconst [c])) && int32(c)==0 => (MOVDconst [0]) +(MNEGW x (MOVDconst [c])) && int32(c)==1 => (NEG x) +(MNEGW x (MOVDconst [c])) && isPowerOfTwo(c) => (NEG (SLLconst [log2(c)] x)) +(MNEGW x (MOVDconst [c])) && isPowerOfTwo(c-1) && int32(c) >= 3 => (NEG (ADDshiftLL x x [log2(c-1)])) +(MNEGW x (MOVDconst [c])) && isPowerOfTwo(c+1) && int32(c) >= 7 => (NEG (ADDshiftLL (NEG x) x [log2(c+1)])) +(MNEGW x (MOVDconst [c])) && c%3 == 0 && isPowerOfTwo(c/3) && is32Bit(c) => (SLLconst [log2(c/3)] (SUBshiftLL x x [2])) +(MNEGW x (MOVDconst [c])) && c%5 == 0 && isPowerOfTwo(c/5) && is32Bit(c) => (NEG (SLLconst [log2(c/5)] (ADDshiftLL x x [2]))) +(MNEGW x (MOVDconst [c])) && c%7 == 0 && isPowerOfTwo(c/7) && is32Bit(c) => (SLLconst [log2(c/7)] (SUBshiftLL x x [3])) +(MNEGW x (MOVDconst [c])) && c%9 == 0 && isPowerOfTwo(c/9) && is32Bit(c) => (NEG (SLLconst [log2(c/9)] (ADDshiftLL x x [3]))) + +(MADD a x (MOVDconst [-1])) => (SUB a x) +(MADD a _ (MOVDconst [0])) => a +(MADD a x (MOVDconst [1])) => (ADD a x) +(MADD a x (MOVDconst [c])) && isPowerOfTwo(c) => (ADDshiftLL a x [log2(c)]) +(MADD a x (MOVDconst [c])) && isPowerOfTwo(c-1) && c>=3 => (ADD a (ADDshiftLL x x [log2(c-1)])) +(MADD a x (MOVDconst [c])) && isPowerOfTwo(c+1) && c>=7 => (SUB a (SUBshiftLL x x [log2(c+1)])) +(MADD a x (MOVDconst [c])) && c%3 == 0 && isPowerOfTwo(c/3) => (SUBshiftLL a (SUBshiftLL x x [2]) [log2(c/3)]) +(MADD a x (MOVDconst [c])) && c%5 == 0 && isPowerOfTwo(c/5) => (ADDshiftLL a (ADDshiftLL x x [2]) [log2(c/5)]) +(MADD a x (MOVDconst [c])) && c%7 == 0 && isPowerOfTwo(c/7) => (SUBshiftLL a (SUBshiftLL x x [3]) [log2(c/7)]) +(MADD a x (MOVDconst [c])) && c%9 == 0 && isPowerOfTwo(c/9) => (ADDshiftLL a (ADDshiftLL x x [3]) [log2(c/9)]) + +(MADD a (MOVDconst [-1]) x) => (SUB a x) +(MADD a (MOVDconst [0]) _) => a +(MADD a (MOVDconst [1]) x) => (ADD a x) +(MADD a (MOVDconst [c]) x) && isPowerOfTwo(c) => (ADDshiftLL a x [log2(c)]) +(MADD a (MOVDconst [c]) x) && isPowerOfTwo(c-1) && c>=3 => (ADD a (ADDshiftLL x x [log2(c-1)])) +(MADD a (MOVDconst [c]) x) && isPowerOfTwo(c+1) && c>=7 => (SUB a (SUBshiftLL x x [log2(c+1)])) +(MADD a (MOVDconst [c]) x) && c%3 == 0 && isPowerOfTwo(c/3) => (SUBshiftLL a (SUBshiftLL x x [2]) [log2(c/3)]) +(MADD a (MOVDconst [c]) x) && c%5 == 0 && isPowerOfTwo(c/5) => (ADDshiftLL a (ADDshiftLL x x [2]) [log2(c/5)]) +(MADD a (MOVDconst [c]) x) && c%7 == 0 && isPowerOfTwo(c/7) => (SUBshiftLL a (SUBshiftLL x x [3]) [log2(c/7)]) +(MADD a (MOVDconst [c]) x) && c%9 == 0 && isPowerOfTwo(c/9) => (ADDshiftLL a (ADDshiftLL x x [3]) [log2(c/9)]) + +(MADDW a x (MOVDconst [c])) && int32(c)==-1 => (SUB a x) +(MADDW a _ (MOVDconst [c])) && int32(c)==0 => a +(MADDW a x (MOVDconst [c])) && int32(c)==1 => (ADD a x) +(MADDW a x (MOVDconst [c])) && isPowerOfTwo(c) => (ADDshiftLL a x [log2(c)]) +(MADDW a x (MOVDconst [c])) && isPowerOfTwo(c-1) && int32(c)>=3 => (ADD a (ADDshiftLL x x [log2(c-1)])) +(MADDW a x (MOVDconst [c])) && isPowerOfTwo(c+1) && int32(c)>=7 => (SUB a (SUBshiftLL x x [log2(c+1)])) +(MADDW a x (MOVDconst [c])) && c%3 == 0 && isPowerOfTwo(c/3) && is32Bit(c) => (SUBshiftLL a (SUBshiftLL x x [2]) [log2(c/3)]) +(MADDW a x (MOVDconst [c])) && c%5 == 0 && isPowerOfTwo(c/5) && is32Bit(c) => (ADDshiftLL a (ADDshiftLL x x [2]) [log2(c/5)]) +(MADDW a x (MOVDconst [c])) && c%7 == 0 && isPowerOfTwo(c/7) && is32Bit(c) => (SUBshiftLL a (SUBshiftLL x x [3]) [log2(c/7)]) +(MADDW a x (MOVDconst [c])) && c%9 == 0 && isPowerOfTwo(c/9) && is32Bit(c) => (ADDshiftLL a (ADDshiftLL x x [3]) [log2(c/9)]) + +(MADDW a (MOVDconst [c]) x) && int32(c)==-1 => (SUB a x) +(MADDW a (MOVDconst [c]) _) && int32(c)==0 => a +(MADDW a (MOVDconst [c]) x) && int32(c)==1 => (ADD a x) +(MADDW a (MOVDconst [c]) x) && isPowerOfTwo(c) => (ADDshiftLL a x [log2(c)]) +(MADDW a (MOVDconst [c]) x) && isPowerOfTwo(c-1) && int32(c)>=3 => (ADD a (ADDshiftLL x x [log2(c-1)])) +(MADDW a (MOVDconst [c]) x) && isPowerOfTwo(c+1) && int32(c)>=7 => (SUB a (SUBshiftLL x x [log2(c+1)])) +(MADDW a (MOVDconst [c]) x) && c%3 == 0 && isPowerOfTwo(c/3) && is32Bit(c) => (SUBshiftLL a (SUBshiftLL x x [2]) [log2(c/3)]) +(MADDW a (MOVDconst [c]) x) && c%5 == 0 && isPowerOfTwo(c/5) && is32Bit(c) => (ADDshiftLL a (ADDshiftLL x x [2]) [log2(c/5)]) +(MADDW a (MOVDconst [c]) x) && c%7 == 0 && isPowerOfTwo(c/7) && is32Bit(c) => (SUBshiftLL a (SUBshiftLL x x [3]) [log2(c/7)]) +(MADDW a (MOVDconst [c]) x) && c%9 == 0 && isPowerOfTwo(c/9) && is32Bit(c) => (ADDshiftLL a (ADDshiftLL x x [3]) [log2(c/9)]) + +(MSUB a x (MOVDconst [-1])) => (ADD a x) +(MSUB a _ (MOVDconst [0])) => a +(MSUB a x (MOVDconst [1])) => (SUB a x) +(MSUB a x (MOVDconst [c])) && isPowerOfTwo(c) => (SUBshiftLL a x [log2(c)]) +(MSUB a x (MOVDconst [c])) && isPowerOfTwo(c-1) && c>=3 => (SUB a (ADDshiftLL x x [log2(c-1)])) +(MSUB a x (MOVDconst [c])) && isPowerOfTwo(c+1) && c>=7 => (ADD a (SUBshiftLL x x [log2(c+1)])) +(MSUB a x (MOVDconst [c])) && c%3 == 0 && isPowerOfTwo(c/3) => (ADDshiftLL a (SUBshiftLL x x [2]) [log2(c/3)]) +(MSUB a x (MOVDconst [c])) && c%5 == 0 && isPowerOfTwo(c/5) => (SUBshiftLL a (ADDshiftLL x x [2]) [log2(c/5)]) +(MSUB a x (MOVDconst [c])) && c%7 == 0 && isPowerOfTwo(c/7) => (ADDshiftLL a (SUBshiftLL x x [3]) [log2(c/7)]) +(MSUB a x (MOVDconst [c])) && c%9 == 0 && isPowerOfTwo(c/9) => (SUBshiftLL a (ADDshiftLL x x [3]) [log2(c/9)]) + +(MSUB a (MOVDconst [-1]) x) => (ADD a x) +(MSUB a (MOVDconst [0]) _) => a +(MSUB a (MOVDconst [1]) x) => (SUB a x) +(MSUB a (MOVDconst [c]) x) && isPowerOfTwo(c) => (SUBshiftLL a x [log2(c)]) +(MSUB a (MOVDconst [c]) x) && isPowerOfTwo(c-1) && c>=3 => (SUB a (ADDshiftLL x x [log2(c-1)])) +(MSUB a (MOVDconst [c]) x) && isPowerOfTwo(c+1) && c>=7 => (ADD a (SUBshiftLL x x [log2(c+1)])) +(MSUB a (MOVDconst [c]) x) && c%3 == 0 && isPowerOfTwo(c/3) => (ADDshiftLL a (SUBshiftLL x x [2]) [log2(c/3)]) +(MSUB a (MOVDconst [c]) x) && c%5 == 0 && isPowerOfTwo(c/5) => (SUBshiftLL a (ADDshiftLL x x [2]) [log2(c/5)]) +(MSUB a (MOVDconst [c]) x) && c%7 == 0 && isPowerOfTwo(c/7) => (ADDshiftLL a (SUBshiftLL x x [3]) [log2(c/7)]) +(MSUB a (MOVDconst [c]) x) && c%9 == 0 && isPowerOfTwo(c/9) => (SUBshiftLL a (ADDshiftLL x x [3]) [log2(c/9)]) + +(MSUBW a x (MOVDconst [c])) && int32(c)==-1 => (ADD a x) +(MSUBW a _ (MOVDconst [c])) && int32(c)==0 => a +(MSUBW a x (MOVDconst [c])) && int32(c)==1 => (SUB a x) +(MSUBW a x (MOVDconst [c])) && isPowerOfTwo(c) => (SUBshiftLL a x [log2(c)]) +(MSUBW a x (MOVDconst [c])) && isPowerOfTwo(c-1) && int32(c)>=3 => (SUB a (ADDshiftLL x x [log2(c-1)])) +(MSUBW a x (MOVDconst [c])) && isPowerOfTwo(c+1) && int32(c)>=7 => (ADD a (SUBshiftLL x x [log2(c+1)])) +(MSUBW a x (MOVDconst [c])) && c%3 == 0 && isPowerOfTwo(c/3) && is32Bit(c) => (ADDshiftLL a (SUBshiftLL x x [2]) [log2(c/3)]) +(MSUBW a x (MOVDconst [c])) && c%5 == 0 && isPowerOfTwo(c/5) && is32Bit(c) => (SUBshiftLL a (ADDshiftLL x x [2]) [log2(c/5)]) +(MSUBW a x (MOVDconst [c])) && c%7 == 0 && isPowerOfTwo(c/7) && is32Bit(c) => (ADDshiftLL a (SUBshiftLL x x [3]) [log2(c/7)]) +(MSUBW a x (MOVDconst [c])) && c%9 == 0 && isPowerOfTwo(c/9) && is32Bit(c) => (SUBshiftLL a (ADDshiftLL x x [3]) [log2(c/9)]) + +(MSUBW a (MOVDconst [c]) x) && int32(c)==-1 => (ADD a x) +(MSUBW a (MOVDconst [c]) _) && int32(c)==0 => a +(MSUBW a (MOVDconst [c]) x) && int32(c)==1 => (SUB a x) +(MSUBW a (MOVDconst [c]) x) && isPowerOfTwo(c) => (SUBshiftLL a x [log2(c)]) +(MSUBW a (MOVDconst [c]) x) && isPowerOfTwo(c-1) && int32(c)>=3 => (SUB a (ADDshiftLL x x [log2(c-1)])) +(MSUBW a (MOVDconst [c]) x) && isPowerOfTwo(c+1) && int32(c)>=7 => (ADD a (SUBshiftLL x x [log2(c+1)])) +(MSUBW a (MOVDconst [c]) x) && c%3 == 0 && isPowerOfTwo(c/3) && is32Bit(c) => (ADDshiftLL a (SUBshiftLL x x [2]) [log2(c/3)]) +(MSUBW a (MOVDconst [c]) x) && c%5 == 0 && isPowerOfTwo(c/5) && is32Bit(c) => (SUBshiftLL a (ADDshiftLL x x [2]) [log2(c/5)]) +(MSUBW a (MOVDconst [c]) x) && c%7 == 0 && isPowerOfTwo(c/7) && is32Bit(c) => (ADDshiftLL a (SUBshiftLL x x [3]) [log2(c/7)]) +(MSUBW a (MOVDconst [c]) x) && c%9 == 0 && isPowerOfTwo(c/9) && is32Bit(c) => (SUBshiftLL a (ADDshiftLL x x [3]) [log2(c/9)]) // div by constant -(UDIV x (MOVDconst [1])) -> x -(UDIV x (MOVDconst [c])) && isPowerOfTwo(c) -> (SRLconst [log2(c)] x) -(UDIVW x (MOVDconst [c])) && uint32(c)==1 -> x -(UDIVW x (MOVDconst [c])) && isPowerOfTwo(c) && is32Bit(c) -> (SRLconst [log2(c)] x) -(UMOD _ (MOVDconst [1])) -> (MOVDconst [0]) -(UMOD x (MOVDconst [c])) && isPowerOfTwo(c) -> (ANDconst [c-1] x) -(UMODW _ (MOVDconst [c])) && uint32(c)==1 -> (MOVDconst [0]) -(UMODW x (MOVDconst [c])) && isPowerOfTwo(c) && is32Bit(c) -> (ANDconst [c-1] x) +(UDIV x (MOVDconst [1])) => x +(UDIV x (MOVDconst [c])) && isPowerOfTwo(c) => (SRLconst [log2(c)] x) +(UDIVW x (MOVDconst [c])) && uint32(c)==1 => x +(UDIVW x (MOVDconst [c])) && isPowerOfTwo(c) && is32Bit(c) => (SRLconst [log2(c)] x) +(UMOD _ (MOVDconst [1])) => (MOVDconst [0]) +(UMOD x (MOVDconst [c])) && isPowerOfTwo(c) => (ANDconst [c-1] x) +(UMODW _ (MOVDconst [c])) && uint32(c)==1 => (MOVDconst [0]) +(UMODW x (MOVDconst [c])) && isPowerOfTwo(c) && is32Bit(c) => (ANDconst [c-1] x) // generic simplifications -(ADD x (NEG y)) -> (SUB x y) -(SUB x x) -> (MOVDconst [0]) -(AND x x) -> x -(OR x x) -> x -(XOR x x) -> (MOVDconst [0]) -(BIC x x) -> (MOVDconst [0]) -(EON x x) -> (MOVDconst [-1]) -(ORN x x) -> (MOVDconst [-1]) -(AND x (MVN y)) -> (BIC x y) -(XOR x (MVN y)) -> (EON x y) -(OR x (MVN y)) -> (ORN x y) -(MVN (XOR x y)) -> (EON x y) +(ADD x (NEG y)) => (SUB x y) +(SUB x x) => (MOVDconst [0]) +(AND x x) => x +(OR x x) => x +(XOR x x) => (MOVDconst [0]) +(BIC x x) => (MOVDconst [0]) +(EON x x) => (MOVDconst [-1]) +(ORN x x) => (MOVDconst [-1]) +(AND x (MVN y)) => (BIC x y) +(XOR x (MVN y)) => (EON x y) +(OR x (MVN y)) => (ORN x y) +(MVN (XOR x y)) => (EON x y) (CSEL [cc] x (MOVDconst [0]) flag) => (CSEL0 [cc] x flag) (CSEL [cc] (MOVDconst [0]) y flag) => (CSEL0 [arm64Negate(cc)] y flag) -(SUB x (SUB y z)) -> (SUB (ADD x z) y) -(SUB (SUB x y) z) -> (SUB x (ADD y z)) +(SUB x (SUB y z)) => (SUB (ADD x z) y) +(SUB (SUB x y) z) => (SUB x (ADD y z)) // remove redundant *const ops -(ADDconst [0] x) -> x -(SUBconst [0] x) -> x -(ANDconst [0] _) -> (MOVDconst [0]) -(ANDconst [-1] x) -> x -(ORconst [0] x) -> x -(ORconst [-1] _) -> (MOVDconst [-1]) -(XORconst [0] x) -> x -(XORconst [-1] x) -> (MVN x) +(ADDconst [0] x) => x +(SUBconst [0] x) => x +(ANDconst [0] _) => (MOVDconst [0]) +(ANDconst [-1] x) => x +(ORconst [0] x) => x +(ORconst [-1] _) => (MOVDconst [-1]) +(XORconst [0] x) => x +(XORconst [-1] x) => (MVN x) // generic constant folding -(ADDconst [c] (MOVDconst [d])) -> (MOVDconst [c+d]) -(ADDconst [c] (ADDconst [d] x)) -> (ADDconst [c+d] x) -(ADDconst [c] (SUBconst [d] x)) -> (ADDconst [c-d] x) -(SUBconst [c] (MOVDconst [d])) -> (MOVDconst [d-c]) -(SUBconst [c] (SUBconst [d] x)) -> (ADDconst [-c-d] x) -(SUBconst [c] (ADDconst [d] x)) -> (ADDconst [-c+d] x) -(SLLconst [c] (MOVDconst [d])) -> (MOVDconst [d< (MOVDconst [int64(uint64(d)>>uint64(c))]) -(SRAconst [c] (MOVDconst [d])) -> (MOVDconst [d>>uint64(c)]) -(MUL (MOVDconst [c]) (MOVDconst [d])) -> (MOVDconst [c*d]) -(MULW (MOVDconst [c]) (MOVDconst [d])) -> (MOVDconst [int64(int32(c)*int32(d))]) -(MNEG (MOVDconst [c]) (MOVDconst [d])) -> (MOVDconst [-c*d]) -(MNEGW (MOVDconst [c]) (MOVDconst [d])) -> (MOVDconst [-int64(int32(c)*int32(d))]) -(MADD (MOVDconst [c]) x y) -> (ADDconst [c] (MUL x y)) -(MADDW (MOVDconst [c]) x y) -> (ADDconst [c] (MULW x y)) -(MSUB (MOVDconst [c]) x y) -> (ADDconst [c] (MNEG x y)) -(MSUBW (MOVDconst [c]) x y) -> (ADDconst [c] (MNEGW x y)) -(MADD a (MOVDconst [c]) (MOVDconst [d])) -> (ADDconst [c*d] a) -(MADDW a (MOVDconst [c]) (MOVDconst [d])) -> (ADDconst [int64(int32(c)*int32(d))] a) -(MSUB a (MOVDconst [c]) (MOVDconst [d])) -> (SUBconst [c*d] a) -(MSUBW a (MOVDconst [c]) (MOVDconst [d])) -> (SUBconst [int64(int32(c)*int32(d))] a) -(DIV (MOVDconst [c]) (MOVDconst [d])) -> (MOVDconst [c/d]) -(UDIV (MOVDconst [c]) (MOVDconst [d])) -> (MOVDconst [int64(uint64(c)/uint64(d))]) -(DIVW (MOVDconst [c]) (MOVDconst [d])) -> (MOVDconst [int64(int32(c)/int32(d))]) -(UDIVW (MOVDconst [c]) (MOVDconst [d])) -> (MOVDconst [int64(uint32(c)/uint32(d))]) -(MOD (MOVDconst [c]) (MOVDconst [d])) -> (MOVDconst [c%d]) -(UMOD (MOVDconst [c]) (MOVDconst [d])) -> (MOVDconst [int64(uint64(c)%uint64(d))]) -(MODW (MOVDconst [c]) (MOVDconst [d])) -> (MOVDconst [int64(int32(c)%int32(d))]) -(UMODW (MOVDconst [c]) (MOVDconst [d])) -> (MOVDconst [int64(uint32(c)%uint32(d))]) -(ANDconst [c] (MOVDconst [d])) -> (MOVDconst [c&d]) -(ANDconst [c] (ANDconst [d] x)) -> (ANDconst [c&d] x) -(ANDconst [c] (MOVWUreg x)) -> (ANDconst [c&(1<<32-1)] x) -(ANDconst [c] (MOVHUreg x)) -> (ANDconst [c&(1<<16-1)] x) -(ANDconst [c] (MOVBUreg x)) -> (ANDconst [c&(1<<8-1)] x) -(MOVWUreg (ANDconst [c] x)) -> (ANDconst [c&(1<<32-1)] x) -(MOVHUreg (ANDconst [c] x)) -> (ANDconst [c&(1<<16-1)] x) -(MOVBUreg (ANDconst [c] x)) -> (ANDconst [c&(1<<8-1)] x) -(ORconst [c] (MOVDconst [d])) -> (MOVDconst [c|d]) -(ORconst [c] (ORconst [d] x)) -> (ORconst [c|d] x) -(XORconst [c] (MOVDconst [d])) -> (MOVDconst [c^d]) -(XORconst [c] (XORconst [d] x)) -> (XORconst [c^d] x) -(MVN (MOVDconst [c])) -> (MOVDconst [^c]) -(NEG (MOVDconst [c])) -> (MOVDconst [-c]) -(MOVBreg (MOVDconst [c])) -> (MOVDconst [int64(int8(c))]) -(MOVBUreg (MOVDconst [c])) -> (MOVDconst [int64(uint8(c))]) -(MOVHreg (MOVDconst [c])) -> (MOVDconst [int64(int16(c))]) -(MOVHUreg (MOVDconst [c])) -> (MOVDconst [int64(uint16(c))]) -(MOVWreg (MOVDconst [c])) -> (MOVDconst [int64(int32(c))]) -(MOVWUreg (MOVDconst [c])) -> (MOVDconst [int64(uint32(c))]) -(MOVDreg (MOVDconst [c])) -> (MOVDconst [c]) +(ADDconst [c] (MOVDconst [d])) => (MOVDconst [c+d]) +(ADDconst [c] (ADDconst [d] x)) => (ADDconst [c+d] x) +(ADDconst [c] (SUBconst [d] x)) => (ADDconst [c-d] x) +(SUBconst [c] (MOVDconst [d])) => (MOVDconst [d-c]) +(SUBconst [c] (SUBconst [d] x)) => (ADDconst [-c-d] x) +(SUBconst [c] (ADDconst [d] x)) => (ADDconst [-c+d] x) +(SLLconst [c] (MOVDconst [d])) => (MOVDconst [d< (MOVDconst [int64(uint64(d)>>uint64(c))]) +(SRAconst [c] (MOVDconst [d])) => (MOVDconst [d>>uint64(c)]) +(MUL (MOVDconst [c]) (MOVDconst [d])) => (MOVDconst [c*d]) +(MULW (MOVDconst [c]) (MOVDconst [d])) => (MOVDconst [int64(int32(c)*int32(d))]) +(MNEG (MOVDconst [c]) (MOVDconst [d])) => (MOVDconst [-c*d]) +(MNEGW (MOVDconst [c]) (MOVDconst [d])) => (MOVDconst [-int64(int32(c)*int32(d))]) +(MADD (MOVDconst [c]) x y) => (ADDconst [c] (MUL x y)) +(MADDW (MOVDconst [c]) x y) => (ADDconst [c] (MULW x y)) +(MSUB (MOVDconst [c]) x y) => (ADDconst [c] (MNEG x y)) +(MSUBW (MOVDconst [c]) x y) => (ADDconst [c] (MNEGW x y)) +(MADD a (MOVDconst [c]) (MOVDconst [d])) => (ADDconst [c*d] a) +(MADDW a (MOVDconst [c]) (MOVDconst [d])) => (ADDconst [int64(int32(c)*int32(d))] a) +(MSUB a (MOVDconst [c]) (MOVDconst [d])) => (SUBconst [c*d] a) +(MSUBW a (MOVDconst [c]) (MOVDconst [d])) => (SUBconst [int64(int32(c)*int32(d))] a) +(DIV (MOVDconst [c]) (MOVDconst [d])) => (MOVDconst [c/d]) +(UDIV (MOVDconst [c]) (MOVDconst [d])) => (MOVDconst [int64(uint64(c)/uint64(d))]) +(DIVW (MOVDconst [c]) (MOVDconst [d])) => (MOVDconst [int64(int32(c)/int32(d))]) +(UDIVW (MOVDconst [c]) (MOVDconst [d])) => (MOVDconst [int64(uint32(c)/uint32(d))]) +(MOD (MOVDconst [c]) (MOVDconst [d])) => (MOVDconst [c%d]) +(UMOD (MOVDconst [c]) (MOVDconst [d])) => (MOVDconst [int64(uint64(c)%uint64(d))]) +(MODW (MOVDconst [c]) (MOVDconst [d])) => (MOVDconst [int64(int32(c)%int32(d))]) +(UMODW (MOVDconst [c]) (MOVDconst [d])) => (MOVDconst [int64(uint32(c)%uint32(d))]) +(ANDconst [c] (MOVDconst [d])) => (MOVDconst [c&d]) +(ANDconst [c] (ANDconst [d] x)) => (ANDconst [c&d] x) +(ANDconst [c] (MOVWUreg x)) => (ANDconst [c&(1<<32-1)] x) +(ANDconst [c] (MOVHUreg x)) => (ANDconst [c&(1<<16-1)] x) +(ANDconst [c] (MOVBUreg x)) => (ANDconst [c&(1<<8-1)] x) +(MOVWUreg (ANDconst [c] x)) => (ANDconst [c&(1<<32-1)] x) +(MOVHUreg (ANDconst [c] x)) => (ANDconst [c&(1<<16-1)] x) +(MOVBUreg (ANDconst [c] x)) => (ANDconst [c&(1<<8-1)] x) +(ORconst [c] (MOVDconst [d])) => (MOVDconst [c|d]) +(ORconst [c] (ORconst [d] x)) => (ORconst [c|d] x) +(XORconst [c] (MOVDconst [d])) => (MOVDconst [c^d]) +(XORconst [c] (XORconst [d] x)) => (XORconst [c^d] x) +(MVN (MOVDconst [c])) => (MOVDconst [^c]) +(NEG (MOVDconst [c])) => (MOVDconst [-c]) +(MOVBreg (MOVDconst [c])) => (MOVDconst [int64(int8(c))]) +(MOVBUreg (MOVDconst [c])) => (MOVDconst [int64(uint8(c))]) +(MOVHreg (MOVDconst [c])) => (MOVDconst [int64(int16(c))]) +(MOVHUreg (MOVDconst [c])) => (MOVDconst [int64(uint16(c))]) +(MOVWreg (MOVDconst [c])) => (MOVDconst [int64(int32(c))]) +(MOVWUreg (MOVDconst [c])) => (MOVDconst [int64(uint32(c))]) +(MOVDreg (MOVDconst [c])) => (MOVDconst [c]) // constant comparisons (CMPconst (MOVDconst [x]) [y]) => (FlagConstant [subFlags64(x,y)]) diff --git a/src/cmd/compile/internal/ssa/rewriteARM64.go b/src/cmd/compile/internal/ssa/rewriteARM64.go index 0fb86b6bdd..6c48812121 100644 --- a/src/cmd/compile/internal/ssa/rewriteARM64.go +++ b/src/cmd/compile/internal/ssa/rewriteARM64.go @@ -1065,7 +1065,7 @@ func rewriteValueARM64_OpARM64ADCSflags(v *Value) bool { break } v_2_0 := v_2.Args[0] - if v_2_0.Op != OpARM64ADDSconstflags || v_2_0.AuxInt != -1 { + if v_2_0.Op != OpARM64ADDSconstflags || auxIntToInt64(v_2_0.AuxInt) != -1 { break } v_2_0_0 := v_2_0.Args[0] @@ -1086,11 +1086,11 @@ func rewriteValueARM64_OpARM64ADCSflags(v *Value) bool { break } v_2_0 := v_2.Args[0] - if v_2_0.Op != OpARM64ADDSconstflags || v_2_0.AuxInt != -1 { + if v_2_0.Op != OpARM64ADDSconstflags || auxIntToInt64(v_2_0.AuxInt) != -1 { break } v_2_0_0 := v_2_0.Args[0] - if v_2_0_0.Op != OpARM64MOVDconst || v_2_0_0.AuxInt != 0 { + if v_2_0_0.Op != OpARM64MOVDconst || auxIntToInt64(v_2_0_0.AuxInt) != 0 { break } v.reset(OpARM64ADDSflags) @@ -1112,9 +1112,9 @@ func rewriteValueARM64_OpARM64ADD(v *Value) bool { if v_1.Op != OpARM64MOVDconst { continue } - c := v_1.AuxInt + c := auxIntToInt64(v_1.AuxInt) v.reset(OpARM64ADDconst) - v.AuxInt = c + v.AuxInt = int64ToAuxInt(c) v.AddArg(x) return true } @@ -1593,7 +1593,7 @@ func rewriteValueARM64_OpARM64ADDconst(v *Value) bool { // match: (ADDconst [0] x) // result: x for { - if v.AuxInt != 0 { + if auxIntToInt64(v.AuxInt) != 0 { break } x := v_0 @@ -1603,40 +1603,40 @@ func rewriteValueARM64_OpARM64ADDconst(v *Value) bool { // match: (ADDconst [c] (MOVDconst [d])) // result: (MOVDconst [c+d]) for { - c := v.AuxInt + c := auxIntToInt64(v.AuxInt) if v_0.Op != OpARM64MOVDconst { break } - d := v_0.AuxInt + d := auxIntToInt64(v_0.AuxInt) v.reset(OpARM64MOVDconst) - v.AuxInt = c + d + v.AuxInt = int64ToAuxInt(c + d) return true } // match: (ADDconst [c] (ADDconst [d] x)) // result: (ADDconst [c+d] x) for { - c := v.AuxInt + c := auxIntToInt64(v.AuxInt) if v_0.Op != OpARM64ADDconst { break } - d := v_0.AuxInt + d := auxIntToInt64(v_0.AuxInt) x := v_0.Args[0] v.reset(OpARM64ADDconst) - v.AuxInt = c + d + v.AuxInt = int64ToAuxInt(c + d) v.AddArg(x) return true } // match: (ADDconst [c] (SUBconst [d] x)) // result: (ADDconst [c-d] x) for { - c := v.AuxInt + c := auxIntToInt64(v.AuxInt) if v_0.Op != OpARM64SUBconst { break } - d := v_0.AuxInt + d := auxIntToInt64(v_0.AuxInt) x := v_0.Args[0] v.reset(OpARM64ADDconst) - v.AuxInt = c - d + v.AuxInt = int64ToAuxInt(c - d) v.AddArg(x) return true } @@ -1882,9 +1882,9 @@ func rewriteValueARM64_OpARM64AND(v *Value) bool { if v_1.Op != OpARM64MOVDconst { continue } - c := v_1.AuxInt + c := auxIntToInt64(v_1.AuxInt) v.reset(OpARM64ANDconst) - v.AuxInt = c + v.AuxInt = int64ToAuxInt(c) v.AddArg(x) return true } @@ -1988,17 +1988,17 @@ func rewriteValueARM64_OpARM64ANDconst(v *Value) bool { // match: (ANDconst [0] _) // result: (MOVDconst [0]) for { - if v.AuxInt != 0 { + if auxIntToInt64(v.AuxInt) != 0 { break } v.reset(OpARM64MOVDconst) - v.AuxInt = 0 + v.AuxInt = int64ToAuxInt(0) return true } // match: (ANDconst [-1] x) // result: x for { - if v.AuxInt != -1 { + if auxIntToInt64(v.AuxInt) != -1 { break } x := v_0 @@ -2008,65 +2008,65 @@ func rewriteValueARM64_OpARM64ANDconst(v *Value) bool { // match: (ANDconst [c] (MOVDconst [d])) // result: (MOVDconst [c&d]) for { - c := v.AuxInt + c := auxIntToInt64(v.AuxInt) if v_0.Op != OpARM64MOVDconst { break } - d := v_0.AuxInt + d := auxIntToInt64(v_0.AuxInt) v.reset(OpARM64MOVDconst) - v.AuxInt = c & d + v.AuxInt = int64ToAuxInt(c & d) return true } // match: (ANDconst [c] (ANDconst [d] x)) // result: (ANDconst [c&d] x) for { - c := v.AuxInt + c := auxIntToInt64(v.AuxInt) if v_0.Op != OpARM64ANDconst { break } - d := v_0.AuxInt + d := auxIntToInt64(v_0.AuxInt) x := v_0.Args[0] v.reset(OpARM64ANDconst) - v.AuxInt = c & d + v.AuxInt = int64ToAuxInt(c & d) v.AddArg(x) return true } // match: (ANDconst [c] (MOVWUreg x)) // result: (ANDconst [c&(1<<32-1)] x) for { - c := v.AuxInt + c := auxIntToInt64(v.AuxInt) if v_0.Op != OpARM64MOVWUreg { break } x := v_0.Args[0] v.reset(OpARM64ANDconst) - v.AuxInt = c & (1<<32 - 1) + v.AuxInt = int64ToAuxInt(c & (1<<32 - 1)) v.AddArg(x) return true } // match: (ANDconst [c] (MOVHUreg x)) // result: (ANDconst [c&(1<<16-1)] x) for { - c := v.AuxInt + c := auxIntToInt64(v.AuxInt) if v_0.Op != OpARM64MOVHUreg { break } x := v_0.Args[0] v.reset(OpARM64ANDconst) - v.AuxInt = c & (1<<16 - 1) + v.AuxInt = int64ToAuxInt(c & (1<<16 - 1)) v.AddArg(x) return true } // match: (ANDconst [c] (MOVBUreg x)) // result: (ANDconst [c&(1<<8-1)] x) for { - c := v.AuxInt + c := auxIntToInt64(v.AuxInt) if v_0.Op != OpARM64MOVBUreg { break } x := v_0.Args[0] v.reset(OpARM64ANDconst) - v.AuxInt = c & (1<<8 - 1) + v.AuxInt = int64ToAuxInt(c & (1<<8 - 1)) v.AddArg(x) return true } @@ -2280,9 +2280,9 @@ func rewriteValueARM64_OpARM64BIC(v *Value) bool { if v_1.Op != OpARM64MOVDconst { break } - c := v_1.AuxInt + c := auxIntToInt64(v_1.AuxInt) v.reset(OpARM64ANDconst) - v.AuxInt = ^c + v.AuxInt = int64ToAuxInt(^c) v.AddArg(x) return true } @@ -2294,7 +2294,7 @@ func rewriteValueARM64_OpARM64BIC(v *Value) bool { break } v.reset(OpARM64MOVDconst) - v.AuxInt = 0 + v.AuxInt = int64ToAuxInt(0) return true } // match: (BIC x0 x1:(SLLconst [c] y)) @@ -2475,9 +2475,9 @@ func rewriteValueARM64_OpARM64CMN(v *Value) bool { if v_1.Op != OpARM64MOVDconst { continue } - c := v_1.AuxInt + c := auxIntToInt64(v_1.AuxInt) v.reset(OpARM64CMNconst) - v.AuxInt = c + v.AuxInt = int64ToAuxInt(c) v.AddArg(x) return true } @@ -2555,16 +2555,16 @@ func rewriteValueARM64_OpARM64CMNW(v *Value) bool { v_1 := v.Args[1] v_0 := v.Args[0] // match: (CMNW x (MOVDconst [c])) - // result: (CMNWconst [c] x) + // result: (CMNWconst [int32(c)] x) for { for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { x := v_0 if v_1.Op != OpARM64MOVDconst { continue } - c := v_1.AuxInt + c := auxIntToInt64(v_1.AuxInt) v.reset(OpARM64CMNWconst) - v.AuxInt = c + v.AuxInt = int32ToAuxInt(int32(c)) v.AddArg(x) return true } @@ -2726,9 +2726,9 @@ func rewriteValueARM64_OpARM64CMP(v *Value) bool { if v_1.Op != OpARM64MOVDconst { break } - c := v_1.AuxInt + c := auxIntToInt64(v_1.AuxInt) v.reset(OpARM64CMPconst) - v.AuxInt = c + v.AuxInt = int64ToAuxInt(c) v.AddArg(x) return true } @@ -2738,11 +2738,11 @@ func rewriteValueARM64_OpARM64CMP(v *Value) bool { if v_0.Op != OpARM64MOVDconst { break } - c := v_0.AuxInt + c := auxIntToInt64(v_0.AuxInt) x := v_1 v.reset(OpARM64InvertFlags) v0 := b.NewValue0(v.Pos, OpARM64CMPconst, types.TypeFlags) - v0.AuxInt = c + v0.AuxInt = int64ToAuxInt(c) v0.AddArg(x) v.AddArg(v0) return true @@ -3377,13 +3377,13 @@ func rewriteValueARM64_OpARM64DIV(v *Value) bool { if v_0.Op != OpARM64MOVDconst { break } - c := v_0.AuxInt + c := auxIntToInt64(v_0.AuxInt) if v_1.Op != OpARM64MOVDconst { break } - d := v_1.AuxInt + d := auxIntToInt64(v_1.AuxInt) v.reset(OpARM64MOVDconst) - v.AuxInt = c / d + v.AuxInt = int64ToAuxInt(c / d) return true } return false @@ -3397,13 +3397,13 @@ func rewriteValueARM64_OpARM64DIVW(v *Value) bool { if v_0.Op != OpARM64MOVDconst { break } - c := v_0.AuxInt + c := auxIntToInt64(v_0.AuxInt) if v_1.Op != OpARM64MOVDconst { break } - d := v_1.AuxInt + d := auxIntToInt64(v_1.AuxInt) v.reset(OpARM64MOVDconst) - v.AuxInt = int64(int32(c) / int32(d)) + v.AuxInt = int64ToAuxInt(int64(int32(c) / int32(d))) return true } return false @@ -3418,9 +3418,9 @@ func rewriteValueARM64_OpARM64EON(v *Value) bool { if v_1.Op != OpARM64MOVDconst { break } - c := v_1.AuxInt + c := auxIntToInt64(v_1.AuxInt) v.reset(OpARM64XORconst) - v.AuxInt = ^c + v.AuxInt = int64ToAuxInt(^c) v.AddArg(x) return true } @@ -3432,7 +3432,7 @@ func rewriteValueARM64_OpARM64EON(v *Value) bool { break } v.reset(OpARM64MOVDconst) - v.AuxInt = -1 + v.AuxInt = int64ToAuxInt(-1) return true } // match: (EON x0 x1:(SLLconst [c] y)) @@ -4858,7 +4858,7 @@ func rewriteValueARM64_OpARM64MADD(v *Value) bool { for { a := v_0 x := v_1 - if v_2.Op != OpARM64MOVDconst || v_2.AuxInt != -1 { + if v_2.Op != OpARM64MOVDconst || auxIntToInt64(v_2.AuxInt) != -1 { break } v.reset(OpARM64SUB) @@ -4869,7 +4869,7 @@ func rewriteValueARM64_OpARM64MADD(v *Value) bool { // result: a for { a := v_0 - if v_2.Op != OpARM64MOVDconst || v_2.AuxInt != 0 { + if v_2.Op != OpARM64MOVDconst || auxIntToInt64(v_2.AuxInt) != 0 { break } v.copyOf(a) @@ -4880,7 +4880,7 @@ func rewriteValueARM64_OpARM64MADD(v *Value) bool { for { a := v_0 x := v_1 - if v_2.Op != OpARM64MOVDconst || v_2.AuxInt != 1 { + if v_2.Op != OpARM64MOVDconst || auxIntToInt64(v_2.AuxInt) != 1 { break } v.reset(OpARM64ADD) @@ -4896,12 +4896,12 @@ func rewriteValueARM64_OpARM64MADD(v *Value) bool { if v_2.Op != OpARM64MOVDconst { break } - c := v_2.AuxInt + c := auxIntToInt64(v_2.AuxInt) if !(isPowerOfTwo(c)) { break } v.reset(OpARM64ADDshiftLL) - v.AuxInt = log2(c) + v.AuxInt = int64ToAuxInt(log2(c)) v.AddArg2(a, x) return true } @@ -4914,13 +4914,13 @@ func rewriteValueARM64_OpARM64MADD(v *Value) bool { if v_2.Op != OpARM64MOVDconst { break } - c := v_2.AuxInt + c := auxIntToInt64(v_2.AuxInt) if !(isPowerOfTwo(c-1) && c >= 3) { break } v.reset(OpARM64ADD) v0 := b.NewValue0(v.Pos, OpARM64ADDshiftLL, x.Type) - v0.AuxInt = log2(c - 1) + v0.AuxInt = int64ToAuxInt(log2(c - 1)) v0.AddArg2(x, x) v.AddArg2(a, v0) return true @@ -4934,13 +4934,13 @@ func rewriteValueARM64_OpARM64MADD(v *Value) bool { if v_2.Op != OpARM64MOVDconst { break } - c := v_2.AuxInt + c := auxIntToInt64(v_2.AuxInt) if !(isPowerOfTwo(c+1) && c >= 7) { break } v.reset(OpARM64SUB) v0 := b.NewValue0(v.Pos, OpARM64SUBshiftLL, x.Type) - v0.AuxInt = log2(c + 1) + v0.AuxInt = int64ToAuxInt(log2(c + 1)) v0.AddArg2(x, x) v.AddArg2(a, v0) return true @@ -4954,14 +4954,14 @@ func rewriteValueARM64_OpARM64MADD(v *Value) bool { if v_2.Op != OpARM64MOVDconst { break } - c := v_2.AuxInt + c := auxIntToInt64(v_2.AuxInt) if !(c%3 == 0 && isPowerOfTwo(c/3)) { break } v.reset(OpARM64SUBshiftLL) - v.AuxInt = log2(c / 3) + v.AuxInt = int64ToAuxInt(log2(c / 3)) v0 := b.NewValue0(v.Pos, OpARM64SUBshiftLL, x.Type) - v0.AuxInt = 2 + v0.AuxInt = int64ToAuxInt(2) v0.AddArg2(x, x) v.AddArg2(a, v0) return true @@ -4975,14 +4975,14 @@ func rewriteValueARM64_OpARM64MADD(v *Value) bool { if v_2.Op != OpARM64MOVDconst { break } - c := v_2.AuxInt + c := auxIntToInt64(v_2.AuxInt) if !(c%5 == 0 && isPowerOfTwo(c/5)) { break } v.reset(OpARM64ADDshiftLL) - v.AuxInt = log2(c / 5) + v.AuxInt = int64ToAuxInt(log2(c / 5)) v0 := b.NewValue0(v.Pos, OpARM64ADDshiftLL, x.Type) - v0.AuxInt = 2 + v0.AuxInt = int64ToAuxInt(2) v0.AddArg2(x, x) v.AddArg2(a, v0) return true @@ -4996,14 +4996,14 @@ func rewriteValueARM64_OpARM64MADD(v *Value) bool { if v_2.Op != OpARM64MOVDconst { break } - c := v_2.AuxInt + c := auxIntToInt64(v_2.AuxInt) if !(c%7 == 0 && isPowerOfTwo(c/7)) { break } v.reset(OpARM64SUBshiftLL) - v.AuxInt = log2(c / 7) + v.AuxInt = int64ToAuxInt(log2(c / 7)) v0 := b.NewValue0(v.Pos, OpARM64SUBshiftLL, x.Type) - v0.AuxInt = 3 + v0.AuxInt = int64ToAuxInt(3) v0.AddArg2(x, x) v.AddArg2(a, v0) return true @@ -5017,14 +5017,14 @@ func rewriteValueARM64_OpARM64MADD(v *Value) bool { if v_2.Op != OpARM64MOVDconst { break } - c := v_2.AuxInt + c := auxIntToInt64(v_2.AuxInt) if !(c%9 == 0 && isPowerOfTwo(c/9)) { break } v.reset(OpARM64ADDshiftLL) - v.AuxInt = log2(c / 9) + v.AuxInt = int64ToAuxInt(log2(c / 9)) v0 := b.NewValue0(v.Pos, OpARM64ADDshiftLL, x.Type) - v0.AuxInt = 3 + v0.AuxInt = int64ToAuxInt(3) v0.AddArg2(x, x) v.AddArg2(a, v0) return true @@ -5033,7 +5033,7 @@ func rewriteValueARM64_OpARM64MADD(v *Value) bool { // result: (SUB a x) for { a := v_0 - if v_1.Op != OpARM64MOVDconst || v_1.AuxInt != -1 { + if v_1.Op != OpARM64MOVDconst || auxIntToInt64(v_1.AuxInt) != -1 { break } x := v_2 @@ -5045,7 +5045,7 @@ func rewriteValueARM64_OpARM64MADD(v *Value) bool { // result: a for { a := v_0 - if v_1.Op != OpARM64MOVDconst || v_1.AuxInt != 0 { + if v_1.Op != OpARM64MOVDconst || auxIntToInt64(v_1.AuxInt) != 0 { break } v.copyOf(a) @@ -5055,7 +5055,7 @@ func rewriteValueARM64_OpARM64MADD(v *Value) bool { // result: (ADD a x) for { a := v_0 - if v_1.Op != OpARM64MOVDconst || v_1.AuxInt != 1 { + if v_1.Op != OpARM64MOVDconst || auxIntToInt64(v_1.AuxInt) != 1 { break } x := v_2 @@ -5071,13 +5071,13 @@ func rewriteValueARM64_OpARM64MADD(v *Value) bool { if v_1.Op != OpARM64MOVDconst { break } - c := v_1.AuxInt + c := auxIntToInt64(v_1.AuxInt) x := v_2 if !(isPowerOfTwo(c)) { break } v.reset(OpARM64ADDshiftLL) - v.AuxInt = log2(c) + v.AuxInt = int64ToAuxInt(log2(c)) v.AddArg2(a, x) return true } @@ -5089,14 +5089,14 @@ func rewriteValueARM64_OpARM64MADD(v *Value) bool { if v_1.Op != OpARM64MOVDconst { break } - c := v_1.AuxInt + c := auxIntToInt64(v_1.AuxInt) x := v_2 if !(isPowerOfTwo(c-1) && c >= 3) { break } v.reset(OpARM64ADD) v0 := b.NewValue0(v.Pos, OpARM64ADDshiftLL, x.Type) - v0.AuxInt = log2(c - 1) + v0.AuxInt = int64ToAuxInt(log2(c - 1)) v0.AddArg2(x, x) v.AddArg2(a, v0) return true @@ -5109,14 +5109,14 @@ func rewriteValueARM64_OpARM64MADD(v *Value) bool { if v_1.Op != OpARM64MOVDconst { break } - c := v_1.AuxInt + c := auxIntToInt64(v_1.AuxInt) x := v_2 if !(isPowerOfTwo(c+1) && c >= 7) { break } v.reset(OpARM64SUB) v0 := b.NewValue0(v.Pos, OpARM64SUBshiftLL, x.Type) - v0.AuxInt = log2(c + 1) + v0.AuxInt = int64ToAuxInt(log2(c + 1)) v0.AddArg2(x, x) v.AddArg2(a, v0) return true @@ -5129,15 +5129,15 @@ func rewriteValueARM64_OpARM64MADD(v *Value) bool { if v_1.Op != OpARM64MOVDconst { break } - c := v_1.AuxInt + c := auxIntToInt64(v_1.AuxInt) x := v_2 if !(c%3 == 0 && isPowerOfTwo(c/3)) { break } v.reset(OpARM64SUBshiftLL) - v.AuxInt = log2(c / 3) + v.AuxInt = int64ToAuxInt(log2(c / 3)) v0 := b.NewValue0(v.Pos, OpARM64SUBshiftLL, x.Type) - v0.AuxInt = 2 + v0.AuxInt = int64ToAuxInt(2) v0.AddArg2(x, x) v.AddArg2(a, v0) return true @@ -5150,15 +5150,15 @@ func rewriteValueARM64_OpARM64MADD(v *Value) bool { if v_1.Op != OpARM64MOVDconst { break } - c := v_1.AuxInt + c := auxIntToInt64(v_1.AuxInt) x := v_2 if !(c%5 == 0 && isPowerOfTwo(c/5)) { break } v.reset(OpARM64ADDshiftLL) - v.AuxInt = log2(c / 5) + v.AuxInt = int64ToAuxInt(log2(c / 5)) v0 := b.NewValue0(v.Pos, OpARM64ADDshiftLL, x.Type) - v0.AuxInt = 2 + v0.AuxInt = int64ToAuxInt(2) v0.AddArg2(x, x) v.AddArg2(a, v0) return true @@ -5171,15 +5171,15 @@ func rewriteValueARM64_OpARM64MADD(v *Value) bool { if v_1.Op != OpARM64MOVDconst { break } - c := v_1.AuxInt + c := auxIntToInt64(v_1.AuxInt) x := v_2 if !(c%7 == 0 && isPowerOfTwo(c/7)) { break } v.reset(OpARM64SUBshiftLL) - v.AuxInt = log2(c / 7) + v.AuxInt = int64ToAuxInt(log2(c / 7)) v0 := b.NewValue0(v.Pos, OpARM64SUBshiftLL, x.Type) - v0.AuxInt = 3 + v0.AuxInt = int64ToAuxInt(3) v0.AddArg2(x, x) v.AddArg2(a, v0) return true @@ -5192,15 +5192,15 @@ func rewriteValueARM64_OpARM64MADD(v *Value) bool { if v_1.Op != OpARM64MOVDconst { break } - c := v_1.AuxInt + c := auxIntToInt64(v_1.AuxInt) x := v_2 if !(c%9 == 0 && isPowerOfTwo(c/9)) { break } v.reset(OpARM64ADDshiftLL) - v.AuxInt = log2(c / 9) + v.AuxInt = int64ToAuxInt(log2(c / 9)) v0 := b.NewValue0(v.Pos, OpARM64ADDshiftLL, x.Type) - v0.AuxInt = 3 + v0.AuxInt = int64ToAuxInt(3) v0.AddArg2(x, x) v.AddArg2(a, v0) return true @@ -5211,11 +5211,11 @@ func rewriteValueARM64_OpARM64MADD(v *Value) bool { if v_0.Op != OpARM64MOVDconst { break } - c := v_0.AuxInt + c := auxIntToInt64(v_0.AuxInt) x := v_1 y := v_2 v.reset(OpARM64ADDconst) - v.AuxInt = c + v.AuxInt = int64ToAuxInt(c) v0 := b.NewValue0(v.Pos, OpARM64MUL, x.Type) v0.AddArg2(x, y) v.AddArg(v0) @@ -5228,13 +5228,13 @@ func rewriteValueARM64_OpARM64MADD(v *Value) bool { if v_1.Op != OpARM64MOVDconst { break } - c := v_1.AuxInt + c := auxIntToInt64(v_1.AuxInt) if v_2.Op != OpARM64MOVDconst { break } - d := v_2.AuxInt + d := auxIntToInt64(v_2.AuxInt) v.reset(OpARM64ADDconst) - v.AuxInt = c * d + v.AuxInt = int64ToAuxInt(c * d) v.AddArg(a) return true } @@ -5254,7 +5254,7 @@ func rewriteValueARM64_OpARM64MADDW(v *Value) bool { if v_2.Op != OpARM64MOVDconst { break } - c := v_2.AuxInt + c := auxIntToInt64(v_2.AuxInt) if !(int32(c) == -1) { break } @@ -5270,7 +5270,7 @@ func rewriteValueARM64_OpARM64MADDW(v *Value) bool { if v_2.Op != OpARM64MOVDconst { break } - c := v_2.AuxInt + c := auxIntToInt64(v_2.AuxInt) if !(int32(c) == 0) { break } @@ -5286,7 +5286,7 @@ func rewriteValueARM64_OpARM64MADDW(v *Value) bool { if v_2.Op != OpARM64MOVDconst { break } - c := v_2.AuxInt + c := auxIntToInt64(v_2.AuxInt) if !(int32(c) == 1) { break } @@ -5303,12 +5303,12 @@ func rewriteValueARM64_OpARM64MADDW(v *Value) bool { if v_2.Op != OpARM64MOVDconst { break } - c := v_2.AuxInt + c := auxIntToInt64(v_2.AuxInt) if !(isPowerOfTwo(c)) { break } v.reset(OpARM64ADDshiftLL) - v.AuxInt = log2(c) + v.AuxInt = int64ToAuxInt(log2(c)) v.AddArg2(a, x) return true } @@ -5321,13 +5321,13 @@ func rewriteValueARM64_OpARM64MADDW(v *Value) bool { if v_2.Op != OpARM64MOVDconst { break } - c := v_2.AuxInt + c := auxIntToInt64(v_2.AuxInt) if !(isPowerOfTwo(c-1) && int32(c) >= 3) { break } v.reset(OpARM64ADD) v0 := b.NewValue0(v.Pos, OpARM64ADDshiftLL, x.Type) - v0.AuxInt = log2(c - 1) + v0.AuxInt = int64ToAuxInt(log2(c - 1)) v0.AddArg2(x, x) v.AddArg2(a, v0) return true @@ -5341,13 +5341,13 @@ func rewriteValueARM64_OpARM64MADDW(v *Value) bool { if v_2.Op != OpARM64MOVDconst { break } - c := v_2.AuxInt + c := auxIntToInt64(v_2.AuxInt) if !(isPowerOfTwo(c+1) && int32(c) >= 7) { break } v.reset(OpARM64SUB) v0 := b.NewValue0(v.Pos, OpARM64SUBshiftLL, x.Type) - v0.AuxInt = log2(c + 1) + v0.AuxInt = int64ToAuxInt(log2(c + 1)) v0.AddArg2(x, x) v.AddArg2(a, v0) return true @@ -5361,14 +5361,14 @@ func rewriteValueARM64_OpARM64MADDW(v *Value) bool { if v_2.Op != OpARM64MOVDconst { break } - c := v_2.AuxInt + c := auxIntToInt64(v_2.AuxInt) if !(c%3 == 0 && isPowerOfTwo(c/3) && is32Bit(c)) { break } v.reset(OpARM64SUBshiftLL) - v.AuxInt = log2(c / 3) + v.AuxInt = int64ToAuxInt(log2(c / 3)) v0 := b.NewValue0(v.Pos, OpARM64SUBshiftLL, x.Type) - v0.AuxInt = 2 + v0.AuxInt = int64ToAuxInt(2) v0.AddArg2(x, x) v.AddArg2(a, v0) return true @@ -5382,14 +5382,14 @@ func rewriteValueARM64_OpARM64MADDW(v *Value) bool { if v_2.Op != OpARM64MOVDconst { break } - c := v_2.AuxInt + c := auxIntToInt64(v_2.AuxInt) if !(c%5 == 0 && isPowerOfTwo(c/5) && is32Bit(c)) { break } v.reset(OpARM64ADDshiftLL) - v.AuxInt = log2(c / 5) + v.AuxInt = int64ToAuxInt(log2(c / 5)) v0 := b.NewValue0(v.Pos, OpARM64ADDshiftLL, x.Type) - v0.AuxInt = 2 + v0.AuxInt = int64ToAuxInt(2) v0.AddArg2(x, x) v.AddArg2(a, v0) return true @@ -5403,14 +5403,14 @@ func rewriteValueARM64_OpARM64MADDW(v *Value) bool { if v_2.Op != OpARM64MOVDconst { break } - c := v_2.AuxInt + c := auxIntToInt64(v_2.AuxInt) if !(c%7 == 0 && isPowerOfTwo(c/7) && is32Bit(c)) { break } v.reset(OpARM64SUBshiftLL) - v.AuxInt = log2(c / 7) + v.AuxInt = int64ToAuxInt(log2(c / 7)) v0 := b.NewValue0(v.Pos, OpARM64SUBshiftLL, x.Type) - v0.AuxInt = 3 + v0.AuxInt = int64ToAuxInt(3) v0.AddArg2(x, x) v.AddArg2(a, v0) return true @@ -5424,14 +5424,14 @@ func rewriteValueARM64_OpARM64MADDW(v *Value) bool { if v_2.Op != OpARM64MOVDconst { break } - c := v_2.AuxInt + c := auxIntToInt64(v_2.AuxInt) if !(c%9 == 0 && isPowerOfTwo(c/9) && is32Bit(c)) { break } v.reset(OpARM64ADDshiftLL) - v.AuxInt = log2(c / 9) + v.AuxInt = int64ToAuxInt(log2(c / 9)) v0 := b.NewValue0(v.Pos, OpARM64ADDshiftLL, x.Type) - v0.AuxInt = 3 + v0.AuxInt = int64ToAuxInt(3) v0.AddArg2(x, x) v.AddArg2(a, v0) return true @@ -5444,7 +5444,7 @@ func rewriteValueARM64_OpARM64MADDW(v *Value) bool { if v_1.Op != OpARM64MOVDconst { break } - c := v_1.AuxInt + c := auxIntToInt64(v_1.AuxInt) x := v_2 if !(int32(c) == -1) { break @@ -5461,7 +5461,7 @@ func rewriteValueARM64_OpARM64MADDW(v *Value) bool { if v_1.Op != OpARM64MOVDconst { break } - c := v_1.AuxInt + c := auxIntToInt64(v_1.AuxInt) if !(int32(c) == 0) { break } @@ -5476,7 +5476,7 @@ func rewriteValueARM64_OpARM64MADDW(v *Value) bool { if v_1.Op != OpARM64MOVDconst { break } - c := v_1.AuxInt + c := auxIntToInt64(v_1.AuxInt) x := v_2 if !(int32(c) == 1) { break @@ -5493,13 +5493,13 @@ func rewriteValueARM64_OpARM64MADDW(v *Value) bool { if v_1.Op != OpARM64MOVDconst { break } - c := v_1.AuxInt + c := auxIntToInt64(v_1.AuxInt) x := v_2 if !(isPowerOfTwo(c)) { break } v.reset(OpARM64ADDshiftLL) - v.AuxInt = log2(c) + v.AuxInt = int64ToAuxInt(log2(c)) v.AddArg2(a, x) return true } @@ -5511,14 +5511,14 @@ func rewriteValueARM64_OpARM64MADDW(v *Value) bool { if v_1.Op != OpARM64MOVDconst { break } - c := v_1.AuxInt + c := auxIntToInt64(v_1.AuxInt) x := v_2 if !(isPowerOfTwo(c-1) && int32(c) >= 3) { break } v.reset(OpARM64ADD) v0 := b.NewValue0(v.Pos, OpARM64ADDshiftLL, x.Type) - v0.AuxInt = log2(c - 1) + v0.AuxInt = int64ToAuxInt(log2(c - 1)) v0.AddArg2(x, x) v.AddArg2(a, v0) return true @@ -5531,14 +5531,14 @@ func rewriteValueARM64_OpARM64MADDW(v *Value) bool { if v_1.Op != OpARM64MOVDconst { break } - c := v_1.AuxInt + c := auxIntToInt64(v_1.AuxInt) x := v_2 if !(isPowerOfTwo(c+1) && int32(c) >= 7) { break } v.reset(OpARM64SUB) v0 := b.NewValue0(v.Pos, OpARM64SUBshiftLL, x.Type) - v0.AuxInt = log2(c + 1) + v0.AuxInt = int64ToAuxInt(log2(c + 1)) v0.AddArg2(x, x) v.AddArg2(a, v0) return true @@ -5551,15 +5551,15 @@ func rewriteValueARM64_OpARM64MADDW(v *Value) bool { if v_1.Op != OpARM64MOVDconst { break } - c := v_1.AuxInt + c := auxIntToInt64(v_1.AuxInt) x := v_2 if !(c%3 == 0 && isPowerOfTwo(c/3) && is32Bit(c)) { break } v.reset(OpARM64SUBshiftLL) - v.AuxInt = log2(c / 3) + v.AuxInt = int64ToAuxInt(log2(c / 3)) v0 := b.NewValue0(v.Pos, OpARM64SUBshiftLL, x.Type) - v0.AuxInt = 2 + v0.AuxInt = int64ToAuxInt(2) v0.AddArg2(x, x) v.AddArg2(a, v0) return true @@ -5572,15 +5572,15 @@ func rewriteValueARM64_OpARM64MADDW(v *Value) bool { if v_1.Op != OpARM64MOVDconst { break } - c := v_1.AuxInt + c := auxIntToInt64(v_1.AuxInt) x := v_2 if !(c%5 == 0 && isPowerOfTwo(c/5) && is32Bit(c)) { break } v.reset(OpARM64ADDshiftLL) - v.AuxInt = log2(c / 5) + v.AuxInt = int64ToAuxInt(log2(c / 5)) v0 := b.NewValue0(v.Pos, OpARM64ADDshiftLL, x.Type) - v0.AuxInt = 2 + v0.AuxInt = int64ToAuxInt(2) v0.AddArg2(x, x) v.AddArg2(a, v0) return true @@ -5593,15 +5593,15 @@ func rewriteValueARM64_OpARM64MADDW(v *Value) bool { if v_1.Op != OpARM64MOVDconst { break } - c := v_1.AuxInt + c := auxIntToInt64(v_1.AuxInt) x := v_2 if !(c%7 == 0 && isPowerOfTwo(c/7) && is32Bit(c)) { break } v.reset(OpARM64SUBshiftLL) - v.AuxInt = log2(c / 7) + v.AuxInt = int64ToAuxInt(log2(c / 7)) v0 := b.NewValue0(v.Pos, OpARM64SUBshiftLL, x.Type) - v0.AuxInt = 3 + v0.AuxInt = int64ToAuxInt(3) v0.AddArg2(x, x) v.AddArg2(a, v0) return true @@ -5614,15 +5614,15 @@ func rewriteValueARM64_OpARM64MADDW(v *Value) bool { if v_1.Op != OpARM64MOVDconst { break } - c := v_1.AuxInt + c := auxIntToInt64(v_1.AuxInt) x := v_2 if !(c%9 == 0 && isPowerOfTwo(c/9) && is32Bit(c)) { break } v.reset(OpARM64ADDshiftLL) - v.AuxInt = log2(c / 9) + v.AuxInt = int64ToAuxInt(log2(c / 9)) v0 := b.NewValue0(v.Pos, OpARM64ADDshiftLL, x.Type) - v0.AuxInt = 3 + v0.AuxInt = int64ToAuxInt(3) v0.AddArg2(x, x) v.AddArg2(a, v0) return true @@ -5633,11 +5633,11 @@ func rewriteValueARM64_OpARM64MADDW(v *Value) bool { if v_0.Op != OpARM64MOVDconst { break } - c := v_0.AuxInt + c := auxIntToInt64(v_0.AuxInt) x := v_1 y := v_2 v.reset(OpARM64ADDconst) - v.AuxInt = c + v.AuxInt = int64ToAuxInt(c) v0 := b.NewValue0(v.Pos, OpARM64MULW, x.Type) v0.AddArg2(x, y) v.AddArg(v0) @@ -5650,13 +5650,13 @@ func rewriteValueARM64_OpARM64MADDW(v *Value) bool { if v_1.Op != OpARM64MOVDconst { break } - c := v_1.AuxInt + c := auxIntToInt64(v_1.AuxInt) if v_2.Op != OpARM64MOVDconst { break } - d := v_2.AuxInt + d := auxIntToInt64(v_2.AuxInt) v.reset(OpARM64ADDconst) - v.AuxInt = int64(int32(c) * int32(d)) + v.AuxInt = int64ToAuxInt(int64(int32(c) * int32(d))) v.AddArg(a) return true } @@ -5671,7 +5671,7 @@ func rewriteValueARM64_OpARM64MNEG(v *Value) bool { for { for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { x := v_0 - if v_1.Op != OpARM64MOVDconst || v_1.AuxInt != -1 { + if v_1.Op != OpARM64MOVDconst || auxIntToInt64(v_1.AuxInt) != -1 { continue } v.copyOf(x) @@ -5683,11 +5683,11 @@ func rewriteValueARM64_OpARM64MNEG(v *Value) bool { // result: (MOVDconst [0]) for { for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - if v_1.Op != OpARM64MOVDconst || v_1.AuxInt != 0 { + if v_1.Op != OpARM64MOVDconst || auxIntToInt64(v_1.AuxInt) != 0 { continue } v.reset(OpARM64MOVDconst) - v.AuxInt = 0 + v.AuxInt = int64ToAuxInt(0) return true } break @@ -5697,7 +5697,7 @@ func rewriteValueARM64_OpARM64MNEG(v *Value) bool { for { for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { x := v_0 - if v_1.Op != OpARM64MOVDconst || v_1.AuxInt != 1 { + if v_1.Op != OpARM64MOVDconst || auxIntToInt64(v_1.AuxInt) != 1 { continue } v.reset(OpARM64NEG) @@ -5715,13 +5715,13 @@ func rewriteValueARM64_OpARM64MNEG(v *Value) bool { if v_1.Op != OpARM64MOVDconst { continue } - c := v_1.AuxInt + c := auxIntToInt64(v_1.AuxInt) if !(isPowerOfTwo(c)) { continue } v.reset(OpARM64NEG) v0 := b.NewValue0(v.Pos, OpARM64SLLconst, x.Type) - v0.AuxInt = log2(c) + v0.AuxInt = int64ToAuxInt(log2(c)) v0.AddArg(x) v.AddArg(v0) return true @@ -5737,13 +5737,13 @@ func rewriteValueARM64_OpARM64MNEG(v *Value) bool { if v_1.Op != OpARM64MOVDconst { continue } - c := v_1.AuxInt + c := auxIntToInt64(v_1.AuxInt) if !(isPowerOfTwo(c-1) && c >= 3) { continue } v.reset(OpARM64NEG) v0 := b.NewValue0(v.Pos, OpARM64ADDshiftLL, x.Type) - v0.AuxInt = log2(c - 1) + v0.AuxInt = int64ToAuxInt(log2(c - 1)) v0.AddArg2(x, x) v.AddArg(v0) return true @@ -5759,13 +5759,13 @@ func rewriteValueARM64_OpARM64MNEG(v *Value) bool { if v_1.Op != OpARM64MOVDconst { continue } - c := v_1.AuxInt + c := auxIntToInt64(v_1.AuxInt) if !(isPowerOfTwo(c+1) && c >= 7) { continue } v.reset(OpARM64NEG) v0 := b.NewValue0(v.Pos, OpARM64ADDshiftLL, x.Type) - v0.AuxInt = log2(c + 1) + v0.AuxInt = int64ToAuxInt(log2(c + 1)) v1 := b.NewValue0(v.Pos, OpARM64NEG, x.Type) v1.AddArg(x) v0.AddArg2(v1, x) @@ -5783,15 +5783,15 @@ func rewriteValueARM64_OpARM64MNEG(v *Value) bool { if v_1.Op != OpARM64MOVDconst { continue } - c := v_1.AuxInt + c := auxIntToInt64(v_1.AuxInt) if !(c%3 == 0 && isPowerOfTwo(c/3)) { continue } v.reset(OpARM64SLLconst) v.Type = x.Type - v.AuxInt = log2(c / 3) + v.AuxInt = int64ToAuxInt(log2(c / 3)) v0 := b.NewValue0(v.Pos, OpARM64SUBshiftLL, x.Type) - v0.AuxInt = 2 + v0.AuxInt = int64ToAuxInt(2) v0.AddArg2(x, x) v.AddArg(v0) return true @@ -5807,15 +5807,15 @@ func rewriteValueARM64_OpARM64MNEG(v *Value) bool { if v_1.Op != OpARM64MOVDconst { continue } - c := v_1.AuxInt + c := auxIntToInt64(v_1.AuxInt) if !(c%5 == 0 && isPowerOfTwo(c/5)) { continue } v.reset(OpARM64NEG) v0 := b.NewValue0(v.Pos, OpARM64SLLconst, x.Type) - v0.AuxInt = log2(c / 5) + v0.AuxInt = int64ToAuxInt(log2(c / 5)) v1 := b.NewValue0(v.Pos, OpARM64ADDshiftLL, x.Type) - v1.AuxInt = 2 + v1.AuxInt = int64ToAuxInt(2) v1.AddArg2(x, x) v0.AddArg(v1) v.AddArg(v0) @@ -5832,15 +5832,15 @@ func rewriteValueARM64_OpARM64MNEG(v *Value) bool { if v_1.Op != OpARM64MOVDconst { continue } - c := v_1.AuxInt + c := auxIntToInt64(v_1.AuxInt) if !(c%7 == 0 && isPowerOfTwo(c/7)) { continue } v.reset(OpARM64SLLconst) v.Type = x.Type - v.AuxInt = log2(c / 7) + v.AuxInt = int64ToAuxInt(log2(c / 7)) v0 := b.NewValue0(v.Pos, OpARM64SUBshiftLL, x.Type) - v0.AuxInt = 3 + v0.AuxInt = int64ToAuxInt(3) v0.AddArg2(x, x) v.AddArg(v0) return true @@ -5856,15 +5856,15 @@ func rewriteValueARM64_OpARM64MNEG(v *Value) bool { if v_1.Op != OpARM64MOVDconst { continue } - c := v_1.AuxInt + c := auxIntToInt64(v_1.AuxInt) if !(c%9 == 0 && isPowerOfTwo(c/9)) { continue } v.reset(OpARM64NEG) v0 := b.NewValue0(v.Pos, OpARM64SLLconst, x.Type) - v0.AuxInt = log2(c / 9) + v0.AuxInt = int64ToAuxInt(log2(c / 9)) v1 := b.NewValue0(v.Pos, OpARM64ADDshiftLL, x.Type) - v1.AuxInt = 3 + v1.AuxInt = int64ToAuxInt(3) v1.AddArg2(x, x) v0.AddArg(v1) v.AddArg(v0) @@ -5879,13 +5879,13 @@ func rewriteValueARM64_OpARM64MNEG(v *Value) bool { if v_0.Op != OpARM64MOVDconst { continue } - c := v_0.AuxInt + c := auxIntToInt64(v_0.AuxInt) if v_1.Op != OpARM64MOVDconst { continue } - d := v_1.AuxInt + d := auxIntToInt64(v_1.AuxInt) v.reset(OpARM64MOVDconst) - v.AuxInt = -c * d + v.AuxInt = int64ToAuxInt(-c * d) return true } break @@ -5905,7 +5905,7 @@ func rewriteValueARM64_OpARM64MNEGW(v *Value) bool { if v_1.Op != OpARM64MOVDconst { continue } - c := v_1.AuxInt + c := auxIntToInt64(v_1.AuxInt) if !(int32(c) == -1) { continue } @@ -5922,12 +5922,12 @@ func rewriteValueARM64_OpARM64MNEGW(v *Value) bool { if v_1.Op != OpARM64MOVDconst { continue } - c := v_1.AuxInt + c := auxIntToInt64(v_1.AuxInt) if !(int32(c) == 0) { continue } v.reset(OpARM64MOVDconst) - v.AuxInt = 0 + v.AuxInt = int64ToAuxInt(0) return true } break @@ -5941,7 +5941,7 @@ func rewriteValueARM64_OpARM64MNEGW(v *Value) bool { if v_1.Op != OpARM64MOVDconst { continue } - c := v_1.AuxInt + c := auxIntToInt64(v_1.AuxInt) if !(int32(c) == 1) { continue } @@ -5960,13 +5960,13 @@ func rewriteValueARM64_OpARM64MNEGW(v *Value) bool { if v_1.Op != OpARM64MOVDconst { continue } - c := v_1.AuxInt + c := auxIntToInt64(v_1.AuxInt) if !(isPowerOfTwo(c)) { continue } v.reset(OpARM64NEG) v0 := b.NewValue0(v.Pos, OpARM64SLLconst, x.Type) - v0.AuxInt = log2(c) + v0.AuxInt = int64ToAuxInt(log2(c)) v0.AddArg(x) v.AddArg(v0) return true @@ -5982,13 +5982,13 @@ func rewriteValueARM64_OpARM64MNEGW(v *Value) bool { if v_1.Op != OpARM64MOVDconst { continue } - c := v_1.AuxInt + c := auxIntToInt64(v_1.AuxInt) if !(isPowerOfTwo(c-1) && int32(c) >= 3) { continue } v.reset(OpARM64NEG) v0 := b.NewValue0(v.Pos, OpARM64ADDshiftLL, x.Type) - v0.AuxInt = log2(c - 1) + v0.AuxInt = int64ToAuxInt(log2(c - 1)) v0.AddArg2(x, x) v.AddArg(v0) return true @@ -6004,13 +6004,13 @@ func rewriteValueARM64_OpARM64MNEGW(v *Value) bool { if v_1.Op != OpARM64MOVDconst { continue } - c := v_1.AuxInt + c := auxIntToInt64(v_1.AuxInt) if !(isPowerOfTwo(c+1) && int32(c) >= 7) { continue } v.reset(OpARM64NEG) v0 := b.NewValue0(v.Pos, OpARM64ADDshiftLL, x.Type) - v0.AuxInt = log2(c + 1) + v0.AuxInt = int64ToAuxInt(log2(c + 1)) v1 := b.NewValue0(v.Pos, OpARM64NEG, x.Type) v1.AddArg(x) v0.AddArg2(v1, x) @@ -6028,15 +6028,15 @@ func rewriteValueARM64_OpARM64MNEGW(v *Value) bool { if v_1.Op != OpARM64MOVDconst { continue } - c := v_1.AuxInt + c := auxIntToInt64(v_1.AuxInt) if !(c%3 == 0 && isPowerOfTwo(c/3) && is32Bit(c)) { continue } v.reset(OpARM64SLLconst) v.Type = x.Type - v.AuxInt = log2(c / 3) + v.AuxInt = int64ToAuxInt(log2(c / 3)) v0 := b.NewValue0(v.Pos, OpARM64SUBshiftLL, x.Type) - v0.AuxInt = 2 + v0.AuxInt = int64ToAuxInt(2) v0.AddArg2(x, x) v.AddArg(v0) return true @@ -6052,15 +6052,15 @@ func rewriteValueARM64_OpARM64MNEGW(v *Value) bool { if v_1.Op != OpARM64MOVDconst { continue } - c := v_1.AuxInt + c := auxIntToInt64(v_1.AuxInt) if !(c%5 == 0 && isPowerOfTwo(c/5) && is32Bit(c)) { continue } v.reset(OpARM64NEG) v0 := b.NewValue0(v.Pos, OpARM64SLLconst, x.Type) - v0.AuxInt = log2(c / 5) + v0.AuxInt = int64ToAuxInt(log2(c / 5)) v1 := b.NewValue0(v.Pos, OpARM64ADDshiftLL, x.Type) - v1.AuxInt = 2 + v1.AuxInt = int64ToAuxInt(2) v1.AddArg2(x, x) v0.AddArg(v1) v.AddArg(v0) @@ -6077,15 +6077,15 @@ func rewriteValueARM64_OpARM64MNEGW(v *Value) bool { if v_1.Op != OpARM64MOVDconst { continue } - c := v_1.AuxInt + c := auxIntToInt64(v_1.AuxInt) if !(c%7 == 0 && isPowerOfTwo(c/7) && is32Bit(c)) { continue } v.reset(OpARM64SLLconst) v.Type = x.Type - v.AuxInt = log2(c / 7) + v.AuxInt = int64ToAuxInt(log2(c / 7)) v0 := b.NewValue0(v.Pos, OpARM64SUBshiftLL, x.Type) - v0.AuxInt = 3 + v0.AuxInt = int64ToAuxInt(3) v0.AddArg2(x, x) v.AddArg(v0) return true @@ -6101,15 +6101,15 @@ func rewriteValueARM64_OpARM64MNEGW(v *Value) bool { if v_1.Op != OpARM64MOVDconst { continue } - c := v_1.AuxInt + c := auxIntToInt64(v_1.AuxInt) if !(c%9 == 0 && isPowerOfTwo(c/9) && is32Bit(c)) { continue } v.reset(OpARM64NEG) v0 := b.NewValue0(v.Pos, OpARM64SLLconst, x.Type) - v0.AuxInt = log2(c / 9) + v0.AuxInt = int64ToAuxInt(log2(c / 9)) v1 := b.NewValue0(v.Pos, OpARM64ADDshiftLL, x.Type) - v1.AuxInt = 3 + v1.AuxInt = int64ToAuxInt(3) v1.AddArg2(x, x) v0.AddArg(v1) v.AddArg(v0) @@ -6124,13 +6124,13 @@ func rewriteValueARM64_OpARM64MNEGW(v *Value) bool { if v_0.Op != OpARM64MOVDconst { continue } - c := v_0.AuxInt + c := auxIntToInt64(v_0.AuxInt) if v_1.Op != OpARM64MOVDconst { continue } - d := v_1.AuxInt + d := auxIntToInt64(v_1.AuxInt) v.reset(OpARM64MOVDconst) - v.AuxInt = -int64(int32(c) * int32(d)) + v.AuxInt = int64ToAuxInt(-int64(int32(c) * int32(d))) return true } break @@ -6146,13 +6146,13 @@ func rewriteValueARM64_OpARM64MOD(v *Value) bool { if v_0.Op != OpARM64MOVDconst { break } - c := v_0.AuxInt + c := auxIntToInt64(v_0.AuxInt) if v_1.Op != OpARM64MOVDconst { break } - d := v_1.AuxInt + d := auxIntToInt64(v_1.AuxInt) v.reset(OpARM64MOVDconst) - v.AuxInt = c % d + v.AuxInt = int64ToAuxInt(c % d) return true } return false @@ -6166,13 +6166,13 @@ func rewriteValueARM64_OpARM64MODW(v *Value) bool { if v_0.Op != OpARM64MOVDconst { break } - c := v_0.AuxInt + c := auxIntToInt64(v_0.AuxInt) if v_1.Op != OpARM64MOVDconst { break } - d := v_1.AuxInt + d := auxIntToInt64(v_1.AuxInt) v.reset(OpARM64MOVDconst) - v.AuxInt = int64(int32(c) % int32(d)) + v.AuxInt = int64ToAuxInt(int64(int32(c) % int32(d))) return true } return false @@ -6380,10 +6380,10 @@ func rewriteValueARM64_OpARM64MOVBUreg(v *Value) bool { if v_0.Op != OpARM64ANDconst { break } - c := v_0.AuxInt + c := auxIntToInt64(v_0.AuxInt) x := v_0.Args[0] v.reset(OpARM64ANDconst) - v.AuxInt = c & (1<<8 - 1) + v.AuxInt = int64ToAuxInt(c & (1<<8 - 1)) v.AddArg(x) return true } @@ -6393,9 +6393,9 @@ func rewriteValueARM64_OpARM64MOVBUreg(v *Value) bool { if v_0.Op != OpARM64MOVDconst { break } - c := v_0.AuxInt + c := auxIntToInt64(v_0.AuxInt) v.reset(OpARM64MOVDconst) - v.AuxInt = int64(uint8(c)) + v.AuxInt = int64ToAuxInt(int64(uint8(c))) return true } // match: (MOVBUreg x) @@ -6636,9 +6636,9 @@ func rewriteValueARM64_OpARM64MOVBreg(v *Value) bool { if v_0.Op != OpARM64MOVDconst { break } - c := v_0.AuxInt + c := auxIntToInt64(v_0.AuxInt) v.reset(OpARM64MOVDconst) - v.AuxInt = int64(int8(c)) + v.AuxInt = int64ToAuxInt(int64(int8(c))) return true } // match: (MOVBreg (SLLconst [lc] x)) @@ -8991,9 +8991,9 @@ func rewriteValueARM64_OpARM64MOVDreg(v *Value) bool { if v_0.Op != OpARM64MOVDconst { break } - c := v_0.AuxInt + c := auxIntToInt64(v_0.AuxInt) v.reset(OpARM64MOVDconst) - v.AuxInt = c + v.AuxInt = int64ToAuxInt(c) return true } return false @@ -9874,10 +9874,10 @@ func rewriteValueARM64_OpARM64MOVHUreg(v *Value) bool { if v_0.Op != OpARM64ANDconst { break } - c := v_0.AuxInt + c := auxIntToInt64(v_0.AuxInt) x := v_0.Args[0] v.reset(OpARM64ANDconst) - v.AuxInt = c & (1<<16 - 1) + v.AuxInt = int64ToAuxInt(c & (1<<16 - 1)) v.AddArg(x) return true } @@ -9887,9 +9887,9 @@ func rewriteValueARM64_OpARM64MOVHUreg(v *Value) bool { if v_0.Op != OpARM64MOVDconst { break } - c := v_0.AuxInt + c := auxIntToInt64(v_0.AuxInt) v.reset(OpARM64MOVDconst) - v.AuxInt = int64(uint16(c)) + v.AuxInt = int64ToAuxInt(int64(uint16(c))) return true } // match: (MOVHUreg (SLLconst [sc] x)) @@ -10301,9 +10301,9 @@ func rewriteValueARM64_OpARM64MOVHreg(v *Value) bool { if v_0.Op != OpARM64MOVDconst { break } - c := v_0.AuxInt + c := auxIntToInt64(v_0.AuxInt) v.reset(OpARM64MOVDconst) - v.AuxInt = int64(int16(c)) + v.AuxInt = int64ToAuxInt(int64(int16(c))) return true } // match: (MOVHreg (SLLconst [lc] x)) @@ -11971,10 +11971,10 @@ func rewriteValueARM64_OpARM64MOVWUreg(v *Value) bool { if v_0.Op != OpARM64ANDconst { break } - c := v_0.AuxInt + c := auxIntToInt64(v_0.AuxInt) x := v_0.Args[0] v.reset(OpARM64ANDconst) - v.AuxInt = c & (1<<32 - 1) + v.AuxInt = int64ToAuxInt(c & (1<<32 - 1)) v.AddArg(x) return true } @@ -11984,9 +11984,9 @@ func rewriteValueARM64_OpARM64MOVWUreg(v *Value) bool { if v_0.Op != OpARM64MOVDconst { break } - c := v_0.AuxInt + c := auxIntToInt64(v_0.AuxInt) v.reset(OpARM64MOVDconst) - v.AuxInt = int64(uint32(c)) + v.AuxInt = int64ToAuxInt(int64(uint32(c))) return true } // match: (MOVWUreg (SLLconst [sc] x)) @@ -12456,9 +12456,9 @@ func rewriteValueARM64_OpARM64MOVWreg(v *Value) bool { if v_0.Op != OpARM64MOVDconst { break } - c := v_0.AuxInt + c := auxIntToInt64(v_0.AuxInt) v.reset(OpARM64MOVDconst) - v.AuxInt = int64(int32(c)) + v.AuxInt = int64ToAuxInt(int64(int32(c))) return true } // match: (MOVWreg (SLLconst [lc] x)) @@ -13346,7 +13346,7 @@ func rewriteValueARM64_OpARM64MSUB(v *Value) bool { for { a := v_0 x := v_1 - if v_2.Op != OpARM64MOVDconst || v_2.AuxInt != -1 { + if v_2.Op != OpARM64MOVDconst || auxIntToInt64(v_2.AuxInt) != -1 { break } v.reset(OpARM64ADD) @@ -13357,7 +13357,7 @@ func rewriteValueARM64_OpARM64MSUB(v *Value) bool { // result: a for { a := v_0 - if v_2.Op != OpARM64MOVDconst || v_2.AuxInt != 0 { + if v_2.Op != OpARM64MOVDconst || auxIntToInt64(v_2.AuxInt) != 0 { break } v.copyOf(a) @@ -13368,7 +13368,7 @@ func rewriteValueARM64_OpARM64MSUB(v *Value) bool { for { a := v_0 x := v_1 - if v_2.Op != OpARM64MOVDconst || v_2.AuxInt != 1 { + if v_2.Op != OpARM64MOVDconst || auxIntToInt64(v_2.AuxInt) != 1 { break } v.reset(OpARM64SUB) @@ -13384,12 +13384,12 @@ func rewriteValueARM64_OpARM64MSUB(v *Value) bool { if v_2.Op != OpARM64MOVDconst { break } - c := v_2.AuxInt + c := auxIntToInt64(v_2.AuxInt) if !(isPowerOfTwo(c)) { break } v.reset(OpARM64SUBshiftLL) - v.AuxInt = log2(c) + v.AuxInt = int64ToAuxInt(log2(c)) v.AddArg2(a, x) return true } @@ -13402,13 +13402,13 @@ func rewriteValueARM64_OpARM64MSUB(v *Value) bool { if v_2.Op != OpARM64MOVDconst { break } - c := v_2.AuxInt + c := auxIntToInt64(v_2.AuxInt) if !(isPowerOfTwo(c-1) && c >= 3) { break } v.reset(OpARM64SUB) v0 := b.NewValue0(v.Pos, OpARM64ADDshiftLL, x.Type) - v0.AuxInt = log2(c - 1) + v0.AuxInt = int64ToAuxInt(log2(c - 1)) v0.AddArg2(x, x) v.AddArg2(a, v0) return true @@ -13422,13 +13422,13 @@ func rewriteValueARM64_OpARM64MSUB(v *Value) bool { if v_2.Op != OpARM64MOVDconst { break } - c := v_2.AuxInt + c := auxIntToInt64(v_2.AuxInt) if !(isPowerOfTwo(c+1) && c >= 7) { break } v.reset(OpARM64ADD) v0 := b.NewValue0(v.Pos, OpARM64SUBshiftLL, x.Type) - v0.AuxInt = log2(c + 1) + v0.AuxInt = int64ToAuxInt(log2(c + 1)) v0.AddArg2(x, x) v.AddArg2(a, v0) return true @@ -13442,14 +13442,14 @@ func rewriteValueARM64_OpARM64MSUB(v *Value) bool { if v_2.Op != OpARM64MOVDconst { break } - c := v_2.AuxInt + c := auxIntToInt64(v_2.AuxInt) if !(c%3 == 0 && isPowerOfTwo(c/3)) { break } v.reset(OpARM64ADDshiftLL) - v.AuxInt = log2(c / 3) + v.AuxInt = int64ToAuxInt(log2(c / 3)) v0 := b.NewValue0(v.Pos, OpARM64SUBshiftLL, x.Type) - v0.AuxInt = 2 + v0.AuxInt = int64ToAuxInt(2) v0.AddArg2(x, x) v.AddArg2(a, v0) return true @@ -13463,14 +13463,14 @@ func rewriteValueARM64_OpARM64MSUB(v *Value) bool { if v_2.Op != OpARM64MOVDconst { break } - c := v_2.AuxInt + c := auxIntToInt64(v_2.AuxInt) if !(c%5 == 0 && isPowerOfTwo(c/5)) { break } v.reset(OpARM64SUBshiftLL) - v.AuxInt = log2(c / 5) + v.AuxInt = int64ToAuxInt(log2(c / 5)) v0 := b.NewValue0(v.Pos, OpARM64ADDshiftLL, x.Type) - v0.AuxInt = 2 + v0.AuxInt = int64ToAuxInt(2) v0.AddArg2(x, x) v.AddArg2(a, v0) return true @@ -13484,14 +13484,14 @@ func rewriteValueARM64_OpARM64MSUB(v *Value) bool { if v_2.Op != OpARM64MOVDconst { break } - c := v_2.AuxInt + c := auxIntToInt64(v_2.AuxInt) if !(c%7 == 0 && isPowerOfTwo(c/7)) { break } v.reset(OpARM64ADDshiftLL) - v.AuxInt = log2(c / 7) + v.AuxInt = int64ToAuxInt(log2(c / 7)) v0 := b.NewValue0(v.Pos, OpARM64SUBshiftLL, x.Type) - v0.AuxInt = 3 + v0.AuxInt = int64ToAuxInt(3) v0.AddArg2(x, x) v.AddArg2(a, v0) return true @@ -13505,14 +13505,14 @@ func rewriteValueARM64_OpARM64MSUB(v *Value) bool { if v_2.Op != OpARM64MOVDconst { break } - c := v_2.AuxInt + c := auxIntToInt64(v_2.AuxInt) if !(c%9 == 0 && isPowerOfTwo(c/9)) { break } v.reset(OpARM64SUBshiftLL) - v.AuxInt = log2(c / 9) + v.AuxInt = int64ToAuxInt(log2(c / 9)) v0 := b.NewValue0(v.Pos, OpARM64ADDshiftLL, x.Type) - v0.AuxInt = 3 + v0.AuxInt = int64ToAuxInt(3) v0.AddArg2(x, x) v.AddArg2(a, v0) return true @@ -13521,7 +13521,7 @@ func rewriteValueARM64_OpARM64MSUB(v *Value) bool { // result: (ADD a x) for { a := v_0 - if v_1.Op != OpARM64MOVDconst || v_1.AuxInt != -1 { + if v_1.Op != OpARM64MOVDconst || auxIntToInt64(v_1.AuxInt) != -1 { break } x := v_2 @@ -13533,7 +13533,7 @@ func rewriteValueARM64_OpARM64MSUB(v *Value) bool { // result: a for { a := v_0 - if v_1.Op != OpARM64MOVDconst || v_1.AuxInt != 0 { + if v_1.Op != OpARM64MOVDconst || auxIntToInt64(v_1.AuxInt) != 0 { break } v.copyOf(a) @@ -13543,7 +13543,7 @@ func rewriteValueARM64_OpARM64MSUB(v *Value) bool { // result: (SUB a x) for { a := v_0 - if v_1.Op != OpARM64MOVDconst || v_1.AuxInt != 1 { + if v_1.Op != OpARM64MOVDconst || auxIntToInt64(v_1.AuxInt) != 1 { break } x := v_2 @@ -13559,13 +13559,13 @@ func rewriteValueARM64_OpARM64MSUB(v *Value) bool { if v_1.Op != OpARM64MOVDconst { break } - c := v_1.AuxInt + c := auxIntToInt64(v_1.AuxInt) x := v_2 if !(isPowerOfTwo(c)) { break } v.reset(OpARM64SUBshiftLL) - v.AuxInt = log2(c) + v.AuxInt = int64ToAuxInt(log2(c)) v.AddArg2(a, x) return true } @@ -13577,14 +13577,14 @@ func rewriteValueARM64_OpARM64MSUB(v *Value) bool { if v_1.Op != OpARM64MOVDconst { break } - c := v_1.AuxInt + c := auxIntToInt64(v_1.AuxInt) x := v_2 if !(isPowerOfTwo(c-1) && c >= 3) { break } v.reset(OpARM64SUB) v0 := b.NewValue0(v.Pos, OpARM64ADDshiftLL, x.Type) - v0.AuxInt = log2(c - 1) + v0.AuxInt = int64ToAuxInt(log2(c - 1)) v0.AddArg2(x, x) v.AddArg2(a, v0) return true @@ -13597,14 +13597,14 @@ func rewriteValueARM64_OpARM64MSUB(v *Value) bool { if v_1.Op != OpARM64MOVDconst { break } - c := v_1.AuxInt + c := auxIntToInt64(v_1.AuxInt) x := v_2 if !(isPowerOfTwo(c+1) && c >= 7) { break } v.reset(OpARM64ADD) v0 := b.NewValue0(v.Pos, OpARM64SUBshiftLL, x.Type) - v0.AuxInt = log2(c + 1) + v0.AuxInt = int64ToAuxInt(log2(c + 1)) v0.AddArg2(x, x) v.AddArg2(a, v0) return true @@ -13617,15 +13617,15 @@ func rewriteValueARM64_OpARM64MSUB(v *Value) bool { if v_1.Op != OpARM64MOVDconst { break } - c := v_1.AuxInt + c := auxIntToInt64(v_1.AuxInt) x := v_2 if !(c%3 == 0 && isPowerOfTwo(c/3)) { break } v.reset(OpARM64ADDshiftLL) - v.AuxInt = log2(c / 3) + v.AuxInt = int64ToAuxInt(log2(c / 3)) v0 := b.NewValue0(v.Pos, OpARM64SUBshiftLL, x.Type) - v0.AuxInt = 2 + v0.AuxInt = int64ToAuxInt(2) v0.AddArg2(x, x) v.AddArg2(a, v0) return true @@ -13638,15 +13638,15 @@ func rewriteValueARM64_OpARM64MSUB(v *Value) bool { if v_1.Op != OpARM64MOVDconst { break } - c := v_1.AuxInt + c := auxIntToInt64(v_1.AuxInt) x := v_2 if !(c%5 == 0 && isPowerOfTwo(c/5)) { break } v.reset(OpARM64SUBshiftLL) - v.AuxInt = log2(c / 5) + v.AuxInt = int64ToAuxInt(log2(c / 5)) v0 := b.NewValue0(v.Pos, OpARM64ADDshiftLL, x.Type) - v0.AuxInt = 2 + v0.AuxInt = int64ToAuxInt(2) v0.AddArg2(x, x) v.AddArg2(a, v0) return true @@ -13659,15 +13659,15 @@ func rewriteValueARM64_OpARM64MSUB(v *Value) bool { if v_1.Op != OpARM64MOVDconst { break } - c := v_1.AuxInt + c := auxIntToInt64(v_1.AuxInt) x := v_2 if !(c%7 == 0 && isPowerOfTwo(c/7)) { break } v.reset(OpARM64ADDshiftLL) - v.AuxInt = log2(c / 7) + v.AuxInt = int64ToAuxInt(log2(c / 7)) v0 := b.NewValue0(v.Pos, OpARM64SUBshiftLL, x.Type) - v0.AuxInt = 3 + v0.AuxInt = int64ToAuxInt(3) v0.AddArg2(x, x) v.AddArg2(a, v0) return true @@ -13680,15 +13680,15 @@ func rewriteValueARM64_OpARM64MSUB(v *Value) bool { if v_1.Op != OpARM64MOVDconst { break } - c := v_1.AuxInt + c := auxIntToInt64(v_1.AuxInt) x := v_2 if !(c%9 == 0 && isPowerOfTwo(c/9)) { break } v.reset(OpARM64SUBshiftLL) - v.AuxInt = log2(c / 9) + v.AuxInt = int64ToAuxInt(log2(c / 9)) v0 := b.NewValue0(v.Pos, OpARM64ADDshiftLL, x.Type) - v0.AuxInt = 3 + v0.AuxInt = int64ToAuxInt(3) v0.AddArg2(x, x) v.AddArg2(a, v0) return true @@ -13699,11 +13699,11 @@ func rewriteValueARM64_OpARM64MSUB(v *Value) bool { if v_0.Op != OpARM64MOVDconst { break } - c := v_0.AuxInt + c := auxIntToInt64(v_0.AuxInt) x := v_1 y := v_2 v.reset(OpARM64ADDconst) - v.AuxInt = c + v.AuxInt = int64ToAuxInt(c) v0 := b.NewValue0(v.Pos, OpARM64MNEG, x.Type) v0.AddArg2(x, y) v.AddArg(v0) @@ -13716,13 +13716,13 @@ func rewriteValueARM64_OpARM64MSUB(v *Value) bool { if v_1.Op != OpARM64MOVDconst { break } - c := v_1.AuxInt + c := auxIntToInt64(v_1.AuxInt) if v_2.Op != OpARM64MOVDconst { break } - d := v_2.AuxInt + d := auxIntToInt64(v_2.AuxInt) v.reset(OpARM64SUBconst) - v.AuxInt = c * d + v.AuxInt = int64ToAuxInt(c * d) v.AddArg(a) return true } @@ -13742,7 +13742,7 @@ func rewriteValueARM64_OpARM64MSUBW(v *Value) bool { if v_2.Op != OpARM64MOVDconst { break } - c := v_2.AuxInt + c := auxIntToInt64(v_2.AuxInt) if !(int32(c) == -1) { break } @@ -13758,7 +13758,7 @@ func rewriteValueARM64_OpARM64MSUBW(v *Value) bool { if v_2.Op != OpARM64MOVDconst { break } - c := v_2.AuxInt + c := auxIntToInt64(v_2.AuxInt) if !(int32(c) == 0) { break } @@ -13774,7 +13774,7 @@ func rewriteValueARM64_OpARM64MSUBW(v *Value) bool { if v_2.Op != OpARM64MOVDconst { break } - c := v_2.AuxInt + c := auxIntToInt64(v_2.AuxInt) if !(int32(c) == 1) { break } @@ -13791,12 +13791,12 @@ func rewriteValueARM64_OpARM64MSUBW(v *Value) bool { if v_2.Op != OpARM64MOVDconst { break } - c := v_2.AuxInt + c := auxIntToInt64(v_2.AuxInt) if !(isPowerOfTwo(c)) { break } v.reset(OpARM64SUBshiftLL) - v.AuxInt = log2(c) + v.AuxInt = int64ToAuxInt(log2(c)) v.AddArg2(a, x) return true } @@ -13809,13 +13809,13 @@ func rewriteValueARM64_OpARM64MSUBW(v *Value) bool { if v_2.Op != OpARM64MOVDconst { break } - c := v_2.AuxInt + c := auxIntToInt64(v_2.AuxInt) if !(isPowerOfTwo(c-1) && int32(c) >= 3) { break } v.reset(OpARM64SUB) v0 := b.NewValue0(v.Pos, OpARM64ADDshiftLL, x.Type) - v0.AuxInt = log2(c - 1) + v0.AuxInt = int64ToAuxInt(log2(c - 1)) v0.AddArg2(x, x) v.AddArg2(a, v0) return true @@ -13829,13 +13829,13 @@ func rewriteValueARM64_OpARM64MSUBW(v *Value) bool { if v_2.Op != OpARM64MOVDconst { break } - c := v_2.AuxInt + c := auxIntToInt64(v_2.AuxInt) if !(isPowerOfTwo(c+1) && int32(c) >= 7) { break } v.reset(OpARM64ADD) v0 := b.NewValue0(v.Pos, OpARM64SUBshiftLL, x.Type) - v0.AuxInt = log2(c + 1) + v0.AuxInt = int64ToAuxInt(log2(c + 1)) v0.AddArg2(x, x) v.AddArg2(a, v0) return true @@ -13849,14 +13849,14 @@ func rewriteValueARM64_OpARM64MSUBW(v *Value) bool { if v_2.Op != OpARM64MOVDconst { break } - c := v_2.AuxInt + c := auxIntToInt64(v_2.AuxInt) if !(c%3 == 0 && isPowerOfTwo(c/3) && is32Bit(c)) { break } v.reset(OpARM64ADDshiftLL) - v.AuxInt = log2(c / 3) + v.AuxInt = int64ToAuxInt(log2(c / 3)) v0 := b.NewValue0(v.Pos, OpARM64SUBshiftLL, x.Type) - v0.AuxInt = 2 + v0.AuxInt = int64ToAuxInt(2) v0.AddArg2(x, x) v.AddArg2(a, v0) return true @@ -13870,14 +13870,14 @@ func rewriteValueARM64_OpARM64MSUBW(v *Value) bool { if v_2.Op != OpARM64MOVDconst { break } - c := v_2.AuxInt + c := auxIntToInt64(v_2.AuxInt) if !(c%5 == 0 && isPowerOfTwo(c/5) && is32Bit(c)) { break } v.reset(OpARM64SUBshiftLL) - v.AuxInt = log2(c / 5) + v.AuxInt = int64ToAuxInt(log2(c / 5)) v0 := b.NewValue0(v.Pos, OpARM64ADDshiftLL, x.Type) - v0.AuxInt = 2 + v0.AuxInt = int64ToAuxInt(2) v0.AddArg2(x, x) v.AddArg2(a, v0) return true @@ -13891,14 +13891,14 @@ func rewriteValueARM64_OpARM64MSUBW(v *Value) bool { if v_2.Op != OpARM64MOVDconst { break } - c := v_2.AuxInt + c := auxIntToInt64(v_2.AuxInt) if !(c%7 == 0 && isPowerOfTwo(c/7) && is32Bit(c)) { break } v.reset(OpARM64ADDshiftLL) - v.AuxInt = log2(c / 7) + v.AuxInt = int64ToAuxInt(log2(c / 7)) v0 := b.NewValue0(v.Pos, OpARM64SUBshiftLL, x.Type) - v0.AuxInt = 3 + v0.AuxInt = int64ToAuxInt(3) v0.AddArg2(x, x) v.AddArg2(a, v0) return true @@ -13912,14 +13912,14 @@ func rewriteValueARM64_OpARM64MSUBW(v *Value) bool { if v_2.Op != OpARM64MOVDconst { break } - c := v_2.AuxInt + c := auxIntToInt64(v_2.AuxInt) if !(c%9 == 0 && isPowerOfTwo(c/9) && is32Bit(c)) { break } v.reset(OpARM64SUBshiftLL) - v.AuxInt = log2(c / 9) + v.AuxInt = int64ToAuxInt(log2(c / 9)) v0 := b.NewValue0(v.Pos, OpARM64ADDshiftLL, x.Type) - v0.AuxInt = 3 + v0.AuxInt = int64ToAuxInt(3) v0.AddArg2(x, x) v.AddArg2(a, v0) return true @@ -13932,7 +13932,7 @@ func rewriteValueARM64_OpARM64MSUBW(v *Value) bool { if v_1.Op != OpARM64MOVDconst { break } - c := v_1.AuxInt + c := auxIntToInt64(v_1.AuxInt) x := v_2 if !(int32(c) == -1) { break @@ -13949,7 +13949,7 @@ func rewriteValueARM64_OpARM64MSUBW(v *Value) bool { if v_1.Op != OpARM64MOVDconst { break } - c := v_1.AuxInt + c := auxIntToInt64(v_1.AuxInt) if !(int32(c) == 0) { break } @@ -13964,7 +13964,7 @@ func rewriteValueARM64_OpARM64MSUBW(v *Value) bool { if v_1.Op != OpARM64MOVDconst { break } - c := v_1.AuxInt + c := auxIntToInt64(v_1.AuxInt) x := v_2 if !(int32(c) == 1) { break @@ -13981,13 +13981,13 @@ func rewriteValueARM64_OpARM64MSUBW(v *Value) bool { if v_1.Op != OpARM64MOVDconst { break } - c := v_1.AuxInt + c := auxIntToInt64(v_1.AuxInt) x := v_2 if !(isPowerOfTwo(c)) { break } v.reset(OpARM64SUBshiftLL) - v.AuxInt = log2(c) + v.AuxInt = int64ToAuxInt(log2(c)) v.AddArg2(a, x) return true } @@ -13999,14 +13999,14 @@ func rewriteValueARM64_OpARM64MSUBW(v *Value) bool { if v_1.Op != OpARM64MOVDconst { break } - c := v_1.AuxInt + c := auxIntToInt64(v_1.AuxInt) x := v_2 if !(isPowerOfTwo(c-1) && int32(c) >= 3) { break } v.reset(OpARM64SUB) v0 := b.NewValue0(v.Pos, OpARM64ADDshiftLL, x.Type) - v0.AuxInt = log2(c - 1) + v0.AuxInt = int64ToAuxInt(log2(c - 1)) v0.AddArg2(x, x) v.AddArg2(a, v0) return true @@ -14019,14 +14019,14 @@ func rewriteValueARM64_OpARM64MSUBW(v *Value) bool { if v_1.Op != OpARM64MOVDconst { break } - c := v_1.AuxInt + c := auxIntToInt64(v_1.AuxInt) x := v_2 if !(isPowerOfTwo(c+1) && int32(c) >= 7) { break } v.reset(OpARM64ADD) v0 := b.NewValue0(v.Pos, OpARM64SUBshiftLL, x.Type) - v0.AuxInt = log2(c + 1) + v0.AuxInt = int64ToAuxInt(log2(c + 1)) v0.AddArg2(x, x) v.AddArg2(a, v0) return true @@ -14039,15 +14039,15 @@ func rewriteValueARM64_OpARM64MSUBW(v *Value) bool { if v_1.Op != OpARM64MOVDconst { break } - c := v_1.AuxInt + c := auxIntToInt64(v_1.AuxInt) x := v_2 if !(c%3 == 0 && isPowerOfTwo(c/3) && is32Bit(c)) { break } v.reset(OpARM64ADDshiftLL) - v.AuxInt = log2(c / 3) + v.AuxInt = int64ToAuxInt(log2(c / 3)) v0 := b.NewValue0(v.Pos, OpARM64SUBshiftLL, x.Type) - v0.AuxInt = 2 + v0.AuxInt = int64ToAuxInt(2) v0.AddArg2(x, x) v.AddArg2(a, v0) return true @@ -14060,15 +14060,15 @@ func rewriteValueARM64_OpARM64MSUBW(v *Value) bool { if v_1.Op != OpARM64MOVDconst { break } - c := v_1.AuxInt + c := auxIntToInt64(v_1.AuxInt) x := v_2 if !(c%5 == 0 && isPowerOfTwo(c/5) && is32Bit(c)) { break } v.reset(OpARM64SUBshiftLL) - v.AuxInt = log2(c / 5) + v.AuxInt = int64ToAuxInt(log2(c / 5)) v0 := b.NewValue0(v.Pos, OpARM64ADDshiftLL, x.Type) - v0.AuxInt = 2 + v0.AuxInt = int64ToAuxInt(2) v0.AddArg2(x, x) v.AddArg2(a, v0) return true @@ -14081,15 +14081,15 @@ func rewriteValueARM64_OpARM64MSUBW(v *Value) bool { if v_1.Op != OpARM64MOVDconst { break } - c := v_1.AuxInt + c := auxIntToInt64(v_1.AuxInt) x := v_2 if !(c%7 == 0 && isPowerOfTwo(c/7) && is32Bit(c)) { break } v.reset(OpARM64ADDshiftLL) - v.AuxInt = log2(c / 7) + v.AuxInt = int64ToAuxInt(log2(c / 7)) v0 := b.NewValue0(v.Pos, OpARM64SUBshiftLL, x.Type) - v0.AuxInt = 3 + v0.AuxInt = int64ToAuxInt(3) v0.AddArg2(x, x) v.AddArg2(a, v0) return true @@ -14102,15 +14102,15 @@ func rewriteValueARM64_OpARM64MSUBW(v *Value) bool { if v_1.Op != OpARM64MOVDconst { break } - c := v_1.AuxInt + c := auxIntToInt64(v_1.AuxInt) x := v_2 if !(c%9 == 0 && isPowerOfTwo(c/9) && is32Bit(c)) { break } v.reset(OpARM64SUBshiftLL) - v.AuxInt = log2(c / 9) + v.AuxInt = int64ToAuxInt(log2(c / 9)) v0 := b.NewValue0(v.Pos, OpARM64ADDshiftLL, x.Type) - v0.AuxInt = 3 + v0.AuxInt = int64ToAuxInt(3) v0.AddArg2(x, x) v.AddArg2(a, v0) return true @@ -14121,11 +14121,11 @@ func rewriteValueARM64_OpARM64MSUBW(v *Value) bool { if v_0.Op != OpARM64MOVDconst { break } - c := v_0.AuxInt + c := auxIntToInt64(v_0.AuxInt) x := v_1 y := v_2 v.reset(OpARM64ADDconst) - v.AuxInt = c + v.AuxInt = int64ToAuxInt(c) v0 := b.NewValue0(v.Pos, OpARM64MNEGW, x.Type) v0.AddArg2(x, y) v.AddArg(v0) @@ -14138,13 +14138,13 @@ func rewriteValueARM64_OpARM64MSUBW(v *Value) bool { if v_1.Op != OpARM64MOVDconst { break } - c := v_1.AuxInt + c := auxIntToInt64(v_1.AuxInt) if v_2.Op != OpARM64MOVDconst { break } - d := v_2.AuxInt + d := auxIntToInt64(v_2.AuxInt) v.reset(OpARM64SUBconst) - v.AuxInt = int64(int32(c) * int32(d)) + v.AuxInt = int64ToAuxInt(int64(int32(c) * int32(d))) v.AddArg(a) return true } @@ -14174,7 +14174,7 @@ func rewriteValueARM64_OpARM64MUL(v *Value) bool { for { for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { x := v_0 - if v_1.Op != OpARM64MOVDconst || v_1.AuxInt != -1 { + if v_1.Op != OpARM64MOVDconst || auxIntToInt64(v_1.AuxInt) != -1 { continue } v.reset(OpARM64NEG) @@ -14187,11 +14187,11 @@ func rewriteValueARM64_OpARM64MUL(v *Value) bool { // result: (MOVDconst [0]) for { for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - if v_1.Op != OpARM64MOVDconst || v_1.AuxInt != 0 { + if v_1.Op != OpARM64MOVDconst || auxIntToInt64(v_1.AuxInt) != 0 { continue } v.reset(OpARM64MOVDconst) - v.AuxInt = 0 + v.AuxInt = int64ToAuxInt(0) return true } break @@ -14201,7 +14201,7 @@ func rewriteValueARM64_OpARM64MUL(v *Value) bool { for { for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { x := v_0 - if v_1.Op != OpARM64MOVDconst || v_1.AuxInt != 1 { + if v_1.Op != OpARM64MOVDconst || auxIntToInt64(v_1.AuxInt) != 1 { continue } v.copyOf(x) @@ -14218,12 +14218,12 @@ func rewriteValueARM64_OpARM64MUL(v *Value) bool { if v_1.Op != OpARM64MOVDconst { continue } - c := v_1.AuxInt + c := auxIntToInt64(v_1.AuxInt) if !(isPowerOfTwo(c)) { continue } v.reset(OpARM64SLLconst) - v.AuxInt = log2(c) + v.AuxInt = int64ToAuxInt(log2(c)) v.AddArg(x) return true } @@ -14238,12 +14238,12 @@ func rewriteValueARM64_OpARM64MUL(v *Value) bool { if v_1.Op != OpARM64MOVDconst { continue } - c := v_1.AuxInt + c := auxIntToInt64(v_1.AuxInt) if !(isPowerOfTwo(c-1) && c >= 3) { continue } v.reset(OpARM64ADDshiftLL) - v.AuxInt = log2(c - 1) + v.AuxInt = int64ToAuxInt(log2(c - 1)) v.AddArg2(x, x) return true } @@ -14258,12 +14258,12 @@ func rewriteValueARM64_OpARM64MUL(v *Value) bool { if v_1.Op != OpARM64MOVDconst { continue } - c := v_1.AuxInt + c := auxIntToInt64(v_1.AuxInt) if !(isPowerOfTwo(c+1) && c >= 7) { continue } v.reset(OpARM64ADDshiftLL) - v.AuxInt = log2(c + 1) + v.AuxInt = int64ToAuxInt(log2(c + 1)) v0 := b.NewValue0(v.Pos, OpARM64NEG, x.Type) v0.AddArg(x) v.AddArg2(v0, x) @@ -14280,14 +14280,14 @@ func rewriteValueARM64_OpARM64MUL(v *Value) bool { if v_1.Op != OpARM64MOVDconst { continue } - c := v_1.AuxInt + c := auxIntToInt64(v_1.AuxInt) if !(c%3 == 0 && isPowerOfTwo(c/3)) { continue } v.reset(OpARM64SLLconst) - v.AuxInt = log2(c / 3) + v.AuxInt = int64ToAuxInt(log2(c / 3)) v0 := b.NewValue0(v.Pos, OpARM64ADDshiftLL, x.Type) - v0.AuxInt = 1 + v0.AuxInt = int64ToAuxInt(1) v0.AddArg2(x, x) v.AddArg(v0) return true @@ -14303,14 +14303,14 @@ func rewriteValueARM64_OpARM64MUL(v *Value) bool { if v_1.Op != OpARM64MOVDconst { continue } - c := v_1.AuxInt + c := auxIntToInt64(v_1.AuxInt) if !(c%5 == 0 && isPowerOfTwo(c/5)) { continue } v.reset(OpARM64SLLconst) - v.AuxInt = log2(c / 5) + v.AuxInt = int64ToAuxInt(log2(c / 5)) v0 := b.NewValue0(v.Pos, OpARM64ADDshiftLL, x.Type) - v0.AuxInt = 2 + v0.AuxInt = int64ToAuxInt(2) v0.AddArg2(x, x) v.AddArg(v0) return true @@ -14326,14 +14326,14 @@ func rewriteValueARM64_OpARM64MUL(v *Value) bool { if v_1.Op != OpARM64MOVDconst { continue } - c := v_1.AuxInt + c := auxIntToInt64(v_1.AuxInt) if !(c%7 == 0 && isPowerOfTwo(c/7)) { continue } v.reset(OpARM64SLLconst) - v.AuxInt = log2(c / 7) + v.AuxInt = int64ToAuxInt(log2(c / 7)) v0 := b.NewValue0(v.Pos, OpARM64ADDshiftLL, x.Type) - v0.AuxInt = 3 + v0.AuxInt = int64ToAuxInt(3) v1 := b.NewValue0(v.Pos, OpARM64NEG, x.Type) v1.AddArg(x) v0.AddArg2(v1, x) @@ -14351,14 +14351,14 @@ func rewriteValueARM64_OpARM64MUL(v *Value) bool { if v_1.Op != OpARM64MOVDconst { continue } - c := v_1.AuxInt + c := auxIntToInt64(v_1.AuxInt) if !(c%9 == 0 && isPowerOfTwo(c/9)) { continue } v.reset(OpARM64SLLconst) - v.AuxInt = log2(c / 9) + v.AuxInt = int64ToAuxInt(log2(c / 9)) v0 := b.NewValue0(v.Pos, OpARM64ADDshiftLL, x.Type) - v0.AuxInt = 3 + v0.AuxInt = int64ToAuxInt(3) v0.AddArg2(x, x) v.AddArg(v0) return true @@ -14372,13 +14372,13 @@ func rewriteValueARM64_OpARM64MUL(v *Value) bool { if v_0.Op != OpARM64MOVDconst { continue } - c := v_0.AuxInt + c := auxIntToInt64(v_0.AuxInt) if v_1.Op != OpARM64MOVDconst { continue } - d := v_1.AuxInt + d := auxIntToInt64(v_1.AuxInt) v.reset(OpARM64MOVDconst) - v.AuxInt = c * d + v.AuxInt = int64ToAuxInt(c * d) return true } break @@ -14413,7 +14413,7 @@ func rewriteValueARM64_OpARM64MULW(v *Value) bool { if v_1.Op != OpARM64MOVDconst { continue } - c := v_1.AuxInt + c := auxIntToInt64(v_1.AuxInt) if !(int32(c) == -1) { continue } @@ -14431,12 +14431,12 @@ func rewriteValueARM64_OpARM64MULW(v *Value) bool { if v_1.Op != OpARM64MOVDconst { continue } - c := v_1.AuxInt + c := auxIntToInt64(v_1.AuxInt) if !(int32(c) == 0) { continue } v.reset(OpARM64MOVDconst) - v.AuxInt = 0 + v.AuxInt = int64ToAuxInt(0) return true } break @@ -14450,7 +14450,7 @@ func rewriteValueARM64_OpARM64MULW(v *Value) bool { if v_1.Op != OpARM64MOVDconst { continue } - c := v_1.AuxInt + c := auxIntToInt64(v_1.AuxInt) if !(int32(c) == 1) { continue } @@ -14468,12 +14468,12 @@ func rewriteValueARM64_OpARM64MULW(v *Value) bool { if v_1.Op != OpARM64MOVDconst { continue } - c := v_1.AuxInt + c := auxIntToInt64(v_1.AuxInt) if !(isPowerOfTwo(c)) { continue } v.reset(OpARM64SLLconst) - v.AuxInt = log2(c) + v.AuxInt = int64ToAuxInt(log2(c)) v.AddArg(x) return true } @@ -14488,12 +14488,12 @@ func rewriteValueARM64_OpARM64MULW(v *Value) bool { if v_1.Op != OpARM64MOVDconst { continue } - c := v_1.AuxInt + c := auxIntToInt64(v_1.AuxInt) if !(isPowerOfTwo(c-1) && int32(c) >= 3) { continue } v.reset(OpARM64ADDshiftLL) - v.AuxInt = log2(c - 1) + v.AuxInt = int64ToAuxInt(log2(c - 1)) v.AddArg2(x, x) return true } @@ -14508,12 +14508,12 @@ func rewriteValueARM64_OpARM64MULW(v *Value) bool { if v_1.Op != OpARM64MOVDconst { continue } - c := v_1.AuxInt + c := auxIntToInt64(v_1.AuxInt) if !(isPowerOfTwo(c+1) && int32(c) >= 7) { continue } v.reset(OpARM64ADDshiftLL) - v.AuxInt = log2(c + 1) + v.AuxInt = int64ToAuxInt(log2(c + 1)) v0 := b.NewValue0(v.Pos, OpARM64NEG, x.Type) v0.AddArg(x) v.AddArg2(v0, x) @@ -14530,14 +14530,14 @@ func rewriteValueARM64_OpARM64MULW(v *Value) bool { if v_1.Op != OpARM64MOVDconst { continue } - c := v_1.AuxInt + c := auxIntToInt64(v_1.AuxInt) if !(c%3 == 0 && isPowerOfTwo(c/3) && is32Bit(c)) { continue } v.reset(OpARM64SLLconst) - v.AuxInt = log2(c / 3) + v.AuxInt = int64ToAuxInt(log2(c / 3)) v0 := b.NewValue0(v.Pos, OpARM64ADDshiftLL, x.Type) - v0.AuxInt = 1 + v0.AuxInt = int64ToAuxInt(1) v0.AddArg2(x, x) v.AddArg(v0) return true @@ -14553,14 +14553,14 @@ func rewriteValueARM64_OpARM64MULW(v *Value) bool { if v_1.Op != OpARM64MOVDconst { continue } - c := v_1.AuxInt + c := auxIntToInt64(v_1.AuxInt) if !(c%5 == 0 && isPowerOfTwo(c/5) && is32Bit(c)) { continue } v.reset(OpARM64SLLconst) - v.AuxInt = log2(c / 5) + v.AuxInt = int64ToAuxInt(log2(c / 5)) v0 := b.NewValue0(v.Pos, OpARM64ADDshiftLL, x.Type) - v0.AuxInt = 2 + v0.AuxInt = int64ToAuxInt(2) v0.AddArg2(x, x) v.AddArg(v0) return true @@ -14576,14 +14576,14 @@ func rewriteValueARM64_OpARM64MULW(v *Value) bool { if v_1.Op != OpARM64MOVDconst { continue } - c := v_1.AuxInt + c := auxIntToInt64(v_1.AuxInt) if !(c%7 == 0 && isPowerOfTwo(c/7) && is32Bit(c)) { continue } v.reset(OpARM64SLLconst) - v.AuxInt = log2(c / 7) + v.AuxInt = int64ToAuxInt(log2(c / 7)) v0 := b.NewValue0(v.Pos, OpARM64ADDshiftLL, x.Type) - v0.AuxInt = 3 + v0.AuxInt = int64ToAuxInt(3) v1 := b.NewValue0(v.Pos, OpARM64NEG, x.Type) v1.AddArg(x) v0.AddArg2(v1, x) @@ -14601,14 +14601,14 @@ func rewriteValueARM64_OpARM64MULW(v *Value) bool { if v_1.Op != OpARM64MOVDconst { continue } - c := v_1.AuxInt + c := auxIntToInt64(v_1.AuxInt) if !(c%9 == 0 && isPowerOfTwo(c/9) && is32Bit(c)) { continue } v.reset(OpARM64SLLconst) - v.AuxInt = log2(c / 9) + v.AuxInt = int64ToAuxInt(log2(c / 9)) v0 := b.NewValue0(v.Pos, OpARM64ADDshiftLL, x.Type) - v0.AuxInt = 3 + v0.AuxInt = int64ToAuxInt(3) v0.AddArg2(x, x) v.AddArg(v0) return true @@ -14622,13 +14622,13 @@ func rewriteValueARM64_OpARM64MULW(v *Value) bool { if v_0.Op != OpARM64MOVDconst { continue } - c := v_0.AuxInt + c := auxIntToInt64(v_0.AuxInt) if v_1.Op != OpARM64MOVDconst { continue } - d := v_1.AuxInt + d := auxIntToInt64(v_1.AuxInt) v.reset(OpARM64MOVDconst) - v.AuxInt = int64(int32(c) * int32(d)) + v.AuxInt = int64ToAuxInt(int64(int32(c) * int32(d))) return true } break @@ -14655,9 +14655,9 @@ func rewriteValueARM64_OpARM64MVN(v *Value) bool { if v_0.Op != OpARM64MOVDconst { break } - c := v_0.AuxInt + c := auxIntToInt64(v_0.AuxInt) v.reset(OpARM64MOVDconst) - v.AuxInt = ^c + v.AuxInt = int64ToAuxInt(^c) return true } // match: (MVN x:(SLLconst [c] y)) @@ -14796,9 +14796,9 @@ func rewriteValueARM64_OpARM64NEG(v *Value) bool { if v_0.Op != OpARM64MOVDconst { break } - c := v_0.AuxInt + c := auxIntToInt64(v_0.AuxInt) v.reset(OpARM64MOVDconst) - v.AuxInt = -c + v.AuxInt = int64ToAuxInt(-c) return true } // match: (NEG x:(SLLconst [c] y)) @@ -14944,9 +14944,9 @@ func rewriteValueARM64_OpARM64OR(v *Value) bool { if v_1.Op != OpARM64MOVDconst { continue } - c := v_1.AuxInt + c := auxIntToInt64(v_1.AuxInt) v.reset(OpARM64ORconst) - v.AuxInt = c + v.AuxInt = int64ToAuxInt(c) v.AddArg(x) return true } @@ -16938,9 +16938,9 @@ func rewriteValueARM64_OpARM64ORN(v *Value) bool { if v_1.Op != OpARM64MOVDconst { break } - c := v_1.AuxInt + c := auxIntToInt64(v_1.AuxInt) v.reset(OpARM64ORconst) - v.AuxInt = ^c + v.AuxInt = int64ToAuxInt(^c) v.AddArg(x) return true } @@ -16952,7 +16952,7 @@ func rewriteValueARM64_OpARM64ORN(v *Value) bool { break } v.reset(OpARM64MOVDconst) - v.AuxInt = -1 + v.AuxInt = int64ToAuxInt(-1) return true } // match: (ORN x0 x1:(SLLconst [c] y)) @@ -17127,7 +17127,7 @@ func rewriteValueARM64_OpARM64ORconst(v *Value) bool { // match: (ORconst [0] x) // result: x for { - if v.AuxInt != 0 { + if auxIntToInt64(v.AuxInt) != 0 { break } x := v_0 @@ -17137,36 +17137,36 @@ func rewriteValueARM64_OpARM64ORconst(v *Value) bool { // match: (ORconst [-1] _) // result: (MOVDconst [-1]) for { - if v.AuxInt != -1 { + if auxIntToInt64(v.AuxInt) != -1 { break } v.reset(OpARM64MOVDconst) - v.AuxInt = -1 + v.AuxInt = int64ToAuxInt(-1) return true } // match: (ORconst [c] (MOVDconst [d])) // result: (MOVDconst [c|d]) for { - c := v.AuxInt + c := auxIntToInt64(v.AuxInt) if v_0.Op != OpARM64MOVDconst { break } - d := v_0.AuxInt + d := auxIntToInt64(v_0.AuxInt) v.reset(OpARM64MOVDconst) - v.AuxInt = c | d + v.AuxInt = int64ToAuxInt(c | d) return true } // match: (ORconst [c] (ORconst [d] x)) // result: (ORconst [c|d] x) for { - c := v.AuxInt + c := auxIntToInt64(v.AuxInt) if v_0.Op != OpARM64ORconst { break } - d := v_0.AuxInt + d := auxIntToInt64(v_0.AuxInt) x := v_0.Args[0] v.reset(OpARM64ORconst) - v.AuxInt = c | d + v.AuxInt = int64ToAuxInt(c | d) v.AddArg(x) return true } @@ -19064,7 +19064,7 @@ func rewriteValueARM64_OpARM64SBCSflags(v *Value) bool { break } v_2_0_0 := v_2_0.Args[0] - if v_2_0_0.Op != OpARM64MOVDconst || v_2_0_0.AuxInt != 0 { + if v_2_0_0.Op != OpARM64MOVDconst || auxIntToInt64(v_2_0_0.AuxInt) != 0 { break } v.reset(OpARM64SUBSflags) @@ -19083,9 +19083,9 @@ func rewriteValueARM64_OpARM64SLL(v *Value) bool { if v_1.Op != OpARM64MOVDconst { break } - c := v_1.AuxInt + c := auxIntToInt64(v_1.AuxInt) v.reset(OpARM64SLLconst) - v.AuxInt = c & 63 + v.AuxInt = int64ToAuxInt(c & 63) v.AddArg(x) return true } @@ -19096,13 +19096,13 @@ func rewriteValueARM64_OpARM64SLLconst(v *Value) bool { // match: (SLLconst [c] (MOVDconst [d])) // result: (MOVDconst [d<>uint64(c)]) for { - c := v.AuxInt + c := auxIntToInt64(v.AuxInt) if v_0.Op != OpARM64MOVDconst { break } - d := v_0.AuxInt + d := auxIntToInt64(v_0.AuxInt) v.reset(OpARM64MOVDconst) - v.AuxInt = d >> uint64(c) + v.AuxInt = int64ToAuxInt(d >> uint64(c)) return true } // match: (SRAconst [rc] (SLLconst [lc] x)) @@ -19378,9 +19378,9 @@ func rewriteValueARM64_OpARM64SRL(v *Value) bool { if v_1.Op != OpARM64MOVDconst { break } - c := v_1.AuxInt + c := auxIntToInt64(v_1.AuxInt) v.reset(OpARM64SRLconst) - v.AuxInt = c & 63 + v.AuxInt = int64ToAuxInt(c & 63) v.AddArg(x) return true } @@ -19391,13 +19391,13 @@ func rewriteValueARM64_OpARM64SRLconst(v *Value) bool { // match: (SRLconst [c] (MOVDconst [d])) // result: (MOVDconst [int64(uint64(d)>>uint64(c))]) for { - c := v.AuxInt + c := auxIntToInt64(v.AuxInt) if v_0.Op != OpARM64MOVDconst { break } - d := v_0.AuxInt + d := auxIntToInt64(v_0.AuxInt) v.reset(OpARM64MOVDconst) - v.AuxInt = int64(uint64(d) >> uint64(c)) + v.AuxInt = int64ToAuxInt(int64(uint64(d) >> uint64(c))) return true } // match: (SRLconst [c] (SLLconst [c] x)) @@ -19679,9 +19679,9 @@ func rewriteValueARM64_OpARM64SUB(v *Value) bool { if v_1.Op != OpARM64MOVDconst { break } - c := v_1.AuxInt + c := auxIntToInt64(v_1.AuxInt) v.reset(OpARM64SUBconst) - v.AuxInt = c + v.AuxInt = int64ToAuxInt(c) v.AddArg(x) return true } @@ -19765,7 +19765,7 @@ func rewriteValueARM64_OpARM64SUB(v *Value) bool { break } v.reset(OpARM64MOVDconst) - v.AuxInt = 0 + v.AuxInt = int64ToAuxInt(0) return true } // match: (SUB x (SUB y z)) @@ -19862,7 +19862,7 @@ func rewriteValueARM64_OpARM64SUBconst(v *Value) bool { // match: (SUBconst [0] x) // result: x for { - if v.AuxInt != 0 { + if auxIntToInt64(v.AuxInt) != 0 { break } x := v_0 @@ -19872,40 +19872,40 @@ func rewriteValueARM64_OpARM64SUBconst(v *Value) bool { // match: (SUBconst [c] (MOVDconst [d])) // result: (MOVDconst [d-c]) for { - c := v.AuxInt + c := auxIntToInt64(v.AuxInt) if v_0.Op != OpARM64MOVDconst { break } - d := v_0.AuxInt + d := auxIntToInt64(v_0.AuxInt) v.reset(OpARM64MOVDconst) - v.AuxInt = d - c + v.AuxInt = int64ToAuxInt(d - c) return true } // match: (SUBconst [c] (SUBconst [d] x)) // result: (ADDconst [-c-d] x) for { - c := v.AuxInt + c := auxIntToInt64(v.AuxInt) if v_0.Op != OpARM64SUBconst { break } - d := v_0.AuxInt + d := auxIntToInt64(v_0.AuxInt) x := v_0.Args[0] v.reset(OpARM64ADDconst) - v.AuxInt = -c - d + v.AuxInt = int64ToAuxInt(-c - d) v.AddArg(x) return true } // match: (SUBconst [c] (ADDconst [d] x)) // result: (ADDconst [-c+d] x) for { - c := v.AuxInt + c := auxIntToInt64(v.AuxInt) if v_0.Op != OpARM64ADDconst { break } - d := v_0.AuxInt + d := auxIntToInt64(v_0.AuxInt) x := v_0.Args[0] v.reset(OpARM64ADDconst) - v.AuxInt = -c + d + v.AuxInt = int64ToAuxInt(-c + d) v.AddArg(x) return true } @@ -20030,9 +20030,9 @@ func rewriteValueARM64_OpARM64TST(v *Value) bool { if v_1.Op != OpARM64MOVDconst { continue } - c := v_1.AuxInt + c := auxIntToInt64(v_1.AuxInt) v.reset(OpARM64TSTconst) - v.AuxInt = c + v.AuxInt = int64ToAuxInt(c) v.AddArg(x) return true } @@ -20110,16 +20110,16 @@ func rewriteValueARM64_OpARM64TSTW(v *Value) bool { v_1 := v.Args[1] v_0 := v.Args[0] // match: (TSTW x (MOVDconst [c])) - // result: (TSTWconst [c] x) + // result: (TSTWconst [int32(c)] x) for { for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { x := v_0 if v_1.Op != OpARM64MOVDconst { continue } - c := v_1.AuxInt + c := auxIntToInt64(v_1.AuxInt) v.reset(OpARM64TSTWconst) - v.AuxInt = c + v.AuxInt = int32ToAuxInt(int32(c)) v.AddArg(x) return true } @@ -20375,7 +20375,7 @@ func rewriteValueARM64_OpARM64UDIV(v *Value) bool { // result: x for { x := v_0 - if v_1.Op != OpARM64MOVDconst || v_1.AuxInt != 1 { + if v_1.Op != OpARM64MOVDconst || auxIntToInt64(v_1.AuxInt) != 1 { break } v.copyOf(x) @@ -20389,12 +20389,12 @@ func rewriteValueARM64_OpARM64UDIV(v *Value) bool { if v_1.Op != OpARM64MOVDconst { break } - c := v_1.AuxInt + c := auxIntToInt64(v_1.AuxInt) if !(isPowerOfTwo(c)) { break } v.reset(OpARM64SRLconst) - v.AuxInt = log2(c) + v.AuxInt = int64ToAuxInt(log2(c)) v.AddArg(x) return true } @@ -20404,13 +20404,13 @@ func rewriteValueARM64_OpARM64UDIV(v *Value) bool { if v_0.Op != OpARM64MOVDconst { break } - c := v_0.AuxInt + c := auxIntToInt64(v_0.AuxInt) if v_1.Op != OpARM64MOVDconst { break } - d := v_1.AuxInt + d := auxIntToInt64(v_1.AuxInt) v.reset(OpARM64MOVDconst) - v.AuxInt = int64(uint64(c) / uint64(d)) + v.AuxInt = int64ToAuxInt(int64(uint64(c) / uint64(d))) return true } return false @@ -20426,7 +20426,7 @@ func rewriteValueARM64_OpARM64UDIVW(v *Value) bool { if v_1.Op != OpARM64MOVDconst { break } - c := v_1.AuxInt + c := auxIntToInt64(v_1.AuxInt) if !(uint32(c) == 1) { break } @@ -20441,12 +20441,12 @@ func rewriteValueARM64_OpARM64UDIVW(v *Value) bool { if v_1.Op != OpARM64MOVDconst { break } - c := v_1.AuxInt + c := auxIntToInt64(v_1.AuxInt) if !(isPowerOfTwo(c) && is32Bit(c)) { break } v.reset(OpARM64SRLconst) - v.AuxInt = log2(c) + v.AuxInt = int64ToAuxInt(log2(c)) v.AddArg(x) return true } @@ -20456,13 +20456,13 @@ func rewriteValueARM64_OpARM64UDIVW(v *Value) bool { if v_0.Op != OpARM64MOVDconst { break } - c := v_0.AuxInt + c := auxIntToInt64(v_0.AuxInt) if v_1.Op != OpARM64MOVDconst { break } - d := v_1.AuxInt + d := auxIntToInt64(v_1.AuxInt) v.reset(OpARM64MOVDconst) - v.AuxInt = int64(uint32(c) / uint32(d)) + v.AuxInt = int64ToAuxInt(int64(uint32(c) / uint32(d))) return true } return false @@ -20490,11 +20490,11 @@ func rewriteValueARM64_OpARM64UMOD(v *Value) bool { // match: (UMOD _ (MOVDconst [1])) // result: (MOVDconst [0]) for { - if v_1.Op != OpARM64MOVDconst || v_1.AuxInt != 1 { + if v_1.Op != OpARM64MOVDconst || auxIntToInt64(v_1.AuxInt) != 1 { break } v.reset(OpARM64MOVDconst) - v.AuxInt = 0 + v.AuxInt = int64ToAuxInt(0) return true } // match: (UMOD x (MOVDconst [c])) @@ -20505,12 +20505,12 @@ func rewriteValueARM64_OpARM64UMOD(v *Value) bool { if v_1.Op != OpARM64MOVDconst { break } - c := v_1.AuxInt + c := auxIntToInt64(v_1.AuxInt) if !(isPowerOfTwo(c)) { break } v.reset(OpARM64ANDconst) - v.AuxInt = c - 1 + v.AuxInt = int64ToAuxInt(c - 1) v.AddArg(x) return true } @@ -20520,13 +20520,13 @@ func rewriteValueARM64_OpARM64UMOD(v *Value) bool { if v_0.Op != OpARM64MOVDconst { break } - c := v_0.AuxInt + c := auxIntToInt64(v_0.AuxInt) if v_1.Op != OpARM64MOVDconst { break } - d := v_1.AuxInt + d := auxIntToInt64(v_1.AuxInt) v.reset(OpARM64MOVDconst) - v.AuxInt = int64(uint64(c) % uint64(d)) + v.AuxInt = int64ToAuxInt(int64(uint64(c) % uint64(d))) return true } return false @@ -20558,12 +20558,12 @@ func rewriteValueARM64_OpARM64UMODW(v *Value) bool { if v_1.Op != OpARM64MOVDconst { break } - c := v_1.AuxInt + c := auxIntToInt64(v_1.AuxInt) if !(uint32(c) == 1) { break } v.reset(OpARM64MOVDconst) - v.AuxInt = 0 + v.AuxInt = int64ToAuxInt(0) return true } // match: (UMODW x (MOVDconst [c])) @@ -20574,12 +20574,12 @@ func rewriteValueARM64_OpARM64UMODW(v *Value) bool { if v_1.Op != OpARM64MOVDconst { break } - c := v_1.AuxInt + c := auxIntToInt64(v_1.AuxInt) if !(isPowerOfTwo(c) && is32Bit(c)) { break } v.reset(OpARM64ANDconst) - v.AuxInt = c - 1 + v.AuxInt = int64ToAuxInt(c - 1) v.AddArg(x) return true } @@ -20589,13 +20589,13 @@ func rewriteValueARM64_OpARM64UMODW(v *Value) bool { if v_0.Op != OpARM64MOVDconst { break } - c := v_0.AuxInt + c := auxIntToInt64(v_0.AuxInt) if v_1.Op != OpARM64MOVDconst { break } - d := v_1.AuxInt + d := auxIntToInt64(v_1.AuxInt) v.reset(OpARM64MOVDconst) - v.AuxInt = int64(uint32(c) % uint32(d)) + v.AuxInt = int64ToAuxInt(int64(uint32(c) % uint32(d))) return true } return false @@ -20613,9 +20613,9 @@ func rewriteValueARM64_OpARM64XOR(v *Value) bool { if v_1.Op != OpARM64MOVDconst { continue } - c := v_1.AuxInt + c := auxIntToInt64(v_1.AuxInt) v.reset(OpARM64XORconst) - v.AuxInt = c + v.AuxInt = int64ToAuxInt(c) v.AddArg(x) return true } @@ -20629,7 +20629,7 @@ func rewriteValueARM64_OpARM64XOR(v *Value) bool { break } v.reset(OpARM64MOVDconst) - v.AuxInt = 0 + v.AuxInt = int64ToAuxInt(0) return true } // match: (XOR x (MVN y)) @@ -21001,7 +21001,7 @@ func rewriteValueARM64_OpARM64XORconst(v *Value) bool { // match: (XORconst [0] x) // result: x for { - if v.AuxInt != 0 { + if auxIntToInt64(v.AuxInt) != 0 { break } x := v_0 @@ -21011,7 +21011,7 @@ func rewriteValueARM64_OpARM64XORconst(v *Value) bool { // match: (XORconst [-1] x) // result: (MVN x) for { - if v.AuxInt != -1 { + if auxIntToInt64(v.AuxInt) != -1 { break } x := v_0 @@ -21022,26 +21022,26 @@ func rewriteValueARM64_OpARM64XORconst(v *Value) bool { // match: (XORconst [c] (MOVDconst [d])) // result: (MOVDconst [c^d]) for { - c := v.AuxInt + c := auxIntToInt64(v.AuxInt) if v_0.Op != OpARM64MOVDconst { break } - d := v_0.AuxInt + d := auxIntToInt64(v_0.AuxInt) v.reset(OpARM64MOVDconst) - v.AuxInt = c ^ d + v.AuxInt = int64ToAuxInt(c ^ d) return true } // match: (XORconst [c] (XORconst [d] x)) // result: (XORconst [c^d] x) for { - c := v.AuxInt + c := auxIntToInt64(v.AuxInt) if v_0.Op != OpARM64XORconst { break } - d := v_0.AuxInt + d := auxIntToInt64(v_0.AuxInt) x := v_0.Args[0] v.reset(OpARM64XORconst) - v.AuxInt = c ^ d + v.AuxInt = int64ToAuxInt(c ^ d) v.AddArg(x) return true } -- cgit v1.3 From 790fa1c546a05936406f6bbf24f6a6ddeb6ec6ad Mon Sep 17 00:00:00 2001 From: Martin Möhrmann Date: Mon, 14 Sep 2020 16:30:43 +0200 Subject: cmd/compile: unify reflect, string and slice copy runtime functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use a common runtime slicecopy function to copy strings or slices into slices. This deduplicates similar code previously used in reflect.slicecopy and runtime.stringslicecopy. Change-Id: I09572ff0647a9e12bb5c6989689ce1c43f16b7f1 Reviewed-on: https://go-review.googlesource.com/c/go/+/254658 Run-TryBot: Martin Möhrmann TryBot-Result: Go Bot Trust: Martin Möhrmann Reviewed-by: Keith Randall --- src/cmd/compile/internal/gc/builtin.go | 408 ++++++++++++------------- src/cmd/compile/internal/gc/builtin/runtime.go | 3 +- src/cmd/compile/internal/gc/subr.go | 12 +- src/cmd/compile/internal/gc/walk.go | 60 ++-- src/runtime/mbarrier.go | 23 +- src/runtime/slice.go | 44 +-- 6 files changed, 247 insertions(+), 303 deletions(-) (limited to 'src/cmd/compile/internal') diff --git a/src/cmd/compile/internal/gc/builtin.go b/src/cmd/compile/internal/gc/builtin.go index 861ffaaa5b..da7b107bfe 100644 --- a/src/cmd/compile/internal/gc/builtin.go +++ b/src/cmd/compile/internal/gc/builtin.go @@ -64,136 +64,135 @@ var runtimeDecls = [...]struct { {"stringtoslicebyte", funcTag, 49}, {"stringtoslicerune", funcTag, 52}, {"slicecopy", funcTag, 53}, - {"slicestringcopy", funcTag, 54}, - {"decoderune", funcTag, 55}, - {"countrunes", funcTag, 56}, - {"convI2I", funcTag, 57}, - {"convT16", funcTag, 58}, - {"convT32", funcTag, 58}, - {"convT64", funcTag, 58}, - {"convTstring", funcTag, 58}, - {"convTslice", funcTag, 58}, - {"convT2E", funcTag, 59}, - {"convT2Enoptr", funcTag, 59}, - {"convT2I", funcTag, 59}, - {"convT2Inoptr", funcTag, 59}, - {"assertE2I", funcTag, 57}, - {"assertE2I2", funcTag, 60}, - {"assertI2I", funcTag, 57}, - {"assertI2I2", funcTag, 60}, - {"panicdottypeE", funcTag, 61}, - {"panicdottypeI", funcTag, 61}, - {"panicnildottype", funcTag, 62}, - {"ifaceeq", funcTag, 64}, - {"efaceeq", funcTag, 64}, - {"fastrand", funcTag, 66}, - {"makemap64", funcTag, 68}, - {"makemap", funcTag, 69}, - {"makemap_small", funcTag, 70}, - {"mapaccess1", funcTag, 71}, - {"mapaccess1_fast32", funcTag, 72}, - {"mapaccess1_fast64", funcTag, 72}, - {"mapaccess1_faststr", funcTag, 72}, - {"mapaccess1_fat", funcTag, 73}, - {"mapaccess2", funcTag, 74}, - {"mapaccess2_fast32", funcTag, 75}, - {"mapaccess2_fast64", funcTag, 75}, - {"mapaccess2_faststr", funcTag, 75}, - {"mapaccess2_fat", funcTag, 76}, - {"mapassign", funcTag, 71}, - {"mapassign_fast32", funcTag, 72}, - {"mapassign_fast32ptr", funcTag, 72}, - {"mapassign_fast64", funcTag, 72}, - {"mapassign_fast64ptr", funcTag, 72}, - {"mapassign_faststr", funcTag, 72}, - {"mapiterinit", funcTag, 77}, - {"mapdelete", funcTag, 77}, - {"mapdelete_fast32", funcTag, 78}, - {"mapdelete_fast64", funcTag, 78}, - {"mapdelete_faststr", funcTag, 78}, - {"mapiternext", funcTag, 79}, - {"mapclear", funcTag, 80}, - {"makechan64", funcTag, 82}, - {"makechan", funcTag, 83}, - {"chanrecv1", funcTag, 85}, - {"chanrecv2", funcTag, 86}, - {"chansend1", funcTag, 88}, + {"decoderune", funcTag, 54}, + {"countrunes", funcTag, 55}, + {"convI2I", funcTag, 56}, + {"convT16", funcTag, 57}, + {"convT32", funcTag, 57}, + {"convT64", funcTag, 57}, + {"convTstring", funcTag, 57}, + {"convTslice", funcTag, 57}, + {"convT2E", funcTag, 58}, + {"convT2Enoptr", funcTag, 58}, + {"convT2I", funcTag, 58}, + {"convT2Inoptr", funcTag, 58}, + {"assertE2I", funcTag, 56}, + {"assertE2I2", funcTag, 59}, + {"assertI2I", funcTag, 56}, + {"assertI2I2", funcTag, 59}, + {"panicdottypeE", funcTag, 60}, + {"panicdottypeI", funcTag, 60}, + {"panicnildottype", funcTag, 61}, + {"ifaceeq", funcTag, 63}, + {"efaceeq", funcTag, 63}, + {"fastrand", funcTag, 65}, + {"makemap64", funcTag, 67}, + {"makemap", funcTag, 68}, + {"makemap_small", funcTag, 69}, + {"mapaccess1", funcTag, 70}, + {"mapaccess1_fast32", funcTag, 71}, + {"mapaccess1_fast64", funcTag, 71}, + {"mapaccess1_faststr", funcTag, 71}, + {"mapaccess1_fat", funcTag, 72}, + {"mapaccess2", funcTag, 73}, + {"mapaccess2_fast32", funcTag, 74}, + {"mapaccess2_fast64", funcTag, 74}, + {"mapaccess2_faststr", funcTag, 74}, + {"mapaccess2_fat", funcTag, 75}, + {"mapassign", funcTag, 70}, + {"mapassign_fast32", funcTag, 71}, + {"mapassign_fast32ptr", funcTag, 71}, + {"mapassign_fast64", funcTag, 71}, + {"mapassign_fast64ptr", funcTag, 71}, + {"mapassign_faststr", funcTag, 71}, + {"mapiterinit", funcTag, 76}, + {"mapdelete", funcTag, 76}, + {"mapdelete_fast32", funcTag, 77}, + {"mapdelete_fast64", funcTag, 77}, + {"mapdelete_faststr", funcTag, 77}, + {"mapiternext", funcTag, 78}, + {"mapclear", funcTag, 79}, + {"makechan64", funcTag, 81}, + {"makechan", funcTag, 82}, + {"chanrecv1", funcTag, 84}, + {"chanrecv2", funcTag, 85}, + {"chansend1", funcTag, 87}, {"closechan", funcTag, 30}, - {"writeBarrier", varTag, 90}, - {"typedmemmove", funcTag, 91}, - {"typedmemclr", funcTag, 92}, - {"typedslicecopy", funcTag, 93}, - {"selectnbsend", funcTag, 94}, - {"selectnbrecv", funcTag, 95}, - {"selectnbrecv2", funcTag, 97}, - {"selectsetpc", funcTag, 98}, - {"selectgo", funcTag, 99}, + {"writeBarrier", varTag, 89}, + {"typedmemmove", funcTag, 90}, + {"typedmemclr", funcTag, 91}, + {"typedslicecopy", funcTag, 92}, + {"selectnbsend", funcTag, 93}, + {"selectnbrecv", funcTag, 94}, + {"selectnbrecv2", funcTag, 96}, + {"selectsetpc", funcTag, 97}, + {"selectgo", funcTag, 98}, {"block", funcTag, 9}, - {"makeslice", funcTag, 100}, - {"makeslice64", funcTag, 101}, - {"makeslicecopy", funcTag, 102}, - {"growslice", funcTag, 104}, - {"memmove", funcTag, 105}, - {"memclrNoHeapPointers", funcTag, 106}, - {"memclrHasPointers", funcTag, 106}, - {"memequal", funcTag, 107}, - {"memequal0", funcTag, 108}, - {"memequal8", funcTag, 108}, - {"memequal16", funcTag, 108}, - {"memequal32", funcTag, 108}, - {"memequal64", funcTag, 108}, - {"memequal128", funcTag, 108}, - {"f32equal", funcTag, 109}, - {"f64equal", funcTag, 109}, - {"c64equal", funcTag, 109}, - {"c128equal", funcTag, 109}, - {"strequal", funcTag, 109}, - {"interequal", funcTag, 109}, - {"nilinterequal", funcTag, 109}, - {"memhash", funcTag, 110}, - {"memhash0", funcTag, 111}, - {"memhash8", funcTag, 111}, - {"memhash16", funcTag, 111}, - {"memhash32", funcTag, 111}, - {"memhash64", funcTag, 111}, - {"memhash128", funcTag, 111}, - {"f32hash", funcTag, 111}, - {"f64hash", funcTag, 111}, - {"c64hash", funcTag, 111}, - {"c128hash", funcTag, 111}, - {"strhash", funcTag, 111}, - {"interhash", funcTag, 111}, - {"nilinterhash", funcTag, 111}, - {"int64div", funcTag, 112}, - {"uint64div", funcTag, 113}, - {"int64mod", funcTag, 112}, - {"uint64mod", funcTag, 113}, - {"float64toint64", funcTag, 114}, - {"float64touint64", funcTag, 115}, - {"float64touint32", funcTag, 116}, - {"int64tofloat64", funcTag, 117}, - {"uint64tofloat64", funcTag, 118}, - {"uint32tofloat64", funcTag, 119}, - {"complex128div", funcTag, 120}, - {"racefuncenter", funcTag, 121}, + {"makeslice", funcTag, 99}, + {"makeslice64", funcTag, 100}, + {"makeslicecopy", funcTag, 101}, + {"growslice", funcTag, 103}, + {"memmove", funcTag, 104}, + {"memclrNoHeapPointers", funcTag, 105}, + {"memclrHasPointers", funcTag, 105}, + {"memequal", funcTag, 106}, + {"memequal0", funcTag, 107}, + {"memequal8", funcTag, 107}, + {"memequal16", funcTag, 107}, + {"memequal32", funcTag, 107}, + {"memequal64", funcTag, 107}, + {"memequal128", funcTag, 107}, + {"f32equal", funcTag, 108}, + {"f64equal", funcTag, 108}, + {"c64equal", funcTag, 108}, + {"c128equal", funcTag, 108}, + {"strequal", funcTag, 108}, + {"interequal", funcTag, 108}, + {"nilinterequal", funcTag, 108}, + {"memhash", funcTag, 109}, + {"memhash0", funcTag, 110}, + {"memhash8", funcTag, 110}, + {"memhash16", funcTag, 110}, + {"memhash32", funcTag, 110}, + {"memhash64", funcTag, 110}, + {"memhash128", funcTag, 110}, + {"f32hash", funcTag, 110}, + {"f64hash", funcTag, 110}, + {"c64hash", funcTag, 110}, + {"c128hash", funcTag, 110}, + {"strhash", funcTag, 110}, + {"interhash", funcTag, 110}, + {"nilinterhash", funcTag, 110}, + {"int64div", funcTag, 111}, + {"uint64div", funcTag, 112}, + {"int64mod", funcTag, 111}, + {"uint64mod", funcTag, 112}, + {"float64toint64", funcTag, 113}, + {"float64touint64", funcTag, 114}, + {"float64touint32", funcTag, 115}, + {"int64tofloat64", funcTag, 116}, + {"uint64tofloat64", funcTag, 117}, + {"uint32tofloat64", funcTag, 118}, + {"complex128div", funcTag, 119}, + {"racefuncenter", funcTag, 120}, {"racefuncenterfp", funcTag, 9}, {"racefuncexit", funcTag, 9}, - {"raceread", funcTag, 121}, - {"racewrite", funcTag, 121}, - {"racereadrange", funcTag, 122}, - {"racewriterange", funcTag, 122}, - {"msanread", funcTag, 122}, - {"msanwrite", funcTag, 122}, - {"checkptrAlignment", funcTag, 123}, - {"checkptrArithmetic", funcTag, 125}, - {"libfuzzerTraceCmp1", funcTag, 127}, - {"libfuzzerTraceCmp2", funcTag, 129}, - {"libfuzzerTraceCmp4", funcTag, 130}, - {"libfuzzerTraceCmp8", funcTag, 131}, - {"libfuzzerTraceConstCmp1", funcTag, 127}, - {"libfuzzerTraceConstCmp2", funcTag, 129}, - {"libfuzzerTraceConstCmp4", funcTag, 130}, - {"libfuzzerTraceConstCmp8", funcTag, 131}, + {"raceread", funcTag, 120}, + {"racewrite", funcTag, 120}, + {"racereadrange", funcTag, 121}, + {"racewriterange", funcTag, 121}, + {"msanread", funcTag, 121}, + {"msanwrite", funcTag, 121}, + {"checkptrAlignment", funcTag, 122}, + {"checkptrArithmetic", funcTag, 124}, + {"libfuzzerTraceCmp1", funcTag, 126}, + {"libfuzzerTraceCmp2", funcTag, 128}, + {"libfuzzerTraceCmp4", funcTag, 129}, + {"libfuzzerTraceCmp8", funcTag, 130}, + {"libfuzzerTraceConstCmp1", funcTag, 126}, + {"libfuzzerTraceConstCmp2", funcTag, 128}, + {"libfuzzerTraceConstCmp4", funcTag, 129}, + {"libfuzzerTraceConstCmp8", funcTag, 130}, {"x86HasPOPCNT", varTag, 6}, {"x86HasSSE41", varTag, 6}, {"x86HasFMA", varTag, 6}, @@ -202,7 +201,7 @@ var runtimeDecls = [...]struct { } func runtimeTypes() []*types.Type { - var typs [132]*types.Type + var typs [131]*types.Type typs[0] = types.Bytetype typs[1] = types.NewPtr(typs[0]) typs[2] = types.Types[TANY] @@ -257,83 +256,82 @@ func runtimeTypes() []*types.Type { typs[51] = types.NewPtr(typs[50]) typs[52] = functype(nil, []*Node{anonfield(typs[51]), anonfield(typs[28])}, []*Node{anonfield(typs[46])}) typs[53] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[15]), anonfield(typs[3]), anonfield(typs[15]), anonfield(typs[5])}, []*Node{anonfield(typs[15])}) - typs[54] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[15]), anonfield(typs[28])}, []*Node{anonfield(typs[15])}) - typs[55] = functype(nil, []*Node{anonfield(typs[28]), anonfield(typs[15])}, []*Node{anonfield(typs[45]), anonfield(typs[15])}) - typs[56] = functype(nil, []*Node{anonfield(typs[28])}, []*Node{anonfield(typs[15])}) - typs[57] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[2])}, []*Node{anonfield(typs[2])}) - typs[58] = functype(nil, []*Node{anonfield(typs[2])}, []*Node{anonfield(typs[7])}) - typs[59] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[3])}, []*Node{anonfield(typs[2])}) - typs[60] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[2])}, []*Node{anonfield(typs[2]), anonfield(typs[6])}) - typs[61] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[1]), anonfield(typs[1])}, nil) - typs[62] = functype(nil, []*Node{anonfield(typs[1])}, nil) - typs[63] = types.NewPtr(typs[5]) - typs[64] = functype(nil, []*Node{anonfield(typs[63]), anonfield(typs[7]), anonfield(typs[7])}, []*Node{anonfield(typs[6])}) - typs[65] = types.Types[TUINT32] - typs[66] = functype(nil, nil, []*Node{anonfield(typs[65])}) - typs[67] = types.NewMap(typs[2], typs[2]) - typs[68] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[22]), anonfield(typs[3])}, []*Node{anonfield(typs[67])}) - typs[69] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[15]), anonfield(typs[3])}, []*Node{anonfield(typs[67])}) - typs[70] = functype(nil, nil, []*Node{anonfield(typs[67])}) - typs[71] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[67]), anonfield(typs[3])}, []*Node{anonfield(typs[3])}) - typs[72] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[67]), anonfield(typs[2])}, []*Node{anonfield(typs[3])}) - typs[73] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[67]), anonfield(typs[3]), anonfield(typs[1])}, []*Node{anonfield(typs[3])}) - typs[74] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[67]), anonfield(typs[3])}, []*Node{anonfield(typs[3]), anonfield(typs[6])}) - typs[75] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[67]), anonfield(typs[2])}, []*Node{anonfield(typs[3]), anonfield(typs[6])}) - typs[76] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[67]), anonfield(typs[3]), anonfield(typs[1])}, []*Node{anonfield(typs[3]), anonfield(typs[6])}) - typs[77] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[67]), anonfield(typs[3])}, nil) - typs[78] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[67]), anonfield(typs[2])}, nil) - typs[79] = functype(nil, []*Node{anonfield(typs[3])}, nil) - typs[80] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[67])}, nil) - typs[81] = types.NewChan(typs[2], types.Cboth) - typs[82] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[22])}, []*Node{anonfield(typs[81])}) - typs[83] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[15])}, []*Node{anonfield(typs[81])}) - typs[84] = types.NewChan(typs[2], types.Crecv) - typs[85] = functype(nil, []*Node{anonfield(typs[84]), anonfield(typs[3])}, nil) - typs[86] = functype(nil, []*Node{anonfield(typs[84]), anonfield(typs[3])}, []*Node{anonfield(typs[6])}) - typs[87] = types.NewChan(typs[2], types.Csend) - typs[88] = functype(nil, []*Node{anonfield(typs[87]), anonfield(typs[3])}, nil) - typs[89] = types.NewArray(typs[0], 3) - typs[90] = tostruct([]*Node{namedfield("enabled", typs[6]), namedfield("pad", typs[89]), namedfield("needed", typs[6]), namedfield("cgo", typs[6]), namedfield("alignme", typs[24])}) - typs[91] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[3]), anonfield(typs[3])}, nil) - typs[92] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[3])}, nil) - typs[93] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[3]), anonfield(typs[15]), anonfield(typs[3]), anonfield(typs[15])}, []*Node{anonfield(typs[15])}) - typs[94] = functype(nil, []*Node{anonfield(typs[87]), anonfield(typs[3])}, []*Node{anonfield(typs[6])}) - typs[95] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[84])}, []*Node{anonfield(typs[6])}) - typs[96] = types.NewPtr(typs[6]) - typs[97] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[96]), anonfield(typs[84])}, []*Node{anonfield(typs[6])}) - typs[98] = functype(nil, []*Node{anonfield(typs[63])}, nil) - typs[99] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[1]), anonfield(typs[63]), anonfield(typs[15]), anonfield(typs[15]), anonfield(typs[6])}, []*Node{anonfield(typs[15]), anonfield(typs[6])}) - typs[100] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[15]), anonfield(typs[15])}, []*Node{anonfield(typs[7])}) - typs[101] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[22]), anonfield(typs[22])}, []*Node{anonfield(typs[7])}) - typs[102] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[15]), anonfield(typs[15]), anonfield(typs[7])}, []*Node{anonfield(typs[7])}) - typs[103] = types.NewSlice(typs[2]) - typs[104] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[103]), anonfield(typs[15])}, []*Node{anonfield(typs[103])}) - typs[105] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[3]), anonfield(typs[5])}, nil) - typs[106] = functype(nil, []*Node{anonfield(typs[7]), anonfield(typs[5])}, nil) - typs[107] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[3]), anonfield(typs[5])}, []*Node{anonfield(typs[6])}) - typs[108] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[3])}, []*Node{anonfield(typs[6])}) - typs[109] = functype(nil, []*Node{anonfield(typs[7]), anonfield(typs[7])}, []*Node{anonfield(typs[6])}) - typs[110] = functype(nil, []*Node{anonfield(typs[7]), anonfield(typs[5]), anonfield(typs[5])}, []*Node{anonfield(typs[5])}) - typs[111] = functype(nil, []*Node{anonfield(typs[7]), anonfield(typs[5])}, []*Node{anonfield(typs[5])}) - typs[112] = functype(nil, []*Node{anonfield(typs[22]), anonfield(typs[22])}, []*Node{anonfield(typs[22])}) - typs[113] = functype(nil, []*Node{anonfield(typs[24]), anonfield(typs[24])}, []*Node{anonfield(typs[24])}) - typs[114] = functype(nil, []*Node{anonfield(typs[20])}, []*Node{anonfield(typs[22])}) - typs[115] = functype(nil, []*Node{anonfield(typs[20])}, []*Node{anonfield(typs[24])}) - typs[116] = functype(nil, []*Node{anonfield(typs[20])}, []*Node{anonfield(typs[65])}) - typs[117] = functype(nil, []*Node{anonfield(typs[22])}, []*Node{anonfield(typs[20])}) - typs[118] = functype(nil, []*Node{anonfield(typs[24])}, []*Node{anonfield(typs[20])}) - typs[119] = functype(nil, []*Node{anonfield(typs[65])}, []*Node{anonfield(typs[20])}) - typs[120] = functype(nil, []*Node{anonfield(typs[26]), anonfield(typs[26])}, []*Node{anonfield(typs[26])}) - typs[121] = functype(nil, []*Node{anonfield(typs[5])}, nil) - typs[122] = functype(nil, []*Node{anonfield(typs[5]), anonfield(typs[5])}, nil) - typs[123] = functype(nil, []*Node{anonfield(typs[7]), anonfield(typs[1]), anonfield(typs[5])}, nil) - typs[124] = types.NewSlice(typs[7]) - typs[125] = functype(nil, []*Node{anonfield(typs[7]), anonfield(typs[124])}, nil) - typs[126] = types.Types[TUINT8] - typs[127] = functype(nil, []*Node{anonfield(typs[126]), anonfield(typs[126])}, nil) - typs[128] = types.Types[TUINT16] - typs[129] = functype(nil, []*Node{anonfield(typs[128]), anonfield(typs[128])}, nil) - typs[130] = functype(nil, []*Node{anonfield(typs[65]), anonfield(typs[65])}, nil) - typs[131] = functype(nil, []*Node{anonfield(typs[24]), anonfield(typs[24])}, nil) + typs[54] = functype(nil, []*Node{anonfield(typs[28]), anonfield(typs[15])}, []*Node{anonfield(typs[45]), anonfield(typs[15])}) + typs[55] = functype(nil, []*Node{anonfield(typs[28])}, []*Node{anonfield(typs[15])}) + typs[56] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[2])}, []*Node{anonfield(typs[2])}) + typs[57] = functype(nil, []*Node{anonfield(typs[2])}, []*Node{anonfield(typs[7])}) + typs[58] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[3])}, []*Node{anonfield(typs[2])}) + typs[59] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[2])}, []*Node{anonfield(typs[2]), anonfield(typs[6])}) + typs[60] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[1]), anonfield(typs[1])}, nil) + typs[61] = functype(nil, []*Node{anonfield(typs[1])}, nil) + typs[62] = types.NewPtr(typs[5]) + typs[63] = functype(nil, []*Node{anonfield(typs[62]), anonfield(typs[7]), anonfield(typs[7])}, []*Node{anonfield(typs[6])}) + typs[64] = types.Types[TUINT32] + typs[65] = functype(nil, nil, []*Node{anonfield(typs[64])}) + typs[66] = types.NewMap(typs[2], typs[2]) + typs[67] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[22]), anonfield(typs[3])}, []*Node{anonfield(typs[66])}) + typs[68] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[15]), anonfield(typs[3])}, []*Node{anonfield(typs[66])}) + typs[69] = functype(nil, nil, []*Node{anonfield(typs[66])}) + typs[70] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[66]), anonfield(typs[3])}, []*Node{anonfield(typs[3])}) + typs[71] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[66]), anonfield(typs[2])}, []*Node{anonfield(typs[3])}) + typs[72] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[66]), anonfield(typs[3]), anonfield(typs[1])}, []*Node{anonfield(typs[3])}) + typs[73] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[66]), anonfield(typs[3])}, []*Node{anonfield(typs[3]), anonfield(typs[6])}) + typs[74] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[66]), anonfield(typs[2])}, []*Node{anonfield(typs[3]), anonfield(typs[6])}) + typs[75] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[66]), anonfield(typs[3]), anonfield(typs[1])}, []*Node{anonfield(typs[3]), anonfield(typs[6])}) + typs[76] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[66]), anonfield(typs[3])}, nil) + typs[77] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[66]), anonfield(typs[2])}, nil) + typs[78] = functype(nil, []*Node{anonfield(typs[3])}, nil) + typs[79] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[66])}, nil) + typs[80] = types.NewChan(typs[2], types.Cboth) + typs[81] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[22])}, []*Node{anonfield(typs[80])}) + typs[82] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[15])}, []*Node{anonfield(typs[80])}) + typs[83] = types.NewChan(typs[2], types.Crecv) + typs[84] = functype(nil, []*Node{anonfield(typs[83]), anonfield(typs[3])}, nil) + typs[85] = functype(nil, []*Node{anonfield(typs[83]), anonfield(typs[3])}, []*Node{anonfield(typs[6])}) + typs[86] = types.NewChan(typs[2], types.Csend) + typs[87] = functype(nil, []*Node{anonfield(typs[86]), anonfield(typs[3])}, nil) + typs[88] = types.NewArray(typs[0], 3) + typs[89] = tostruct([]*Node{namedfield("enabled", typs[6]), namedfield("pad", typs[88]), namedfield("needed", typs[6]), namedfield("cgo", typs[6]), namedfield("alignme", typs[24])}) + typs[90] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[3]), anonfield(typs[3])}, nil) + typs[91] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[3])}, nil) + typs[92] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[3]), anonfield(typs[15]), anonfield(typs[3]), anonfield(typs[15])}, []*Node{anonfield(typs[15])}) + typs[93] = functype(nil, []*Node{anonfield(typs[86]), anonfield(typs[3])}, []*Node{anonfield(typs[6])}) + typs[94] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[83])}, []*Node{anonfield(typs[6])}) + typs[95] = types.NewPtr(typs[6]) + typs[96] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[95]), anonfield(typs[83])}, []*Node{anonfield(typs[6])}) + typs[97] = functype(nil, []*Node{anonfield(typs[62])}, nil) + typs[98] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[1]), anonfield(typs[62]), anonfield(typs[15]), anonfield(typs[15]), anonfield(typs[6])}, []*Node{anonfield(typs[15]), anonfield(typs[6])}) + typs[99] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[15]), anonfield(typs[15])}, []*Node{anonfield(typs[7])}) + typs[100] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[22]), anonfield(typs[22])}, []*Node{anonfield(typs[7])}) + typs[101] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[15]), anonfield(typs[15]), anonfield(typs[7])}, []*Node{anonfield(typs[7])}) + typs[102] = types.NewSlice(typs[2]) + typs[103] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[102]), anonfield(typs[15])}, []*Node{anonfield(typs[102])}) + typs[104] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[3]), anonfield(typs[5])}, nil) + typs[105] = functype(nil, []*Node{anonfield(typs[7]), anonfield(typs[5])}, nil) + typs[106] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[3]), anonfield(typs[5])}, []*Node{anonfield(typs[6])}) + typs[107] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[3])}, []*Node{anonfield(typs[6])}) + typs[108] = functype(nil, []*Node{anonfield(typs[7]), anonfield(typs[7])}, []*Node{anonfield(typs[6])}) + typs[109] = functype(nil, []*Node{anonfield(typs[7]), anonfield(typs[5]), anonfield(typs[5])}, []*Node{anonfield(typs[5])}) + typs[110] = functype(nil, []*Node{anonfield(typs[7]), anonfield(typs[5])}, []*Node{anonfield(typs[5])}) + typs[111] = functype(nil, []*Node{anonfield(typs[22]), anonfield(typs[22])}, []*Node{anonfield(typs[22])}) + typs[112] = functype(nil, []*Node{anonfield(typs[24]), anonfield(typs[24])}, []*Node{anonfield(typs[24])}) + typs[113] = functype(nil, []*Node{anonfield(typs[20])}, []*Node{anonfield(typs[22])}) + typs[114] = functype(nil, []*Node{anonfield(typs[20])}, []*Node{anonfield(typs[24])}) + typs[115] = functype(nil, []*Node{anonfield(typs[20])}, []*Node{anonfield(typs[64])}) + typs[116] = functype(nil, []*Node{anonfield(typs[22])}, []*Node{anonfield(typs[20])}) + typs[117] = functype(nil, []*Node{anonfield(typs[24])}, []*Node{anonfield(typs[20])}) + typs[118] = functype(nil, []*Node{anonfield(typs[64])}, []*Node{anonfield(typs[20])}) + typs[119] = functype(nil, []*Node{anonfield(typs[26]), anonfield(typs[26])}, []*Node{anonfield(typs[26])}) + typs[120] = functype(nil, []*Node{anonfield(typs[5])}, nil) + typs[121] = functype(nil, []*Node{anonfield(typs[5]), anonfield(typs[5])}, nil) + typs[122] = functype(nil, []*Node{anonfield(typs[7]), anonfield(typs[1]), anonfield(typs[5])}, nil) + typs[123] = types.NewSlice(typs[7]) + typs[124] = functype(nil, []*Node{anonfield(typs[7]), anonfield(typs[123])}, nil) + typs[125] = types.Types[TUINT8] + typs[126] = functype(nil, []*Node{anonfield(typs[125]), anonfield(typs[125])}, nil) + typs[127] = types.Types[TUINT16] + typs[128] = functype(nil, []*Node{anonfield(typs[127]), anonfield(typs[127])}, nil) + typs[129] = functype(nil, []*Node{anonfield(typs[64]), anonfield(typs[64])}, nil) + typs[130] = functype(nil, []*Node{anonfield(typs[24]), anonfield(typs[24])}, nil) return typs[:] } diff --git a/src/cmd/compile/internal/gc/builtin/runtime.go b/src/cmd/compile/internal/gc/builtin/runtime.go index 635da80f7c..02d6c7b7f5 100644 --- a/src/cmd/compile/internal/gc/builtin/runtime.go +++ b/src/cmd/compile/internal/gc/builtin/runtime.go @@ -75,8 +75,7 @@ func slicebytetostringtmp(ptr *byte, n int) string func slicerunetostring(*[32]byte, []rune) string func stringtoslicebyte(*[32]byte, string) []byte func stringtoslicerune(*[32]rune, string) []rune -func slicecopy(toPtr *any, toLen int, frPtr *any, frLen int, wid uintptr) int -func slicestringcopy(toPtr *byte, toLen int, fr string) int +func slicecopy(toPtr *any, toLen int, fromPtr *any, fromLen int, wid uintptr) int func decoderune(string, int) (retv rune, retk int) func countrunes(string) int diff --git a/src/cmd/compile/internal/gc/subr.go b/src/cmd/compile/internal/gc/subr.go index 5a5833d19f..8883e75c49 100644 --- a/src/cmd/compile/internal/gc/subr.go +++ b/src/cmd/compile/internal/gc/subr.go @@ -928,16 +928,20 @@ func (o Op) IsSlice3() bool { return false } -// slicePtrLen extracts the pointer and length from a slice. +// backingArrayPtrLen extracts the pointer and length from a slice or string. // This constructs two nodes referring to n, so n must be a cheapexpr. -func (n *Node) slicePtrLen() (ptr, len *Node) { +func (n *Node) backingArrayPtrLen() (ptr, len *Node) { var init Nodes c := cheapexpr(n, &init) if c != n || init.Len() != 0 { - Fatalf("slicePtrLen not cheap: %v", n) + Fatalf("backingArrayPtrLen not cheap: %v", n) } ptr = nod(OSPTR, n, nil) - ptr.Type = n.Type.Elem().PtrTo() + if n.Type.IsString() { + ptr.Type = types.Types[TUINT8].PtrTo() + } else { + ptr.Type = n.Type.Elem().PtrTo() + } len = nod(OLEN, n, nil) len.Type = types.Types[TINT] return ptr, len diff --git a/src/cmd/compile/internal/gc/walk.go b/src/cmd/compile/internal/gc/walk.go index 2d29366880..c3a740d4cc 100644 --- a/src/cmd/compile/internal/gc/walk.go +++ b/src/cmd/compile/internal/gc/walk.go @@ -1484,7 +1484,7 @@ opswitch: } else { // slicebytetostring(*[32]byte, ptr *byte, n int) string n.Left = cheapexpr(n.Left, init) - ptr, len := n.Left.slicePtrLen() + ptr, len := n.Left.backingArrayPtrLen() n = mkcall("slicebytetostring", n.Type, init, a, ptr, len) } @@ -1497,7 +1497,7 @@ opswitch: } // slicebytetostringtmp(ptr *byte, n int) string n.Left = cheapexpr(n.Left, init) - ptr, len := n.Left.slicePtrLen() + ptr, len := n.Left.backingArrayPtrLen() n = mkcall("slicebytetostringtmp", n.Type, init, ptr, len) case OSTR2BYTES: @@ -2764,36 +2764,25 @@ func appendslice(n *Node, init *Nodes) *Node { // instantiate typedslicecopy(typ *type, dstPtr *any, dstLen int, srcPtr *any, srcLen int) int fn := syslook("typedslicecopy") fn = substArgTypes(fn, l1.Type.Elem(), l2.Type.Elem()) - ptr1, len1 := nptr1.slicePtrLen() - ptr2, len2 := nptr2.slicePtrLen() + ptr1, len1 := nptr1.backingArrayPtrLen() + ptr2, len2 := nptr2.backingArrayPtrLen() ncopy = mkcall1(fn, types.Types[TINT], &nodes, typename(elemtype), ptr1, len1, ptr2, len2) - } else if instrumenting && !compiling_runtime { - // rely on runtime to instrument copy. - // copy(s[len(l1):], l2) + // rely on runtime to instrument: + // copy(s[len(l1):], l2) + // l2 can be a slice or string. nptr1 := nod(OSLICE, s, nil) nptr1.Type = s.Type nptr1.SetSliceBounds(nod(OLEN, l1, nil), nil, nil) nptr1 = cheapexpr(nptr1, &nodes) - nptr2 := l2 - if l2.Type.IsString() { - // instantiate func slicestringcopy(toPtr *byte, toLen int, fr string) int - fn := syslook("slicestringcopy") - ptr, len := nptr1.slicePtrLen() - str := nod(OCONVNOP, nptr2, nil) - str.Type = types.Types[TSTRING] - ncopy = mkcall1(fn, types.Types[TINT], &nodes, ptr, len, str) - } else { - // instantiate func slicecopy(to any, fr any, wid uintptr) int - fn := syslook("slicecopy") - fn = substArgTypes(fn, l1.Type.Elem(), l2.Type.Elem()) - ptr1, len1 := nptr1.slicePtrLen() - ptr2, len2 := nptr2.slicePtrLen() - ncopy = mkcall1(fn, types.Types[TINT], &nodes, ptr1, len1, ptr2, len2, nodintconst(elemtype.Width)) - } + ptr1, len1 := nptr1.backingArrayPtrLen() + ptr2, len2 := nptr2.backingArrayPtrLen() + fn := syslook("slicecopy") + fn = substArgTypes(fn, ptr1.Type.Elem(), ptr2.Type.Elem()) + ncopy = mkcall1(fn, types.Types[TINT], &nodes, ptr1, len1, ptr2, len2, nodintconst(elemtype.Width)) } else { // memmove(&s[len(l1)], &l2[0], len(l2)*sizeof(T)) nptr1 := nod(OINDEX, s, nod(OLEN, l1, nil)) @@ -3092,28 +3081,25 @@ func copyany(n *Node, init *Nodes, runtimecall bool) *Node { Curfn.Func.setWBPos(n.Pos) fn := writebarrierfn("typedslicecopy", n.Left.Type.Elem(), n.Right.Type.Elem()) n.Left = cheapexpr(n.Left, init) - ptrL, lenL := n.Left.slicePtrLen() + ptrL, lenL := n.Left.backingArrayPtrLen() n.Right = cheapexpr(n.Right, init) - ptrR, lenR := n.Right.slicePtrLen() + ptrR, lenR := n.Right.backingArrayPtrLen() return mkcall1(fn, n.Type, init, typename(n.Left.Type.Elem()), ptrL, lenL, ptrR, lenR) } if runtimecall { - if n.Right.Type.IsString() { - fn := syslook("slicestringcopy") - n.Left = cheapexpr(n.Left, init) - ptr, len := n.Left.slicePtrLen() - str := nod(OCONVNOP, n.Right, nil) - str.Type = types.Types[TSTRING] - return mkcall1(fn, n.Type, init, ptr, len, str) - } + // rely on runtime to instrument: + // copy(n.Left, n.Right) + // n.Right can be a slice or string. - fn := syslook("slicecopy") - fn = substArgTypes(fn, n.Left.Type.Elem(), n.Right.Type.Elem()) n.Left = cheapexpr(n.Left, init) - ptrL, lenL := n.Left.slicePtrLen() + ptrL, lenL := n.Left.backingArrayPtrLen() n.Right = cheapexpr(n.Right, init) - ptrR, lenR := n.Right.slicePtrLen() + ptrR, lenR := n.Right.backingArrayPtrLen() + + fn := syslook("slicecopy") + fn = substArgTypes(fn, ptrL.Type.Elem(), ptrR.Type.Elem()) + return mkcall1(fn, n.Type, init, ptrL, lenL, ptrR, lenR, nodintconst(n.Left.Type.Elem().Width)) } diff --git a/src/runtime/mbarrier.go b/src/runtime/mbarrier.go index f7875d327a..2b5affce52 100644 --- a/src/runtime/mbarrier.go +++ b/src/runtime/mbarrier.go @@ -281,28 +281,7 @@ func typedslicecopy(typ *_type, dstPtr unsafe.Pointer, dstLen int, srcPtr unsafe //go:linkname reflect_typedslicecopy reflect.typedslicecopy func reflect_typedslicecopy(elemType *_type, dst, src slice) int { if elemType.ptrdata == 0 { - n := dst.len - if n > src.len { - n = src.len - } - if n == 0 { - return 0 - } - - size := uintptr(n) * elemType.size - if raceenabled { - callerpc := getcallerpc() - pc := funcPC(reflect_typedslicecopy) - racewriterangepc(dst.array, size, callerpc, pc) - racereadrangepc(src.array, size, callerpc, pc) - } - if msanenabled { - msanwrite(dst.array, size) - msanread(src.array, size) - } - - memmove(dst.array, src.array, size) - return n + return slicecopy(dst.array, dst.len, src.array, src.len, elemType.size) } return typedslicecopy(elemType, dst.array, dst.len, src.array, src.len) } diff --git a/src/runtime/slice.go b/src/runtime/slice.go index 0418ace25a..82a45c78a9 100644 --- a/src/runtime/slice.go +++ b/src/runtime/slice.go @@ -243,12 +243,13 @@ func isPowerOfTwo(x uintptr) bool { return x&(x-1) == 0 } -func slicecopy(toPtr unsafe.Pointer, toLen int, fmPtr unsafe.Pointer, fmLen int, width uintptr) int { - if fmLen == 0 || toLen == 0 { +// slicecopy is used to copy from a string or slice of pointerless elements into a slice. +func slicecopy(toPtr unsafe.Pointer, toLen int, fromPtr unsafe.Pointer, fromLen int, width uintptr) int { + if fromLen == 0 || toLen == 0 { return 0 } - n := fmLen + n := fromLen if toLen < n { n = toLen } @@ -257,46 +258,23 @@ func slicecopy(toPtr unsafe.Pointer, toLen int, fmPtr unsafe.Pointer, fmLen int, return n } + size := uintptr(n) * width if raceenabled { callerpc := getcallerpc() pc := funcPC(slicecopy) - racereadrangepc(fmPtr, uintptr(n*int(width)), callerpc, pc) - racewriterangepc(toPtr, uintptr(n*int(width)), callerpc, pc) + racereadrangepc(fromPtr, size, callerpc, pc) + racewriterangepc(toPtr, size, callerpc, pc) } if msanenabled { - msanread(fmPtr, uintptr(n*int(width))) - msanwrite(toPtr, uintptr(n*int(width))) + msanread(fromPtr, size) + msanwrite(toPtr, size) } - size := uintptr(n) * width if size == 1 { // common case worth about 2x to do here // TODO: is this still worth it with new memmove impl? - *(*byte)(toPtr) = *(*byte)(fmPtr) // known to be a byte pointer + *(*byte)(toPtr) = *(*byte)(fromPtr) // known to be a byte pointer } else { - memmove(toPtr, fmPtr, size) - } - return n -} - -func slicestringcopy(toPtr *byte, toLen int, fm string) int { - if len(fm) == 0 || toLen == 0 { - return 0 - } - - n := len(fm) - if toLen < n { - n = toLen + memmove(toPtr, fromPtr, size) } - - if raceenabled { - callerpc := getcallerpc() - pc := funcPC(slicestringcopy) - racewriterangepc(unsafe.Pointer(toPtr), uintptr(n), callerpc, pc) - } - if msanenabled { - msanwrite(unsafe.Pointer(toPtr), uintptr(n)) - } - - memmove(unsafe.Pointer(toPtr), stringStructOf(&fm).str, uintptr(n)) return n } -- cgit v1.3 From 4f915911e84819b69329a224d5b646983ac9fed7 Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Wed, 26 Aug 2020 14:07:35 -0700 Subject: cmd/compile: allow aliases to go:notinheap types The alias doesn't need to be marked go:notinheap. It gets its notinheap-ness from the target type. Without this change, the type alias test in the notinheap.go file generates these two errors: notinheap.go:62: misplaced compiler directive notinheap.go:63: type nih must be go:notinheap The first is a result of go:notinheap pragmas not applying to type alias declarations. The second is the result of then trying to match the notinheap-ness of the alias and the target type. Add a few more go:notinheap tests while we are here. Update #40954 Change-Id: I067ec47698df6e9e593e080d67796fd05a1d480f Reviewed-on: https://go-review.googlesource.com/c/go/+/250939 Run-TryBot: Keith Randall TryBot-Result: Go Bot Reviewed-by: Emmanuel Odeke Trust: Keith Randall --- src/cmd/compile/internal/gc/typecheck.go | 2 +- test/notinheap.go | 8 ++++++++ test/notinheap2.go | 10 +++++++--- 3 files changed, 16 insertions(+), 4 deletions(-) (limited to 'src/cmd/compile/internal') diff --git a/src/cmd/compile/internal/gc/typecheck.go b/src/cmd/compile/internal/gc/typecheck.go index fb169cfec8..9bb3c69cd0 100644 --- a/src/cmd/compile/internal/gc/typecheck.go +++ b/src/cmd/compile/internal/gc/typecheck.go @@ -2068,7 +2068,7 @@ func typecheck1(n *Node, top int) (res *Node) { ok |= ctxStmt n.Left = typecheck(n.Left, ctxType) checkwidth(n.Left.Type) - if n.Left.Type != nil && n.Left.Type.NotInHeap() && n.Left.Name.Param.Pragma&NotInHeap == 0 { + if n.Left.Type != nil && n.Left.Type.NotInHeap() && !n.Left.Name.Param.Alias && n.Left.Name.Param.Pragma&NotInHeap == 0 { // The type contains go:notinheap types, so it // must be marked as such (alternatively, we // could silently propagate go:notinheap). diff --git a/test/notinheap.go b/test/notinheap.go index 16c3f8faf0..a2284a5068 100644 --- a/test/notinheap.go +++ b/test/notinheap.go @@ -52,6 +52,14 @@ type t3 byte //go:notinheap type t4 rune +// Type aliases inherit the go:notinheap-ness of the type they alias. +type nihAlias = nih + +type embedAlias1 struct { // ERROR "must be go:notinheap" + x nihAlias +} +type embedAlias2 [1]nihAlias // ERROR "must be go:notinheap" + var sink interface{} func i() { diff --git a/test/notinheap2.go b/test/notinheap2.go index de1e6db1d3..09d0fc0b7b 100644 --- a/test/notinheap2.go +++ b/test/notinheap2.go @@ -27,14 +27,18 @@ func f() { // Heap allocation is not okay. var y *nih +var y2 *struct{ x nih } +var y3 *[1]nih var z []nih var w []nih var n int func g() { - y = new(nih) // ERROR "heap allocation disallowed" - z = make([]nih, 1) // ERROR "heap allocation disallowed" - z = append(z, x) // ERROR "heap allocation disallowed" + y = new(nih) // ERROR "heap allocation disallowed" + y2 = new(struct{ x nih }) // ERROR "heap allocation disallowed" + y3 = new([1]nih) // ERROR "heap allocation disallowed" + z = make([]nih, 1) // ERROR "heap allocation disallowed" + z = append(z, x) // ERROR "heap allocation disallowed" // Test for special case of OMAKESLICECOPY x := make([]nih, n) // ERROR "heap allocation disallowed" copy(x, z) -- cgit v1.3 From 37f261010f837f945eaa2d33d90cd822b4e93459 Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Thu, 27 Aug 2020 14:05:52 -0700 Subject: cmd/compile: make go:notinheap error message friendlier for cgo Update #40954 Change-Id: Ifaab7349631ccb12fc892882bbdf7f0ebf3d845f Reviewed-on: https://go-review.googlesource.com/c/go/+/251158 Run-TryBot: Keith Randall Reviewed-by: Ian Lance Taylor TryBot-Result: Go Bot Trust: Keith Randall --- src/cmd/compile/internal/gc/escape.go | 2 +- src/cmd/compile/internal/gc/subr.go | 4 ++-- src/cmd/compile/internal/gc/typecheck.go | 6 +++--- src/cmd/compile/internal/gc/walk.go | 8 ++++---- test/notinheap.go | 14 +++++++------- test/notinheap2.go | 14 +++++++------- 6 files changed, 24 insertions(+), 24 deletions(-) (limited to 'src/cmd/compile/internal') diff --git a/src/cmd/compile/internal/gc/escape.go b/src/cmd/compile/internal/gc/escape.go index 75da439bb7..f435d8ff6a 100644 --- a/src/cmd/compile/internal/gc/escape.go +++ b/src/cmd/compile/internal/gc/escape.go @@ -1030,7 +1030,7 @@ func (e *Escape) newLoc(n *Node, transient bool) *EscLocation { Fatalf("e.curfn isn't set") } if n != nil && n.Type != nil && n.Type.NotInHeap() { - yyerrorl(n.Pos, "%v is go:notinheap; stack allocation disallowed", n.Type) + yyerrorl(n.Pos, "%v is incomplete (or unallocatable); stack allocation disallowed", n.Type) } n = canonicalNode(n) diff --git a/src/cmd/compile/internal/gc/subr.go b/src/cmd/compile/internal/gc/subr.go index 8883e75c49..b5527e2f83 100644 --- a/src/cmd/compile/internal/gc/subr.go +++ b/src/cmd/compile/internal/gc/subr.go @@ -689,14 +689,14 @@ func convertop(srcConstant bool, src, dst *types.Type, why *string) Op { // (a) Disallow (*T) to (*U) where T is go:notinheap but U isn't. if src.IsPtr() && dst.IsPtr() && dst.Elem().NotInHeap() && !src.Elem().NotInHeap() { if why != nil { - *why = fmt.Sprintf(":\n\t%v is go:notinheap, but %v is not", dst.Elem(), src.Elem()) + *why = fmt.Sprintf(":\n\t%v is incomplete (or unallocatable), but %v is not", dst.Elem(), src.Elem()) } return OXXX } // (b) Disallow string to []T where T is go:notinheap. if src.IsString() && dst.IsSlice() && dst.Elem().NotInHeap() && (dst.Elem().Etype == types.Bytetype.Etype || dst.Elem().Etype == types.Runetype.Etype) { if why != nil { - *why = fmt.Sprintf(":\n\t%v is go:notinheap", dst.Elem()) + *why = fmt.Sprintf(":\n\t%v is incomplete (or unallocatable)", dst.Elem()) } return OXXX } diff --git a/src/cmd/compile/internal/gc/typecheck.go b/src/cmd/compile/internal/gc/typecheck.go index 9bb3c69cd0..8d777c399e 100644 --- a/src/cmd/compile/internal/gc/typecheck.go +++ b/src/cmd/compile/internal/gc/typecheck.go @@ -471,10 +471,10 @@ func typecheck1(n *Node, top int) (res *Node) { return n } if l.Type.NotInHeap() { - yyerror("go:notinheap map key not allowed") + yyerror("incomplete (or unallocatable) map key not allowed") } if r.Type.NotInHeap() { - yyerror("go:notinheap map value not allowed") + yyerror("incomplete (or unallocatable) map value not allowed") } setTypeNode(n, types.NewMap(l.Type, r.Type)) @@ -491,7 +491,7 @@ func typecheck1(n *Node, top int) (res *Node) { return n } if l.Type.NotInHeap() { - yyerror("chan of go:notinheap type not allowed") + yyerror("chan of incomplete (or unallocatable) type not allowed") } setTypeNode(n, types.NewChan(l.Type, n.TChanDir())) diff --git a/src/cmd/compile/internal/gc/walk.go b/src/cmd/compile/internal/gc/walk.go index c3a740d4cc..2db352c8d5 100644 --- a/src/cmd/compile/internal/gc/walk.go +++ b/src/cmd/compile/internal/gc/walk.go @@ -648,7 +648,7 @@ opswitch: // x = append(...) r := n.Right if r.Type.Elem().NotInHeap() { - yyerror("%v is go:notinheap; heap allocation disallowed", r.Type.Elem()) + yyerror("%v can't be allocated in Go; it is incomplete (or unallocatable)", r.Type.Elem()) } switch { case isAppendOfMake(r): @@ -1164,7 +1164,7 @@ opswitch: case ONEW: if n.Type.Elem().NotInHeap() { - yyerror("%v is go:notinheap; heap allocation disallowed", n.Type.Elem()) + yyerror("%v can't be allocated in Go; it is incomplete (or unallocatable)", n.Type.Elem()) } if n.Esc == EscNone { if n.Type.Elem().Width >= maxImplicitStackVarSize { @@ -1335,7 +1335,7 @@ opswitch: } t := n.Type if t.Elem().NotInHeap() { - yyerror("%v is go:notinheap; heap allocation disallowed", t.Elem()) + yyerror("%v can't be allocated in Go; it is incomplete (or unallocatable)", t.Elem()) } if n.Esc == EscNone { if !isSmallMakeSlice(n) { @@ -1412,7 +1412,7 @@ opswitch: t := n.Type if t.Elem().NotInHeap() { - yyerror("%v is go:notinheap; heap allocation disallowed", t.Elem()) + yyerror("%v can't be allocated in Go; it is incomplete (or unallocatable)", t.Elem()) } length := conv(n.Left, types.Types[TINT]) diff --git a/test/notinheap.go b/test/notinheap.go index a2284a5068..5dd4997a65 100644 --- a/test/notinheap.go +++ b/test/notinheap.go @@ -23,11 +23,11 @@ type embed3 struct { // ERROR "must be go:notinheap" x [1]nih } -type embed4 map[nih]int // ERROR "go:notinheap map key not allowed" +type embed4 map[nih]int // ERROR "incomplete \(or unallocatable\) map key not allowed" -type embed5 map[int]nih // ERROR "go:notinheap map value not allowed" +type embed5 map[int]nih // ERROR "incomplete \(or unallocatable\) map value not allowed" -type emebd6 chan nih // ERROR "chan of go:notinheap type not allowed" +type emebd6 chan nih // ERROR "chan of incomplete \(or unallocatable\) type not allowed" type okay1 *nih @@ -64,8 +64,8 @@ var sink interface{} func i() { sink = new(t1) // no error - sink = (*t2)(new(t1)) // ERROR "cannot convert(.|\n)*t2 is go:notinheap" - sink = (*t2)(new(struct{ x int })) // ERROR "cannot convert(.|\n)*t2 is go:notinheap" - sink = []t3("foo") // ERROR "cannot convert(.|\n)*t3 is go:notinheap" - sink = []t4("bar") // ERROR "cannot convert(.|\n)*t4 is go:notinheap" + sink = (*t2)(new(t1)) // ERROR "cannot convert(.|\n)*t2 is incomplete \(or unallocatable\)" + sink = (*t2)(new(struct{ x int })) // ERROR "cannot convert(.|\n)*t2 is incomplete \(or unallocatable\)" + sink = []t3("foo") // ERROR "cannot convert(.|\n)*t3 is incomplete \(or unallocatable\)" + sink = []t4("bar") // ERROR "cannot convert(.|\n)*t4 is incomplete \(or unallocatable\)" } diff --git a/test/notinheap2.go b/test/notinheap2.go index 09d0fc0b7b..23d4b0ae77 100644 --- a/test/notinheap2.go +++ b/test/notinheap2.go @@ -20,7 +20,7 @@ var x nih // Stack variables are not okay. func f() { - var y nih // ERROR "nih is go:notinheap; stack allocation disallowed" + var y nih // ERROR "nih is incomplete \(or unallocatable\); stack allocation disallowed" x = y } @@ -34,13 +34,13 @@ var w []nih var n int func g() { - y = new(nih) // ERROR "heap allocation disallowed" - y2 = new(struct{ x nih }) // ERROR "heap allocation disallowed" - y3 = new([1]nih) // ERROR "heap allocation disallowed" - z = make([]nih, 1) // ERROR "heap allocation disallowed" - z = append(z, x) // ERROR "heap allocation disallowed" + y = new(nih) // ERROR "can't be allocated in Go" + y2 = new(struct{ x nih }) // ERROR "can't be allocated in Go" + y3 = new([1]nih) // ERROR "can't be allocated in Go" + z = make([]nih, 1) // ERROR "can't be allocated in Go" + z = append(z, x) // ERROR "can't be allocated in Go" // Test for special case of OMAKESLICECOPY - x := make([]nih, n) // ERROR "heap allocation disallowed" + x := make([]nih, n) // ERROR "can't be allocated in Go" copy(x, z) z = x } -- cgit v1.3 From 7ee35cb301eddf4d53e7bb2d5bf0873922d63a6e Mon Sep 17 00:00:00 2001 From: Alberto Donizetti Date: Wed, 16 Sep 2020 13:13:50 +0200 Subject: cmd/compile: be more specific in cannot assign errors "cannot assign to" compiler errors are very laconic: they never explain why the lhs cannot be assigned to (with one exception, when assigning to a struct field in a map). This change makes them a little more specific, in two more cases: when assigning to a string, or to a const; by giving a very brief reason why the lhs cannot be assigned to. Change-Id: I244cca7fc3c3814e00e0ccadeec62f747c293979 Reviewed-on: https://go-review.googlesource.com/c/go/+/255199 Trust: Alberto Donizetti Run-TryBot: Alberto Donizetti TryBot-Result: Go Bot Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/gc/typecheck.go | 9 +++++++-- test/cannotassign.go | 33 ++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 2 deletions(-) create mode 100644 test/cannotassign.go (limited to 'src/cmd/compile/internal') diff --git a/src/cmd/compile/internal/gc/typecheck.go b/src/cmd/compile/internal/gc/typecheck.go index 8d777c399e..55773641ed 100644 --- a/src/cmd/compile/internal/gc/typecheck.go +++ b/src/cmd/compile/internal/gc/typecheck.go @@ -3135,9 +3135,14 @@ func checkassign(stmt *Node, n *Node) { return } - if n.Op == ODOT && n.Left.Op == OINDEXMAP { + switch { + case n.Op == ODOT && n.Left.Op == OINDEXMAP: yyerror("cannot assign to struct field %v in map", n) - } else { + case (n.Op == OINDEX && n.Left.Type.IsString()) || n.Op == OSLICESTR: + yyerror("cannot assign to %v (strings are immutable)", n) + case n.Op == OLITERAL && n.Sym != nil && n.isGoConst(): + yyerror("cannot assign to %v (declared const)", n) + default: yyerror("cannot assign to %v", n) } n.Type = nil diff --git a/test/cannotassign.go b/test/cannotassign.go new file mode 100644 index 0000000000..0de04ecad0 --- /dev/null +++ b/test/cannotassign.go @@ -0,0 +1,33 @@ +// errorcheck + +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Test "cannot assign" errors + +package main + +func main() { + var s string = "hello" + s[1:2] = "a" // ERROR "cannot assign to .* \(strings are immutable\)" + s[3] = "b" // ERROR "cannot assign to .* \(strings are immutable\)" + + const n int = 1 + const cs string = "hello" + n = 2 // ERROR "cannot assign to .* \(declared const\)" + cs = "hi" // ERROR "cannot assign to .* \(declared const\)" + true = false // ERROR "cannot assign to .* \(declared const\)" + + var m map[int]struct{ n int } + m[0].n = 7 // ERROR "cannot assign to struct field .* in map$" + + 1 = 7 // ERROR "cannot assign to 1$" + "hi" = 7 // ERROR `cannot assign to "hi"$` + nil = 7 // ERROR "cannot assign to nil$" + len("") = 7 // ERROR `cannot assign to len\(""\)$` + []int{} = nil // ERROR "cannot assign to \[\]int\{\}$" + + var x int = 7 + x + 1 = 7 // ERROR "cannot assign to x \+ 1$" +} -- cgit v1.3 From b4ef49e527787ec932d0b371bb24c3fc370b1e8d Mon Sep 17 00:00:00 2001 From: David Chase Date: Fri, 12 Jun 2020 13:48:26 -0400 Subject: cmd/compile: introduce special ssa Aux type for calls This is prerequisite to moving call expansion later into SSA, and probably a good idea anyway. Passes tests. This is the first minimal CL that does a 1-for-1 substitution of *ssa.AuxCall for *obj.LSym. Next step (next CL) is to make this change for all calls so that additional information can be stored in AuxCall. Change-Id: Ia3a7715648fd9fb1a176850767a726e6f5b959eb Reviewed-on: https://go-review.googlesource.com/c/go/+/237680 Trust: David Chase Run-TryBot: David Chase TryBot-Result: Go Bot Reviewed-by: Cherry Zhang --- src/cmd/compile/internal/gc/plive.go | 6 +-- src/cmd/compile/internal/gc/ssa.go | 40 ++++++++++------- src/cmd/compile/internal/ssa/check.go | 12 +++++ src/cmd/compile/internal/ssa/func_test.go | 7 +++ src/cmd/compile/internal/ssa/fuse_test.go | 4 +- src/cmd/compile/internal/ssa/gen/386Ops.go | 2 +- src/cmd/compile/internal/ssa/gen/AMD64Ops.go | 2 +- src/cmd/compile/internal/ssa/gen/ARM64Ops.go | 2 +- src/cmd/compile/internal/ssa/gen/ARMOps.go | 2 +- src/cmd/compile/internal/ssa/gen/MIPS64Ops.go | 2 +- src/cmd/compile/internal/ssa/gen/MIPSOps.go | 2 +- src/cmd/compile/internal/ssa/gen/PPC64Ops.go | 2 +- src/cmd/compile/internal/ssa/gen/RISCV64Ops.go | 6 +-- src/cmd/compile/internal/ssa/gen/S390XOps.go | 2 +- src/cmd/compile/internal/ssa/gen/WasmOps.go | 2 +- src/cmd/compile/internal/ssa/gen/generic.rules | 12 ++--- src/cmd/compile/internal/ssa/gen/genericOps.go | 6 +-- src/cmd/compile/internal/ssa/gen/rulegen.go | 10 ++++- src/cmd/compile/internal/ssa/loopreschedchecks.go | 2 +- src/cmd/compile/internal/ssa/op.go | 13 ++++++ src/cmd/compile/internal/ssa/opGen.go | 53 +++++++++-------------- src/cmd/compile/internal/ssa/regalloc_test.go | 12 ++--- src/cmd/compile/internal/ssa/rewrite.go | 33 +++++++------- src/cmd/compile/internal/ssa/rewritegeneric.go | 40 ++++++++--------- src/cmd/compile/internal/ssa/value.go | 4 +- src/cmd/compile/internal/ssa/writebarrier.go | 4 +- src/cmd/compile/internal/wasm/ssa.go | 5 ++- 27 files changed, 164 insertions(+), 123 deletions(-) (limited to 'src/cmd/compile/internal') diff --git a/src/cmd/compile/internal/gc/plive.go b/src/cmd/compile/internal/gc/plive.go index 8976ed657a..a9ea37701e 100644 --- a/src/cmd/compile/internal/gc/plive.go +++ b/src/cmd/compile/internal/gc/plive.go @@ -861,7 +861,7 @@ func (lv *Liveness) hasStackMap(v *ssa.Value) bool { // typedmemclr and typedmemmove are write barriers and // deeply non-preemptible. They are unsafe points and // hence should not have liveness maps. - if sym, _ := v.Aux.(*obj.LSym); sym == typedmemclr || sym == typedmemmove { + if sym, ok := v.Aux.(*ssa.AuxCall); ok && (sym.Fn == typedmemclr || sym.Fn == typedmemmove) { return false } return true @@ -1231,8 +1231,8 @@ func (lv *Liveness) showlive(v *ssa.Value, live bvec) { s := "live at " if v == nil { s += fmt.Sprintf("entry to %s:", lv.fn.funcname()) - } else if sym, ok := v.Aux.(*obj.LSym); ok { - fn := sym.Name + } else if sym, ok := v.Aux.(*ssa.AuxCall); ok && sym.Fn != nil { + fn := sym.Fn.Name if pos := strings.Index(fn, "."); pos >= 0 { fn = fn[pos+1:] } diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go index 3bdb5b0b9f..0ee31bd9a3 100644 --- a/src/cmd/compile/internal/gc/ssa.go +++ b/src/cmd/compile/internal/gc/ssa.go @@ -805,6 +805,11 @@ func (s *state) newValue2(op ssa.Op, t *types.Type, arg0, arg1 *ssa.Value) *ssa. return s.curBlock.NewValue2(s.peekPos(), op, t, arg0, arg1) } +// newValue2A adds a new value with two arguments and an aux value to the current block. +func (s *state) newValue2A(op ssa.Op, t *types.Type, aux interface{}, arg0, arg1 *ssa.Value) *ssa.Value { + return s.curBlock.NewValue2A(s.peekPos(), op, t, aux, arg0, arg1) +} + // newValue2Apos adds a new value with two arguments and an aux value to the current block. // isStmt determines whether the created values may be a statement or not // (i.e., false means never, yes means maybe). @@ -4297,10 +4302,10 @@ func (s *state) openDeferExit() { v := s.load(r.closure.Type.Elem(), r.closure) s.maybeNilCheckClosure(v, callDefer) codeptr := s.rawLoad(types.Types[TUINTPTR], v) - call = s.newValue3(ssa.OpClosureCall, types.TypeMem, codeptr, v, s.mem()) + call = s.newValue3A(ssa.OpClosureCall, types.TypeMem, nil, codeptr, v, s.mem()) } else { // Do a static call if the original call was a static function or method - call = s.newValue1A(ssa.OpStaticCall, types.TypeMem, fn.Sym.Linksym(), s.mem()) + call = s.newValue1A(ssa.OpStaticCall, types.TypeMem, &ssa.AuxCall{Fn: fn.Sym.Linksym()}, s.mem()) } call.AuxInt = stksize s.vars[&memVar] = call @@ -4432,7 +4437,7 @@ func (s *state) call(n *Node, k callKind) *ssa.Value { // Call runtime.deferprocStack with pointer to _defer record. arg0 := s.constOffPtrSP(types.Types[TUINTPTR], Ctxt.FixedFrameSize()) s.store(types.Types[TUINTPTR], arg0, addr) - call = s.newValue1A(ssa.OpStaticCall, types.TypeMem, deferprocStack, s.mem()) + call = s.newValue1A(ssa.OpStaticCall, types.TypeMem, &ssa.AuxCall{Fn: deferprocStack}, s.mem()) if stksize < int64(Widthptr) { // We need room for both the call to deferprocStack and the call to // the deferred function. @@ -4477,9 +4482,9 @@ func (s *state) call(n *Node, k callKind) *ssa.Value { // call target switch { case k == callDefer: - call = s.newValue1A(ssa.OpStaticCall, types.TypeMem, deferproc, s.mem()) + call = s.newValue1A(ssa.OpStaticCall, types.TypeMem, &ssa.AuxCall{Fn: deferproc}, s.mem()) case k == callGo: - call = s.newValue1A(ssa.OpStaticCall, types.TypeMem, newproc, s.mem()) + call = s.newValue1A(ssa.OpStaticCall, types.TypeMem, &ssa.AuxCall{Fn: newproc}, s.mem()) case closure != nil: // rawLoad because loading the code pointer from a // closure is always safe, but IsSanitizerSafeAddr @@ -4487,11 +4492,11 @@ func (s *state) call(n *Node, k callKind) *ssa.Value { // critical that we not clobber any arguments already // stored onto the stack. codeptr = s.rawLoad(types.Types[TUINTPTR], closure) - call = s.newValue3(ssa.OpClosureCall, types.TypeMem, codeptr, closure, s.mem()) + call = s.newValue3A(ssa.OpClosureCall, types.TypeMem, nil, codeptr, closure, s.mem()) case codeptr != nil: - call = s.newValue2(ssa.OpInterCall, types.TypeMem, codeptr, s.mem()) + call = s.newValue2A(ssa.OpInterCall, types.TypeMem, nil, codeptr, s.mem()) case sym != nil: - call = s.newValue1A(ssa.OpStaticCall, types.TypeMem, sym.Linksym(), s.mem()) + call = s.newValue1A(ssa.OpStaticCall, types.TypeMem, &ssa.AuxCall{Fn: sym.Linksym()}, s.mem()) default: s.Fatalf("bad call type %v %v", n.Op, n) } @@ -4924,7 +4929,7 @@ func (s *state) rtcall(fn *obj.LSym, returns bool, results []*types.Type, args . off = Rnd(off, int64(Widthreg)) // Issue call - call := s.newValue1A(ssa.OpStaticCall, types.TypeMem, fn, s.mem()) + call := s.newValue1A(ssa.OpStaticCall, types.TypeMem, &ssa.AuxCall{Fn: fn}, s.mem()) s.vars[&memVar] = call if !returns { @@ -6355,6 +6360,9 @@ func AddAux2(a *obj.Addr, v *ssa.Value, offset int64) { } // Add symbol's offset from its base register. switch n := v.Aux.(type) { + case *ssa.AuxCall: + a.Name = obj.NAME_EXTERN + a.Sym = n.Fn case *obj.LSym: a.Name = obj.NAME_EXTERN a.Sym = n @@ -6541,10 +6549,10 @@ func (s *SSAGenState) Call(v *ssa.Value) *obj.Prog { } else { p.Pos = v.Pos.WithNotStmt() } - if sym, ok := v.Aux.(*obj.LSym); ok { + if sym, ok := v.Aux.(*ssa.AuxCall); ok && sym.Fn != nil { p.To.Type = obj.TYPE_MEM p.To.Name = obj.NAME_EXTERN - p.To.Sym = sym + p.To.Sym = sym.Fn } else { // TODO(mdempsky): Can these differences be eliminated? switch thearch.LinkArch.Family { @@ -6567,12 +6575,14 @@ func (s *SSAGenState) PrepareCall(v *ssa.Value) { idx := s.livenessMap.Get(v) if !idx.StackMapValid() { // See Liveness.hasStackMap. - if sym, _ := v.Aux.(*obj.LSym); !(sym == typedmemclr || sym == typedmemmove) { + if sym, ok := v.Aux.(*ssa.AuxCall); !ok || !(sym.Fn == typedmemclr || sym.Fn == typedmemmove) { Fatalf("missing stack map index for %v", v.LongString()) } } - if sym, _ := v.Aux.(*obj.LSym); sym == Deferreturn { + call, ok := v.Aux.(*ssa.AuxCall) + + if ok && call.Fn == Deferreturn { // Deferred calls will appear to be returning to // the CALL deferreturn(SB) that we are about to emit. // However, the stack trace code will show the line @@ -6584,11 +6594,11 @@ func (s *SSAGenState) PrepareCall(v *ssa.Value) { thearch.Ginsnopdefer(s.pp) } - if sym, ok := v.Aux.(*obj.LSym); ok { + if ok { // Record call graph information for nowritebarrierrec // analysis. if nowritebarrierrecCheck != nil { - nowritebarrierrecCheck.recordCall(s.pp.curfn, sym, v.Pos) + nowritebarrierrecCheck.recordCall(s.pp.curfn, call.Fn, v.Pos) } } diff --git a/src/cmd/compile/internal/ssa/check.go b/src/cmd/compile/internal/ssa/check.go index 828f645b39..9ce87e0aea 100644 --- a/src/cmd/compile/internal/ssa/check.go +++ b/src/cmd/compile/internal/ssa/check.go @@ -165,6 +165,18 @@ func checkFunc(f *Func) { f.Fatalf("value %v has Aux type %T, want string", v, v.Aux) } canHaveAux = true + case auxCallOff: + canHaveAuxInt = true + fallthrough + case auxCall: + if ac, ok := v.Aux.(*AuxCall); ok { + if v.Op == OpStaticCall && ac.Fn == nil { + f.Fatalf("value %v has *AuxCall with nil Fn", v) + } + } else { + f.Fatalf("value %v has Aux type %T, want *AuxCall", v, v.Aux) + } + canHaveAux = true case auxSym, auxTyp: canHaveAux = true case auxSymOff, auxSymValAndOff, auxTypSize: diff --git a/src/cmd/compile/internal/ssa/func_test.go b/src/cmd/compile/internal/ssa/func_test.go index 5f6f80f72a..568c6436f5 100644 --- a/src/cmd/compile/internal/ssa/func_test.go +++ b/src/cmd/compile/internal/ssa/func_test.go @@ -38,6 +38,7 @@ package ssa import ( "cmd/compile/internal/types" + "cmd/internal/obj" "cmd/internal/src" "fmt" "reflect" @@ -140,6 +141,12 @@ var emptyPass pass = pass{ name: "empty pass", } +// AuxCallLSym returns an AuxCall initialized with an LSym that should pass "check" +// as the Aux of a static call. +func AuxCallLSym(name string) *AuxCall { + return &AuxCall{Fn: &obj.LSym{}} +} + // Fun takes the name of an entry bloc and a series of Bloc calls, and // returns a fun containing the composed Func. entry must be a name // supplied to one of the Bloc functions. Each of the bloc names and diff --git a/src/cmd/compile/internal/ssa/fuse_test.go b/src/cmd/compile/internal/ssa/fuse_test.go index 5fe3da93ca..15190997f2 100644 --- a/src/cmd/compile/internal/ssa/fuse_test.go +++ b/src/cmd/compile/internal/ssa/fuse_test.go @@ -142,10 +142,10 @@ func TestFuseSideEffects(t *testing.T) { Valu("b", OpArg, c.config.Types.Bool, 0, nil), If("b", "then", "else")), Bloc("then", - Valu("call1", OpStaticCall, types.TypeMem, 0, nil, "mem"), + Valu("call1", OpStaticCall, types.TypeMem, 0, AuxCallLSym("_"), "mem"), Goto("empty")), Bloc("else", - Valu("call2", OpStaticCall, types.TypeMem, 0, nil, "mem"), + Valu("call2", OpStaticCall, types.TypeMem, 0, AuxCallLSym("_"), "mem"), Goto("empty")), Bloc("empty", Goto("loop")), diff --git a/src/cmd/compile/internal/ssa/gen/386Ops.go b/src/cmd/compile/internal/ssa/gen/386Ops.go index 1061e5579d..64a17cb7a3 100644 --- a/src/cmd/compile/internal/ssa/gen/386Ops.go +++ b/src/cmd/compile/internal/ssa/gen/386Ops.go @@ -463,7 +463,7 @@ func init() { faultOnNilArg0: true, }, - {name: "CALLstatic", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "SymOff", clobberFlags: true, call: true, symEffect: "None"}, // call static function aux.(*obj.LSym). arg0=mem, auxint=argsize, returns mem + {name: "CALLstatic", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call static function aux.(*obj.LSym). arg0=mem, auxint=argsize, returns mem {name: "CALLclosure", argLength: 3, reg: regInfo{inputs: []regMask{gpsp, buildReg("DX"), 0}, clobbers: callerSave}, aux: "Int64", clobberFlags: true, call: true}, // call function via closure. arg0=codeptr, arg1=closure, arg2=mem, auxint=argsize, returns mem {name: "CALLinter", argLength: 2, reg: regInfo{inputs: []regMask{gp}, clobbers: callerSave}, aux: "Int64", clobberFlags: true, call: true}, // call fn by pointer. arg0=codeptr, arg1=mem, auxint=argsize, returns mem diff --git a/src/cmd/compile/internal/ssa/gen/AMD64Ops.go b/src/cmd/compile/internal/ssa/gen/AMD64Ops.go index e6d66957dd..d267fe8753 100644 --- a/src/cmd/compile/internal/ssa/gen/AMD64Ops.go +++ b/src/cmd/compile/internal/ssa/gen/AMD64Ops.go @@ -767,7 +767,7 @@ func init() { faultOnNilArg0: true, }, - {name: "CALLstatic", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "SymOff", clobberFlags: true, call: true, symEffect: "None"}, // call static function aux.(*obj.LSym). arg0=mem, auxint=argsize, returns mem + {name: "CALLstatic", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call static function aux.(*obj.LSym). arg0=mem, auxint=argsize, returns mem {name: "CALLclosure", argLength: 3, reg: regInfo{inputs: []regMask{gpsp, buildReg("DX"), 0}, clobbers: callerSave}, aux: "Int64", clobberFlags: true, call: true}, // call function via closure. arg0=codeptr, arg1=closure, arg2=mem, auxint=argsize, returns mem {name: "CALLinter", argLength: 2, reg: regInfo{inputs: []regMask{gp}, clobbers: callerSave}, aux: "Int64", clobberFlags: true, call: true}, // call fn by pointer. arg0=codeptr, arg1=mem, auxint=argsize, returns mem diff --git a/src/cmd/compile/internal/ssa/gen/ARM64Ops.go b/src/cmd/compile/internal/ssa/gen/ARM64Ops.go index e9af261a6a..f52d68dc33 100644 --- a/src/cmd/compile/internal/ssa/gen/ARM64Ops.go +++ b/src/cmd/compile/internal/ssa/gen/ARM64Ops.go @@ -471,7 +471,7 @@ func init() { {name: "CSEL0", argLength: 2, reg: gp1flags1, asm: "CSEL", aux: "CCop"}, // auxint(flags) ? arg0 : 0 // function calls - {name: "CALLstatic", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "SymOff", clobberFlags: true, call: true, symEffect: "None"}, // call static function aux.(*obj.LSym). arg0=mem, auxint=argsize, returns mem + {name: "CALLstatic", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call static function aux.(*obj.LSym). arg0=mem, auxint=argsize, returns mem {name: "CALLclosure", argLength: 3, reg: regInfo{inputs: []regMask{gpsp, buildReg("R26"), 0}, clobbers: callerSave}, aux: "Int64", clobberFlags: true, call: true}, // call function via closure. arg0=codeptr, arg1=closure, arg2=mem, auxint=argsize, returns mem {name: "CALLinter", argLength: 2, reg: regInfo{inputs: []regMask{gp}, clobbers: callerSave}, aux: "Int64", clobberFlags: true, call: true}, // call fn by pointer. arg0=codeptr, arg1=mem, auxint=argsize, returns mem diff --git a/src/cmd/compile/internal/ssa/gen/ARMOps.go b/src/cmd/compile/internal/ssa/gen/ARMOps.go index 068fecf74c..1e6b4546da 100644 --- a/src/cmd/compile/internal/ssa/gen/ARMOps.go +++ b/src/cmd/compile/internal/ssa/gen/ARMOps.go @@ -428,7 +428,7 @@ func init() { {name: "SRAcond", argLength: 3, reg: gp2flags1, asm: "SRA"}, // arg0 >> 31 if flags indicates HS, arg0 >> arg1 otherwise, signed shift, arg2=flags // function calls - {name: "CALLstatic", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "SymOff", clobberFlags: true, call: true, symEffect: "None"}, // call static function aux.(*obj.LSym). arg0=mem, auxint=argsize, returns mem + {name: "CALLstatic", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call static function aux.(*obj.LSym). arg0=mem, auxint=argsize, returns mem {name: "CALLclosure", argLength: 3, reg: regInfo{inputs: []regMask{gpsp, buildReg("R7"), 0}, clobbers: callerSave}, aux: "Int64", clobberFlags: true, call: true}, // call function via closure. arg0=codeptr, arg1=closure, arg2=mem, auxint=argsize, returns mem {name: "CALLinter", argLength: 2, reg: regInfo{inputs: []regMask{gp}, clobbers: callerSave}, aux: "Int64", clobberFlags: true, call: true}, // call fn by pointer. arg0=codeptr, arg1=mem, auxint=argsize, returns mem diff --git a/src/cmd/compile/internal/ssa/gen/MIPS64Ops.go b/src/cmd/compile/internal/ssa/gen/MIPS64Ops.go index 5f00c080af..dc2e9d3ec9 100644 --- a/src/cmd/compile/internal/ssa/gen/MIPS64Ops.go +++ b/src/cmd/compile/internal/ssa/gen/MIPS64Ops.go @@ -273,7 +273,7 @@ func init() { {name: "MOVDF", argLength: 1, reg: fp11, asm: "MOVDF"}, // float64 -> float32 // function calls - {name: "CALLstatic", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "SymOff", clobberFlags: true, call: true, symEffect: "None"}, // call static function aux.(*obj.LSym). arg0=mem, auxint=argsize, returns mem + {name: "CALLstatic", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call static function aux.(*obj.LSym). arg0=mem, auxint=argsize, returns mem {name: "CALLclosure", argLength: 3, reg: regInfo{inputs: []regMask{gpsp, buildReg("R22"), 0}, clobbers: callerSave}, aux: "Int64", clobberFlags: true, call: true}, // call function via closure. arg0=codeptr, arg1=closure, arg2=mem, auxint=argsize, returns mem {name: "CALLinter", argLength: 2, reg: regInfo{inputs: []regMask{gp}, clobbers: callerSave}, aux: "Int64", clobberFlags: true, call: true}, // call fn by pointer. arg0=codeptr, arg1=mem, auxint=argsize, returns mem diff --git a/src/cmd/compile/internal/ssa/gen/MIPSOps.go b/src/cmd/compile/internal/ssa/gen/MIPSOps.go index a5f6c8df54..c66adcf93a 100644 --- a/src/cmd/compile/internal/ssa/gen/MIPSOps.go +++ b/src/cmd/compile/internal/ssa/gen/MIPSOps.go @@ -255,7 +255,7 @@ func init() { {name: "MOVDF", argLength: 1, reg: fp11, asm: "MOVDF"}, // float64 -> float32 // function calls - {name: "CALLstatic", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "SymOff", clobberFlags: true, call: true, symEffect: "None"}, // call static function aux.(*obj.LSym). arg0=mem, auxint=argsize, returns mem + {name: "CALLstatic", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call static function aux.(*obj.LSym). arg0=mem, auxint=argsize, returns mem {name: "CALLclosure", argLength: 3, reg: regInfo{inputs: []regMask{gpsp, buildReg("R22"), 0}, clobbers: callerSave}, aux: "Int64", clobberFlags: true, call: true}, // call function via closure. arg0=codeptr, arg1=closure, arg2=mem, auxint=argsize, returns mem {name: "CALLinter", argLength: 2, reg: regInfo{inputs: []regMask{gp}, clobbers: callerSave}, aux: "Int64", clobberFlags: true, call: true}, // call fn by pointer. arg0=codeptr, arg1=mem, auxint=argsize, returns mem diff --git a/src/cmd/compile/internal/ssa/gen/PPC64Ops.go b/src/cmd/compile/internal/ssa/gen/PPC64Ops.go index 44f6a74c63..0c04e561ad 100644 --- a/src/cmd/compile/internal/ssa/gen/PPC64Ops.go +++ b/src/cmd/compile/internal/ssa/gen/PPC64Ops.go @@ -414,7 +414,7 @@ func init() { {name: "LoweredRound32F", argLength: 1, reg: fp11, resultInArg0: true, zeroWidth: true}, {name: "LoweredRound64F", argLength: 1, reg: fp11, resultInArg0: true, zeroWidth: true}, - {name: "CALLstatic", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "SymOff", clobberFlags: true, call: true, symEffect: "None"}, // call static function aux.(*obj.LSym). arg0=mem, auxint=argsize, returns mem + {name: "CALLstatic", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call static function aux.(*obj.LSym). arg0=mem, auxint=argsize, returns mem {name: "CALLclosure", argLength: 3, reg: regInfo{inputs: []regMask{callptr, ctxt, 0}, clobbers: callerSave}, aux: "Int64", clobberFlags: true, call: true}, // call function via closure. arg0=codeptr, arg1=closure, arg2=mem, auxint=argsize, returns mem {name: "CALLinter", argLength: 2, reg: regInfo{inputs: []regMask{callptr}, clobbers: callerSave}, aux: "Int64", clobberFlags: true, call: true}, // call fn by pointer. arg0=codeptr, arg1=mem, auxint=argsize, returns mem diff --git a/src/cmd/compile/internal/ssa/gen/RISCV64Ops.go b/src/cmd/compile/internal/ssa/gen/RISCV64Ops.go index 8ab4abe04a..17970918e2 100644 --- a/src/cmd/compile/internal/ssa/gen/RISCV64Ops.go +++ b/src/cmd/compile/internal/ssa/gen/RISCV64Ops.go @@ -224,9 +224,9 @@ func init() { {name: "MOVconvert", argLength: 2, reg: gp11, asm: "MOV"}, // arg0, but converted to int/ptr as appropriate; arg1=mem // Calls - {name: "CALLstatic", argLength: 1, reg: call, aux: "SymOff", call: true, symEffect: "None"}, // call static function aux.(*gc.Sym). arg0=mem, auxint=argsize, returns mem - {name: "CALLclosure", argLength: 3, reg: callClosure, aux: "Int64", call: true}, // call function via closure. arg0=codeptr, arg1=closure, arg2=mem, auxint=argsize, returns mem - {name: "CALLinter", argLength: 2, reg: callInter, aux: "Int64", call: true}, // call fn by pointer. arg0=codeptr, arg1=mem, auxint=argsize, returns mem + {name: "CALLstatic", argLength: 1, reg: call, aux: "CallOff", call: true}, // call static function aux.(*gc.Sym). arg0=mem, auxint=argsize, returns mem + {name: "CALLclosure", argLength: 3, reg: callClosure, aux: "Int64", call: true}, // call function via closure. arg0=codeptr, arg1=closure, arg2=mem, auxint=argsize, returns mem + {name: "CALLinter", argLength: 2, reg: callInter, aux: "Int64", call: true}, // call fn by pointer. arg0=codeptr, arg1=mem, auxint=argsize, returns mem // Generic moves and zeros diff --git a/src/cmd/compile/internal/ssa/gen/S390XOps.go b/src/cmd/compile/internal/ssa/gen/S390XOps.go index 710beaddbb..eede8a654b 100644 --- a/src/cmd/compile/internal/ssa/gen/S390XOps.go +++ b/src/cmd/compile/internal/ssa/gen/S390XOps.go @@ -475,7 +475,7 @@ func init() { {name: "CLEAR", argLength: 2, reg: regInfo{inputs: []regMask{ptr, 0}}, asm: "CLEAR", aux: "SymValAndOff", typ: "Mem", clobberFlags: true, faultOnNilArg0: true, symEffect: "Write"}, - {name: "CALLstatic", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "SymOff", clobberFlags: true, call: true, symEffect: "None"}, // call static function aux.(*obj.LSym). arg0=mem, auxint=argsize, returns mem + {name: "CALLstatic", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call static function aux.(*obj.LSym). arg0=mem, auxint=argsize, returns mem {name: "CALLclosure", argLength: 3, reg: regInfo{inputs: []regMask{ptrsp, buildReg("R12"), 0}, clobbers: callerSave}, aux: "Int64", clobberFlags: true, call: true}, // call function via closure. arg0=codeptr, arg1=closure, arg2=mem, auxint=argsize, returns mem {name: "CALLinter", argLength: 2, reg: regInfo{inputs: []regMask{ptr}, clobbers: callerSave}, aux: "Int64", clobberFlags: true, call: true}, // call fn by pointer. arg0=codeptr, arg1=mem, auxint=argsize, returns mem diff --git a/src/cmd/compile/internal/ssa/gen/WasmOps.go b/src/cmd/compile/internal/ssa/gen/WasmOps.go index e43eae17e9..3286a68fb0 100644 --- a/src/cmd/compile/internal/ssa/gen/WasmOps.go +++ b/src/cmd/compile/internal/ssa/gen/WasmOps.go @@ -122,7 +122,7 @@ func init() { ) var WasmOps = []opData{ - {name: "LoweredStaticCall", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "SymOff", call: true, symEffect: "None"}, // call static function aux.(*obj.LSym). arg0=mem, auxint=argsize, returns mem + {name: "LoweredStaticCall", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "CallOff", call: true}, // call static function aux.(*obj.LSym). arg0=mem, auxint=argsize, returns mem {name: "LoweredClosureCall", argLength: 3, reg: regInfo{inputs: []regMask{gp, gp, 0}, clobbers: callerSave}, aux: "Int64", call: true}, // call function via closure. arg0=codeptr, arg1=closure, arg2=mem, auxint=argsize, returns mem {name: "LoweredInterCall", argLength: 2, reg: regInfo{inputs: []regMask{gp}, clobbers: callerSave}, aux: "Int64", call: true}, // call fn by pointer. arg0=codeptr, arg1=mem, auxint=argsize, returns mem diff --git a/src/cmd/compile/internal/ssa/gen/generic.rules b/src/cmd/compile/internal/ssa/gen/generic.rules index f7e6bbebac..df70838aa9 100644 --- a/src/cmd/compile/internal/ssa/gen/generic.rules +++ b/src/cmd/compile/internal/ssa/gen/generic.rules @@ -1933,30 +1933,30 @@ // recognize runtime.newobject and don't Zero/Nilcheck it (Zero (Load (OffPtr [c] (SP)) mem) mem) && mem.Op == OpStaticCall - && isSameSym(mem.Aux, "runtime.newobject") + && isSameCall(mem.Aux, "runtime.newobject") && c == config.ctxt.FixedFrameSize() + config.RegSize // offset of return value => mem (Store (Load (OffPtr [c] (SP)) mem) x mem) && isConstZero(x) && mem.Op == OpStaticCall - && isSameSym(mem.Aux, "runtime.newobject") + && isSameCall(mem.Aux, "runtime.newobject") && c == config.ctxt.FixedFrameSize() + config.RegSize // offset of return value => mem (Store (OffPtr (Load (OffPtr [c] (SP)) mem)) x mem) && isConstZero(x) && mem.Op == OpStaticCall - && isSameSym(mem.Aux, "runtime.newobject") + && isSameCall(mem.Aux, "runtime.newobject") && c == config.ctxt.FixedFrameSize() + config.RegSize // offset of return value => mem // nil checks just need to rewrite to something useless. // they will be deadcode eliminated soon afterwards. (NilCheck (Load (OffPtr [c] (SP)) (StaticCall {sym} _)) _) - && symNamed(sym, "runtime.newobject") + && isSameCall(sym, "runtime.newobject") && c == config.ctxt.FixedFrameSize() + config.RegSize // offset of return value && warnRule(fe.Debug_checknil(), v, "removed nil check") => (Invalid) (NilCheck (OffPtr (Load (OffPtr [c] (SP)) (StaticCall {sym} _))) _) - && symNamed(sym, "runtime.newobject") + && isSameCall(sym, "runtime.newobject") && c == config.ctxt.FixedFrameSize() + config.RegSize // offset of return value && warnRule(fe.Debug_checknil(), v, "removed nil check") => (Invalid) @@ -2010,7 +2010,7 @@ // See the comment in op Move in genericOps.go for discussion of the type. (StaticCall {sym} s1:(Store _ (Const(64|32) [sz]) s2:(Store _ src s3:(Store {t} _ dst mem)))) && sz >= 0 - && symNamed(sym, "runtime.memmove") + && isSameCall(sym, "runtime.memmove") && t.IsPtr() // avoids TUINTPTR, see issue 30061 && s1.Uses == 1 && s2.Uses == 1 && s3.Uses == 1 && isInlinableMemmove(dst, src, int64(sz), config) diff --git a/src/cmd/compile/internal/ssa/gen/genericOps.go b/src/cmd/compile/internal/ssa/gen/genericOps.go index 5df0a164bf..acfe222089 100644 --- a/src/cmd/compile/internal/ssa/gen/genericOps.go +++ b/src/cmd/compile/internal/ssa/gen/genericOps.go @@ -387,9 +387,9 @@ var genericOps = []opData{ // as a phantom first argument. // TODO(josharian): ClosureCall and InterCall should have Int32 aux // to match StaticCall's 32 bit arg size limit. - {name: "ClosureCall", argLength: 3, aux: "Int64", call: true}, // arg0=code pointer, arg1=context ptr, arg2=memory. auxint=arg size. Returns memory. - {name: "StaticCall", argLength: 1, aux: "SymOff", call: true, symEffect: "None"}, // call function aux.(*obj.LSym), arg0=memory. auxint=arg size. Returns memory. - {name: "InterCall", argLength: 2, aux: "Int64", call: true}, // interface call. arg0=code pointer, arg1=memory, auxint=arg size. Returns memory. + {name: "ClosureCall", argLength: 3, aux: "Int64", call: true}, // arg0=code pointer, arg1=context ptr, arg2=memory. auxint=arg size. Returns memory. + {name: "StaticCall", argLength: 1, aux: "CallOff", call: true}, // call function aux.(*obj.LSym), arg0=memory. auxint=arg size. Returns memory. + {name: "InterCall", argLength: 2, aux: "Int64", call: true}, // interface call. arg0=code pointer, arg1=memory, auxint=arg size. Returns memory. // Conversions: signed extensions, zero (unsigned) extensions, truncations {name: "SignExt8to16", argLength: 1, typ: "Int16"}, diff --git a/src/cmd/compile/internal/ssa/gen/rulegen.go b/src/cmd/compile/internal/ssa/gen/rulegen.go index 9e2e112cd7..be51a7c5f8 100644 --- a/src/cmd/compile/internal/ssa/gen/rulegen.go +++ b/src/cmd/compile/internal/ssa/gen/rulegen.go @@ -1424,7 +1424,7 @@ func parseValue(val string, arch arch, loc string) (op opData, oparch, typ, auxi func opHasAuxInt(op opData) bool { switch op.aux { case "Bool", "Int8", "Int16", "Int32", "Int64", "Int128", "Float32", "Float64", - "SymOff", "SymValAndOff", "TypSize", "ARM64BitField", "FlagConstant", "CCop": + "SymOff", "CallOff", "SymValAndOff", "TypSize", "ARM64BitField", "FlagConstant", "CCop": return true } return false @@ -1432,7 +1432,7 @@ func opHasAuxInt(op opData) bool { func opHasAux(op opData) bool { switch op.aux { - case "String", "Sym", "SymOff", "SymValAndOff", "Typ", "TypSize", + case "String", "Sym", "SymOff", "Call", "CallOff", "SymValAndOff", "Typ", "TypSize", "S390XCCMask", "S390XRotateParams": return true } @@ -1775,6 +1775,10 @@ func (op opData) auxType() string { return "Sym" case "SymOff": return "Sym" + case "Call": + return "Call" + case "CallOff": + return "Call" case "SymValAndOff": return "Sym" case "Typ": @@ -1809,6 +1813,8 @@ func (op opData) auxIntType() string { return "float32" case "Float64": return "float64" + case "CallOff": + return "int32" case "SymOff": return "int32" case "SymValAndOff": diff --git a/src/cmd/compile/internal/ssa/loopreschedchecks.go b/src/cmd/compile/internal/ssa/loopreschedchecks.go index 1932f9d23a..4a720fdede 100644 --- a/src/cmd/compile/internal/ssa/loopreschedchecks.go +++ b/src/cmd/compile/internal/ssa/loopreschedchecks.go @@ -246,7 +246,7 @@ func insertLoopReschedChecks(f *Func) { // mem1 := call resched (mem0) // goto header resched := f.fe.Syslook("goschedguarded") - mem1 := sched.NewValue1A(bb.Pos, OpStaticCall, types.TypeMem, resched, mem0) + mem1 := sched.NewValue1A(bb.Pos, OpStaticCall, types.TypeMem, &AuxCall{resched}, mem0) sched.AddEdgeTo(h) headerMemPhi.AddArg(mem1) diff --git a/src/cmd/compile/internal/ssa/op.go b/src/cmd/compile/internal/ssa/op.go index 063998c6a1..3aa506e3ab 100644 --- a/src/cmd/compile/internal/ssa/op.go +++ b/src/cmd/compile/internal/ssa/op.go @@ -67,6 +67,17 @@ type regInfo struct { type auxType int8 +type AuxCall struct { + Fn *obj.LSym +} + +func (a *AuxCall) String() string { + if a.Fn == nil { + return "AuxCall(nil)" + } + return fmt.Sprintf("AuxCall(%v)", a.Fn) +} + const ( auxNone auxType = iota auxBool // auxInt is 0/1 for false/true @@ -85,6 +96,8 @@ const ( auxTyp // aux is a type auxTypSize // aux is a type, auxInt is a size, must have Aux.(Type).Size() == AuxInt auxCCop // aux is a ssa.Op that represents a flags-to-bool conversion (e.g. LessThan) + auxCall // aux is a *ssa.AuxCall + auxCallOff // aux is a *ssa.AuxCall, AuxInt is int64 param (in+out) size // architecture specific aux types auxARM64BitField // aux is an arm64 bitfield lsb and width packed into auxInt diff --git a/src/cmd/compile/internal/ssa/opGen.go b/src/cmd/compile/internal/ssa/opGen.go index 45401898c8..797d82f2d1 100644 --- a/src/cmd/compile/internal/ssa/opGen.go +++ b/src/cmd/compile/internal/ssa/opGen.go @@ -5816,11 +5816,10 @@ var opcodeTable = [...]opInfo{ }, { name: "CALLstatic", - auxType: auxSymOff, + auxType: auxCallOff, argLen: 1, clobberFlags: true, call: true, - symEffect: SymNone, reg: regInfo{ clobbers: 65519, // AX CX DX BX BP SI DI X0 X1 X2 X3 X4 X5 X6 X7 }, @@ -13152,11 +13151,10 @@ var opcodeTable = [...]opInfo{ }, { name: "CALLstatic", - auxType: auxSymOff, + auxType: auxCallOff, argLen: 1, clobberFlags: true, call: true, - symEffect: SymNone, reg: regInfo{ clobbers: 4294967279, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 }, @@ -16922,11 +16920,10 @@ var opcodeTable = [...]opInfo{ }, { name: "CALLstatic", - auxType: auxSymOff, + auxType: auxCallOff, argLen: 1, clobberFlags: true, call: true, - symEffect: SymNone, reg: regInfo{ clobbers: 4294924287, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14 F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 }, @@ -20556,11 +20553,10 @@ var opcodeTable = [...]opInfo{ }, { name: "CALLstatic", - auxType: auxSymOff, + auxType: auxCallOff, argLen: 1, clobberFlags: true, call: true, - symEffect: SymNone, reg: regInfo{ clobbers: 9223372035512336383, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 }, @@ -22257,11 +22253,10 @@ var opcodeTable = [...]opInfo{ }, { name: "CALLstatic", - auxType: auxSymOff, + auxType: auxCallOff, argLen: 1, clobberFlags: true, call: true, - symEffect: SymNone, reg: regInfo{ clobbers: 140737421246462, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 g R31 F0 F2 F4 F6 F8 F10 F12 F14 F16 F18 F20 F22 F24 F26 F28 F30 HI LO }, @@ -23804,11 +23799,10 @@ var opcodeTable = [...]opInfo{ }, { name: "CALLstatic", - auxType: auxSymOff, + auxType: auxCallOff, argLen: 1, clobberFlags: true, call: true, - symEffect: SymNone, reg: regInfo{ clobbers: 4611686018393833470, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 g R31 F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 HI LO }, @@ -26504,11 +26498,10 @@ var opcodeTable = [...]opInfo{ }, { name: "CALLstatic", - auxType: auxSymOff, + auxType: auxCallOff, argLen: 1, clobberFlags: true, call: true, - symEffect: SymNone, reg: regInfo{ clobbers: 576460745860964344, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29 g F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 }, @@ -27787,11 +27780,10 @@ var opcodeTable = [...]opInfo{ }, }, { - name: "CALLstatic", - auxType: auxSymOff, - argLen: 1, - call: true, - symEffect: SymNone, + name: "CALLstatic", + auxType: auxCallOff, + argLen: 1, + call: true, reg: regInfo{ clobbers: 9223372035781033980, // X3 g X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 }, @@ -31386,11 +31378,10 @@ var opcodeTable = [...]opInfo{ }, { name: "CALLstatic", - auxType: auxSymOff, + auxType: auxCallOff, argLen: 1, clobberFlags: true, call: true, - symEffect: SymNone, reg: regInfo{ clobbers: 4294933503, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 g R14 F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 }, @@ -32031,11 +32022,10 @@ var opcodeTable = [...]opInfo{ }, { - name: "LoweredStaticCall", - auxType: auxSymOff, - argLen: 1, - call: true, - symEffect: SymNone, + name: "LoweredStaticCall", + auxType: auxCallOff, + argLen: 1, + call: true, reg: regInfo{ clobbers: 844424930131967, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 g }, @@ -34779,12 +34769,11 @@ var opcodeTable = [...]opInfo{ generic: true, }, { - name: "StaticCall", - auxType: auxSymOff, - argLen: 1, - call: true, - symEffect: SymNone, - generic: true, + name: "StaticCall", + auxType: auxCallOff, + argLen: 1, + call: true, + generic: true, }, { name: "InterCall", diff --git a/src/cmd/compile/internal/ssa/regalloc_test.go b/src/cmd/compile/internal/ssa/regalloc_test.go index bb8be5e7ac..d990cac47b 100644 --- a/src/cmd/compile/internal/ssa/regalloc_test.go +++ b/src/cmd/compile/internal/ssa/regalloc_test.go @@ -68,7 +68,7 @@ func TestNoGetgLoadReg(t *testing.T) { Exit("v16"), ), Bloc("b2", - Valu("v12", OpARM64CALLstatic, types.TypeMem, 0, nil, "v1"), + Valu("v12", OpARM64CALLstatic, types.TypeMem, 0, AuxCallLSym("_"), "v1"), Goto("b3"), ), ) @@ -99,7 +99,7 @@ func TestSpillWithLoop(t *testing.T) { ), Bloc("loop", Valu("memphi", OpPhi, types.TypeMem, 0, nil, "mem", "call"), - Valu("call", OpAMD64CALLstatic, types.TypeMem, 0, nil, "memphi"), + Valu("call", OpAMD64CALLstatic, types.TypeMem, 0, AuxCallLSym("_"), "memphi"), Valu("test", OpAMD64CMPBconst, types.TypeFlags, 0, nil, "cond"), Eq("test", "next", "exit"), ), @@ -140,12 +140,12 @@ func TestSpillMove1(t *testing.T) { Bloc("exit1", // store before call, y is available in a register Valu("mem2", OpAMD64MOVQstore, types.TypeMem, 0, nil, "p", "y", "mem"), - Valu("mem3", OpAMD64CALLstatic, types.TypeMem, 0, nil, "mem2"), + Valu("mem3", OpAMD64CALLstatic, types.TypeMem, 0, AuxCallLSym("_"), "mem2"), Exit("mem3"), ), Bloc("exit2", // store after call, y must be loaded from a spill location - Valu("mem4", OpAMD64CALLstatic, types.TypeMem, 0, nil, "mem"), + Valu("mem4", OpAMD64CALLstatic, types.TypeMem, 0, AuxCallLSym("_"), "mem"), Valu("mem5", OpAMD64MOVQstore, types.TypeMem, 0, nil, "p", "y", "mem4"), Exit("mem5"), ), @@ -188,13 +188,13 @@ func TestSpillMove2(t *testing.T) { ), Bloc("exit1", // store after call, y must be loaded from a spill location - Valu("mem2", OpAMD64CALLstatic, types.TypeMem, 0, nil, "mem"), + Valu("mem2", OpAMD64CALLstatic, types.TypeMem, 0, AuxCallLSym("_"), "mem"), Valu("mem3", OpAMD64MOVQstore, types.TypeMem, 0, nil, "p", "y", "mem2"), Exit("mem3"), ), Bloc("exit2", // store after call, y must be loaded from a spill location - Valu("mem4", OpAMD64CALLstatic, types.TypeMem, 0, nil, "mem"), + Valu("mem4", OpAMD64CALLstatic, types.TypeMem, 0, AuxCallLSym("_"), "mem"), Valu("mem5", OpAMD64MOVQstore, types.TypeMem, 0, nil, "p", "y", "mem4"), Exit("mem5"), ), diff --git a/src/cmd/compile/internal/ssa/rewrite.go b/src/cmd/compile/internal/ssa/rewrite.go index 09f94ef53e..8195d407e0 100644 --- a/src/cmd/compile/internal/ssa/rewrite.go +++ b/src/cmd/compile/internal/ssa/rewrite.go @@ -393,15 +393,9 @@ func canMergeLoad(target, load *Value) bool { return true } -// symNamed reports whether sym's name is name. -func symNamed(sym Sym, name string) bool { - return sym.String() == name -} - -// isSameSym reports whether sym is the same as the given named symbol -func isSameSym(sym interface{}, name string) bool { - s, ok := sym.(fmt.Stringer) - return ok && s.String() == name +// isSameCall reports whether sym is the same as the given named symbol +func isSameCall(sym interface{}, name string) bool { + return sym.(*AuxCall).Fn.String() == name } // nlz returns the number of leading zeros. @@ -713,6 +707,9 @@ func auxToSym(i interface{}) Sym { func auxToType(i interface{}) *types.Type { return i.(*types.Type) } +func auxToCall(i interface{}) *AuxCall { + return i.(*AuxCall) +} func auxToS390xCCMask(i interface{}) s390x.CCMask { return i.(s390x.CCMask) } @@ -726,6 +723,9 @@ func stringToAux(s string) interface{} { func symToAux(s Sym) interface{} { return s } +func callToAux(s *AuxCall) interface{} { + return s +} func typeToAux(t *types.Type) interface{} { return t } @@ -743,7 +743,7 @@ func uaddOvf(a, b int64) bool { // de-virtualize an InterCall // 'sym' is the symbol for the itab -func devirt(v *Value, sym Sym, offset int64) *obj.LSym { +func devirt(v *Value, sym Sym, offset int64) *AuxCall { f := v.Block.Func n, ok := sym.(*obj.LSym) if !ok { @@ -757,7 +757,10 @@ func devirt(v *Value, sym Sym, offset int64) *obj.LSym { f.Warnl(v.Pos, "couldn't de-virtualize call") } } - return lsym + if lsym == nil { + return nil + } + return &AuxCall{Fn: lsym} } // isSamePtr reports whether p1 and p2 point to the same address. @@ -1377,12 +1380,12 @@ func registerizable(b *Block, typ *types.Type) bool { } // needRaceCleanup reports whether this call to racefuncenter/exit isn't needed. -func needRaceCleanup(sym Sym, v *Value) bool { +func needRaceCleanup(sym *AuxCall, v *Value) bool { f := v.Block.Func if !f.Config.Race { return false } - if !symNamed(sym, "runtime.racefuncenter") && !symNamed(sym, "runtime.racefuncexit") { + if !isSameCall(sym, "runtime.racefuncenter") && !isSameCall(sym, "runtime.racefuncexit") { return false } for _, b := range f.Blocks { @@ -1391,7 +1394,7 @@ func needRaceCleanup(sym Sym, v *Value) bool { case OpStaticCall: // Check for racefuncenter will encounter racefuncexit and vice versa. // Allow calls to panic* - s := v.Aux.(fmt.Stringer).String() + s := v.Aux.(*AuxCall).Fn.String() switch s { case "runtime.racefuncenter", "runtime.racefuncexit", "runtime.panicdivide", "runtime.panicwrap", @@ -1409,7 +1412,7 @@ func needRaceCleanup(sym Sym, v *Value) bool { } } } - if symNamed(sym, "runtime.racefuncenter") { + if isSameCall(sym, "runtime.racefuncenter") { // If we're removing racefuncenter, remove its argument as well. if v.Args[0].Op != OpStore { return false diff --git a/src/cmd/compile/internal/ssa/rewritegeneric.go b/src/cmd/compile/internal/ssa/rewritegeneric.go index 180e48b34c..4b388a68cd 100644 --- a/src/cmd/compile/internal/ssa/rewritegeneric.go +++ b/src/cmd/compile/internal/ssa/rewritegeneric.go @@ -8515,7 +8515,7 @@ func rewriteValuegeneric_OpInterCall(v *Value) bool { } v.reset(OpStaticCall) v.AuxInt = int32ToAuxInt(int32(argsize)) - v.Aux = symToAux(devirt(v, itab, off)) + v.Aux = callToAux(devirt(v, itab, off)) v.AddArg(mem) return true } @@ -16022,7 +16022,7 @@ func rewriteValuegeneric_OpNilCheck(v *Value) bool { return true } // match: (NilCheck (Load (OffPtr [c] (SP)) (StaticCall {sym} _)) _) - // cond: symNamed(sym, "runtime.newobject") && c == config.ctxt.FixedFrameSize() + config.RegSize && warnRule(fe.Debug_checknil(), v, "removed nil check") + // cond: isSameCall(sym, "runtime.newobject") && c == config.ctxt.FixedFrameSize() + config.RegSize && warnRule(fe.Debug_checknil(), v, "removed nil check") // result: (Invalid) for { if v_0.Op != OpLoad { @@ -16042,15 +16042,15 @@ func rewriteValuegeneric_OpNilCheck(v *Value) bool { if v_0_1.Op != OpStaticCall { break } - sym := auxToSym(v_0_1.Aux) - if !(symNamed(sym, "runtime.newobject") && c == config.ctxt.FixedFrameSize()+config.RegSize && warnRule(fe.Debug_checknil(), v, "removed nil check")) { + sym := auxToCall(v_0_1.Aux) + if !(isSameCall(sym, "runtime.newobject") && c == config.ctxt.FixedFrameSize()+config.RegSize && warnRule(fe.Debug_checknil(), v, "removed nil check")) { break } v.reset(OpInvalid) return true } // match: (NilCheck (OffPtr (Load (OffPtr [c] (SP)) (StaticCall {sym} _))) _) - // cond: symNamed(sym, "runtime.newobject") && c == config.ctxt.FixedFrameSize() + config.RegSize && warnRule(fe.Debug_checknil(), v, "removed nil check") + // cond: isSameCall(sym, "runtime.newobject") && c == config.ctxt.FixedFrameSize() + config.RegSize && warnRule(fe.Debug_checknil(), v, "removed nil check") // result: (Invalid) for { if v_0.Op != OpOffPtr { @@ -16074,8 +16074,8 @@ func rewriteValuegeneric_OpNilCheck(v *Value) bool { if v_0_0_1.Op != OpStaticCall { break } - sym := auxToSym(v_0_0_1.Aux) - if !(symNamed(sym, "runtime.newobject") && c == config.ctxt.FixedFrameSize()+config.RegSize && warnRule(fe.Debug_checknil(), v, "removed nil check")) { + sym := auxToCall(v_0_0_1.Aux) + if !(isSameCall(sym, "runtime.newobject") && c == config.ctxt.FixedFrameSize()+config.RegSize && warnRule(fe.Debug_checknil(), v, "removed nil check")) { break } v.reset(OpInvalid) @@ -21067,10 +21067,10 @@ func rewriteValuegeneric_OpStaticCall(v *Value) bool { b := v.Block config := b.Func.Config // match: (StaticCall {sym} s1:(Store _ (Const64 [sz]) s2:(Store _ src s3:(Store {t} _ dst mem)))) - // cond: sz >= 0 && symNamed(sym, "runtime.memmove") && t.IsPtr() && s1.Uses == 1 && s2.Uses == 1 && s3.Uses == 1 && isInlinableMemmove(dst, src, int64(sz), config) && clobber(s1, s2, s3) + // cond: sz >= 0 && isSameCall(sym, "runtime.memmove") && t.IsPtr() && s1.Uses == 1 && s2.Uses == 1 && s3.Uses == 1 && isInlinableMemmove(dst, src, int64(sz), config) && clobber(s1, s2, s3) // result: (Move {t.Elem()} [int64(sz)] dst src mem) for { - sym := auxToSym(v.Aux) + sym := auxToCall(v.Aux) s1 := v_0 if s1.Op != OpStore { break @@ -21094,7 +21094,7 @@ func rewriteValuegeneric_OpStaticCall(v *Value) bool { t := auxToType(s3.Aux) mem := s3.Args[2] dst := s3.Args[1] - if !(sz >= 0 && symNamed(sym, "runtime.memmove") && t.IsPtr() && s1.Uses == 1 && s2.Uses == 1 && s3.Uses == 1 && isInlinableMemmove(dst, src, int64(sz), config) && clobber(s1, s2, s3)) { + if !(sz >= 0 && isSameCall(sym, "runtime.memmove") && t.IsPtr() && s1.Uses == 1 && s2.Uses == 1 && s3.Uses == 1 && isInlinableMemmove(dst, src, int64(sz), config) && clobber(s1, s2, s3)) { break } v.reset(OpMove) @@ -21104,10 +21104,10 @@ func rewriteValuegeneric_OpStaticCall(v *Value) bool { return true } // match: (StaticCall {sym} s1:(Store _ (Const32 [sz]) s2:(Store _ src s3:(Store {t} _ dst mem)))) - // cond: sz >= 0 && symNamed(sym, "runtime.memmove") && t.IsPtr() && s1.Uses == 1 && s2.Uses == 1 && s3.Uses == 1 && isInlinableMemmove(dst, src, int64(sz), config) && clobber(s1, s2, s3) + // cond: sz >= 0 && isSameCall(sym, "runtime.memmove") && t.IsPtr() && s1.Uses == 1 && s2.Uses == 1 && s3.Uses == 1 && isInlinableMemmove(dst, src, int64(sz), config) && clobber(s1, s2, s3) // result: (Move {t.Elem()} [int64(sz)] dst src mem) for { - sym := auxToSym(v.Aux) + sym := auxToCall(v.Aux) s1 := v_0 if s1.Op != OpStore { break @@ -21131,7 +21131,7 @@ func rewriteValuegeneric_OpStaticCall(v *Value) bool { t := auxToType(s3.Aux) mem := s3.Args[2] dst := s3.Args[1] - if !(sz >= 0 && symNamed(sym, "runtime.memmove") && t.IsPtr() && s1.Uses == 1 && s2.Uses == 1 && s3.Uses == 1 && isInlinableMemmove(dst, src, int64(sz), config) && clobber(s1, s2, s3)) { + if !(sz >= 0 && isSameCall(sym, "runtime.memmove") && t.IsPtr() && s1.Uses == 1 && s2.Uses == 1 && s3.Uses == 1 && isInlinableMemmove(dst, src, int64(sz), config) && clobber(s1, s2, s3)) { break } v.reset(OpMove) @@ -21144,7 +21144,7 @@ func rewriteValuegeneric_OpStaticCall(v *Value) bool { // cond: needRaceCleanup(sym, v) // result: x for { - sym := auxToSym(v.Aux) + sym := auxToCall(v.Aux) x := v_0 if !(needRaceCleanup(sym, v)) { break @@ -21608,7 +21608,7 @@ func rewriteValuegeneric_OpStore(v *Value) bool { return true } // match: (Store (Load (OffPtr [c] (SP)) mem) x mem) - // cond: isConstZero(x) && mem.Op == OpStaticCall && isSameSym(mem.Aux, "runtime.newobject") && c == config.ctxt.FixedFrameSize() + config.RegSize + // cond: isConstZero(x) && mem.Op == OpStaticCall && isSameCall(mem.Aux, "runtime.newobject") && c == config.ctxt.FixedFrameSize() + config.RegSize // result: mem for { if v_0.Op != OpLoad { @@ -21625,14 +21625,14 @@ func rewriteValuegeneric_OpStore(v *Value) bool { break } x := v_1 - if mem != v_2 || !(isConstZero(x) && mem.Op == OpStaticCall && isSameSym(mem.Aux, "runtime.newobject") && c == config.ctxt.FixedFrameSize()+config.RegSize) { + if mem != v_2 || !(isConstZero(x) && mem.Op == OpStaticCall && isSameCall(mem.Aux, "runtime.newobject") && c == config.ctxt.FixedFrameSize()+config.RegSize) { break } v.copyOf(mem) return true } // match: (Store (OffPtr (Load (OffPtr [c] (SP)) mem)) x mem) - // cond: isConstZero(x) && mem.Op == OpStaticCall && isSameSym(mem.Aux, "runtime.newobject") && c == config.ctxt.FixedFrameSize() + config.RegSize + // cond: isConstZero(x) && mem.Op == OpStaticCall && isSameCall(mem.Aux, "runtime.newobject") && c == config.ctxt.FixedFrameSize() + config.RegSize // result: mem for { if v_0.Op != OpOffPtr { @@ -21653,7 +21653,7 @@ func rewriteValuegeneric_OpStore(v *Value) bool { break } x := v_1 - if mem != v_2 || !(isConstZero(x) && mem.Op == OpStaticCall && isSameSym(mem.Aux, "runtime.newobject") && c == config.ctxt.FixedFrameSize()+config.RegSize) { + if mem != v_2 || !(isConstZero(x) && mem.Op == OpStaticCall && isSameCall(mem.Aux, "runtime.newobject") && c == config.ctxt.FixedFrameSize()+config.RegSize) { break } v.copyOf(mem) @@ -24337,7 +24337,7 @@ func rewriteValuegeneric_OpZero(v *Value) bool { b := v.Block config := b.Func.Config // match: (Zero (Load (OffPtr [c] (SP)) mem) mem) - // cond: mem.Op == OpStaticCall && isSameSym(mem.Aux, "runtime.newobject") && c == config.ctxt.FixedFrameSize() + config.RegSize + // cond: mem.Op == OpStaticCall && isSameCall(mem.Aux, "runtime.newobject") && c == config.ctxt.FixedFrameSize() + config.RegSize // result: mem for { if v_0.Op != OpLoad { @@ -24350,7 +24350,7 @@ func rewriteValuegeneric_OpZero(v *Value) bool { } c := auxIntToInt64(v_0_0.AuxInt) v_0_0_0 := v_0_0.Args[0] - if v_0_0_0.Op != OpSP || mem != v_1 || !(mem.Op == OpStaticCall && isSameSym(mem.Aux, "runtime.newobject") && c == config.ctxt.FixedFrameSize()+config.RegSize) { + if v_0_0_0.Op != OpSP || mem != v_1 || !(mem.Op == OpStaticCall && isSameCall(mem.Aux, "runtime.newobject") && c == config.ctxt.FixedFrameSize()+config.RegSize) { break } v.copyOf(mem) diff --git a/src/cmd/compile/internal/ssa/value.go b/src/cmd/compile/internal/ssa/value.go index 6692df7921..94b8763d5d 100644 --- a/src/cmd/compile/internal/ssa/value.go +++ b/src/cmd/compile/internal/ssa/value.go @@ -193,11 +193,11 @@ func (v *Value) auxString() string { return fmt.Sprintf(" [%g]", v.AuxFloat()) case auxString: return fmt.Sprintf(" {%q}", v.Aux) - case auxSym, auxTyp: + case auxSym, auxCall, auxTyp: if v.Aux != nil { return fmt.Sprintf(" {%v}", v.Aux) } - case auxSymOff, auxTypSize: + case auxSymOff, auxCallOff, auxTypSize: s := "" if v.Aux != nil { s = fmt.Sprintf(" {%v}", v.Aux) diff --git a/src/cmd/compile/internal/ssa/writebarrier.go b/src/cmd/compile/internal/ssa/writebarrier.go index 214798a1ab..c358406862 100644 --- a/src/cmd/compile/internal/ssa/writebarrier.go +++ b/src/cmd/compile/internal/ssa/writebarrier.go @@ -523,7 +523,7 @@ func wbcall(pos src.XPos, b *Block, fn, typ *obj.LSym, ptr, val, mem, sp, sb *Va off = round(off, config.PtrSize) // issue call - mem = b.NewValue1A(pos, OpStaticCall, types.TypeMem, fn, mem) + mem = b.NewValue1A(pos, OpStaticCall, types.TypeMem, &AuxCall{fn}, mem) mem.AuxInt = off - config.ctxt.FixedFrameSize() return mem } @@ -582,7 +582,7 @@ func IsNewObject(v *Value, mem *Value) bool { if mem.Op != OpStaticCall { return false } - if !isSameSym(mem.Aux, "runtime.newobject") { + if !isSameCall(mem.Aux, "runtime.newobject") { return false } if v.Args[0].Op != OpOffPtr { diff --git a/src/cmd/compile/internal/wasm/ssa.go b/src/cmd/compile/internal/wasm/ssa.go index 7861667b88..a36fbca4e0 100644 --- a/src/cmd/compile/internal/wasm/ssa.go +++ b/src/cmd/compile/internal/wasm/ssa.go @@ -122,7 +122,7 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) { switch v.Op { case ssa.OpWasmLoweredStaticCall, ssa.OpWasmLoweredClosureCall, ssa.OpWasmLoweredInterCall: s.PrepareCall(v) - if v.Aux == gc.Deferreturn { + if call, ok := v.Aux.(*ssa.AuxCall); ok && call.Fn == gc.Deferreturn { // add a resume point before call to deferreturn so it can be called again via jmpdefer s.Prog(wasm.ARESUMEPOINT) } @@ -130,7 +130,8 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) { getValue64(s, v.Args[1]) setReg(s, wasm.REG_CTXT) } - if sym, ok := v.Aux.(*obj.LSym); ok { + if call, ok := v.Aux.(*ssa.AuxCall); ok && call.Fn != nil { + sym := call.Fn p := s.Prog(obj.ACALL) p.To = obj.Addr{Type: obj.TYPE_MEM, Name: obj.NAME_EXTERN, Sym: sym} p.Pos = v.Pos -- cgit v1.3 From 3c85e995efd0c2adf8578ed27565ad3b427f1a43 Mon Sep 17 00:00:00 2001 From: David Chase Date: Mon, 15 Jun 2020 18:27:02 -0400 Subject: cmd/compile: extend ssa.AuxCall to closure and interface calls Also introduce helper methods. Change-Id: I11a744ed002bae0ca9ebabba3206e1c14147e03d Reviewed-on: https://go-review.googlesource.com/c/go/+/239080 Trust: David Chase Run-TryBot: David Chase TryBot-Result: Go Bot Reviewed-by: Cherry Zhang --- src/cmd/compile/internal/gc/ssa.go | 18 +++++----- src/cmd/compile/internal/ssa/gen/386Ops.go | 6 ++-- src/cmd/compile/internal/ssa/gen/AMD64Ops.go | 6 ++-- src/cmd/compile/internal/ssa/gen/ARM64Ops.go | 6 ++-- src/cmd/compile/internal/ssa/gen/ARMOps.go | 6 ++-- src/cmd/compile/internal/ssa/gen/MIPS64Ops.go | 6 ++-- src/cmd/compile/internal/ssa/gen/MIPSOps.go | 6 ++-- src/cmd/compile/internal/ssa/gen/PPC64Ops.go | 6 ++-- src/cmd/compile/internal/ssa/gen/RISCV64Ops.go | 6 ++-- src/cmd/compile/internal/ssa/gen/S390XOps.go | 6 ++-- src/cmd/compile/internal/ssa/gen/WasmOps.go | 8 ++--- src/cmd/compile/internal/ssa/gen/genericOps.go | 6 ++-- src/cmd/compile/internal/ssa/loopreschedchecks.go | 2 +- src/cmd/compile/internal/ssa/op.go | 15 ++++++++ src/cmd/compile/internal/ssa/opGen.go | 44 +++++++++++------------ src/cmd/compile/internal/ssa/rewrite.go | 2 +- src/cmd/compile/internal/ssa/rewritegeneric.go | 2 +- src/cmd/compile/internal/ssa/writebarrier.go | 2 +- 18 files changed, 84 insertions(+), 69 deletions(-) (limited to 'src/cmd/compile/internal') diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go index 0ee31bd9a3..542b1b51c2 100644 --- a/src/cmd/compile/internal/gc/ssa.go +++ b/src/cmd/compile/internal/gc/ssa.go @@ -4302,10 +4302,10 @@ func (s *state) openDeferExit() { v := s.load(r.closure.Type.Elem(), r.closure) s.maybeNilCheckClosure(v, callDefer) codeptr := s.rawLoad(types.Types[TUINTPTR], v) - call = s.newValue3A(ssa.OpClosureCall, types.TypeMem, nil, codeptr, v, s.mem()) + call = s.newValue3A(ssa.OpClosureCall, types.TypeMem, ssa.ClosureAuxCall(), codeptr, v, s.mem()) } else { // Do a static call if the original call was a static function or method - call = s.newValue1A(ssa.OpStaticCall, types.TypeMem, &ssa.AuxCall{Fn: fn.Sym.Linksym()}, s.mem()) + call = s.newValue1A(ssa.OpStaticCall, types.TypeMem, ssa.StaticAuxCall(fn.Sym.Linksym()), s.mem()) } call.AuxInt = stksize s.vars[&memVar] = call @@ -4437,7 +4437,7 @@ func (s *state) call(n *Node, k callKind) *ssa.Value { // Call runtime.deferprocStack with pointer to _defer record. arg0 := s.constOffPtrSP(types.Types[TUINTPTR], Ctxt.FixedFrameSize()) s.store(types.Types[TUINTPTR], arg0, addr) - call = s.newValue1A(ssa.OpStaticCall, types.TypeMem, &ssa.AuxCall{Fn: deferprocStack}, s.mem()) + call = s.newValue1A(ssa.OpStaticCall, types.TypeMem, ssa.StaticAuxCall(deferprocStack), s.mem()) if stksize < int64(Widthptr) { // We need room for both the call to deferprocStack and the call to // the deferred function. @@ -4482,9 +4482,9 @@ func (s *state) call(n *Node, k callKind) *ssa.Value { // call target switch { case k == callDefer: - call = s.newValue1A(ssa.OpStaticCall, types.TypeMem, &ssa.AuxCall{Fn: deferproc}, s.mem()) + call = s.newValue1A(ssa.OpStaticCall, types.TypeMem, ssa.StaticAuxCall(deferproc), s.mem()) case k == callGo: - call = s.newValue1A(ssa.OpStaticCall, types.TypeMem, &ssa.AuxCall{Fn: newproc}, s.mem()) + call = s.newValue1A(ssa.OpStaticCall, types.TypeMem, ssa.StaticAuxCall(newproc), s.mem()) case closure != nil: // rawLoad because loading the code pointer from a // closure is always safe, but IsSanitizerSafeAddr @@ -4492,11 +4492,11 @@ func (s *state) call(n *Node, k callKind) *ssa.Value { // critical that we not clobber any arguments already // stored onto the stack. codeptr = s.rawLoad(types.Types[TUINTPTR], closure) - call = s.newValue3A(ssa.OpClosureCall, types.TypeMem, nil, codeptr, closure, s.mem()) + call = s.newValue3A(ssa.OpClosureCall, types.TypeMem, ssa.ClosureAuxCall(), codeptr, closure, s.mem()) case codeptr != nil: - call = s.newValue2A(ssa.OpInterCall, types.TypeMem, nil, codeptr, s.mem()) + call = s.newValue2A(ssa.OpInterCall, types.TypeMem, ssa.InterfaceAuxCall(), codeptr, s.mem()) case sym != nil: - call = s.newValue1A(ssa.OpStaticCall, types.TypeMem, &ssa.AuxCall{Fn: sym.Linksym()}, s.mem()) + call = s.newValue1A(ssa.OpStaticCall, types.TypeMem, ssa.StaticAuxCall(sym.Linksym()), s.mem()) default: s.Fatalf("bad call type %v %v", n.Op, n) } @@ -4929,7 +4929,7 @@ func (s *state) rtcall(fn *obj.LSym, returns bool, results []*types.Type, args . off = Rnd(off, int64(Widthreg)) // Issue call - call := s.newValue1A(ssa.OpStaticCall, types.TypeMem, &ssa.AuxCall{Fn: fn}, s.mem()) + call := s.newValue1A(ssa.OpStaticCall, types.TypeMem, ssa.StaticAuxCall(fn), s.mem()) s.vars[&memVar] = call if !returns { diff --git a/src/cmd/compile/internal/ssa/gen/386Ops.go b/src/cmd/compile/internal/ssa/gen/386Ops.go index 64a17cb7a3..ddabde7d3d 100644 --- a/src/cmd/compile/internal/ssa/gen/386Ops.go +++ b/src/cmd/compile/internal/ssa/gen/386Ops.go @@ -463,9 +463,9 @@ func init() { faultOnNilArg0: true, }, - {name: "CALLstatic", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call static function aux.(*obj.LSym). arg0=mem, auxint=argsize, returns mem - {name: "CALLclosure", argLength: 3, reg: regInfo{inputs: []regMask{gpsp, buildReg("DX"), 0}, clobbers: callerSave}, aux: "Int64", clobberFlags: true, call: true}, // call function via closure. arg0=codeptr, arg1=closure, arg2=mem, auxint=argsize, returns mem - {name: "CALLinter", argLength: 2, reg: regInfo{inputs: []regMask{gp}, clobbers: callerSave}, aux: "Int64", clobberFlags: true, call: true}, // call fn by pointer. arg0=codeptr, arg1=mem, auxint=argsize, returns mem + {name: "CALLstatic", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call static function aux.(*obj.LSym). arg0=mem, auxint=argsize, returns mem + {name: "CALLclosure", argLength: 3, reg: regInfo{inputs: []regMask{gpsp, buildReg("DX"), 0}, clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call function via closure. arg0=codeptr, arg1=closure, arg2=mem, auxint=argsize, returns mem + {name: "CALLinter", argLength: 2, reg: regInfo{inputs: []regMask{gp}, clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call fn by pointer. arg0=codeptr, arg1=mem, auxint=argsize, returns mem // arg0 = destination pointer // arg1 = source pointer diff --git a/src/cmd/compile/internal/ssa/gen/AMD64Ops.go b/src/cmd/compile/internal/ssa/gen/AMD64Ops.go index d267fe8753..2df5016d59 100644 --- a/src/cmd/compile/internal/ssa/gen/AMD64Ops.go +++ b/src/cmd/compile/internal/ssa/gen/AMD64Ops.go @@ -767,9 +767,9 @@ func init() { faultOnNilArg0: true, }, - {name: "CALLstatic", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call static function aux.(*obj.LSym). arg0=mem, auxint=argsize, returns mem - {name: "CALLclosure", argLength: 3, reg: regInfo{inputs: []regMask{gpsp, buildReg("DX"), 0}, clobbers: callerSave}, aux: "Int64", clobberFlags: true, call: true}, // call function via closure. arg0=codeptr, arg1=closure, arg2=mem, auxint=argsize, returns mem - {name: "CALLinter", argLength: 2, reg: regInfo{inputs: []regMask{gp}, clobbers: callerSave}, aux: "Int64", clobberFlags: true, call: true}, // call fn by pointer. arg0=codeptr, arg1=mem, auxint=argsize, returns mem + {name: "CALLstatic", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call static function aux.(*obj.LSym). arg0=mem, auxint=argsize, returns mem + {name: "CALLclosure", argLength: 3, reg: regInfo{inputs: []regMask{gpsp, buildReg("DX"), 0}, clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call function via closure. arg0=codeptr, arg1=closure, arg2=mem, auxint=argsize, returns mem + {name: "CALLinter", argLength: 2, reg: regInfo{inputs: []regMask{gp}, clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call fn by pointer. arg0=codeptr, arg1=mem, auxint=argsize, returns mem // arg0 = destination pointer // arg1 = source pointer diff --git a/src/cmd/compile/internal/ssa/gen/ARM64Ops.go b/src/cmd/compile/internal/ssa/gen/ARM64Ops.go index f52d68dc33..9ff53f7e4e 100644 --- a/src/cmd/compile/internal/ssa/gen/ARM64Ops.go +++ b/src/cmd/compile/internal/ssa/gen/ARM64Ops.go @@ -471,9 +471,9 @@ func init() { {name: "CSEL0", argLength: 2, reg: gp1flags1, asm: "CSEL", aux: "CCop"}, // auxint(flags) ? arg0 : 0 // function calls - {name: "CALLstatic", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call static function aux.(*obj.LSym). arg0=mem, auxint=argsize, returns mem - {name: "CALLclosure", argLength: 3, reg: regInfo{inputs: []regMask{gpsp, buildReg("R26"), 0}, clobbers: callerSave}, aux: "Int64", clobberFlags: true, call: true}, // call function via closure. arg0=codeptr, arg1=closure, arg2=mem, auxint=argsize, returns mem - {name: "CALLinter", argLength: 2, reg: regInfo{inputs: []regMask{gp}, clobbers: callerSave}, aux: "Int64", clobberFlags: true, call: true}, // call fn by pointer. arg0=codeptr, arg1=mem, auxint=argsize, returns mem + {name: "CALLstatic", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call static function aux.(*obj.LSym). arg0=mem, auxint=argsize, returns mem + {name: "CALLclosure", argLength: 3, reg: regInfo{inputs: []regMask{gpsp, buildReg("R26"), 0}, clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call function via closure. arg0=codeptr, arg1=closure, arg2=mem, auxint=argsize, returns mem + {name: "CALLinter", argLength: 2, reg: regInfo{inputs: []regMask{gp}, clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call fn by pointer. arg0=codeptr, arg1=mem, auxint=argsize, returns mem // pseudo-ops {name: "LoweredNilCheck", argLength: 2, reg: regInfo{inputs: []regMask{gpg}}, nilCheck: true, faultOnNilArg0: true}, // panic if arg0 is nil. arg1=mem. diff --git a/src/cmd/compile/internal/ssa/gen/ARMOps.go b/src/cmd/compile/internal/ssa/gen/ARMOps.go index 1e6b4546da..70c789937a 100644 --- a/src/cmd/compile/internal/ssa/gen/ARMOps.go +++ b/src/cmd/compile/internal/ssa/gen/ARMOps.go @@ -428,9 +428,9 @@ func init() { {name: "SRAcond", argLength: 3, reg: gp2flags1, asm: "SRA"}, // arg0 >> 31 if flags indicates HS, arg0 >> arg1 otherwise, signed shift, arg2=flags // function calls - {name: "CALLstatic", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call static function aux.(*obj.LSym). arg0=mem, auxint=argsize, returns mem - {name: "CALLclosure", argLength: 3, reg: regInfo{inputs: []regMask{gpsp, buildReg("R7"), 0}, clobbers: callerSave}, aux: "Int64", clobberFlags: true, call: true}, // call function via closure. arg0=codeptr, arg1=closure, arg2=mem, auxint=argsize, returns mem - {name: "CALLinter", argLength: 2, reg: regInfo{inputs: []regMask{gp}, clobbers: callerSave}, aux: "Int64", clobberFlags: true, call: true}, // call fn by pointer. arg0=codeptr, arg1=mem, auxint=argsize, returns mem + {name: "CALLstatic", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call static function aux.(*obj.LSym). arg0=mem, auxint=argsize, returns mem + {name: "CALLclosure", argLength: 3, reg: regInfo{inputs: []regMask{gpsp, buildReg("R7"), 0}, clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call function via closure. arg0=codeptr, arg1=closure, arg2=mem, auxint=argsize, returns mem + {name: "CALLinter", argLength: 2, reg: regInfo{inputs: []regMask{gp}, clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call fn by pointer. arg0=codeptr, arg1=mem, auxint=argsize, returns mem // pseudo-ops {name: "LoweredNilCheck", argLength: 2, reg: regInfo{inputs: []regMask{gpg}}, nilCheck: true, faultOnNilArg0: true}, // panic if arg0 is nil. arg1=mem. diff --git a/src/cmd/compile/internal/ssa/gen/MIPS64Ops.go b/src/cmd/compile/internal/ssa/gen/MIPS64Ops.go index dc2e9d3ec9..e1e3933502 100644 --- a/src/cmd/compile/internal/ssa/gen/MIPS64Ops.go +++ b/src/cmd/compile/internal/ssa/gen/MIPS64Ops.go @@ -273,9 +273,9 @@ func init() { {name: "MOVDF", argLength: 1, reg: fp11, asm: "MOVDF"}, // float64 -> float32 // function calls - {name: "CALLstatic", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call static function aux.(*obj.LSym). arg0=mem, auxint=argsize, returns mem - {name: "CALLclosure", argLength: 3, reg: regInfo{inputs: []regMask{gpsp, buildReg("R22"), 0}, clobbers: callerSave}, aux: "Int64", clobberFlags: true, call: true}, // call function via closure. arg0=codeptr, arg1=closure, arg2=mem, auxint=argsize, returns mem - {name: "CALLinter", argLength: 2, reg: regInfo{inputs: []regMask{gp}, clobbers: callerSave}, aux: "Int64", clobberFlags: true, call: true}, // call fn by pointer. arg0=codeptr, arg1=mem, auxint=argsize, returns mem + {name: "CALLstatic", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call static function aux.(*obj.LSym). arg0=mem, auxint=argsize, returns mem + {name: "CALLclosure", argLength: 3, reg: regInfo{inputs: []regMask{gpsp, buildReg("R22"), 0}, clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call function via closure. arg0=codeptr, arg1=closure, arg2=mem, auxint=argsize, returns mem + {name: "CALLinter", argLength: 2, reg: regInfo{inputs: []regMask{gp}, clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call fn by pointer. arg0=codeptr, arg1=mem, auxint=argsize, returns mem // duffzero // arg0 = address of memory to zero diff --git a/src/cmd/compile/internal/ssa/gen/MIPSOps.go b/src/cmd/compile/internal/ssa/gen/MIPSOps.go index c66adcf93a..cd7357f62b 100644 --- a/src/cmd/compile/internal/ssa/gen/MIPSOps.go +++ b/src/cmd/compile/internal/ssa/gen/MIPSOps.go @@ -255,9 +255,9 @@ func init() { {name: "MOVDF", argLength: 1, reg: fp11, asm: "MOVDF"}, // float64 -> float32 // function calls - {name: "CALLstatic", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call static function aux.(*obj.LSym). arg0=mem, auxint=argsize, returns mem - {name: "CALLclosure", argLength: 3, reg: regInfo{inputs: []regMask{gpsp, buildReg("R22"), 0}, clobbers: callerSave}, aux: "Int64", clobberFlags: true, call: true}, // call function via closure. arg0=codeptr, arg1=closure, arg2=mem, auxint=argsize, returns mem - {name: "CALLinter", argLength: 2, reg: regInfo{inputs: []regMask{gp}, clobbers: callerSave}, aux: "Int64", clobberFlags: true, call: true}, // call fn by pointer. arg0=codeptr, arg1=mem, auxint=argsize, returns mem + {name: "CALLstatic", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call static function aux.(*obj.LSym). arg0=mem, auxint=argsize, returns mem + {name: "CALLclosure", argLength: 3, reg: regInfo{inputs: []regMask{gpsp, buildReg("R22"), 0}, clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call function via closure. arg0=codeptr, arg1=closure, arg2=mem, auxint=argsize, returns mem + {name: "CALLinter", argLength: 2, reg: regInfo{inputs: []regMask{gp}, clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call fn by pointer. arg0=codeptr, arg1=mem, auxint=argsize, returns mem // atomic ops diff --git a/src/cmd/compile/internal/ssa/gen/PPC64Ops.go b/src/cmd/compile/internal/ssa/gen/PPC64Ops.go index 0c04e561ad..37706b2dd9 100644 --- a/src/cmd/compile/internal/ssa/gen/PPC64Ops.go +++ b/src/cmd/compile/internal/ssa/gen/PPC64Ops.go @@ -414,9 +414,9 @@ func init() { {name: "LoweredRound32F", argLength: 1, reg: fp11, resultInArg0: true, zeroWidth: true}, {name: "LoweredRound64F", argLength: 1, reg: fp11, resultInArg0: true, zeroWidth: true}, - {name: "CALLstatic", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call static function aux.(*obj.LSym). arg0=mem, auxint=argsize, returns mem - {name: "CALLclosure", argLength: 3, reg: regInfo{inputs: []regMask{callptr, ctxt, 0}, clobbers: callerSave}, aux: "Int64", clobberFlags: true, call: true}, // call function via closure. arg0=codeptr, arg1=closure, arg2=mem, auxint=argsize, returns mem - {name: "CALLinter", argLength: 2, reg: regInfo{inputs: []regMask{callptr}, clobbers: callerSave}, aux: "Int64", clobberFlags: true, call: true}, // call fn by pointer. arg0=codeptr, arg1=mem, auxint=argsize, returns mem + {name: "CALLstatic", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call static function aux.(*obj.LSym). arg0=mem, auxint=argsize, returns mem + {name: "CALLclosure", argLength: 3, reg: regInfo{inputs: []regMask{callptr, ctxt, 0}, clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call function via closure. arg0=codeptr, arg1=closure, arg2=mem, auxint=argsize, returns mem + {name: "CALLinter", argLength: 2, reg: regInfo{inputs: []regMask{callptr}, clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call fn by pointer. arg0=codeptr, arg1=mem, auxint=argsize, returns mem // large or unaligned zeroing // arg0 = address of memory to zero (in R3, changed as side effect) diff --git a/src/cmd/compile/internal/ssa/gen/RISCV64Ops.go b/src/cmd/compile/internal/ssa/gen/RISCV64Ops.go index 17970918e2..b06b86075e 100644 --- a/src/cmd/compile/internal/ssa/gen/RISCV64Ops.go +++ b/src/cmd/compile/internal/ssa/gen/RISCV64Ops.go @@ -224,9 +224,9 @@ func init() { {name: "MOVconvert", argLength: 2, reg: gp11, asm: "MOV"}, // arg0, but converted to int/ptr as appropriate; arg1=mem // Calls - {name: "CALLstatic", argLength: 1, reg: call, aux: "CallOff", call: true}, // call static function aux.(*gc.Sym). arg0=mem, auxint=argsize, returns mem - {name: "CALLclosure", argLength: 3, reg: callClosure, aux: "Int64", call: true}, // call function via closure. arg0=codeptr, arg1=closure, arg2=mem, auxint=argsize, returns mem - {name: "CALLinter", argLength: 2, reg: callInter, aux: "Int64", call: true}, // call fn by pointer. arg0=codeptr, arg1=mem, auxint=argsize, returns mem + {name: "CALLstatic", argLength: 1, reg: call, aux: "CallOff", call: true}, // call static function aux.(*gc.Sym). arg0=mem, auxint=argsize, returns mem + {name: "CALLclosure", argLength: 3, reg: callClosure, aux: "CallOff", call: true}, // call function via closure. arg0=codeptr, arg1=closure, arg2=mem, auxint=argsize, returns mem + {name: "CALLinter", argLength: 2, reg: callInter, aux: "CallOff", call: true}, // call fn by pointer. arg0=codeptr, arg1=mem, auxint=argsize, returns mem // Generic moves and zeros diff --git a/src/cmd/compile/internal/ssa/gen/S390XOps.go b/src/cmd/compile/internal/ssa/gen/S390XOps.go index eede8a654b..417b33cf91 100644 --- a/src/cmd/compile/internal/ssa/gen/S390XOps.go +++ b/src/cmd/compile/internal/ssa/gen/S390XOps.go @@ -475,9 +475,9 @@ func init() { {name: "CLEAR", argLength: 2, reg: regInfo{inputs: []regMask{ptr, 0}}, asm: "CLEAR", aux: "SymValAndOff", typ: "Mem", clobberFlags: true, faultOnNilArg0: true, symEffect: "Write"}, - {name: "CALLstatic", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call static function aux.(*obj.LSym). arg0=mem, auxint=argsize, returns mem - {name: "CALLclosure", argLength: 3, reg: regInfo{inputs: []regMask{ptrsp, buildReg("R12"), 0}, clobbers: callerSave}, aux: "Int64", clobberFlags: true, call: true}, // call function via closure. arg0=codeptr, arg1=closure, arg2=mem, auxint=argsize, returns mem - {name: "CALLinter", argLength: 2, reg: regInfo{inputs: []regMask{ptr}, clobbers: callerSave}, aux: "Int64", clobberFlags: true, call: true}, // call fn by pointer. arg0=codeptr, arg1=mem, auxint=argsize, returns mem + {name: "CALLstatic", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call static function aux.(*obj.LSym). arg0=mem, auxint=argsize, returns mem + {name: "CALLclosure", argLength: 3, reg: regInfo{inputs: []regMask{ptrsp, buildReg("R12"), 0}, clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call function via closure. arg0=codeptr, arg1=closure, arg2=mem, auxint=argsize, returns mem + {name: "CALLinter", argLength: 2, reg: regInfo{inputs: []regMask{ptr}, clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call fn by pointer. arg0=codeptr, arg1=mem, auxint=argsize, returns mem // (InvertFlags (CMP a b)) == (CMP b a) // InvertFlags is a pseudo-op which can't appear in assembly output. diff --git a/src/cmd/compile/internal/ssa/gen/WasmOps.go b/src/cmd/compile/internal/ssa/gen/WasmOps.go index 3286a68fb0..36c53bc78c 100644 --- a/src/cmd/compile/internal/ssa/gen/WasmOps.go +++ b/src/cmd/compile/internal/ssa/gen/WasmOps.go @@ -122,9 +122,9 @@ func init() { ) var WasmOps = []opData{ - {name: "LoweredStaticCall", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "CallOff", call: true}, // call static function aux.(*obj.LSym). arg0=mem, auxint=argsize, returns mem - {name: "LoweredClosureCall", argLength: 3, reg: regInfo{inputs: []regMask{gp, gp, 0}, clobbers: callerSave}, aux: "Int64", call: true}, // call function via closure. arg0=codeptr, arg1=closure, arg2=mem, auxint=argsize, returns mem - {name: "LoweredInterCall", argLength: 2, reg: regInfo{inputs: []regMask{gp}, clobbers: callerSave}, aux: "Int64", call: true}, // call fn by pointer. arg0=codeptr, arg1=mem, auxint=argsize, returns mem + {name: "LoweredStaticCall", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "CallOff", call: true}, // call static function aux.(*obj.LSym). arg0=mem, auxint=argsize, returns mem + {name: "LoweredClosureCall", argLength: 3, reg: regInfo{inputs: []regMask{gp, gp, 0}, clobbers: callerSave}, aux: "CallOff", call: true}, // call function via closure. arg0=codeptr, arg1=closure, arg2=mem, auxint=argsize, returns mem + {name: "LoweredInterCall", argLength: 2, reg: regInfo{inputs: []regMask{gp}, clobbers: callerSave}, aux: "CallOff", call: true}, // call fn by pointer. arg0=codeptr, arg1=mem, auxint=argsize, returns mem {name: "LoweredAddr", argLength: 1, reg: gp11, aux: "SymOff", rematerializeable: true, symEffect: "Addr"}, // returns base+aux+auxint, arg0=base {name: "LoweredMove", argLength: 3, reg: regInfo{inputs: []regMask{gp, gp}}, aux: "Int64"}, // large move. arg0=dst, arg1=src, arg2=mem, auxint=len/8, returns mem @@ -137,7 +137,7 @@ func init() { {name: "LoweredWB", argLength: 3, reg: regInfo{inputs: []regMask{gp, gp}}, aux: "Sym", symEffect: "None"}, // invokes runtime.gcWriteBarrier. arg0=destptr, arg1=srcptr, arg2=mem, aux=runtime.gcWriteBarrier // LoweredConvert converts between pointers and integers. - // We have a special op for this so as to not confuse GC + // We have a special op for this so as to not confuse GCCallOff // (particularly stack maps). It takes a memory arg so it // gets correctly ordered with respect to GC safepoints. // arg0=ptr/int arg1=mem, output=int/ptr diff --git a/src/cmd/compile/internal/ssa/gen/genericOps.go b/src/cmd/compile/internal/ssa/gen/genericOps.go index acfe222089..145ba2d50c 100644 --- a/src/cmd/compile/internal/ssa/gen/genericOps.go +++ b/src/cmd/compile/internal/ssa/gen/genericOps.go @@ -387,9 +387,9 @@ var genericOps = []opData{ // as a phantom first argument. // TODO(josharian): ClosureCall and InterCall should have Int32 aux // to match StaticCall's 32 bit arg size limit. - {name: "ClosureCall", argLength: 3, aux: "Int64", call: true}, // arg0=code pointer, arg1=context ptr, arg2=memory. auxint=arg size. Returns memory. - {name: "StaticCall", argLength: 1, aux: "CallOff", call: true}, // call function aux.(*obj.LSym), arg0=memory. auxint=arg size. Returns memory. - {name: "InterCall", argLength: 2, aux: "Int64", call: true}, // interface call. arg0=code pointer, arg1=memory, auxint=arg size. Returns memory. + {name: "ClosureCall", argLength: 3, aux: "CallOff", call: true}, // arg0=code pointer, arg1=context ptr, arg2=memory. auxint=arg size. Returns memory. + {name: "StaticCall", argLength: 1, aux: "CallOff", call: true}, // call function aux.(*obj.LSym), arg0=memory. auxint=arg size. Returns memory. + {name: "InterCall", argLength: 2, aux: "CallOff", call: true}, // interface call. arg0=code pointer, arg1=memory, auxint=arg size. Returns memory. // Conversions: signed extensions, zero (unsigned) extensions, truncations {name: "SignExt8to16", argLength: 1, typ: "Int16"}, diff --git a/src/cmd/compile/internal/ssa/loopreschedchecks.go b/src/cmd/compile/internal/ssa/loopreschedchecks.go index 4a720fdede..ebd23b34c7 100644 --- a/src/cmd/compile/internal/ssa/loopreschedchecks.go +++ b/src/cmd/compile/internal/ssa/loopreschedchecks.go @@ -246,7 +246,7 @@ func insertLoopReschedChecks(f *Func) { // mem1 := call resched (mem0) // goto header resched := f.fe.Syslook("goschedguarded") - mem1 := sched.NewValue1A(bb.Pos, OpStaticCall, types.TypeMem, &AuxCall{resched}, mem0) + mem1 := sched.NewValue1A(bb.Pos, OpStaticCall, types.TypeMem, StaticAuxCall(resched), mem0) sched.AddEdgeTo(h) headerMemPhi.AddArg(mem1) diff --git a/src/cmd/compile/internal/ssa/op.go b/src/cmd/compile/internal/ssa/op.go index 3aa506e3ab..c498a288a1 100644 --- a/src/cmd/compile/internal/ssa/op.go +++ b/src/cmd/compile/internal/ssa/op.go @@ -78,6 +78,21 @@ func (a *AuxCall) String() string { return fmt.Sprintf("AuxCall(%v)", a.Fn) } +// StaticAuxCall returns an AuxCall for a static call. +func StaticAuxCall(sym *obj.LSym) *AuxCall { + return &AuxCall{Fn: sym} +} + +// InterfaceAuxCall returns an AuxCall for an interface call. +func InterfaceAuxCall() *AuxCall { + return &AuxCall{} +} + +// ClosureAuxCall returns an AuxCall for a closure call. +func ClosureAuxCall() *AuxCall { + return &AuxCall{} +} + const ( auxNone auxType = iota auxBool // auxInt is 0/1 for false/true diff --git a/src/cmd/compile/internal/ssa/opGen.go b/src/cmd/compile/internal/ssa/opGen.go index 797d82f2d1..d95943231a 100644 --- a/src/cmd/compile/internal/ssa/opGen.go +++ b/src/cmd/compile/internal/ssa/opGen.go @@ -5826,7 +5826,7 @@ var opcodeTable = [...]opInfo{ }, { name: "CALLclosure", - auxType: auxInt64, + auxType: auxCallOff, argLen: 3, clobberFlags: true, call: true, @@ -5840,7 +5840,7 @@ var opcodeTable = [...]opInfo{ }, { name: "CALLinter", - auxType: auxInt64, + auxType: auxCallOff, argLen: 2, clobberFlags: true, call: true, @@ -13161,7 +13161,7 @@ var opcodeTable = [...]opInfo{ }, { name: "CALLclosure", - auxType: auxInt64, + auxType: auxCallOff, argLen: 3, clobberFlags: true, call: true, @@ -13175,7 +13175,7 @@ var opcodeTable = [...]opInfo{ }, { name: "CALLinter", - auxType: auxInt64, + auxType: auxCallOff, argLen: 2, clobberFlags: true, call: true, @@ -16930,7 +16930,7 @@ var opcodeTable = [...]opInfo{ }, { name: "CALLclosure", - auxType: auxInt64, + auxType: auxCallOff, argLen: 3, clobberFlags: true, call: true, @@ -16944,7 +16944,7 @@ var opcodeTable = [...]opInfo{ }, { name: "CALLinter", - auxType: auxInt64, + auxType: auxCallOff, argLen: 2, clobberFlags: true, call: true, @@ -20563,7 +20563,7 @@ var opcodeTable = [...]opInfo{ }, { name: "CALLclosure", - auxType: auxInt64, + auxType: auxCallOff, argLen: 3, clobberFlags: true, call: true, @@ -20577,7 +20577,7 @@ var opcodeTable = [...]opInfo{ }, { name: "CALLinter", - auxType: auxInt64, + auxType: auxCallOff, argLen: 2, clobberFlags: true, call: true, @@ -22263,7 +22263,7 @@ var opcodeTable = [...]opInfo{ }, { name: "CALLclosure", - auxType: auxInt64, + auxType: auxCallOff, argLen: 3, clobberFlags: true, call: true, @@ -22277,7 +22277,7 @@ var opcodeTable = [...]opInfo{ }, { name: "CALLinter", - auxType: auxInt64, + auxType: auxCallOff, argLen: 2, clobberFlags: true, call: true, @@ -23809,7 +23809,7 @@ var opcodeTable = [...]opInfo{ }, { name: "CALLclosure", - auxType: auxInt64, + auxType: auxCallOff, argLen: 3, clobberFlags: true, call: true, @@ -23823,7 +23823,7 @@ var opcodeTable = [...]opInfo{ }, { name: "CALLinter", - auxType: auxInt64, + auxType: auxCallOff, argLen: 2, clobberFlags: true, call: true, @@ -26508,7 +26508,7 @@ var opcodeTable = [...]opInfo{ }, { name: "CALLclosure", - auxType: auxInt64, + auxType: auxCallOff, argLen: 3, clobberFlags: true, call: true, @@ -26522,7 +26522,7 @@ var opcodeTable = [...]opInfo{ }, { name: "CALLinter", - auxType: auxInt64, + auxType: auxCallOff, argLen: 2, clobberFlags: true, call: true, @@ -27790,7 +27790,7 @@ var opcodeTable = [...]opInfo{ }, { name: "CALLclosure", - auxType: auxInt64, + auxType: auxCallOff, argLen: 3, call: true, reg: regInfo{ @@ -27803,7 +27803,7 @@ var opcodeTable = [...]opInfo{ }, { name: "CALLinter", - auxType: auxInt64, + auxType: auxCallOff, argLen: 2, call: true, reg: regInfo{ @@ -31388,7 +31388,7 @@ var opcodeTable = [...]opInfo{ }, { name: "CALLclosure", - auxType: auxInt64, + auxType: auxCallOff, argLen: 3, clobberFlags: true, call: true, @@ -31402,7 +31402,7 @@ var opcodeTable = [...]opInfo{ }, { name: "CALLinter", - auxType: auxInt64, + auxType: auxCallOff, argLen: 2, clobberFlags: true, call: true, @@ -32032,7 +32032,7 @@ var opcodeTable = [...]opInfo{ }, { name: "LoweredClosureCall", - auxType: auxInt64, + auxType: auxCallOff, argLen: 3, call: true, reg: regInfo{ @@ -32045,7 +32045,7 @@ var opcodeTable = [...]opInfo{ }, { name: "LoweredInterCall", - auxType: auxInt64, + auxType: auxCallOff, argLen: 2, call: true, reg: regInfo{ @@ -34763,7 +34763,7 @@ var opcodeTable = [...]opInfo{ }, { name: "ClosureCall", - auxType: auxInt64, + auxType: auxCallOff, argLen: 3, call: true, generic: true, @@ -34777,7 +34777,7 @@ var opcodeTable = [...]opInfo{ }, { name: "InterCall", - auxType: auxInt64, + auxType: auxCallOff, argLen: 2, call: true, generic: true, diff --git a/src/cmd/compile/internal/ssa/rewrite.go b/src/cmd/compile/internal/ssa/rewrite.go index 8195d407e0..eb371ce38b 100644 --- a/src/cmd/compile/internal/ssa/rewrite.go +++ b/src/cmd/compile/internal/ssa/rewrite.go @@ -760,7 +760,7 @@ func devirt(v *Value, sym Sym, offset int64) *AuxCall { if lsym == nil { return nil } - return &AuxCall{Fn: lsym} + return StaticAuxCall(lsym) } // isSamePtr reports whether p1 and p2 point to the same address. diff --git a/src/cmd/compile/internal/ssa/rewritegeneric.go b/src/cmd/compile/internal/ssa/rewritegeneric.go index 4b388a68cd..1ecfabf7cb 100644 --- a/src/cmd/compile/internal/ssa/rewritegeneric.go +++ b/src/cmd/compile/internal/ssa/rewritegeneric.go @@ -8483,7 +8483,7 @@ func rewriteValuegeneric_OpInterCall(v *Value) bool { // cond: devirt(v, itab, off) != nil // result: (StaticCall [int32(argsize)] {devirt(v, itab, off)} mem) for { - argsize := auxIntToInt64(v.AuxInt) + argsize := auxIntToInt32(v.AuxInt) if v_0.Op != OpLoad { break } diff --git a/src/cmd/compile/internal/ssa/writebarrier.go b/src/cmd/compile/internal/ssa/writebarrier.go index c358406862..4322a85c90 100644 --- a/src/cmd/compile/internal/ssa/writebarrier.go +++ b/src/cmd/compile/internal/ssa/writebarrier.go @@ -523,7 +523,7 @@ func wbcall(pos src.XPos, b *Block, fn, typ *obj.LSym, ptr, val, mem, sp, sb *Va off = round(off, config.PtrSize) // issue call - mem = b.NewValue1A(pos, OpStaticCall, types.TypeMem, &AuxCall{fn}, mem) + mem = b.NewValue1A(pos, OpStaticCall, types.TypeMem, StaticAuxCall(fn), mem) mem.AuxInt = off - config.ctxt.FixedFrameSize() return mem } -- cgit v1.3 From acde81e0a9c17ea23a6fc545b40bfabc80133f78 Mon Sep 17 00:00:00 2001 From: David Chase Date: Fri, 19 Jun 2020 15:29:51 -0400 Subject: cmd/compile: initialize ACArgs and ACResults AuxCall fields for static and interface calls. Extend use of AuxCall Change-Id: I68b6d9bad09506532e1415fd70d44cf6c15b4b93 Reviewed-on: https://go-review.googlesource.com/c/go/+/239081 Trust: David Chase Run-TryBot: David Chase TryBot-Result: Go Bot Reviewed-by: Cherry Zhang --- src/cmd/compile/internal/gc/ssa.go | 53 ++++++++++++++++++----- src/cmd/compile/internal/ssa/gen/generic.rules | 4 +- src/cmd/compile/internal/ssa/loopreschedchecks.go | 2 +- src/cmd/compile/internal/ssa/op.go | 50 ++++++++++++++++++--- src/cmd/compile/internal/ssa/rewrite.go | 5 ++- src/cmd/compile/internal/ssa/rewritegeneric.go | 11 ++--- src/cmd/compile/internal/ssa/writebarrier.go | 6 ++- 7 files changed, 102 insertions(+), 29 deletions(-) (limited to 'src/cmd/compile/internal') diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go index 542b1b51c2..6c0b027c17 100644 --- a/src/cmd/compile/internal/gc/ssa.go +++ b/src/cmd/compile/internal/gc/ssa.go @@ -4280,16 +4280,20 @@ func (s *state) openDeferExit() { argStart := Ctxt.FixedFrameSize() fn := r.n.Left stksize := fn.Type.ArgWidth() + var ACArgs []ssa.Param + var ACResults []ssa.Param if r.rcvr != nil { // rcvr in case of OCALLINTER v := s.load(r.rcvr.Type.Elem(), r.rcvr) addr := s.constOffPtrSP(s.f.Config.Types.UintptrPtr, argStart) + ACArgs = append(ACArgs, ssa.Param{Type: types.Types[TUINTPTR], Offset: int32(argStart)}) s.store(types.Types[TUINTPTR], addr, v) } for j, argAddrVal := range r.argVals { f := getParam(r.n, j) pt := types.NewPtr(f.Type) addr := s.constOffPtrSP(pt, argStart+f.Offset) + ACArgs = append(ACArgs, ssa.Param{Type: types.Types[TUINTPTR], Offset: int32(argStart + f.Offset)}) if !canSSAType(f.Type) { s.move(f.Type, addr, argAddrVal) } else { @@ -4305,7 +4309,7 @@ func (s *state) openDeferExit() { call = s.newValue3A(ssa.OpClosureCall, types.TypeMem, ssa.ClosureAuxCall(), codeptr, v, s.mem()) } else { // Do a static call if the original call was a static function or method - call = s.newValue1A(ssa.OpStaticCall, types.TypeMem, ssa.StaticAuxCall(fn.Sym.Linksym()), s.mem()) + call = s.newValue1A(ssa.OpStaticCall, types.TypeMem, ssa.StaticAuxCall(fn.Sym.Linksym(), ACArgs, ACResults), s.mem()) } call.AuxInt = stksize s.vars[&memVar] = call @@ -4340,6 +4344,17 @@ func (s *state) call(n *Node, k callKind) *ssa.Value { var codeptr *ssa.Value // ptr to target code (if dynamic) var rcvr *ssa.Value // receiver to set fn := n.Left + var ACArgs []ssa.Param + var ACResults []ssa.Param + res := n.Left.Type.Results() + if k == callNormal { + nf := res.NumFields() + for i := 0; i < nf; i++ { + fp := res.Field(i) + ACResults = append(ACResults, ssa.Param{Type: fp.Type, Offset: int32(fp.Offset + Ctxt.FixedFrameSize())}) + } + } + switch n.Op { case OCALLFUNC: if k == callNormal && fn.Op == ONAME && fn.Class() == PFUNC { @@ -4437,10 +4452,12 @@ func (s *state) call(n *Node, k callKind) *ssa.Value { // Call runtime.deferprocStack with pointer to _defer record. arg0 := s.constOffPtrSP(types.Types[TUINTPTR], Ctxt.FixedFrameSize()) s.store(types.Types[TUINTPTR], arg0, addr) - call = s.newValue1A(ssa.OpStaticCall, types.TypeMem, ssa.StaticAuxCall(deferprocStack), s.mem()) + ACArgs = append(ACArgs, ssa.Param{Type: types.Types[TUINTPTR], Offset: int32(Ctxt.FixedFrameSize())}) + call = s.newValue1A(ssa.OpStaticCall, types.TypeMem, ssa.StaticAuxCall(deferprocStack, ACArgs, ACResults), s.mem()) if stksize < int64(Widthptr) { // We need room for both the call to deferprocStack and the call to // the deferred function. + // TODO Revisit this if/when we pass args in registers. stksize = int64(Widthptr) } call.AuxInt = stksize @@ -4453,8 +4470,10 @@ func (s *state) call(n *Node, k callKind) *ssa.Value { // Write argsize and closure (args to newproc/deferproc). argsize := s.constInt32(types.Types[TUINT32], int32(stksize)) addr := s.constOffPtrSP(s.f.Config.Types.UInt32Ptr, argStart) + ACArgs = append(ACArgs, ssa.Param{Type: types.Types[TUINT32], Offset: int32(argStart)}) s.store(types.Types[TUINT32], addr, argsize) addr = s.constOffPtrSP(s.f.Config.Types.UintptrPtr, argStart+int64(Widthptr)) + ACArgs = append(ACArgs, ssa.Param{Type: types.Types[TUINTPTR], Offset: int32(argStart) + int32(Widthptr)}) s.store(types.Types[TUINTPTR], addr, closure) stksize += 2 * int64(Widthptr) argStart += 2 * int64(Widthptr) @@ -4463,6 +4482,7 @@ func (s *state) call(n *Node, k callKind) *ssa.Value { // Set receiver (for interface calls). if rcvr != nil { addr := s.constOffPtrSP(s.f.Config.Types.UintptrPtr, argStart) + ACArgs = append(ACArgs, ssa.Param{Type: types.Types[TUINTPTR], Offset: int32(argStart)}) s.store(types.Types[TUINTPTR], addr, rcvr) } @@ -4471,20 +4491,20 @@ func (s *state) call(n *Node, k callKind) *ssa.Value { args := n.Rlist.Slice() if n.Op == OCALLMETH { f := t.Recv() - s.storeArg(args[0], f.Type, argStart+f.Offset) + ACArgs = append(ACArgs, s.storeArg(args[0], f.Type, argStart+f.Offset)) args = args[1:] } for i, n := range args { f := t.Params().Field(i) - s.storeArg(n, f.Type, argStart+f.Offset) + ACArgs = append(ACArgs, s.storeArg(n, f.Type, argStart+f.Offset)) } // call target switch { case k == callDefer: - call = s.newValue1A(ssa.OpStaticCall, types.TypeMem, ssa.StaticAuxCall(deferproc), s.mem()) + call = s.newValue1A(ssa.OpStaticCall, types.TypeMem, ssa.StaticAuxCall(deferproc, ACArgs, ACResults), s.mem()) case k == callGo: - call = s.newValue1A(ssa.OpStaticCall, types.TypeMem, ssa.StaticAuxCall(newproc), s.mem()) + call = s.newValue1A(ssa.OpStaticCall, types.TypeMem, ssa.StaticAuxCall(newproc, ACArgs, ACResults), s.mem()) case closure != nil: // rawLoad because loading the code pointer from a // closure is always safe, but IsSanitizerSafeAddr @@ -4494,9 +4514,9 @@ func (s *state) call(n *Node, k callKind) *ssa.Value { codeptr = s.rawLoad(types.Types[TUINTPTR], closure) call = s.newValue3A(ssa.OpClosureCall, types.TypeMem, ssa.ClosureAuxCall(), codeptr, closure, s.mem()) case codeptr != nil: - call = s.newValue2A(ssa.OpInterCall, types.TypeMem, ssa.InterfaceAuxCall(), codeptr, s.mem()) + call = s.newValue2A(ssa.OpInterCall, types.TypeMem, ssa.InterfaceAuxCall(ACArgs, ACResults), codeptr, s.mem()) case sym != nil: - call = s.newValue1A(ssa.OpStaticCall, types.TypeMem, ssa.StaticAuxCall(sym.Linksym()), s.mem()) + call = s.newValue1A(ssa.OpStaticCall, types.TypeMem, ssa.StaticAuxCall(sym.Linksym(), ACArgs, ACResults), s.mem()) default: s.Fatalf("bad call type %v %v", n.Op, n) } @@ -4522,7 +4542,6 @@ func (s *state) call(n *Node, k callKind) *ssa.Value { s.startBlock(bNext) } - res := n.Left.Type.Results() if res.NumFields() == 0 || k != callNormal { // call has no return value. Continue with the next statement. return nil @@ -4918,18 +4937,29 @@ func (s *state) intDivide(n *Node, a, b *ssa.Value) *ssa.Value { func (s *state) rtcall(fn *obj.LSym, returns bool, results []*types.Type, args ...*ssa.Value) []*ssa.Value { // Write args to the stack off := Ctxt.FixedFrameSize() + var ACArgs []ssa.Param + var ACResults []ssa.Param for _, arg := range args { t := arg.Type off = Rnd(off, t.Alignment()) ptr := s.constOffPtrSP(t.PtrTo(), off) size := t.Size() + ACArgs = append(ACArgs, ssa.Param{Type: t, Offset: int32(off)}) s.store(t, ptr, arg) off += size } off = Rnd(off, int64(Widthreg)) + // Accumulate results types and offsets + offR := off + for _, t := range results { + offR = Rnd(offR, t.Alignment()) + ACResults = append(ACResults, ssa.Param{Type: t, Offset: int32(offR)}) + offR += t.Size() + } + // Issue call - call := s.newValue1A(ssa.OpStaticCall, types.TypeMem, ssa.StaticAuxCall(fn), s.mem()) + call := s.newValue1A(ssa.OpStaticCall, types.TypeMem, ssa.StaticAuxCall(fn, ACArgs, ACResults), s.mem()) s.vars[&memVar] = call if !returns { @@ -5064,8 +5094,9 @@ func (s *state) storeTypePtrs(t *types.Type, left, right *ssa.Value) { } } -func (s *state) storeArg(n *Node, t *types.Type, off int64) { +func (s *state) storeArg(n *Node, t *types.Type, off int64) ssa.Param { s.storeArgWithBase(n, t, s.sp, off) + return ssa.Param{Type: t, Offset: int32(off)} } func (s *state) storeArgWithBase(n *Node, t *types.Type, base *ssa.Value, off int64) { diff --git a/src/cmd/compile/internal/ssa/gen/generic.rules b/src/cmd/compile/internal/ssa/gen/generic.rules index df70838aa9..39f8cc8889 100644 --- a/src/cmd/compile/internal/ssa/gen/generic.rules +++ b/src/cmd/compile/internal/ssa/gen/generic.rules @@ -2021,8 +2021,8 @@ // Note that (ITab (IMake)) doesn't get // rewritten until after the first opt pass, // so this rule should trigger reliably. -(InterCall [argsize] (Load (OffPtr [off] (ITab (IMake (Addr {itab} (SB)) _))) _) mem) && devirt(v, itab, off) != nil => - (StaticCall [int32(argsize)] {devirt(v, itab, off)} mem) +(InterCall [argsize] {auxCall} (Load (OffPtr [off] (ITab (IMake (Addr {itab} (SB)) _))) _) mem) && devirt(v, auxCall, itab, off) != nil => + (StaticCall [int32(argsize)] {devirt(v, auxCall, itab, off)} mem) // Move and Zero optimizations. // Move source and destination may overlap. diff --git a/src/cmd/compile/internal/ssa/loopreschedchecks.go b/src/cmd/compile/internal/ssa/loopreschedchecks.go index ebd23b34c7..9c73bcff26 100644 --- a/src/cmd/compile/internal/ssa/loopreschedchecks.go +++ b/src/cmd/compile/internal/ssa/loopreschedchecks.go @@ -246,7 +246,7 @@ func insertLoopReschedChecks(f *Func) { // mem1 := call resched (mem0) // goto header resched := f.fe.Syslook("goschedguarded") - mem1 := sched.NewValue1A(bb.Pos, OpStaticCall, types.TypeMem, StaticAuxCall(resched), mem0) + mem1 := sched.NewValue1A(bb.Pos, OpStaticCall, types.TypeMem, StaticAuxCall(resched, nil, nil), mem0) sched.AddEdgeTo(h) headerMemPhi.AddArg(mem1) diff --git a/src/cmd/compile/internal/ssa/op.go b/src/cmd/compile/internal/ssa/op.go index c498a288a1..f94399028a 100644 --- a/src/cmd/compile/internal/ssa/op.go +++ b/src/cmd/compile/internal/ssa/op.go @@ -5,6 +5,7 @@ package ssa import ( + "cmd/compile/internal/types" "cmd/internal/obj" "fmt" ) @@ -67,25 +68,60 @@ type regInfo struct { type auxType int8 +type Param struct { + Type *types.Type + Offset int32 // TODO someday this will be a register +} + type AuxCall struct { - Fn *obj.LSym + Fn *obj.LSym + args []Param // Includes receiver for method calls. Does NOT include hidden closure pointer. + results []Param } func (a *AuxCall) String() string { + var fn string if a.Fn == nil { - return "AuxCall(nil)" + fn = "AuxCall{nil" // could be interface/closure etc. + } else { + fn = fmt.Sprintf("AuxCall{%v", a.Fn) + } + + if len(a.args) == 0 { + fn += "()" + } else { + s := "(" + for _, arg := range a.args { + fn += fmt.Sprintf("%s[%v,%v]", s, arg.Type, arg.Offset) + s = "," + } + fn += ")" } - return fmt.Sprintf("AuxCall(%v)", a.Fn) + + if len(a.results) > 0 { // usual is zero or one; only some RT calls have more than one. + if len(a.results) == 1 { + fn += fmt.Sprintf("[%v,%v]", a.results[0].Type, a.results[0].Offset) + } else { + s := "(" + for _, result := range a.results { + fn += fmt.Sprintf("%s[%v,%v]", s, result.Type, result.Offset) + s = "," + } + fn += ")" + } + } + + return fn + "}" } // StaticAuxCall returns an AuxCall for a static call. -func StaticAuxCall(sym *obj.LSym) *AuxCall { - return &AuxCall{Fn: sym} +func StaticAuxCall(sym *obj.LSym, args []Param, results []Param) *AuxCall { + return &AuxCall{Fn: sym, args: args, results: results} } // InterfaceAuxCall returns an AuxCall for an interface call. -func InterfaceAuxCall() *AuxCall { - return &AuxCall{} +func InterfaceAuxCall(args []Param, results []Param) *AuxCall { + return &AuxCall{Fn: nil, args: args, results: results} } // ClosureAuxCall returns an AuxCall for a closure call. diff --git a/src/cmd/compile/internal/ssa/rewrite.go b/src/cmd/compile/internal/ssa/rewrite.go index eb371ce38b..2ab310ad85 100644 --- a/src/cmd/compile/internal/ssa/rewrite.go +++ b/src/cmd/compile/internal/ssa/rewrite.go @@ -743,7 +743,7 @@ func uaddOvf(a, b int64) bool { // de-virtualize an InterCall // 'sym' is the symbol for the itab -func devirt(v *Value, sym Sym, offset int64) *AuxCall { +func devirt(v *Value, aux interface{}, sym Sym, offset int64) *AuxCall { f := v.Block.Func n, ok := sym.(*obj.LSym) if !ok { @@ -760,7 +760,8 @@ func devirt(v *Value, sym Sym, offset int64) *AuxCall { if lsym == nil { return nil } - return StaticAuxCall(lsym) + va := aux.(*AuxCall) + return StaticAuxCall(lsym, va.args, va.results) } // isSamePtr reports whether p1 and p2 point to the same address. diff --git a/src/cmd/compile/internal/ssa/rewritegeneric.go b/src/cmd/compile/internal/ssa/rewritegeneric.go index 1ecfabf7cb..925ff53fd1 100644 --- a/src/cmd/compile/internal/ssa/rewritegeneric.go +++ b/src/cmd/compile/internal/ssa/rewritegeneric.go @@ -8479,11 +8479,12 @@ func rewriteValuegeneric_OpIMake(v *Value) bool { func rewriteValuegeneric_OpInterCall(v *Value) bool { v_1 := v.Args[1] v_0 := v.Args[0] - // match: (InterCall [argsize] (Load (OffPtr [off] (ITab (IMake (Addr {itab} (SB)) _))) _) mem) - // cond: devirt(v, itab, off) != nil - // result: (StaticCall [int32(argsize)] {devirt(v, itab, off)} mem) + // match: (InterCall [argsize] {auxCall} (Load (OffPtr [off] (ITab (IMake (Addr {itab} (SB)) _))) _) mem) + // cond: devirt(v, auxCall, itab, off) != nil + // result: (StaticCall [int32(argsize)] {devirt(v, auxCall, itab, off)} mem) for { argsize := auxIntToInt32(v.AuxInt) + auxCall := auxToCall(v.Aux) if v_0.Op != OpLoad { break } @@ -8510,12 +8511,12 @@ func rewriteValuegeneric_OpInterCall(v *Value) bool { break } mem := v_1 - if !(devirt(v, itab, off) != nil) { + if !(devirt(v, auxCall, itab, off) != nil) { break } v.reset(OpStaticCall) v.AuxInt = int32ToAuxInt(int32(argsize)) - v.Aux = callToAux(devirt(v, itab, off)) + v.Aux = callToAux(devirt(v, auxCall, itab, off)) v.AddArg(mem) return true } diff --git a/src/cmd/compile/internal/ssa/writebarrier.go b/src/cmd/compile/internal/ssa/writebarrier.go index 4322a85c90..7cc8bf7af9 100644 --- a/src/cmd/compile/internal/ssa/writebarrier.go +++ b/src/cmd/compile/internal/ssa/writebarrier.go @@ -501,29 +501,33 @@ func wbcall(pos src.XPos, b *Block, fn, typ *obj.LSym, ptr, val, mem, sp, sb *Va // put arguments on stack off := config.ctxt.FixedFrameSize() + var ACArgs []Param if typ != nil { // for typedmemmove taddr := b.NewValue1A(pos, OpAddr, b.Func.Config.Types.Uintptr, typ, sb) off = round(off, taddr.Type.Alignment()) arg := b.NewValue1I(pos, OpOffPtr, taddr.Type.PtrTo(), off, sp) mem = b.NewValue3A(pos, OpStore, types.TypeMem, ptr.Type, arg, taddr, mem) + ACArgs = append(ACArgs, Param{Type: b.Func.Config.Types.Uintptr, Offset: int32(off)}) off += taddr.Type.Size() } off = round(off, ptr.Type.Alignment()) arg := b.NewValue1I(pos, OpOffPtr, ptr.Type.PtrTo(), off, sp) mem = b.NewValue3A(pos, OpStore, types.TypeMem, ptr.Type, arg, ptr, mem) + ACArgs = append(ACArgs, Param{Type: ptr.Type, Offset: int32(off)}) off += ptr.Type.Size() if val != nil { off = round(off, val.Type.Alignment()) arg = b.NewValue1I(pos, OpOffPtr, val.Type.PtrTo(), off, sp) mem = b.NewValue3A(pos, OpStore, types.TypeMem, val.Type, arg, val, mem) + ACArgs = append(ACArgs, Param{Type: val.Type, Offset: int32(off)}) off += val.Type.Size() } off = round(off, config.PtrSize) // issue call - mem = b.NewValue1A(pos, OpStaticCall, types.TypeMem, StaticAuxCall(fn), mem) + mem = b.NewValue1A(pos, OpStaticCall, types.TypeMem, StaticAuxCall(fn, ACArgs, nil), mem) mem.AuxInt = off - config.ctxt.FixedFrameSize() return mem } -- cgit v1.3 From 39da81da5e35e50da74ebb8c4fe12fd363bf41b9 Mon Sep 17 00:00:00 2001 From: David Chase Date: Wed, 24 Jun 2020 17:00:48 -0400 Subject: cmd/compile: populate AuxCall fields for OpClosureCall Change-Id: Ib5f62826d5249c1727b57d9f8ff2f3a1d6dc5032 Reviewed-on: https://go-review.googlesource.com/c/go/+/240185 Trust: David Chase Run-TryBot: David Chase TryBot-Result: Go Bot Reviewed-by: Cherry Zhang --- src/cmd/compile/internal/gc/ssa.go | 4 ++-- src/cmd/compile/internal/ssa/op.go | 8 ++++++-- 2 files changed, 8 insertions(+), 4 deletions(-) (limited to 'src/cmd/compile/internal') diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go index 6c0b027c17..75fdbbae04 100644 --- a/src/cmd/compile/internal/gc/ssa.go +++ b/src/cmd/compile/internal/gc/ssa.go @@ -4306,7 +4306,7 @@ func (s *state) openDeferExit() { v := s.load(r.closure.Type.Elem(), r.closure) s.maybeNilCheckClosure(v, callDefer) codeptr := s.rawLoad(types.Types[TUINTPTR], v) - call = s.newValue3A(ssa.OpClosureCall, types.TypeMem, ssa.ClosureAuxCall(), codeptr, v, s.mem()) + call = s.newValue3A(ssa.OpClosureCall, types.TypeMem, ssa.ClosureAuxCall(ACArgs, ACResults), codeptr, v, s.mem()) } else { // Do a static call if the original call was a static function or method call = s.newValue1A(ssa.OpStaticCall, types.TypeMem, ssa.StaticAuxCall(fn.Sym.Linksym(), ACArgs, ACResults), s.mem()) @@ -4512,7 +4512,7 @@ func (s *state) call(n *Node, k callKind) *ssa.Value { // critical that we not clobber any arguments already // stored onto the stack. codeptr = s.rawLoad(types.Types[TUINTPTR], closure) - call = s.newValue3A(ssa.OpClosureCall, types.TypeMem, ssa.ClosureAuxCall(), codeptr, closure, s.mem()) + call = s.newValue3A(ssa.OpClosureCall, types.TypeMem, ssa.ClosureAuxCall(ACArgs, ACResults), codeptr, closure, s.mem()) case codeptr != nil: call = s.newValue2A(ssa.OpInterCall, types.TypeMem, ssa.InterfaceAuxCall(ACArgs, ACResults), codeptr, s.mem()) case sym != nil: diff --git a/src/cmd/compile/internal/ssa/op.go b/src/cmd/compile/internal/ssa/op.go index f94399028a..02ecdef5e6 100644 --- a/src/cmd/compile/internal/ssa/op.go +++ b/src/cmd/compile/internal/ssa/op.go @@ -79,6 +79,10 @@ type AuxCall struct { results []Param } +// String returns +// "AuxCall{()}" if len(results) == 0; +// "AuxCall{()}" if len(results) == 1; +// "AuxCall{()()}" otherwise. func (a *AuxCall) String() string { var fn string if a.Fn == nil { @@ -125,8 +129,8 @@ func InterfaceAuxCall(args []Param, results []Param) *AuxCall { } // ClosureAuxCall returns an AuxCall for a closure call. -func ClosureAuxCall() *AuxCall { - return &AuxCall{} +func ClosureAuxCall(args []Param, results []Param) *AuxCall { + return &AuxCall{Fn: nil, args: args, results: results} } const ( -- cgit v1.3 From 396688af7ee121d478e9b8d2cc9d06999ba7fc6e Mon Sep 17 00:00:00 2001 From: David Chase Date: Fri, 26 Jun 2020 18:19:01 -0400 Subject: cmd/compile: make translation to calls for SSA look more "value-oriented" The existing translation assumes an in-memory return values, thus it returns the address of the result(s). Most consumers immediately load from the address to get the value, and in late call expansion that is the favored idiom, and it is also the favored idiom when arguments and results use registers instead of memory. Change-Id: Ie0ccc70f399682a42509d847b330ef3956462d56 Reviewed-on: https://go-review.googlesource.com/c/go/+/240186 Trust: David Chase Run-TryBot: David Chase TryBot-Result: Go Bot Reviewed-by: Cherry Zhang --- src/cmd/compile/internal/gc/ssa.go | 44 +++++++++++++++++++++----------------- 1 file changed, 24 insertions(+), 20 deletions(-) (limited to 'src/cmd/compile/internal') diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go index 75fdbbae04..c59945f206 100644 --- a/src/cmd/compile/internal/gc/ssa.go +++ b/src/cmd/compile/internal/gc/ssa.go @@ -1076,7 +1076,7 @@ func (s *state) stmt(n *Node) { fallthrough case OCALLMETH, OCALLINTER: - s.call(n, callNormal) + s.callAddr(n, callNormal) if n.Op == OCALLFUNC && n.Left.Op == ONAME && n.Left.Class() == PFUNC { if fn := n.Left.Sym.Name; compiling_runtime && fn == "throw" || n.Left.Sym.Pkg == Runtimepkg && (fn == "throwinit" || fn == "gopanic" || fn == "panicwrap" || fn == "block" || fn == "panicmakeslicelen" || fn == "panicmakeslicecap") { @@ -1108,10 +1108,10 @@ func (s *state) stmt(n *Node) { if n.Esc == EscNever { d = callDeferStack } - s.call(n.Left, d) + s.callAddr(n.Left, d) } case OGO: - s.call(n.Left, callGo) + s.callAddr(n.Left, callGo) case OAS2DOTTYPE: res, resok := s.dottype(n.Right, true) @@ -2715,8 +2715,7 @@ func (s *state) expr(n *Node) *ssa.Value { fallthrough case OCALLINTER, OCALLMETH: - a := s.call(n, callNormal) - return s.load(n.Type, a) + return s.callResult(n, callNormal) case OGETG: return s.newValue1(ssa.OpGetG, n.Type, s.mem()) @@ -3589,8 +3588,7 @@ func init() { addF("math", "FMA", func(s *state, n *Node, args []*ssa.Value) *ssa.Value { if !s.config.UseFMA { - a := s.call(n, callNormal) - s.vars[n] = s.load(types.Types[TFLOAT64], a) + s.vars[n] = s.callResult(n, callNormal) // types.Types[TFLOAT64] return s.variable(n, types.Types[TFLOAT64]) } v := s.entryNewValue0A(ssa.OpHasCPUFeature, types.Types[TBOOL], x86HasFMA) @@ -3611,8 +3609,7 @@ func init() { // Call the pure Go version. s.startBlock(bFalse) - a := s.call(n, callNormal) - s.vars[n] = s.load(types.Types[TFLOAT64], a) + s.vars[n] = s.callResult(n, callNormal) // types.Types[TFLOAT64] s.endBlock().AddEdgeTo(bEnd) // Merge results. @@ -3623,8 +3620,7 @@ func init() { addF("math", "FMA", func(s *state, n *Node, args []*ssa.Value) *ssa.Value { if !s.config.UseFMA { - a := s.call(n, callNormal) - s.vars[n] = s.load(types.Types[TFLOAT64], a) + s.vars[n] = s.callResult(n, callNormal) // types.Types[TFLOAT64] return s.variable(n, types.Types[TFLOAT64]) } addr := s.entryNewValue1A(ssa.OpAddr, types.Types[TBOOL].PtrTo(), armHasVFPv4, s.sb) @@ -3646,8 +3642,7 @@ func init() { // Call the pure Go version. s.startBlock(bFalse) - a := s.call(n, callNormal) - s.vars[n] = s.load(types.Types[TFLOAT64], a) + s.vars[n] = s.callResult(n, callNormal) // types.Types[TFLOAT64] s.endBlock().AddEdgeTo(bEnd) // Merge results. @@ -3676,8 +3671,7 @@ func init() { // Call the pure Go version. s.startBlock(bFalse) - a := s.call(n, callNormal) - s.vars[n] = s.load(types.Types[TFLOAT64], a) + s.vars[n] = s.callResult(n, callNormal) // types.Types[TFLOAT64] s.endBlock().AddEdgeTo(bEnd) // Merge results. @@ -3887,8 +3881,7 @@ func init() { // Call the pure Go version. s.startBlock(bFalse) - a := s.call(n, callNormal) - s.vars[n] = s.load(types.Types[TINT], a) + s.vars[n] = s.callResult(n, callNormal) // types.Types[TINT] s.endBlock().AddEdgeTo(bEnd) // Merge results. @@ -4336,9 +4329,17 @@ func (s *state) openDeferExit() { } } +func (s *state) callResult(n *Node, k callKind) *ssa.Value { + return s.call(n, k, false) +} + +func (s *state) callAddr(n *Node, k callKind) *ssa.Value { + return s.call(n, k, true) +} + // Calls the function n using the specified call type. // Returns the address of the return value (or nil if none). -func (s *state) call(n *Node, k callKind) *ssa.Value { +func (s *state) call(n *Node, k callKind, returnResultAddr bool) *ssa.Value { var sym *types.Sym // target symbol (if static) var closure *ssa.Value // ptr to closure to run (if dynamic) var codeptr *ssa.Value // ptr to target code (if dynamic) @@ -4547,7 +4548,10 @@ func (s *state) call(n *Node, k callKind) *ssa.Value { return nil } fp := res.Field(0) - return s.constOffPtrSP(types.NewPtr(fp.Type), fp.Offset+Ctxt.FixedFrameSize()) + if returnResultAddr { + return s.constOffPtrSP(types.NewPtr(fp.Type), fp.Offset+Ctxt.FixedFrameSize()) + } + return s.load(n.Type, s.constOffPtrSP(types.NewPtr(fp.Type), fp.Offset+Ctxt.FixedFrameSize())) } // maybeNilCheckClosure checks if a nil check of a closure is needed in some @@ -4676,7 +4680,7 @@ func (s *state) addr(n *Node) *ssa.Value { addr := s.addr(n.Left) return s.newValue1(ssa.OpCopy, t, addr) // ensure that addr has the right type case OCALLFUNC, OCALLINTER, OCALLMETH: - return s.call(n, callNormal) + return s.callAddr(n, callNormal) case ODOTTYPE: v, _ := s.dottype(n, false) if v.Op != ssa.OpLoad { -- cgit v1.3 From f5d59d0e382dc59195537a128fe9423a49a4cea8 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Wed, 16 Sep 2020 15:41:47 -0700 Subject: cmd/compile: skip looking for OCLOSURE nodes in xtop xtop holds package's top-level declaration statements, but OCLOSURE only appears in expression contexts. xtop will instead hold the synthetic ODCLFUNC representing OCLOSURE's function body. This CL makes the loop consistent with the later phases that only look for ODCLFUNC nodes in xtop. Passes toolstash-check. Change-Id: I852a10ef1bf75bb3351e3da0357ca8b2e26aec6e Reviewed-on: https://go-review.googlesource.com/c/go/+/255340 Trust: Matthew Dempsky Run-TryBot: Matthew Dempsky Reviewed-by: Cuong Manh Le TryBot-Result: Go Bot --- src/cmd/compile/internal/gc/main.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/cmd/compile/internal') diff --git a/src/cmd/compile/internal/gc/main.go b/src/cmd/compile/internal/gc/main.go index 8783cb4e46..7ad3bfe0c8 100644 --- a/src/cmd/compile/internal/gc/main.go +++ b/src/cmd/compile/internal/gc/main.go @@ -617,7 +617,7 @@ func Main(archInit func(*Arch)) { var fcount int64 for i := 0; i < len(xtop); i++ { n := xtop[i] - if op := n.Op; op == ODCLFUNC || op == OCLOSURE { + if n.Op == ODCLFUNC { Curfn = n decldepth = 1 saveerrors() -- cgit v1.3 From 967465da2975fe4322080703ce5a77ea90752829 Mon Sep 17 00:00:00 2001 From: Lynn Boger Date: Mon, 31 Aug 2020 09:43:40 -0400 Subject: cmd/compile: use combined shifts to improve array addressing on ppc64x MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This change adds rules to find pairs of instructions that can be combined into a single shifts. These instruction sequences are common in array addressing within loops. Improvements can be seen in many crypto packages and the hash packages. These are based on the extended mnemonics found in the ISA sections C.8.1 and C.8.2. Some rules in PPC64.rules were moved because the ordering prevented some matching. The following results were generated on power9. hash/crc32: CRC32/poly=Koopman/size=40/align=0 195ns ± 0% 163ns ± 0% -16.41% CRC32/poly=Koopman/size=40/align=1 200ns ± 0% 163ns ± 0% -18.50% CRC32/poly=Koopman/size=512/align=0 1.98µs ± 0% 1.67µs ± 0% -15.46% CRC32/poly=Koopman/size=512/align=1 1.98µs ± 0% 1.69µs ± 0% -14.80% CRC32/poly=Koopman/size=1kB/align=0 3.90µs ± 0% 3.31µs ± 0% -15.27% CRC32/poly=Koopman/size=1kB/align=1 3.85µs ± 0% 3.31µs ± 0% -14.15% CRC32/poly=Koopman/size=4kB/align=0 15.3µs ± 0% 13.1µs ± 0% -14.22% CRC32/poly=Koopman/size=4kB/align=1 15.4µs ± 0% 13.1µs ± 0% -14.79% CRC32/poly=Koopman/size=32kB/align=0 137µs ± 0% 105µs ± 0% -23.56% CRC32/poly=Koopman/size=32kB/align=1 137µs ± 0% 105µs ± 0% -23.53% crypto/rc4: RC4_128 733ns ± 0% 650ns ± 0% -11.32% (p=1.000 n=1+1) RC4_1K 5.80µs ± 0% 5.17µs ± 0% -10.89% (p=1.000 n=1+1) RC4_8K 45.7µs ± 0% 40.8µs ± 0% -10.73% (p=1.000 n=1+1) crypto/sha1: Hash8Bytes 635ns ± 0% 613ns ± 0% -3.46% (p=1.000 n=1+1) Hash320Bytes 2.30µs ± 0% 2.18µs ± 0% -5.38% (p=1.000 n=1+1) Hash1K 5.88µs ± 0% 5.38µs ± 0% -8.62% (p=1.000 n=1+1) Hash8K 42.0µs ± 0% 37.9µs ± 0% -9.75% (p=1.000 n=1+1) There are other improvements found in golang.org/x/crypto which are all in the range of 5-15%. Change-Id: I193471fbcf674151ffe2edab212799d9b08dfb8c Reviewed-on: https://go-review.googlesource.com/c/go/+/252097 Trust: Lynn Boger Run-TryBot: Lynn Boger TryBot-Result: Go Bot Reviewed-by: Carlos Eduardo Seo --- src/cmd/asm/internal/asm/testdata/ppc64enc.s | 4 + src/cmd/compile/internal/ppc64/ssa.go | 36 ++ src/cmd/compile/internal/ssa/gen/PPC64.rules | 63 ++- src/cmd/compile/internal/ssa/gen/PPC64Ops.go | 5 + src/cmd/compile/internal/ssa/opGen.go | 45 ++ src/cmd/compile/internal/ssa/rewrite.go | 38 ++ src/cmd/compile/internal/ssa/rewritePPC64.go | 787 +++++++++++++++++++++++++++ src/cmd/internal/obj/ppc64/a.out.go | 4 + src/cmd/internal/obj/ppc64/anames.go | 4 + src/cmd/internal/obj/ppc64/asm9.go | 74 ++- test/codegen/shift.go | 55 ++ 11 files changed, 1087 insertions(+), 28 deletions(-) (limited to 'src/cmd/compile/internal') diff --git a/src/cmd/asm/internal/asm/testdata/ppc64enc.s b/src/cmd/asm/internal/asm/testdata/ppc64enc.s index 10a05ec402..e26f6f8933 100644 --- a/src/cmd/asm/internal/asm/testdata/ppc64enc.s +++ b/src/cmd/asm/internal/asm/testdata/ppc64enc.s @@ -284,6 +284,10 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$0 RLDICLCC $0, R4, $15, R6 // 788603c1 RLDICR $0, R4, $15, R6 // 788603c4 RLDICRCC $0, R4, $15, R6 // 788603c5 + RLDIC $0, R4, $15, R6 // 788603c8 + RLDICCC $0, R4, $15, R6 // 788603c9 + CLRLSLWI $16, R5, $8, R4 // 54a4861e + CLRLSLDI $2, R4, $24, R3 // 78831588 BEQ 0(PC) // 41820000 BGE 0(PC) // 40800000 diff --git a/src/cmd/compile/internal/ppc64/ssa.go b/src/cmd/compile/internal/ppc64/ssa.go index f8d9ac2379..4a83a0bdd7 100644 --- a/src/cmd/compile/internal/ppc64/ssa.go +++ b/src/cmd/compile/internal/ppc64/ssa.go @@ -565,6 +565,42 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) { p = s.Prog(obj.ANOP) gc.Patch(pbover, p) + case ssa.OpPPC64CLRLSLWI: + r := v.Reg() + r1 := v.Args[0].Reg() + shifts := v.AuxInt + p := s.Prog(v.Op.Asm()) + // clrlslwi ra,rs,sh,mb will become rlwinm ra,rs,sh,mb-sh,31-n as described in ISA + p.From = obj.Addr{Type: obj.TYPE_CONST, Offset: ssa.GetPPC64Shiftsh(shifts)} + p.SetFrom3(obj.Addr{Type: obj.TYPE_CONST, Offset: ssa.GetPPC64Shiftmb(shifts)}) + p.Reg = r1 + p.To.Type = obj.TYPE_REG + p.To.Reg = r + + case ssa.OpPPC64CLRLSLDI: + r := v.Reg() + r1 := v.Args[0].Reg() + shifts := v.AuxInt + p := s.Prog(v.Op.Asm()) + // clrlsldi ra,rs,sh,mb will become rldic ra,rs,sh,mb-sh + p.From = obj.Addr{Type: obj.TYPE_CONST, Offset: ssa.GetPPC64Shiftsh(shifts)} + p.SetFrom3(obj.Addr{Type: obj.TYPE_CONST, Offset: ssa.GetPPC64Shiftmb(shifts)}) + p.Reg = r1 + p.To.Type = obj.TYPE_REG + p.To.Reg = r + + // Mask has been set as sh + case ssa.OpPPC64RLDICL: + r := v.Reg() + r1 := v.Args[0].Reg() + shifts := v.AuxInt + p := s.Prog(v.Op.Asm()) + p.From = obj.Addr{Type: obj.TYPE_CONST, Offset: ssa.GetPPC64Shiftsh(shifts)} + p.SetFrom3(obj.Addr{Type: obj.TYPE_CONST, Offset: ssa.GetPPC64Shiftmb(shifts)}) + p.Reg = r1 + p.To.Type = obj.TYPE_REG + p.To.Reg = r + case ssa.OpPPC64ADD, ssa.OpPPC64FADD, ssa.OpPPC64FADDS, ssa.OpPPC64SUB, ssa.OpPPC64FSUB, ssa.OpPPC64FSUBS, ssa.OpPPC64MULLD, ssa.OpPPC64MULLW, ssa.OpPPC64DIVDU, ssa.OpPPC64DIVWU, ssa.OpPPC64SRAD, ssa.OpPPC64SRAW, ssa.OpPPC64SRD, ssa.OpPPC64SRW, ssa.OpPPC64SLD, ssa.OpPPC64SLW, diff --git a/src/cmd/compile/internal/ssa/gen/PPC64.rules b/src/cmd/compile/internal/ssa/gen/PPC64.rules index e5fb1e98c2..774d5096de 100644 --- a/src/cmd/compile/internal/ssa/gen/PPC64.rules +++ b/src/cmd/compile/internal/ssa/gen/PPC64.rules @@ -79,6 +79,23 @@ (Abs ...) => (FABS ...) (FMA ...) => (FMADD ...) +// Lowering extension +// Note: we always extend to 64 bits even though some ops don't need that many result bits. +(SignExt8to(16|32|64) ...) => (MOVBreg ...) +(SignExt16to(32|64) ...) => (MOVHreg ...) +(SignExt32to64 ...) => (MOVWreg ...) + +(ZeroExt8to(16|32|64) ...) => (MOVBZreg ...) +(ZeroExt16to(32|64) ...) => (MOVHZreg ...) +(ZeroExt32to64 ...) => (MOVWZreg ...) + +(Trunc(16|32|64)to8 x) && isSigned(t) => (MOVBreg x) +(Trunc(16|32|64)to8 x) => (MOVBZreg x) +(Trunc(32|64)to16 x) && isSigned(t) => (MOVHreg x) +(Trunc(32|64)to16 x) => (MOVHZreg x) +(Trunc64to32 x) && isSigned(t) => (MOVWreg x) +(Trunc64to32 x) => (MOVWZreg x) + // Lowering constants (Const(64|32|16|8) [val]) => (MOVDconst [int64(val)]) (Const(32|64)F ...) => (FMOV(S|D)const ...) @@ -780,6 +797,21 @@ (MOVWreg y:(MOVWZreg x)) => (MOVWreg x) (MOVWZreg y:(MOVWreg x)) => (MOVWZreg x) +// Truncate then logical then truncate: omit first, lesser or equal truncate +(MOVWZreg ((OR|XOR|AND) x (MOVWZreg y))) => (MOVWZreg ((OR|XOR|AND) x y)) +(MOVHZreg ((OR|XOR|AND) x (MOVWZreg y))) => (MOVHZreg ((OR|XOR|AND) x y)) +(MOVHZreg ((OR|XOR|AND) x (MOVHZreg y))) => (MOVHZreg ((OR|XOR|AND) x y)) +(MOVBZreg ((OR|XOR|AND) x (MOVWZreg y))) => (MOVBZreg ((OR|XOR|AND) x y)) +(MOVBZreg ((OR|XOR|AND) x (MOVHZreg y))) => (MOVBZreg ((OR|XOR|AND) x y)) +(MOVBZreg ((OR|XOR|AND) x (MOVBZreg y))) => (MOVBZreg ((OR|XOR|AND) x y)) + +(MOV(B|H|W)Zreg z:(ANDconst [c] (MOVBZload ptr x))) => z +(MOVBZreg z:(AND y (MOVBZload ptr x))) => z +(MOV(H|W)Zreg z:(ANDconst [c] (MOVHZload ptr x))) => z +(MOVHZreg z:(AND y (MOVHZload ptr x))) => z +(MOVWZreg z:(ANDconst [c] (MOVWZload ptr x))) => z +(MOVWZreg z:(AND y (MOVWZload ptr x))) => z + // Arithmetic constant ops (ADD x (MOVDconst [c])) && is32Bit(c) => (ADDconst [c] x) @@ -949,23 +981,6 @@ (AtomicAnd8 ...) => (LoweredAtomicAnd8 ...) (AtomicOr8 ...) => (LoweredAtomicOr8 ...) -// Lowering extension -// Note: we always extend to 64 bits even though some ops don't need that many result bits. -(SignExt8to(16|32|64) ...) => (MOVBreg ...) -(SignExt16to(32|64) ...) => (MOVHreg ...) -(SignExt32to64 ...) => (MOVWreg ...) - -(ZeroExt8to(16|32|64) ...) => (MOVBZreg ...) -(ZeroExt16to(32|64) ...) => (MOVHZreg ...) -(ZeroExt32to64 ...) => (MOVWZreg ...) - -(Trunc(16|32|64)to8 x) && isSigned(t) => (MOVBreg x) -(Trunc(16|32|64)to8 x) => (MOVBZreg x) -(Trunc(32|64)to16 x) && isSigned(t) => (MOVHreg x) -(Trunc(32|64)to16 x) => (MOVHZreg x) -(Trunc64to32 x) && isSigned(t) => (MOVWreg x) -(Trunc64to32 x) => (MOVWZreg x) - (Slicemask x) => (SRADconst (NEG x) [63]) // Note that MOV??reg returns a 64-bit int, x is not necessarily that wide @@ -996,6 +1011,20 @@ (MOVWreg (MOVDconst [c])) => (MOVDconst [int64(int32(c))]) (MOVWZreg (MOVDconst [c])) => (MOVDconst [int64(uint32(c))]) +// Implement clrsldi and clrslwi extended mnemonics as described in +// ISA 3.0 section C.8. AuxInt field contains values needed for +// the instructions, packed together since there is only one available. +(SLDconst [c] z:(MOVBZreg x)) && c < 8 && z.Uses == 1 => (CLRLSLDI [newPPC64ShiftAuxInt(c,56,63,64)] x) +(SLDconst [c] z:(MOVHZreg x)) && c < 16 && z.Uses == 1 => (CLRLSLDI [newPPC64ShiftAuxInt(c,48,63,64)] x) +(SLDconst [c] z:(MOVWZreg x)) && c < 32 && z.Uses == 1 => (CLRLSLDI [newPPC64ShiftAuxInt(c,32,63,64)] x) + +(SLDconst [c] z:(ANDconst [d] x)) && z.Uses == 1 && isPPC64ValidShiftMask(d) => (CLRLSLDI [newPPC64ShiftAuxInt(c,64-getPPC64ShiftMaskLength(d),63,64)] x) +(SLDconst [c] z:(AND (MOVDconst [d]) x)) && z.Uses == 1 && isPPC64ValidShiftMask(d) => (CLRLSLDI [newPPC64ShiftAuxInt(c,64-getPPC64ShiftMaskLength(d),63,64)] x) +(SLWconst [c] z:(MOVBZreg x)) && z.Uses == 1 && c < 8 => (CLRLSLWI [newPPC64ShiftAuxInt(c,24,31,32)] x) +(SLWconst [c] z:(MOVHZreg x)) && z.Uses == 1 && c < 16 => (CLRLSLWI [newPPC64ShiftAuxInt(c,16,31,32)] x) +(SLWconst [c] z:(MOVWZreg x)) && z.Uses == 1 && c < 24 => (CLRLSLWI [newPPC64ShiftAuxInt(c,8,31,32)] x) +(SLWconst [c] z:(ANDconst [d] x)) && z.Uses == 1 && isPPC64ValidShiftMask(d) => (CLRLSLWI [newPPC64ShiftAuxInt(c,32-getPPC64ShiftMaskLength(d),31,32)] x) +(SLWconst [c] z:(AND (MOVDconst [d]) x)) && z.Uses == 1 && isPPC64ValidShiftMask(d) => (CLRLSLWI [newPPC64ShiftAuxInt(c,32-getPPC64ShiftMaskLength(d),31,32)] x) // Lose widening ops fed to stores (MOVBstore [off] {sym} ptr (MOV(B|BZ|H|HZ|W|WZ)reg x) mem) => (MOVBstore [off] {sym} ptr x mem) diff --git a/src/cmd/compile/internal/ssa/gen/PPC64Ops.go b/src/cmd/compile/internal/ssa/gen/PPC64Ops.go index 37706b2dd9..ed99c40cd2 100644 --- a/src/cmd/compile/internal/ssa/gen/PPC64Ops.go +++ b/src/cmd/compile/internal/ssa/gen/PPC64Ops.go @@ -206,6 +206,11 @@ func init() { {name: "ROTL", argLength: 2, reg: gp21, asm: "ROTL"}, // arg0 rotate left by arg1 mod 64 {name: "ROTLW", argLength: 2, reg: gp21, asm: "ROTLW"}, // uint32(arg0) rotate left by arg1 mod 32 + // The following are ops to implement the extended mnemonics for shifts as described in section C.8 of the ISA. + // The constant shift values are packed into the aux int32. + {name: "RLDICL", argLength: 1, reg: gp11, asm: "RLDICL", aux: "Int32"}, // arg0 extract bits identified by shift params" + {name: "CLRLSLWI", argLength: 1, reg: gp11, asm: "CLRLSLWI", aux: "Int32"}, // + {name: "CLRLSLDI", argLength: 1, reg: gp11, asm: "CLRLSLDI", aux: "Int32"}, // {name: "LoweredAdd64Carry", argLength: 3, reg: gp32, resultNotInArgs: true}, // arg0 + arg1 + carry, returns (sum, carry) diff --git a/src/cmd/compile/internal/ssa/opGen.go b/src/cmd/compile/internal/ssa/opGen.go index d95943231a..f00dc3f7f5 100644 --- a/src/cmd/compile/internal/ssa/opGen.go +++ b/src/cmd/compile/internal/ssa/opGen.go @@ -1853,6 +1853,9 @@ const ( OpPPC64SLW OpPPC64ROTL OpPPC64ROTLW + OpPPC64RLDICL + OpPPC64CLRLSLWI + OpPPC64CLRLSLDI OpPPC64LoweredAdd64Carry OpPPC64SRADconst OpPPC64SRAWconst @@ -24672,6 +24675,48 @@ var opcodeTable = [...]opInfo{ }, }, }, + { + name: "RLDICL", + auxType: auxInt32, + argLen: 1, + asm: ppc64.ARLDICL, + reg: regInfo{ + inputs: []inputInfo{ + {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29 + }, + outputs: []outputInfo{ + {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29 + }, + }, + }, + { + name: "CLRLSLWI", + auxType: auxInt32, + argLen: 1, + asm: ppc64.ACLRLSLWI, + reg: regInfo{ + inputs: []inputInfo{ + {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29 + }, + outputs: []outputInfo{ + {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29 + }, + }, + }, + { + name: "CLRLSLDI", + auxType: auxInt32, + argLen: 1, + asm: ppc64.ACLRLSLDI, + reg: regInfo{ + inputs: []inputInfo{ + {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29 + }, + outputs: []outputInfo{ + {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29 + }, + }, + }, { name: "LoweredAdd64Carry", argLen: 3, diff --git a/src/cmd/compile/internal/ssa/rewrite.go b/src/cmd/compile/internal/ssa/rewrite.go index 2ab310ad85..d9c3e455a0 100644 --- a/src/cmd/compile/internal/ssa/rewrite.go +++ b/src/cmd/compile/internal/ssa/rewrite.go @@ -1325,6 +1325,44 @@ func hasSmallRotate(c *Config) bool { } } +func newPPC64ShiftAuxInt(sh, mb, me, sz int64) int32 { + if sh < 0 || sh >= sz { + panic("PPC64 shift arg sh out of range") + } + if mb < 0 || mb >= sz { + panic("PPC64 shift arg mb out of range") + } + if me < 0 || me >= sz { + panic("PPC64 shift arg me out of range") + } + return int32(sh<<16 | mb<<8 | me) +} + +func GetPPC64Shiftsh(auxint int64) int64 { + return int64(int8(auxint >> 16)) +} + +func GetPPC64Shiftmb(auxint int64) int64 { + return int64(int8(auxint >> 8)) +} + +func GetPPC64Shiftme(auxint int64) int64 { + return int64(int8(auxint)) +} + +// Catch the simple ones first +// TODO: Later catch more cases +func isPPC64ValidShiftMask(v int64) bool { + if ((v + 1) & v) == 0 { + return true + } + return false +} + +func getPPC64ShiftMaskLength(v int64) int64 { + return int64(bits.Len64(uint64(v))) +} + // encodes the lsb and width for arm(64) bitfield ops into the expected auxInt format. func armBFAuxInt(lsb, width int64) arm64BitField { if lsb < 0 || lsb > 63 { diff --git a/src/cmd/compile/internal/ssa/rewritePPC64.go b/src/cmd/compile/internal/ssa/rewritePPC64.go index 152cdfdf4d..12b08824b5 100644 --- a/src/cmd/compile/internal/ssa/rewritePPC64.go +++ b/src/cmd/compile/internal/ssa/rewritePPC64.go @@ -586,8 +586,12 @@ func rewriteValuePPC64(v *Value) bool { return rewriteValuePPC64_OpPPC64ROTLW(v) case OpPPC64SLD: return rewriteValuePPC64_OpPPC64SLD(v) + case OpPPC64SLDconst: + return rewriteValuePPC64_OpPPC64SLDconst(v) case OpPPC64SLW: return rewriteValuePPC64_OpPPC64SLW(v) + case OpPPC64SLWconst: + return rewriteValuePPC64_OpPPC64SLWconst(v) case OpPPC64SRAD: return rewriteValuePPC64_OpPPC64SRAD(v) case OpPPC64SRAW: @@ -6565,6 +6569,255 @@ func rewriteValuePPC64_OpPPC64MOVBZreg(v *Value) bool { v.AddArg(x) return true } + // match: (MOVBZreg (OR x (MOVWZreg y))) + // result: (MOVBZreg (OR x y)) + for { + if v_0.Op != OpPPC64OR { + break + } + t := v_0.Type + _ = v_0.Args[1] + v_0_0 := v_0.Args[0] + v_0_1 := v_0.Args[1] + for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 { + x := v_0_0 + if v_0_1.Op != OpPPC64MOVWZreg { + continue + } + y := v_0_1.Args[0] + v.reset(OpPPC64MOVBZreg) + v0 := b.NewValue0(v.Pos, OpPPC64OR, t) + v0.AddArg2(x, y) + v.AddArg(v0) + return true + } + break + } + // match: (MOVBZreg (XOR x (MOVWZreg y))) + // result: (MOVBZreg (XOR x y)) + for { + if v_0.Op != OpPPC64XOR { + break + } + t := v_0.Type + _ = v_0.Args[1] + v_0_0 := v_0.Args[0] + v_0_1 := v_0.Args[1] + for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 { + x := v_0_0 + if v_0_1.Op != OpPPC64MOVWZreg { + continue + } + y := v_0_1.Args[0] + v.reset(OpPPC64MOVBZreg) + v0 := b.NewValue0(v.Pos, OpPPC64XOR, t) + v0.AddArg2(x, y) + v.AddArg(v0) + return true + } + break + } + // match: (MOVBZreg (AND x (MOVWZreg y))) + // result: (MOVBZreg (AND x y)) + for { + if v_0.Op != OpPPC64AND { + break + } + t := v_0.Type + _ = v_0.Args[1] + v_0_0 := v_0.Args[0] + v_0_1 := v_0.Args[1] + for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 { + x := v_0_0 + if v_0_1.Op != OpPPC64MOVWZreg { + continue + } + y := v_0_1.Args[0] + v.reset(OpPPC64MOVBZreg) + v0 := b.NewValue0(v.Pos, OpPPC64AND, t) + v0.AddArg2(x, y) + v.AddArg(v0) + return true + } + break + } + // match: (MOVBZreg (OR x (MOVHZreg y))) + // result: (MOVBZreg (OR x y)) + for { + if v_0.Op != OpPPC64OR { + break + } + t := v_0.Type + _ = v_0.Args[1] + v_0_0 := v_0.Args[0] + v_0_1 := v_0.Args[1] + for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 { + x := v_0_0 + if v_0_1.Op != OpPPC64MOVHZreg { + continue + } + y := v_0_1.Args[0] + v.reset(OpPPC64MOVBZreg) + v0 := b.NewValue0(v.Pos, OpPPC64OR, t) + v0.AddArg2(x, y) + v.AddArg(v0) + return true + } + break + } + // match: (MOVBZreg (XOR x (MOVHZreg y))) + // result: (MOVBZreg (XOR x y)) + for { + if v_0.Op != OpPPC64XOR { + break + } + t := v_0.Type + _ = v_0.Args[1] + v_0_0 := v_0.Args[0] + v_0_1 := v_0.Args[1] + for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 { + x := v_0_0 + if v_0_1.Op != OpPPC64MOVHZreg { + continue + } + y := v_0_1.Args[0] + v.reset(OpPPC64MOVBZreg) + v0 := b.NewValue0(v.Pos, OpPPC64XOR, t) + v0.AddArg2(x, y) + v.AddArg(v0) + return true + } + break + } + // match: (MOVBZreg (AND x (MOVHZreg y))) + // result: (MOVBZreg (AND x y)) + for { + if v_0.Op != OpPPC64AND { + break + } + t := v_0.Type + _ = v_0.Args[1] + v_0_0 := v_0.Args[0] + v_0_1 := v_0.Args[1] + for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 { + x := v_0_0 + if v_0_1.Op != OpPPC64MOVHZreg { + continue + } + y := v_0_1.Args[0] + v.reset(OpPPC64MOVBZreg) + v0 := b.NewValue0(v.Pos, OpPPC64AND, t) + v0.AddArg2(x, y) + v.AddArg(v0) + return true + } + break + } + // match: (MOVBZreg (OR x (MOVBZreg y))) + // result: (MOVBZreg (OR x y)) + for { + if v_0.Op != OpPPC64OR { + break + } + t := v_0.Type + _ = v_0.Args[1] + v_0_0 := v_0.Args[0] + v_0_1 := v_0.Args[1] + for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 { + x := v_0_0 + if v_0_1.Op != OpPPC64MOVBZreg { + continue + } + y := v_0_1.Args[0] + v.reset(OpPPC64MOVBZreg) + v0 := b.NewValue0(v.Pos, OpPPC64OR, t) + v0.AddArg2(x, y) + v.AddArg(v0) + return true + } + break + } + // match: (MOVBZreg (XOR x (MOVBZreg y))) + // result: (MOVBZreg (XOR x y)) + for { + if v_0.Op != OpPPC64XOR { + break + } + t := v_0.Type + _ = v_0.Args[1] + v_0_0 := v_0.Args[0] + v_0_1 := v_0.Args[1] + for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 { + x := v_0_0 + if v_0_1.Op != OpPPC64MOVBZreg { + continue + } + y := v_0_1.Args[0] + v.reset(OpPPC64MOVBZreg) + v0 := b.NewValue0(v.Pos, OpPPC64XOR, t) + v0.AddArg2(x, y) + v.AddArg(v0) + return true + } + break + } + // match: (MOVBZreg (AND x (MOVBZreg y))) + // result: (MOVBZreg (AND x y)) + for { + if v_0.Op != OpPPC64AND { + break + } + t := v_0.Type + _ = v_0.Args[1] + v_0_0 := v_0.Args[0] + v_0_1 := v_0.Args[1] + for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 { + x := v_0_0 + if v_0_1.Op != OpPPC64MOVBZreg { + continue + } + y := v_0_1.Args[0] + v.reset(OpPPC64MOVBZreg) + v0 := b.NewValue0(v.Pos, OpPPC64AND, t) + v0.AddArg2(x, y) + v.AddArg(v0) + return true + } + break + } + // match: (MOVBZreg z:(ANDconst [c] (MOVBZload ptr x))) + // result: z + for { + z := v_0 + if z.Op != OpPPC64ANDconst { + break + } + z_0 := z.Args[0] + if z_0.Op != OpPPC64MOVBZload { + break + } + v.copyOf(z) + return true + } + // match: (MOVBZreg z:(AND y (MOVBZload ptr x))) + // result: z + for { + z := v_0 + if z.Op != OpPPC64AND { + break + } + _ = z.Args[1] + z_0 := z.Args[0] + z_1 := z.Args[1] + for _i0 := 0; _i0 <= 1; _i0, z_0, z_1 = _i0+1, z_1, z_0 { + if z_1.Op != OpPPC64MOVBZload { + continue + } + v.copyOf(z) + return true + } + break + } // match: (MOVBZreg x:(MOVBZload _ _)) // result: x for { @@ -8507,6 +8760,197 @@ func rewriteValuePPC64_OpPPC64MOVHZreg(v *Value) bool { v.AddArg(x) return true } + // match: (MOVHZreg (OR x (MOVWZreg y))) + // result: (MOVHZreg (OR x y)) + for { + if v_0.Op != OpPPC64OR { + break + } + t := v_0.Type + _ = v_0.Args[1] + v_0_0 := v_0.Args[0] + v_0_1 := v_0.Args[1] + for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 { + x := v_0_0 + if v_0_1.Op != OpPPC64MOVWZreg { + continue + } + y := v_0_1.Args[0] + v.reset(OpPPC64MOVHZreg) + v0 := b.NewValue0(v.Pos, OpPPC64OR, t) + v0.AddArg2(x, y) + v.AddArg(v0) + return true + } + break + } + // match: (MOVHZreg (XOR x (MOVWZreg y))) + // result: (MOVHZreg (XOR x y)) + for { + if v_0.Op != OpPPC64XOR { + break + } + t := v_0.Type + _ = v_0.Args[1] + v_0_0 := v_0.Args[0] + v_0_1 := v_0.Args[1] + for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 { + x := v_0_0 + if v_0_1.Op != OpPPC64MOVWZreg { + continue + } + y := v_0_1.Args[0] + v.reset(OpPPC64MOVHZreg) + v0 := b.NewValue0(v.Pos, OpPPC64XOR, t) + v0.AddArg2(x, y) + v.AddArg(v0) + return true + } + break + } + // match: (MOVHZreg (AND x (MOVWZreg y))) + // result: (MOVHZreg (AND x y)) + for { + if v_0.Op != OpPPC64AND { + break + } + t := v_0.Type + _ = v_0.Args[1] + v_0_0 := v_0.Args[0] + v_0_1 := v_0.Args[1] + for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 { + x := v_0_0 + if v_0_1.Op != OpPPC64MOVWZreg { + continue + } + y := v_0_1.Args[0] + v.reset(OpPPC64MOVHZreg) + v0 := b.NewValue0(v.Pos, OpPPC64AND, t) + v0.AddArg2(x, y) + v.AddArg(v0) + return true + } + break + } + // match: (MOVHZreg (OR x (MOVHZreg y))) + // result: (MOVHZreg (OR x y)) + for { + if v_0.Op != OpPPC64OR { + break + } + t := v_0.Type + _ = v_0.Args[1] + v_0_0 := v_0.Args[0] + v_0_1 := v_0.Args[1] + for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 { + x := v_0_0 + if v_0_1.Op != OpPPC64MOVHZreg { + continue + } + y := v_0_1.Args[0] + v.reset(OpPPC64MOVHZreg) + v0 := b.NewValue0(v.Pos, OpPPC64OR, t) + v0.AddArg2(x, y) + v.AddArg(v0) + return true + } + break + } + // match: (MOVHZreg (XOR x (MOVHZreg y))) + // result: (MOVHZreg (XOR x y)) + for { + if v_0.Op != OpPPC64XOR { + break + } + t := v_0.Type + _ = v_0.Args[1] + v_0_0 := v_0.Args[0] + v_0_1 := v_0.Args[1] + for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 { + x := v_0_0 + if v_0_1.Op != OpPPC64MOVHZreg { + continue + } + y := v_0_1.Args[0] + v.reset(OpPPC64MOVHZreg) + v0 := b.NewValue0(v.Pos, OpPPC64XOR, t) + v0.AddArg2(x, y) + v.AddArg(v0) + return true + } + break + } + // match: (MOVHZreg (AND x (MOVHZreg y))) + // result: (MOVHZreg (AND x y)) + for { + if v_0.Op != OpPPC64AND { + break + } + t := v_0.Type + _ = v_0.Args[1] + v_0_0 := v_0.Args[0] + v_0_1 := v_0.Args[1] + for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 { + x := v_0_0 + if v_0_1.Op != OpPPC64MOVHZreg { + continue + } + y := v_0_1.Args[0] + v.reset(OpPPC64MOVHZreg) + v0 := b.NewValue0(v.Pos, OpPPC64AND, t) + v0.AddArg2(x, y) + v.AddArg(v0) + return true + } + break + } + // match: (MOVHZreg z:(ANDconst [c] (MOVBZload ptr x))) + // result: z + for { + z := v_0 + if z.Op != OpPPC64ANDconst { + break + } + z_0 := z.Args[0] + if z_0.Op != OpPPC64MOVBZload { + break + } + v.copyOf(z) + return true + } + // match: (MOVHZreg z:(ANDconst [c] (MOVHZload ptr x))) + // result: z + for { + z := v_0 + if z.Op != OpPPC64ANDconst { + break + } + z_0 := z.Args[0] + if z_0.Op != OpPPC64MOVHZload { + break + } + v.copyOf(z) + return true + } + // match: (MOVHZreg z:(AND y (MOVHZload ptr x))) + // result: z + for { + z := v_0 + if z.Op != OpPPC64AND { + break + } + _ = z.Args[1] + z_0 := z.Args[0] + z_1 := z.Args[1] + for _i0 := 0; _i0 <= 1; _i0, z_0, z_1 = _i0+1, z_1, z_0 { + if z_1.Op != OpPPC64MOVHZload { + continue + } + v.copyOf(z) + return true + } + break + } // match: (MOVHZreg x:(MOVBZload _ _)) // result: x for { @@ -9657,6 +10101,139 @@ func rewriteValuePPC64_OpPPC64MOVWZreg(v *Value) bool { v.AddArg(x) return true } + // match: (MOVWZreg (OR x (MOVWZreg y))) + // result: (MOVWZreg (OR x y)) + for { + if v_0.Op != OpPPC64OR { + break + } + t := v_0.Type + _ = v_0.Args[1] + v_0_0 := v_0.Args[0] + v_0_1 := v_0.Args[1] + for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 { + x := v_0_0 + if v_0_1.Op != OpPPC64MOVWZreg { + continue + } + y := v_0_1.Args[0] + v.reset(OpPPC64MOVWZreg) + v0 := b.NewValue0(v.Pos, OpPPC64OR, t) + v0.AddArg2(x, y) + v.AddArg(v0) + return true + } + break + } + // match: (MOVWZreg (XOR x (MOVWZreg y))) + // result: (MOVWZreg (XOR x y)) + for { + if v_0.Op != OpPPC64XOR { + break + } + t := v_0.Type + _ = v_0.Args[1] + v_0_0 := v_0.Args[0] + v_0_1 := v_0.Args[1] + for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 { + x := v_0_0 + if v_0_1.Op != OpPPC64MOVWZreg { + continue + } + y := v_0_1.Args[0] + v.reset(OpPPC64MOVWZreg) + v0 := b.NewValue0(v.Pos, OpPPC64XOR, t) + v0.AddArg2(x, y) + v.AddArg(v0) + return true + } + break + } + // match: (MOVWZreg (AND x (MOVWZreg y))) + // result: (MOVWZreg (AND x y)) + for { + if v_0.Op != OpPPC64AND { + break + } + t := v_0.Type + _ = v_0.Args[1] + v_0_0 := v_0.Args[0] + v_0_1 := v_0.Args[1] + for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 { + x := v_0_0 + if v_0_1.Op != OpPPC64MOVWZreg { + continue + } + y := v_0_1.Args[0] + v.reset(OpPPC64MOVWZreg) + v0 := b.NewValue0(v.Pos, OpPPC64AND, t) + v0.AddArg2(x, y) + v.AddArg(v0) + return true + } + break + } + // match: (MOVWZreg z:(ANDconst [c] (MOVBZload ptr x))) + // result: z + for { + z := v_0 + if z.Op != OpPPC64ANDconst { + break + } + z_0 := z.Args[0] + if z_0.Op != OpPPC64MOVBZload { + break + } + v.copyOf(z) + return true + } + // match: (MOVWZreg z:(ANDconst [c] (MOVHZload ptr x))) + // result: z + for { + z := v_0 + if z.Op != OpPPC64ANDconst { + break + } + z_0 := z.Args[0] + if z_0.Op != OpPPC64MOVHZload { + break + } + v.copyOf(z) + return true + } + // match: (MOVWZreg z:(ANDconst [c] (MOVWZload ptr x))) + // result: z + for { + z := v_0 + if z.Op != OpPPC64ANDconst { + break + } + z_0 := z.Args[0] + if z_0.Op != OpPPC64MOVWZload { + break + } + v.copyOf(z) + return true + } + // match: (MOVWZreg z:(AND y (MOVWZload ptr x))) + // result: z + for { + z := v_0 + if z.Op != OpPPC64AND { + break + } + _ = z.Args[1] + z_0 := z.Args[0] + z_1 := z.Args[1] + for _i0 := 0; _i0 <= 1; _i0, z_0, z_1 = _i0+1, z_1, z_0 { + if z_1.Op != OpPPC64MOVWZload { + continue + } + v.copyOf(z) + return true + } + break + } // match: (MOVWZreg x:(MOVBZload _ _)) // result: x for { @@ -12197,6 +12774,111 @@ func rewriteValuePPC64_OpPPC64SLD(v *Value) bool { } return false } +func rewriteValuePPC64_OpPPC64SLDconst(v *Value) bool { + v_0 := v.Args[0] + // match: (SLDconst [c] z:(MOVBZreg x)) + // cond: c < 8 && z.Uses == 1 + // result: (CLRLSLDI [newPPC64ShiftAuxInt(c,56,63,64)] x) + for { + c := auxIntToInt64(v.AuxInt) + z := v_0 + if z.Op != OpPPC64MOVBZreg { + break + } + x := z.Args[0] + if !(c < 8 && z.Uses == 1) { + break + } + v.reset(OpPPC64CLRLSLDI) + v.AuxInt = int32ToAuxInt(newPPC64ShiftAuxInt(c, 56, 63, 64)) + v.AddArg(x) + return true + } + // match: (SLDconst [c] z:(MOVHZreg x)) + // cond: c < 16 && z.Uses == 1 + // result: (CLRLSLDI [newPPC64ShiftAuxInt(c,48,63,64)] x) + for { + c := auxIntToInt64(v.AuxInt) + z := v_0 + if z.Op != OpPPC64MOVHZreg { + break + } + x := z.Args[0] + if !(c < 16 && z.Uses == 1) { + break + } + v.reset(OpPPC64CLRLSLDI) + v.AuxInt = int32ToAuxInt(newPPC64ShiftAuxInt(c, 48, 63, 64)) + v.AddArg(x) + return true + } + // match: (SLDconst [c] z:(MOVWZreg x)) + // cond: c < 32 && z.Uses == 1 + // result: (CLRLSLDI [newPPC64ShiftAuxInt(c,32,63,64)] x) + for { + c := auxIntToInt64(v.AuxInt) + z := v_0 + if z.Op != OpPPC64MOVWZreg { + break + } + x := z.Args[0] + if !(c < 32 && z.Uses == 1) { + break + } + v.reset(OpPPC64CLRLSLDI) + v.AuxInt = int32ToAuxInt(newPPC64ShiftAuxInt(c, 32, 63, 64)) + v.AddArg(x) + return true + } + // match: (SLDconst [c] z:(ANDconst [d] x)) + // cond: z.Uses == 1 && isPPC64ValidShiftMask(d) + // result: (CLRLSLDI [newPPC64ShiftAuxInt(c,64-getPPC64ShiftMaskLength(d),63,64)] x) + for { + c := auxIntToInt64(v.AuxInt) + z := v_0 + if z.Op != OpPPC64ANDconst { + break + } + d := auxIntToInt64(z.AuxInt) + x := z.Args[0] + if !(z.Uses == 1 && isPPC64ValidShiftMask(d)) { + break + } + v.reset(OpPPC64CLRLSLDI) + v.AuxInt = int32ToAuxInt(newPPC64ShiftAuxInt(c, 64-getPPC64ShiftMaskLength(d), 63, 64)) + v.AddArg(x) + return true + } + // match: (SLDconst [c] z:(AND (MOVDconst [d]) x)) + // cond: z.Uses == 1 && isPPC64ValidShiftMask(d) + // result: (CLRLSLDI [newPPC64ShiftAuxInt(c,64-getPPC64ShiftMaskLength(d),63,64)] x) + for { + c := auxIntToInt64(v.AuxInt) + z := v_0 + if z.Op != OpPPC64AND { + break + } + _ = z.Args[1] + z_0 := z.Args[0] + z_1 := z.Args[1] + for _i0 := 0; _i0 <= 1; _i0, z_0, z_1 = _i0+1, z_1, z_0 { + if z_0.Op != OpPPC64MOVDconst { + continue + } + d := auxIntToInt64(z_0.AuxInt) + x := z_1 + if !(z.Uses == 1 && isPPC64ValidShiftMask(d)) { + continue + } + v.reset(OpPPC64CLRLSLDI) + v.AuxInt = int32ToAuxInt(newPPC64ShiftAuxInt(c, 64-getPPC64ShiftMaskLength(d), 63, 64)) + v.AddArg(x) + return true + } + break + } + return false +} func rewriteValuePPC64_OpPPC64SLW(v *Value) bool { v_1 := v.Args[1] v_0 := v.Args[0] @@ -12215,6 +12897,111 @@ func rewriteValuePPC64_OpPPC64SLW(v *Value) bool { } return false } +func rewriteValuePPC64_OpPPC64SLWconst(v *Value) bool { + v_0 := v.Args[0] + // match: (SLWconst [c] z:(MOVBZreg x)) + // cond: z.Uses == 1 && c < 8 + // result: (CLRLSLWI [newPPC64ShiftAuxInt(c,24,31,32)] x) + for { + c := auxIntToInt64(v.AuxInt) + z := v_0 + if z.Op != OpPPC64MOVBZreg { + break + } + x := z.Args[0] + if !(z.Uses == 1 && c < 8) { + break + } + v.reset(OpPPC64CLRLSLWI) + v.AuxInt = int32ToAuxInt(newPPC64ShiftAuxInt(c, 24, 31, 32)) + v.AddArg(x) + return true + } + // match: (SLWconst [c] z:(MOVHZreg x)) + // cond: z.Uses == 1 && c < 16 + // result: (CLRLSLWI [newPPC64ShiftAuxInt(c,16,31,32)] x) + for { + c := auxIntToInt64(v.AuxInt) + z := v_0 + if z.Op != OpPPC64MOVHZreg { + break + } + x := z.Args[0] + if !(z.Uses == 1 && c < 16) { + break + } + v.reset(OpPPC64CLRLSLWI) + v.AuxInt = int32ToAuxInt(newPPC64ShiftAuxInt(c, 16, 31, 32)) + v.AddArg(x) + return true + } + // match: (SLWconst [c] z:(MOVWZreg x)) + // cond: z.Uses == 1 && c < 24 + // result: (CLRLSLWI [newPPC64ShiftAuxInt(c,8,31,32)] x) + for { + c := auxIntToInt64(v.AuxInt) + z := v_0 + if z.Op != OpPPC64MOVWZreg { + break + } + x := z.Args[0] + if !(z.Uses == 1 && c < 24) { + break + } + v.reset(OpPPC64CLRLSLWI) + v.AuxInt = int32ToAuxInt(newPPC64ShiftAuxInt(c, 8, 31, 32)) + v.AddArg(x) + return true + } + // match: (SLWconst [c] z:(ANDconst [d] x)) + // cond: z.Uses == 1 && isPPC64ValidShiftMask(d) + // result: (CLRLSLWI [newPPC64ShiftAuxInt(c,32-getPPC64ShiftMaskLength(d),31,32)] x) + for { + c := auxIntToInt64(v.AuxInt) + z := v_0 + if z.Op != OpPPC64ANDconst { + break + } + d := auxIntToInt64(z.AuxInt) + x := z.Args[0] + if !(z.Uses == 1 && isPPC64ValidShiftMask(d)) { + break + } + v.reset(OpPPC64CLRLSLWI) + v.AuxInt = int32ToAuxInt(newPPC64ShiftAuxInt(c, 32-getPPC64ShiftMaskLength(d), 31, 32)) + v.AddArg(x) + return true + } + // match: (SLWconst [c] z:(AND (MOVDconst [d]) x)) + // cond: z.Uses == 1 && isPPC64ValidShiftMask(d) + // result: (CLRLSLWI [newPPC64ShiftAuxInt(c,32-getPPC64ShiftMaskLength(d),31,32)] x) + for { + c := auxIntToInt64(v.AuxInt) + z := v_0 + if z.Op != OpPPC64AND { + break + } + _ = z.Args[1] + z_0 := z.Args[0] + z_1 := z.Args[1] + for _i0 := 0; _i0 <= 1; _i0, z_0, z_1 = _i0+1, z_1, z_0 { + if z_0.Op != OpPPC64MOVDconst { + continue + } + d := auxIntToInt64(z_0.AuxInt) + x := z_1 + if !(z.Uses == 1 && isPPC64ValidShiftMask(d)) { + continue + } + v.reset(OpPPC64CLRLSLWI) + v.AuxInt = int32ToAuxInt(newPPC64ShiftAuxInt(c, 32-getPPC64ShiftMaskLength(d), 31, 32)) + v.AddArg(x) + return true + } + break + } + return false +} func rewriteValuePPC64_OpPPC64SRAD(v *Value) bool { v_1 := v.Args[1] v_0 := v.Args[0] diff --git a/src/cmd/internal/obj/ppc64/a.out.go b/src/cmd/internal/obj/ppc64/a.out.go index 8b32692778..f438803fb5 100644 --- a/src/cmd/internal/obj/ppc64/a.out.go +++ b/src/cmd/internal/obj/ppc64/a.out.go @@ -575,6 +575,7 @@ const ( ARLWMICC ARLWNM ARLWNMCC + ACLRLSLWI ASLW ASLWCC ASRW @@ -716,6 +717,9 @@ const ( ARLDCLCC ARLDICL ARLDICLCC + ARLDIC + ARLDICCC + ACLRLSLDI AROTL AROTLW ASLBIA diff --git a/src/cmd/internal/obj/ppc64/anames.go b/src/cmd/internal/obj/ppc64/anames.go index 287011877c..accd87fe00 100644 --- a/src/cmd/internal/obj/ppc64/anames.go +++ b/src/cmd/internal/obj/ppc64/anames.go @@ -180,6 +180,7 @@ var Anames = []string{ "RLWMICC", "RLWNM", "RLWNMCC", + "CLRLSLWI", "SLW", "SLWCC", "SRW", @@ -312,6 +313,9 @@ var Anames = []string{ "RLDCLCC", "RLDICL", "RLDICLCC", + "RLDIC", + "RLDICCC", + "CLRLSLDI", "ROTL", "ROTLW", "SLBIA", diff --git a/src/cmd/internal/obj/ppc64/asm9.go b/src/cmd/internal/obj/ppc64/asm9.go index 98b453de6c..60dda72507 100644 --- a/src/cmd/internal/obj/ppc64/asm9.go +++ b/src/cmd/internal/obj/ppc64/asm9.go @@ -1904,6 +1904,7 @@ func buildop(ctxt *obj.Link) { opset(ARLWMICC, r0) opset(ARLWNM, r0) opset(ARLWNMCC, r0) + opset(ACLRLSLWI, r0) case ARLDMI: opset(ARLDMICC, r0) @@ -1922,6 +1923,9 @@ func buildop(ctxt *obj.Link) { opset(ARLDICLCC, r0) opset(ARLDICR, r0) opset(ARLDICRCC, r0) + opset(ARLDIC, r0) + opset(ARLDICCC, r0) + opset(ACLRLSLDI, r0) case AFMOVD: opset(AFMOVDCC, r0) @@ -2734,13 +2738,31 @@ func (c *ctxt9) asmout(p *obj.Prog, o *Optab, out []uint32) { case ARLDICR, ARLDICRCC: me := int(d) sh := c.regoff(&p.From) + if me < 0 || me > 63 || sh > 63 { + c.ctxt.Diag("Invalid me or sh for RLDICR: %x %x\n%v", int(d), sh) + } o1 = AOP_RLDIC(c.oprrr(p.As), uint32(p.To.Reg), uint32(r), uint32(sh), uint32(me)) - case ARLDICL, ARLDICLCC: + case ARLDICL, ARLDICLCC, ARLDIC, ARLDICCC: mb := int(d) sh := c.regoff(&p.From) + if mb < 0 || mb > 63 || sh > 63 { + c.ctxt.Diag("Invalid mb or sh for RLDIC, RLDICL: %x %x\n%v", mb, sh) + } o1 = AOP_RLDIC(c.oprrr(p.As), uint32(p.To.Reg), uint32(r), uint32(sh), uint32(mb)) + case ACLRLSLDI: + // This is an extended mnemonic defined in the ISA section C.8.1 + // clrlsldi ra,rs,n,b --> rldic ra,rs,n,b-n + // It maps onto RLDIC so is directly generated here based on the operands from + // the clrlsldi. + b := int(d) + n := c.regoff(&p.From) + if n > int32(b) || b > 63 { + c.ctxt.Diag("Invalid n or b for CLRLSLDI: %x %x\n%v", n, b) + } + o1 = AOP_RLDIC(OP_RLDIC, uint32(p.To.Reg), uint32(r), uint32(n), uint32(b)-uint32(n)) + default: c.ctxt.Diag("unexpected op in rldc case\n%v", p) a = 0 @@ -3354,18 +3376,43 @@ func (c *ctxt9) asmout(p *obj.Prog, o *Optab, out []uint32) { case 62: /* rlwmi $sh,s,$mask,a */ v := c.regoff(&p.From) - - var mask [2]uint8 - c.maskgen(p, mask[:], uint32(c.regoff(p.GetFrom3()))) - o1 = AOP_RRR(c.opirr(p.As), uint32(p.Reg), uint32(p.To.Reg), uint32(v)) - o1 |= (uint32(mask[0])&31)<<6 | (uint32(mask[1])&31)<<1 + switch p.As { + case ACLRLSLWI: + b := c.regoff(p.GetFrom3()) + // This is an extended mnemonic described in the ISA C.8.2 + // clrlslwi ra,rs,n,b -> rlwinm ra,rs,n,b-n,31-n + // It maps onto rlwinm which is directly generated here. + if v < 0 || v > 32 || b > 32 { + c.ctxt.Diag("Invalid n or b for CLRLSLWI: %x %x\n%v", v, b) + } + o1 = OP_RLW(OP_RLWINM, uint32(p.To.Reg), uint32(p.Reg), uint32(v), uint32(b-v), uint32(31-v)) + default: + var mask [2]uint8 + c.maskgen(p, mask[:], uint32(c.regoff(p.GetFrom3()))) + o1 = AOP_RRR(c.opirr(p.As), uint32(p.Reg), uint32(p.To.Reg), uint32(v)) + o1 |= (uint32(mask[0])&31)<<6 | (uint32(mask[1])&31)<<1 + } case 63: /* rlwmi b,s,$mask,a */ - var mask [2]uint8 - c.maskgen(p, mask[:], uint32(c.regoff(p.GetFrom3()))) - - o1 = AOP_RRR(c.opirr(p.As), uint32(p.Reg), uint32(p.To.Reg), uint32(p.From.Reg)) - o1 |= (uint32(mask[0])&31)<<6 | (uint32(mask[1])&31)<<1 + v := c.regoff(&p.From) + switch p.As { + case ACLRLSLWI: + b := c.regoff(p.GetFrom3()) + if v > b || b > 32 { + // Message will match operands from the ISA even though in the + // code it uses 'v' + c.ctxt.Diag("Invalid n or b for CLRLSLWI: %x %x\n%v", v, b) + } + // This is an extended mnemonic described in the ISA C.8.2 + // clrlslwi ra,rs,n,b -> rlwinm ra,rs,n,b-n,31-n + // It generates the rlwinm directly here. + o1 = OP_RLW(OP_RLWINM, uint32(p.To.Reg), uint32(p.Reg), uint32(v), uint32(b-v), uint32(31-v)) + default: + var mask [2]uint8 + c.maskgen(p, mask[:], uint32(c.regoff(p.GetFrom3()))) + o1 = AOP_RRR(c.opirr(p.As), uint32(p.Reg), uint32(p.To.Reg), uint32(v)) + o1 |= (uint32(mask[0])&31)<<6 | (uint32(mask[1])&31)<<1 + } case 64: /* mtfsf fr[, $m] {,fpcsr} */ var v int32 @@ -4277,6 +4324,11 @@ func (c *ctxt9) oprrr(a obj.As) uint32 { case ARLDICRCC: return OPVCC(30, 0, 0, 1) | 2<<1 // rldicr. + case ARLDIC: + return OPVCC(30, 0, 0, 0) | 4<<1 // rldic + case ARLDICCC: + return OPVCC(30, 0, 0, 1) | 4<<1 // rldic. + case ASYSCALL: return OPVCC(17, 1, 0, 0) diff --git a/test/codegen/shift.go b/test/codegen/shift.go index 5e50ea6bff..32214851b5 100644 --- a/test/codegen/shift.go +++ b/test/codegen/shift.go @@ -150,6 +150,61 @@ func lshGuarded64(v int64, s uint) int64 { panic("shift too large") } +func checkUnneededTrunc(tab *[100000]uint32, d uint64, v uint32, h uint16, b byte) (uint32, uint64) { + + // ppc64le:-".*RLWINM",-".*RLDICR",".*CLRLSLDI" + // ppc64:-".*RLWINM",-".*RLDICR",".*CLRLSLDI" + f := tab[byte(v)^b] + // ppc64le:-".*RLWINM",-".*RLDICR",".*CLRLSLDI" + // ppc64:-".*RLWINM",-".*RLDICR",".*CLRLSLDI" + f += tab[byte(v)&b] + // ppc64le:-".*RLWINM",-".*RLDICR",".*CLRLSLDI" + // ppc64:-".*RLWINM",-".*RLDICR",".*CLRLSLDI" + f += tab[byte(v)|b] + // ppc64le:-".*RLWINM",-".*RLDICR",".*CLRLSLDI" + // ppc64:-".*RLWINM",-".*RLDICR",".*CLRLSLDI" + f += tab[uint16(v)&h] + // ppc64le:-".*RLWINM",-".*RLDICR",".*CLRLSLDI" + // ppc64:-".*RLWINM",-".*RLDICR",".*CLRLSLDI" + f += tab[uint16(v)^h] + // ppc64le:-".*RLWINM",-".*RLDICR",".*CLRLSLDI" + // ppc64:-".*RLWINM",-".*RLDICR",".*CLRLSLDI" + f += tab[uint16(v)|h] + // ppc64le:-".*AND",-"RLDICR",".*CLRLSLDI" + // ppc64:-".*AND",-"RLDICR",".*CLRLSLDI" + f += tab[v&0xff] + // ppc64le:-".*AND",".*CLRLSLWI" + // ppc64:-".*AND",".*CLRLSLWI" + f += 2*uint32(uint16(d)) + // ppc64le:-".*AND",-"RLDICR",".*CLRLSLDI" + // ppc64:-".*AND",-"RLDICR",".*CLRLSLDI" + g := 2*uint64(uint32(d)) + return f, g +} + +func checkCombinedShifts(v8 uint8, v16 uint16, v32 uint32, v64 uint64) (uint8, uint16, uint32, uint64) { + + // ppc64le:-"AND","CLRLSLWI" + // ppc64:-"AND","CLRLSLWI" + f := (v8 &0xF) << 2 + // ppc64le:-"AND","CLRLSLWI" + // ppc64:-"AND","CLRLSLWI" + f += byte(v16)<<3 + // ppc64le:-"AND","CLRLSLWI" + // ppc64:-"AND","CLRLSLWI" + g := (v16 & 0xFF) << 3 + // ppc64le:-"AND","CLRLSLWI" + // ppc64:-"AND","CLRLSLWI" + h := (v32 & 0xFFFFF) << 2 + // ppc64le:-"AND","CLRLSLWI" + // ppc64:-"AND","CLRLSLWI" + h += uint32(v64)<<4 + // ppc64le:-"AND","CLRLSLDI" + // ppc64:-"AND","CLRLSLDI" + i := (v64 & 0xFFFFFFFF) << 5 + return f, g, h, i +} + func checkWidenAfterShift(v int64, u uint64) (int64, uint64) { // ppc64le:-".*MOVW" -- cgit v1.3 From f554eb7bc332cc265e6cc0490a7595b2f5873cba Mon Sep 17 00:00:00 2001 From: David Chase Date: Mon, 13 Jul 2020 14:44:14 -0400 Subject: cmd/compile: add variable length TRESULTS type for SSA use. This type is very much like TTUPLE, but not just for pairs. Used to describe results of a pre-expansion function call. (will later probably also be used to describe the incoming args). Change-Id: I811850cfcc2b3de85085eb4c2eca217c04c330b3 Reviewed-on: https://go-review.googlesource.com/c/go/+/242360 Trust: David Chase Run-TryBot: David Chase TryBot-Result: Go Bot Reviewed-by: Than McIntosh Reviewed-by: Cherry Zhang --- src/cmd/compile/internal/gc/fmt.go | 11 +++++ src/cmd/compile/internal/types/etype_string.go | 7 +-- src/cmd/compile/internal/types/type.go | 66 +++++++++++++++++++++++--- 3 files changed, 74 insertions(+), 10 deletions(-) (limited to 'src/cmd/compile/internal') diff --git a/src/cmd/compile/internal/gc/fmt.go b/src/cmd/compile/internal/gc/fmt.go index 43e501deaf..d4af451506 100644 --- a/src/cmd/compile/internal/gc/fmt.go +++ b/src/cmd/compile/internal/gc/fmt.go @@ -711,6 +711,17 @@ func tconv2(b *bytes.Buffer, t *types.Type, flag FmtFlag, mode fmtMode, visited return } + if t.Etype == types.TRESULTS { + tys := t.Extra.(*types.Results).Types + for i, et := range tys { + if i > 0 { + b.WriteByte(',') + } + b.WriteString(et.String()) + } + return + } + flag, mode = flag.update(mode) if mode == FTypeIdName { flag |= FmtUnsigned diff --git a/src/cmd/compile/internal/types/etype_string.go b/src/cmd/compile/internal/types/etype_string.go index 0ff05a8c2a..14fd5b71df 100644 --- a/src/cmd/compile/internal/types/etype_string.go +++ b/src/cmd/compile/internal/types/etype_string.go @@ -44,12 +44,13 @@ func _() { _ = x[TCHANARGS-33] _ = x[TSSA-34] _ = x[TTUPLE-35] - _ = x[NTYPE-36] + _ = x[TRESULTS-36] + _ = x[NTYPE-37] } -const _EType_name = "xxxINT8UINT8INT16UINT16INT32UINT32INT64UINT64INTUINTUINTPTRCOMPLEX64COMPLEX128FLOAT32FLOAT64BOOLPTRFUNCSLICEARRAYSTRUCTCHANMAPINTERFORWANYSTRINGUNSAFEPTRIDEALNILBLANKFUNCARGSCHANARGSSSATUPLENTYPE" +const _EType_name = "xxxINT8UINT8INT16UINT16INT32UINT32INT64UINT64INTUINTUINTPTRCOMPLEX64COMPLEX128FLOAT32FLOAT64BOOLPTRFUNCSLICEARRAYSTRUCTCHANMAPINTERFORWANYSTRINGUNSAFEPTRIDEALNILBLANKFUNCARGSCHANARGSSSATUPLERESULTSNTYPE" -var _EType_index = [...]uint8{0, 3, 7, 12, 17, 23, 28, 34, 39, 45, 48, 52, 59, 68, 78, 85, 92, 96, 99, 103, 108, 113, 119, 123, 126, 131, 135, 138, 144, 153, 158, 161, 166, 174, 182, 185, 190, 195} +var _EType_index = [...]uint8{0, 3, 7, 12, 17, 23, 28, 34, 39, 45, 48, 52, 59, 68, 78, 85, 92, 96, 99, 103, 108, 113, 119, 123, 126, 131, 135, 138, 144, 153, 158, 161, 166, 174, 182, 185, 190, 197, 202} func (i EType) String() string { if i >= EType(len(_EType_index)-1) { diff --git a/src/cmd/compile/internal/types/type.go b/src/cmd/compile/internal/types/type.go index a777a5fd90..9b05aef429 100644 --- a/src/cmd/compile/internal/types/type.go +++ b/src/cmd/compile/internal/types/type.go @@ -66,8 +66,9 @@ const ( TCHANARGS // SSA backend types - TSSA // internal types used by SSA backend (flags, memory, etc.) - TTUPLE // a pair of types, used by SSA backend + TSSA // internal types used by SSA backend (flags, memory, etc.) + TTUPLE // a pair of types, used by SSA backend + TRESULTS // multiuple types; the resulting of calling a function or method, plus a memory at the end. NTYPE ) @@ -330,6 +331,11 @@ type Tuple struct { // Any tuple with a memory type must put that memory type second. } +type Results struct { + Types []*Type + // Any Results with a memory type must put that memory type last. +} + // Array contains Type fields specific to array types. type Array struct { Elem *Type // element type @@ -466,6 +472,8 @@ func New(et EType) *Type { t.Extra = new(Chan) case TTUPLE: t.Extra = new(Tuple) + case TRESULTS: + t.Extra = new(Results) } return t } @@ -512,6 +520,12 @@ func NewTuple(t1, t2 *Type) *Type { return t } +func NewResults(types []*Type) *Type { + t := New(TRESULTS) + t.Extra.(*Results).Types = types + return t +} + func newSSA(name string) *Type { t := New(TSSA) t.Extra = name @@ -688,7 +702,7 @@ func (t *Type) copy() *Type { case TARRAY: x := *t.Extra.(*Array) nt.Extra = &x - case TTUPLE, TSSA: + case TTUPLE, TSSA, TRESULTS: Fatalf("ssa types cannot be copied") } // TODO(mdempsky): Find out why this is necessary and explain. @@ -1051,6 +1065,23 @@ func (t *Type) cmp(x *Type) Cmp { } return ttup.second.Compare(xtup.second) + case TRESULTS: + xResults := x.Extra.(*Results) + tResults := t.Extra.(*Results) + xl, tl := len(xResults.Types), len(tResults.Types) + if tl != xl { + if tl < xl { + return CMPlt + } + return CMPgt + } + for i := 0; i < tl; i++ { + if c := tResults.Types[i].Compare(xResults.Types[i]); c != CMPeq { + return c + } + } + return CMPeq + case TMAP: if c := t.Key().cmp(x.Key()); c != CMPeq { return c @@ -1305,6 +1336,9 @@ func (t *Type) FieldType(i int) *Type { panic("bad tuple index") } } + if t.Etype == TRESULTS { + return t.Extra.(*Results).Types[i] + } return t.Field(i).Type } func (t *Type) FieldOff(i int) int64 { @@ -1382,11 +1416,20 @@ func (t *Type) ChanDir() ChanDir { } func (t *Type) IsMemory() bool { - return t == TypeMem || t.Etype == TTUPLE && t.Extra.(*Tuple).second == TypeMem + if t == TypeMem || t.Etype == TTUPLE && t.Extra.(*Tuple).second == TypeMem { + return true + } + if t.Etype == TRESULTS { + if types := t.Extra.(*Results).Types; len(types) > 0 && types[len(types)-1] == TypeMem { + return true + } + } + return false } -func (t *Type) IsFlags() bool { return t == TypeFlags } -func (t *Type) IsVoid() bool { return t == TypeVoid } -func (t *Type) IsTuple() bool { return t.Etype == TTUPLE } +func (t *Type) IsFlags() bool { return t == TypeFlags } +func (t *Type) IsVoid() bool { return t == TypeVoid } +func (t *Type) IsTuple() bool { return t.Etype == TTUPLE } +func (t *Type) IsResults() bool { return t.Etype == TRESULTS } // IsUntyped reports whether t is an untyped type. func (t *Type) IsUntyped() bool { @@ -1431,6 +1474,15 @@ func (t *Type) HasPointers() bool { case TTUPLE: ttup := t.Extra.(*Tuple) return ttup.first.HasPointers() || ttup.second.HasPointers() + + case TRESULTS: + types := t.Extra.(*Results).Types + for _, et := range types { + if et.HasPointers() { + return true + } + } + return false } return true -- cgit v1.3 From 35e413c5373538ca6e0516f454f78c74477eff2c Mon Sep 17 00:00:00 2001 From: David Chase Date: Mon, 15 Jun 2020 14:20:36 -0400 Subject: cmd/compile: add new ops for experiment with late call expansion Added Dereference, StaticLECall, SelectN, SelectNAddr Change-Id: I5426ae488e83956539aa07f7415b8acc26c933e6 Reviewed-on: https://go-review.googlesource.com/c/go/+/239082 Trust: David Chase Run-TryBot: David Chase Reviewed-by: Cherry Zhang TryBot-Result: Go Bot --- src/cmd/compile/internal/ssa/gen/genericOps.go | 15 +++++++++----- src/cmd/compile/internal/ssa/opGen.go | 28 ++++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 5 deletions(-) (limited to 'src/cmd/compile/internal') diff --git a/src/cmd/compile/internal/ssa/gen/genericOps.go b/src/cmd/compile/internal/ssa/gen/genericOps.go index 145ba2d50c..95edff4c8c 100644 --- a/src/cmd/compile/internal/ssa/gen/genericOps.go +++ b/src/cmd/compile/internal/ssa/gen/genericOps.go @@ -346,6 +346,7 @@ var genericOps = []opData{ // Memory operations {name: "Load", argLength: 2}, // Load from arg0. arg1=memory + {name: "Dereference", argLength: 2}, // Load from arg0. arg1=memory. Helper op for arg/result passing, result is an otherwise not-SSA-able "value". {name: "Store", argLength: 3, typ: "Mem", aux: "Typ"}, // Store arg1 to arg0. arg2=memory, aux=type. Returns memory. // The source and destination of Move may overlap in some cases. See e.g. // memmove inlining in generic.rules. When inlineablememmovesize (in ../rewrite.go) @@ -387,9 +388,11 @@ var genericOps = []opData{ // as a phantom first argument. // TODO(josharian): ClosureCall and InterCall should have Int32 aux // to match StaticCall's 32 bit arg size limit. - {name: "ClosureCall", argLength: 3, aux: "CallOff", call: true}, // arg0=code pointer, arg1=context ptr, arg2=memory. auxint=arg size. Returns memory. - {name: "StaticCall", argLength: 1, aux: "CallOff", call: true}, // call function aux.(*obj.LSym), arg0=memory. auxint=arg size. Returns memory. - {name: "InterCall", argLength: 2, aux: "CallOff", call: true}, // interface call. arg0=code pointer, arg1=memory, auxint=arg size. Returns memory. + // TODO(drchase,josharian): could the arg size limit be bundled into the rules for CallOff? + {name: "ClosureCall", argLength: 3, aux: "CallOff", call: true}, // arg0=code pointer, arg1=context ptr, arg2=memory. auxint=arg size. Returns memory. + {name: "StaticCall", argLength: 1, aux: "CallOff", call: true}, // call function aux.(*obj.LSym), arg0=memory. auxint=arg size. Returns memory. + {name: "InterCall", argLength: 2, aux: "CallOff", call: true}, // interface call. arg0=code pointer, arg1=memory, auxint=arg size. Returns memory. + {name: "StaticLECall", argLength: -1, aux: "CallOff", call: true}, // late-expanded static call function aux.(*ssa.AuxCall.Fn). arg0..argN-1 are inputs, argN is mem. auxint = arg size. Result is tuple of result(s), plus mem. // Conversions: signed extensions, zero (unsigned) extensions, truncations {name: "SignExt8to16", argLength: 1, typ: "Int16"}, @@ -531,8 +534,10 @@ var genericOps = []opData{ {name: "Cvt64Fto64U", argLength: 1}, // float64 -> uint64, only used on archs that has the instruction // pseudo-ops for breaking Tuple - {name: "Select0", argLength: 1, zeroWidth: true}, // the first component of a tuple - {name: "Select1", argLength: 1, zeroWidth: true}, // the second component of a tuple + {name: "Select0", argLength: 1, zeroWidth: true}, // the first component of a tuple + {name: "Select1", argLength: 1, zeroWidth: true}, // the second component of a tuple + {name: "SelectN", argLength: 1, aux: "Int64"}, // arg0=tuple, auxint=field index. Returns the auxint'th member. + {name: "SelectNAddr", argLength: 1, aux: "Int64"}, // arg0=tuple, auxint=field index. Returns the address of auxint'th member. Used for un-SSA-able result types. // Atomic operations used for semantically inlining runtime/internal/atomic. // Atomic loads return a new memory so that the loads are properly ordered diff --git a/src/cmd/compile/internal/ssa/opGen.go b/src/cmd/compile/internal/ssa/opGen.go index f00dc3f7f5..1fc0f7ea79 100644 --- a/src/cmd/compile/internal/ssa/opGen.go +++ b/src/cmd/compile/internal/ssa/opGen.go @@ -2717,6 +2717,7 @@ const ( OpSP OpSB OpLoad + OpDereference OpStore OpMove OpZero @@ -2730,6 +2731,7 @@ const ( OpClosureCall OpStaticCall OpInterCall + OpStaticLECall OpSignExt8to16 OpSignExt8to32 OpSignExt8to64 @@ -2826,6 +2828,8 @@ const ( OpCvt64Fto64U OpSelect0 OpSelect1 + OpSelectN + OpSelectNAddr OpAtomicLoad8 OpAtomicLoad32 OpAtomicLoad64 @@ -34742,6 +34746,11 @@ var opcodeTable = [...]opInfo{ argLen: 2, generic: true, }, + { + name: "Dereference", + argLen: 2, + generic: true, + }, { name: "Store", auxType: auxTyp, @@ -34827,6 +34836,13 @@ var opcodeTable = [...]opInfo{ call: true, generic: true, }, + { + name: "StaticLECall", + auxType: auxCallOff, + argLen: -1, + call: true, + generic: true, + }, { name: "SignExt8to16", argLen: 1, @@ -35328,6 +35344,18 @@ var opcodeTable = [...]opInfo{ zeroWidth: true, generic: true, }, + { + name: "SelectN", + auxType: auxInt64, + argLen: 1, + generic: true, + }, + { + name: "SelectNAddr", + auxType: auxInt64, + argLen: 1, + generic: true, + }, { name: "AtomicLoad8", argLen: 2, -- cgit v1.3 From 22053790fa2c0944df53ea95df476ad2f855424f Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Thu, 17 Sep 2020 09:55:23 -0700 Subject: cmd/compile: propagate go:notinheap implicitly //go:notinheap type T int type U T We already correctly propagate the notinheap-ness of T to U. But we have an assertion in the typechecker that if there's no explicit //go:notinheap associated with U, then report an error. Get rid of that error so that implicit propagation is allowed. Adjust the tests so that we make sure that uses of types like U do correctly report an error when U is used in a context that might cause a Go heap allocation. Fixes #41451 Update #40954 Update #41432 Change-Id: I1692bc7cceff21ebb3f557f3748812a40887118d Reviewed-on: https://go-review.googlesource.com/c/go/+/255637 Run-TryBot: Keith Randall Reviewed-by: Cuong Manh Le Reviewed-by: Ian Lance Taylor Trust: Cuong Manh Le TryBot-Result: Go Bot --- src/cmd/compile/internal/gc/typecheck.go | 6 ------ test/notinheap.go | 20 -------------------- test/notinheap2.go | 26 ++++++++++++++++++++++++++ 3 files changed, 26 insertions(+), 26 deletions(-) (limited to 'src/cmd/compile/internal') diff --git a/src/cmd/compile/internal/gc/typecheck.go b/src/cmd/compile/internal/gc/typecheck.go index 55773641ed..834c1a8ee6 100644 --- a/src/cmd/compile/internal/gc/typecheck.go +++ b/src/cmd/compile/internal/gc/typecheck.go @@ -2068,12 +2068,6 @@ func typecheck1(n *Node, top int) (res *Node) { ok |= ctxStmt n.Left = typecheck(n.Left, ctxType) checkwidth(n.Left.Type) - if n.Left.Type != nil && n.Left.Type.NotInHeap() && !n.Left.Name.Param.Alias && n.Left.Name.Param.Pragma&NotInHeap == 0 { - // The type contains go:notinheap types, so it - // must be marked as such (alternatively, we - // could silently propagate go:notinheap). - yyerror("type %v must be go:notinheap", n.Left.Type) - } } t := n.Type diff --git a/test/notinheap.go b/test/notinheap.go index 5dd4997a65..2188a38a14 100644 --- a/test/notinheap.go +++ b/test/notinheap.go @@ -11,18 +11,6 @@ package p //go:notinheap type nih struct{} -// Types embedding notinheap types must be notinheap. - -type embed1 struct { // ERROR "must be go:notinheap" - x nih -} - -type embed2 [1]nih // ERROR "must be go:notinheap" - -type embed3 struct { // ERROR "must be go:notinheap" - x [1]nih -} - type embed4 map[nih]int // ERROR "incomplete \(or unallocatable\) map key not allowed" type embed5 map[int]nih // ERROR "incomplete \(or unallocatable\) map value not allowed" @@ -52,14 +40,6 @@ type t3 byte //go:notinheap type t4 rune -// Type aliases inherit the go:notinheap-ness of the type they alias. -type nihAlias = nih - -type embedAlias1 struct { // ERROR "must be go:notinheap" - x nihAlias -} -type embedAlias2 [1]nihAlias // ERROR "must be go:notinheap" - var sink interface{} func i() { diff --git a/test/notinheap2.go b/test/notinheap2.go index 23d4b0ae77..100ed37b72 100644 --- a/test/notinheap2.go +++ b/test/notinheap2.go @@ -32,6 +32,25 @@ var y3 *[1]nih var z []nih var w []nih var n int +var sink interface{} + +type embed1 struct { // implicitly notinheap + x nih +} + +type embed2 [1]nih // implicitly notinheap + +type embed3 struct { // implicitly notinheap + x [1]nih +} + +// Type aliases inherit the go:notinheap-ness of the type they alias. +type nihAlias = nih + +type embedAlias1 struct { // implicitly notinheap + x nihAlias +} +type embedAlias2 [1]nihAlias // implicitly notinheap func g() { y = new(nih) // ERROR "can't be allocated in Go" @@ -39,6 +58,13 @@ func g() { y3 = new([1]nih) // ERROR "can't be allocated in Go" z = make([]nih, 1) // ERROR "can't be allocated in Go" z = append(z, x) // ERROR "can't be allocated in Go" + + sink = new(embed1) // ERROR "can't be allocated in Go" + sink = new(embed2) // ERROR "can't be allocated in Go" + sink = new(embed3) // ERROR "can't be allocated in Go" + sink = new(embedAlias1) // ERROR "can't be allocated in Go" + sink = new(embedAlias2) // ERROR "can't be allocated in Go" + // Test for special case of OMAKESLICECOPY x := make([]nih, n) // ERROR "can't be allocated in Go" copy(x, z) -- cgit v1.3 From 0dc369b127651830edef453938dfb5c149aa37cf Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Wed, 16 Sep 2020 15:42:00 +0700 Subject: cmd/compile: make typecheck set correct untyped type Passes toolstash-check. Change-Id: Ie631d8dacb1cc76613e1f50da8422850ac7119a1 Reviewed-on: https://go-review.googlesource.com/c/go/+/255217 Trust: Cuong Manh Le Run-TryBot: Cuong Manh Le TryBot-Result: Go Bot Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/gc/const.go | 122 +++++++++++-------------------- src/cmd/compile/internal/gc/typecheck.go | 19 ++++- 2 files changed, 60 insertions(+), 81 deletions(-) (limited to 'src/cmd/compile/internal') diff --git a/src/cmd/compile/internal/gc/const.go b/src/cmd/compile/internal/gc/const.go index fe73df9d57..59b2c56051 100644 --- a/src/cmd/compile/internal/gc/const.go +++ b/src/cmd/compile/internal/gc/const.go @@ -44,7 +44,7 @@ func (v Val) Ctype() Ctype { Fatalf("unexpected Ctype for %T", v.U) panic("unreachable") case nil: - return 0 + return CTxxx case *NilVal: return CTNIL case bool: @@ -261,7 +261,7 @@ func convlit1(n *Node, t *types.Type, explicit bool, context func() string) *Nod } if t == nil || !okforconst[t.Etype] { - t = defaultType(idealkind(n)) + t = defaultType(n.Type) } switch n.Op { @@ -994,10 +994,8 @@ func setconst(n *Node, v Val) { Xoffset: BADWIDTH, } n.SetVal(v) - if n.Type.IsUntyped() { - // TODO(mdempsky): Make typecheck responsible for setting - // the correct untyped type. - n.Type = idealType(v.Ctype()) + if vt := idealType(v.Ctype()); n.Type.IsUntyped() && n.Type != vt { + Fatalf("untyped type mismatch, have: %v, want: %v", n.Type, vt) } // Check range. @@ -1056,67 +1054,6 @@ func idealType(ct Ctype) *types.Type { return nil } -// idealkind returns a constant kind like consttype -// but for an arbitrary "ideal" (untyped constant) expression. -func idealkind(n *Node) Ctype { - if n == nil || !n.Type.IsUntyped() { - return CTxxx - } - - switch n.Op { - default: - return CTxxx - - case OLITERAL: - return n.Val().Ctype() - - // numeric kinds. - case OADD, - OAND, - OANDNOT, - OBITNOT, - ODIV, - ONEG, - OMOD, - OMUL, - OSUB, - OXOR, - OOR, - OPLUS: - k1 := idealkind(n.Left) - k2 := idealkind(n.Right) - if k1 > k2 { - return k1 - } else { - return k2 - } - - case OREAL, OIMAG: - return CTFLT - - case OCOMPLEX: - return CTCPLX - - case OADDSTR: - return CTSTR - - case OANDAND, - OEQ, - OGE, - OGT, - OLE, - OLT, - ONE, - ONOT, - OOROR: - return CTBOOL - - // shifts (beware!). - case OLSH, ORSH: - return idealkind(n.Left) - } -} - // defaultlit on both nodes simultaneously; // if they're both ideal going in they better // get the same type going out. @@ -1152,32 +1089,57 @@ func defaultlit2(l *Node, r *Node, force bool) (*Node, *Node) { return l, r } - k := idealkind(l) - if rk := idealkind(r); rk > k { - k = rk + nn := l + if ctype(r.Type) > ctype(l.Type) { + nn = r } - t := defaultType(k) + + t := defaultType(nn.Type) l = convlit(l, t) r = convlit(r, t) return l, r } -func defaultType(k Ctype) *types.Type { - switch k { - case CTBOOL: +func ctype(t *types.Type) Ctype { + switch t { + case types.Idealbool: + return CTBOOL + case types.Idealstring: + return CTSTR + case types.Idealint: + return CTINT + case types.Idealrune: + return CTRUNE + case types.Idealfloat: + return CTFLT + case types.Idealcomplex: + return CTCPLX + } + Fatalf("bad type %v", t) + panic("unreachable") +} + +func defaultType(t *types.Type) *types.Type { + if !t.IsUntyped() { + return t + } + + switch t { + case types.Idealbool: return types.Types[TBOOL] - case CTSTR: + case types.Idealstring: return types.Types[TSTRING] - case CTINT: + case types.Idealint: return types.Types[TINT] - case CTRUNE: + case types.Idealrune: return types.Runetype - case CTFLT: + case types.Idealfloat: return types.Types[TFLOAT64] - case CTCPLX: + case types.Idealcomplex: return types.Types[TCOMPLEX128] } - Fatalf("bad idealkind: %v", k) + + Fatalf("bad type %v", t) return nil } diff --git a/src/cmd/compile/internal/gc/typecheck.go b/src/cmd/compile/internal/gc/typecheck.go index 834c1a8ee6..274787a22b 100644 --- a/src/cmd/compile/internal/gc/typecheck.go +++ b/src/cmd/compile/internal/gc/typecheck.go @@ -623,6 +623,9 @@ func typecheck1(n *Node, top int) (res *Node) { // no defaultlit for left // the outer context gives the type n.Type = l.Type + if (l.Type == types.Idealfloat || l.Type == types.Idealcomplex) && r.Op == OLITERAL { + n.Type = types.Idealint + } break } @@ -798,6 +801,20 @@ func typecheck1(n *Node, top int) (res *Node) { } n.Type = t + if t.Etype == TIDEAL { + switch { + case l.Type == types.Idealcomplex || r.Type == types.Idealcomplex: + n.Type = types.Idealcomplex + case l.Type == types.Idealfloat || r.Type == types.Idealfloat: + n.Type = types.Idealfloat + case l.Type == types.Idealrune || r.Type == types.Idealrune: + n.Type = types.Idealrune + case l.Type == types.Idealint || r.Type == types.Idealint: + n.Type = types.Idealint + default: + Fatalf("bad untyped type: %v", t) + } + } case OBITNOT, ONEG, ONOT, OPLUS: ok |= ctxExpr @@ -1678,7 +1695,7 @@ func typecheck1(n *Node, top int) (res *Node) { } var why string n.Op = convertop(n.Left.Op == OLITERAL, t, n.Type, &why) - if n.Op == 0 { + if n.Op == OXXX { if !n.Diag() && !n.Type.Broke() && !n.Left.Diag() { yyerror("cannot convert %L to type %v%s", n.Left, n.Type, why) n.SetDiag(true) -- cgit v1.3 From dc59469f5178a0715a582cbfcc4cf9c06a2c9e82 Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Thu, 17 Sep 2020 22:53:39 +0700 Subject: cmd/compile: move validation from unary/binaryOp to typecheck CL 254400 makes typecheck set untyped type correctly. We now have enough information to check valid operators for a type in typecheck. Passes toolstash-check. Change-Id: I01a7606ee6ce9964ec52430d53eaa886442bd17f Reviewed-on: https://go-review.googlesource.com/c/go/+/255617 Trust: Cuong Manh Le Run-TryBot: Cuong Manh Le TryBot-Result: Go Bot Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/gc/const.go | 19 +------------- src/cmd/compile/internal/gc/typecheck.go | 44 +++++++++++++------------------- 2 files changed, 19 insertions(+), 44 deletions(-) (limited to 'src/cmd/compile/internal') diff --git a/src/cmd/compile/internal/gc/const.go b/src/cmd/compile/internal/gc/const.go index 59b2c56051..399d0148bb 100644 --- a/src/cmd/compile/internal/gc/const.go +++ b/src/cmd/compile/internal/gc/const.go @@ -838,10 +838,6 @@ Outer: return Val{} } u.Quo(y) - case OMOD, OOR, OAND, OANDNOT, OXOR: - // TODO(mdempsky): Move to typecheck; see #31060. - yyerror("invalid operation: operator %v not defined on untyped float", op) - return Val{} default: break Outer } @@ -867,10 +863,6 @@ Outer: yyerror("complex division by zero") return Val{} } - case OMOD, OOR, OAND, OANDNOT, OXOR: - // TODO(mdempsky): Move to typecheck; see #31060. - yyerror("invalid operation: operator %v not defined on untyped complex", op) - return Val{} default: break Outer } @@ -932,15 +924,6 @@ func unaryOp(op Op, x Val, t *types.Type) Val { } u.Xor(x) return Val{U: u} - - case CTFLT: - // TODO(mdempsky): Move to typecheck; see #31060. - yyerror("invalid operation: operator %v not defined on untyped float", op) - return Val{} - case CTCPLX: - // TODO(mdempsky): Move to typecheck; see #31060. - yyerror("invalid operation: operator %v not defined on untyped complex", op) - return Val{} } case ONOT: @@ -1120,7 +1103,7 @@ func ctype(t *types.Type) Ctype { } func defaultType(t *types.Type) *types.Type { - if !t.IsUntyped() { + if !t.IsUntyped() || t.Etype == TNIL { return t } diff --git a/src/cmd/compile/internal/gc/typecheck.go b/src/cmd/compile/internal/gc/typecheck.go index 274787a22b..faa13d72f9 100644 --- a/src/cmd/compile/internal/gc/typecheck.go +++ b/src/cmd/compile/internal/gc/typecheck.go @@ -716,8 +716,22 @@ func typecheck1(n *Node, top int) (res *Node) { } } - if !okfor[op][et] { - yyerror("invalid operation: %v (operator %v not defined on %s)", n, op, typekind(t)) + if t.Etype == TIDEAL { + switch { + case l.Type == types.Idealcomplex || r.Type == types.Idealcomplex: + t = types.Idealcomplex + case l.Type == types.Idealfloat || r.Type == types.Idealfloat: + t = types.Idealfloat + case l.Type == types.Idealrune || r.Type == types.Idealrune: + t = types.Idealrune + case l.Type == types.Idealint || r.Type == types.Idealint: + t = types.Idealint + default: + Fatalf("bad untyped type: %v", t) + } + } + if dt := defaultType(t); !okfor[op][dt.Etype] { + yyerror("invalid operation: %v (operator %v not defined on %v)", n, op, t) n.Type = nil return n } @@ -756,15 +770,7 @@ func typecheck1(n *Node, top int) (res *Node) { } } - t = l.Type if iscmp[n.Op] { - // TIDEAL includes complex constant, but only OEQ and ONE are defined for complex, - // so check that the n.op is available for complex here before doing evconst. - if !okfor[n.Op][TCOMPLEX128] && (Isconst(l, CTCPLX) || Isconst(r, CTCPLX)) { - yyerror("invalid operation: %v (operator %v not defined on untyped complex)", n, n.Op) - n.Type = nil - return n - } evconst(n) t = types.Idealbool if n.Op != OLITERAL { @@ -801,20 +807,6 @@ func typecheck1(n *Node, top int) (res *Node) { } n.Type = t - if t.Etype == TIDEAL { - switch { - case l.Type == types.Idealcomplex || r.Type == types.Idealcomplex: - n.Type = types.Idealcomplex - case l.Type == types.Idealfloat || r.Type == types.Idealfloat: - n.Type = types.Idealfloat - case l.Type == types.Idealrune || r.Type == types.Idealrune: - n.Type = types.Idealrune - case l.Type == types.Idealint || r.Type == types.Idealint: - n.Type = types.Idealint - default: - Fatalf("bad untyped type: %v", t) - } - } case OBITNOT, ONEG, ONOT, OPLUS: ok |= ctxExpr @@ -825,8 +817,8 @@ func typecheck1(n *Node, top int) (res *Node) { n.Type = nil return n } - if !okfor[n.Op][t.Etype] { - yyerror("invalid operation: %v %v", n.Op, t) + if !okfor[n.Op][defaultType(t).Etype] { + yyerror("invalid operation: %v (operator %v not defined on %s)", n, n.Op, typekind(t)) n.Type = nil return n } -- cgit v1.3 From 0b1cec7ad33a073be15db89da90efcba9797df83 Mon Sep 17 00:00:00 2001 From: root <2863768433@qq.com> Date: Sun, 30 Aug 2020 11:36:45 +0800 Subject: cmd/compile: rotate phase's title 180 degrees in ssa/html.go Modify phase's title according to html.go:122 TODO. Fixes #41098 Change-Id: I58fa365e718600aaaa0a72cce72d35a484cde8b8 Reviewed-on: https://go-review.googlesource.com/c/go/+/251657 Reviewed-by: Bradford Lamson-Scribner Reviewed-by: Keith Randall Trust: Josh Bleecher Snyder --- src/cmd/compile/internal/ssa/html.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/cmd/compile/internal') diff --git a/src/cmd/compile/internal/ssa/html.go b/src/cmd/compile/internal/ssa/html.go index ba37a80412..1c70b64708 100644 --- a/src/cmd/compile/internal/ssa/html.go +++ b/src/cmd/compile/internal/ssa/html.go @@ -119,7 +119,8 @@ td.collapsed { } td.collapsed div { - /* TODO: Flip the direction of the phase's title 90 degrees on a collapsed column. */ + text-align: right; + transform: rotate(180deg); writing-mode: vertical-lr; white-space: pre; } -- cgit v1.3 From 234e23d76351c31b191e25b688aa43248d9b3d5b Mon Sep 17 00:00:00 2001 From: root <2863768433@qq.com> Date: Mon, 17 Aug 2020 10:03:06 +0800 Subject: cmd/compile: make expanded/hidden columns in GOSSAFUNC persist across reloads use pushState with updated state and read it on page load,so that state can survive across reloads. Change-Id: I6c5e80e9747576245b979a62cb96d231d8f27d57 Reviewed-on: https://go-review.googlesource.com/c/go/+/248687 Run-TryBot: Alberto Donizetti TryBot-Result: Go Bot Reviewed-by: Bradford Lamson-Scribner Reviewed-by: Keith Randall Trust: Josh Bleecher Snyder --- src/cmd/compile/internal/ssa/html.go | 48 ++++++++++++++++++++++++------------ 1 file changed, 32 insertions(+), 16 deletions(-) (limited to 'src/cmd/compile/internal') diff --git a/src/cmd/compile/internal/ssa/html.go b/src/cmd/compile/internal/ssa/html.go index 1c70b64708..c781ca92cc 100644 --- a/src/cmd/compile/internal/ssa/html.go +++ b/src/cmd/compile/internal/ssa/html.go @@ -358,6 +358,21 @@ body.darkmode ellipse.outline-black { outline: gray solid 2px; }