aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/gcc/elna-generic.cc139
-rw-r--r--gcc/gcc/elna-tree.cc5
2 files changed, 95 insertions, 49 deletions
diff --git a/gcc/gcc/elna-generic.cc b/gcc/gcc/elna-generic.cc
index 6fe3da9..ebf4f8f 100644
--- a/gcc/gcc/elna-generic.cc
+++ b/gcc/gcc/elna-generic.cc
@@ -947,7 +947,7 @@ namespace elna::gcc
if (TREE_CODE(aggregate_type) == ARRAY_TYPE && expression->field() == "length")
{
- this->current_expression = convert(build_qualified_type(elna_word_type_node, TYPE_QUAL_CONST),
+ this->current_expression = fold_convert(elna_word_type_node,
TYPE_MAX_VALUE(TYPE_DOMAIN(aggregate_type)));
}
else if (TREE_CODE(aggregate_type) == ARRAY_TYPE && expression->field() == "ptr")
@@ -1082,69 +1082,120 @@ namespace elna::gcc
return build3(COND_EXPR, void_type_node, condition, then_body, next);
}
- void generic_visitor::visit(boot::for_statement *statement)
+ tree generic_visitor::declare_local_variable(const boot::identifier& name,
+ const boot::variable_info& info, tree initial_value)
{
- 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);
+ tree decl = declare_variable(name.name(), info, this->symbols);
+ DECL_CONTEXT(decl) = current_function_decl;
+ f_binding_level->names = chainon(f_binding_level->names, decl);
+ DECL_INITIAL(decl) = initial_value;
+ tree declaration_statement = build1_loc(get_location(&name.position()),
+ DECL_EXPR, void_type_node, decl);
append_statement(declaration_statement);
- tree control_type = TREE_TYPE(control_variable_declaration);
- if (statement->step == nullptr)
- {
- step = build_int_cst_type(control_type, 1);
- }
+ return decl;
+ }
+ std::pair<tree, tree> generic_visitor::build_loop_head(tree control_variable_declaration, tree limit,
+ tree_code comparison, location_t check_location)
+ {
// 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 condition = fold_build2(comparison, elna_bool_type_node, control_variable_declaration, limit);
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);
+ return { check_label, end_label };
+ }
+
+ void generic_visitor::visit(boot::repeat_statement *statement)
+ {
+ tree loop_label = create_artificial_label(get_location(&statement->position()));
+ tree goto_loop = build1(GOTO_EXPR, void_type_node, loop_label);
+ append_statement(build1(LABEL_EXPR, void_type_node, loop_label));
+
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);
+ statement->condition().accept(this);
+ tree condition_statement = build3(COND_EXPR, void_type_node,
+ this->current_expression, NULL_TREE, goto_loop);
+ append_statement(condition_statement);
+ }
+
+ void generic_visitor::visit(boot::for_statement *statement)
+ {
+ statement->range().accept(this);
+ tree range_expression = this->current_expression;
+ location_t location = get_location(&statement->position());
+ tree start_pointer;
+ tree length;
+
+ if (TREE_CODE(TREE_TYPE(range_expression)) == ARRAY_TYPE)
+ {
+ tree element_type = TREE_TYPE(TREE_TYPE(range_expression));
+ tree array_reference = build4_loc(location, ARRAY_REF, element_type,
+ range_expression, size_one_node, NULL_TREE, NULL_TREE);
+
+ start_pointer = build1(ADDR_EXPR, build_pointer_type(element_type), array_reference);
+ length = TYPE_MAX_VALUE(TYPE_DOMAIN(TREE_TYPE(range_expression)));
+ }
+ else
+ {
+ tree ptr_field = TYPE_FIELDS(TREE_TYPE(range_expression));
+ tree length_field = TREE_CHAIN(ptr_field);
+
+ start_pointer = build3_loc(location, COMPONENT_REF, TREE_TYPE(ptr_field),
+ range_expression, ptr_field, NULL_TREE);
+ length = build3_loc(location, COMPONENT_REF, TREE_TYPE(length_field),
+ range_expression, length_field, NULL_TREE);
+ }
+ tree end_pointer = do_pointer_arithmetic(boot::binary_operator::sum, start_pointer, length, location);
+
+ 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(
+ boot::resolve_underlying_type(control_variable_info->is_variable()->symbol),
+ control_variable_info->is_variable()->is_extern);
+ tree control_variable_declaration = declare_local_variable(
+ statement->control_variable, unqualified_info, start_pointer);
+
+ tree elna_one = build_int_cst_type(elna_word_type_node, 1);
+ tree counter_declaration{ NULL_TREE };
+ if (statement->counter != nullptr)
+ {
+ auto counter_info = statement->symbols->lookup(statement->counter->name());
+ counter_declaration = declare_local_variable(*statement->counter,
+ *counter_info->is_variable(), elna_one);
+ }
+ auto [check_label, end_label] = build_loop_head(control_variable_declaration,
+ end_pointer, LT_EXPR, location);
+
+ for (auto *body_statement : statement->body)
+ {
+ body_statement->accept(this);
+ }
+ tree pointer_plus = do_pointer_arithmetic(boot::binary_operator::sum,
+ control_variable_declaration, elna_one, location);
+ append_statement(build2(MODIFY_EXPR, void_type_node, control_variable_declaration, pointer_plus));
+
+ if (counter_declaration != NULL_TREE)
+ {
+ tree counter_plus = fold_build2(PLUS_EXPR, elna_word_type_node, counter_declaration, elna_one);
+ append_statement(build2(MODIFY_EXPR, void_type_node, counter_declaration, counter_plus));
+ }
+ append_statement(build1(GOTO_EXPR, void_type_node, check_label));
+ append_statement(build1(LABEL_EXPR, void_type_node, end_label));
tree for_binding = leave_scope();
append_statement(for_binding);
diff --git a/gcc/gcc/elna-tree.cc b/gcc/gcc/elna-tree.cc
index 2568430..7466f24 100644
--- a/gcc/gcc/elna-tree.cc
+++ b/gcc/gcc/elna-tree.cc
@@ -31,11 +31,6 @@ namespace elna::gcc
return TREE_CODE(type) == INTEGER_TYPE && type != elna_char_type_node;
}
- bool is_numeric_type(tree type)
- {
- return is_integral_type(type) || type == elna_float_type_node;
- }
-
bool is_unique_type(tree type)
{
gcc_assert(TYPE_P(type));