aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/gcc/elna-builtins.cc4
-rw-r--r--gcc/gcc/elna-generic.cc108
-rw-r--r--gcc/gcc/elna-tree.cc2
-rw-r--r--gcc/gcc/elna1.cc4
4 files changed, 88 insertions, 30 deletions
diff --git a/gcc/gcc/elna-builtins.cc b/gcc/gcc/elna-builtins.cc
index 57d2875..6ea8874 100644
--- a/gcc/gcc/elna-builtins.cc
+++ b/gcc/gcc/elna-builtins.cc
@@ -65,8 +65,8 @@ namespace elna::gcc
return builtin_table;
}
- tree build_composite_type(const std::vector<boot::type_field>& fields, tree composite_type_node,
- std::shared_ptr<symbol_table> symbols)
+ tree build_composite_type(const boot::ordered_map<boot::type>& fields,
+ tree composite_type_node, std::shared_ptr<symbol_table> symbols)
{
for (auto& field : fields)
{
diff --git a/gcc/gcc/elna-generic.cc b/gcc/gcc/elna-generic.cc
index c462924..f77f371 100644
--- a/gcc/gcc/elna-generic.cc
+++ b/gcc/gcc/elna-generic.cc
@@ -429,6 +429,14 @@ namespace elna::gcc
{
return null_pointer_node;
}
+ else if (std::holds_alternative<boot::constant_aggregate<boot::ordered_map>>(constant_value))
+ {
+ return NULL_TREE; // Compound constants are not lowered to trees yet.
+ }
+ else if (std::holds_alternative<boot::constant_aggregate<std::vector>>(constant_value))
+ {
+ return NULL_TREE; // Compound constants are not lowered to trees yet.
+ }
return NULL_TREE;
}
@@ -498,26 +506,33 @@ namespace elna::gcc
this->current_expression = build_constructor(slice_type, elms);
}
- tree generic_visitor::build_equality_operation(boot::binary_expression *expression, tree left, tree right)
+ tree generic_visitor::build_equality(boot::binary_expression *expression, tree left, tree right)
{
- location_t expression_location = get_location(&expression->position());
- tree_code equality_code, combination_code;
+ tree_code equality_code;
if (expression->operation() == boot::binary_operator::equals)
{
equality_code = EQ_EXPR;
- combination_code = TRUTH_ANDIF_EXPR;
}
else if (expression->operation() == boot::binary_operator::not_equals)
{
equality_code = NE_EXPR;
- combination_code = TRUTH_ORIF_EXPR;
}
else
{
gcc_unreachable();
}
- if (expression->lhs().type_decoration.get<boot::slice_type>() != nullptr)
+ return build_equality_comparison(get_location(&expression->position()), left, right,
+ expression->lhs().type_decoration, equality_code);
+ }
+
+ tree generic_visitor::build_equality_comparison(location_t loc, tree left, tree right,
+ const boot::type& left_type, tree_code equality_code)
+ {
+ tree_code combination_code = equality_code == EQ_EXPR
+ ? TRUTH_ANDIF_EXPR : TRUTH_ORIF_EXPR;
+
+ if (left_type.get<boot::slice_type>() != nullptr)
{
tree lhs_ptr_field = TYPE_FIELDS(TREE_TYPE(left));
tree lhs_length_field = TREE_CHAIN(lhs_ptr_field);
@@ -543,22 +558,20 @@ namespace elna::gcc
return build2(combination_code, elna_bool_type_node, length_equality, equals_zero);
}
- else if (expression->lhs().type_decoration.get<boot::record_type>() != nullptr
- || expression->lhs().type_decoration.get<boot::array_type>() != nullptr)
+ else if (left_type.get<boot::record_type>() != nullptr
+ || left_type.get<boot::array_type>() != nullptr)
{
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 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);
+ return build2_loc(loc, equality_code, elna_bool_type_node, left, right);
}
}
@@ -574,9 +587,11 @@ namespace elna::gcc
location_t expression_location = get_location(&expression->position());
+ const bool is_pointer_arithmetic_operation
+ = expression->operation() == boot::binary_operator::sum
+ || expression->operation() == boot::binary_operator::subtraction;
if ((POINTER_TYPE_P(left_type) || POINTER_TYPE_P(right_type))
- && (expression->operation() == boot::binary_operator::sum
- || expression->operation() == boot::binary_operator::subtraction))
+ && is_pointer_arithmetic_operation)
{
this->current_expression = do_pointer_arithmetic(expression->operation(),
left, right, expression_location);
@@ -655,7 +670,7 @@ namespace elna::gcc
break;
case equals:
case not_equals:
- this->current_expression = build_equality_operation(expression, left, right);
+ this->current_expression = build_equality(expression, left, right);
break;
case shift_left:
this->current_expression = fold_build2_loc(expression_location,
@@ -1247,16 +1262,21 @@ namespace elna::gcc
{
statement->condition().accept(this);
tree condition_expression = this->current_expression;
- tree unqualified_condition = get_qualified_type(TREE_TYPE(this->current_expression), TYPE_UNQUALIFIED);
+ tree unqualified_condition = get_qualified_type(TREE_TYPE(condition_expression), TYPE_UNQUALIFIED);
- if (!INTEGRAL_TYPE_P(unqualified_condition))
+ if (INTEGRAL_TYPE_P(unqualified_condition))
{
- error_at(get_location(&statement->condition().position()),
- "Case expressions can only be integral numbers, characters and enumerations, given '%s'",
- print_type(unqualified_condition).c_str());
- this->current_expression = NULL_TREE;
- return;
+ build_case_integral(statement, condition_expression);
}
+ else
+ {
+ build_case_general(statement, condition_expression);
+ }
+ this->current_expression = NULL_TREE;
+ }
+
+ void generic_visitor::build_case_integral(boot::case_statement *statement, tree condition_expression)
+ {
tree end_label_declaration = create_artificial_label(get_location(&statement->position()));
tree switch_statements = alloc_stmt_list();
@@ -1296,13 +1316,51 @@ namespace elna::gcc
}
tree switch_expression = build2(SWITCH_EXPR, TREE_TYPE(condition_expression),
condition_expression, switch_statements);
-
append_statement(switch_expression);
tree end_label_expression = build1(LABEL_EXPR, void_type_node, end_label_declaration);
append_statement(end_label_expression);
+ }
- this->current_expression = NULL_TREE;
+ void generic_visitor::build_case_general(boot::case_statement *statement, tree condition_expression)
+ {
+ tree condition_value = build1(SAVE_EXPR, TREE_TYPE(condition_expression), condition_expression);
+
+ // Build from the bottom up: else branch first.
+ tree result = NULL_TREE;
+ if (statement->alternative != nullptr)
+ {
+ enter_scope();
+ visit_statements(*statement->alternative);
+ result = leave_scope();
+ }
+ for (const boot::switch_case& case_block : statement->cases | std::views::reverse)
+ {
+ tree case_condition = boolean_false_node;
+ for (boot::expression *const case_label : case_block.labels)
+ {
+ case_label->accept(this);
+ if (!assert_constant(get_location(&case_label->position())))
+ {
+ continue;
+ }
+ tree label_comparison = build_equality_comparison(get_location(&case_label->position()),
+ condition_value, this->current_expression,
+ statement->condition().type_decoration, EQ_EXPR);
+ case_condition = build2(TRUTH_ORIF_EXPR, elna_bool_type_node,
+ case_condition, label_comparison);
+ }
+
+ enter_scope();
+ visit_statements(case_block.statements);
+ tree then_body = leave_scope();
+
+ result = build3(COND_EXPR, void_type_node, case_condition, then_body, result);
+ }
+ if (result != NULL_TREE)
+ {
+ append_statement(result);
+ }
}
bool generic_visitor::assert_constant(location_t expression_location)
diff --git a/gcc/gcc/elna-tree.cc b/gcc/gcc/elna-tree.cc
index 26936fe..c47bb94 100644
--- a/gcc/gcc/elna-tree.cc
+++ b/gcc/gcc/elna-tree.cc
@@ -252,7 +252,7 @@ namespace elna::gcc
{
return DECL_INITIAL(expression);
}
- else if (TREE_CODE_CLASS(code) == tcc_constant)
+ else if (TREE_CODE_CLASS(code) == tcc_constant || TREE_CONSTANT(expression))
{
return expression;
}
diff --git a/gcc/gcc/elna1.cc b/gcc/gcc/elna1.cc
index 94055e5..fde2adc 100644
--- a/gcc/gcc/elna1.cc
+++ b/gcc/gcc/elna1.cc
@@ -136,14 +136,14 @@ static elna::boot::dependency elna_parse_file(dependency_state& state, const cha
std::filesystem::path sub_path = find_module(sub_tree)[0];
dependency_state::const_iterator cached_import = state.find(sub_path);
- if (cached_import == state.cend())
+ if (cached_import == std::cend(state))
{
auto filename_pointer = ggc_strdup(sub_path.native().c_str());
elna_parse_file(state, filename_pointer);
cached_import = state.find(sub_path);
}
- if (cached_import != state.cend())
+ if (cached_import != std::cend(state))
{
outcome_bag.add_import(cached_import->second);
}