From: Ian Lance Taylor Date: Fri, 10 May 2019 13:44:36 +0000 (+0000) Subject: compiler: permit inlining variable declaration statements X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=93d2b7038de17c5a675c07490ab55b77af815604;p=gcc.git compiler: permit inlining variable declaration statements This adds all of two inlinable functions to the standard library: crypto/subtle.ConstantTimeLessOrEq, regexp.(*Regexp).Copy. Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/176378 From-SVN: r271063 --- diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE index b6017708540..8158367c62b 100644 --- a/gcc/go/gofrontend/MERGE +++ b/gcc/go/gofrontend/MERGE @@ -1,4 +1,4 @@ -3dbf51c01c5d0acbf9ae47f77166fa9935881749 +b5e4ba88a2e7f3c34e9183f43370c38ea639c393 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 929571b29e4..ed658524240 100644 --- a/gcc/go/gofrontend/expressions.cc +++ b/gcc/go/gofrontend/expressions.cc @@ -843,14 +843,14 @@ Var_expression::do_address_taken(bool escapes) } // The cost to inline a variable reference. We currently only support -// references to parameters. +// references to parameters and local variables. int Var_expression::do_inlining_cost() const { if (this->variable_->is_variable()) { - if (this->variable_->var_value()->is_parameter()) + if (!this->variable_->var_value()->is_global()) return 1; } else if (this->variable_->is_result_variable()) diff --git a/gcc/go/gofrontend/statements.cc b/gcc/go/gofrontend/statements.cc index 67ab18469a5..cd1b60199e8 100644 --- a/gcc/go/gofrontend/statements.cc +++ b/gcc/go/gofrontend/statements.cc @@ -155,6 +155,8 @@ Statement::import_statement(Import_function_body* ifb, Location loc) ifb->advance(6); return Statement::make_return_statement(NULL, loc); } + else if (ifb->match_c_string("var ")) + return Variable_declaration_statement::do_import(ifb, loc); Expression* lhs = Expression::import_expression(ifb, loc); ifb->require_c_string(" = "); @@ -408,6 +410,57 @@ Statement::make_variable_declaration(Named_object* var) return new Variable_declaration_statement(var); } +// Export a variable declaration. + +void +Variable_declaration_statement::do_export_statement(Export_function_body* efb) +{ + efb->write_c_string("var "); + efb->write_string(Gogo::unpack_hidden_name(this->var_->name())); + efb->write_c_string(" "); + Variable* var = this->var_->var_value(); + Type* type = var->type(); + efb->write_type(type); + Expression* init = var->init(); + if (init != NULL) + { + efb->write_c_string(" = "); + + go_assert(efb->type_context() == NULL); + efb->set_type_context(type); + + init->export_expression(efb); + + efb->set_type_context(NULL); + } +} + +// Import a variable declaration. + +Statement* +Variable_declaration_statement::do_import(Import_function_body* ifb, + Location loc) +{ + ifb->require_c_string("var "); + std::string id = ifb->read_identifier(); + ifb->require_c_string(" "); + Type* type = ifb->read_type(); + Expression* init = NULL; + if (ifb->match_c_string(" = ")) + { + ifb->advance(3); + init = Expression::import_expression(ifb, loc); + Type_context context(type, false); + init->determine_type(&context); + } + Variable* var = new Variable(type, init, false, false, false, loc); + var->set_is_used(); + // FIXME: The package we are importing does not yet exist, so we + // can't pass the correct package here. It probably doesn't matter. + Named_object* no = ifb->block()->bindings()->add_variable(id, NULL, var); + return Statement::make_variable_declaration(no); +} + // Class Temporary_statement. // Return the type of the temporary variable. diff --git a/gcc/go/gofrontend/statements.h b/gcc/go/gofrontend/statements.h index ec9ade3f9e7..19ccb85a4bd 100644 --- a/gcc/go/gofrontend/statements.h +++ b/gcc/go/gofrontend/statements.h @@ -16,6 +16,7 @@ class Block; class Function; class Unnamed_label; class Export_function_body; +class Import_function_body; class Assignment_statement; class Temporary_statement; class Variable_declaration_statement; @@ -332,8 +333,7 @@ class Statement inlining_cost() { return this->do_inlining_cost(); } - // Export data for this statement to BODY. INDENT is an indentation - // level used if the export data requires multiple lines. + // Export data for this statement to BODY. void export_statement(Export_function_body* efb) { this->do_export_statement(efb); } @@ -514,10 +514,8 @@ class Statement { return 0x100000; } // Implemented by child class: write export data for this statement - // to the string. The integer is an indentation level used if the - // export data requires multiple lines. This need only be - // implemented by classes that implement do_inlining_cost with a - // reasonable value. + // to the string. This need only be implemented by classes that + // implement do_inlining_cost with a reasonable value. virtual void do_export_statement(Export_function_body*) { go_unreachable(); } @@ -746,6 +744,10 @@ class Variable_declaration_statement : public Statement var() { return this->var_; } + // Import a variable declaration. + static Statement* + do_import(Import_function_body*, Location); + protected: int do_traverse(Traverse*); @@ -756,6 +758,13 @@ class Variable_declaration_statement : public Statement Statement* do_lower(Gogo*, Named_object*, Block*, Statement_inserter*); + int + do_inlining_cost() + { return 1; } + + void + do_export_statement(Export_function_body*); + Statement* do_flatten(Gogo*, Named_object*, Block*, Statement_inserter*);