{
if (ifb->match_c_string("{"))
{
- Block* block = Block_statement::do_import(ifb, loc);
+ bool is_lowered_for_statement;
+ Block* block = Block_statement::do_import(ifb, loc,
+ &is_lowered_for_statement);
if (block == NULL)
return Statement::make_error_statement(loc);
- return Statement::make_block_statement(block, loc);
+ Block_statement* s = Statement::make_block_statement(block, loc);
+ if (is_lowered_for_statement)
+ s->set_is_lowered_for_statement();
+ return s;
}
else if (ifb->match_c_string("return"))
{
return Variable_declaration_statement::do_import(ifb, loc);
else if (ifb->match_c_string("if "))
return If_statement::do_import(ifb, loc);
+ else if (ifb->match_c_string(":"))
+ return Label_statement::do_import(ifb, loc);
+ else if (ifb->match_c_string("goto "))
+ return Goto_statement::do_import(ifb, loc);
Expression* lhs = Expression::import_expression(ifb, loc);
ifb->require_c_string(" = ");
void
Block_statement::do_export_statement(Export_function_body* efb)
{
- Block_statement::export_block(efb, this->block_);
+ Block_statement::export_block(efb, this->block_,
+ this->is_lowered_for_statement_);
}
void
-Block_statement::export_block(Export_function_body* efb, Block* block)
+Block_statement::export_block(Export_function_body* efb, Block* block,
+ bool is_lowered_for_statement)
{
// We are already indented to the right position.
char buf[50];
- snprintf(buf, sizeof buf, "{ //%d\n",
+ efb->write_c_string("{");
+ if (is_lowered_for_statement)
+ efb->write_c_string(" /*for*/");
+ snprintf(buf, sizeof buf, " //%d\n",
Linemap::location_to_line(block->start_location()));
efb->write_c_string(buf);
// Import a block statement, returning the block.
Block*
-Block_statement::do_import(Import_function_body* ifb, Location loc)
+Block_statement::do_import(Import_function_body* ifb, Location loc,
+ bool* is_lowered_for_statement)
{
go_assert(ifb->match_c_string("{"));
+ *is_lowered_for_statement = false;
+ if (ifb->match_c_string(" /*for*/"))
+ {
+ ifb->advance(8);
+ *is_lowered_for_statement = true;
+ }
size_t nl = ifb->body().find('\n', ifb->off());
if (nl == std::string::npos)
{
// Make a block statement.
-Statement*
+Block_statement*
Statement::make_block_statement(Block* block, Location location)
{
return new Block_statement(block, location);
return context->backend()->goto_statement(blabel, this->location());
}
+// Export a goto statement.
+
+void
+Goto_statement::do_export_statement(Export_function_body *efb)
+{
+ efb->write_c_string("goto ");
+ efb->write_string(this->label_->name());
+}
+
+// Import a goto or goto unnamed statement.
+
+Statement*
+Goto_statement::do_import(Import_function_body* ifb, Location loc)
+{
+ ifb->require_c_string("goto ");
+ std::string id = ifb->read_identifier();
+ if (id[0] != '$')
+ {
+ Function* fn = ifb->function()->func_value();
+ Label* label = fn->add_label_reference(ifb->gogo(), id, loc, false);
+ return Statement::make_goto_statement(label, loc);
+ }
+ else
+ {
+ if (id[1] != 'l')
+ {
+ if (!ifb->saw_error())
+ go_error_at(loc,
+ ("invalid export data for %qs: "
+ "bad unnamed label at %lu"),
+ ifb->name().c_str(),
+ static_cast<unsigned long>(ifb->off()));
+ ifb->set_saw_error();
+ return Statement::make_error_statement(loc);
+ }
+ 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 unnamed label index at %lu"),
+ ifb->name().c_str(),
+ static_cast<unsigned long>(ifb->off()));
+ ifb->set_saw_error();
+ return Statement::make_error_statement(loc);
+ }
+
+ Unnamed_label* label = ifb->unnamed_label(idx, loc);
+ return Statement::make_goto_unnamed_statement(label, loc);
+ }
+}
+
// Dump the AST representation for a goto statement.
void
return this->label_->get_goto(context, this->location());
}
+// Export a goto unnamed statement.
+
+void
+Goto_unnamed_statement::do_export_statement(Export_function_body *efb)
+{
+ unsigned int index = efb->unnamed_label_index(this->label_);
+ char buf[100];
+ snprintf(buf, sizeof buf, "goto $l%u", index);
+ efb->write_c_string(buf);
+}
+
// Dump the AST representation for an unnamed goto statement
void
return context->backend()->label_definition_statement(blabel);
}
+// Export a label.
+
+void
+Label_statement::do_export_statement(Export_function_body* efb)
+{
+ if (this->label_->is_dummy_label())
+ return;
+ // We use a leading colon, not a trailing one, to simplify import.
+ efb->write_c_string(":");
+ efb->write_string(this->label_->name());
+}
+
+// Import a label or an unnamed label.
+
+Statement*
+Label_statement::do_import(Import_function_body* ifb, Location loc)
+{
+ ifb->require_c_string(":");
+ std::string id = ifb->read_identifier();
+ if (id[0] != '$')
+ {
+ Function* fn = ifb->function()->func_value();
+ Label* label = fn->add_label_definition(ifb->gogo(), id, loc);
+ return Statement::make_label_statement(label, loc);
+ }
+ else
+ {
+ if (id[1] != 'l')
+ {
+ if (!ifb->saw_error())
+ go_error_at(loc,
+ ("invalid export data for %qs: "
+ "bad unnamed label at %lu"),
+ ifb->name().c_str(),
+ static_cast<unsigned long>(ifb->off()));
+ ifb->set_saw_error();
+ return Statement::make_error_statement(loc);
+ }
+ 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 unnamed label index at %lu"),
+ ifb->name().c_str(),
+ static_cast<unsigned long>(ifb->off()));
+ ifb->set_saw_error();
+ return Statement::make_error_statement(loc);
+ }
+
+ Unnamed_label* label = ifb->unnamed_label(idx, loc);
+ return Statement::make_unnamed_label_statement(label);
+ }
+}
+
// Dump the AST for a label definition statement.
void
return this->label_->get_definition(context);
}
+// Export an unnamed label.
+
+void
+Unnamed_label_statement::do_export_statement(Export_function_body* efb)
+{
+ unsigned int index = efb->unnamed_label_index(this->label_);
+ char buf[50];
+ // We use a leading colon, not a trailing one, to simplify import.
+ snprintf(buf, sizeof buf, ":$l%u", index);
+ efb->write_c_string(buf);
+}
+
// Dump the AST representation for an unnamed label definition statement.
void
efb->write_c_string("if ");
this->cond_->export_expression(efb);
efb->write_c_string(" ");
- Block_statement::export_block(efb, this->then_block_);
+ Block_statement::export_block(efb, this->then_block_, false);
if (this->else_block_ != NULL)
{
efb->write_c_string(" else ");
- Block_statement::export_block(efb, this->else_block_);
+ Block_statement::export_block(efb, this->else_block_, false);
}
}
return Statement::make_error_statement(loc);
}
- Block* then_block = Block_statement::do_import(ifb, loc);
+ bool is_lowered_for_statement;
+ Block* then_block = Block_statement::do_import(ifb, loc,
+ &is_lowered_for_statement);
if (then_block == NULL)
return Statement::make_error_statement(loc);
+ if (is_lowered_for_statement)
+ {
+ if (!ifb->saw_error())
+ go_error_at(ifb->location(),
+ ("import error for %qs: "
+ "unexpected lowered for in if statement at %lu"),
+ ifb->name().c_str(),
+ static_cast<unsigned long>(ifb->off()));
+ ifb->set_saw_error();
+ return Statement::make_error_statement(loc);
+ }
Block* else_block = NULL;
if (ifb->match_c_string(" else "))
return Statement::make_error_statement(loc);
}
- else_block = Block_statement::do_import(ifb, loc);
+ else_block = Block_statement::do_import(ifb, loc,
+ &is_lowered_for_statement);
if (else_block == NULL)
return Statement::make_error_statement(loc);
+ if (is_lowered_for_statement)
+ {
+ if (!ifb->saw_error())
+ go_error_at(ifb->location(),
+ ("import error for %qs: "
+ "unexpected lowered for in if statement at %lu"),
+ ifb->name().c_str(),
+ static_cast<unsigned long>(ifb->off()));
+ ifb->set_saw_error();
+ return Statement::make_error_statement(loc);
+ }
}
return Statement::make_if_statement(cond, then_block, else_block, loc);