1
2
3
4
5 package escape
6
7 import (
8 "cmd/compile/internal/base"
9 "cmd/compile/internal/ir"
10 "fmt"
11 )
12
13
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
36
37 case ir.OBREAK, ir.OCONTINUE, ir.OGOTO:
38
39
40 case ir.OBLOCK:
41 n := n.(*ir.BlockStmt)
42 e.stmts(n.List)
43
44 case ir.ODCL:
45
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 switch e.labels[n.Label] {
54 case nonlooping:
55 if base.Flag.LowerM > 2 {
56 fmt.Printf("%v:%v non-looping label\n", base.FmtPos(base.Pos), n)
57 }
58 case looping:
59 if base.Flag.LowerM > 2 {
60 fmt.Printf("%v: %v looping label\n", base.FmtPos(base.Pos), n)
61 }
62 e.loopDepth++
63 default:
64 base.Fatalf("label missing tag")
65 }
66 delete(e.labels, n.Label)
67
68 case ir.OIF:
69 n := n.(*ir.IfStmt)
70 e.discard(n.Cond)
71 e.block(n.Body)
72 e.block(n.Else)
73
74 case ir.OFOR, ir.OFORUNTIL:
75 n := n.(*ir.ForStmt)
76 e.loopDepth++
77 e.discard(n.Cond)
78 e.stmt(n.Post)
79 e.block(n.Body)
80 e.loopDepth--
81
82 case ir.ORANGE:
83
84 n := n.(*ir.RangeStmt)
85
86
87 tmp := e.newLoc(nil, false)
88 e.expr(tmp.asHole(), n.X)
89
90 e.loopDepth++
91 ks := e.addrs([]ir.Node{n.Key, n.Value})
92 if n.X.Type().IsArray() {
93 e.flow(ks[1].note(n, "range"), tmp)
94 } else {
95 e.flow(ks[1].deref(n, "range-deref"), tmp)
96 }
97 e.reassigned(ks, n)
98
99 e.block(n.Body)
100 e.loopDepth--
101
102 case ir.OSWITCH:
103 n := n.(*ir.SwitchStmt)
104
105 if guard, ok := n.Tag.(*ir.TypeSwitchGuard); ok {
106 var ks []hole
107 if guard.Tag != nil {
108 for _, cas := range n.Cases {
109 cv := cas.Var
110 k := e.dcl(cv)
111 if cv.Type().HasPointers() {
112 ks = append(ks, k.dotType(cv.Type(), cas, "switch case"))
113 }
114 }
115 }
116 e.expr(e.teeHole(ks...), n.Tag.(*ir.TypeSwitchGuard).X)
117 } else {
118 e.discard(n.Tag)
119 }
120
121 for _, cas := range n.Cases {
122 e.discards(cas.List)
123 e.block(cas.Body)
124 }
125
126 case ir.OSELECT:
127 n := n.(*ir.SelectStmt)
128 for _, cas := range n.Cases {
129 e.stmt(cas.Comm)
130 e.block(cas.Body)
131 }
132 case ir.ORECV:
133
134 n := n.(*ir.UnaryExpr)
135 e.exprSkipInit(e.discardHole(), n)
136 case ir.OSEND:
137 n := n.(*ir.SendStmt)
138 e.discard(n.Chan)
139 e.assignHeap(n.Value, "send", n)
140
141 case ir.OAS:
142 n := n.(*ir.AssignStmt)
143 e.assignList([]ir.Node{n.X}, []ir.Node{n.Y}, "assign", n)
144 case ir.OASOP:
145 n := n.(*ir.AssignOpStmt)
146
147 e.assignList([]ir.Node{n.X}, []ir.Node{n.Y}, "assign", n)
148 case ir.OAS2:
149 n := n.(*ir.AssignListStmt)
150 e.assignList(n.Lhs, n.Rhs, "assign-pair", n)
151
152 case ir.OAS2DOTTYPE:
153 n := n.(*ir.AssignListStmt)
154 e.assignList(n.Lhs, n.Rhs, "assign-pair-dot-type", n)
155 case ir.OAS2MAPR:
156 n := n.(*ir.AssignListStmt)
157 e.assignList(n.Lhs, n.Rhs, "assign-pair-mapr", n)
158 case ir.OAS2RECV, ir.OSELRECV2:
159 n := n.(*ir.AssignListStmt)
160 e.assignList(n.Lhs, n.Rhs, "assign-pair-receive", n)
161
162 case ir.OAS2FUNC:
163 n := n.(*ir.AssignListStmt)
164 e.stmts(n.Rhs[0].Init())
165 ks := e.addrs(n.Lhs)
166 e.call(ks, n.Rhs[0])
167 e.reassigned(ks, n)
168 case ir.ORETURN:
169 n := n.(*ir.ReturnStmt)
170 results := e.curfn.Type().Results().FieldSlice()
171 dsts := make([]ir.Node, len(results))
172 for i, res := range results {
173 dsts[i] = res.Nname.(*ir.Name)
174 }
175 e.assignList(dsts, n.Results, "return", n)
176 case ir.OCALLFUNC, ir.OCALLMETH, ir.OCALLINTER, ir.OINLCALL, ir.OCLOSE, ir.OCOPY, ir.ODELETE, ir.OPANIC, ir.OPRINT, ir.OPRINTN, ir.ORECOVER:
177 e.call(nil, n)
178 case ir.OGO, ir.ODEFER:
179 n := n.(*ir.GoDeferStmt)
180 e.goDeferStmt(n)
181
182 case ir.OTAILCALL:
183 n := n.(*ir.TailCallStmt)
184 e.call(nil, n.Call)
185 }
186 }
187
188 func (e *escape) stmts(l ir.Nodes) {
189 for _, n := range l {
190 e.stmt(n)
191 }
192 }
193
194
195 func (e *escape) block(l ir.Nodes) {
196 old := e.loopDepth
197 e.stmts(l)
198 e.loopDepth = old
199 }
200
201 func (e *escape) dcl(n *ir.Name) hole {
202 if n.Curfn != e.curfn || n.IsClosureVar() {
203 base.Fatalf("bad declaration of %v", n)
204 }
205 loc := e.oldLoc(n)
206 loc.loopDepth = e.loopDepth
207 return loc.asHole()
208 }
209
View as plain text