-b013405f2c66596c47cb9be493c798db1087c0f0
+a8f768d68760768da5e86a8e63ef1ad5691c3ae8
The first line of this file holds the git revision number of the last
merge done from the gofrontend repository.
}
}
+// 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*
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"); }
this->location());
}
+ int
+ do_inlining_cost() const
+ { return 1; }
+
void
do_export(Export_function_body*) const;
Bexpression*
do_get_backend(Translate_context*);
+ int
+ do_inlining_cost() const
+ { return 1; }
+
void
do_export(Export_function_body*) const;
Bexpression*
do_get_backend(Translate_context*);
+ int
+ do_inlining_cost() const
+ { return 2; }
+
void
do_export(Export_function_body*) const;
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"); }
}
}
+// 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
efb->write_c_string("^");
break;
case OPERATOR_AND:
+ efb->write_c_string("&");
+ break;
case OPERATOR_MULT:
+ efb->write_c_string("*");
+ break;
default:
go_unreachable();
}
case '^':
op = OPERATOR_XOR;
break;
+ case '&':
+ op = OPERATOR_AND;
+ break;
+ case '*':
+ op = OPERATOR_MULT;
+ break;
default:
go_unreachable();
}
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);
|| (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.
// 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
// 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.
do_copy()
{ return this; }
+ int
+ do_inlining_cost() const;
+
+ void
+ do_export(Export_function_body*) const;
+
bool
do_is_addressable() const
{ return true; }
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;
Bexpression*
do_get_backend(Translate_context* context);
+ int
+ do_inlining_cost() const;
+
void
do_export(Export_function_body*) const;
Bexpression*
do_get_backend(Translate_context*);
+ int
+ do_inlining_cost() const
+ { return 1; }
+
void
do_export(Export_function_body*) const;
Bexpression*
do_get_backend(Translate_context*);
+ int
+ do_inlining_cost() const
+ { return 1; }
+
void
do_export(Export_function_body*) const;
#include "expressions.h"
#include "gogo.h"
#include "export.h"
+#include "import.h"
#include "runtime.h"
#include "backend.h"
#include "statements.h"
// 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.
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.
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
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*);
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*);