diff --git a/gcc/Make-lang.in b/gcc/Make-lang.in
index ae1a410..e8d5369 100644
--- a/gcc/Make-lang.in
+++ b/gcc/Make-lang.in
@@ -39,7 +39,6 @@ gelna$(exeext): $(ELNA_OBJS) $(EXTRA_GCC_OBJS) libcommon-target.a $(LIBDEPS)
elna_OBJS = \
elna/elna1.o \
elna/elna-generic.o \
- elna/elna-convert.o \
elna/elna-diagnostic.o \
elna/elna-tree.o \
elna/elna-builtins.o \
diff --git a/gcc/elna-builtins.cc b/gcc/elna-builtins.cc
index 0f71e1c..a2e6ee0 100644
--- a/gcc/elna-builtins.cc
+++ b/gcc/elna-builtins.cc
@@ -1,3 +1,20 @@
+/* Builtin definitions.
+ Copyright (C) 2025 Free Software Foundation, Inc.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3. If not see
+. */
+
#include "elna/gcc/elna-builtins.h"
#include "elna/gcc/elna1.h"
#include "stor-layout.h"
@@ -18,13 +35,15 @@ namespace gcc
elna_float_type_node = double_type_node;
elna_string_type_node = make_node(RECORD_TYPE);
- tree_chain record_chain;
+ tree string_ptr_type = build_pointer_type_for_mode(elna_char_type_node, VOIDmode, true);
+ tree record_chain = NULL_TREE;
- record_chain.append(build_field(UNKNOWN_LOCATION, elna_string_type_node, "length", elna_word_type_node));
- record_chain.append(build_field(UNKNOWN_LOCATION, elna_string_type_node, "ptr",
- build_pointer_type_for_mode(elna_char_type_node, VOIDmode, true)));
+ record_chain = chainon(record_chain,
+ build_field(UNKNOWN_LOCATION, elna_string_type_node, "length", elna_word_type_node));
+ record_chain = chainon(record_chain,
+ build_field(UNKNOWN_LOCATION, elna_string_type_node, "ptr", string_ptr_type));
- TYPE_FIELDS(elna_string_type_node) = record_chain.head();
+ TYPE_FIELDS(elna_string_type_node) = record_chain;
layout_type(elna_string_type_node);
}
}
diff --git a/gcc/elna-convert.cc b/gcc/elna-convert.cc
deleted file mode 100644
index c21d3cc..0000000
--- a/gcc/elna-convert.cc
+++ /dev/null
@@ -1,31 +0,0 @@
-/* Data type conversion routines.
- Copyright (C) 2025 Free Software Foundation, Inc.
-
-GCC is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 3, or (at your option)
-any later version.
-
-GCC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING3. If not see
-. */
-
-#include "config.h"
-#include "system.h"
-#include "coretypes.h"
-#include "tree.h"
-#include "fold-const.h"
-#include "convert.h"
-
-/* Creates an expression whose value is that of EXPR, converted to type TYPE.
- This function implements all reasonable scalar conversions. */
-
-tree convert(tree /* type */, tree expr)
-{
- return expr;
-}
diff --git a/gcc/elna-generic.cc b/gcc/elna-generic.cc
index f130d25..4739f29 100644
--- a/gcc/elna-generic.cc
+++ b/gcc/elna-generic.cc
@@ -31,6 +31,7 @@ along with GCC; see the file COPYING3. If not see
#include "stor-layout.h"
#include "varasm.h"
#include "fold-const.h"
+#include "langhooks.h"
#include
namespace elna
@@ -69,7 +70,7 @@ namespace gcc
if (return_type == void_type_node)
{
- this->scope.front().append_statement(stmt);
+ append_statement(stmt);
this->current_expression = NULL_TREE;
}
else
@@ -96,11 +97,6 @@ namespace gcc
this->current_expression = build1(CONVERT_EXPR, elna_word_type_node, size_in_bytes(body_type));
}
- bool generic_visitor::is_numeric_type(tree type)
- {
- return is_integral_type(type) || type == elna_float_type_node;
- }
-
void generic_visitor::visit(boot::program *program)
{
for (boot::constant_definition *const constant : program->constants)
@@ -119,11 +115,8 @@ namespace gcc
{
procedure->accept(this);
}
- std::array parameter_types{
- integer_type_node,
- build_pointer_type(build_pointer_type(char_type_node))
- };
- tree declaration_type = build_function_type_array(integer_type_node, 2, parameter_types.data());
+ tree declaration_type = build_function_type_list(integer_type_node, integer_type_node,
+ build_pointer_type(build_pointer_type(char_type_node)), NULL_TREE);
tree fndecl = build_fn_decl("main", declaration_type);
tree resdecl = build_decl(UNKNOWN_LOCATION, RESULT_DECL, NULL_TREE, integer_type_node);
@@ -132,23 +125,21 @@ namespace gcc
push_struct_function(fndecl, false);
DECL_STRUCT_FUNCTION(fndecl)->language = ggc_cleared_alloc();
- DECL_STRUCT_FUNCTION(fndecl)->language->binding_level = ggc_cleared_alloc();
enter_scope();
- tree_chain argument_chain;
- for (std::size_t i = 0; i < 2; ++i)
+ tree parameter_type = TYPE_ARG_TYPES(declaration_type);
+ for (const char *argument_name : std::array{ "count", "parameters" })
{
- std::string argument_name = i == 0 ? "count" : "parameters";
- tree argc_declaration_tree = build_decl(UNKNOWN_LOCATION, PARM_DECL,
- get_identifier(argument_name.c_str()), parameter_types[i]);
- DECL_CONTEXT(argc_declaration_tree) = fndecl;
- DECL_ARG_TYPE(argc_declaration_tree) = parameter_types[i];
+ tree declaration_tree = build_decl(UNKNOWN_LOCATION, PARM_DECL,
+ get_identifier(argument_name), TREE_VALUE(parameter_type));
+ DECL_CONTEXT(declaration_tree) = fndecl;
+ DECL_ARG_TYPE(declaration_tree) = TREE_VALUE(parameter_type);
- argument_chain.append(argc_declaration_tree);
+ this->symbol_map->enter(argument_name, declaration_tree);
+ DECL_ARGUMENTS(fndecl) = chainon(DECL_ARGUMENTS(fndecl), declaration_tree);
+ parameter_type = TREE_CHAIN(parameter_type);
}
- DECL_ARGUMENTS(fndecl) = argument_chain.head();
-
for (boot::statement *const body_statement : program->body)
{
body_statement->accept(this);
@@ -156,12 +147,12 @@ namespace gcc
tree set_result = build2(INIT_EXPR, void_type_node, DECL_RESULT(fndecl),
build_int_cst_type(integer_type_node, 0));
tree return_stmt = build1(RETURN_EXPR, void_type_node, set_result);
- this->scope.front().append_statement(return_stmt);
- tree_symbol_mapping mapping = leave_scope();
+ append_statement(return_stmt);
+ tree mapping = leave_scope();
- BLOCK_SUPERCONTEXT(mapping.block()) = fndecl;
- DECL_INITIAL(fndecl) = mapping.block();
- DECL_SAVED_TREE(fndecl) = mapping.bind_expression();
+ BLOCK_SUPERCONTEXT(BIND_EXPR_BLOCK(mapping)) = fndecl;
+ DECL_INITIAL(fndecl) = BIND_EXPR_BLOCK(mapping);
+ DECL_SAVED_TREE(fndecl) = mapping;
DECL_EXTERNAL(fndecl) = 0;
DECL_PRESERVE_P(fndecl) = 1;
@@ -189,14 +180,16 @@ namespace gcc
if (definition->body() != nullptr)
{
- current_function_decl = fndecl;
tree resdecl = build_decl(UNKNOWN_LOCATION, RESULT_DECL, NULL_TREE, return_type);
DECL_CONTEXT(resdecl) = fndecl;
DECL_RESULT(fndecl) = resdecl;
+ push_struct_function(fndecl, false);
+ DECL_STRUCT_FUNCTION(fndecl)->language = ggc_cleared_alloc();
+
enter_scope();
}
- tree_chain argument_chain;
+ tree argument_chain = NULL_TREE;
for (std::size_t i = 0; i < definition->parameters.size(); ++i)
{
auto parameter = definition->parameters.at(i);
@@ -210,24 +203,24 @@ namespace gcc
{
this->symbol_map->enter(parameter->identifier, declaration_tree);
}
- argument_chain.append(declaration_tree);
+ argument_chain = chainon(argument_chain, declaration_tree);
}
- DECL_ARGUMENTS(fndecl) = argument_chain.head();
+ DECL_ARGUMENTS(fndecl) = argument_chain;
TREE_PUBLIC(fndecl) = definition->exported;
if (definition->body() != nullptr)
{
definition->body()->accept(this);
- tree_symbol_mapping mapping = leave_scope();
+ tree mapping = leave_scope();
- BLOCK_SUPERCONTEXT(mapping.block()) = fndecl;
- DECL_INITIAL(fndecl) = mapping.block();
- DECL_SAVED_TREE(fndecl) = mapping.bind_expression();
+ BLOCK_SUPERCONTEXT(BIND_EXPR_BLOCK(mapping)) = fndecl;
+ DECL_INITIAL(fndecl) = BIND_EXPR_BLOCK(mapping);
+ DECL_SAVED_TREE(fndecl) = mapping;
DECL_EXTERNAL(fndecl) = 0;
DECL_PRESERVE_P(fndecl) = 1;
- current_function_decl = NULL_TREE;
+ pop_cfun();
gimplify_function_tree(fndecl);
cgraph_node::finalize_function(fndecl, true);
}
@@ -239,30 +232,35 @@ namespace gcc
void generic_visitor::enter_scope()
{
- scope.emplace_front();
this->symbol_map = std::make_shared>(this->symbol_map);
+
+ // Chain the binding levels.
+ struct binding_level *new_level = ggc_cleared_alloc();
+ new_level->level_chain = f_binding_level;
+ new_level->statement_list = alloc_stmt_list();
+ f_binding_level = new_level;
}
- tree_symbol_mapping generic_visitor::leave_scope()
+ tree generic_visitor::leave_scope()
{
- tree new_block = build_block(this->scope.front().variables.head(),
- this->scope.front().blocks.head(), NULL_TREE, NULL_TREE);
+ // Variables are only defined in the top function scope.
+ tree variables = f_binding_level->level_chain == nullptr ? f_names : NULL_TREE;
+ tree new_block = build_block(variables, f_binding_level->blocks, NULL_TREE, NULL_TREE);
- for (tree it = this->scope.front().blocks.head(); it != NULL_TREE; it = BLOCK_CHAIN(it))
+ for (tree it = f_binding_level->blocks; it != NULL_TREE; it = BLOCK_CHAIN(it))
{
BLOCK_SUPERCONTEXT(it) = new_block;
}
- tree bind_expr = build3(BIND_EXPR, void_type_node, this->scope.front().variables.head(),
- this->scope.front().chain_defer(), new_block);
+ tree bind_expr = build3(BIND_EXPR, void_type_node, variables, chain_defer(), new_block);
this->symbol_map = this->symbol_map->scope();
- scope.pop_front();
+ f_binding_level = f_binding_level->level_chain;
- if (!scope.empty())
+ if (f_binding_level != nullptr)
{
- scope.front().blocks.append(new_block);
+ f_binding_level->blocks = chainon(f_binding_level->blocks, new_block);
}
- return tree_symbol_mapping{ bind_expr, new_block };
+ return bind_expr;
}
tree generic_visitor::lookup(const std::string& name)
@@ -295,16 +293,6 @@ namespace gcc
{
return elna_string_type_node;
}
- if (current_function_decl != NULL_TREE)
- {
- for (tree decl = DECL_ARGUMENTS(current_function_decl); decl; decl = DECL_CHAIN(decl))
- {
- if (name == IDENTIFIER_POINTER(DECL_NAME(decl)))
- {
- return decl;
- }
- }
- }
return this->symbol_map->lookup(name);
}
@@ -392,11 +380,52 @@ namespace gcc
expression, operator_code, left, right, elna_bool_type_node);
}
- tree generic_visitor::build_equality_operation(boot::binary_expression *expression,
- tree_code operator_code, tree left, tree right)
+ tree generic_visitor::build_equality_operation(boot::binary_expression *expression, tree left, tree right)
{
- return build_binary_operation(true, expression,
- operator_code, left, right, elna_bool_type_node);
+ location_t expression_location = get_location(&expression->position());
+ tree_code equality_code, combination_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 (TREE_TYPE(left) == elna_string_type_node)
+ {
+ tree length_field = TYPE_FIELDS(elna_string_type_node);
+ tree ptr_field = TREE_CHAIN(length_field);
+
+ tree lhs_length = build3(COMPONENT_REF, TREE_TYPE(length_field), left, length_field, NULL_TREE);
+ tree lhs_ptr = build3(COMPONENT_REF, TREE_TYPE(ptr_field), left, ptr_field, NULL_TREE);
+
+ tree rhs_length = build3(COMPONENT_REF, TREE_TYPE(length_field), right, length_field, NULL_TREE);
+ tree rhs_ptr = build3(COMPONENT_REF, TREE_TYPE(ptr_field), right, ptr_field, NULL_TREE);
+
+ tree length_equality = build2(equality_code, elna_bool_type_node, lhs_length, rhs_length);
+ tree *memcmp = elna_global_decls->get("__builtin_memcmp");
+ gcc_assert(memcmp != nullptr);
+
+ tree fndecl_type = build_function_type(integer_type_node, TYPE_ARG_TYPES(*memcmp));
+ tree memcmp_addr = build1(ADDR_EXPR, build_pointer_type(fndecl_type), *memcmp);
+ tree memcmp_call = build_call_nary(integer_type_node, memcmp_addr, 3, lhs_ptr, rhs_ptr, lhs_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
+ {
+ return build2_loc(expression_location, equality_code, elna_bool_type_node, left, right);
+ }
}
void generic_visitor::visit(boot::binary_expression *expression)
@@ -473,10 +502,10 @@ namespace gcc
this->current_expression = build_logic_operation(expression, TRUTH_ORIF_EXPR, left, right);
break;
case boot::binary_operator::equals:
- this->current_expression = build_equality_operation(expression, EQ_EXPR, left, right);
+ this->current_expression = build_equality_operation(expression, left, right);
break;
case boot::binary_operator::not_equals:
- this->current_expression = build_equality_operation(expression, NE_EXPR, left, right);
+ this->current_expression = build_equality_operation(expression, left, right);
break;
}
}
@@ -520,11 +549,11 @@ namespace gcc
TREE_READONLY(definition_tree) = 1;
TREE_PUBLIC(definition_tree) = definition->exported;
- if (!scope.empty())
+ if (!lang_hooks.decls.global_bindings_p())
{
auto declaration_statement = build1_loc(definition_location, DECL_EXPR,
void_type_node, definition_tree);
- this->scope.front().append_statement(declaration_statement);
+ append_statement(declaration_statement);
}
}
else
@@ -599,7 +628,6 @@ namespace gcc
{
std::set field_names;
tree record_type_node = make_node(RECORD_TYPE);
- tree_chain record_chain;
for (auto& field : record_type->fields)
{
@@ -617,9 +645,8 @@ namespace gcc
}
tree field_declaration = build_field(get_location(&field.second->position()),
record_type_node, field.first, field_type);
- record_chain.append(field_declaration);
+ TYPE_FIELDS(record_type_node) = chainon(TYPE_FIELDS(record_type_node), field_declaration);
}
- TYPE_FIELDS(record_type_node) = record_chain.head();
layout_type(record_type_node);
return record_type_node;
@@ -628,7 +655,6 @@ namespace gcc
{
std::set field_names;
tree union_type_node = make_node(UNION_TYPE);
- tree_chain union_chain;
for (auto& field : union_type->fields)
{
@@ -646,9 +672,8 @@ namespace gcc
}
tree field_declaration = build_field(get_location(&field.second->position()),
union_type_node, field.first, field_type);
- union_chain.append(field_declaration);
+ TYPE_FIELDS(union_type_node) = chainon(TYPE_FIELDS(union_type_node), field_declaration);
}
- TYPE_FIELDS(union_type_node) = union_chain.head();
layout_type(union_type_node);
return union_type_node;
@@ -671,7 +696,7 @@ namespace gcc
error_at(declaration_location, "variable '%s' already declared in this scope",
declaration->identifier.c_str());
}
- else if (current_function_decl == NULL_TREE)
+ else if (lang_hooks.decls.global_bindings_p())
{
TREE_STATIC(declaration_tree) = 1;
varpool_node::get_create(declaration_tree);
@@ -680,11 +705,11 @@ namespace gcc
else
{
DECL_CONTEXT(declaration_tree) = current_function_decl;
- this->scope.front().variables.append(declaration_tree);
+ f_names = chainon(f_names, declaration_tree);
auto declaration_statement = build1_loc(declaration_location, DECL_EXPR,
void_type_node, declaration_tree);
- this->scope.front().append_statement(declaration_statement);
+ append_statement(declaration_statement);
}
}
@@ -779,7 +804,7 @@ namespace gcc
tree assignment = build2_loc(statement_location, MODIFY_EXPR,
void_type_node, lvalue, this->current_expression);
- this->scope.front().append_statement(assignment);
+ append_statement(assignment);
this->current_expression = NULL_TREE;
}
else
@@ -810,11 +835,11 @@ namespace gcc
{
body_statement->accept(this);
}
- tree_symbol_mapping mapping = leave_scope();
- scope.front().append_statement(mapping.bind_expression());
+ tree mapping = leave_scope();
+ append_statement(mapping);
}
tree endif_label_expr = build1(LABEL_EXPR, void_type_node, endif_label_decl);
- this->scope.front().append_statement(endif_label_expr);
+ append_statement(endif_label_expr);
this->current_expression = NULL_TREE;
}
@@ -837,22 +862,22 @@ namespace gcc
tree goto_else = build1(GOTO_EXPR, void_type_node, else_label_decl);
auto cond_expr = build3(COND_EXPR, void_type_node, this->current_expression, goto_then, goto_else);
- this->scope.front().append_statement(cond_expr);
+ append_statement(cond_expr);
tree then_label_expr = build1(LABEL_EXPR, void_type_node, then_label_decl);
- this->scope.front().append_statement(then_label_expr);
+ append_statement(then_label_expr);
enter_scope();
for (const auto body_statement : branch.statements)
{
body_statement->accept(this);
}
- tree_symbol_mapping mapping = leave_scope();
- this->scope.front().append_statement(mapping.bind_expression());
- this->scope.front().append_statement(goto_endif);
+ tree mapping = leave_scope();
+ append_statement(mapping);
+ append_statement(goto_endif);
tree else_label_expr = build1(LABEL_EXPR, void_type_node, else_label_decl);
- this->scope.front().append_statement(else_label_expr);
+ append_statement(else_label_expr);
}
tree generic_visitor::build_label_decl(const char *name, location_t loc)
@@ -885,7 +910,7 @@ namespace gcc
auto prerequisite_label_decl = build_label_decl("while_check", prerequisite_location);
auto prerequisite_label_expr = build1_loc(prerequisite_location, LABEL_EXPR,
void_type_node, prerequisite_label_decl);
- this->scope.front().append_statement(prerequisite_label_expr);
+ append_statement(prerequisite_label_expr);
auto body_label_decl = build_label_decl("while_body", body_location);
auto end_label_decl = build_label_decl("end_while", UNKNOWN_LOCATION);
@@ -897,24 +922,24 @@ namespace gcc
auto cond_expr = build3_loc(prerequisite_location, COND_EXPR,
void_type_node, this->current_expression, goto_body, goto_end);
- this->scope.front().append_statement(cond_expr);
+ append_statement(cond_expr);
auto body_label_expr = build1_loc(body_location, LABEL_EXPR,
void_type_node, body_label_decl);
- this->scope.front().append_statement(body_label_expr);
+ append_statement(body_label_expr);
for (const auto body_statement : statement->body().statements)
{
body_statement->accept(this);
}
- tree_symbol_mapping mapping = leave_scope();
- this->scope.front().append_statement(mapping.bind_expression());
+ tree mapping = leave_scope();
+ append_statement(mapping);
auto goto_check = build1(GOTO_EXPR, void_type_node, prerequisite_label_decl);
- this->scope.front().append_statement(goto_check);
+ append_statement(goto_check);
auto endif_label_expr = build1(LABEL_EXPR, void_type_node, end_label_decl);
- this->scope.front().append_statement(endif_label_expr);
+ append_statement(endif_label_expr);
this->current_expression = NULL_TREE;
}
@@ -922,7 +947,7 @@ namespace gcc
void generic_visitor::visit(boot::call_statement *statement)
{
statement->body().accept(this);
- this->scope.front().append_statement(this->current_expression);
+ append_statement(this->current_expression);
this->current_expression = NULL_TREE;
}
@@ -939,7 +964,7 @@ namespace gcc
tree set_result = build2(INIT_EXPR, void_type_node, DECL_RESULT(current_function_decl),
this->current_expression);
tree return_stmt = build1(RETURN_EXPR, void_type_node, set_result);
- this->scope.front().append_statement(return_stmt);
+ append_statement(return_stmt);
}
void generic_visitor::visit(boot::defer_statement *statement)
@@ -949,8 +974,7 @@ namespace gcc
{
body_statement->accept(this);
}
- tree_symbol_mapping mapping = leave_scope();
- scope.front().defer(mapping.bind_expression());
+ defer(leave_scope());
}
}
}
diff --git a/gcc/elna-tree.cc b/gcc/elna-tree.cc
index 41c6458..300a9cf 100644
--- a/gcc/elna-tree.cc
+++ b/gcc/elna-tree.cc
@@ -19,6 +19,7 @@ along with GCC; see the file COPYING3. If not see
#include "elna/gcc/elna-diagnostic.h"
#include "elna/gcc/elna1.h"
+#include "function.h"
#include "stor-layout.h"
#include "fold-const.h"
#include "diagnostic-core.h"
@@ -39,6 +40,11 @@ namespace gcc
return TREE_CODE(type) == INTEGER_TYPE;
}
+ bool is_numeric_type(tree type)
+ {
+ return is_integral_type(type) || type == elna_float_type_node;
+ }
+
bool are_compatible_pointers(tree lhs, tree rhs)
{
tree lhs_type = TREE_TYPE(lhs);
@@ -48,90 +54,42 @@ namespace gcc
|| (is_pointer_type(lhs_type) && lhs_type == rhs_type);
}
- tree tree_chain_base::head()
+ void append_statement(tree statement_tree)
{
- return first;
- }
-
- void tree_chain_base::append(tree t)
- {
- gcc_assert(t != NULL_TREE);
-
- if (this->first == NULL_TREE)
+ if (!vec_safe_is_empty(f_binding_level->defers))
{
- this->first = this->last = t;
+ append_to_statement_list(statement_tree, &f_binding_level->defers->begin()->try_statements);
}
else
{
- chain(t);
- this->last = t;
+ append_to_statement_list(statement_tree, &f_binding_level->statement_list);
}
}
- void tree_chain::chain(tree t)
+ void defer(tree statement_tree)
{
- TREE_CHAIN(this->last) = t;
+ defer_scope new_defer{ statement_tree, alloc_stmt_list() };
+ vec_safe_insert(f_binding_level->defers, 0, new_defer);
}
- void block_chain::chain(tree t)
+ tree chain_defer()
{
- BLOCK_CHAIN(this->last) = t;
- }
-
- tree_symbol_mapping::tree_symbol_mapping(tree bind_expression, tree block)
- : m_bind_expression(bind_expression), m_block(block)
- {
- }
-
- tree tree_symbol_mapping::bind_expression()
- {
- return m_bind_expression;
- }
-
- tree tree_symbol_mapping::block()
- {
- return m_block;
- }
-
- block_scope::block_scope()
- : m_statement_list(alloc_stmt_list())
- {
- }
-
- void block_scope::append_statement(tree statement_tree)
- {
- if (!defers.empty())
+ if (vec_safe_is_empty(f_binding_level->defers))
{
- append_to_statement_list(statement_tree, &this->defers.front().second);
+ return f_binding_level->statement_list;
}
- else
- {
- append_to_statement_list(statement_tree, &this->m_statement_list);
- }
- }
+ defer_scope *defer_iterator = f_binding_level->defers->begin();
+ tree defer_tree = build2(TRY_FINALLY_EXPR, void_type_node,
+ defer_iterator->try_statements, defer_iterator->defer_block);
+ int i;
- void block_scope::defer(tree statement_tree)
- {
- defers.push_front({ statement_tree, alloc_stmt_list() });
- }
-
- tree block_scope::chain_defer()
- {
- if (this->defers.empty())
+ FOR_EACH_VEC_ELT_FROM(*f_binding_level->defers, i, defer_iterator, 1)
{
- return m_statement_list;
+ append_to_statement_list(defer_tree, &defer_iterator->try_statements);
+ defer_tree = build2(TRY_FINALLY_EXPR, void_type_node,
+ defer_iterator->try_statements, defer_iterator->defer_block);
}
- std::forward_list>::iterator defer_iterator =
- this->defers.begin();
- tree defer_tree = build2(TRY_FINALLY_EXPR, void_type_node, defer_iterator->second, defer_iterator->first);
-
- ++defer_iterator;
- for (; defer_iterator != this->defers.end(); ++defer_iterator)
- {
- append_to_statement_list(defer_tree, &defer_iterator->second);
- defer_tree = build2(TRY_FINALLY_EXPR, void_type_node, defer_iterator->second, defer_iterator->first);
- }
- return build2(COMPOUND_EXPR, TREE_TYPE(defer_tree), m_statement_list, defer_tree);
+ return build2(COMPOUND_EXPR, TREE_TYPE(defer_tree), f_binding_level->statement_list, defer_tree);
}
tree build_field(location_t location, tree record_type, const std::string name, tree type)
diff --git a/gcc/elna1.cc b/gcc/elna1.cc
index 2ac2a69..5ea5ab4 100644
--- a/gcc/elna1.cc
+++ b/gcc/elna1.cc
@@ -1,5 +1,5 @@
/* Language-dependent hooks for Elna.
- Copyright (C) 2006-2024 Free Software Foundation, Inc.
+ Copyright (C) 2025 Free Software Foundation, Inc.
GCC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -37,6 +37,7 @@ along with GCC; see the file COPYING3. If not see
#include "parser.hh"
tree elna_global_trees[ELNA_TI_MAX];
+hash_map *elna_global_decls = nullptr;
/* The resulting tree type. */
@@ -53,7 +54,9 @@ union GTY ((desc ("TREE_CODE (&%h.generic) == IDENTIFIER_NODE"),
static bool elna_langhook_init(void)
{
build_common_tree_nodes(false);
+
elna::gcc::init_ttree();
+ elna_global_decls = hash_map::create_ggc(default_hash_map_size);
build_common_builtin_nodes();
@@ -172,30 +175,32 @@ static bool global_bindings_p(void)
return current_function_decl == NULL_TREE;
}
-tree getdecls(void)
+static tree pushdecl(tree decl)
{
- if (current_function_decl != NULL_TREE)
- {
- return f_binding_level->names;
- }
- return NULL_TREE;
-}
-
-tree pushdecl(tree decl)
-{
- if (current_function_decl != NULL_TREE)
- {
- TREE_CHAIN(decl) = f_binding_level->names;
- f_binding_level->names = decl;
- }
return decl;
}
static tree elna_langhook_builtin_function(tree decl)
{
+ elna_global_decls->put(IDENTIFIER_POINTER(DECL_NAME(decl)), decl);
return decl;
}
+/* Creates an expression whose value is that of EXPR, converted to type TYPE.
+ This function implements all reasonable scalar conversions. */
+tree convert(tree type, tree expr)
+{
+ if (error_operand_p(type) || error_operand_p(expr))
+ {
+ return error_mark_node;
+ }
+ if (TREE_TYPE(expr) == type)
+ {
+ return expr;
+ }
+ return error_mark_node;
+}
+
#undef LANG_HOOKS_NAME
#define LANG_HOOKS_NAME "GNU Elna"
@@ -208,6 +213,9 @@ static tree elna_langhook_builtin_function(tree decl)
#undef LANG_HOOKS_TYPE_FOR_MODE
#define LANG_HOOKS_TYPE_FOR_MODE elna_langhook_type_for_mode
+#undef LANG_HOOKS_GETDECLS
+#define LANG_HOOKS_GETDECLS hook_tree_void_null
+
#undef LANG_HOOKS_BUILTIN_FUNCTION
#define LANG_HOOKS_BUILTIN_FUNCTION elna_langhook_builtin_function
diff --git a/include/elna/gcc/elna-builtins.h b/include/elna/gcc/elna-builtins.h
index 83e3cfe..a7d6b9f 100644
--- a/include/elna/gcc/elna-builtins.h
+++ b/include/elna/gcc/elna-builtins.h
@@ -1,3 +1,20 @@
+/* Builtin definitions.
+ Copyright (C) 2025 Free Software Foundation, Inc.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3. If not see
+. */
+
#include "config.h"
#include "system.h"
#include "coretypes.h"
diff --git a/include/elna/gcc/elna-generic.h b/include/elna/gcc/elna-generic.h
index fe74cab..6bd2b4c 100644
--- a/include/elna/gcc/elna-generic.h
+++ b/include/elna/gcc/elna-generic.h
@@ -36,7 +36,6 @@ namespace gcc
{
class generic_visitor final : public boot::empty_visitor
{
- std::forward_list scope;
tree current_expression{ NULL_TREE };
std::shared_ptr> symbol_map;
@@ -44,22 +43,19 @@ namespace gcc
tree build_type(boot::type_expression& type);
void enter_scope();
- tree_symbol_mapping leave_scope();
+ tree leave_scope();
tree lookup(const std::string& name);
void make_if_branch(boot::conditional_statements& branch, tree goto_endif);
- bool is_numeric_type(tree type);
-
tree build_arithmetic_operation(boot::binary_expression *expression,
tree_code operator_code, tree left, tree right);
tree build_comparison_operation(boot::binary_expression *expression,
tree_code operator_code, tree left, tree right);
tree build_logic_operation(boot::binary_expression *expression,
tree_code operator_code, tree left, tree right);
- tree build_equality_operation(boot::binary_expression *expression,
- tree_code operator_code, tree left, tree right);
+ tree build_equality_operation(boot::binary_expression *expression, tree left, tree right);
public:
generic_visitor(std::shared_ptr> symbol_table);
diff --git a/include/elna/gcc/elna-tree.h b/include/elna/gcc/elna-tree.h
index cb09caf..8586355 100644
--- a/include/elna/gcc/elna-tree.h
+++ b/include/elna/gcc/elna-tree.h
@@ -35,6 +35,7 @@ namespace gcc
{
bool is_pointer_type(tree type);
bool is_integral_type(tree type);
+ bool is_numeric_type(tree type);
/**
* \param lhs Left hand value.
@@ -43,59 +44,9 @@ namespace gcc
*/
bool are_compatible_pointers(tree lhs, tree rhs);
- class tree_chain_base
- {
- protected:
- tree first{};
- tree last{};
-
- public:
- tree head();
- void append(tree t);
-
- protected:
- virtual void chain(tree t) = 0;
- };
-
- class tree_chain final : public tree_chain_base
- {
- protected:
- void chain(tree t) override;
- };
-
- class block_chain final : public tree_chain_base
- {
- protected:
- void chain(tree t) override;
- };
-
- class tree_symbol_mapping final
- {
- tree m_bind_expression;
- tree m_block;
-
- public:
- tree_symbol_mapping(tree bind_expression, tree block);
-
- tree bind_expression();
- tree block();
- };
-
- class block_scope
- {
- tree m_statement_list{ NULL_TREE };
- std::forward_list> defers;
-
- public:
- tree_chain variables;
- block_chain blocks;
-
- block_scope();
-
- void append_statement(tree statement_tree);
- void defer(tree statement_tree);
- tree chain_defer();
- };
+ void append_statement(tree statement_tree);
+ void defer(tree statement_tree);
+ tree chain_defer();
tree do_pointer_arithmetic(boot::binary_operator binary_operator, tree left, tree right);
tree build_binary_operation(bool condition, boot::binary_expression *expression,
diff --git a/include/elna/gcc/elna1.h b/include/elna/gcc/elna1.h
index b43dbac..93d0043 100644
--- a/include/elna/gcc/elna1.h
+++ b/include/elna/gcc/elna1.h
@@ -1,3 +1,20 @@
+/* Language-dependent hooks for Elna.
+ Copyright (C) 2025 Free Software Foundation, Inc.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3. If not see
+. */
+
enum elna_tree_index
{
ELNA_TI_INT_TYPE,
@@ -11,6 +28,7 @@ enum elna_tree_index
};
extern GTY(()) tree elna_global_trees[ELNA_TI_MAX];
+extern GTY(()) hash_map *elna_global_decls;
#define elna_int_type_node elna_global_trees[ELNA_TI_INT_TYPE]
#define elna_word_type_node elna_global_trees[ELNA_TI_WORD_TYPE]
@@ -30,18 +48,35 @@ struct GTY (()) lang_decl
{
};
-struct GTY (()) binding_level
+struct GTY (()) defer_scope
{
- // A chain of all declarations in this binding level.
- tree names;
+ tree defer_block;
+ tree try_statements;
+};
+
+struct GTY ((chain_next ("%h.level_chain"))) binding_level
+{
+ // A block chain is needed to call defer statements beloning to each block.
+ tree blocks;
+
+ // Parent level.
+ struct binding_level *level_chain;
+
+ // Statements before the first defer has been seen.
+ tree statement_list;
+
+ // Defer statement coupled with statements following it.
+ vec *defers;
};
struct GTY (()) language_function
{
+ // Local variables and constants.
+ tree names;
+
+ // Lexical scope.
struct binding_level *binding_level;
};
#define f_binding_level DECL_STRUCT_FUNCTION(current_function_decl)->language->binding_level
-
-extern tree pushdecl(tree);
-extern tree getdecls(void);
+#define f_names DECL_STRUCT_FUNCTION(current_function_decl)->language->names
diff --git a/source.elna b/source.elna
index 4d41524..b069d86 100644
--- a/source.elna
+++ b/source.elna
@@ -174,14 +174,6 @@ begin
return c = ' ' or c = '\n' or c = '\t'
end
-proc string_equals(this: String, that: String): Bool;
-begin
- if this.length <> that.length then
- return false
- end;
- return strncmp(this.ptr, that.ptr, this.length) = 0
-end
-
proc open_substring(string: String, start: Word): String;
begin
string.ptr := string.ptr + start;
@@ -560,67 +552,67 @@ proc categorize_identifier(token_content: String): Token;
var
current_token: Token;
begin
- if string_equals("if", token_content) then
+ if "if" = token_content then
current_token.kind := TOKEN_IF
- elsif string_equals("then", token_content) then
+ elsif "then" = token_content then
current_token.kind := TOKEN_THEN
- elsif string_equals("else", token_content) then
+ elsif "else" = token_content then
current_token.kind := TOKEN_ELSE
- elsif string_equals("elsif", token_content) then
+ elsif "elsif" = token_content then
current_token.kind := TOKEN_ELSIF
- elsif string_equals("while", token_content) then
+ elsif "while" = token_content then
current_token.kind := TOKEN_WHILE
- elsif string_equals("do", token_content) then
+ elsif "do" = token_content then
current_token.kind := TOKEN_DO
- elsif string_equals("proc", token_content) then
+ elsif "proc" = token_content then
current_token.kind := TOKEN_PROC
- elsif string_equals("begin", token_content) then
+ elsif "begin" = token_content then
current_token.kind := TOKEN_BEGIN
- elsif string_equals("end", token_content) then
+ elsif "end" = token_content then
current_token.kind := TOKEN_END
- elsif string_equals("extern", token_content) then
+ elsif "extern" = token_content then
current_token.kind := TOKEN_EXTERN
- elsif string_equals("const", token_content) then
+ elsif "const" = token_content then
current_token.kind := TOKEN_CONST
- elsif string_equals("var", token_content) then
+ elsif "var" = token_content then
current_token.kind := TOKEN_VAR
- elsif string_equals("array", token_content) then
+ elsif "array" = token_content then
current_token.kind := TOKEN_ARRAY
- elsif string_equals("of", token_content) then
+ elsif "of" = token_content then
current_token.kind := TOKEN_OF
- elsif string_equals("type", token_content) then
+ elsif "type" = token_content then
current_token.kind := TOKEN_TYPE
- elsif string_equals("record", token_content) then
+ elsif "record" = token_content then
current_token.kind := TOKEN_RECORD
- elsif string_equals("union", token_content) then
+ elsif "union" = token_content then
current_token.kind := TOKEN_UNION
- elsif string_equals("pointer", token_content) then
+ elsif "pointer" = token_content then
current_token.kind := TOKEN_POINTER
- elsif string_equals("to", token_content) then
+ elsif "to" = token_content then
current_token.kind := TOKEN_TO
- elsif string_equals("true", token_content) then
+ elsif "true" = token_content then
current_token.kind := TOKEN_BOOLEAN;
current_token.value.boolean_value := true
- elsif string_equals("false", token_content) then
+ elsif "false" = token_content then
current_token.kind := TOKEN_BOOLEAN;
current_token.value.boolean_value := false
- elsif string_equals("nil", token_content) then
+ elsif "nil" = token_content then
current_token.kind := TOKEN_NIL
- elsif string_equals("and", token_content) then
+ elsif "and" = token_content then
current_token.kind := TOKEN_AND
- elsif string_equals("or", token_content) then
+ elsif "or" = token_content then
current_token.kind := TOKEN_OR
- elsif string_equals("not", token_content) then
+ elsif "not" = token_content then
current_token.kind := TOKEN_NOT
- elsif string_equals("return", token_content) then
+ elsif "return" = token_content then
current_token.kind := TOKEN_RETURN
- elsif string_equals("cast", token_content) then
+ elsif "cast" = token_content then
current_token.kind := TOKEN_CAST
- elsif string_equals("as", token_content) then
+ elsif "as" = token_content then
current_token.kind := TOKEN_AS
- elsif string_equals("sizeof", token_content) then
+ elsif "sizeof" = token_content then
current_token.kind := TOKEN_SIZEOF
- elsif string_equals("defer", token_content) then
+ elsif "defer" = token_content then
current_token.kind := TOKEN_DEFER
else
current_token.kind := TOKEN_IDENTIFIER;
@@ -650,9 +642,7 @@ begin
if is_alpha(first_char) or first_char = '_' then
lex_identifier(@source_code, @token_content);
- current_token^ := categorize_identifier(token_content);
-
- source_code := advance_source(source_code, 1u)
+ current_token^ := categorize_identifier(token_content)
elsif is_digit(first_char) then
token_end := nil;
current_token^.value.int_value := strtol(source_code.text.ptr, @token_end, 10);