Label loops
This commit is contained in:
@ -1174,7 +1174,7 @@ namespace elna::gcc
|
||||
|
||||
void generic_visitor::visit(boot::if_statement *statement)
|
||||
{
|
||||
tree endif_label_decl = build_label_decl("endif", UNKNOWN_LOCATION);
|
||||
tree endif_label_decl = create_artificial_label(UNKNOWN_LOCATION);
|
||||
tree goto_endif = build1(GOTO_EXPR, void_type_node, endif_label_decl);
|
||||
|
||||
make_if_branch(statement->body(), goto_endif);
|
||||
@ -1202,7 +1202,7 @@ namespace elna::gcc
|
||||
if (TREE_TYPE(this->current_expression) != elna_bool_type_node)
|
||||
{
|
||||
error_at(get_location(&branch.prerequisite().position()),
|
||||
"expected expression of boolean type but its type is %s",
|
||||
"Expected expression of boolean type but its type is %s",
|
||||
print_type(TREE_TYPE(this->current_expression)).c_str());
|
||||
this->current_expression = error_mark_node;
|
||||
return;
|
||||
@ -1229,13 +1229,46 @@ namespace elna::gcc
|
||||
append_statement(else_label_expr);
|
||||
}
|
||||
|
||||
void generic_visitor::visit(boot::escape_statement *statement)
|
||||
{
|
||||
for (const auto& [begin, end] : this->loops)
|
||||
{
|
||||
if (statement->label == IDENTIFIER_POINTER(DECL_NAME(begin)))
|
||||
{
|
||||
tree target_declaration{ NULL_TREE };
|
||||
|
||||
switch (statement->direction)
|
||||
{
|
||||
case boot::escape_direction::begin:
|
||||
target_declaration = begin;
|
||||
break;
|
||||
case boot::escape_direction::end:
|
||||
target_declaration = end;
|
||||
break;
|
||||
default:
|
||||
gcc_unreachable();
|
||||
}
|
||||
tree goto_expression = build1(GOTO_EXPR, void_type_node, target_declaration);
|
||||
TREE_USED(target_declaration) = 1;
|
||||
append_statement(goto_expression);
|
||||
return;
|
||||
}
|
||||
}
|
||||
error_at(get_location(&statement->position()), "Unknown loop labeled '%s'", statement->label.c_str());
|
||||
}
|
||||
|
||||
void generic_visitor::visit(boot::while_statement *statement)
|
||||
{
|
||||
auto prerequisite_location = get_location(&statement->body().prerequisite().position());
|
||||
auto prerequisite_label_decl = build_label_decl("while_check", prerequisite_location);
|
||||
std::string loop_identifier = statement->label.value_or("while");
|
||||
location_t prerequisite_location = get_location(&statement->body().prerequisite().position());
|
||||
tree prerequisite_label_decl = build_label_decl(loop_identifier.c_str(), prerequisite_location);
|
||||
auto prerequisite_label_expr = build1_loc(prerequisite_location, LABEL_EXPR,
|
||||
void_type_node, prerequisite_label_decl);
|
||||
auto goto_check = build1(GOTO_EXPR, void_type_node, prerequisite_label_decl);
|
||||
tree branch_end_declaration = build_label_decl(loop_identifier.c_str(), UNKNOWN_LOCATION);
|
||||
tree branch_end_expression = build1_loc(UNKNOWN_LOCATION, LABEL_EXPR, void_type_node, branch_end_declaration);
|
||||
|
||||
this->loops.push_front({ prerequisite_label_decl, branch_end_declaration });
|
||||
|
||||
append_statement(prerequisite_label_expr);
|
||||
make_if_branch(statement->body(), goto_check);
|
||||
@ -1244,6 +1277,7 @@ namespace elna::gcc
|
||||
{
|
||||
make_if_branch(*branch, goto_check);
|
||||
}
|
||||
append_statement(branch_end_expression);
|
||||
this->current_expression = NULL_TREE;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user