aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorEugen Wissner <belka@caraus.de>2026-07-28 19:19:32 +0200
committerEugen Wissner <belka@caraus.de>2026-07-28 19:19:32 +0200
commit36a274c9a8bca944234589220def025d3920b3ef (patch)
treef198ad272b74ffa3abb13e5063b55514d521e1f6 /gcc
parent5cdaceb77af6a1d98145f8afb34ce6884e21a3d6 (diff)
downloadelna-36a274c9a8bca944234589220def025d3920b3ef.tar.gz
Enforce case label uniqueness and constness
Diffstat (limited to 'gcc')
-rw-r--r--gcc/Make-lang.in1
-rw-r--r--gcc/gcc/elna-builtins.cc2
-rw-r--r--gcc/gcc/elna-generic.cc140
-rw-r--r--gcc/gcc/elna-tree.cc103
4 files changed, 137 insertions, 109 deletions
diff --git a/gcc/Make-lang.in b/gcc/Make-lang.in
index 5b8b6a8..690d047 100644
--- a/gcc/Make-lang.in
+++ b/gcc/Make-lang.in
@@ -57,6 +57,7 @@ elna_OBJS = \
elna/type_check.o \
elna/symbol.o \
elna/result.o \
+ elna/validation.o \
$(END)
elna1$(exeext): attribs.o $(elna_OBJS) $(BACKEND) $(LIBDEPS)
diff --git a/gcc/gcc/elna-builtins.cc b/gcc/gcc/elna-builtins.cc
index 226de4a..7e47c30 100644
--- a/gcc/gcc/elna-builtins.cc
+++ b/gcc/gcc/elna-builtins.cc
@@ -19,6 +19,8 @@ along with GCC; see the file COPYING3. If not see
#include "elna/gcc/elna1.h"
#include "stor-layout.h"
#include "stringpool.h"
+
+#include "elna/boot/evaluator.h"
#include "elna/gcc/elna-tree.h"
namespace elna::gcc
diff --git a/gcc/gcc/elna-generic.cc b/gcc/gcc/elna-generic.cc
index 00581df..559d09c 100644
--- a/gcc/gcc/elna-generic.cc
+++ b/gcc/gcc/elna-generic.cc
@@ -16,10 +16,8 @@ along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
#include <array>
-#include <cstring>
#include <ranges>
-#include "elna/boot/evaluator.h"
#include "elna/gcc/elna-diagnostic.h"
#include "elna/gcc/elna-generic.h"
#include "elna/gcc/elna1.h"
@@ -38,7 +36,8 @@ namespace elna::gcc
{
generic_visitor::generic_visitor(const std::shared_ptr<symbol_table>& symbol_table,
boot::symbol_bag bag, const boot::target_info& target)
- : bag(std::move(bag)), symbols(symbol_table), target(target)
+ : bag(std::move(bag)), symbols(symbol_table), target(target),
+ constant_evaluator(this->bag, this->target)
{
}
@@ -483,104 +482,14 @@ namespace elna::gcc
cgraph_node::finalize_function(fndecl, true);
}
- static tree constant_to_tree(const boot::constant_value& constant_value, tree type = NULL_TREE)
- {
- if (std::holds_alternative<std::int32_t>(constant_value))
- {
- return build_int_cst(elna_int_type_node, std::get<std::int32_t>(constant_value));
- }
- else if (std::holds_alternative<std::uint32_t>(constant_value))
- {
- return build_int_cstu(elna_word_type_node, std::get<std::uint32_t>(constant_value));
- }
-
- else if (std::holds_alternative<double>(constant_value))
- {
- auto real_value = std::get<double>(constant_value);
- REAL_VALUE_TYPE real;
- constexpr std::size_t bits_size = (sizeof(double) + sizeof(HOST_WIDE_INT) - 1) / sizeof(HOST_WIDE_INT);
- std::array<HOST_WIDE_INT, bits_size> target_bits;
-
- std::memcpy(target_bits.data(), &real_value, sizeof(real_value));
- real_from_target(&real, target_bits.data(), REAL_MODE_FORMAT(TYPE_MODE(elna_float_type_node)));
-
- return build_real(elna_float_type_node, real);
- }
- else if (std::holds_alternative<bool>(constant_value))
- {
- return std::get<bool>(constant_value) ? boolean_true_node : boolean_false_node;
- }
- else if (std::holds_alternative<unsigned char>(constant_value))
- {
- return build_int_cstu(elna_char_type_node, std::get<unsigned char>(constant_value));
- }
- else if (std::holds_alternative<std::nullptr_t>(constant_value))
- {
- return null_pointer_node;
- }
- else if (std::holds_alternative<boot::constant_aggregate<boot::ordered_map>>(constant_value))
- {
- // NOLINTNEXTLINE(readability-simplify-boolean-expr)
- if (type == NULL_TREE || !RECORD_OR_UNION_TYPE_P(type))
- {
- return NULL_TREE;
- }
- const auto& aggregate = std::get<boot::constant_aggregate<boot::ordered_map>>(constant_value);
- const auto& fields = *aggregate;
- vec<constructor_elt, va_gc> *tree_arguments = nullptr;
-
- for (const auto& [field_name, field_value] : fields)
- {
- tree field_decl = find_field_by_name(UNKNOWN_LOCATION, type, field_name);
- if (field_decl == error_mark_node)
- {
- return NULL_TREE;
- }
- tree value_tree = constant_to_tree(field_value, TREE_TYPE(field_decl));
- if (value_tree == NULL_TREE)
- {
- return NULL_TREE;
- }
- CONSTRUCTOR_APPEND_ELT(tree_arguments, field_decl, value_tree);
- }
- return build_constructor(type, tree_arguments);
- }
- else if (std::holds_alternative<boot::constant_aggregate<std::vector>>(constant_value))
- {
- if (type == NULL_TREE || TREE_CODE(type) != ARRAY_TYPE)
- {
- return NULL_TREE;
- }
- const auto& aggregate = std::get<boot::constant_aggregate<std::vector>>(constant_value);
- const auto& elements = *aggregate;
- tree domain = TYPE_DOMAIN(type);
- tree index = TYPE_MIN_VALUE(domain);
- tree element_type = TREE_TYPE(type);
- vec<constructor_elt, va_gc> *tree_arguments = nullptr;
-
- for (const auto& element : elements)
- {
- tree element_tree = constant_to_tree(element, element_type);
- if (element_tree == NULL_TREE)
- {
- return NULL_TREE;
- }
- CONSTRUCTOR_APPEND_ELT(tree_arguments, index, element_tree);
- index = int_const_binop(PLUS_EXPR, index, elna_word_one_node);
- }
- return build_constructor(type, tree_arguments);
- }
- return NULL_TREE;
- }
-
void generic_visitor::visit(boot::literal<std::int32_t> *literal)
{
- this->current_expression = constant_to_tree(boot::constant_value{ literal->value });
+ this->current_expression = constant_to_tree(boot::constant_value{ literal->value }, this->symbols);
}
void generic_visitor::visit(boot::literal<std::uint32_t> *literal)
{
- this->current_expression = constant_to_tree(boot::constant_value{ literal->value });
+ this->current_expression = constant_to_tree(boot::constant_value{ literal->value }, this->symbols);
}
void generic_visitor::visit(boot::literal<double> *literal)
@@ -600,17 +509,17 @@ namespace elna::gcc
void generic_visitor::visit(boot::literal<bool> *boolean)
{
- this->current_expression = constant_to_tree(boot::constant_value{ boolean->value });
+ this->current_expression = constant_to_tree(boot::constant_value{ boolean->value }, this->symbols);
}
void generic_visitor::visit(boot::literal<unsigned char> *character)
{
- this->current_expression = constant_to_tree(boot::constant_value{ character->value });
+ this->current_expression = constant_to_tree(boot::constant_value{ character->value }, this->symbols);
}
void generic_visitor::visit(boot::literal<std::nullptr_t> *)
{
- this->current_expression = constant_to_tree(boot::constant_value{ std::nullptr_t{} });
+ this->current_expression = constant_to_tree(boot::constant_value{ std::nullptr_t{} }, this->symbols);
}
void generic_visitor::visit(boot::literal<std::string> *string)
@@ -639,6 +548,19 @@ namespace elna::gcc
this->current_expression = build_constructor(slice_type, elms);
}
+ void generic_visitor::visit(boot::traits_expression *trait)
+ {
+ auto value = this->constant_evaluator.evaluate_traits(*trait);
+
+ if (!value.has_value())
+ {
+ this->current_expression = error_mark_node;
+ return;
+ }
+ tree type = get_inner_alias(trait->type_decoration, this->symbols);
+ this->current_expression = constant_to_tree(value.value(), this->symbols, type);
+ }
+
void generic_visitor::visit(boot::binary_expression *expression)
{
expression->lhs().accept(this);
@@ -794,15 +716,19 @@ namespace elna::gcc
location_t declaration_location = get_location(&declaration->position());
tree declaration_tree = this->symbols->lookup(variable_identifier.name());
+ auto variable_symbol = this->bag.lookup(variable_identifier.name())->is_variable();
+
if (declaration_tree == NULL_TREE)
{
- auto variable_symbol = this->bag.lookup(variable_identifier.name())->is_variable();
-
declaration_tree = declare_variable(variable_identifier.name(), *variable_symbol, this->symbols);
}
- // Set initializer if given. The constant_folder pass has
- // already folded the initializer into literals at this point.
- if (declaration->initializer != nullptr)
+ if (variable_symbol->value.has_value())
+ {
+ tree type = get_inner_alias(variable_symbol->symbol, this->symbols);
+ DECL_INITIAL(declaration_tree) = constant_to_tree(
+ variable_symbol->value.value(), this->symbols, type);
+ }
+ else if (declaration->initializer != nullptr)
{
declaration->initializer->accept(this);
DECL_INITIAL(declaration_tree) = this->current_expression;
@@ -811,13 +737,9 @@ namespace elna::gcc
{
DECL_INITIAL(declaration_tree) = null_pointer_node;
}
+ if (variable_symbol->symbol.get<boot::constant_type>() != nullptr)
{
- auto variable_symbol = this->bag.lookup(variable_identifier.name())->is_variable();
-
- if (variable_symbol != nullptr && variable_symbol->symbol.get<boot::constant_type>() != nullptr)
- {
- TREE_READONLY(declaration_tree) = 1;
- }
+ TREE_READONLY(declaration_tree) = 1;
}
this->current_expression = NULL_TREE;
diff --git a/gcc/gcc/elna-tree.cc b/gcc/gcc/elna-tree.cc
index e8a7daa..352d413 100644
--- a/gcc/gcc/elna-tree.cc
+++ b/gcc/gcc/elna-tree.cc
@@ -15,6 +15,9 @@ You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
+#include <array>
+#include <cstring>
+
#include "elna/gcc/elna-diagnostic.h"
#include "elna/gcc/elna-tree.h"
#include "elna/gcc/elna1.h"
@@ -281,4 +284,104 @@ namespace elna::gcc
}
return NULL_TREE;
}
+
+ tree constant_to_tree(const boot::constant_value& constant_value,
+ const std::shared_ptr<symbol_table>& symbols, tree type)
+ {
+ if (std::holds_alternative<std::int32_t>(constant_value))
+ {
+ return build_int_cst(elna_int_type_node, std::get<std::int32_t>(constant_value));
+ }
+ else if (std::holds_alternative<std::uint32_t>(constant_value))
+ {
+ return build_int_cstu(elna_word_type_node, std::get<std::uint32_t>(constant_value));
+ }
+ else if (std::holds_alternative<double>(constant_value))
+ {
+ auto real_value = std::get<double>(constant_value);
+ REAL_VALUE_TYPE real;
+ constexpr std::size_t bits_size = (sizeof(double) + sizeof(HOST_WIDE_INT) - 1) / sizeof(HOST_WIDE_INT);
+ std::array<HOST_WIDE_INT, bits_size> target_bits;
+
+ std::memcpy(target_bits.data(), &real_value, sizeof(real_value));
+ real_from_target(&real, target_bits.data(), REAL_MODE_FORMAT(TYPE_MODE(elna_float_type_node)));
+
+ return build_real(elna_float_type_node, real);
+ }
+ else if (std::holds_alternative<bool>(constant_value))
+ {
+ return std::get<bool>(constant_value) ? boolean_true_node : boolean_false_node;
+ }
+ else if (std::holds_alternative<unsigned char>(constant_value))
+ {
+ return build_int_cstu(elna_char_type_node, std::get<unsigned char>(constant_value));
+ }
+ else if (std::holds_alternative<std::nullptr_t>(constant_value))
+ {
+ return null_pointer_node;
+ }
+ else if (std::holds_alternative<boot::global_address>(constant_value))
+ {
+ const auto& address = std::get<boot::global_address>(constant_value);
+ tree decl = symbols->lookup(address.name);
+ if (decl == NULL_TREE)
+ {
+ return NULL_TREE;
+ }
+ return build1(ADDR_EXPR, build_pointer_type(TREE_TYPE(decl)), decl);
+ }
+ else if (std::holds_alternative<boot::constant_aggregate<boot::ordered_map>>(constant_value))
+ {
+ // NOLINTNEXTLINE(readability-simplify-boolean-expr)
+ if (type == NULL_TREE || !RECORD_OR_UNION_TYPE_P(type))
+ {
+ return NULL_TREE;
+ }
+ const auto& aggregate = std::get<boot::constant_aggregate<boot::ordered_map>>(constant_value);
+ const auto& fields = *aggregate;
+ vec<constructor_elt, va_gc> *tree_arguments = nullptr;
+
+ for (const auto& [field_name, field_value] : fields)
+ {
+ tree field_decl = find_field_by_name(UNKNOWN_LOCATION, type, field_name);
+ if (field_decl == error_mark_node)
+ {
+ return NULL_TREE;
+ }
+ tree value_tree = constant_to_tree(field_value, symbols, TREE_TYPE(field_decl));
+ if (value_tree == NULL_TREE)
+ {
+ return NULL_TREE;
+ }
+ CONSTRUCTOR_APPEND_ELT(tree_arguments, field_decl, value_tree);
+ }
+ return build_constructor(type, tree_arguments);
+ }
+ else if (std::holds_alternative<boot::constant_aggregate<std::vector>>(constant_value))
+ {
+ if (type == NULL_TREE || TREE_CODE(type) != ARRAY_TYPE)
+ {
+ return NULL_TREE;
+ }
+ const auto& aggregate = std::get<boot::constant_aggregate<std::vector>>(constant_value);
+ const auto& elements = *aggregate;
+ tree domain = TYPE_DOMAIN(type);
+ tree index = TYPE_MIN_VALUE(domain);
+ tree element_type = TREE_TYPE(type);
+ vec<constructor_elt, va_gc> *tree_arguments = nullptr;
+
+ for (const auto& element : elements)
+ {
+ tree element_tree = constant_to_tree(element, symbols, element_type);
+ if (element_tree == NULL_TREE)
+ {
+ return NULL_TREE;
+ }
+ CONSTRUCTOR_APPEND_ELT(tree_arguments, index, element_tree);
+ index = int_const_binop(PLUS_EXPR, index, elna_word_one_node);
+ }
+ return build_constructor(type, tree_arguments);
+ }
+ return NULL_TREE;
+ }
}