1
2
3
4
5 package walk
6
7 import (
8 "cmd/compile/internal/base"
9 "cmd/compile/internal/ir"
10 "cmd/compile/internal/reflectdata"
11 )
12
13
14
15
16 func walkStmt(n ir.Node) ir.Node {
17 if n == nil {
18 return n
19 }
20
21 ir.SetPos(n)
22
23 walkStmtList(n.Init())
24
25 switch n.Op() {
26 default:
27 if n.Op() == ir.ONAME {
28 n := n.(*ir.Name)
29 base.Errorf("%v is not a top level statement", n.Sym())
30 } else {
31 base.Errorf("%v is not a top level statement", n.Op())
32 }
33 ir.Dump("nottop", n)
34 return n
35
36 case ir.OAS,
37 ir.OASOP,
38 ir.OAS2,
39 ir.OAS2DOTTYPE,
40 ir.OAS2RECV,
41 ir.OAS2FUNC,
42 ir.OAS2MAPR,
43 ir.OCLEAR,
44 ir.OCLOSE,
45 ir.OCOPY,
46 ir.OCALLINTER,
47 ir.OCALL,
48 ir.OCALLFUNC,
49 ir.ODELETE,
50 ir.OSEND,
51 ir.OPRINT,
52 ir.OPRINTLN,
53 ir.OPANIC,
54 ir.ORECOVER,
55 ir.OGETG:
56 if n.Typecheck() == 0 {
57 base.Fatalf("missing typecheck: %+v", n)
58 }
59
60 init := ir.TakeInit(n)
61 n = walkExpr(n, &init)
62 if n.Op() == ir.ONAME {
63
64
65 n = ir.NewBlockStmt(n.Pos(), init)
66 init = nil
67 }
68 if len(init) > 0 {
69 switch n.Op() {
70 case ir.OAS, ir.OAS2, ir.OBLOCK:
71 n.(ir.InitNode).PtrInit().Prepend(init...)
72
73 default:
74 init.Append(n)
75 n = ir.NewBlockStmt(n.Pos(), init)
76 }
77 }
78 return n
79
80
81
82 case ir.ORECV:
83 n := n.(*ir.UnaryExpr)
84 return walkRecv(n)
85
86 case ir.OBREAK,
87 ir.OCONTINUE,
88 ir.OFALL,
89 ir.OGOTO,
90 ir.OLABEL,
91 ir.OJUMPTABLE,
92 ir.OINTERFACESWITCH,
93 ir.ODCL,
94 ir.OCHECKNIL:
95 return n
96
97 case ir.OBLOCK:
98 n := n.(*ir.BlockStmt)
99 walkStmtList(n.List)
100 return n
101
102 case ir.OCASE:
103 base.Errorf("case statement out of place")
104 panic("unreachable")
105
106 case ir.ODEFER:
107 n := n.(*ir.GoDeferStmt)
108 ir.CurFunc.SetHasDefer(true)
109 ir.CurFunc.NumDefers++
110 if ir.CurFunc.NumDefers > maxOpenDefers || n.DeferAt != nil {
111
112
113
114
115 ir.CurFunc.SetOpenCodedDeferDisallowed(true)
116 }
117 if n.Esc() != ir.EscNever {
118
119
120 ir.CurFunc.SetOpenCodedDeferDisallowed(true)
121 }
122 fallthrough
123 case ir.OGO:
124 n := n.(*ir.GoDeferStmt)
125 return walkGoDefer(n)
126
127 case ir.OFOR:
128 n := n.(*ir.ForStmt)
129 return walkFor(n)
130
131 case ir.OIF:
132 n := n.(*ir.IfStmt)
133 return walkIf(n)
134
135 case ir.ORETURN:
136 n := n.(*ir.ReturnStmt)
137 return walkReturn(n)
138
139 case ir.OTAILCALL:
140 n := n.(*ir.TailCallStmt)
141
142
143
144
145
146
147 if n.Call.Op() == ir.OCALLINTER {
148 usemethod(n.Call)
149 reflectdata.MarkUsedIfaceMethod(n.Call)
150 }
151
152 var init ir.Nodes
153 n.Call.Fun = walkExpr(n.Call.Fun, &init)
154
155 if len(init) > 0 {
156 init.Append(n)
157 return ir.NewBlockStmt(n.Pos(), init)
158 }
159 return n
160
161 case ir.OINLMARK:
162 n := n.(*ir.InlineMarkStmt)
163 return n
164
165 case ir.OSELECT:
166 n := n.(*ir.SelectStmt)
167 walkSelect(n)
168 return n
169
170 case ir.OSWITCH:
171 n := n.(*ir.SwitchStmt)
172 walkSwitch(n)
173 return n
174
175 case ir.ORANGE:
176 n := n.(*ir.RangeStmt)
177 return walkRange(n)
178 }
179
180
181
182
183 }
184
185 func walkStmtList(s []ir.Node) {
186 for i := range s {
187 s[i] = walkStmt(s[i])
188 }
189 }
190
191
192 func walkFor(n *ir.ForStmt) ir.Node {
193 if n.Cond != nil {
194 init := ir.TakeInit(n.Cond)
195 walkStmtList(init)
196 n.Cond = walkExpr(n.Cond, &init)
197 n.Cond = ir.InitExpr(init, n.Cond)
198 }
199
200 n.Post = walkStmt(n.Post)
201 walkStmtList(n.Body)
202 return n
203 }
204
205
206
207
208 func validGoDeferCall(call ir.Node) bool {
209 if call, ok := call.(*ir.CallExpr); ok && call.Op() == ir.OCALLFUNC && len(call.KeepAlive) == 0 {
210 sig := call.Fun.Type()
211 return sig.NumParams()+sig.NumResults() == 0
212 }
213 return false
214 }
215
216
217 func walkGoDefer(n *ir.GoDeferStmt) ir.Node {
218 if !validGoDeferCall(n.Call) {
219 base.FatalfAt(n.Pos(), "invalid %v call: %v", n.Op(), n.Call)
220 }
221
222 var init ir.Nodes
223
224 call := n.Call.(*ir.CallExpr)
225 call.Fun = walkExpr(call.Fun, &init)
226
227 if len(init) > 0 {
228 init.Append(n)
229 return ir.NewBlockStmt(n.Pos(), init)
230 }
231 return n
232 }
233
234
235 func walkIf(n *ir.IfStmt) ir.Node {
236 n.Cond = walkExpr(n.Cond, n.PtrInit())
237 walkStmtList(n.Body)
238 walkStmtList(n.Else)
239 return n
240 }
241
View as plain text