aboutsummaryrefslogtreecommitdiff
path: root/gcc/go/gofrontend/statements.cc
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@gcc.gnu.org>2019-06-06 23:34:00 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2019-06-06 23:34:00 +0000
commit93cbebde76ac7de2d69b223d99acb39e0370687f (patch)
tree66c133d573a219583b5c460b329b900c18ee0ac6 /gcc/go/gofrontend/statements.cc
parent5e664ed0938357392823d2a43be8a196526dd97c (diff)
downloadgcc-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.cc88
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