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