diff options
Diffstat (limited to 'gcc/go')
-rw-r--r-- | gcc/go/gofrontend/MERGE | 2 | ||||
-rw-r--r-- | gcc/go/gofrontend/expressions.cc | 102 | ||||
-rw-r--r-- | gcc/go/gofrontend/expressions.h | 27 | ||||
-rw-r--r-- | gcc/go/gofrontend/statements.cc | 55 | ||||
-rw-r--r-- | gcc/go/gofrontend/statements.h | 14 |
5 files changed, 193 insertions, 7 deletions
diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE index 8e220f50..74806a2 100644 --- a/gcc/go/gofrontend/MERGE +++ b/gcc/go/gofrontend/MERGE @@ -1,4 +1,4 @@ -b013405f2c66596c47cb9be493c798db1087c0f0 +a8f768d68760768da5e86a8e63ef1ad5691c3ae8 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 5f00eff..7c464ce 100644 --- a/gcc/go/gofrontend/expressions.cc +++ b/gcc/go/gofrontend/expressions.cc @@ -786,6 +786,31 @@ Var_expression::do_address_taken(bool escapes) } } +// The cost to inline a variable reference. We currently only support +// references to parameters. + +int +Var_expression::do_inlining_cost() const +{ + if (this->variable_->is_variable()) + { + if (this->variable_->var_value()->is_parameter()) + return 1; + } + else if (this->variable_->is_result_variable()) + return 1; + + return 0x100000; +} + +// Export a reference to a variable. + +void +Var_expression::do_export(Export_function_body* efb) const +{ + efb->write_string(Gogo::unpack_hidden_name(this->variable_->name())); +} + // Get the backend representation for a reference to a variable. Bexpression* @@ -1608,6 +1633,10 @@ class Boolean_expression : public Expression do_get_backend(Translate_context* context) { return context->backend()->boolean_constant_expression(this->val_); } + int + do_inlining_cost() const + { return 1; } + void do_export(Export_function_body* efb) const { efb->write_c_string(this->val_ ? "$true" : "$false"); } @@ -1997,6 +2026,10 @@ class Integer_expression : public Expression this->location()); } + int + do_inlining_cost() const + { return 1; } + void do_export(Export_function_body*) const; @@ -2408,6 +2441,10 @@ class Float_expression : public Expression Bexpression* do_get_backend(Translate_context*); + int + do_inlining_cost() const + { return 1; } + void do_export(Export_function_body*) const; @@ -2617,6 +2654,10 @@ class Complex_expression : public Expression Bexpression* do_get_backend(Translate_context*); + int + do_inlining_cost() const + { return 2; } + void do_export(Export_function_body*) const; @@ -3204,6 +3245,10 @@ class Nil_expression : public Expression do_get_backend(Translate_context* context) { return context->backend()->nil_pointer_expression(); } + int + do_inlining_cost() const + { return 1; } + void do_export(Export_function_body* efb) const { efb->write_c_string("$nil"); } @@ -3654,6 +3699,25 @@ Type_conversion_expression::do_get_backend(Translate_context* context) } } +// Cost of inlining a type conversion. + +int +Type_conversion_expression::do_inlining_cost() const +{ + Type* type = this->type_; + Type* expr_type = this->expr_->type(); + if (type->interface_type() != NULL || expr_type->interface_type() != NULL) + return 10; + else if (type->is_string_type() && expr_type->integer_type() != NULL) + return 10; + else if (type->is_string_type() && expr_type->is_slice_type()) + return 10; + else if (type->is_slice_type() && expr_type->is_string_type()) + return 10; + else + return 1; +} + // Output a type conversion in a constant expression. void @@ -4677,7 +4741,11 @@ Unary_expression::do_export(Export_function_body* efb) const efb->write_c_string("^"); break; case OPERATOR_AND: + efb->write_c_string("&"); + break; case OPERATOR_MULT: + efb->write_c_string("*"); + break; default: go_unreachable(); } @@ -4704,6 +4772,12 @@ Unary_expression::do_import(Import_expression* imp, Location loc) case '^': op = OPERATOR_XOR; break; + case '&': + op = OPERATOR_AND; + break; + case '*': + op = OPERATOR_MULT; + break; default: go_unreachable(); } @@ -16195,7 +16269,7 @@ Expression* Expression::import_expression(Import_expression* imp, Location loc) { int c = imp->peek_char(); - if (c == '+' || c == '-' || c == '!' || c == '^') + if (c == '+' || c == '-' || c == '!' || c == '^' || c == '&' || c == '*') return Unary_expression::do_import(imp, loc); else if (c == '(') return Binary_expression::do_import(imp, loc); @@ -16220,11 +16294,35 @@ Expression::import_expression(Import_expression* imp, Location loc) || (imp->version() < EXPORT_FORMAT_V3 && imp->match_c_string("convert"))) return Type_conversion_expression::do_import(imp, loc); - else + + Import_function_body* ifb = imp->ifb(); + if (ifb == NULL) { go_error_at(imp->location(), "import error: expected expression"); return Expression::make_error(loc); } + if (ifb->saw_error()) + return Expression::make_error(loc); + std::string id = ifb->read_identifier(); + if (id.empty()) + { + if (!ifb->saw_error()) + go_error_at(imp->location(), + "import error: expected identifier at %lu", + static_cast<unsigned long>(ifb->off())); + ifb->set_saw_error(); + return Expression::make_error(loc); + } + Named_object* var = ifb->block()->bindings()->lookup(id); + if (var == NULL) + { + if (!ifb->saw_error()) + go_error_at(imp->location(), "import error: lookup of %qs failed", + id.c_str()); + ifb->set_saw_error(); + return Expression::make_error(loc); + } + return Expression::make_var_reference(var, loc); } // Class Expression_list. diff --git a/gcc/go/gofrontend/expressions.h b/gcc/go/gofrontend/expressions.h index 7061657..a18322c 100644 --- a/gcc/go/gofrontend/expressions.h +++ b/gcc/go/gofrontend/expressions.h @@ -941,7 +941,7 @@ class Expression // Return the cost of this statement for inlining purposes. int - inlining_cost() + inlining_cost() const { return this->do_inlining_cost(); } // Return whether the expression is addressable--something which may @@ -1093,7 +1093,7 @@ class Expression // inlining. The default cost is high, so we only need to define // this method for expressions that can be inlined. virtual int - do_inlining_cost() + do_inlining_cost() const { return 0x100000; } // Child class implements whether the expression is addressable. @@ -1355,6 +1355,12 @@ class Var_expression : public Expression do_copy() { return this; } + int + do_inlining_cost() const; + + void + do_export(Export_function_body*) const; + bool do_is_addressable() const { return true; } @@ -1602,6 +1608,12 @@ class String_expression : public Expression static void export_string(String_dump* exp, const String_expression* str); + // Set the inlining cost a bit high since inlining may cause + // duplicated string literals. + int + do_inlining_cost() const + { return 5; } + void do_export(Export_function_body*) const; @@ -1686,6 +1698,9 @@ class Type_conversion_expression : public Expression Bexpression* do_get_backend(Translate_context* context); + int + do_inlining_cost() const; + void do_export(Export_function_body*) const; @@ -1877,6 +1892,10 @@ class Unary_expression : public Expression Bexpression* do_get_backend(Translate_context*); + int + do_inlining_cost() const + { return 1; } + void do_export(Export_function_body*) const; @@ -2022,6 +2041,10 @@ class Binary_expression : public Expression Bexpression* do_get_backend(Translate_context*); + int + do_inlining_cost() const + { return 1; } + void do_export(Export_function_body*) const; diff --git a/gcc/go/gofrontend/statements.cc b/gcc/go/gofrontend/statements.cc index 60b7a70..4d10f60 100644 --- a/gcc/go/gofrontend/statements.cc +++ b/gcc/go/gofrontend/statements.cc @@ -12,6 +12,7 @@ #include "expressions.h" #include "gogo.h" #include "export.h" +#include "import.h" #include "runtime.h" #include "backend.h" #include "statements.h" @@ -124,9 +125,41 @@ Statement::determine_types() // Read a statement from export data. Statement* -Statement::import_statement(Import_function_body*, Location) +Statement::import_statement(Import_function_body* ifb, Location loc) { - go_unreachable(); + 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<unsigned long>(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) + return Statement::make_error_statement(loc); + return Statement::make_block_statement(block, loc); + } + else if (ifb->match_c_string("return")) + { + // After lowering return statements have no expressions. The + // return expressions are assigned to result parameters. + ifb->advance(6); + return Statement::make_return_statement(NULL, loc); + } + + Expression* lhs = Expression::import_expression(ifb, loc); + ifb->require_c_string(" = "); + Expression* rhs = Expression::import_expression(ifb, loc); + return Statement::make_assignment(lhs, rhs, loc); } // If this is a thunk statement, return it. @@ -834,6 +867,14 @@ Assignment_statement::do_check_types(Gogo*) this->set_is_error(); } +void +Assignment_statement::do_export_statement(Export_function_body* efb) +{ + this->lhs_->export_expression(efb); + efb->write_c_string(" = "); + this->rhs_->export_expression(efb); +} + // Flatten an assignment statement. We may need a temporary for // interface conversion. @@ -2844,6 +2885,16 @@ Return_statement::do_get_backend(Translate_context* context) retvals, loc); } +// Export a return statement. At this point all the expressions have +// been converted to assignments to the result variables, so this is +// simple. + +void +Return_statement::do_export_statement(Export_function_body* efb) +{ + efb->write_c_string("return"); +} + // Dump the AST representation for a return statement. void diff --git a/gcc/go/gofrontend/statements.h b/gcc/go/gofrontend/statements.h index 3b5c68a..621d301 100644 --- a/gcc/go/gofrontend/statements.h +++ b/gcc/go/gofrontend/statements.h @@ -631,6 +631,13 @@ class Assignment_statement : public Statement void do_check_types(Gogo*); + int + do_inlining_cost() + { return 1; } + + void + do_export_statement(Export_function_body*); + Statement* do_flatten(Gogo*, Named_object*, Block*, Statement_inserter*); @@ -792,6 +799,13 @@ class Return_statement : public Statement do_may_fall_through() const { return false; } + int + do_inlining_cost() + { return 1; } + + void + do_export_statement(Export_function_body*); + Bstatement* do_get_backend(Translate_context*); |