diff options
author | Ian Lance Taylor <ian@gcc.gnu.org> | 2019-06-06 23:34:00 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@gcc.gnu.org> | 2019-06-06 23:34:00 +0000 |
commit | 93cbebde76ac7de2d69b223d99acb39e0370687f (patch) | |
tree | 66c133d573a219583b5c460b329b900c18ee0ac6 /gcc/go/gofrontend/statements.cc | |
parent | 5e664ed0938357392823d2a43be8a196526dd97c (diff) | |
download | gcc-93cbebde76ac7de2d69b223d99acb39e0370687f.zip gcc-93cbebde76ac7de2d69b223d99acb39e0370687f.tar.gz gcc-93cbebde76ac7de2d69b223d99acb39e0370687f.tar.bz2 |
compiler: permit inlining temporary statements and references
This increases the number of inlinable functions from 439 to 455.
An example is math/bits.Mul32, which uses temporaries to handle the
tuple assignment.
Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/180837
From-SVN: r272022
Diffstat (limited to 'gcc/go/gofrontend/statements.cc')
-rw-r--r-- | gcc/go/gofrontend/statements.cc | 88 |
1 files changed, 88 insertions, 0 deletions
diff --git a/gcc/go/gofrontend/statements.cc b/gcc/go/gofrontend/statements.cc index 8368c5b..cd7b856 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 $t")) + return Temporary_statement::do_import(ifb, loc); else if (ifb->match_c_string("var ")) return Variable_declaration_statement::do_import(ifb, loc); @@ -693,6 +695,92 @@ Statement::make_temporary(Type* type, Expression* init, return new Temporary_statement(type, init, location); } +// Export a temporary statement. + +void +Temporary_statement::do_export_statement(Export_function_body* efb) +{ + unsigned int idx = efb->record_temporary(this); + char buf[100]; + snprintf(buf, sizeof buf, "var $t%u", idx); + efb->write_c_string(buf); + if (this->type_ != NULL) + { + efb->write_c_string(" "); + efb->write_type(this->type_); + } + if (this->init_ != NULL) + { + efb->write_c_string(" = "); + + go_assert(efb->type_context() == NULL); + efb->set_type_context(this->type_); + + this->init_->export_expression(efb); + + efb->set_type_context(NULL); + } +} + +// Import a temporary statement. + +Statement* +Temporary_statement::do_import(Import_function_body* ifb, Location loc) +{ + ifb->require_c_string("var "); + std::string id = ifb->read_identifier(); + go_assert(id[0] == '$' && id[1] == 't'); + const char *p = id.c_str(); + char *end; + long idx = strtol(p + 2, &end, 10); + if (*end != '\0' || idx > 0x7fffffff) + { + if (!ifb->saw_error()) + go_error_at(loc, + ("invalid export data for %qs: " + "bad temporary statement index at %lu"), + ifb->name().c_str(), + static_cast<unsigned long>(ifb->off())); + ifb->set_saw_error(); + return Statement::make_error_statement(loc); + } + + Type* type = NULL; + if (!ifb->match_c_string(" = ")) + { + ifb->require_c_string(" "); + type = ifb->read_type(); + } + Expression* init = NULL; + if (ifb->match_c_string(" = ")) + { + ifb->advance(3); + init = Expression::import_expression(ifb, loc); + if (type != NULL) + { + Type_context context(type, false); + init->determine_type(&context); + } + } + if (type == NULL && init == NULL) + { + if (!ifb->saw_error()) + go_error_at(loc, + ("invalid export data for %qs: " + "temporary statement has neither type nor init at %lu"), + ifb->name().c_str(), + static_cast<unsigned long>(ifb->off())); + ifb->set_saw_error(); + return Statement::make_error_statement(loc); + } + + Temporary_statement* temp = Statement::make_temporary(type, init, loc); + + ifb->record_temporary(temp, static_cast<unsigned int>(idx)); + + return temp; +} + // The Move_subexpressions class is used to move all top-level // subexpressions of an expression. This is used for things like // index expressions in which we must evaluate the index value before |