From 6e5443979505b2bc71afe76ef9fd95c38cdb9090 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Fri, 7 Jun 2019 14:19:51 +0000 Subject: [PATCH] compiler: support inlining functions with if statements This increases the number of inlinable functions from 455 to 500. An example of a newly inlinable function is strings.Compare. Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/181137 From-SVN: r272045 --- gcc/go/gofrontend/MERGE | 2 +- gcc/go/gofrontend/gogo.cc | 7 +- gcc/go/gofrontend/statements.cc | 123 +++++++++++++++++++++++++++----- gcc/go/gofrontend/statements.h | 19 +++++ 4 files changed, 131 insertions(+), 20 deletions(-) diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE index 428b59a08fe..e107d529eb6 100644 --- a/gcc/go/gofrontend/MERGE +++ b/gcc/go/gofrontend/MERGE @@ -1,4 +1,4 @@ -46329dd9e6473fff46df6b310c11116d1558e470 +9df825b5f142ac2b6f48a8dac94fcff740acd411 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/gogo.cc b/gcc/go/gofrontend/gogo.cc index 480077823d1..6d51d9e0c90 100644 --- a/gcc/go/gofrontend/gogo.cc +++ b/gcc/go/gofrontend/gogo.cc @@ -6941,7 +6941,12 @@ Block::import_block(Block* set, Import_function_body *ifb, Location loc) if (at_end) { - off = nl + 1; + // An if statement can have an "else" following the "}", in + // which case we want to leave the offset where it is, just + // after the "}". We don't get the block ending location + // quite right for if statements. + if (body.compare(off, 6, " else ") != 0) + off = nl + 1; break; } diff --git a/gcc/go/gofrontend/statements.cc b/gcc/go/gofrontend/statements.cc index cd7b8568a12..f680a0a1c3e 100644 --- a/gcc/go/gofrontend/statements.cc +++ b/gcc/go/gofrontend/statements.cc @@ -129,22 +129,8 @@ Statement::import_statement(Import_function_body* ifb, Location loc) { if (ifb->match_c_string("{")) { - size_t nl = ifb->body().find('\n', ifb->off()); - if (nl == std::string::npos) - { - if (!ifb->saw_error()) - go_error_at(ifb->location(), - "import error: no newline after { at %lu", - static_cast(ifb->off())); - ifb->set_saw_error(); - return Statement::make_error_statement(loc); - } - ifb->set_off(nl + 1); - ifb->increment_indent(); - Block* block = new Block(ifb->block(), loc); - bool ok = Block::import_block(block, ifb, loc); - ifb->decrement_indent(); - if (!ok) + Block* block = Block_statement::do_import(ifb, loc); + if (block == NULL) return Statement::make_error_statement(loc); return Statement::make_block_statement(block, loc); } @@ -159,6 +145,8 @@ Statement::import_statement(Import_function_body* ifb, Location loc) return Temporary_statement::do_import(ifb, loc); else if (ifb->match_c_string("var ")) return Variable_declaration_statement::do_import(ifb, loc); + else if (ifb->match_c_string("if ")) + return If_statement::do_import(ifb, loc); Expression* lhs = Expression::import_expression(ifb, loc); ifb->require_c_string(" = "); @@ -2120,14 +2108,20 @@ Statement::make_statement(Expression* expr, bool is_ignored) void Block_statement::do_export_statement(Export_function_body* efb) +{ + Block_statement::export_block(efb, this->block_); +} + +void +Block_statement::export_block(Export_function_body* efb, Block* block) { // We are already indented to the right position. char buf[50]; snprintf(buf, sizeof buf, "{ //%d\n", - Linemap::location_to_line(this->block_->start_location())); + Linemap::location_to_line(block->start_location())); efb->write_c_string(buf); - this->block_->export_block(efb); + block->export_block(efb); // The indentation is correct for the statements in the block, so // subtract one for the closing curly brace. efb->decrement_indent(); @@ -2137,6 +2131,32 @@ Block_statement::do_export_statement(Export_function_body* efb) efb->increment_indent(); } +// Import a block statement, returning the block. + +Block* +Block_statement::do_import(Import_function_body* ifb, Location loc) +{ + go_assert(ifb->match_c_string("{")); + size_t nl = ifb->body().find('\n', ifb->off()); + if (nl == std::string::npos) + { + if (!ifb->saw_error()) + go_error_at(ifb->location(), + "import error: no newline after { at %lu", + static_cast(ifb->off())); + ifb->set_saw_error(); + return NULL; + } + ifb->set_off(nl + 1); + ifb->increment_indent(); + Block* block = new Block(ifb->block(), loc); + bool ok = Block::import_block(block, ifb, loc); + ifb->decrement_indent(); + if (!ok) + return NULL; + return block; +} + // Convert a block to the backend representation of a statement. Bstatement* @@ -3529,6 +3549,73 @@ If_statement::do_get_backend(Translate_context* context) this->location()); } +// Export an if statement. + +void +If_statement::do_export_statement(Export_function_body* efb) +{ + efb->write_c_string("if "); + this->cond_->export_expression(efb); + efb->write_c_string(" "); + Block_statement::export_block(efb, this->then_block_); + if (this->else_block_ != NULL) + { + efb->write_c_string(" else "); + Block_statement::export_block(efb, this->else_block_); + } +} + +// Import an if statement. + +Statement* +If_statement::do_import(Import_function_body* ifb, Location loc) +{ + ifb->require_c_string("if "); + + Expression* cond = Expression::import_expression(ifb, loc); + Type_context context(Type::lookup_bool_type(), false); + cond->determine_type(&context); + ifb->require_c_string(" "); + + if (!ifb->match_c_string("{")) + { + if (!ifb->saw_error()) + go_error_at(ifb->location(), + "import error for %qs: no block for if statement at %lu", + ifb->name().c_str(), + static_cast(ifb->off())); + ifb->set_saw_error(); + return Statement::make_error_statement(loc); + } + + Block* then_block = Block_statement::do_import(ifb, loc); + if (then_block == NULL) + return Statement::make_error_statement(loc); + + Block* else_block = NULL; + if (ifb->match_c_string(" else ")) + { + ifb->advance(6); + if (!ifb->match_c_string("{")) + { + if (!ifb->saw_error()) + go_error_at(ifb->location(), + ("import error for %qs: no else block " + "for if statement at %lu"), + ifb->name().c_str(), + static_cast(ifb->off())); + ifb->set_saw_error(); + return Statement::make_error_statement(loc); + } + + else_block = Block_statement::do_import(ifb, loc); + if (else_block == NULL) + return Statement::make_error_statement(loc); + } + + return Statement::make_if_statement(cond, then_block, else_block, loc); +} + // Dump the AST representation for an if statement void diff --git a/gcc/go/gofrontend/statements.h b/gcc/go/gofrontend/statements.h index 3743d44bb43..3e85243b084 100644 --- a/gcc/go/gofrontend/statements.h +++ b/gcc/go/gofrontend/statements.h @@ -954,6 +954,14 @@ class Block_statement : public Statement is_lowered_for_statement() { return this->is_lowered_for_statement_; } + // Export a block for a block statement. + static void + export_block(Export_function_body*, Block*); + + // Import a block statement, returning the block. + static Block* + do_import(Import_function_body*, Location); + protected: int do_traverse(Traverse* traverse) @@ -1529,6 +1537,10 @@ class If_statement : public Statement else_block() const { return this->else_block_; } + // Import an if statement. + static Statement* + do_import(Import_function_body*, Location); + protected: int do_traverse(Traverse*); @@ -1539,6 +1551,13 @@ class If_statement : public Statement void do_check_types(Gogo*); + int + do_inlining_cost() + { return 5; } + + void + do_export_statement(Export_function_body*); + bool do_may_fall_through() const; -- 2.30.2