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