From 2e1e95dc716167853be4a4b6acaaee1688142744 Mon Sep 17 00:00:00 2001 From: Eugen Wissner Date: Sun, 19 Jul 2026 02:08:06 +0200 Subject: Implement initializer evaluator --- gcc/Make-lang.in | 1 + gcc/gcc/elna-generic.cc | 68 ++++++++++++++++++++++++++++++++++++++++++++++--- gcc/gcc/elna1.cc | 26 +++++++++++++++++-- 3 files changed, 89 insertions(+), 6 deletions(-) (limited to 'gcc') diff --git a/gcc/Make-lang.in b/gcc/Make-lang.in index e6d6f2d..ecb0141 100644 --- a/gcc/Make-lang.in +++ b/gcc/Make-lang.in @@ -48,6 +48,7 @@ elna_OBJS = \ elna/elna-tree.o \ elna/elna-builtins.o \ elna/ast.o \ + elna/evaluator.o \ elna/dependency.o \ elna/driver.o \ elna/lexer.o \ diff --git a/gcc/gcc/elna-generic.cc b/gcc/gcc/elna-generic.cc index b849715..0516f5a 100644 --- a/gcc/gcc/elna-generic.cc +++ b/gcc/gcc/elna-generic.cc @@ -16,7 +16,9 @@ along with GCC; see the file COPYING3. If not see . */ #include +#include +#include "elna/boot/evaluator.h" #include "elna/gcc/elna-diagnostic.h" #include "elna/gcc/elna-generic.h" #include "elna/gcc/elna1.h" @@ -35,8 +37,9 @@ along with GCC; see the file COPYING3. If not see namespace elna::gcc { - generic_visitor::generic_visitor(std::shared_ptr symbol_table, boot::symbol_bag bag) - : bag(bag), symbols(symbol_table) + generic_visitor::generic_visitor(std::shared_ptr symbol_table, + boot::symbol_bag bag, const boot::target_info& target) + : bag(bag), symbols(symbol_table), target(target) { } @@ -160,7 +163,7 @@ namespace elna::gcc void generic_visitor::visit(boot::cast_expression *expression) { - tree cast_target = get_inner_alias(expression->type_decoration, this->symbols->scope()); + tree cast_target = get_inner_alias(expression->type_decoration, this->symbols); expression->value().accept(this); tree cast_source = TREE_TYPE(this->current_expression); @@ -696,6 +699,42 @@ namespace elna::gcc } } + static tree constant_to_tree(const boot::constant_value& constant_value) + { + if (std::holds_alternative(constant_value)) + { + return build_int_cst(elna_int_type_node, std::get(constant_value)); + } + else if (std::holds_alternative(constant_value)) + { + return build_int_cst(elna_word_type_node, std::get(constant_value)); + } + + else if (std::holds_alternative(constant_value)) + { + auto real_value = std::get(constant_value); + REAL_VALUE_TYPE real; + HOST_WIDE_INT target_bits[(sizeof(double) + sizeof(HOST_WIDE_INT) - 1) + / sizeof(HOST_WIDE_INT)]; + std::memcpy(target_bits, &real_value, sizeof(real_value)); + real_from_target(&real, target_bits, REAL_MODE_FORMAT(TYPE_MODE(elna_float_type_node))); + return build_real(elna_float_type_node, real); + } + else if (std::holds_alternative(constant_value)) + { + return std::get(constant_value) ? boolean_true_node : boolean_false_node; + } + else if (std::holds_alternative(constant_value)) + { + return build_int_cst(elna_char_type_node, std::get(constant_value)); + } + else if (std::holds_alternative(constant_value)) + { + return elna_pointer_nil_node; + } + return NULL_TREE; + } + void generic_visitor::visit(boot::variable_declaration *declaration) { for (const auto& variable_identifier : declaration->identifiers) @@ -713,7 +752,28 @@ namespace elna::gcc if (declaration->initializer != nullptr) { declaration->initializer->accept(this); - DECL_INITIAL(declaration_tree) = this->current_expression; + tree initializer_tree = this->current_expression; + + std::map evaluated_initializers; + boot::evaluator constant_evaluator(this->bag, this->target, evaluated_initializers); + if (auto constant_value = constant_evaluator.evaluate(*declaration->initializer)) + { + tree folded = constant_to_tree(constant_value.value()); + if (folded != NULL_TREE) + { + initializer_tree = folded; + } + } + // Follow a const variable's DECL_INITIAL when the + // evaluator cannot chain (e.g. y := x with x: const Int). + if (initializer_tree != NULL_TREE + && TREE_CODE(initializer_tree) == VAR_DECL + && TREE_READONLY(initializer_tree) + && DECL_INITIAL(initializer_tree) != NULL_TREE) + { + initializer_tree = DECL_INITIAL(initializer_tree); + } + DECL_INITIAL(declaration_tree) = initializer_tree; } else if (!declaration->is_extern && POINTER_TYPE_P(TREE_TYPE(declaration_tree))) { diff --git a/gcc/gcc/elna1.cc b/gcc/gcc/elna1.cc index 0ccee02..e75277e 100644 --- a/gcc/gcc/elna1.cc +++ b/gcc/gcc/elna1.cc @@ -52,6 +52,27 @@ union GTY ((desc("TREE_CODE (&%h.generic) == IDENTIFIER_NODE"), /* Language hooks. */ +static const elna::boot::target_info& get_host_target() +{ + static const elna::boot::target_info info = []{ + elna::boot::target_info target_info; + + target_info.int_size = TYPE_PRECISION(elna_int_type_node) / BITS_PER_UNIT; + target_info.int_alignment = TYPE_ALIGN_UNIT(elna_int_type_node); + target_info.word_size = TYPE_PRECISION(elna_word_type_node) / BITS_PER_UNIT; + target_info.word_alignment = TYPE_ALIGN_UNIT(elna_word_type_node); + target_info.pointer_size = TYPE_PRECISION(ptr_type_node) / BITS_PER_UNIT; + target_info.pointer_alignment = TYPE_ALIGN_UNIT(ptr_type_node); + target_info.char_size = TYPE_PRECISION(elna_char_type_node) / BITS_PER_UNIT; + 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); + + return target_info; + }(); + return info; +} + static bool elna_langhook_init(void) { build_common_tree_nodes(false); @@ -125,7 +146,7 @@ static elna::boot::dependency elna_parse_file(dependency_state& state, const cha outcome_bag.add_import(cached_import->second); } } - outcome.errors() = analyze_semantics(outcome.tree, outcome_bag); + outcome.errors() = analyze_semantics(outcome.tree, outcome_bag, get_host_target()); } if (outcome.has_errors()) { @@ -148,7 +169,8 @@ static void elna_langhook_parse_file(void) if (!outcome.has_errors()) { linemap_add(line_table, LC_ENTER, 0, in_fnames[i], 1); - elna::gcc::generic_visitor generic_visitor{ state.custom, state.find(in_fnames[i])->second }; + elna::gcc::generic_visitor generic_visitor{ state.custom, + state.find(in_fnames[i])->second, get_host_target() }; outcome.tree->accept(&generic_visitor); linemap_add(line_table, LC_LEAVE, 0, NULL, 0); } -- cgit v1.2.3