diff options
Diffstat (limited to 'gcc')
| -rw-r--r-- | gcc/gcc/elna-generic.cc | 139 | ||||
| -rw-r--r-- | gcc/gcc/elna-tree.cc | 5 |
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)); |
