aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/go/gofrontend/MERGE2
-rw-r--r--gcc/go/gofrontend/expressions.cc102
-rw-r--r--gcc/go/gofrontend/expressions.h27
-rw-r--r--gcc/go/gofrontend/statements.cc55
-rw-r--r--gcc/go/gofrontend/statements.h14
5 files changed, 193 insertions, 7 deletions
diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE
index 8e220f50..74806a2 100644
--- a/gcc/go/gofrontend/MERGE
+++ b/gcc/go/gofrontend/MERGE
@@ -1,4 +1,4 @@
-b013405f2c66596c47cb9be493c798db1087c0f0
+a8f768d68760768da5e86a8e63ef1ad5691c3ae8
The first line of this file holds the git revision number of the last
merge done from the gofrontend repository.
diff --git a/gcc/go/gofrontend/expressions.cc b/gcc/go/gofrontend/expressions.cc
index 5f00eff..7c464ce 100644
--- a/gcc/go/gofrontend/expressions.cc
+++ b/gcc/go/gofrontend/expressions.cc
@@ -786,6 +786,31 @@ Var_expression::do_address_taken(bool escapes)
}
}
+// The cost to inline a variable reference. We currently only support
+// references to parameters.
+
+int
+Var_expression::do_inlining_cost() const
+{
+ if (this->variable_->is_variable())
+ {
+ if (this->variable_->var_value()->is_parameter())
+ return 1;
+ }
+ else if (this->variable_->is_result_variable())
+ return 1;
+
+ return 0x100000;
+}
+
+// Export a reference to a variable.
+
+void
+Var_expression::do_export(Export_function_body* efb) const
+{
+ efb->write_string(Gogo::unpack_hidden_name(this->variable_->name()));
+}
+
// Get the backend representation for a reference to a variable.
Bexpression*
@@ -1608,6 +1633,10 @@ class Boolean_expression : public Expression
do_get_backend(Translate_context* context)
{ return context->backend()->boolean_constant_expression(this->val_); }
+ int
+ do_inlining_cost() const
+ { return 1; }
+
void
do_export(Export_function_body* efb) const
{ efb->write_c_string(this->val_ ? "$true" : "$false"); }
@@ -1997,6 +2026,10 @@ class Integer_expression : public Expression
this->location());
}
+ int
+ do_inlining_cost() const
+ { return 1; }
+
void
do_export(Export_function_body*) const;
@@ -2408,6 +2441,10 @@ class Float_expression : public Expression
Bexpression*
do_get_backend(Translate_context*);
+ int
+ do_inlining_cost() const
+ { return 1; }
+
void
do_export(Export_function_body*) const;
@@ -2617,6 +2654,10 @@ class Complex_expression : public Expression
Bexpression*
do_get_backend(Translate_context*);
+ int
+ do_inlining_cost() const
+ { return 2; }
+
void
do_export(Export_function_body*) const;
@@ -3204,6 +3245,10 @@ class Nil_expression : public Expression
do_get_backend(Translate_context* context)
{ return context->backend()->nil_pointer_expression(); }
+ int
+ do_inlining_cost() const
+ { return 1; }
+
void
do_export(Export_function_body* efb) const
{ efb->write_c_string("$nil"); }
@@ -3654,6 +3699,25 @@ Type_conversion_expression::do_get_backend(Translate_context* context)
}
}
+// Cost of inlining a type conversion.
+
+int
+Type_conversion_expression::do_inlining_cost() const
+{
+ Type* type = this->type_;
+ Type* expr_type = this->expr_->type();
+ if (type->interface_type() != NULL || expr_type->interface_type() != NULL)
+ return 10;
+ else if (type->is_string_type() && expr_type->integer_type() != NULL)
+ return 10;
+ else if (type->is_string_type() && expr_type->is_slice_type())
+ return 10;
+ else if (type->is_slice_type() && expr_type->is_string_type())
+ return 10;
+ else
+ return 1;
+}
+
// Output a type conversion in a constant expression.
void
@@ -4677,7 +4741,11 @@ Unary_expression::do_export(Export_function_body* efb) const
efb->write_c_string("^");
break;
case OPERATOR_AND:
+ efb->write_c_string("&");
+ break;
case OPERATOR_MULT:
+ efb->write_c_string("*");
+ break;
default:
go_unreachable();
}
@@ -4704,6 +4772,12 @@ Unary_expression::do_import(Import_expression* imp, Location loc)
case '^':
op = OPERATOR_XOR;
break;
+ case '&':
+ op = OPERATOR_AND;
+ break;
+ case '*':
+ op = OPERATOR_MULT;
+ break;
default:
go_unreachable();
}
@@ -16195,7 +16269,7 @@ Expression*
Expression::import_expression(Import_expression* imp, Location loc)
{
int c = imp->peek_char();
- if (c == '+' || c == '-' || c == '!' || c == '^')
+ if (c == '+' || c == '-' || c == '!' || c == '^' || c == '&' || c == '*')
return Unary_expression::do_import(imp, loc);
else if (c == '(')
return Binary_expression::do_import(imp, loc);
@@ -16220,11 +16294,35 @@ Expression::import_expression(Import_expression* imp, Location loc)
|| (imp->version() < EXPORT_FORMAT_V3
&& imp->match_c_string("convert")))
return Type_conversion_expression::do_import(imp, loc);
- else
+
+ Import_function_body* ifb = imp->ifb();
+ if (ifb == NULL)
{
go_error_at(imp->location(), "import error: expected expression");
return Expression::make_error(loc);
}
+ if (ifb->saw_error())
+ return Expression::make_error(loc);
+ std::string id = ifb->read_identifier();
+ if (id.empty())
+ {
+ if (!ifb->saw_error())
+ go_error_at(imp->location(),
+ "import error: expected identifier at %lu",
+ static_cast<unsigned long>(ifb->off()));
+ ifb->set_saw_error();
+ return Expression::make_error(loc);
+ }
+ Named_object* var = ifb->block()->bindings()->lookup(id);
+ if (var == NULL)
+ {
+ if (!ifb->saw_error())
+ go_error_at(imp->location(), "import error: lookup of %qs failed",
+ id.c_str());
+ ifb->set_saw_error();
+ return Expression::make_error(loc);
+ }
+ return Expression::make_var_reference(var, loc);
}
// Class Expression_list.
diff --git a/gcc/go/gofrontend/expressions.h b/gcc/go/gofrontend/expressions.h
index 7061657..a18322c 100644
--- a/gcc/go/gofrontend/expressions.h
+++ b/gcc/go/gofrontend/expressions.h
@@ -941,7 +941,7 @@ class Expression
// Return the cost of this statement for inlining purposes.
int
- inlining_cost()
+ inlining_cost() const
{ return this->do_inlining_cost(); }
// Return whether the expression is addressable--something which may
@@ -1093,7 +1093,7 @@ class Expression
// inlining. The default cost is high, so we only need to define
// this method for expressions that can be inlined.
virtual int
- do_inlining_cost()
+ do_inlining_cost() const
{ return 0x100000; }
// Child class implements whether the expression is addressable.
@@ -1355,6 +1355,12 @@ class Var_expression : public Expression
do_copy()
{ return this; }
+ int
+ do_inlining_cost() const;
+
+ void
+ do_export(Export_function_body*) const;
+
bool
do_is_addressable() const
{ return true; }
@@ -1602,6 +1608,12 @@ class String_expression : public Expression
static void
export_string(String_dump* exp, const String_expression* str);
+ // Set the inlining cost a bit high since inlining may cause
+ // duplicated string literals.
+ int
+ do_inlining_cost() const
+ { return 5; }
+
void
do_export(Export_function_body*) const;
@@ -1686,6 +1698,9 @@ class Type_conversion_expression : public Expression
Bexpression*
do_get_backend(Translate_context* context);
+ int
+ do_inlining_cost() const;
+
void
do_export(Export_function_body*) const;
@@ -1877,6 +1892,10 @@ class Unary_expression : public Expression
Bexpression*
do_get_backend(Translate_context*);
+ int
+ do_inlining_cost() const
+ { return 1; }
+
void
do_export(Export_function_body*) const;
@@ -2022,6 +2041,10 @@ class Binary_expression : public Expression
Bexpression*
do_get_backend(Translate_context*);
+ int
+ do_inlining_cost() const
+ { return 1; }
+
void
do_export(Export_function_body*) const;
diff --git a/gcc/go/gofrontend/statements.cc b/gcc/go/gofrontend/statements.cc
index 60b7a70..4d10f60 100644
--- a/gcc/go/gofrontend/statements.cc
+++ b/gcc/go/gofrontend/statements.cc
@@ -12,6 +12,7 @@
#include "expressions.h"
#include "gogo.h"
#include "export.h"
+#include "import.h"
#include "runtime.h"
#include "backend.h"
#include "statements.h"
@@ -124,9 +125,41 @@ Statement::determine_types()
// Read a statement from export data.
Statement*
-Statement::import_statement(Import_function_body*, Location)
+Statement::import_statement(Import_function_body* ifb, Location loc)
{
- go_unreachable();
+ if (ifb->match_c_string("{"))
+ {
+ size_t nl = ifb->body().find('\n', ifb->off());
+ if (nl == std::string::npos)
+ {
+ if (!ifb->saw_error())
+ go_error_at(ifb->location(),
+ "import error: no newline after { at %lu",
+ static_cast<unsigned long>(ifb->off()));
+ ifb->set_saw_error();
+ return Statement::make_error_statement(loc);
+ }
+ ifb->set_off(nl + 1);
+ ifb->increment_indent();
+ Block* block = new Block(ifb->block(), loc);
+ bool ok = Block::import_block(block, ifb, loc);
+ ifb->decrement_indent();
+ if (!ok)
+ return Statement::make_error_statement(loc);
+ return Statement::make_block_statement(block, loc);
+ }
+ else if (ifb->match_c_string("return"))
+ {
+ // After lowering return statements have no expressions. The
+ // return expressions are assigned to result parameters.
+ ifb->advance(6);
+ return Statement::make_return_statement(NULL, loc);
+ }
+
+ Expression* lhs = Expression::import_expression(ifb, loc);
+ ifb->require_c_string(" = ");
+ Expression* rhs = Expression::import_expression(ifb, loc);
+ return Statement::make_assignment(lhs, rhs, loc);
}
// If this is a thunk statement, return it.
@@ -834,6 +867,14 @@ Assignment_statement::do_check_types(Gogo*)
this->set_is_error();
}
+void
+Assignment_statement::do_export_statement(Export_function_body* efb)
+{
+ this->lhs_->export_expression(efb);
+ efb->write_c_string(" = ");
+ this->rhs_->export_expression(efb);
+}
+
// Flatten an assignment statement. We may need a temporary for
// interface conversion.
@@ -2844,6 +2885,16 @@ Return_statement::do_get_backend(Translate_context* context)
retvals, loc);
}
+// Export a return statement. At this point all the expressions have
+// been converted to assignments to the result variables, so this is
+// simple.
+
+void
+Return_statement::do_export_statement(Export_function_body* efb)
+{
+ efb->write_c_string("return");
+}
+
// Dump the AST representation for a return statement.
void
diff --git a/gcc/go/gofrontend/statements.h b/gcc/go/gofrontend/statements.h
index 3b5c68a..621d301 100644
--- a/gcc/go/gofrontend/statements.h
+++ b/gcc/go/gofrontend/statements.h
@@ -631,6 +631,13 @@ class Assignment_statement : public Statement
void
do_check_types(Gogo*);
+ int
+ do_inlining_cost()
+ { return 1; }
+
+ void
+ do_export_statement(Export_function_body*);
+
Statement*
do_flatten(Gogo*, Named_object*, Block*, Statement_inserter*);
@@ -792,6 +799,13 @@ class Return_statement : public Statement
do_may_fall_through() const
{ return false; }
+ int
+ do_inlining_cost()
+ { return 1; }
+
+ void
+ do_export_statement(Export_function_body*);
+
Bstatement*
do_get_backend(Translate_context*);