Label loops

This commit is contained in:
2025-04-12 12:05:32 +02:00
parent 6fd1bda112
commit 8ec407515a
9 changed files with 134 additions and 103 deletions

View File

@ -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;
}