diff options
author | Ian Lance Taylor <ian@gcc.gnu.org> | 2018-11-28 18:08:21 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@gcc.gnu.org> | 2018-11-28 18:08:21 +0000 |
commit | 5456f30d92062d234208cd8634e54787f6e2664f (patch) | |
tree | 023b9e1979b33d40c37b642607932fe34787f69a /gcc/go/gofrontend/expressions.cc | |
parent | 85041a5b7755dc7b9d74b183e933d89152997886 (diff) | |
download | gcc-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.cc | 102 |
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. |