aboutsummaryrefslogtreecommitdiff
path: root/gcc/go/gofrontend/expressions.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/go/gofrontend/expressions.cc')
-rw-r--r--gcc/go/gofrontend/expressions.cc187
1 files changed, 62 insertions, 125 deletions
diff --git a/gcc/go/gofrontend/expressions.cc b/gcc/go/gofrontend/expressions.cc
index 597f0a0daef..6f9c1c96c3f 100644
--- a/gcc/go/gofrontend/expressions.cc
+++ b/gcc/go/gofrontend/expressions.cc
@@ -5655,7 +5655,7 @@ Binary_expression::do_determine_type(const Type_context* context)
Type_context subcontext(*context);
- if (is_constant_expr)
+ if (is_constant_expr && !is_shift_op)
{
subcontext.type = NULL;
subcontext.may_be_abstract = true;
@@ -9463,24 +9463,28 @@ Call_expression::do_lower(Gogo* gogo, Named_object* function,
this->is_varargs_, loc);
// If this call returns multiple results, create a temporary
- // variable for each result.
- size_t rc = this->result_count();
- if (rc > 1 && this->results_ == NULL)
+ // variable to hold them.
+ if (this->result_count() > 1 && this->call_temp_ == NULL)
{
- std::vector<Temporary_statement*>* temps =
- new std::vector<Temporary_statement*>;
- temps->reserve(rc);
+ Struct_field_list* sfl = new Struct_field_list();
+ Function_type* fntype = this->get_function_type();
const Typed_identifier_list* results = fntype->results();
+ Location loc = this->location();
+
+ int i = 0;
+ char buf[20];
for (Typed_identifier_list::const_iterator p = results->begin();
- p != results->end();
- ++p)
- {
- Temporary_statement* temp = Statement::make_temporary(p->type(),
- NULL, loc);
- inserter->insert(temp);
- temps->push_back(temp);
- }
- this->results_ = temps;
+ p != results->end();
+ ++p, ++i)
+ {
+ snprintf(buf, sizeof buf, "res%d", i);
+ sfl->push_back(Struct_field(Typed_identifier(buf, p->type(), loc)));
+ }
+
+ Struct_type* st = Type::make_struct_type(sfl, loc);
+ st->set_is_struct_incomparable();
+ this->call_temp_ = Statement::make_temporary(st, NULL, loc);
+ inserter->insert(this->call_temp_);
}
// Handle a call to a varargs function by packaging up the extra
@@ -9779,30 +9783,6 @@ Call_expression::do_flatten(Gogo* gogo, Named_object*,
this->args_ = args;
}
- size_t rc = this->result_count();
- if (rc > 1 && this->call_temp_ == NULL)
- {
- Struct_field_list* sfl = new Struct_field_list();
- Function_type* fntype = this->get_function_type();
- const Typed_identifier_list* results = fntype->results();
- Location loc = this->location();
-
- int i = 0;
- char buf[20];
- for (Typed_identifier_list::const_iterator p = results->begin();
- p != results->end();
- ++p, ++i)
- {
- snprintf(buf, sizeof buf, "res%d", i);
- sfl->push_back(Struct_field(Typed_identifier(buf, p->type(), loc)));
- }
-
- Struct_type* st = Type::make_struct_type(sfl, loc);
- st->set_is_struct_incomparable();
- this->call_temp_ = Statement::make_temporary(st, NULL, loc);
- inserter->insert(this->call_temp_);
- }
-
return this;
}
@@ -9827,17 +9807,18 @@ Call_expression::result_count() const
return fntype->results()->size();
}
-// Return the temporary which holds a result.
+// Return the temporary that holds the result for a call with multiple
+// results.
Temporary_statement*
-Call_expression::result(size_t i) const
+Call_expression::results() const
{
- if (this->results_ == NULL || this->results_->size() <= i)
+ if (this->call_temp_ == NULL)
{
go_assert(saw_errors());
return NULL;
}
- return (*this->results_)[i];
+ return this->call_temp_;
}
// Set the number of results expected from a call expression.
@@ -10191,8 +10172,21 @@ Call_expression::interface_method_function(
Bexpression*
Call_expression::do_get_backend(Translate_context* context)
{
+ Location location = this->location();
+
if (this->call_ != NULL)
- return this->call_;
+ {
+ // If the call returns multiple results, make a new reference to
+ // the temporary.
+ if (this->call_temp_ != NULL)
+ {
+ Expression* ref =
+ Expression::make_temporary_reference(this->call_temp_, location);
+ return ref->get_backend(context);
+ }
+
+ return this->call_;
+ }
Function_type* fntype = this->get_function_type();
if (fntype == NULL)
@@ -10202,7 +10196,6 @@ Call_expression::do_get_backend(Translate_context* context)
return context->backend()->error_expression();
Gogo* gogo = context->gogo();
- Location location = this->location();
Func_expression* func = this->fn_->func_expression();
Interface_field_reference_expression* interface_method =
@@ -10323,91 +10316,28 @@ Call_expression::do_get_backend(Translate_context* context)
fn_args, bclosure,
location);
- if (this->results_ != NULL)
+ if (this->call_temp_ != NULL)
{
- Bexpression* bcall_ref = this->call_result_ref(context);
- Bstatement* assn_stmt =
- gogo->backend()->assignment_statement(bfunction,
- bcall_ref, call, location);
+ // This case occurs when the call returns multiple results.
- this->call_ = this->set_results(context);
+ Expression* ref = Expression::make_temporary_reference(this->call_temp_,
+ location);
+ Bexpression* bref = ref->get_backend(context);
+ Bstatement* bassn = gogo->backend()->assignment_statement(bfunction,
+ bref, call,
+ location);
- Bexpression* set_and_call =
- gogo->backend()->compound_expression(assn_stmt, this->call_,
- location);
- return set_and_call;
+ ref = Expression::make_temporary_reference(this->call_temp_, location);
+ this->call_ = ref->get_backend(context);
+
+ return gogo->backend()->compound_expression(bassn, this->call_,
+ location);
}
this->call_ = call;
return this->call_;
}
-// Return the backend representation of a reference to the struct used
-// to capture the result of a multiple-output call.
-
-Bexpression*
-Call_expression::call_result_ref(Translate_context* context)
-{
- go_assert(this->call_temp_ != NULL);
- Location location = this->location();
- Expression* call_ref =
- Expression::make_temporary_reference(this->call_temp_, location);
- Bexpression* bcall_ref = call_ref->get_backend(context);
- return bcall_ref;
-}
-
-// Set the result variables if this call returns multiple results.
-
-Bexpression*
-Call_expression::set_results(Translate_context* context)
-{
- Gogo* gogo = context->gogo();
-
- Bexpression* results = NULL;
- Location loc = this->location();
-
- go_assert(this->call_temp_ != NULL);
-
- size_t rc = this->result_count();
- for (size_t i = 0; i < rc; ++i)
- {
- Temporary_statement* temp = this->result(i);
- if (temp == NULL)
- {
- go_assert(saw_errors());
- return gogo->backend()->error_expression();
- }
- Temporary_reference_expression* ref =
- Expression::make_temporary_reference(temp, loc);
- ref->set_is_lvalue();
-
- Bfunction* bfunction = context->function()->func_value()->get_decl();
- Bexpression* result_ref = ref->get_backend(context);
- Bexpression* bcall_ref = this->call_result_ref(context);
- Bexpression* call_result =
- gogo->backend()->struct_field_expression(bcall_ref, i, loc);
- Bstatement* assn_stmt =
- gogo->backend()->assignment_statement(bfunction,
- result_ref, call_result, loc);
-
- bcall_ref = this->call_result_ref(context);
- call_result = gogo->backend()->struct_field_expression(bcall_ref, i, loc);
- Bexpression* result =
- gogo->backend()->compound_expression(assn_stmt, call_result, loc);
-
- if (results == NULL)
- results = result;
- else
- {
- Bstatement* expr_stmt =
- gogo->backend()->expression_statement(bfunction, result);
- results =
- gogo->backend()->compound_expression(expr_stmt, results, loc);
- }
- }
- return results;
-}
-
// Dump ast representation for a call expressin.
void
@@ -10528,13 +10458,14 @@ Call_result_expression::do_get_backend(Translate_context* context)
go_assert(this->call_->is_error_expression());
return context->backend()->error_expression();
}
- Temporary_statement* ts = ce->result(this->index_);
+ Temporary_statement* ts = ce->results();
if (ts == NULL)
{
go_assert(saw_errors());
return context->backend()->error_expression();
}
Expression* ref = Expression::make_temporary_reference(ts, this->location());
+ ref = Expression::make_field_reference(ref, this->index_, this->location());
return ref->get_backend(context);
}
@@ -12126,12 +12057,15 @@ Interface_field_reference_expression::do_get_backend(Translate_context* context)
Bexpression* bclosure =
Expression::make_heap_expression(expr, loc)->get_backend(context);
+ Gogo* gogo = context->gogo();
+ Btype* btype = this->type()->get_backend(gogo);
+ bclosure = gogo->backend()->convert_expression(btype, bclosure, loc);
+
Expression* nil_check =
Expression::make_binary(OPERATOR_EQEQ, this->expr_,
Expression::make_nil(loc), loc);
Bexpression* bnil_check = nil_check->get_backend(context);
- Gogo* gogo = context->gogo();
Bexpression* bcrash = gogo->runtime_error(RUNTIME_ERROR_NIL_DEREFERENCE,
loc)->get_backend(context);
@@ -14307,7 +14241,10 @@ Type_guard_expression::do_get_backend(Translate_context* context)
Expression::convert_for_assignment(context->gogo(), this->type_,
this->expr_, this->location());
- return conversion->get_backend(context);
+ Gogo* gogo = context->gogo();
+ Btype* bt = this->type_->get_backend(gogo);
+ Bexpression* bexpr = conversion->get_backend(context);
+ return gogo->backend()->convert_expression(bt, bexpr, this->location());
}
// Dump ast representation for a type guard expression.