1
2
3
4
5 package noder
6
7 import (
8 "cmd/compile/internal/ir"
9 "cmd/compile/internal/syntax"
10 "cmd/compile/internal/typecheck"
11 "cmd/compile/internal/types"
12 "cmd/internal/src"
13 )
14
15 func (g *irgen) stmts(stmts []syntax.Stmt) []ir.Node {
16 var nodes []ir.Node
17 for _, stmt := range stmts {
18 switch s := g.stmt(stmt).(type) {
19 case nil:
20 case *ir.BlockStmt:
21 nodes = append(nodes, s.List...)
22 default:
23 nodes = append(nodes, s)
24 }
25 }
26 return nodes
27 }
28
29 func (g *irgen) stmt(stmt syntax.Stmt) ir.Node {
30 switch stmt := stmt.(type) {
31 case nil, *syntax.EmptyStmt:
32 return nil
33 case *syntax.LabeledStmt:
34 return g.labeledStmt(stmt)
35 case *syntax.BlockStmt:
36 return ir.NewBlockStmt(g.pos(stmt), g.blockStmt(stmt))
37 case *syntax.ExprStmt:
38 x := g.expr(stmt.X)
39 if call, ok := x.(*ir.CallExpr); ok {
40 call.Use = ir.CallUseStmt
41 }
42 return x
43 case *syntax.SendStmt:
44 n := ir.NewSendStmt(g.pos(stmt), g.expr(stmt.Chan), g.expr(stmt.Value))
45 if n.Chan.Type().HasTParam() || n.Value.Type().HasTParam() {
46
47
48 n.SetTypecheck(3)
49 return n
50 }
51 transformSend(n)
52 n.SetTypecheck(1)
53 return n
54 case *syntax.DeclStmt:
55 return ir.NewBlockStmt(g.pos(stmt), g.decls(stmt.DeclList))
56
57 case *syntax.AssignStmt:
58 if stmt.Op != 0 && stmt.Op != syntax.Def {
59 op := g.op(stmt.Op, binOps[:])
60 var n *ir.AssignOpStmt
61 if stmt.Rhs == nil {
62 n = IncDec(g.pos(stmt), op, g.expr(stmt.Lhs))
63 } else {
64 n = ir.NewAssignOpStmt(g.pos(stmt), op, g.expr(stmt.Lhs), g.expr(stmt.Rhs))
65 }
66 if n.X.Typecheck() == 3 {
67 n.SetTypecheck(3)
68 return n
69 }
70 transformAsOp(n)
71 n.SetTypecheck(1)
72 return n
73 }
74
75 names, lhs := g.assignList(stmt.Lhs, stmt.Op == syntax.Def)
76 rhs := g.exprList(stmt.Rhs)
77
78
79
80
81 delay := false
82 for _, e := range lhs {
83 if e.Typecheck() == 3 {
84 delay = true
85 break
86 }
87 }
88 for _, e := range rhs {
89 if e.Typecheck() == 3 {
90 delay = true
91 break
92 }
93 }
94
95 if len(lhs) == 1 && len(rhs) == 1 {
96 n := ir.NewAssignStmt(g.pos(stmt), lhs[0], rhs[0])
97 n.Def = initDefn(n, names)
98
99 if delay {
100 n.SetTypecheck(3)
101 return n
102 }
103
104 lhs, rhs := []ir.Node{n.X}, []ir.Node{n.Y}
105 transformAssign(n, lhs, rhs)
106 n.X, n.Y = lhs[0], rhs[0]
107 n.SetTypecheck(1)
108 return n
109 }
110
111 n := ir.NewAssignListStmt(g.pos(stmt), ir.OAS2, lhs, rhs)
112 n.Def = initDefn(n, names)
113 if delay {
114 n.SetTypecheck(3)
115 return n
116 }
117 transformAssign(n, n.Lhs, n.Rhs)
118 n.SetTypecheck(1)
119 return n
120
121 case *syntax.BranchStmt:
122 return ir.NewBranchStmt(g.pos(stmt), g.tokOp(int(stmt.Tok), branchOps[:]), g.name(stmt.Label))
123 case *syntax.CallStmt:
124 return ir.NewGoDeferStmt(g.pos(stmt), g.tokOp(int(stmt.Tok), callOps[:]), g.expr(stmt.Call))
125 case *syntax.ReturnStmt:
126 n := ir.NewReturnStmt(g.pos(stmt), g.exprList(stmt.Results))
127 for _, e := range n.Results {
128 if e.Type().HasTParam() {
129
130
131 n.SetTypecheck(3)
132 return n
133 }
134 }
135 transformReturn(n)
136 n.SetTypecheck(1)
137 return n
138 case *syntax.IfStmt:
139 return g.ifStmt(stmt)
140 case *syntax.ForStmt:
141 return g.forStmt(stmt)
142 case *syntax.SelectStmt:
143 n := g.selectStmt(stmt)
144 transformSelect(n.(*ir.SelectStmt))
145 n.SetTypecheck(1)
146 return n
147 case *syntax.SwitchStmt:
148 return g.switchStmt(stmt)
149
150 default:
151 g.unhandled("statement", stmt)
152 panic("unreachable")
153 }
154 }
155
156
157
158 var branchOps = [...]ir.Op{
159 syntax.Break: ir.OBREAK,
160 syntax.Continue: ir.OCONTINUE,
161 syntax.Fallthrough: ir.OFALL,
162 syntax.Goto: ir.OGOTO,
163 }
164
165 var callOps = [...]ir.Op{
166 syntax.Defer: ir.ODEFER,
167 syntax.Go: ir.OGO,
168 }
169
170 func (g *irgen) tokOp(tok int, ops []ir.Op) ir.Op {
171
172 return ops[tok]
173 }
174
175 func (g *irgen) op(op syntax.Operator, ops []ir.Op) ir.Op {
176
177 return ops[op]
178 }
179
180 func (g *irgen) assignList(expr syntax.Expr, def bool) ([]*ir.Name, []ir.Node) {
181 if !def {
182 return nil, g.exprList(expr)
183 }
184
185 var exprs []syntax.Expr
186 if list, ok := expr.(*syntax.ListExpr); ok {
187 exprs = list.ElemList
188 } else {
189 exprs = []syntax.Expr{expr}
190 }
191
192 var names []*ir.Name
193 res := make([]ir.Node, len(exprs))
194 for i, expr := range exprs {
195 expr := expr.(*syntax.Name)
196 if expr.Value == "_" {
197 res[i] = ir.BlankNode
198 continue
199 }
200
201 if obj, ok := g.info.Uses[expr]; ok {
202 res[i] = g.obj(obj)
203 continue
204 }
205
206 name, _ := g.def(expr)
207 names = append(names, name)
208 res[i] = name
209 }
210
211 return names, res
212 }
213
214
215
216
217 func initDefn(defn ir.InitNode, names []*ir.Name) bool {
218 if len(names) == 0 {
219 return false
220 }
221
222 init := make([]ir.Node, len(names))
223 for i, name := range names {
224 name.Defn = defn
225 init[i] = ir.NewDecl(name.Pos(), ir.ODCL, name)
226 }
227 defn.SetInit(init)
228 return true
229 }
230
231 func (g *irgen) blockStmt(stmt *syntax.BlockStmt) []ir.Node {
232 return g.stmts(stmt.List)
233 }
234
235 func (g *irgen) ifStmt(stmt *syntax.IfStmt) ir.Node {
236 init := g.stmt(stmt.Init)
237 n := ir.NewIfStmt(g.pos(stmt), g.expr(stmt.Cond), g.blockStmt(stmt.Then), nil)
238 if stmt.Else != nil {
239 e := g.stmt(stmt.Else)
240 if e.Op() == ir.OBLOCK {
241 e := e.(*ir.BlockStmt)
242 n.Else = e.List
243 } else {
244 n.Else = []ir.Node{e}
245 }
246 }
247 return g.init(init, n)
248 }
249
250
251
252 func unpackTwo(list []ir.Node) (fst, snd ir.Node) {
253 switch len(list) {
254 case 0:
255 return nil, nil
256 case 1:
257 return list[0], nil
258 default:
259 return list[0], list[1]
260 }
261 }
262
263 func (g *irgen) forStmt(stmt *syntax.ForStmt) ir.Node {
264 if r, ok := stmt.Init.(*syntax.RangeClause); ok {
265 names, lhs := g.assignList(r.Lhs, r.Def)
266 key, value := unpackTwo(lhs)
267 n := ir.NewRangeStmt(g.pos(r), key, value, g.expr(r.X), g.blockStmt(stmt.Body))
268 n.Def = initDefn(n, names)
269 return n
270 }
271
272 return ir.NewForStmt(g.pos(stmt), g.stmt(stmt.Init), g.expr(stmt.Cond), g.stmt(stmt.Post), g.blockStmt(stmt.Body))
273 }
274
275 func (g *irgen) selectStmt(stmt *syntax.SelectStmt) ir.Node {
276 body := make([]*ir.CommClause, len(stmt.Body))
277 for i, clause := range stmt.Body {
278 body[i] = ir.NewCommStmt(g.pos(clause), g.stmt(clause.Comm), g.stmts(clause.Body))
279 }
280 return ir.NewSelectStmt(g.pos(stmt), body)
281 }
282
283 func (g *irgen) switchStmt(stmt *syntax.SwitchStmt) ir.Node {
284 pos := g.pos(stmt)
285 init := g.stmt(stmt.Init)
286
287 var expr ir.Node
288 switch tag := stmt.Tag.(type) {
289 case *syntax.TypeSwitchGuard:
290 var ident *ir.Ident
291 if tag.Lhs != nil {
292 ident = ir.NewIdent(g.pos(tag.Lhs), g.name(tag.Lhs))
293 }
294 expr = ir.NewTypeSwitchGuard(pos, ident, g.expr(tag.X))
295 default:
296 expr = g.expr(tag)
297 }
298
299 body := make([]*ir.CaseClause, len(stmt.Body))
300 for i, clause := range stmt.Body {
301
302
303
304
305
306
307
308
309
310 var cv *ir.Name
311 if obj, ok := g.info.Implicits[clause]; ok {
312 cv = g.obj(obj)
313 cv.SetPos(g.makeXPos(clause.Colon))
314 }
315 body[i] = ir.NewCaseStmt(g.pos(clause), g.exprList(clause.Cases), g.stmts(clause.Body))
316 body[i].Var = cv
317 }
318
319 return g.init(init, ir.NewSwitchStmt(pos, expr, body))
320 }
321
322 func (g *irgen) labeledStmt(label *syntax.LabeledStmt) ir.Node {
323 sym := g.name(label.Label)
324 lhs := ir.NewLabelStmt(g.pos(label), sym)
325 ls := g.stmt(label.Stmt)
326
327
328 switch ls := ls.(type) {
329 case *ir.ForStmt:
330 ls.Label = sym
331 case *ir.RangeStmt:
332 ls.Label = sym
333 case *ir.SelectStmt:
334 ls.Label = sym
335 case *ir.SwitchStmt:
336 ls.Label = sym
337 }
338
339 l := []ir.Node{lhs}
340 if ls != nil {
341 if ls.Op() == ir.OBLOCK {
342 ls := ls.(*ir.BlockStmt)
343 l = append(l, ls.List...)
344 } else {
345 l = append(l, ls)
346 }
347 }
348 return ir.NewBlockStmt(src.NoXPos, l)
349 }
350
351 func (g *irgen) init(init ir.Node, stmt ir.InitNode) ir.InitNode {
352 if init != nil {
353 stmt.SetInit([]ir.Node{init})
354 }
355 return stmt
356 }
357
358 func (g *irgen) name(name *syntax.Name) *types.Sym {
359 if name == nil {
360 return nil
361 }
362 return typecheck.Lookup(name.Value)
363 }
364
View as plain text