@@ -101,6 +101,7 @@ func walkselect(sel *Node) {
101
101
var n * Node
102
102
var var_ * Node
103
103
var selv * Node
104
+ var chosen * Node
104
105
if i == 0 {
105
106
sel .Nbody .Set1 (mkcall ("block" , nil , nil ))
106
107
goto out
@@ -165,6 +166,7 @@ func walkselect(sel *Node) {
165
166
}
166
167
167
168
l = append (l , cas .Nbody .Slice ()... )
169
+ l = append (l , nod (OBREAK , nil , nil ))
168
170
sel .Nbody .Set (l )
169
171
goto out
170
172
}
@@ -220,24 +222,21 @@ func walkselect(sel *Node) {
220
222
default :
221
223
Fatalf ("select %v" , n .Op )
222
224
223
- // if selectnbsend(c, v) { body } else { default body }
224
225
case OSEND :
226
+ // if selectnbsend(c, v) { body } else { default body }
225
227
ch := n .Left
226
-
227
228
r .Left = mkcall1 (chanfn ("selectnbsend" , 2 , ch .Type ), Types [TBOOL ], & r .Ninit , typename (ch .Type ), ch , n .Right )
228
229
229
- // if c != nil && selectnbrecv(&v, c) { body } else { default body }
230
230
case OSELRECV :
231
+ // if c != nil && selectnbrecv(&v, c) { body } else { default body }
231
232
r = nod (OIF , nil , nil )
232
-
233
233
r .Ninit .Set (cas .Ninit .Slice ())
234
234
ch := n .Right .Left
235
235
r .Left = mkcall1 (chanfn ("selectnbrecv" , 2 , ch .Type ), Types [TBOOL ], & r .Ninit , typename (ch .Type ), n .Left , ch )
236
236
237
- // if c != nil && selectnbrecv2(&v, c) { body } else { default body }
238
237
case OSELRECV2 :
238
+ // if c != nil && selectnbrecv2(&v, c) { body } else { default body }
239
239
r = nod (OIF , nil , nil )
240
-
241
240
r .Ninit .Set (cas .Ninit .Slice ())
242
241
ch := n .Right .Left
243
242
r .Left = mkcall1 (chanfn ("selectnbrecv2" , 2 , ch .Type ), Types [TBOOL ], & r .Ninit , typename (ch .Type ), n .Left , n .List .First (), ch )
@@ -246,7 +245,7 @@ func walkselect(sel *Node) {
246
245
r .Left = typecheck (r .Left , Erv )
247
246
r .Nbody .Set (cas .Nbody .Slice ())
248
247
r .Rlist .Set (append (dflt .Ninit .Slice (), dflt .Nbody .Slice ()... ))
249
- sel .Nbody .Set1 ( r )
248
+ sel .Nbody .Set2 ( r , nod ( OBREAK , nil , nil ) )
250
249
goto out
251
250
}
252
251
@@ -255,7 +254,6 @@ func walkselect(sel *Node) {
255
254
256
255
// generate sel-struct
257
256
setlineno (sel )
258
-
259
257
selv = temp (selecttype (int32 (sel .Xoffset )))
260
258
r = nod (OAS , selv , nil )
261
259
r = typecheck (r , Etop )
@@ -264,52 +262,62 @@ func walkselect(sel *Node) {
264
262
r = mkcall ("newselect" , nil , nil , var_ , nodintconst (selv .Type .Width ), nodintconst (sel .Xoffset ))
265
263
r = typecheck (r , Etop )
266
264
init = append (init , r )
265
+
267
266
// register cases
268
267
for _ , cas := range sel .List .Slice () {
269
268
setlineno (cas )
270
- n = cas .Left
271
- r = nod (OIF , nil , nil )
272
- r .Ninit .Set (cas .Ninit .Slice ())
269
+
270
+ init = append (init , cas .Ninit .Slice ()... )
273
271
cas .Ninit .Set (nil )
274
- if n != nil {
275
- r .Ninit .AppendNodes (& n .Ninit )
276
- n .Ninit .Set (nil )
277
- }
278
272
279
- if n == nil {
280
- // selectdefault(sel *byte);
281
- r . Left = mkcall ( "selectdefault" , Types [ TBOOL ], & r .Ninit , var_ )
282
- } else {
273
+ var x * Node
274
+ if n := cas . Left ; n != nil {
275
+ init = append ( init , n .Ninit . Slice () ... )
276
+
283
277
switch n .Op {
284
278
default :
285
279
Fatalf ("select %v" , n .Op )
286
-
287
- // selectsend(sel *byte, hchan *chan any, elem *any) (selected bool);
288
280
case OSEND :
289
- r .Left = mkcall1 (chanfn ("selectsend" , 2 , n .Left .Type ), Types [TBOOL ], & r .Ninit , var_ , n .Left , n .Right )
290
-
291
- // selectrecv(sel *byte, hchan *chan any, elem *any) (selected bool);
281
+ // selectsend(sel *byte, hchan *chan any, elem *any)
282
+ x = mkcall1 (chanfn ("selectsend" , 2 , n .Left .Type ), nil , nil , var_ , n .Left , n .Right )
292
283
case OSELRECV :
293
- r .Left = mkcall1 (chanfn ("selectrecv" , 2 , n .Right .Left .Type ), Types [TBOOL ], & r .Ninit , var_ , n .Right .Left , n .Left )
294
-
295
- // selectrecv2(sel *byte, hchan *chan any, elem *any, received *bool) (selected bool);
284
+ // selectrecv(sel *byte, hchan *chan any, elem *any, received *bool)
285
+ x = mkcall1 (chanfn ("selectrecv" , 2 , n .Right .Left .Type ), nil , nil , var_ , n .Right .Left , n .Left , nodnil ())
296
286
case OSELRECV2 :
297
- r .Left = mkcall1 (chanfn ("selectrecv2" , 2 , n .Right .Left .Type ), Types [TBOOL ], & r .Ninit , var_ , n .Right .Left , n .Left , n .List .First ())
287
+ // selectrecv(sel *byte, hchan *chan any, elem *any, received *bool)
288
+ x = mkcall1 (chanfn ("selectrecv" , 2 , n .Right .Left .Type ), nil , nil , var_ , n .Right .Left , n .Left , n .List .First ())
298
289
}
290
+ } else {
291
+ // selectdefault(sel *byte)
292
+ x = mkcall ("selectdefault" , nil , nil , var_ )
299
293
}
300
294
301
- // selv is no longer alive after use.
302
- r .Nbody .Append (nod (OVARKILL , selv , nil ))
295
+ init = append (init , x )
296
+ }
297
+
298
+ // run the select
299
+ setlineno (sel )
300
+ chosen = temp (Types [TINT ])
301
+ r = nod (OAS , chosen , mkcall ("selectgo" , Types [TINT ], nil , var_ ))
302
+ r = typecheck (r , Etop )
303
+ init = append (init , r )
304
+
305
+ // selv is no longer alive after selectgo.
306
+ init = append (init , nod (OVARKILL , selv , nil ))
307
+
308
+ // dispatch cases
309
+ for i , cas := range sel .List .Slice () {
310
+ setlineno (cas )
303
311
312
+ cond := nod (OEQ , chosen , nodintconst (int64 (i )))
313
+ cond = typecheck (cond , Erv )
314
+
315
+ r = nod (OIF , cond , nil )
304
316
r .Nbody .AppendNodes (& cas .Nbody )
305
317
r .Nbody .Append (nod (OBREAK , nil , nil ))
306
318
init = append (init , r )
307
319
}
308
320
309
- // run the select
310
- setlineno (sel )
311
-
312
- init = append (init , mkcall ("selectgo" , nil , nil , var_ ))
313
321
sel .Nbody .Set (init )
314
322
315
323
out:
@@ -328,7 +336,6 @@ func selecttype(size int32) *Type {
328
336
scase .List .Append (nod (ODCLFIELD , newname (lookup ("chan" )), typenod (ptrto (Types [TUINT8 ]))))
329
337
scase .List .Append (nod (ODCLFIELD , newname (lookup ("pc" )), typenod (Types [TUINTPTR ])))
330
338
scase .List .Append (nod (ODCLFIELD , newname (lookup ("kind" )), typenod (Types [TUINT16 ])))
331
- scase .List .Append (nod (ODCLFIELD , newname (lookup ("so" )), typenod (Types [TUINT16 ])))
332
339
scase .List .Append (nod (ODCLFIELD , newname (lookup ("receivedp" )), typenod (ptrto (Types [TUINT8 ]))))
333
340
scase .List .Append (nod (ODCLFIELD , newname (lookup ("releasetime" )), typenod (Types [TUINT64 ])))
334
341
scase = typecheck (scase , Etype )
0 commit comments