From e898243c23c82247ec01b32f551402ca52f32927 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Mon, 10 Jun 2019 21:34:12 +0000 Subject: [PATCH] compiler: support inlining functions that use index expressions Also move the determine_types pass on an inlined function body to one place, rather than doing it ad hoc as needed. This adds 79 new inlinable functions in the standard library, such as bytes.HasPrefix and bytes.LastIndexByte. Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/181261 From-SVN: r272133 --- gcc/go/gofrontend/MERGE | 2 +- gcc/go/gofrontend/expressions.cc | 105 +++++++++++++++++++++++++++++++ gcc/go/gofrontend/expressions.h | 21 +++++++ gcc/go/gofrontend/gogo.cc | 1 + gcc/go/gofrontend/import.cc | 2 +- gcc/go/gofrontend/statements.cc | 9 --- 6 files changed, 129 insertions(+), 11 deletions(-) diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE index 84c00ae570e..d89e8e3e288 100644 --- a/gcc/go/gofrontend/MERGE +++ b/gcc/go/gofrontend/MERGE @@ -1,4 +1,4 @@ -764fe6702f2bb8650622d4102de31058e484ecb5 +b1ae35965cadac235d7d218e689944286cccdd90 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 d82eebd521e..740daec5f21 100644 --- a/gcc/go/gofrontend/expressions.cc +++ b/gcc/go/gofrontend/expressions.cc @@ -7110,6 +7110,12 @@ Binary_expression::do_import(Import_expression* imp, Location loc) op = OPERATOR_BITCLEAR; imp->advance(4); } + else if (imp->match_c_string(")")) + { + // Not a binary operator after all. + imp->advance(1); + return left; + } else { go_error_at(imp->location(), "unrecognized binary operator"); @@ -12808,6 +12814,38 @@ Array_index_expression::do_get_backend(Translate_context* context) return ret; } +// Export an array index expression. + +void +Array_index_expression::do_export(Export_function_body* efb) const +{ + efb->write_c_string("("); + this->array_->export_expression(efb); + efb->write_c_string(")["); + + Type* old_context = efb->type_context(); + efb->set_type_context(Type::lookup_integer_type("int")); + + this->start_->export_expression(efb); + if (this->end_ == NULL) + go_assert(this->cap_ == NULL); + else + { + efb->write_c_string(":"); + if (!this->end_->is_nil_expression()) + this->end_->export_expression(efb); + if (this->cap_ != NULL) + { + efb->write_c_string(":"); + this->cap_->export_expression(efb); + } + } + + efb->set_type_context(old_context); + + efb->write_c_string("]"); +} + // Dump ast representation for an array index expression. void @@ -13068,6 +13106,31 @@ String_index_expression::do_get_backend(Translate_context* context) crash, bstrslice, loc); } +// Export a string index expression. + +void +String_index_expression::do_export(Export_function_body* efb) const +{ + efb->write_c_string("("); + this->string_->export_expression(efb); + efb->write_c_string(")["); + + Type* old_context = efb->type_context(); + efb->set_type_context(Type::lookup_integer_type("int")); + + this->start_->export_expression(efb); + if (this->end_ != NULL) + { + efb->write_c_string(":"); + if (!this->end_->is_nil_expression()) + this->end_->export_expression(efb); + } + + efb->set_type_context(old_context); + + efb->write_c_string("]"); +} + // Dump ast representation for a string index expression. void @@ -13338,6 +13401,25 @@ Map_index_expression::get_value_pointer(Gogo* gogo) return this->value_pointer_; } +// Export a map index expression. + +void +Map_index_expression::do_export(Export_function_body* efb) const +{ + efb->write_c_string("("); + this->map_->export_expression(efb); + efb->write_c_string(")["); + + Type* old_context = efb->type_context(); + efb->set_type_context(this->get_map_type()->key_type()); + + this->index_->export_expression(efb); + + efb->set_type_context(old_context); + + efb->write_c_string("]"); +} + // Dump ast representation for a map index expression void @@ -17974,6 +18056,29 @@ Expression::import_expression(Import_expression* imp, Location loc) imp->require_c_string(")"); expr = Expression::make_call(expr, args, is_varargs, loc); } + else if (imp->match_c_string("[")) + { + imp->advance(1); + Expression* start = Expression::import_expression(imp, loc); + Expression* end = NULL; + Expression* cap = NULL; + if (imp->match_c_string(":")) + { + imp->advance(1); + int c = imp->peek_char(); + if (c == ':' || c == ']') + end = Expression::make_nil(loc); + else + end = Expression::import_expression(imp, loc); + if (imp->match_c_string(":")) + { + imp->advance(1); + cap = Expression::import_expression(imp, loc); + } + } + imp->require_c_string("]"); + expr = Expression::make_index(expr, start, end, cap, loc); + } else break; } diff --git a/gcc/go/gofrontend/expressions.h b/gcc/go/gofrontend/expressions.h index 22dd2fc4c1d..1595eb15226 100644 --- a/gcc/go/gofrontend/expressions.h +++ b/gcc/go/gofrontend/expressions.h @@ -3089,6 +3089,13 @@ class Array_index_expression : public Expression Bexpression* do_get_backend(Translate_context*); + int + do_inlining_cost() const + { return this->end_ != NULL ? 2 : 1; } + + void + do_export(Export_function_body*) const; + void do_dump_expression(Ast_dump_context*) const; @@ -3161,6 +3168,13 @@ class String_index_expression : public Expression Bexpression* do_get_backend(Translate_context*); + int + do_inlining_cost() const + { return this->end_ != NULL ? 2 : 1; } + + void + do_export(Export_function_body*) const; + void do_dump_expression(Ast_dump_context*) const; @@ -3247,6 +3261,13 @@ class Map_index_expression : public Expression Bexpression* do_get_backend(Translate_context*); + int + do_inlining_cost() const + { return 5; } + + void + do_export(Export_function_body*) const; + void do_dump_expression(Ast_dump_context*) const; diff --git a/gcc/go/gofrontend/gogo.cc b/gcc/go/gofrontend/gogo.cc index 62d68705671..42a76745925 100644 --- a/gcc/go/gofrontend/gogo.cc +++ b/gcc/go/gofrontend/gogo.cc @@ -7282,6 +7282,7 @@ Function_declaration::import_function_body(Gogo* gogo, Named_object* no) return; gogo->lower_block(no, outer); + outer->determine_types(); gogo->add_imported_inline_function(no); } diff --git a/gcc/go/gofrontend/import.cc b/gcc/go/gofrontend/import.cc index 02c1c48191b..2d76f75a3de 100644 --- a/gcc/go/gofrontend/import.cc +++ b/gcc/go/gofrontend/import.cc @@ -1238,7 +1238,7 @@ Import::register_builtin_type(Gogo* gogo, const char* name, Builtin_code code) // characters that stop an identifier, without worrying about // characters that are permitted in an identifier. That lets us skip // UTF-8 parsing. -static const char * const identifier_stop = " \n;,()[]"; +static const char * const identifier_stop = " \n;:,()[]"; // Read an identifier from the stream. diff --git a/gcc/go/gofrontend/statements.cc b/gcc/go/gofrontend/statements.cc index 9ab11727fe9..7f424fd7b7a 100644 --- a/gcc/go/gofrontend/statements.cc +++ b/gcc/go/gofrontend/statements.cc @@ -465,8 +465,6 @@ Variable_declaration_statement::do_import(Import_function_body* ifb, { 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(); @@ -753,11 +751,6 @@ Temporary_statement::do_import(Import_function_body* ifb, Location loc) { 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) { @@ -3730,8 +3723,6 @@ 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("{")) -- 2.30.2