aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorEugen Wissner <belka@caraus.de>2026-07-19 02:08:06 +0200
committerEugen Wissner <belka@caraus.de>2026-07-19 02:08:06 +0200
commit2e1e95dc716167853be4a4b6acaaee1688142744 (patch)
tree343a27402a2aa0f1f83bc0ca05ad8803310e4959 /gcc
parent349e84c693c1444606e877f4d8cdc1a39aa91634 (diff)
downloadelna-2e1e95dc716167853be4a4b6acaaee1688142744.tar.gz
Implement initializer evaluator
Diffstat (limited to 'gcc')
-rw-r--r--gcc/Make-lang.in1
-rw-r--r--gcc/gcc/elna-generic.cc68
-rw-r--r--gcc/gcc/elna1.cc26
3 files changed, 89 insertions, 6 deletions
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
<http://www.gnu.org/licenses/>. */
#include <array>
+#include <cstring>
+#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> symbol_table, boot::symbol_bag bag)
- : bag(bag), symbols(symbol_table)
+ generic_visitor::generic_visitor(std::shared_ptr<symbol_table> 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<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_cst(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;
+ 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<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_cst(elna_char_type_node, std::get<unsigned char>(constant_value));
+ }
+ else if (std::holds_alternative<std::nullptr_t>(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<std::string, boot::expression*> 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);
}