@@ -5291,22 +5291,23 @@ Select_clauses::Select_clause::traverse(Traverse* traverse)
5291
5291
void
5292
5292
Select_clauses::Select_clause::lower (Gogo* gogo, Named_object* function,
5293
5293
Block* b, Temporary_statement* scases,
5294
- size_t index, Temporary_statement* recvok)
5294
+ int index, Temporary_statement* recvok)
5295
5295
{
5296
5296
Location loc = this ->location_ ;
5297
5297
5298
- Expression* scase = Expression::make_temporary_reference (scases, loc);
5299
- Expression* index_expr = Expression::make_integer_ul (index , NULL , loc);
5300
- scase = Expression::make_array_index (scase, index_expr, NULL , NULL , loc);
5298
+ this ->set_case_index (index );
5301
5299
5302
5300
if (this ->is_default_ )
5303
5301
{
5304
5302
go_assert (this ->channel_ == NULL && this ->val_ == NULL );
5305
- this ->lower_default (b, scase);
5306
5303
this ->is_lowered_ = true ;
5307
5304
return ;
5308
5305
}
5309
5306
5307
+ Expression* scase = Expression::make_temporary_reference (scases, loc);
5308
+ Expression* index_expr = Expression::make_integer_sl (index , NULL , loc);
5309
+ scase = Expression::make_array_index (scase, index_expr, NULL , NULL , loc);
5310
+
5310
5311
// Evaluate the channel before the select statement.
5311
5312
Temporary_statement* channel_temp = Statement::make_temporary (NULL ,
5312
5313
this ->channel_ ,
@@ -5326,15 +5327,6 @@ Select_clauses::Select_clause::lower(Gogo* gogo, Named_object* function,
5326
5327
this ->val_ = NULL ;
5327
5328
}
5328
5329
5329
- // Lower a default clause in a select statement.
5330
-
5331
- void
5332
- Select_clauses::Select_clause::lower_default (Block* b, Expression* scase)
5333
- {
5334
- Location loc = this ->location_ ;
5335
- this ->set_case (b, scase, Expression::make_nil (loc), NULL , caseDefault);
5336
- }
5337
-
5338
5330
// Lower a send clause in a select statement.
5339
5331
5340
5332
void
@@ -5366,7 +5358,7 @@ Select_clauses::Select_clause::lower_send(Block* b, Expression* scase,
5366
5358
Type* unsafe_pointer_type = Type::make_pointer_type (Type::make_void_type ());
5367
5359
valaddr = Expression::make_cast (unsafe_pointer_type, valaddr, loc);
5368
5360
5369
- this ->set_case (b, scase, chanref, valaddr, caseSend );
5361
+ this ->set_case (b, scase, chanref, valaddr);
5370
5362
}
5371
5363
5372
5364
// Lower a receive clause in a select statement.
@@ -5392,7 +5384,7 @@ Select_clauses::Select_clause::lower_recv(Gogo* gogo, Named_object* function,
5392
5384
Type* unsafe_pointer_type = Type::make_pointer_type (Type::make_void_type ());
5393
5385
valaddr = Expression::make_cast (unsafe_pointer_type, valaddr, loc);
5394
5386
5395
- this ->set_case (b, scase, chanref, valaddr, caseRecv );
5387
+ this ->set_case (b, scase, chanref, valaddr);
5396
5388
5397
5389
// If the block of statements is executed, arrange for the received
5398
5390
// value to move from VAL to the place where the statements expect
@@ -5447,8 +5439,7 @@ void
5447
5439
Select_clauses::Select_clause::set_case (Block* b,
5448
5440
Expression* scase,
5449
5441
Expression* chanref,
5450
- Expression* elem,
5451
- int kind)
5442
+ Expression* elem)
5452
5443
{
5453
5444
Location loc = this ->location_ ;
5454
5445
Struct_type* scase_type = scase->type ()->struct_type ();
@@ -5469,14 +5460,6 @@ Select_clauses::Select_clause::set_case(Block* b,
5469
5460
s = Statement::make_assignment (ref, elem, loc);
5470
5461
b->add_statement (s);
5471
5462
}
5472
-
5473
- field_index = 2 ;
5474
- go_assert (scase_type->field (field_index)->is_field_name (" kind" ));
5475
- Type* uint16_type = Type::lookup_integer_type (" uint16" );
5476
- Expression* k = Expression::make_integer_ul (kind, uint16_type, loc);
5477
- ref = Expression::make_field_reference (scase->copy (), field_index, loc);
5478
- s = Statement::make_assignment (ref, k, loc);
5479
- b->add_statement (s);
5480
5463
}
5481
5464
5482
5465
// Determine types.
@@ -5577,6 +5560,19 @@ Select_clauses::Select_clause::dump_clause(
5577
5560
5578
5561
// Class Select_clauses.
5579
5562
5563
+ // Whether there is a default case.
5564
+
5565
+ bool
5566
+ Select_clauses::has_default () const
5567
+ {
5568
+ for (Clauses::const_iterator p = this ->clauses_ .begin ();
5569
+ p != this ->clauses_ .end ();
5570
+ ++p)
5571
+ if (p->is_default ())
5572
+ return true ;
5573
+ return false ;
5574
+ }
5575
+
5580
5576
// Traversal.
5581
5577
5582
5578
int
@@ -5594,17 +5590,60 @@ Select_clauses::traverse(Traverse* traverse)
5594
5590
5595
5591
// Lowering. Here we pull out the channel and the send values, to
5596
5592
// enforce the order of evaluation. We also add explicit send and
5597
- // receive statements to the clauses.
5593
+ // receive statements to the clauses. This builds the entries in the
5594
+ // local array of scase values. It sets *P_SEND_COUNT and
5595
+ // *P_RECV_COUNT.
5598
5596
5599
5597
void
5600
5598
Select_clauses::lower (Gogo* gogo, Named_object* function, Block* b,
5601
- Temporary_statement* scases, Temporary_statement* recvok)
5599
+ Temporary_statement* scases, Temporary_statement* recvok,
5600
+ int *p_send_count, int *p_recv_count)
5602
5601
{
5603
- size_t i = 0 ;
5602
+ int send_count = 0 ;
5603
+ int recv_count = 0 ;
5604
+ bool has_default = false ;
5604
5605
for (Clauses::iterator p = this ->clauses_ .begin ();
5605
5606
p != this ->clauses_ .end ();
5606
- ++p, ++i)
5607
- p->lower (gogo, function, b, scases, i, recvok);
5607
+ ++p)
5608
+ {
5609
+ if (p->is_default ())
5610
+ has_default = true ;
5611
+ else if (p->is_send ())
5612
+ ++send_count;
5613
+ else
5614
+ ++recv_count;
5615
+ }
5616
+
5617
+ *p_send_count = send_count;
5618
+ *p_recv_count = recv_count;
5619
+
5620
+ int send_index = 0 ;
5621
+ int recv_index = send_count;
5622
+ for (Clauses::iterator p = this ->clauses_ .begin ();
5623
+ p != this ->clauses_ .end ();
5624
+ ++p)
5625
+ {
5626
+ int index ;
5627
+ if (p->is_default ())
5628
+ index = -1 ;
5629
+ else if (p->is_send ())
5630
+ {
5631
+ index = send_index;
5632
+ ++send_index;
5633
+ }
5634
+ else
5635
+ {
5636
+ index = recv_index;
5637
+ ++recv_index;
5638
+ }
5639
+
5640
+ p->lower (gogo, function, b, scases, index , recvok);
5641
+ }
5642
+
5643
+ go_assert (send_index == send_count);
5644
+ go_assert (recv_index == send_count + recv_count);
5645
+ go_assert (static_cast <size_t >(recv_index + (has_default ? 1 : 0 ))
5646
+ == this ->size ());
5608
5647
}
5609
5648
5610
5649
// Determine types.
@@ -5664,7 +5703,8 @@ Select_clauses::get_backend(Translate_context* context,
5664
5703
p != this ->clauses_ .end ();
5665
5704
++p, ++i)
5666
5705
{
5667
- Expression* index_expr = Expression::make_integer_ul (i, int_type,
5706
+ Expression* index_expr = Expression::make_integer_sl (p->case_index (),
5707
+ int_type,
5668
5708
location);
5669
5709
cases[i].push_back (index_expr->get_backend (context));
5670
5710
@@ -5749,6 +5789,7 @@ Select_statement::do_lower(Gogo* gogo, Named_object* function,
5749
5789
Block* b = new Block (enclosing, loc);
5750
5790
5751
5791
int ncases = this ->clauses_ ->size ();
5792
+ bool has_default = this ->clauses_ ->has_default ();
5752
5793
5753
5794
// Zero-case select. Just block the execution.
5754
5795
if (ncases == 0 )
@@ -5766,11 +5807,13 @@ Select_statement::do_lower(Gogo* gogo, Named_object* function,
5766
5807
5767
5808
// Two-case select with one default case. It is a non-blocking
5768
5809
// send/receive.
5769
- if (ncases == 2
5770
- && (this ->clauses_ ->at (0 ).is_default ()
5771
- || this ->clauses_ ->at (1 ).is_default ()))
5810
+ if (ncases == 2 && has_default)
5772
5811
return this ->lower_two_case (b);
5773
5812
5813
+ // We don't allocate an entry in scases for the default case.
5814
+ if (has_default)
5815
+ --ncases;
5816
+
5774
5817
Type* scase_type = Channel_type::select_case_type ();
5775
5818
Expression* ncases_expr =
5776
5819
Expression::make_integer_ul (ncases, NULL ,
@@ -5803,7 +5846,10 @@ Select_statement::do_lower(Gogo* gogo, Named_object* function,
5803
5846
b->add_statement (recvok);
5804
5847
5805
5848
// Initialize the scases array.
5806
- this ->clauses_ ->lower (gogo, function, b, scases, recvok);
5849
+ int send_count;
5850
+ int recv_count;
5851
+ this ->clauses_ ->lower (gogo, function, b, scases, recvok, &send_count,
5852
+ &recv_count);
5807
5853
5808
5854
// Build the call to selectgo. Later, in do_get_backend, we will
5809
5855
// build a switch on the result that branches to the various cases.
@@ -5817,11 +5863,18 @@ Select_statement::do_lower(Gogo* gogo, Named_object* function,
5817
5863
order_ref = Expression::make_unary (OPERATOR_AND, order_ref, loc);
5818
5864
order_ref = Expression::make_cast (unsafe_pointer_type, order_ref, loc);
5819
5865
5820
- Expression* count_expr = Expression::make_integer_ul (ncases, int_type, loc);
5866
+ Expression* send_count_expr = Expression::make_integer_sl (send_count,
5867
+ int_type,
5868
+ loc);
5869
+ Expression* recv_count_expr = Expression::make_integer_sl (recv_count,
5870
+ int_type,
5871
+ loc);
5872
+ Expression* block_expr = Expression::make_boolean (!has_default, loc);
5821
5873
5822
- Call_expression* call = Runtime::make_call (Runtime::SELECTGO, loc, 3 ,
5874
+ Call_expression* call = Runtime::make_call (Runtime::SELECTGO, loc, 5 ,
5823
5875
scases_ref, order_ref,
5824
- count_expr);
5876
+ send_count_expr, recv_count_expr,
5877
+ block_expr);
5825
5878
5826
5879
Expression* result = Expression::make_call_result (call, 0 );
5827
5880
Expression* ref = Expression::make_temporary_reference (this ->index_ , loc);
0 commit comments