github.com/bir3/gocompiler@v0.3.205/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.ODCLCONST, ir.ODCLTYPE, 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 missing tag") 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 e.loopDepth++ 84 e.discard(n.Cond) 85 e.stmt(n.Post) 86 e.block(n.Body) 87 e.loopDepth-- 88 89 case ir.ORANGE: 90 // for Key, Value = range X { Body } 91 n := n.(*ir.RangeStmt) 92 93 // X is evaluated outside the loop. 94 tmp := e.newLoc(nil, false) 95 e.expr(tmp.asHole(), n.X) 96 97 e.loopDepth++ 98 ks := e.addrs([]ir.Node{n.Key, n.Value}) 99 if n.X.Type().IsArray() { 100 e.flow(ks[1].note(n, "range"), tmp) 101 } else { 102 e.flow(ks[1].deref(n, "range-deref"), tmp) 103 } 104 e.reassigned(ks, n) 105 106 e.block(n.Body) 107 e.loopDepth-- 108 109 case ir.OSWITCH: 110 n := n.(*ir.SwitchStmt) 111 112 if guard, ok := n.Tag.(*ir.TypeSwitchGuard); ok { 113 var ks []hole 114 if guard.Tag != nil { 115 for _, cas := range n.Cases { 116 cv := cas.Var 117 k := e.dcl(cv) // type switch variables have no ODCL. 118 if cv.Type().HasPointers() { 119 ks = append(ks, k.dotType(cv.Type(), cas, "switch case")) 120 } 121 } 122 } 123 e.expr(e.teeHole(ks...), n.Tag.(*ir.TypeSwitchGuard).X) 124 } else { 125 e.discard(n.Tag) 126 } 127 128 for _, cas := range n.Cases { 129 e.discards(cas.List) 130 e.block(cas.Body) 131 } 132 133 case ir.OSELECT: 134 n := n.(*ir.SelectStmt) 135 for _, cas := range n.Cases { 136 e.stmt(cas.Comm) 137 e.block(cas.Body) 138 } 139 case ir.ORECV: 140 // TODO(mdempsky): Consider e.discard(n.Left). 141 n := n.(*ir.UnaryExpr) 142 e.exprSkipInit(e.discardHole(), n) // already visited n.Ninit 143 case ir.OSEND: 144 n := n.(*ir.SendStmt) 145 e.discard(n.Chan) 146 e.assignHeap(n.Value, "send", n) 147 148 case ir.OAS: 149 n := n.(*ir.AssignStmt) 150 e.assignList([]ir.Node{n.X}, []ir.Node{n.Y}, "assign", n) 151 case ir.OASOP: 152 n := n.(*ir.AssignOpStmt) 153 // TODO(mdempsky): Worry about OLSH/ORSH? 154 e.assignList([]ir.Node{n.X}, []ir.Node{n.Y}, "assign", n) 155 case ir.OAS2: 156 n := n.(*ir.AssignListStmt) 157 e.assignList(n.Lhs, n.Rhs, "assign-pair", n) 158 159 case ir.OAS2DOTTYPE: // v, ok = x.(type) 160 n := n.(*ir.AssignListStmt) 161 e.assignList(n.Lhs, n.Rhs, "assign-pair-dot-type", n) 162 case ir.OAS2MAPR: // v, ok = m[k] 163 n := n.(*ir.AssignListStmt) 164 e.assignList(n.Lhs, n.Rhs, "assign-pair-mapr", n) 165 case ir.OAS2RECV, ir.OSELRECV2: // v, ok = <-ch 166 n := n.(*ir.AssignListStmt) 167 e.assignList(n.Lhs, n.Rhs, "assign-pair-receive", n) 168 169 case ir.OAS2FUNC: 170 n := n.(*ir.AssignListStmt) 171 e.stmts(n.Rhs[0].Init()) 172 ks := e.addrs(n.Lhs) 173 e.call(ks, n.Rhs[0]) 174 e.reassigned(ks, n) 175 case ir.ORETURN: 176 n := n.(*ir.ReturnStmt) 177 results := e.curfn.Type().Results().FieldSlice() 178 dsts := make([]ir.Node, len(results)) 179 for i, res := range results { 180 dsts[i] = res.Nname.(*ir.Name) 181 } 182 e.assignList(dsts, n.Results, "return", n) 183 case ir.OCALLFUNC, ir.OCALLMETH, ir.OCALLINTER, ir.OINLCALL, ir.OCLOSE, ir.OCOPY, ir.ODELETE, ir.OPANIC, ir.OPRINT, ir.OPRINTN, ir.ORECOVER: 184 e.call(nil, n) 185 case ir.OGO, ir.ODEFER: 186 n := n.(*ir.GoDeferStmt) 187 e.goDeferStmt(n) 188 189 case ir.OTAILCALL: 190 n := n.(*ir.TailCallStmt) 191 e.call(nil, n.Call) 192 } 193 } 194 195 func (e *escape) stmts(l ir.Nodes) { 196 for _, n := range l { 197 e.stmt(n) 198 } 199 } 200 201 // block is like stmts, but preserves loopDepth. 202 func (e *escape) block(l ir.Nodes) { 203 old := e.loopDepth 204 e.stmts(l) 205 e.loopDepth = old 206 } 207 208 func (e *escape) dcl(n *ir.Name) hole { 209 if n.Curfn != e.curfn || n.IsClosureVar() { 210 base.Fatalf("bad declaration of %v", n) 211 } 212 loc := e.oldLoc(n) 213 loc.loopDepth = e.loopDepth 214 return loc.asHole() 215 }