aboutsummaryrefslogtreecommitdiff
path: root/gcc/go/gofrontend/expressions.cc
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@gcc.gnu.org>2018-11-28 18:08:21 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2018-11-28 18:08:21 +0000
commit5456f30d92062d234208cd8634e54787f6e2664f (patch)
tree023b9e1979b33d40c37b642607932fe34787f69a /gcc/go/gofrontend/expressions.cc
parent85041a5b7755dc7b9d74b183e933d89152997886 (diff)
downloadgcc-5456f30d92062d234208cd8634e54787f6e2664f.zip
gcc-5456f30d92062d234208cd8634e54787f6e2664f.tar.gz
gcc-5456f30d92062d234208cd8634e54787f6e2664f.tar.bz2
compiler: inline functions with assignments and return statements
Support inlining functions that contain only assignments and return statements, with expressions of either constants or parameters. Functions that contain other kinds of statements or expressions are not yet inlined. With this change, about 100 functions in the standard library are inlinable. Reviewed-on: https://go-review.googlesource.com/c/150073 From-SVN: r266573
Diffstat (limited to 'gcc/go/gofrontend/expressions.cc')
-rw-r--r--gcc/go/gofrontend/expressions.cc102
1 files changed, 100 insertions, 2 deletions
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.