aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/gcc/elna-builtins.cc2
-rw-r--r--gcc/gcc/elna-generic.cc103
-rw-r--r--gcc/gcc/elna-tree.cc9
3 files changed, 82 insertions, 32 deletions
diff --git a/gcc/gcc/elna-builtins.cc b/gcc/gcc/elna-builtins.cc
index 77ffb1c..2790251 100644
--- a/gcc/gcc/elna-builtins.cc
+++ b/gcc/gcc/elna-builtins.cc
@@ -237,7 +237,7 @@ namespace elna::gcc
tree declare_variable(const std::string& name, const boot::variable_info& info,
std::shared_ptr<symbol_table> symbols)
{
- auto variable_type = get_inner_alias(info.symbol, symbols);
+ auto *variable_type = get_inner_alias(info.symbol, symbols);
tree declaration_tree = build_decl(UNKNOWN_LOCATION, VAR_DECL, get_identifier(name.c_str()), variable_type);
TREE_ADDRESSABLE(declaration_tree) = 1;
diff --git a/gcc/gcc/elna-generic.cc b/gcc/gcc/elna-generic.cc
index c2c59aa..6fe3da9 100644
--- a/gcc/gcc/elna-generic.cc
+++ b/gcc/gcc/elna-generic.cc
@@ -228,7 +228,7 @@ namespace elna::gcc
if (TREE_CODE(base_type) == ARRAY_TYPE)
{
// Elna arrays are 1-indexed in TYPE_DOMAIN. Pass the raw
- // (1-based) start index — GCC handles the 1→0 conversion
+ // (1-based) start index since GCC handles the 1→0 conversion
// via the domain lower bound. No -1 adjustment needed here.
slice_ptr = build4_loc(location, ARRAY_REF, TREE_TYPE(base_type),
base, start_index, size_one_node, NULL_TREE);
@@ -256,10 +256,6 @@ namespace elna::gcc
void generic_visitor::visit(boot::unit *unit)
{
- for (boot::import_declaration *const declaration : unit->imports)
- {
- declaration->accept(this);
- }
for (boot::variable_declaration *const variable : unit->variables)
{
variable->accept(this);
@@ -363,15 +359,13 @@ namespace elna::gcc
tree generic_visitor::leave_scope()
{
- // Variables are only defined in the top function scope.
- tree variables = f_binding_level->level_chain == nullptr ? f_names : NULL_TREE;
- tree new_block = build_block(variables, f_binding_level->blocks, NULL_TREE, NULL_TREE);
+ tree new_block = build_block(f_binding_level->names, f_binding_level->blocks, NULL_TREE, NULL_TREE);
for (tree it = f_binding_level->blocks; it != NULL_TREE; it = BLOCK_CHAIN(it))
{
BLOCK_SUPERCONTEXT(it) = new_block;
}
- tree bind_expr = build3(BIND_EXPR, void_type_node, variables, chain_defer(), new_block);
+ tree bind_expr = build3(BIND_EXPR, void_type_node, f_binding_level->names, chain_defer(), new_block);
this->symbols = this->symbols->scope();
f_binding_level = f_binding_level->level_chain;
@@ -639,27 +633,27 @@ namespace elna::gcc
case exclusive_disjunction:
gcc_unreachable();
case logical_conjunction:
- this->current_expression = build2_loc(expression_location,
+ this->current_expression = fold_build2_loc(expression_location,
TRUTH_ANDIF_EXPR, elna_bool_type_node, left, right);
break;
case logical_disjunction:
- this->current_expression = build2_loc(expression_location,
+ this->current_expression = fold_build2_loc(expression_location,
TRUTH_ORIF_EXPR, elna_bool_type_node, left, right);
break;
case logical_exclusive_disjunction:
- this->current_expression = build2_loc(expression_location,
+ this->current_expression = fold_build2_loc(expression_location,
TRUTH_XOR_EXPR, elna_bool_type_node, left, right);
break;
case bitwise_conjunction:
- this->current_expression = build2_loc(expression_location,
+ this->current_expression = fold_build2_loc(expression_location,
BIT_AND_EXPR, left_type, left, right);
break;
case bitwise_disjunction:
- this->current_expression = build2_loc(expression_location,
+ this->current_expression = fold_build2_loc(expression_location,
BIT_IOR_EXPR, left_type, left, right);
break;
case bitwise_exclusive_disjunction:
- this->current_expression = build2_loc(expression_location,
+ this->current_expression = fold_build2_loc(expression_location,
BIT_XOR_EXPR, left_type, left, right);
break;
case equals:
@@ -780,7 +774,7 @@ namespace elna::gcc
else
{
DECL_CONTEXT(declaration_tree) = current_function_decl;
- f_names = chainon(f_names, declaration_tree);
+ f_binding_level->names = chainon(f_binding_level->names, declaration_tree);
auto *declaration_statement = build1_loc(declaration_location, DECL_EXPR,
void_type_node, declaration_tree);
@@ -1031,7 +1025,7 @@ namespace elna::gcc
}
else
{
- tree assignment = build2_loc(statement_location, MODIFY_EXPR, void_type_node, lvalue, rvalue);
+ tree assignment = fold_build2_loc(statement_location, MODIFY_EXPR, void_type_node, lvalue, rvalue);
append_statement(assignment);
}
@@ -1088,21 +1082,86 @@ namespace elna::gcc
return build3(COND_EXPR, void_type_node, condition, then_body, next);
}
- void generic_visitor::visit(boot::import_declaration *)
+ void generic_visitor::visit(boot::for_statement *statement)
{
+ statement->initial_value().accept(this);
+ tree initial_value = this->current_expression;
+
+ statement->final_value().accept(this);
+ tree final_value = this->current_expression;
+
+ tree step;
+ location_t step_location = UNKNOWN_LOCATION;
+ if (statement->step != nullptr)
+ {
+ statement->step->accept(this);
+ step = this->current_expression;
+ step_location = get_location(&statement->step->position());
+ }
+ enter_scope();
+ // Declare control variable with the unqualified type. The constant_type wrapper
+ // is for semantic checking only, because GENERIC needs to modify the control variable.
+ auto control_variable_info = statement->symbols->lookup(statement->control_variable.name());
+ boot::variable_info unqualified_info(resolve_underlying_type(control_variable_info->is_variable()->symbol),
+ control_variable_info->is_variable()->is_extern);
+ tree control_variable_declaration = declare_variable(statement->control_variable.name(),
+ unqualified_info, this->symbols);
+ DECL_CONTEXT(control_variable_declaration) = current_function_decl;
+ f_binding_level->names = chainon(f_binding_level->names, control_variable_declaration);
+ DECL_INITIAL(control_variable_declaration) = initial_value;
+ tree declaration_statement = build1_loc(get_location(&statement->control_variable.position()),
+ DECL_EXPR, void_type_node, control_variable_declaration);
+ append_statement(declaration_statement);
+
+ tree control_type = TREE_TYPE(control_variable_declaration);
+ if (statement->step == nullptr)
+ {
+ step = build_int_cst_type(control_type, 1);
+ }
+
+ // Put a label in front of the loop condition.
+ location_t check_location = get_location(&statement->position());
+ tree check_label = create_artificial_label(check_location);
+ tree check_statement = build1_loc(check_location, LABEL_EXPR, void_type_node, check_label);
+ append_statement(check_statement);
+
+ // Build the condition and jump if the condition isn't met.
+ tree condition = fold_build2(LE_EXPR, elna_bool_type_node, control_variable_declaration, final_value);
+ tree end_label = create_artificial_label(UNKNOWN_LOCATION);
+ tree goto_end = build1(GOTO_EXPR, void_type_node, end_label);
+ tree condition_statement = build3_loc(check_location, COND_EXPR, void_type_node,
+ condition, NULL_TREE, goto_end);
+ append_statement(condition_statement);
+
+ for (auto *body_statement : statement->body)
+ {
+ body_statement->accept(this);
+ }
+ // Adjust the control variable by step and jump to check the condition.
+ tree step_expression = fold_build2_loc(step_location, PLUS_EXPR, control_type,
+ control_variable_declaration, step);
+ append_statement(build2(MODIFY_EXPR, void_type_node, control_variable_declaration, step_expression));
+ tree goto_check = build1(GOTO_EXPR, void_type_node, check_label);
+ append_statement(goto_check);
+ tree end_statement = build1(LABEL_EXPR, void_type_node, end_label);
+ append_statement(end_statement);
+
+ tree for_binding = leave_scope();
+ append_statement(for_binding);
+
+ this->current_expression = NULL_TREE;
}
void generic_visitor::visit(boot::while_statement *statement)
{
location_t prerequisite_location = get_location(&statement->branch().prerequisite().position());
- tree while_check_label = build_label_decl("while_do", prerequisite_location);
- tree while_end_label = build_label_decl("while_end", UNKNOWN_LOCATION);
+ tree while_check_label = create_artificial_label(prerequisite_location);
+ tree while_end_label = create_artificial_label(UNKNOWN_LOCATION);
tree goto_check = build1(GOTO_EXPR, void_type_node, while_check_label);
tree result = NULL_TREE;
- auto& branches = statement->branches;
- for (auto& branch : branches | std::views::reverse)
+ for (boot::conditional_statements *branch : statement->branches | std::views::reverse)
{
result = make_if_branch(*branch, result, goto_check);
}
diff --git a/gcc/gcc/elna-tree.cc b/gcc/gcc/elna-tree.cc
index ab7363f..2568430 100644
--- a/gcc/gcc/elna-tree.cc
+++ b/gcc/gcc/elna-tree.cc
@@ -249,15 +249,6 @@ namespace elna::gcc
return composite_type_node;
}
- tree build_label_decl(const char *name, location_t loc)
- {
- auto label_decl = build_decl(loc, LABEL_DECL, get_identifier(name), void_type_node);
-
- DECL_CONTEXT(label_decl) = current_function_decl;
-
- return label_decl;
- }
-
tree extract_constant(tree expression)
{
int code = TREE_CODE(expression);