github.com/bir3/gocompiler@v0.9.2202/src/cmd/compile/internal/escape/stmt.go (about) 1 // Copyright 2018 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package escape 6 7 import ( 8 "github.com/bir3/gocompiler/src/cmd/compile/internal/base" 9 "github.com/bir3/gocompiler/src/cmd/compile/internal/ir" 10 "fmt" 11 ) 12 13 // stmt evaluates a single Go statement. 14 func (e *escape) stmt(n ir.Node) { 15 if n == nil { 16 return 17 } 18 19 lno := ir.SetPos(n) 20 defer func() { 21 base.Pos = lno 22 }() 23 24 if base.Flag.LowerM > 2 { 25 fmt.Printf("%v:[%d] %v stmt: %v\n", base.FmtPos(base.Pos), e.loopDepth, e.curfn, n) 26 } 27 28 e.stmts(n.Init()) 29 30 switch n.Op() { 31 default: 32 base.Fatalf("unexpected stmt: %v", n) 33 34 case ir.OFALL, ir.OINLMARK: 35 // nop 36 37 case ir.OBREAK, ir.OCONTINUE, ir.OGOTO: 38 // TODO(mdempsky): Handle dead code? 39 40 case ir.OBLOCK: 41 n := n.(*ir.BlockStmt) 42 e.stmts(n.List) 43 44 case ir.ODCL: 45 // Record loop depth at declaration. 46 n := n.(*ir.Decl) 47 if !ir.IsBlank(n.X) { 48 e.dcl(n.X) 49 } 50 51 case ir.OLABEL: 52 n := n.(*ir.LabelStmt) 53 if n.Label.IsBlank() { 54 break 55 } 56 switch e.labels[n.Label] { 57 case nonlooping: 58 if base.Flag.LowerM > 2 { 59 fmt.Printf("%v:%v non-looping label\n", base.FmtPos(base.Pos), n) 60 } 61 case looping: 62 if base.Flag.LowerM > 2 { 63 fmt.Printf("%v: %v looping label\n", base.FmtPos(base.Pos), n) 64 } 65 e.loopDepth++ 66 default: 67 base.Fatalf("label %v missing tag", n.Label) 68 } 69 delete(e.labels, n.Label) 70 71 case ir.OIF: 72 n := n.(*ir.IfStmt) 73 e.discard(n.Cond) 74 e.block(n.Body) 75 e.block(n.Else) 76 77 case ir.OCHECKNIL: 78 n := n.(*ir.UnaryExpr) 79 e.discard(n.X) 80 81 case ir.OFOR: 82 n := n.(*ir.ForStmt) 83 base.Assert(!n.DistinctVars) // Should all be rewritten before escape analysis 84 e.loopDepth++ 85 e.discard(n.Cond) 86 e.stmt(n.Post) 87 e.block(n.Body) 88 e.loopDepth-- 89 90 case ir.ORANGE: 91 // for Key, Value = range X { Body } 92 n := n.(*ir.RangeStmt) 93 base.Assert(!n.DistinctVars) // Should all be rewritten before escape analysis 94 95 // X is evaluated outside the loop and persists until the loop 96 // terminates. 97 tmp := e.newLoc(nil, true) 98 e.expr(tmp.asHole(), n.X) 99 100 e.loopDepth++ 101 ks := e.addrs([]ir.Node{n.Key, n.Value}) 102 if n.X.Type().IsArray() { 103 e.flow(ks[1].note(n, "range"), tmp) 104 } else { 105 e.flow(ks[1].deref(n, "range-deref"), tmp) 106 } 107 e.reassigned(ks, n) 108 109 e.block(n.Body) 110 e.loopDepth-- 111 112 case ir.OSWITCH: 113 n := n.(*ir.SwitchStmt) 114 115 if guard, ok := n.Tag.(*ir.TypeSwitchGuard); ok { 116 var ks []hole 117 if guard.Tag != nil { 118 for _, cas := range n.Cases { 119 cv := cas.Var 120 k := e.dcl(cv) // type switch variables have no ODCL. 121 if cv.Type().HasPointers() { 122 ks = append(ks, k.dotType(cv.Type(), cas, "switch case")) 123 } 124 } 125 } 126 e.expr(e.teeHole(ks...), n.Tag.(*ir.TypeSwitchGuard).X) 127 } else { 128 e.discard(n.Tag) 129 } 130 131 for _, cas := range n.Cases { 132 e.discards(cas.List) 133 e.block(cas.Body) 134 } 135 136 case ir.OSELECT: 137 n := n.(*ir.SelectStmt) 138 for _, cas := range n.Cases { 139 e.stmt(cas.Comm) 140 e.block(cas.Body) 141 } 142 case ir.ORECV: 143 // TODO(mdempsky): Consider e.discard(n.Left). 144 n := n.(*ir.UnaryExpr) 145 e.exprSkipInit(e.discardHole(), n) // already visited n.Ninit 146 case ir.OSEND: 147 n := n.(*ir.SendStmt) 148 e.discard(n.Chan) 149 e.assignHeap(n.Value, "send", n) 150 151 case ir.OAS: 152 n := n.(*ir.AssignStmt) 153 e.assignList([]ir.Node{n.X}, []ir.Node{n.Y}, "assign", n) 154 case ir.OASOP: 155 n := n.(*ir.AssignOpStmt) 156 // TODO(mdempsky): Worry about OLSH/ORSH? 157 e.assignList([]ir.Node{n.X}, []ir.Node{n.Y}, "assign", n) 158 case ir.OAS2: 159 n := n.(*ir.AssignListStmt) 160 e.assignList(n.Lhs, n.Rhs, "assign-pair", n) 161 162 case ir.OAS2DOTTYPE: // v, ok = x.(type) 163 n := n.(*ir.AssignListStmt) 164 e.assignList(n.Lhs, n.Rhs, "assign-pair-dot-type", n) 165 case ir.OAS2MAPR: // v, ok = m[k] 166 n := n.(*ir.AssignListStmt) 167 e.assignList(n.Lhs, n.Rhs, "assign-pair-mapr", n) 168 case ir.OAS2RECV, ir.OSELRECV2: // v, ok = <-ch 169 n := n.(*ir.AssignListStmt) 170 e.assignList(n.Lhs, n.Rhs, "assign-pair-receive", n) 171 172 case ir.OAS2FUNC: 173 n := n.(*ir.AssignListStmt) 174 e.stmts(n.Rhs[0].Init()) 175 ks := e.addrs(n.Lhs) 176 e.call(ks, n.Rhs[0]) 177 e.reassigned(ks, n) 178 case ir.ORETURN: 179 n := n.(*ir.ReturnStmt) 180 results := e.curfn.Type().Results() 181 dsts := make([]ir.Node, len(results)) 182 for i, res := range results { 183 dsts[i] = res.Nname.(*ir.Name) 184 } 185 e.assignList(dsts, n.Results, "return", n) 186 case ir.OCALLFUNC, ir.OCALLMETH, ir.OCALLINTER, ir.OINLCALL, ir.OCLEAR, ir.OCLOSE, ir.OCOPY, ir.ODELETE, ir.OPANIC, ir.OPRINT, ir.OPRINTLN, ir.ORECOVERFP: 187 e.call(nil, n) 188 case ir.OGO, ir.ODEFER: 189 n := n.(*ir.GoDeferStmt) 190 e.goDeferStmt(n) 191 192 case ir.OTAILCALL: 193 n := n.(*ir.TailCallStmt) 194 e.call(nil, n.Call) 195 } 196 } 197 198 func (e *escape) stmts(l ir.Nodes) { 199 for _, n := range l { 200 e.stmt(n) 201 } 202 } 203 204 // block is like stmts, but preserves loopDepth. 205 func (e *escape) block(l ir.Nodes) { 206 old := e.loopDepth 207 e.stmts(l) 208 e.loopDepth = old 209 } 210 211 func (e *escape) dcl(n *ir.Name) hole { 212 if n.Curfn != e.curfn || n.IsClosureVar() { 213 base.Fatalf("bad declaration of %v", n) 214 } 215 loc := e.oldLoc(n) 216 loc.loopDepth = e.loopDepth 217 return loc.asHole() 218 }