diff options
author | Cherry Zhang <cherryyz@google.com> | 2020-10-28 09:12:20 -0400 |
---|---|---|
committer | Cherry Zhang <cherryyz@google.com> | 2020-10-28 09:12:20 -0400 |
commit | a16e30d162c1c7408db7821e7b9513cefa09c6ca (patch) | |
tree | af752ba9ba44c547df39bb0af9bff79f610ba9d5 /src/cmd/compile/internal/gc/walk.go | |
parent | 91e4d2d57bc341dd82c98247117114c851380aef (diff) | |
parent | cf6cfba4d5358404dd890f6025e573a4b2156543 (diff) | |
download | go-git-dev.link.tar.gz |
[dev.link] all: merge branch 'master' into dev.linkdev.link
Clean merge.
Change-Id: Ia7b2808bc649790198d34c226a61d9e569084dc5
Diffstat (limited to 'src/cmd/compile/internal/gc/walk.go')
-rw-r--r-- | src/cmd/compile/internal/gc/walk.go | 179 |
1 files changed, 91 insertions, 88 deletions
diff --git a/src/cmd/compile/internal/gc/walk.go b/src/cmd/compile/internal/gc/walk.go index 8e45059eab..b453e9f1d9 100644 --- a/src/cmd/compile/internal/gc/walk.go +++ b/src/cmd/compile/internal/gc/walk.go @@ -21,7 +21,7 @@ const zeroValSize = 1024 // must match value of runtime/map.go:maxZero func walk(fn *Node) { Curfn = fn - if Debug['W'] != 0 { + if Debug.W != 0 { s := fmt.Sprintf("\nbefore walk %v", Curfn.Func.Nname.Sym) dumplist(s, Curfn.Nbody) } @@ -63,14 +63,14 @@ func walk(fn *Node) { return } walkstmtlist(Curfn.Nbody.Slice()) - if Debug['W'] != 0 { + if Debug.W != 0 { s := fmt.Sprintf("after walk %v", Curfn.Func.Nname.Sym) dumplist(s, Curfn.Nbody) } zeroResults() heapmoves() - if Debug['W'] != 0 && Curfn.Func.Enter.Len() > 0 { + if Debug.W != 0 && Curfn.Func.Enter.Len() > 0 { s := fmt.Sprintf("enter %v", Curfn.Func.Nname.Sym) dumplist(s, Curfn.Func.Enter) } @@ -336,19 +336,6 @@ func walkstmt(n *Node) *Node { return n } -func isSmallMakeSlice(n *Node) bool { - if n.Op != OMAKESLICE { - return false - } - r := n.Right - if r == nil { - r = n.Left - } - t := n.Type - - return smallintconst(r) && (t.Elem().Width == 0 || r.Int64() < maxImplicitStackVarSize/t.Elem().Width) -} - // walk the whole tree of the body of an // expression or simple statement. // the types expressions are calculated. @@ -449,7 +436,7 @@ func walkexpr(n *Node, init *Nodes) *Node { lno := setlineno(n) - if Debug['w'] > 1 { + if Debug.w > 1 { Dump("before walk expr", n) } @@ -487,7 +474,7 @@ opswitch: ODEREF, OSPTR, OITAB, OIDATA, OADDR: n.Left = walkexpr(n.Left, init) - case OEFACE, OAND, OSUB, OMUL, OADD, OOR, OXOR, OLSH, ORSH: + case OEFACE, OAND, OANDNOT, OSUB, OMUL, OADD, OOR, OXOR, OLSH, ORSH: n.Left = walkexpr(n.Left, init) n.Right = walkexpr(n.Right, init) @@ -978,14 +965,6 @@ opswitch: fn := basicnames[param] + "to" + basicnames[result] n = conv(mkcall(fn, types.Types[result], init, conv(n.Left, types.Types[param])), n.Type) - case OANDNOT: - n.Left = walkexpr(n.Left, init) - n.Op = OAND - n.SetImplicit(true) // for walkCheckPtrArithmetic - n.Right = nod(OBITNOT, n.Right, nil) - n.Right = typecheck(n.Right, ctxExpr) - n.Right = walkexpr(n.Right, init) - case ODIV, OMOD: n.Left = walkexpr(n.Left, init) n.Right = walkexpr(n.Right, init) @@ -1014,7 +993,7 @@ opswitch: // The SSA backend will handle those. switch et { case TINT64: - c := n.Right.Int64() + c := n.Right.Int64Val() if c < 0 { c = -c } @@ -1022,7 +1001,7 @@ opswitch: break opswitch } case TUINT64: - c := uint64(n.Right.Int64()) + c := uint64(n.Right.Int64Val()) if c != 0 && c&(c-1) == 0 { break opswitch } @@ -1062,15 +1041,15 @@ opswitch: } if t.IsArray() { n.SetBounded(bounded(r, t.NumElem())) - if Debug['m'] != 0 && n.Bounded() && !Isconst(n.Right, CTINT) { + if Debug.m != 0 && n.Bounded() && !Isconst(n.Right, CTINT) { Warn("index bounds check elided") } if smallintconst(n.Right) && !n.Bounded() { yyerror("index out of bounds") } } else if Isconst(n.Left, CTSTR) { - n.SetBounded(bounded(r, int64(len(strlit(n.Left))))) - if Debug['m'] != 0 && n.Bounded() && !Isconst(n.Right, CTINT) { + n.SetBounded(bounded(r, int64(len(n.Left.StringVal())))) + if Debug.m != 0 && n.Bounded() && !Isconst(n.Right, CTINT) { Warn("index bounds check elided") } if smallintconst(n.Right) && !n.Bounded() { @@ -1339,8 +1318,8 @@ opswitch: yyerror("%v can't be allocated in Go; it is incomplete (or unallocatable)", t.Elem()) } if n.Esc == EscNone { - if !isSmallMakeSlice(n) { - Fatalf("non-small OMAKESLICE with EscNone: %v", n) + if why := heapAllocReason(n); why != "" { + Fatalf("%v has EscNone, but %v", n, why) } // var arr [r]T // n = arr[:l] @@ -1504,7 +1483,7 @@ opswitch: case OSTR2BYTES: s := n.Left if Isconst(s, CTSTR) { - sc := strlit(s) + sc := s.StringVal() // Allocate a [n]byte of the right size. t := types.NewArray(types.Types[TUINT8], int64(len(sc))) @@ -1612,7 +1591,7 @@ opswitch: updateHasCall(n) - if Debug['w'] != 0 && n != nil { + if Debug.w != 0 && n != nil { Dump("after walk expr", n) } @@ -1932,7 +1911,7 @@ func walkprint(nn *Node, init *Nodes) *Node { for i := 0; i < len(s); { var strs []string for i < len(s) && Isconst(s[i], CTSTR) { - strs = append(strs, strlit(s[i])) + strs = append(strs, s[i].StringVal()) i++ } if len(strs) > 0 { @@ -1978,7 +1957,17 @@ func walkprint(nn *Node, init *Nodes) *Node { on = syslook("printiface") } on = substArgTypes(on, n.Type) // any-1 - case TPTR, TCHAN, TMAP, TFUNC, TUNSAFEPTR: + case TPTR: + if n.Type.Elem().NotInHeap() { + on = syslook("printuintptr") + n = nod(OCONV, n, nil) + n.Type = types.Types[TUNSAFEPTR] + n = nod(OCONV, n, nil) + n.Type = types.Types[TUINTPTR] + break + } + fallthrough + case TCHAN, TMAP, TFUNC, TUNSAFEPTR: on = syslook("printpointer") on = substArgTypes(on, n.Type) // any-1 case TSLICE: @@ -2001,7 +1990,7 @@ func walkprint(nn *Node, init *Nodes) *Node { case TSTRING: cs := "" if Isconst(n, CTSTR) { - cs = strlit(n) + cs = n.StringVal() } switch cs { case " ": @@ -2170,7 +2159,7 @@ func reorder3(all []*Node) []*Node { // The result of reorder3save MUST be assigned back to n, e.g. // n.Left = reorder3save(n.Left, all, i, early) func reorder3save(n *Node, all []*Node, i int, early *[]*Node) *Node { - if !aliased(n, all, i) { + if !aliased(n, all[:i]) { return n } @@ -2202,73 +2191,75 @@ func outervalue(n *Node) *Node { } } -// Is it possible that the computation of n might be -// affected by writes in as up to but not including the ith element? -func aliased(n *Node, all []*Node, i int) bool { - if n == nil { +// Is it possible that the computation of r might be +// affected by assignments in all? +func aliased(r *Node, all []*Node) bool { + if r == nil { return false } // Treat all fields of a struct as referring to the whole struct. // We could do better but we would have to keep track of the fields. - for n.Op == ODOT { - n = n.Left + for r.Op == ODOT { + r = r.Left } // Look for obvious aliasing: a variable being assigned // during the all list and appearing in n. - // Also record whether there are any writes to main memory. - // Also record whether there are any writes to variables - // whose addresses have been taken. + // Also record whether there are any writes to addressable + // memory (either main memory or variables whose addresses + // have been taken). memwrite := false - varwrite := false - for _, an := range all[:i] { - a := outervalue(an.Left) - - for a.Op == ODOT { - a = a.Left + for _, as := range all { + // We can ignore assignments to blank. + if as.Left.isBlank() { + continue } - if a.Op != ONAME { + l := outervalue(as.Left) + if l.Op != ONAME { memwrite = true continue } - switch n.Class() { + switch l.Class() { default: - varwrite = true + Fatalf("unexpected class: %v, %v", l, l.Class()) + + case PAUTOHEAP, PEXTERN: + memwrite = true continue case PAUTO, PPARAM, PPARAMOUT: - if n.Name.Addrtaken() { - varwrite = true + if l.Name.Addrtaken() { + memwrite = true continue } - if vmatch2(a, n) { - // Direct hit. + if vmatch2(l, r) { + // Direct hit: l appears in r. return true } } } - // The variables being written do not appear in n. - // However, n might refer to computed addresses + // The variables being written do not appear in r. + // However, r might refer to computed addresses // that are being written. // If no computed addresses are affected by the writes, no aliasing. - if !memwrite && !varwrite { + if !memwrite { return false } - // If n does not refer to computed addresses - // (that is, if n only refers to variables whose addresses + // If r does not refer to computed addresses + // (that is, if r only refers to variables whose addresses // have not been taken), no aliasing. - if varexpr(n) { + if varexpr(r) { return false } - // Otherwise, both the writes and n refer to computed memory addresses. + // Otherwise, both the writes and r refer to computed memory addresses. // Assume that they might conflict. return true } @@ -2656,7 +2647,7 @@ func addstr(n *Node, init *Nodes) *Node { sz := int64(0) for _, n1 := range n.List.Slice() { if n1.Op == OLITERAL { - sz += int64(len(strlit(n1))) + sz += int64(len(n1.StringVal())) } } @@ -2830,7 +2821,7 @@ func appendslice(n *Node, init *Nodes) *Node { // isAppendOfMake reports whether n is of the form append(x , make([]T, y)...). // isAppendOfMake assumes n has already been typechecked. func isAppendOfMake(n *Node) bool { - if Debug['N'] != 0 || instrumenting { + if Debug.N != 0 || instrumenting { return false } @@ -3450,7 +3441,7 @@ func walkcompare(n *Node, init *Nodes) *Node { func tracecmpArg(n *Node, t *types.Type, init *Nodes) *Node { // Ugly hack to avoid "constant -1 overflows uintptr" errors, etc. - if n.Op == OLITERAL && n.Type.IsSigned() && n.Int64() < 0 { + if n.Op == OLITERAL && n.Type.IsSigned() && n.Int64Val() < 0 { n = copyexpr(n, n.Type, init) } @@ -3520,7 +3511,7 @@ func walkcompareString(n *Node, init *Nodes) *Node { // Length-only checks are ok, though. maxRewriteLen = 0 } - if s := strlit(cs); len(s) <= maxRewriteLen { + if s := cs.StringVal(); len(s) <= maxRewriteLen { if len(s) > 0 { ncs = safeexpr(ncs, init) } @@ -3615,26 +3606,32 @@ func bounded(n *Node, max int64) bool { bits := int32(8 * n.Type.Width) if smallintconst(n) { - v := n.Int64() + v := n.Int64Val() return 0 <= v && v < max } switch n.Op { - case OAND: + case OAND, OANDNOT: v := int64(-1) - if smallintconst(n.Left) { - v = n.Left.Int64() - } else if smallintconst(n.Right) { - v = n.Right.Int64() + switch { + case smallintconst(n.Left): + v = n.Left.Int64Val() + case smallintconst(n.Right): + v = n.Right.Int64Val() + if n.Op == OANDNOT { + v = ^v + if !sign { + v &= 1<<uint(bits) - 1 + } + } } - if 0 <= v && v < max { return true } case OMOD: if !sign && smallintconst(n.Right) { - v := n.Right.Int64() + v := n.Right.Int64Val() if 0 <= v && v <= max { return true } @@ -3642,7 +3639,7 @@ func bounded(n *Node, max int64) bool { case ODIV: if !sign && smallintconst(n.Right) { - v := n.Right.Int64() + v := n.Right.Int64Val() for bits > 0 && v >= 2 { bits-- v >>= 1 @@ -3651,7 +3648,7 @@ func bounded(n *Node, max int64) bool { case ORSH: if !sign && smallintconst(n.Right) { - v := n.Right.Int64() + v := n.Right.Int64Val() if v > int64(bits) { return true } @@ -3892,6 +3889,16 @@ func wrapCall(n *Node, init *Nodes) *Node { } isBuiltinCall := n.Op != OCALLFUNC && n.Op != OCALLMETH && n.Op != OCALLINTER + + // Turn f(a, b, []T{c, d, e}...) back into f(a, b, c, d, e). + if !isBuiltinCall && n.IsDDD() { + last := n.List.Len() - 1 + if va := n.List.Index(last); va.Op == OSLICELIT { + n.List.Set(append(n.List.Slice()[:last], va.List.Slice()...)) + n.SetIsDDD(false) + } + } + // origArgs keeps track of what argument is uintptr-unsafe/unsafe-uintptr conversion. origArgs := make([]*Node, n.List.Len()) t := nod(OTFUNC, nil, nil) @@ -3977,7 +3984,7 @@ func canMergeLoads() bool { // isRuneCount reports whether n is of the form len([]rune(string)). // These are optimized into a call to runtime.countrunes. func isRuneCount(n *Node) bool { - return Debug['N'] == 0 && !instrumenting && n.Op == OLEN && n.Left.Op == OSTR2RUNES + return Debug.N == 0 && !instrumenting && n.Op == OLEN && n.Left.Op == OSTR2RUNES } func walkCheckPtrAlignment(n *Node, init *Nodes, count *Node) *Node { @@ -4046,12 +4053,8 @@ func walkCheckPtrArithmetic(n *Node, init *Nodes) *Node { case OADD: walk(n.Left) walk(n.Right) - case OSUB: + case OSUB, OANDNOT: walk(n.Left) - case OAND: - if n.Implicit() { // was OANDNOT - walk(n.Left) - } case OCONVNOP: if n.Left.Type.IsUnsafePtr() { n.Left = cheapexpr(n.Left, init) |