From 44d6e8a27294e5ca7300ab11900011b73d9336d4 Mon Sep 17 00:00:00 2001 From: Eugen Wissner Date: Tue, 21 Jul 2026 01:55:56 +0200 Subject: Implement slices --- gcc/gcc/elna-builtins.cc | 13 +++++ gcc/gcc/elna-generic.cc | 141 +++++++++++++++++++++++++++++++++++++++++++---- gcc/gcc/elna1.cc | 2 + 3 files changed, 145 insertions(+), 11 deletions(-) (limited to 'gcc') diff --git a/gcc/gcc/elna-builtins.cc b/gcc/gcc/elna-builtins.cc index 5284563..141b34f 100644 --- a/gcc/gcc/elna-builtins.cc +++ b/gcc/gcc/elna-builtins.cc @@ -154,6 +154,19 @@ namespace elna::gcc return build_static_array_type(base, reference->size); } + else if (auto reference = type.get()) + { + tree base_type = get_inner_alias(reference->base, symbols); + tree slice_record = make_node(RECORD_TYPE); + tree ptr_field = build_field(UNKNOWN_LOCATION, slice_record, "ptr", + build_pointer_type(base_type)); + tree length_field = build_field(UNKNOWN_LOCATION, slice_record, "length", + elna_word_type_node); + + TYPE_FIELDS(slice_record) = chainon(ptr_field, length_field); + layout_type(slice_record); + return slice_record; + } else if (auto reference = type.get()) { auto procedure = build_procedure_type(*reference, symbols); diff --git a/gcc/gcc/elna-generic.cc b/gcc/gcc/elna-generic.cc index 8561ac4..ea209df 100644 --- a/gcc/gcc/elna-generic.cc +++ b/gcc/gcc/elna-generic.cc @@ -219,6 +219,49 @@ namespace elna::gcc this->current_expression = build_constructor(array_type, tree_arguments); } + void generic_visitor::visit(boot::slicing_expression *expression) + { + location_t location = get_location(&expression->position()); + tree slice_type = get_inner_alias(expression->type_decoration, this->symbols); + tree ptr_field = TYPE_FIELDS(slice_type); + tree length_field = TREE_CHAIN(ptr_field); + + expression->base().accept(this); + tree base = this->current_expression; + tree base_type = TREE_TYPE(base); + + expression->offset().accept(this); + tree offset = fold_convert(elna_word_type_node, this->current_expression); + offset = build2(MINUS_EXPR, elna_word_type_node, offset, size_one_node); + + tree slice_ptr; + if (TREE_CODE(base_type) == ARRAY_TYPE) + { + slice_ptr = build4_loc(location, ARRAY_REF, TREE_TYPE(base_type), + base, offset, size_one_node, NULL_TREE); + slice_ptr = build1(ADDR_EXPR, build_pointer_type(TREE_TYPE(base_type)), slice_ptr); + } + else + { + tree ptr = build3_loc(location, COMPONENT_REF, TREE_TYPE(ptr_field), + base, ptr_field, NULL_TREE); + slice_ptr = do_pointer_arithmetic(boot::binary_operator::sum, ptr, offset, location); + } + + expression->length().accept(this); + tree end_index = fold_convert(elna_word_type_node, this->current_expression); + expression->offset().accept(this); + tree start_index = fold_convert(elna_word_type_node, this->current_expression); + tree slice_length = build2(MINUS_EXPR, elna_word_type_node, + end_index, start_index); + slice_length = build2(PLUS_EXPR, elna_word_type_node, slice_length, size_one_node); + + vec *tree_arguments = nullptr; + CONSTRUCTOR_APPEND_ELT(tree_arguments, ptr_field, slice_ptr); + CONSTRUCTOR_APPEND_ELT(tree_arguments, length_field, slice_length); + this->current_expression = build_constructor(slice_type, tree_arguments); + } + void generic_visitor::visit(boot::unit *unit) { for (boot::import_declaration *const declaration : unit->imports) @@ -531,6 +574,44 @@ namespace elna::gcc return build2(combination_code, elna_bool_type_node, length_equality, equals_zero); } + else if (expression->lhs().type_decoration.get() != nullptr) + { + tree lhs_ptr_field = TYPE_FIELDS(TREE_TYPE(left)); + tree lhs_length_field = TREE_CHAIN(lhs_ptr_field); + + tree lhs_length = build3(COMPONENT_REF, TREE_TYPE(lhs_length_field), + left, lhs_length_field, NULL_TREE); + tree lhs_ptr = build3(COMPONENT_REF, TREE_TYPE(lhs_ptr_field), + left, lhs_ptr_field, NULL_TREE); + + tree rhs_length = build3(COMPONENT_REF, TREE_TYPE(lhs_length_field), + right, lhs_length_field, NULL_TREE); + tree rhs_ptr = build3(COMPONENT_REF, TREE_TYPE(lhs_ptr_field), + right, lhs_ptr_field, NULL_TREE); + + tree element_size = fold_convert(elna_word_type_node, + size_in_bytes(TREE_TYPE(TREE_TYPE(lhs_ptr_field)))); + tree byte_length = build2(MULT_EXPR, elna_word_type_node, lhs_length, element_size); + + tree length_equality = build2(equality_code, elna_bool_type_node, lhs_length, rhs_length); + tree memcmp_call = call_built_in(UNKNOWN_LOCATION, "__builtin_memcmp", integer_type_node, + lhs_ptr, rhs_ptr, byte_length); + tree equals_zero = build2(equality_code, elna_bool_type_node, memcmp_call, integer_zero_node); + + return build2(combination_code, elna_bool_type_node, length_equality, equals_zero); + } + else if (TREE_CODE(TREE_TYPE(left)) == RECORD_TYPE) + { + tree size = fold_convert(elna_word_type_node, + size_in_bytes(TREE_TYPE(left))); + tree lhs_addr = build1(ADDR_EXPR, + build_pointer_type(TREE_TYPE(left)), left); + tree rhs_addr = build1(ADDR_EXPR, + build_pointer_type(TREE_TYPE(right)), right); + tree memcmp_call = call_built_in(UNKNOWN_LOCATION, "__builtin_memcmp", + integer_type_node, lhs_addr, rhs_addr, size); + return build2(equality_code, elna_bool_type_node, memcmp_call, integer_zero_node); + } else { return build2_loc(expression_location, equality_code, elna_bool_type_node, left, right); @@ -828,13 +909,17 @@ namespace elna::gcc this->current_expression = build4_loc(location, ARRAY_REF, element_type, designator, offset, size_one_node, NULL_TREE); } - else if (TREE_TYPE(designator) == elna_string_type_node) + else if (TREE_TYPE(designator) == elna_string_type_node + || expression->base().type_decoration.get() != nullptr) { + tree ptr_field = (TREE_TYPE(designator) == elna_string_type_node) + ? elna_string_ptr_field_node + : TYPE_FIELDS(TREE_TYPE(designator)); offset = build2(MINUS_EXPR, elna_word_type_node, offset, size_one_node); - tree string_ptr = build3_loc(location, COMPONENT_REF, TREE_TYPE(elna_string_ptr_field_node), - designator, elna_string_ptr_field_node, NULL_TREE); + tree slice_ptr = build3_loc(location, COMPONENT_REF, TREE_TYPE(ptr_field), + designator, ptr_field, NULL_TREE); - tree target_pointer = do_pointer_arithmetic(boot::binary_operator::sum, string_ptr, offset, location); + tree target_pointer = do_pointer_arithmetic(boot::binary_operator::sum, slice_ptr, offset, location); this->current_expression = build_simple_mem_ref_loc(location, target_pointer); } @@ -864,13 +949,48 @@ namespace elna::gcc { location_t trait_location = get_location(&trait->position()); - if (trait->name == "size" || trait->name == "alignment" - || trait->name == "min" || trait->name == "max") + if (trait->name == "size") + { + if (expect_trait_type_only(trait)) + { + if (auto value = this->const_evaluator->evaluate_traits(*trait)) + { + this->current_expression = constant_to_tree(*value); + } + else + { + this->current_expression = fold_convert_loc(trait_location, + elna_word_type_node, size_in_bytes(this->current_expression)); + } + } + } + else if (trait->name == "alignment") + { + if (expect_trait_type_only(trait)) + { + if (auto value = this->const_evaluator->evaluate_traits(*trait)) + { + this->current_expression = constant_to_tree(*value); + } + else + { + this->current_expression = build_int_cstu(elna_word_type_node, + TYPE_ALIGN_UNIT(this->current_expression)); + } + } + } + else if (trait->name == "min" || trait->name == "max") { if (expect_trait_type_only(trait)) { - this->current_expression = constant_to_tree( - *this->const_evaluator->evaluate_traits(*trait)); + if (auto value = this->const_evaluator->evaluate_traits(*trait)) + { + this->current_expression = constant_to_tree(*value); + } + else + { + this->current_expression = error_mark_node; + } } } else if (trait->name == "offset") @@ -883,7 +1003,7 @@ namespace elna::gcc return; } this->current_expression = get_inner_alias(trait->types.front(), this->symbols); - auto field_type = trait->arguments.at(1)->is_named(); + auto *field_type = trait->arguments.at(1)->is_named(); if (field_type == nullptr) { @@ -1015,8 +1135,7 @@ namespace elna::gcc result = leave_scope(); } - auto& branches = statement->branches; - for (auto& branch : branches | std::views::reverse) + for (const auto& branch : statement->branches | std::views::reverse) { result = make_if_branch(*branch, result); } diff --git a/gcc/gcc/elna1.cc b/gcc/gcc/elna1.cc index e75277e..94055e5 100644 --- a/gcc/gcc/elna1.cc +++ b/gcc/gcc/elna1.cc @@ -67,6 +67,8 @@ static const elna::boot::target_info& get_host_target() target_info.char_alignment = TYPE_ALIGN_UNIT(elna_char_type_node); target_info.float_size = TYPE_PRECISION(elna_float_type_node) / BITS_PER_UNIT; target_info.float_alignment = TYPE_ALIGN_UNIT(elna_float_type_node); + target_info.bool_size = TYPE_PRECISION(elna_bool_type_node) / BITS_PER_UNIT; + target_info.bool_alignment = TYPE_ALIGN_UNIT(elna_bool_type_node); return target_info; }(); -- cgit v1.2.3