summaryrefslogtreecommitdiff
path: root/gcc/go/gofrontend/statements.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/go/gofrontend/statements.cc')
-rw-r--r--gcc/go/gofrontend/statements.cc62
1 files changed, 31 insertions, 31 deletions
diff --git a/gcc/go/gofrontend/statements.cc b/gcc/go/gofrontend/statements.cc
index 2eb363a97982..41f1ffb06ac7 100644
--- a/gcc/go/gofrontend/statements.cc
+++ b/gcc/go/gofrontend/statements.cc
@@ -4330,7 +4330,6 @@ Send_statement::do_get_backend(Translate_context* context)
element_type,
this->val_, loc);
- bool is_small;
bool can_take_address;
switch (element_type->base()->classification())
{
@@ -4340,25 +4339,18 @@ Send_statement::do_get_backend(Translate_context* context)
case Type::TYPE_POINTER:
case Type::TYPE_MAP:
case Type::TYPE_CHANNEL:
- is_small = true;
- can_take_address = false;
- break;
-
case Type::TYPE_FLOAT:
case Type::TYPE_COMPLEX:
case Type::TYPE_STRING:
case Type::TYPE_INTERFACE:
- is_small = false;
can_take_address = false;
break;
case Type::TYPE_STRUCT:
- is_small = false;
can_take_address = true;
break;
case Type::TYPE_ARRAY:
- is_small = false;
can_take_address = !element_type->is_slice_type();
break;
@@ -4384,28 +4376,19 @@ Send_statement::do_get_backend(Translate_context* context)
Expression* td = Expression::make_type_descriptor(this->channel_->type(),
loc);
- Runtime::Function code;
Bstatement* btemp = NULL;
- if (is_small)
- {
- // Type is small enough to handle as uint64.
- code = Runtime::SEND_SMALL;
- val = Expression::make_unsafe_cast(Type::lookup_integer_type("uint64"),
- val, loc);
- }
- else if (can_take_address)
- {
- // Must pass address of value. The function doesn't change the
- // value, so just take its address directly.
- code = Runtime::SEND_BIG;
+ if (can_take_address)
+ {
+ // The function doesn't change the value, so just take its
+ // address directly.
val = Expression::make_unary(OPERATOR_AND, val, loc);
}
else
{
- // Must pass address of value, but the value is small enough
- // that it might be in registers. Copy value into temporary
- // variable to take address.
- code = Runtime::SEND_BIG;
+ // The value is not in a variable, or is small enough that it
+ // might be in a register, and taking the address would push it
+ // on the stack. Copy it into a temporary variable to take the
+ // address.
Temporary_statement* temp = Statement::make_temporary(element_type,
val, loc);
Expression* ref = Expression::make_temporary_reference(temp, loc);
@@ -4413,7 +4396,8 @@ Send_statement::do_get_backend(Translate_context* context)
btemp = temp->get_backend(context);
}
- Expression* call = Runtime::make_call(code, loc, 3, td, this->channel_, val);
+ Expression* call = Runtime::make_call(Runtime::CHANSEND, loc, 3, td,
+ this->channel_, val);
context->gogo()->lower_expression(context->function(), NULL, &call);
Bexpression* bcall = call->get_backend(context);
@@ -4491,6 +4475,7 @@ Select_clauses::Select_clause::lower(Gogo* gogo, Named_object* function,
Location loc = this->location_;
Expression* selref = Expression::make_temporary_reference(sel, loc);
+ selref = Expression::make_unary(OPERATOR_AND, selref, loc);
Expression* index_expr = Expression::make_integer_ul(this->index_, NULL,
loc);
@@ -4854,6 +4839,7 @@ Select_clauses::get_backend(Translate_context* context,
}
Expression* selref = Expression::make_temporary_reference(sel, location);
+ selref = Expression::make_unary(OPERATOR_AND, selref, location);
Expression* call = Runtime::make_call(Runtime::SELECTGO, location, 1,
selref);
context->gogo()->lower_expression(context->function(), NULL, &call);
@@ -4920,13 +4906,27 @@ Select_statement::do_lower(Gogo* gogo, Named_object* function,
go_assert(this->sel_ == NULL);
- Expression* size_expr = Expression::make_integer_ul(this->clauses_->size(),
- NULL, loc);
- Expression* call = Runtime::make_call(Runtime::NEWSELECT, loc, 1, size_expr);
-
- this->sel_ = Statement::make_temporary(NULL, call, loc);
+ int ncases = this->clauses_->size();
+ Type* selstruct_type = Channel_type::select_type(ncases);
+ this->sel_ = Statement::make_temporary(selstruct_type, NULL, loc);
b->add_statement(this->sel_);
+ int64_t selstruct_size;
+ if (!selstruct_type->backend_type_size(gogo, &selstruct_size))
+ {
+ go_assert(saw_errors());
+ return Statement::make_error_statement(loc);
+ }
+
+ Expression* ref = Expression::make_temporary_reference(this->sel_, loc);
+ ref = Expression::make_unary(OPERATOR_AND, ref, loc);
+ Expression* selstruct_size_expr =
+ Expression::make_integer_int64(selstruct_size, NULL, loc);
+ Expression* size_expr = Expression::make_integer_ul(ncases, NULL, loc);
+ Expression* call = Runtime::make_call(Runtime::NEWSELECT, loc, 3,
+ ref, selstruct_size_expr, size_expr);
+ b->add_statement(Statement::make_statement(call, true));
+
this->clauses_->lower(gogo, function, b, this->sel_);
this->is_lowered_ = true;
b->add_statement(this);