aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorEugen Wissner <belka@caraus.de>2026-07-21 01:55:56 +0200
committerEugen Wissner <belka@caraus.de>2026-07-21 01:55:56 +0200
commit44d6e8a27294e5ca7300ab11900011b73d9336d4 (patch)
treed21addb0dec93fa8fa376bbd11076b17f3412173 /gcc
parent6b131c925dee7a5f97516edd581e051e08bb52d8 (diff)
downloadelna-44d6e8a27294e5ca7300ab11900011b73d9336d4.tar.gz
Implement slices
Diffstat (limited to 'gcc')
-rw-r--r--gcc/gcc/elna-builtins.cc13
-rw-r--r--gcc/gcc/elna-generic.cc141
-rw-r--r--gcc/gcc/elna1.cc2
3 files changed, 145 insertions, 11 deletions
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<boot::slice_type>())
+ {
+ 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<boot::procedure_type>())
{
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<constructor_elt, va_gc> *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<boot::slice_type>() != 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<boot::slice_type>() != 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;
}();