diff --git a/Rakefile b/Rakefile
index 4ea6030..46703ca 100644
--- a/Rakefile
+++ b/Rakefile
@@ -21,6 +21,8 @@ def run(exe)
ENV.fetch('QEMU', '').split << exe
end
+directory 'build'
+
task default: :boot
desc 'Final stage'
diff --git a/config-lang.in b/config-lang.in
deleted file mode 100644
index 1bc1697..0000000
--- a/config-lang.in
+++ /dev/null
@@ -1,21 +0,0 @@
-# Top level configure fragment for gcc Elna frontend.
-# 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
-# .
-
-language="elna"
-gcc_subdir="elna/gcc"
-
-. ${srcdir}/elna/gcc/config-lang.in
diff --git a/gcc/Make-lang.in b/gcc/Make-lang.in
deleted file mode 100644
index e25fc6d..0000000
--- a/gcc/Make-lang.in
+++ /dev/null
@@ -1,174 +0,0 @@
-# Top level -*- makefile -*- fragment for the Elna frontend.
-# 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
-# .
-
-ELNA_INSTALL_NAME := $(shell echo gelna|sed '$(program_transform_name)')
-ELNA_TARGET_INSTALL_NAME := $(target_noncanonical)-$(shell echo gelna|sed '$(program_transform_name)')
-
-elna: elna1$(exeext)
-
-.PHONY: elna
-
-# Driver
-
-ELNA_OBJS = \
- $(GCC_OBJS) \
- elna/elna-spec.o \
- $(END)
-
-gelna$(exeext): $(ELNA_OBJS) $(EXTRA_GCC_OBJS) libcommon-target.a $(LIBDEPS)
- +$(LINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ \
- $(ELNA_OBJS) $(EXTRA_GCC_OBJS) libcommon-target.a \
- $(EXTRA_GCC_LIBS) $(LIBS)
-
-# Create a version of the gelna driver which calls the cross-compiler.
-gelna-cross$(exeext): gelna$(exeext)
- -rm -f gelna-cross$(exeext)
- cp gelna$(exeext) gelna-cross$(exeext)
-
-# The compiler proper
-
-elna_OBJS = \
- elna/elna1.o \
- elna/elna-generic.o \
- elna/elna-diagnostic.o \
- elna/elna-tree.o \
- elna/elna-builtins.o \
- elna/ast.o \
- elna/dependency.o \
- elna/driver.o \
- elna/lexer.o \
- elna/parser.o \
- elna/semantic.o \
- elna/symbol.o \
- elna/result.o \
- $(END)
-
-elna1$(exeext): attribs.o $(elna_OBJS) $(BACKEND) $(LIBDEPS)
- +$(LLINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ \
- attribs.o $(elna_OBJS) $(BACKEND) $(LIBS) $(BACKENDLIBS)
-
-elna.all.cross: gelna-cross$(exeext)
-
-elna.start.encap: gelna$(exeext)
-elna.rest.encap:
-
-# No elna-specific selftests.
-selftest-elna:
-
-ELNA_TEXI_FILES = \
- elna/gcc/gelna.texi \
- $(srcdir)/doc/include/fdl.texi \
- $(srcdir)/doc/include/gpl_v3.texi \
- $(srcdir)/doc/include/funding.texi \
- $(srcdir)/doc/include/gcc-common.texi \
- gcc-vers.texi
-
-elna.install-common: installdirs
- -rm -f $(DESTDIR)$(bindir)/$(ELNA_INSTALL_NAME)$(exeext)
- $(INSTALL_PROGRAM) gelna$(exeext) $(DESTDIR)$(bindir)/$(ELNA_INSTALL_NAME)$(exeext)
- -if test -f elna1$(exeext); then \
- if test -f gelna-cross$(exeext); then \
- :; \
- else \
- rm -f $(DESTDIR)$(bindir)/$(ELNA_TARGET_INSTALL_NAME)$(exeext); \
- ( cd $(DESTDIR)$(bindir) && \
- $(LN) $(ELNA_INSTALL_NAME)$(exeext) $(ELNA_TARGET_INSTALL_NAME)$(exeext) ); \
- fi; \
- fi
-
-$(build_htmldir)/gelna/index.html: $(ELNA_TEXI_FILES)
- $(mkinstalldirs) $(@D)
- rm -f $(@D)/*
- $(TEXI2HTML) -I $(gcc_docdir)/include -I $(srcdir)/elna -o $(@D) $<
-
-# Required goals, they still do nothing
-elna.install-man:
-elna.install-info:
-elna.install-pdf:
-elna.install-plugin:
-
-elna.install-html: $(build_htmldir)/gelna
- @$(NORMAL_INSTALL)
- test -z "$(htmldir)" || $(mkinstalldirs) "$(DESTDIR)$(htmldir)"
- @for p in $(build_htmldir)/gelna; do \
- if test -f "$$p" || test -d "$$p"; then d=""; else d="$(srcdir)/"; fi; \
- f=$(html__strip_dir) \
- if test -d "$$d$$p"; then \
- echo " $(mkinstalldirs) '$(DESTDIR)$(htmldir)/$$f'"; \
- $(mkinstalldirs) "$(DESTDIR)$(htmldir)/$$f" || exit 1; \
- echo " $(INSTALL_DATA) '$$d$$p'/* '$(DESTDIR)$(htmldir)/$$f'"; \
- $(INSTALL_DATA) "$$d$$p"/* "$(DESTDIR)$(htmldir)/$$f"; \
- else \
- echo " $(INSTALL_DATA) '$$d$$p' '$(DESTDIR)$(htmldir)/$$f'"; \
- $(INSTALL_DATA) "$$d$$p" "$(DESTDIR)$(htmldir)/$$f"; \
- fi; \
- done
-
-elna.info:
-elna.dvi:
-elna.pdf:
-elna.html: $(build_htmldir)/gelna/index.html
-elna.man:
-elna.mostlyclean:
-elna.clean:
-elna.distclean:
-elna.maintainer-clean:
-
-# make uninstall
-elna.uninstall:
- -rm -f gelna$(exeext) elna1$(exeext)
- -rm -f $(elna_OBJS)
-
-# Used for handling bootstrap
-elna.stage1: stage1-start
- -mv elna/*$(objext) stage1/elna
-elna.stage2: stage2-start
- -mv elna/*$(objext) stage2/elna
-elna.stage3: stage3-start
- -mv elna/*$(objext) stage3/elna
-elna.stage4: stage4-start
- -mv elna/*$(objext) stage4/elna
-elna.stageprofile: stageprofile-start
- -mv elna/*$(objext) stageprofile/elna
-elna.stagefeedback: stagefeedback-start
- -mv elna/*$(objext) stagefeedback/elna
-
-ELNA_INCLUDES = -I $(srcdir)/elna/include -I elna/generated
-ELNA_CXXFLAGS = -std=c++17
-
-elna/%.o: elna/frontend/%.cc elna/generated/parser.hh elna/generated/location.hh
- $(COMPILE) $(ELNA_CXXFLAGS) $(ELNA_INCLUDES) $<
- $(POSTCOMPILE)
-
-elna/%.o: elna/generated/%.cc elna/generated/parser.hh elna/generated/location.hh
- $(COMPILE) $(ELNA_CXXFLAGS) $(ELNA_INCLUDES) $<
- $(POSTCOMPILE)
-
-elna/%.o: elna/gcc/%.cc elna/generated/parser.hh elna/generated/location.hh
- $(COMPILE) $(ELNA_CXXFLAGS) $(ELNA_INCLUDES) $<
- $(POSTCOMPILE)
-
-elna/generated/parser.cc: elna/frontend/parser.yy
- mkdir -p $(dir $@)
- $(BISON) -d -o $@ $<
-
-elna/generated/parser.hh elna/generated/location.hh: elna/generated/parser.cc
- @touch $@
-
-elna/generated/lexer.cc: elna/frontend/lexer.ll
- mkdir -p $(dir $@)
- $(FLEX) -o $@ $<
diff --git a/gcc/README.md b/gcc/README.md
deleted file mode 100644
index 99d03c3..0000000
--- a/gcc/README.md
+++ /dev/null
@@ -1,42 +0,0 @@
-# Elna programming language
-
-## Current implementation
-
-This repository contains a GCC frontend for Elna. After finishing the frontend
-I'm planning to rewrite the compiler in Elna itself with its own backend and
-a hand-written parser. So GCC gives a way to have a simple bootstrap compiler
-and a possbility to compile Elna programs for different platforms.
-
-## Grammar
-
-Flex and bison grammar specifications, `lexer.ll` and `parser.yy`, can be found
-in the `boot/` directory.
-
-## Build
-
-The frontend requires GCC 15.2.0 (not tested with other versions).
-
-Download the GCC source. Copy the contents of this repository into `gcc/elna`
-inside GCC. Finally build GCC enabling the frontend with
-`--enable-languages=c,c++,elna`. After the installation the compiler can be
-invoked with `$prefix/bin/gelna`.
-
-There is also a `Rakefile` that downloads, builds and installs GCC into the
-`./build/` subdirectory. The `Rakefile` assumes that ruby and rake, as well as
-all GCC dependencies are already available in the system. It works under Linux
-and Mac OS. In the latter case GCC is patched with the patches used by Homebrew
-(official GCC doesn't support Apple silicon targets). Invoke with
-
-```sh
-rake boot
-```
-
-`gcc` binary is used by default, but a different gcc version can be specified
-by passing `CC` and `CXX` environment variables to rake, e.g.:
-
-```sh
-rake CC=gcc-15 CXX=g++-15 boot
-```
-
-See `rake -T` for more tasks. The GCC source is under `build/tools`. The
-installation path is `build/host/install`.
diff --git a/gcc/config-lang.in b/gcc/config-lang.in
deleted file mode 100644
index 0cbbe1f..0000000
--- a/gcc/config-lang.in
+++ /dev/null
@@ -1,37 +0,0 @@
-# Top level configure fragment for gcc Elna frontend.
-# 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
-# .
-
-# Configure looks for the existence of this file to auto-config each language.
-# We define several parameters used by configure:
-#
-# language - name of language as it would appear in $(LANGUAGES)
-# boot_language - "yes" if we need to build this language in stage1
-# compilers - value to add to $(COMPILERS)
-
-language="elna"
-gcc_subdir="elna/gcc"
-
-compilers="elna1\$(exeext)"
-
-target_libs=""
-
-gtfiles="\$(srcdir)/elna/gcc/elna1.cc \$(srcdir)/elna/include/elna/gcc/elna1.h"
-
-lang_requires_boot_languages=c++
-
-# Do not build by default
-build_by_default="no"
diff --git a/gcc/elna-builtins.cc b/gcc/elna-builtins.cc
deleted file mode 100644
index cf06df8..0000000
--- a/gcc/elna-builtins.cc
+++ /dev/null
@@ -1,274 +0,0 @@
-/* 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
-
-#include "elna/gcc/elna-builtins.h"
-#include "elna/gcc/elna1.h"
-#include "stor-layout.h"
-#include "stringpool.h"
-#include "elna/gcc/elna-tree.h"
-
-namespace elna::gcc
-{
- void init_ttree()
- {
- elna_int_type_node = long_integer_type_node;
- elna_word_type_node = size_type_node;
- elna_char_type_node = unsigned_char_type_node;
- elna_pointer_type_node = ptr_type_node;
- elna_float_type_node = double_type_node;
-
- elna_bool_type_node = boolean_type_node;
- elna_bool_true_node = boolean_true_node;
- elna_bool_false_node = boolean_false_node;
-
- elna_pointer_nil_node = null_pointer_node;
-
- elna_string_type_node = make_node(RECORD_TYPE);
- tree string_ptr_type = build_pointer_type_for_mode(elna_char_type_node, VOIDmode, true);
-
- elna_string_length_field_node = build_field(UNKNOWN_LOCATION,
- elna_string_type_node, "length", build_qualified_type(elna_word_type_node, TYPE_QUAL_CONST));
- elna_string_ptr_field_node = build_field(UNKNOWN_LOCATION,
- elna_string_type_node, "ptr", build_qualified_type(string_ptr_type, TYPE_QUAL_CONST));
-
- TYPE_FIELDS(elna_string_type_node) = chainon(elna_string_ptr_field_node, elna_string_length_field_node);
- layout_type(elna_string_type_node);
- }
-
- static
- tree declare_builtin_type(std::shared_ptr symbol_table, const char *name, tree type)
- {
- tree identifier = get_identifier(name);
- tree type_declaration = build_decl(UNKNOWN_LOCATION, TYPE_DECL, identifier, type);
-
- symbol_table->enter(name, type_declaration);
-
- return type_declaration;
- }
-
- std::shared_ptr builtin_symbol_table()
- {
- std::shared_ptr symbol_table = std::make_shared();
-
- declare_builtin_type(symbol_table, "Int", elna_int_type_node);
- declare_builtin_type(symbol_table, "Word", elna_word_type_node);
- declare_builtin_type(symbol_table, "Char", elna_char_type_node);
- declare_builtin_type(symbol_table, "Bool", elna_bool_type_node);
- declare_builtin_type(symbol_table, "Pointer", elna_pointer_type_node);
- declare_builtin_type(symbol_table, "Float", elna_float_type_node);
-
- tree string_declaration = declare_builtin_type(symbol_table, "String", elna_string_type_node);
- TYPE_NAME(elna_string_type_node) = DECL_NAME(string_declaration);
- TYPE_STUB_DECL(elna_string_type_node) = string_declaration;
-
- return symbol_table;
- }
-
- tree build_composite_type(const std::vector& fields, tree composite_type_node,
- std::shared_ptr symbols)
- {
- for (auto& field : fields)
- {
- tree rewritten_field = get_inner_alias(field.second, symbols);
- tree field_declaration = build_field(UNKNOWN_LOCATION,
- composite_type_node, field.first, rewritten_field);
- TYPE_FIELDS(composite_type_node) = chainon(TYPE_FIELDS(composite_type_node), field_declaration);
- }
- layout_type(composite_type_node);
- return composite_type_node;
- }
-
- tree build_procedure_type(const frontend::procedure_type& procedure, std::shared_ptr symbols)
- {
- std::vector parameter_types(procedure.parameters.size());
-
- for (std::size_t i = 0; i < procedure.parameters.size(); ++i)
- {
- parameter_types[i] = get_inner_alias(procedure.parameters.at(i), symbols);
- }
- tree return_type = void_type_node;
-
- if (!procedure.return_type.proper_type.empty())
- {
- return_type = get_inner_alias(procedure.return_type.proper_type, symbols);
- }
- return build_function_type_array(return_type, procedure.parameters.size(), parameter_types.data());
- }
-
- tree get_inner_alias(const frontend::type& type, std::shared_ptr symbols)
- {
- if (auto reference = type.get())
- {
- auto looked_up = symbols->lookup(reference->identifier);
- gcc_assert(looked_up != NULL_TREE);
-
- return TREE_TYPE(looked_up);
- }
- else if (auto reference = type.get())
- {
- tree composite_type_node = make_node(RECORD_TYPE);
-
- build_composite_type(reference->fields, composite_type_node, symbols);
-
- return composite_type_node;
- }
- else if (auto reference = type.get())
- {
- tree composite_type_node = make_node(UNION_TYPE);
-
- build_composite_type(reference->fields, composite_type_node, symbols);
-
- return composite_type_node;
- }
- else if (auto reference = type.get())
- {
- return build_enumeration_type(reference->members);
- }
- else if (auto reference = type.get())
- {
- return build_global_pointer_type(get_inner_alias(reference->base, symbols));
- }
- else if (auto reference = type.get())
- {
- tree base = get_inner_alias(reference->base, symbols);
-
- return build_static_array_type(base, reference->size);
- }
- else if (auto reference = type.get())
- {
- auto procedure = build_procedure_type(*reference, symbols);
-
- return build_global_pointer_type(procedure);
- }
- else if (auto reference = type.get())
- {
- return TREE_TYPE(handle_symbol(reference->name, reference, symbols));
- }
- return error_mark_node;
- }
-
- tree handle_symbol(const std::string& symbol_name, std::shared_ptr reference,
- std::shared_ptr symbols)
- {
- tree looked_up = symbols->lookup(symbol_name);
-
- if (looked_up == NULL_TREE)
- {
- tree type_tree = get_inner_alias(reference->reference, symbols);
- looked_up = build_decl(UNKNOWN_LOCATION, TYPE_DECL,
- get_identifier(symbol_name.c_str()), type_tree);
-
- TREE_PUBLIC(looked_up) = 1;
- if (is_unique_type(type_tree))
- {
- TYPE_NAME(type_tree) = DECL_NAME(looked_up);
- TYPE_STUB_DECL(type_tree) = looked_up;
- }
- else
- {
- TYPE_NAME(type_tree) = looked_up;
- }
- symbols->enter(symbol_name, looked_up);
- }
- return looked_up;
- }
-
- void declare_procedure(const std::string& name, const frontend::procedure_info& info,
- std::shared_ptr symbols)
- {
- tree declaration_type = gcc::build_procedure_type(info.symbol, symbols);
- tree fndecl = build_fn_decl(name.c_str(), declaration_type);
- symbols->enter(name, fndecl);
-
- if (info.symbol.return_type.no_return)
- {
- TREE_THIS_VOLATILE(fndecl) = 1;
- }
- tree resdecl = build_decl(UNKNOWN_LOCATION, RESULT_DECL, NULL_TREE, TREE_TYPE(declaration_type));
- DECL_CONTEXT(resdecl) = fndecl;
- DECL_RESULT(fndecl) = resdecl;
-
- tree argument_chain = NULL_TREE;
- function_args_iterator parameter_type;
- function_args_iter_init(¶meter_type, declaration_type);
-
- std::vector::const_iterator parameter_name = info.names.cbegin();
-
- for (frontend::type parameter : info.symbol.parameters)
- {
- tree declaration_tree = build_decl(UNKNOWN_LOCATION, PARM_DECL,
- get_identifier(parameter_name->c_str()), function_args_iter_cond(¶meter_type));
- DECL_CONTEXT(declaration_tree) = fndecl;
- DECL_ARG_TYPE(declaration_tree) = function_args_iter_cond(¶meter_type);
-
- argument_chain = chainon(argument_chain, declaration_tree);
- function_args_iter_next(¶meter_type);
- ++parameter_name;
- }
- DECL_ARGUMENTS(fndecl) = argument_chain;
- TREE_ADDRESSABLE(fndecl) = 1;
- DECL_EXTERNAL(fndecl) = info.is_extern();
- TREE_PUBLIC(fndecl) = info.exported;
- }
-
- tree declare_variable(const std::string& name, const frontend::variable_info& info,
- std::shared_ptr symbols)
- {
- auto variable_type = get_inner_alias(info.symbol, symbols);
- tree declaration_tree = build_decl(UNKNOWN_LOCATION, VAR_DECL, get_identifier(name.c_str()), variable_type);
-
- TREE_ADDRESSABLE(declaration_tree) = 1;
- DECL_EXTERNAL(declaration_tree) = info.is_extern;
- TREE_PUBLIC(declaration_tree) = info.exported;
-
- symbols->enter(name, declaration_tree);
-
- return declaration_tree;
- }
-
- void declare_type(const std::string& name, const frontend::type_info& info, std::shared_ptr symbols)
- {
- // The top level symbol table has basic (builtin) types in it which are not aliases.
- if (auto alias_type = info.symbol.get())
- {
- tree type_declaration = handle_symbol(name, alias_type, symbols);
-
- TREE_PUBLIC(type_declaration) = info.exported;
- }
- }
-
- void rewrite_symbol_table(std::shared_ptr info_table, std::shared_ptr symbols)
- {
- for (auto& [symbol_name, symbol_info] : *info_table)
- {
- if (auto type_info = symbol_info->is_type())
- {
- declare_type(symbol_name, *type_info, symbols);
- }
- else if (auto variable_info = symbol_info->is_variable())
- {
- declare_variable(symbol_name, *variable_info, symbols);
- }
- else if (auto procedure_info = symbol_info->is_procedure())
- {
- declare_procedure(symbol_name, *procedure_info, symbols);
- }
- }
- }
-}
diff --git a/gcc/elna-diagnostic.cc b/gcc/elna-diagnostic.cc
deleted file mode 100644
index 162d6cb..0000000
--- a/gcc/elna-diagnostic.cc
+++ /dev/null
@@ -1,167 +0,0 @@
-/* Elna frontend specific diagnostic 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 "elna/gcc/elna-diagnostic.h"
-#include "elna/gcc/elna-tree.h"
-#include "elna/gcc/elna1.h"
-
-namespace elna::gcc
-{
- linemap_guard::linemap_guard(const char *filename)
- {
- linemap_add(line_table, LC_ENTER, 0, filename, 1);
- }
-
- linemap_guard::~linemap_guard()
- {
- linemap_add(line_table, LC_LEAVE, 0, NULL, 0);
- }
-
- location_t get_location(const frontend::position *position)
- {
- linemap_line_start(line_table, position->line, 0);
-
- return linemap_position_for_column(line_table, position->column);
- }
-
- std::string print_aggregate_name(tree type, const std::string& kind_name)
- {
- if (TYPE_IDENTIFIER(type) == NULL_TREE)
- {
- return kind_name;
- }
- else
- {
- return std::string(IDENTIFIER_POINTER(TYPE_IDENTIFIER(type)));
- }
- }
-
- std::string print_type(tree type)
- {
- gcc_assert(TYPE_P(type));
-
- tree unqualified_type = get_qualified_type(type, TYPE_UNQUALIFIED);
- tree_code code = TREE_CODE(type);
-
- if (unqualified_type == elna_int_type_node)
- {
- return "Int";
- }
- else if (unqualified_type == elna_word_type_node)
- {
- return "Word";
- }
- else if (unqualified_type == elna_bool_type_node)
- {
- return "Bool";
- }
- else if (unqualified_type == elna_pointer_type_node)
- {
- return "Pointer";
- }
- else if (unqualified_type == elna_float_type_node)
- {
- return "Float";
- }
- else if (unqualified_type == elna_char_type_node)
- {
- return "Char";
- }
- else if (unqualified_type == elna_string_type_node)
- {
- return "String";
- }
- else if (is_void_type(unqualified_type)) // For procedures without a return type.
- {
- return "()";
- }
- else if (POINTER_TYPE_P(unqualified_type))
- {
- tree pointer_target_type = TREE_TYPE(type);
-
- if (TREE_CODE(pointer_target_type) == FUNCTION_TYPE)
- {
- return print_type(pointer_target_type);
- }
- else
- {
- return std::string("^" + print_type(pointer_target_type));
- }
- }
- else if (code == FUNCTION_TYPE)
- {
- std::string output = "proc(";
- tree parameter_type = TYPE_ARG_TYPES(type);
- while (TREE_VALUE(parameter_type) != void_type_node)
- {
- output += print_type(TREE_VALUE(parameter_type));
- parameter_type = TREE_CHAIN(parameter_type);
- if (TREE_VALUE(parameter_type) == void_type_node)
- {
- break;
- }
- else
- {
- output += ", ";
- }
- }
- output += ')';
- tree return_type = TREE_TYPE(type);
-
- if (!is_void_type(return_type))
- {
- output += " -> " + print_type(return_type);
- }
- return output;
- }
- else if (code == ARRAY_TYPE)
- {
- return "array";
- }
- else if (code == RECORD_TYPE)
- {
- return print_aggregate_name(unqualified_type, "record");
- }
- else if (code == UNION_TYPE)
- {
- return print_aggregate_name(unqualified_type, "union");
- }
- else if (code == ENUMERAL_TYPE)
- {
- return print_aggregate_name(unqualified_type, "enumeration");
- }
- else
- {
- return "<>";
- }
- gcc_unreachable();
- }
-
- void report_errors(const std::deque>& errors)
- {
- for (const auto& error : errors)
- {
- location_t gcc_location{ UNKNOWN_LOCATION };
-
- if (error->position.line != 0 || error->position.column != 0)
- {
- gcc_location = elna::gcc::get_location(&error->position);
- }
- error_at(gcc_location, error->what().c_str());
- }
- }
-}
diff --git a/gcc/elna-generic.cc b/gcc/elna-generic.cc
deleted file mode 100644
index b37b111..0000000
--- a/gcc/elna-generic.cc
+++ /dev/null
@@ -1,1277 +0,0 @@
-/* Visitor generating a GENERIC tree.
- 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
-
-#include "elna/gcc/elna-generic.h"
-#include "elna/gcc/elna-diagnostic.h"
-#include "elna/gcc/elna1.h"
-#include "elna/gcc/elna-builtins.h"
-
-#include "ggc.h"
-#include "function.h"
-#include "cgraph.h"
-#include "gimplify.h"
-#include "stringpool.h"
-#include "diagnostic.h"
-#include "realmpfr.h"
-#include "varasm.h"
-#include "fold-const.h"
-#include "langhooks.h"
-
-namespace elna::gcc
-{
- generic_visitor::generic_visitor(std::shared_ptr symbol_table, elna::frontend::symbol_bag bag)
- : bag(bag), symbols(symbol_table)
- {
- }
-
- void generic_visitor::build_procedure_call(location_t call_location,
- tree procedure_address, const std::vector& arguments)
- {
- vec *argument_trees = nullptr;
- tree symbol_type = TREE_TYPE(TREE_TYPE(procedure_address));
-
- tree current_parameter = TYPE_ARG_TYPES(symbol_type);
-
- vec_alloc(argument_trees, arguments.size());
- for (frontend::expression *const argument : arguments)
- {
- location_t argument_location = get_location(&argument->position());
- if (VOID_TYPE_P(TREE_VALUE(current_parameter)))
- {
- error_at(argument_location, "Too many arguments, expected %i, got %lu",
- list_length(TYPE_ARG_TYPES(symbol_type)) - 1, arguments.size());
- this->current_expression = error_mark_node;
- break;
- }
- argument->accept(this);
- this->current_expression = prepare_rvalue(this->current_expression);
- if (!is_assignable_from(TREE_VALUE(current_parameter), this->current_expression))
- {
- error_at(argument_location,
- "Cannot assign value of type '%s' to variable of type '%s'",
- print_type(TREE_TYPE(this->current_expression)).c_str(),
- print_type(TREE_VALUE(current_parameter)).c_str());
- this->current_expression = error_mark_node;
- }
- current_parameter = TREE_CHAIN(current_parameter);
- argument_trees->quick_push(this->current_expression);
- }
- tree stmt = fold_build_call_array_loc(call_location, TREE_TYPE(symbol_type),
- procedure_address, vec_safe_length(argument_trees), vec_safe_address(argument_trees));
-
- if (!VOID_TYPE_P(TREE_VALUE(current_parameter)))
- {
- error_at(call_location, "Too few arguments, expected %i, got %lu",
- list_length(TYPE_ARG_TYPES(symbol_type)) - 1, arguments.size());
- this->current_expression = error_mark_node;
- }
- else
- {
- this->current_expression = stmt;
- }
- }
-
- void generic_visitor::build_record_call(location_t call_location,
- tree symbol, const std::vector& arguments)
- {
- vec *tree_arguments = nullptr;
- tree record_fields = TYPE_FIELDS(symbol);
- for (frontend::expression *const argument : arguments)
- {
- location_t argument_location = get_location(&argument->position());
-
- if (is_void_type(record_fields))
- {
- error_at(argument_location, "Too many arguments, expected %i, got %lu",
- list_length(TYPE_FIELDS(symbol)), arguments.size());
- this->current_expression = error_mark_node;
- break;
- }
- argument->accept(this);
- tree unqualified_field = get_qualified_type(TREE_TYPE(record_fields), TYPE_UNQUALIFIED);
- if (!is_assignable_from(unqualified_field, this->current_expression))
- {
- error_at(argument_location,
- "Cannot assign value of type '%s' to variable of type '%s'",
- print_type(TREE_TYPE(this->current_expression)).c_str(),
- print_type(TREE_TYPE(record_fields)).c_str());
- this->current_expression = error_mark_node;
- }
- CONSTRUCTOR_APPEND_ELT(tree_arguments, record_fields, this->current_expression);
- record_fields = TREE_CHAIN(record_fields);
- }
- if (!is_void_type(record_fields))
- {
- error_at(call_location, "Too few arguments, expected %i, got %lu",
- list_length(TYPE_FIELDS(symbol)), arguments.size());
- this->current_expression = error_mark_node;
- }
- else
- {
- this->current_expression = build_constructor(symbol, tree_arguments);
- }
- }
-
- void generic_visitor::build_assert_builtin(location_t call_location,
- const std::vector& arguments)
- {
- if (arguments.size() != 1)
- {
- error_at(call_location, "assert expects exactly one boolean argument, got %lu", arguments.size());
- this->current_expression = error_mark_node;
- }
- else
- {
- arguments.at(0)->accept(this);
- tree argument_type = TREE_TYPE(this->current_expression);
-
- if (argument_type != elna_bool_type_node)
- {
- error_at(call_location, "assert expects exactly one boolean argument, got %s",
- print_type(argument_type).c_str());
- this->current_expression = error_mark_node;
- }
- tree constant_expression = extract_constant(this->current_expression);
- if (constant_expression == boolean_false_node)
- {
- this->current_expression = call_built_in(call_location, "__builtin_unreachable", void_type_node);
- }
- else if (constant_expression != boolean_true_node)
- {
- tree assert_expression = call_built_in(call_location, "__builtin_trap", void_type_node);
- this->current_expression = build3(COND_EXPR, void_type_node, this->current_expression,
- NULL_TREE, assert_expression);
- }
- else
- {
- this->current_expression = NULL_TREE;
- }
- }
- }
-
- bool generic_visitor::build_builtin_procedures(frontend::procedure_call *call)
- {
- location_t call_location = get_location(&call->position());
-
- if (frontend::variable_expression *named_call = call->callable().is_variable())
- {
- if (named_call->name == "assert")
- {
- build_assert_builtin(call_location, call->arguments);
- return true;
- }
- }
- return false;
- }
-
- void generic_visitor::visit(frontend::procedure_call *call)
- {
- if (build_builtin_procedures(call))
- {
- return;
- }
- location_t call_location = get_location(&call->position());
- call->callable().accept(this);
-
- tree expression_type = TYPE_P(this->current_expression)
- ? this->current_expression
- : TREE_TYPE(this->current_expression);
-
- if (TREE_CODE(expression_type) == RECORD_TYPE)
- {
- build_record_call(call_location, expression_type, call->arguments);
- }
- else if (TREE_CODE(expression_type) == FUNCTION_TYPE)
- {
- this->current_expression = build1(ADDR_EXPR,
- build_global_pointer_type(expression_type), this->current_expression);
- build_procedure_call(call_location, this->current_expression, call->arguments);
- }
- else if (POINTER_TYPE_P(expression_type) && TREE_CODE(TREE_TYPE(expression_type)) == FUNCTION_TYPE)
- {
- build_procedure_call(call_location, this->current_expression, call->arguments);
- }
- else
- {
- error_at(call_location, "'%s' cannot be called, it is neither a procedure nor record",
- print_type(expression_type).c_str());
- this->current_expression = error_mark_node;
- }
- }
-
- void generic_visitor::visit(frontend::cast_expression *expression)
- {
- tree cast_target = get_inner_alias(expression->expression_type, this->symbols->scope());
-
- expression->value().accept(this);
- tree cast_source = TREE_TYPE(this->current_expression);
-
- if (is_castable_type(cast_target) && (is_castable_type(cast_source)))
- {
- this->current_expression = build1_loc(get_location(&expression->position()), CONVERT_EXPR,
- cast_target, this->current_expression);
- }
- else
- {
- error_at(get_location(&expression->position()), "Type '%s' cannot be converted to '%s'",
- print_type(cast_source).c_str(), print_type(cast_target).c_str());
- this->current_expression = error_mark_node;
- }
- }
-
- void generic_visitor::visit(frontend::program *program)
- {
- visit(static_cast(program));
-
- tree declaration_type = build_function_type_list(elna_int_type_node,
- elna_int_type_node,
- build_global_pointer_type(build_global_pointer_type(elna_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);
- DECL_CONTEXT(resdecl) = fndecl;
- DECL_RESULT(fndecl) = resdecl;
-
- push_struct_function(fndecl, false);
- DECL_STRUCT_FUNCTION(fndecl)->language = ggc_cleared_alloc();
-
- enter_scope();
-
- tree parameter_type = TYPE_ARG_TYPES(declaration_type);
- for (const char *argument_name : std::array{ "count", "parameters" })
- {
- 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);
-
- this->symbols->enter(argument_name, declaration_tree);
- DECL_ARGUMENTS(fndecl) = chainon(DECL_ARGUMENTS(fndecl), declaration_tree);
- parameter_type = TREE_CHAIN(parameter_type);
- }
- visit_statements(program->body);
- 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);
- append_statement(return_stmt);
- tree mapping = leave_scope();
-
- 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;
-
- pop_cfun();
- gimplify_function_tree(fndecl);
- cgraph_node::finalize_function(fndecl, true);
- }
-
- void generic_visitor::visit(frontend::unit *unit)
- {
- for (frontend::import_declaration *const declaration : unit->imports)
- {
- declaration->accept(this);
- }
- for (frontend::constant_declaration *const constant : unit->constants)
- {
- constant->accept(this);
- }
- for (frontend::variable_declaration *const variable : unit->variables)
- {
- variable->accept(this);
- }
- for (frontend::procedure_declaration *const procedure : unit->procedures)
- {
- procedure->accept(this);
- }
- }
-
- void generic_visitor::visit(frontend::procedure_declaration *definition)
- {
- tree fndecl = this->symbols->lookup(definition->identifier.name);
-
- if (!definition->body.has_value())
- {
- return;
- }
- push_struct_function(fndecl, false);
- DECL_STRUCT_FUNCTION(fndecl)->language = ggc_cleared_alloc();
-
- enter_scope();
- this->bag.enter(this->bag.lookup(definition->identifier.name)->is_procedure()->scope);
-
- tree argument_chain = DECL_ARGUMENTS(fndecl);
- for (; argument_chain != NULL_TREE; argument_chain = TREE_CHAIN(argument_chain))
- {
- this->symbols->enter(IDENTIFIER_POINTER(DECL_NAME(argument_chain)), argument_chain);
- }
- for (frontend::constant_declaration *const constant : definition->body.value().constants())
- {
- constant->accept(this);
- }
- for (frontend::variable_declaration *const variable : definition->body.value().variables())
- {
- variable->accept(this);
- }
- visit_statements(definition->body.value().body());
-
- tree mapping = leave_scope();
- this->bag.leave();
-
- BLOCK_SUPERCONTEXT(BIND_EXPR_BLOCK(mapping)) = fndecl;
- DECL_INITIAL(fndecl) = BIND_EXPR_BLOCK(mapping);
- DECL_SAVED_TREE(fndecl) = mapping;
-
- DECL_PRESERVE_P(fndecl) = 1;
-
- pop_cfun();
- gimplify_function_tree(fndecl);
- cgraph_node::finalize_function(fndecl, true);
- }
-
- void generic_visitor::enter_scope()
- {
- this->symbols = std::make_shared(this->symbols);
-
- // 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 generic_visitor::leave_scope()
- {
- // 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 = 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, variables, chain_defer(), new_block);
- this->symbols = this->symbols->scope();
-
- f_binding_level = f_binding_level->level_chain;
-
- if (f_binding_level != nullptr)
- {
- f_binding_level->blocks = chainon(f_binding_level->blocks, new_block);
- }
- return bind_expr;
- }
-
- void generic_visitor::visit(frontend::literal *literal)
- {
- this->current_expression = build_int_cst(elna_int_type_node, literal->value);
- }
-
- void generic_visitor::visit(frontend::literal *literal)
- {
- this->current_expression = build_int_cstu(elna_word_type_node, literal->value);
- }
-
- void generic_visitor::visit(frontend::literal *literal)
- {
- REAL_VALUE_TYPE real_value1;
-
- mpfr_t number;
- mpfr_init2(number, SIGNIFICAND_BITS);
- mpfr_set_d(number, literal->value, MPFR_RNDN);
-
- real_from_mpfr(&real_value1, number, double_type_node, MPFR_RNDN);
-
- this->current_expression = build_real(double_type_node, real_value1);
-
- mpfr_clear(number);
- }
-
- void generic_visitor::visit(frontend::literal *boolean)
- {
- this->current_expression = boolean->value ? boolean_true_node : boolean_false_node;
- }
-
- void generic_visitor::visit(frontend::literal *character)
- {
- this->current_expression = build_int_cstu(elna_char_type_node, character->value);
- }
-
- void generic_visitor::visit(frontend::literal *)
- {
- this->current_expression = elna_pointer_nil_node;
- }
-
- void generic_visitor::visit(frontend::literal *string)
- {
- tree index_constant = build_int_cstu(elna_word_type_node, string->value.size());
- tree string_type = build_array_type(elna_char_type_node, build_index_type(index_constant));
-
- tree string_literal = build_string(string->value.size(), string->value.c_str());
- TREE_TYPE(string_literal) = string_type;
- TREE_CONSTANT(string_literal) = 1;
- TREE_READONLY(string_literal) = 1;
- TREE_STATIC(string_literal) = 1;
-
- string_type = TREE_TYPE(elna_string_ptr_field_node);
- string_literal = build4(ARRAY_REF, elna_char_type_node,
- string_literal, integer_zero_node, NULL_TREE, NULL_TREE);
- string_literal = build1(ADDR_EXPR, string_type, string_literal);
-
- vec *elms = nullptr;
- CONSTRUCTOR_APPEND_ELT(elms, elna_string_ptr_field_node, string_literal);
- CONSTRUCTOR_APPEND_ELT(elms, elna_string_length_field_node, index_constant);
-
- this->current_expression = build_constructor(elna_string_type_node, elms);
- }
-
- tree generic_visitor::build_arithmetic_operation(frontend::binary_expression *expression,
- tree_code operator_code, tree left, tree right)
- {
- return build_binary_operation(is_numeric_type(TREE_TYPE(left)),
- expression, operator_code, left, right, TREE_TYPE(left));
- }
-
- tree generic_visitor::build_comparison_operation(frontend::binary_expression *expression,
- tree_code operator_code, tree left, tree right)
- {
- return build_binary_operation(is_numeric_type(TREE_TYPE(left)) || POINTER_TYPE_P(TREE_TYPE(left)),
- expression, operator_code, left, right, elna_bool_type_node);
- }
-
- tree generic_visitor::build_bit_logic_operation(frontend::binary_expression *expression, tree left, tree right)
- {
- location_t expression_location = get_location(&expression->position());
- tree left_type = TREE_TYPE(left);
- tree right_type = TREE_TYPE(right);
- tree_code logical_code, bit_code;
-
- if (expression->operation() == frontend::binary_operator::conjunction)
- {
- bit_code = BIT_AND_EXPR;
- logical_code = TRUTH_ANDIF_EXPR;
- }
- else if (expression->operation() == frontend::binary_operator::disjunction)
- {
- bit_code = BIT_IOR_EXPR;
- logical_code = TRUTH_ORIF_EXPR;
- }
- else if (expression->operation() == frontend::binary_operator::exclusive_disjunction)
- {
- bit_code = BIT_XOR_EXPR;
- logical_code = TRUTH_XOR_EXPR;
- }
- else
- {
- gcc_unreachable();
- }
- if (left_type == elna_bool_type_node)
- {
- return build2_loc(expression_location, logical_code, elna_bool_type_node, left, right);
- }
- else if (is_integral_type(left_type))
- {
- return build2_loc(expression_location, bit_code, left_type, left, right);
- }
- else
- {
- error_at(expression_location, "Invalid operands of type '%s' and '%s' for operator %s",
- print_type(left_type).c_str(), print_type(right_type).c_str(),
- elna::frontend::print_binary_operator(expression->operation()));
- return error_mark_node;
- }
- }
-
- tree generic_visitor::build_equality_operation(frontend::binary_expression *expression, tree left, tree right)
- {
- location_t expression_location = get_location(&expression->position());
- tree_code equality_code, combination_code;
-
- if (expression->operation() == frontend::binary_operator::equals)
- {
- equality_code = EQ_EXPR;
- combination_code = TRUTH_ANDIF_EXPR;
- }
- else if (expression->operation() == frontend::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 lhs_length = build3(COMPONENT_REF, TREE_TYPE(elna_string_length_field_node),
- left, elna_string_length_field_node, NULL_TREE);
- tree lhs_ptr = build3(COMPONENT_REF, TREE_TYPE(elna_string_ptr_field_node),
- left, elna_string_ptr_field_node, NULL_TREE);
-
- tree rhs_length = build3(COMPONENT_REF, TREE_TYPE(elna_string_length_field_node),
- right, elna_string_length_field_node, NULL_TREE);
- tree rhs_ptr = build3(COMPONENT_REF, TREE_TYPE(elna_string_ptr_field_node),
- right, elna_string_ptr_field_node, NULL_TREE);
-
- tree length_equality = build2(equality_code, elna_bool_type_node, lhs_length, rhs_length);
- tree memcmp_call = call_built_in(UNKNOWN_LOCATION, "__builtin_memcmp", integer_type_node,
- 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(frontend::binary_expression *expression)
- {
- expression->lhs().accept(this);
- tree left = this->current_expression;
- tree left_type = get_qualified_type(TREE_TYPE(left), TYPE_UNQUALIFIED);
-
- expression->rhs().accept(this);
- tree right = this->current_expression;
- tree right_type = get_qualified_type(TREE_TYPE(right), TYPE_UNQUALIFIED);
-
- location_t expression_location = get_location(&expression->position());
-
- if ((POINTER_TYPE_P(left_type) || POINTER_TYPE_P(right_type))
- && (expression->operation() == frontend::binary_operator::sum
- || expression->operation() == frontend::binary_operator::subtraction))
- {
- this->current_expression = do_pointer_arithmetic(expression->operation(),
- left, right, expression_location);
- if (this->current_expression == error_mark_node)
- {
- error_at(expression_location,
- "invalid operation %s on a pointer and an integral type",
- frontend::print_binary_operator(expression->operation()));
- }
- else if (TREE_TYPE(this->current_expression) == ssizetype)
- {
- this->current_expression = fold_convert(elna_int_type_node, this->current_expression);
- }
- return;
- }
- if (left_type != right_type
- && !are_compatible_pointers(left_type, right)
- && !are_compatible_pointers(right_type, left)
- && !(is_integral_type(left_type) && right_type == elna_word_type_node))
- {
- error_at(expression_location,
- "invalid operands of type '%s' and '%s' for operator %s",
- print_type(left_type).c_str(), print_type(right_type).c_str(),
- frontend::print_binary_operator(expression->operation()));
- this->current_expression = error_mark_node;
- return;
- }
- switch (expression->operation())
- {
- case frontend::binary_operator::sum:
- this->current_expression = build_arithmetic_operation(expression, PLUS_EXPR, left, right);
- break;
- case frontend::binary_operator::subtraction:
- this->current_expression = build_arithmetic_operation(expression, MINUS_EXPR, left, right);
- break;
- case frontend::binary_operator::division:
- this->current_expression = build_arithmetic_operation(expression, TRUNC_DIV_EXPR, left, right);
- break;
- case frontend::binary_operator::remainder:
- this->current_expression = build_arithmetic_operation(expression, TRUNC_MOD_EXPR, left, right);
- break;
- case frontend::binary_operator::multiplication:
- this->current_expression = build_arithmetic_operation(expression, MULT_EXPR, left, right);
- break;
- case frontend::binary_operator::less:
- this->current_expression = build_comparison_operation(expression, LT_EXPR, left, right);
- break;
- case frontend::binary_operator::greater:
- this->current_expression = build_comparison_operation(expression, GT_EXPR, left, right);
- break;
- case frontend::binary_operator::less_equal:
- this->current_expression = build_comparison_operation(expression, LE_EXPR, left, right);
- break;
- case frontend::binary_operator::greater_equal:
- this->current_expression = build_comparison_operation(expression, GE_EXPR, left, right);
- break;
- case frontend::binary_operator::conjunction:
- this->current_expression = build_bit_logic_operation(expression, left, right);
- break;
- case frontend::binary_operator::disjunction:
- this->current_expression = build_bit_logic_operation(expression, left, right);
- break;
- case frontend::binary_operator::exclusive_disjunction:
- this->current_expression = build_bit_logic_operation(expression, left, right);
- break;
- case frontend::binary_operator::equals:
- this->current_expression = build_equality_operation(expression, left, right);
- break;
- case frontend::binary_operator::not_equals:
- this->current_expression = build_equality_operation(expression, left, right);
- break;
- case frontend::binary_operator::shift_left:
- this->current_expression = build_binary_operation(
- is_numeric_type(left_type) && right_type == elna_word_type_node,
- expression, LSHIFT_EXPR, left, right, left_type);
- break;
- case frontend::binary_operator::shift_right:
- this->current_expression = build_binary_operation(
- is_numeric_type(left_type) && right_type == elna_word_type_node,
- expression, RSHIFT_EXPR, left, right, left_type);
- break;
- }
- }
-
- void generic_visitor::visit(frontend::unary_expression *expression)
- {
- expression->operand().accept(this);
- location_t location = get_location(&expression->position());
-
- switch (expression->operation())
- {
- case frontend::unary_operator::reference:
- this->current_expression = prepare_rvalue(this->current_expression);
- TREE_ADDRESSABLE(this->current_expression) = 1;
- this->current_expression = build_fold_addr_expr_with_type_loc(location,
- this->current_expression,
- build_global_pointer_type(TREE_TYPE(this->current_expression)));
- TREE_NO_TRAMPOLINE(this->current_expression) = 1;
- break;
- case frontend::unary_operator::negation:
- if (TREE_TYPE(this->current_expression) == elna_bool_type_node)
- {
- this->current_expression = build1_loc(location, TRUTH_NOT_EXPR,
- boolean_type_node, this->current_expression);
- }
- else if (is_integral_type(TREE_TYPE(this->current_expression)))
- {
- this->current_expression = build1_loc(location, BIT_NOT_EXPR,
- TREE_TYPE(this->current_expression), this->current_expression);
- }
- else
- {
- error_at(location, "type '%s' cannot be negated",
- print_type(TREE_TYPE(this->current_expression)).c_str());
- this->current_expression = error_mark_node;
- }
- break;
- case frontend::unary_operator::minus:
- if (is_integral_type(TREE_TYPE(this->current_expression)))
- {
- this->current_expression = fold_build1(NEGATE_EXPR, TREE_TYPE(this->current_expression),
- this->current_expression);
- }
- else
- {
- error_at(location, "type '%s' cannot be negated",
- print_type(TREE_TYPE(this->current_expression)).c_str());
- this->current_expression = error_mark_node;
- }
- }
- }
-
- void generic_visitor::visit(frontend::constant_declaration *definition)
- {
- location_t definition_location = get_location(&definition->position());
- definition->body().accept(this);
-
- if (assert_constant(definition_location))
- {
- this->current_expression = fold_init(this->current_expression);
- }
- else
- {
- this->current_expression = NULL_TREE;
- return;
- }
- tree definition_tree = build_decl(definition_location, CONST_DECL,
- get_identifier(definition->identifier.name.c_str()), TREE_TYPE(this->current_expression));
- auto result = this->symbols->enter(definition->identifier.name, definition_tree);
-
- if (result)
- {
- DECL_INITIAL(definition_tree) = this->current_expression;
- TREE_CONSTANT(definition_tree) = 1;
- TREE_READONLY(definition_tree) = 1;
- TREE_PUBLIC(definition_tree) = definition->identifier.exported;
-
- if (!lang_hooks.decls.global_bindings_p())
- {
- auto declaration_statement = build1_loc(definition_location, DECL_EXPR,
- void_type_node, definition_tree);
- append_statement(declaration_statement);
- }
- }
- else
- {
- error_at(definition_location, "Variable '%s' already declared in this scope",
- definition->identifier.name.c_str());
- }
- this->current_expression = NULL_TREE;
- }
-
- void generic_visitor::visit(frontend::variable_declaration *declaration)
- {
- for (const auto& variable_identifier : declaration->identifiers)
- {
- location_t declaration_location = get_location(&declaration->position());
- tree declaration_tree = this->symbols->lookup(variable_identifier.name);
-
- 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.
- if (declaration->body != nullptr)
- {
- declaration->body->accept(this);
- if (is_assignable_from(TREE_TYPE(declaration_tree), this->current_expression))
- {
- DECL_INITIAL(declaration_tree) = this->current_expression;
- }
- else
- {
- error_at(declaration_location, "Cannot initialize variable of type '%s' with a value of type '%s'",
- print_type(TREE_TYPE(declaration_tree)).c_str(),
- print_type(TREE_TYPE(this->current_expression)).c_str());
- }
- }
- else if (!declaration->is_extern && POINTER_TYPE_P(TREE_TYPE(declaration_tree)))
- {
- DECL_INITIAL(declaration_tree) = elna_pointer_nil_node;
- }
- this->current_expression = NULL_TREE;
-
- if (lang_hooks.decls.global_bindings_p())
- {
- TREE_STATIC(declaration_tree) = !variable_identifier.exported && !declaration->is_extern;
- varpool_node::get_create(declaration_tree);
- varpool_node::finalize_decl(declaration_tree);
- }
- else
- {
- DECL_CONTEXT(declaration_tree) = current_function_decl;
- f_names = chainon(f_names, declaration_tree);
-
- auto declaration_statement = build1_loc(declaration_location, DECL_EXPR,
- void_type_node, declaration_tree);
- append_statement(declaration_statement);
- }
- }
- }
-
- void generic_visitor::visit(frontend::variable_expression *expression)
- {
- auto symbol = this->symbols->lookup(expression->name);
-
- if (symbol == NULL_TREE)
- {
- error_at(get_location(&expression->position()), "Symbol '%s' not declared in the current scope",
- expression->name.c_str());
- this->current_expression = error_mark_node;
- }
- else
- {
- this->current_expression = symbol;
- }
- }
-
- void generic_visitor::visit(frontend::array_access_expression *expression)
- {
- expression->base().accept(this);
- tree designator = this->current_expression;
- location_t location = get_location(&expression->position());
-
- expression->index().accept(this);
- if (!is_integral_type(TREE_TYPE(this->current_expression)))
- {
- error_at(location, "Type '%s' cannot be used as index",
- print_type(TREE_TYPE(this->current_expression)).c_str());
- this->current_expression = error_mark_node;
- return;
- }
- tree offset = fold_convert(elna_word_type_node, this->current_expression);
-
- if (TREE_CODE(TREE_TYPE(designator)) == ARRAY_TYPE)
- {
- tree element_type = TREE_TYPE(TREE_TYPE(designator));
-
- this->current_expression = build4_loc(location,
- ARRAY_REF, element_type, designator, offset, size_one_node, NULL_TREE);
- }
- else if (TREE_TYPE(designator) == elna_string_type_node)
- {
- offset = build2(MINUS_EXPR, elna_word_type_node, offset, size_one_node);
- tree string_ptr = build3_loc(location, COMPONENT_REF, TREE_TYPE(elna_string_ptr_field_node),
- designator, elna_string_ptr_field_node, NULL_TREE);
-
- tree target_pointer = do_pointer_arithmetic(frontend::binary_operator::sum, string_ptr, offset, location);
-
- this->current_expression = build1_loc(location, INDIRECT_REF,
- elna_char_type_node, target_pointer);
- }
- else
- {
- error_at(location, "Indexing is not allowed on type '%s'",
- print_type(TREE_TYPE(designator)).c_str());
- this->current_expression = error_mark_node;
- }
- }
-
- bool generic_visitor::expect_trait_type_only(frontend::traits_expression *trait)
- {
- if (trait->parameters.size() != 1)
- {
- error_at(get_location(&trait->position()), "Trait '%s' expects 1 argument, got %lu",
- trait->name.c_str(), trait->parameters.size());
- this->current_expression = error_mark_node;
- return false;
- }
- this->current_expression = get_inner_alias(trait->types.front(), this->symbols);
-
- return this->current_expression != error_mark_node;
- }
-
- bool generic_visitor::expect_trait_for_integral_type(frontend::traits_expression *trait)
- {
- if (!expect_trait_type_only(trait))
- {
- return false;
- }
- else if (!is_integral_type(this->current_expression) && TREE_CODE(this->current_expression) != ENUMERAL_TYPE)
- {
- error_at(get_location(&trait->position()), "Type '%s' does not support trait '%s'",
- print_type(this->current_expression).c_str(), trait->name.c_str());
- this->current_expression = error_mark_node;
- return false;
- }
- return true;
- }
-
- void generic_visitor::visit(frontend::traits_expression *trait)
- {
- location_t trait_location = get_location(&trait->position());
-
- if (trait->name == "size")
- {
- if (expect_trait_type_only(trait))
- {
- this->current_expression = build1_loc(trait_location, CONVERT_EXPR, elna_word_type_node,
- size_in_bytes(this->current_expression));
- }
- }
- else if (trait->name == "alignment")
- {
- if (expect_trait_type_only(trait))
- {
- this->current_expression = build_int_cstu(elna_word_type_node,
- TYPE_ALIGN_UNIT(this->current_expression));
- }
- }
- else if (trait->name == "min")
- {
- if (expect_trait_for_integral_type(trait))
- {
- this->current_expression = TYPE_MIN_VALUE(this->current_expression);
- }
- }
- else if (trait->name == "max")
- {
- if (expect_trait_for_integral_type(trait))
- {
- this->current_expression = TYPE_MAX_VALUE(this->current_expression);
- }
- }
- else if (trait->name == "offset")
- {
- if (trait->parameters.size() != 2)
- {
- error_at(trait_location, "Trait '%s' expects 2 arguments, got %lu",
- trait->name.c_str(), trait->parameters.size());
- this->current_expression = error_mark_node;
- return;
- }
- this->current_expression = get_inner_alias(trait->types.front(), this->symbols);
- auto field_type = trait->parameters.at(1)->is_named();
-
- if (field_type == nullptr)
- {
- error_at(trait_location,
- "The second argument to the offset trait is expected to be a field name,"
- "got a type expression");
- this->current_expression = error_mark_node;
- return;
- }
- tree field_declaration = find_field_by_name(trait_location, this->current_expression, field_type->name);
-
- if (field_declaration != error_mark_node)
- {
- this->current_expression = build1(CONVERT_EXPR, elna_word_type_node,
- byte_position(field_declaration));
- }
- else
- {
- this->current_expression = error_mark_node;
- }
- }
- else
- {
- error_at(get_location(&trait->position()), "Trait '%s' is unknown", trait->name.c_str());
- this->current_expression = error_mark_node;
- }
- }
-
- void generic_visitor::visit(frontend::field_access_expression *expression)
- {
- expression->base().accept(this);
- location_t expression_location = get_location(&expression->position());
- tree aggregate_type = TREE_TYPE(this->current_expression);
-
- if (TREE_CODE(aggregate_type) == ARRAY_TYPE && expression->field() == "length")
- {
- this->current_expression = convert(build_qualified_type(elna_word_type_node, TYPE_QUAL_CONST),
- TYPE_MAX_VALUE(TYPE_DOMAIN(aggregate_type)));
- }
- else if (TREE_CODE(aggregate_type) == ARRAY_TYPE && expression->field() == "ptr")
- {
- tree ptr_type = build_global_pointer_type(TREE_TYPE(aggregate_type));
- this->current_expression = build1(ADDR_EXPR,
- build_qualified_type(ptr_type, TYPE_QUAL_CONST), this->current_expression);
- }
- else if (TREE_CODE(aggregate_type) == ENUMERAL_TYPE)
- {
- tree iterator{ NULL_TREE };
-
- for (iterator = TYPE_VALUES(aggregate_type); iterator != NULL_TREE; iterator = TREE_CHAIN(iterator))
- {
- if (IDENTIFIER_POINTER(TREE_PURPOSE(iterator)) == expression->field())
- {
- this->current_expression = TREE_VALUE(iterator);
- return;
- }
- }
- this->current_expression = error_mark_node;
- error_at(expression_location, "Unknown enumeration member '%s'", expression->field().c_str());
- }
- else
- {
- tree field_declaration = find_field_by_name(expression_location,
- TREE_TYPE(this->current_expression), expression->field());
-
- if (field_declaration != error_mark_node)
- {
- this->current_expression = build3_loc(expression_location, COMPONENT_REF,
- TREE_TYPE(field_declaration), this->current_expression,
- field_declaration, NULL_TREE);
- }
- }
- }
-
- void generic_visitor::visit(frontend::dereference_expression *expression)
- {
- expression->base().accept(this);
- location_t expression_location = get_location(&expression->position());
- tree expression_type = TREE_TYPE(this->current_expression);
-
- if (POINTER_TYPE_P(expression_type))
- {
- this->current_expression = build1_loc(expression_location, INDIRECT_REF,
- TREE_TYPE(expression_type), this->current_expression);
- }
- else
- {
- error_at(expression_location, "Type '%s' cannot be dereferenced, it is not a pointer",
- print_type(expression_type).c_str());
- this->current_expression = error_mark_node;
- }
- }
-
- void generic_visitor::visit(frontend::assign_statement *statement)
- {
- statement->lvalue().accept(this);
-
- tree lvalue = this->current_expression;
- location_t statement_location = get_location(&statement->position());
-
- statement->rvalue().accept(this);
- tree rvalue = prepare_rvalue(this->current_expression);
-
- if (TREE_CODE(lvalue) == CONST_DECL)
- {
- error_at(statement_location, "Cannot modify constant '%s'",
- statement->lvalue().is_variable()->name.c_str());
- }
- else if (TYPE_READONLY(TREE_TYPE(lvalue)))
- {
- error_at(statement_location, "Cannot modify a constant expression of type '%s'",
- print_type(TREE_TYPE(lvalue)).c_str());
- }
- else if (is_assignable_from(TREE_TYPE(lvalue), rvalue))
- {
- tree assignment = build2_loc(statement_location, MODIFY_EXPR, void_type_node, lvalue, rvalue);
-
- append_statement(assignment);
- }
- else
- {
- error_at(statement_location, "Cannot assign value of type '%s' to variable of type '%s'",
- print_type(TREE_TYPE(rvalue)).c_str(),
- print_type(TREE_TYPE(lvalue)).c_str());
- }
- this->current_expression = NULL_TREE;
- }
-
- void generic_visitor::visit(frontend::if_statement *statement)
- {
- tree endif_label_decl = create_artificial_label(UNKNOWN_LOCATION);
- tree goto_endif = build1(GOTO_EXPR, void_type_node, endif_label_decl);
-
- make_if_branch(statement->body(), goto_endif);
-
- for (const auto branch : statement->branches)
- {
- make_if_branch(*branch, goto_endif);
- }
- if (statement->alternative != nullptr)
- {
- enter_scope();
- visit_statements(*statement->alternative);
- tree mapping = leave_scope();
- append_statement(mapping);
- }
- tree endif_label_expr = build1(LABEL_EXPR, void_type_node, endif_label_decl);
- append_statement(endif_label_expr);
- this->current_expression = NULL_TREE;
- }
-
- void generic_visitor::make_if_branch(frontend::conditional_statements& branch, tree goto_endif)
- {
- branch.prerequisite().accept(this);
-
- if (TREE_TYPE(this->current_expression) != elna_bool_type_node)
- {
- error_at(get_location(&branch.prerequisite().position()),
- "Expected expression of boolean type but its type is %s",
- print_type(TREE_TYPE(this->current_expression)).c_str());
- this->current_expression = error_mark_node;
- return;
- }
- tree then_label_decl = build_label_decl("then", UNKNOWN_LOCATION);
- tree goto_then = build1(GOTO_EXPR, void_type_node, then_label_decl);
-
- tree else_label_decl = build_label_decl("else", UNKNOWN_LOCATION);
- 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);
- append_statement(cond_expr);
-
- tree then_label_expr = build1(LABEL_EXPR, void_type_node, then_label_decl);
- append_statement(then_label_expr);
- enter_scope();
-
- visit_statements(branch.statements);
- tree mapping = leave_scope();
- append_statement(mapping);
- append_statement(goto_endif);
-
- tree else_label_expr = build1(LABEL_EXPR, void_type_node, else_label_decl);
- append_statement(else_label_expr);
- }
-
- void generic_visitor::visit(frontend::import_declaration *)
- {
- }
-
- void generic_visitor::visit(frontend::while_statement *statement)
- {
- location_t prerequisite_location = get_location(&statement->body().prerequisite().position());
- tree prerequisite_label_decl = build_label_decl("while_do", prerequisite_location);
- auto prerequisite_label_expr = build1_loc(prerequisite_location, LABEL_EXPR,
- void_type_node, prerequisite_label_decl);
- auto goto_check = build1(GOTO_EXPR, void_type_node, prerequisite_label_decl);
- tree branch_end_declaration = build_label_decl("while_end", UNKNOWN_LOCATION);
- tree branch_end_expression = build1_loc(UNKNOWN_LOCATION, LABEL_EXPR, void_type_node, branch_end_declaration);
-
- append_statement(prerequisite_label_expr);
- make_if_branch(statement->body(), goto_check);
-
- for (const auto branch : statement->branches)
- {
- make_if_branch(*branch, goto_check);
- }
- append_statement(branch_end_expression);
- this->current_expression = NULL_TREE;
- }
-
- void generic_visitor::visit_statements(const std::vector& statements)
- {
- for (frontend::statement *const statement : statements)
- {
- statement->accept(this);
-
- if (this->current_expression != NULL_TREE && this->current_expression != error_mark_node)
- {
- append_statement(this->current_expression);
- this->current_expression = NULL_TREE;
- }
- }
- }
-
- void generic_visitor::visit(frontend::return_statement *statement)
- {
- frontend::expression *return_expression = &statement->return_expression();
- location_t statement_position = get_location(&statement->position());
- tree set_result{ NULL_TREE };
- tree return_type = TREE_TYPE(TREE_TYPE(current_function_decl));
-
- if (TREE_THIS_VOLATILE(current_function_decl) == 1)
- {
- error_at(statement_position, "This procedure is not allowed to return");
- return;
- }
- if (return_expression != nullptr)
- {
- return_expression->accept(this);
-
- set_result = build2(INIT_EXPR, void_type_node, DECL_RESULT(current_function_decl),
- this->current_expression);
- }
- if (return_type == void_type_node && set_result != NULL_TREE)
- {
- error_at(statement_position, "Proper procedure is not allowed to return a value");
- }
- else if (return_type != void_type_node && set_result == NULL_TREE)
- {
- error_at(statement_position, "Procedure is expected to return a value of type '%s'",
- print_type(return_type).c_str());
- }
- else if (return_type != void_type_node && !is_assignable_from(return_type, this->current_expression))
- {
- error_at(statement_position, "Cannot return '%s' from a procedure returning '%s'",
- print_type(return_type).c_str(),
- print_type(TREE_TYPE(this->current_expression)).c_str());
- }
- else
- {
- tree return_stmt = build1_loc(statement_position, RETURN_EXPR, void_type_node, set_result);
- append_statement(return_stmt);
- }
- this->current_expression = NULL_TREE;
- }
-
- void generic_visitor::visit(frontend::defer_statement *statement)
- {
- enter_scope();
- visit_statements(statement->statements);
- defer(leave_scope());
- }
-
- void generic_visitor::visit(frontend::case_statement *statement)
- {
- statement->condition().accept(this);
- tree condition_expression = this->current_expression;
- tree unqualified_condition = get_qualified_type(TREE_TYPE(this->current_expression), TYPE_UNQUALIFIED);
-
- 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;
- }
- tree end_label_declaration = create_artificial_label(get_location(&statement->position()));
- tree switch_statements = alloc_stmt_list();
-
- for (const frontend::switch_case& case_block : statement->cases)
- {
- for (frontend::expression *const case_label : case_block.labels)
- {
- case_label->accept(this);
- location_t case_location = get_location(&case_label->position());
-
- if (assert_constant(case_location)
- && !is_assignable_from(unqualified_condition, this->current_expression))
- {
- error_at(case_location, "Case type '%s' does not match the expression type '%s'",
- print_type(TREE_TYPE(this->current_expression)).c_str(),
- print_type(unqualified_condition).c_str());
- this->current_expression = error_mark_node;
- }
- tree case_label_declaration = create_artificial_label(case_location);
- tree case_expression = build_case_label(this->current_expression, NULL_TREE, case_label_declaration);
-
- append_to_statement_list(case_expression, &switch_statements);
- }
- enter_scope();
- visit_statements(case_block.statements);
- append_to_statement_list(leave_scope(), &switch_statements);
- tree goto_end = build1(GOTO_EXPR, void_type_node, end_label_declaration);
-
- append_to_statement_list(goto_end, &switch_statements);
- TREE_USED(end_label_declaration) = 1;
- }
- if (statement->alternative != nullptr)
- {
- tree case_label_declaration = create_artificial_label(UNKNOWN_LOCATION);
- tree case_expression = build_case_label(NULL_TREE, NULL_TREE, case_label_declaration);
-
- append_to_statement_list(case_expression, &switch_statements);
-
- enter_scope();
- visit_statements(*statement->alternative);
- append_to_statement_list(leave_scope(), &switch_statements);
-
- TREE_USED(end_label_declaration) = 1;
- }
- 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;
- }
-
- bool generic_visitor::assert_constant(location_t expression_location)
- {
- tree constant_expression = extract_constant(this->current_expression);
-
- if (constant_expression == NULL_TREE)
- {
- error_at(expression_location, "Expected a constant expression");
- this->current_expression = error_mark_node;
- }
- else
- {
- this->current_expression = constant_expression;
- }
- return this->current_expression != error_mark_node;
- }
-}
diff --git a/gcc/elna-spec.cc b/gcc/elna-spec.cc
deleted file mode 100644
index 5d1ace1..0000000
--- a/gcc/elna-spec.cc
+++ /dev/null
@@ -1,31 +0,0 @@
-/* Specific flags and argument handling of the Elna front end.
- 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
-. */
-
-void lang_specific_driver(struct cl_decoded_option ** /* in_decoded_options */,
- unsigned int * /* in_decoded_options_count */,
- int * /*in_added_libraries */)
-{
-}
-
-/* Called before linking. Returns 0 on success and -1 on failure. */
-int lang_specific_pre_link(void)
-{
- return 0;
-}
-
-/* Number of extra output files that lang_specific_pre_link may generate. */
-int lang_specific_extra_outfiles = 0;
diff --git a/gcc/elna-tree.cc b/gcc/elna-tree.cc
deleted file mode 100644
index 93f796b..0000000
--- a/gcc/elna-tree.cc
+++ /dev/null
@@ -1,315 +0,0 @@
-/* Utilities to manipulate GCC trees.
- 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-tree.h"
-#include "elna/gcc/elna-diagnostic.h"
-#include "elna/gcc/elna1.h"
-
-#include "function.h"
-#include "stor-layout.h"
-#include "diagnostic-core.h"
-
-namespace elna::gcc
-{
- bool is_integral_type(tree type)
- {
- gcc_assert(TYPE_P(type));
- return TREE_CODE(type) == INTEGER_TYPE && type != elna_char_type_node;
- }
-
- bool is_numeric_type(tree type)
- {
- return is_integral_type(type) || type == elna_float_type_node;
- }
-
- bool is_unique_type(tree type)
- {
- gcc_assert(TYPE_P(type));
- return RECORD_OR_UNION_TYPE_P(type) || TREE_CODE(type) == ENUMERAL_TYPE;
- }
-
- bool is_void_type(tree type)
- {
- return type == NULL_TREE || type == void_type_node;
- }
-
- bool is_castable_type(tree type)
- {
- gcc_assert(TYPE_P(type));
- return INTEGRAL_TYPE_P(type) || POINTER_TYPE_P(type) || TREE_CODE(type) == REAL_TYPE;
- }
-
- bool are_compatible_pointers(tree lhs_type, tree rhs)
- {
- gcc_assert(TYPE_P(lhs_type));
- tree rhs_type = TREE_TYPE(rhs);
-
- return (POINTER_TYPE_P(lhs_type) && rhs == elna_pointer_nil_node)
- || (POINTER_TYPE_P(lhs_type) && lhs_type == rhs_type);
- }
-
- tree prepare_rvalue(tree rvalue)
- {
- if (DECL_P(rvalue) && TREE_CODE(TREE_TYPE(rvalue)) == FUNCTION_TYPE)
- {
- return build1(ADDR_EXPR, build_pointer_type_for_mode(TREE_TYPE(rvalue), VOIDmode, true), rvalue);
- }
- else
- {
- return rvalue;
- }
- }
-
- bool is_assignable_from(tree assignee, tree assignment)
- {
- return get_qualified_type(TREE_TYPE(assignment), TYPE_UNQUALIFIED) == assignee
- || are_compatible_pointers(assignee, assignment);
- }
-
- void append_statement(tree statement_tree)
- {
- if (!vec_safe_is_empty(f_binding_level->defers))
- {
- append_to_statement_list(statement_tree, &f_binding_level->defers->begin()->try_statements);
- }
- else
- {
- append_to_statement_list(statement_tree, &f_binding_level->statement_list);
- }
- }
-
- void defer(tree statement_tree)
- {
- defer_scope new_defer{ statement_tree, alloc_stmt_list() };
- vec_safe_insert(f_binding_level->defers, 0, new_defer);
- }
-
- tree chain_defer()
- {
- if (vec_safe_is_empty(f_binding_level->defers))
- {
- return f_binding_level->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;
-
- FOR_EACH_VEC_ELT_FROM(*f_binding_level->defers, i, defer_iterator, 1)
- {
- 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);
- }
- 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)
- {
- tree field_declaration = build_decl(location,
- FIELD_DECL, get_identifier(name.c_str()), type);
- TREE_ADDRESSABLE(field_declaration) = 1;
- DECL_CONTEXT(field_declaration) = record_type;
-
- return field_declaration;
- }
-
- tree do_pointer_arithmetic(frontend::binary_operator binary_operator,
- tree left, tree right, location_t operation_location)
- {
- tree left_type = get_qualified_type(TREE_TYPE(left), TYPE_UNQUALIFIED);
- tree right_type = get_qualified_type(TREE_TYPE(right), TYPE_UNQUALIFIED);
- if (binary_operator == frontend::binary_operator::sum)
- {
- tree pointer{ NULL_TREE };
- tree offset{ NULL_TREE };
- tree pointer_type{ NULL_TREE };
-
- if (POINTER_TYPE_P(left_type) && is_integral_type(right_type))
- {
- pointer = left;
- offset = right;
- pointer_type = left_type;
- }
- else if (is_integral_type(left_type) && POINTER_TYPE_P(right_type))
- {
- pointer = right;
- offset = left;
- pointer_type = right_type;
- }
- else
- {
- return error_mark_node;
- }
- tree size_exp = pointer_type == elna_pointer_type_node
- ? size_one_node
- : fold_convert(TREE_TYPE(offset), size_in_bytes(TREE_TYPE(TREE_TYPE(pointer))));
-
- offset = fold_build2(MULT_EXPR, TREE_TYPE(offset), offset, size_exp);
- offset = fold_convert(sizetype, offset);
-
- return fold_build2_loc(operation_location, POINTER_PLUS_EXPR, TREE_TYPE(pointer), pointer, offset);
- }
- else if (binary_operator == frontend::binary_operator::subtraction)
- {
- if (POINTER_TYPE_P(left_type) && is_integral_type(right_type))
- {
- tree pointer_type = left_type;
- tree offset_type = right_type;
- tree size_exp = fold_convert(offset_type, size_in_bytes(TREE_TYPE(pointer_type)));
-
- tree convert_expression = fold_build2(MULT_EXPR, offset_type, right, size_exp);
- convert_expression = fold_convert(sizetype, convert_expression);
-
- convert_expression = fold_build1(NEGATE_EXPR, sizetype, convert_expression);
- return fold_build2_loc(operation_location, POINTER_PLUS_EXPR, pointer_type, left, convert_expression);
- }
- else if (POINTER_TYPE_P(left_type) && POINTER_TYPE_P(right_type) && left_type == right_type)
- {
- return fold_build2_loc(operation_location, POINTER_DIFF_EXPR, ssizetype, left, right);
- }
- }
- gcc_unreachable();
- }
-
- tree build_binary_operation(bool condition, frontend::binary_expression *expression,
- tree_code operator_code, tree left, tree right, tree target_type)
- {
- location_t expression_location = get_location(&expression->position());
- tree left_type = get_qualified_type(TREE_TYPE(left), TYPE_UNQUALIFIED);
- tree right_type = get_qualified_type(TREE_TYPE(right), TYPE_UNQUALIFIED);
-
- if (condition)
- {
- return fold_build2_loc(expression_location, operator_code, target_type, left, right);
- }
- else
- {
- error_at(expression_location,
- "invalid operands of type '%s' and '%s' for operator %s",
- print_type(left_type).c_str(), print_type(right_type).c_str(),
- elna::frontend::print_binary_operator(expression->operation()));
- return error_mark_node;
- }
- }
-
- tree find_field_by_name(location_t expression_location, tree type, const std::string& field_name)
- {
- if (type == error_mark_node)
- {
- return type;
- }
- tree field_declaration = TYPE_FIELDS(type);
-
- if (!RECORD_OR_UNION_TYPE_P(type))
- {
- error_at(expression_location, "Type '%s' does not have a field named '%s'",
- print_type(type).c_str(), field_name.c_str());
- return error_mark_node;
- }
- while (field_declaration != NULL_TREE)
- {
- tree declaration_name = DECL_NAME(field_declaration);
- const char *identifier_pointer = IDENTIFIER_POINTER(declaration_name);
-
- if (field_name == identifier_pointer)
- {
- break;
- }
- field_declaration = TREE_CHAIN(field_declaration);
- }
- if (field_declaration == NULL_TREE)
- {
- error_at(expression_location, "Aggregate type does not have a field '%s'", field_name.c_str());
- return error_mark_node;
- }
- return field_declaration;
- }
-
- tree build_global_pointer_type(tree type)
- {
- return build_pointer_type_for_mode(type, VOIDmode, true);
- }
-
- tree build_static_array_type(tree type, const std::uint64_t size)
- {
- tree upper_bound = build_int_cst_type(integer_type_node, size);
- tree range_type = build_range_type(integer_type_node, size_one_node, upper_bound);
-
- return build_array_type(type, range_type);
- }
-
- tree build_enumeration_type(const std::vector& members)
- {
- tree composite_type_node = make_node(ENUMERAL_TYPE);
- const tree base_type = integer_type_node;
-
- TREE_TYPE(composite_type_node) = base_type;
- ENUM_IS_SCOPED(composite_type_node) = 1;
-
- tree *pp = &TYPE_VALUES(composite_type_node);
- std::size_t order{ 1 };
-
- for (const std::string& member : members)
- {
- tree member_name = get_identifier(member.c_str());
- tree member_declaration = build_decl(UNKNOWN_LOCATION, CONST_DECL, member_name, composite_type_node);
-
- DECL_CONTEXT(member_declaration) = composite_type_node;
- DECL_INITIAL(member_declaration) = build_int_cst_type(composite_type_node, order++);
- TREE_CONSTANT(member_declaration) = 1;
- TREE_READONLY(member_declaration) = 1;
-
- TYPE_MAX_VALUE(composite_type_node) = DECL_INITIAL(member_declaration);
-
- *pp = build_tree_list(member_name, member_declaration);
- pp = &TREE_CHAIN(*pp);
- }
- TYPE_MIN_VALUE(composite_type_node) = DECL_INITIAL(TREE_VALUE(TYPE_VALUES(composite_type_node)));
- TYPE_UNSIGNED(composite_type_node) = TYPE_UNSIGNED(base_type);
- SET_TYPE_ALIGN(composite_type_node, TYPE_ALIGN(base_type));
- TYPE_SIZE(composite_type_node) = NULL_TREE;
- TYPE_PRECISION(composite_type_node) = TYPE_PRECISION(base_type);
-
- layout_type(composite_type_node);
- return composite_type_node;
- }
-
- tree build_label_decl(const char *name, location_t loc)
- {
- auto label_decl = build_decl(loc, LABEL_DECL, get_identifier(name), void_type_node);
-
- DECL_CONTEXT(label_decl) = current_function_decl;
-
- return label_decl;
- }
-
- tree extract_constant(tree expression)
- {
- int code = TREE_CODE(expression);
-
- if (code == CONST_DECL)
- {
- return DECL_INITIAL(expression);
- }
- else if (TREE_CODE_CLASS(code) == tcc_constant)
- {
- return expression;
- }
- return NULL_TREE;
- }
-}
diff --git a/gcc/elna1.cc b/gcc/elna1.cc
deleted file mode 100644
index 448a24c..0000000
--- a/gcc/elna1.cc
+++ /dev/null
@@ -1,256 +0,0 @@
-/* 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
-. */
-
-#include "config.h"
-#include "system.h"
-#include "coretypes.h"
-#include "target.h"
-#include "function.h"
-#include "tree.h"
-#include "elna/gcc/elna1.h"
-#include "diagnostic.h"
-#include "opts.h"
-#include "debug.h"
-#include "langhooks.h"
-#include "langhooks-def.h"
-
-#include
-#include "elna/frontend/dependency.h"
-#include "elna/gcc/elna-tree.h"
-#include "elna/gcc/elna-generic.h"
-#include "elna/gcc/elna-diagnostic.h"
-#include "elna/gcc/elna-builtins.h"
-
-tree elna_global_trees[ELNA_TI_MAX];
-hash_map *elna_global_decls = nullptr;
-
-/* The resulting tree type. */
-
-union GTY ((desc("TREE_CODE (&%h.generic) == IDENTIFIER_NODE"),
- chain_next("CODE_CONTAINS_STRUCT (TREE_CODE (&%h.generic), "
- "TS_COMMON) ? ((union lang_tree_node *) TREE_CHAIN "
- "(&%h.generic)) : NULL"))) lang_tree_node
-{
- union tree_node GTY ((tag ("0"), desc ("tree_node_structure (&%h)"))) generic;
-};
-
-/* Language hooks. */
-
-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();
-
- return true;
-}
-
-using dependency_state = elna::frontend::dependency_state>;
-
-static elna::frontend::dependency elna_parse_file(dependency_state& state, const char *filename)
-{
- std::ifstream entry_point{ filename, std::ios::in };
-
- if (!entry_point)
- {
- fatal_error(UNKNOWN_LOCATION, "Cannot open filename %s: %m", filename);
- }
- elna::gcc::linemap_guard{ filename };
- elna::frontend::dependency outcome = elna::frontend::read_source(entry_point, filename);
-
- if (outcome.has_errors())
- {
- elna::gcc::report_errors(outcome.errors());
- return outcome;
- }
- elna::frontend::symbol_bag outcome_bag = elna::frontend::symbol_bag{ std::move(outcome.unresolved), state.globals };
-
- for (const auto& sub_tree : outcome.tree->imports)
- {
- std::filesystem::path sub_path = "source" / elna::frontend::build_path(sub_tree->segments);
- std::unordered_map::const_iterator cached_import =
- state.cache.find(sub_path);
-
- if (cached_import == state.cache.end())
- {
- elna_parse_file(state, sub_path.c_str());
- cached_import = state.cache.find(sub_path);
- }
- outcome_bag.add_import(cached_import->second);
- }
- outcome.errors() = analyze_semantics(filename, outcome.tree, outcome_bag);
-
- if (outcome.has_errors())
- {
- elna::gcc::report_errors(outcome.errors());
- return outcome;
- }
- state.cache.insert({ filename, outcome_bag });
- elna::gcc::rewrite_symbol_table(outcome_bag.leave(), state.custom);
-
- return outcome;
-}
-
-static void elna_langhook_parse_file(void)
-{
- dependency_state state{ elna::gcc::builtin_symbol_table() };
-
- for (unsigned int i = 0; i < num_in_fnames; i++)
- {
- elna::frontend::dependency outcome = elna_parse_file(state, in_fnames[i]);
-
- linemap_add(line_table, LC_ENTER, 0, in_fnames[i], 1);
- elna::gcc::generic_visitor generic_visitor{ state.custom, state.cache.find(in_fnames[i])->second };
- outcome.tree->accept(&generic_visitor);
- linemap_add(line_table, LC_LEAVE, 0, NULL, 0);
- }
-}
-
-static tree elna_langhook_type_for_mode(enum machine_mode mode, int unsignedp)
-{
- if (mode == TYPE_MODE(float_type_node))
- {
- return float_type_node;
- }
- else if (mode == TYPE_MODE(double_type_node))
- {
- return double_type_node;
- }
- if (mode == TYPE_MODE(intQI_type_node))
- {
- return unsignedp ? unsigned_intQI_type_node : intQI_type_node;
- }
- else if (mode == TYPE_MODE(intHI_type_node))
- {
- return unsignedp ? unsigned_intHI_type_node : intHI_type_node;
- }
- else if (mode == TYPE_MODE(intSI_type_node))
- {
- return unsignedp ? unsigned_intSI_type_node : intSI_type_node;
- }
- else if (mode == TYPE_MODE(intDI_type_node))
- {
- return unsignedp ? unsigned_intDI_type_node : intDI_type_node;
- }
- else if (mode == TYPE_MODE(intTI_type_node))
- {
- return unsignedp ? unsigned_intTI_type_node : intTI_type_node;
- }
- else if (mode == TYPE_MODE(integer_type_node))
- {
- return unsignedp ? unsigned_type_node : integer_type_node;
- }
- else if (mode == TYPE_MODE(long_integer_type_node))
- {
- return unsignedp ? long_unsigned_type_node : long_integer_type_node;
- }
- else if (mode == TYPE_MODE(long_long_integer_type_node))
- {
- return unsignedp
- ? long_long_unsigned_type_node
- : long_long_integer_type_node;
- }
- if (COMPLEX_MODE_P(mode))
- {
- if (mode == TYPE_MODE(complex_float_type_node))
- {
- return complex_float_type_node;
- }
- if (mode == TYPE_MODE(complex_double_type_node))
- {
- return complex_double_type_node;
- }
- if (mode == TYPE_MODE(complex_long_double_type_node))
- {
- return complex_long_double_type_node;
- }
- if (mode == TYPE_MODE(complex_integer_type_node) && !unsignedp)
- {
- return complex_integer_type_node;
- }
- }
- /* gcc_unreachable */
- return nullptr;
-}
-
-static bool global_bindings_p(void)
-{
- return current_function_decl == NULL_TREE;
-}
-
-static tree pushdecl(tree decl)
-{
- return decl;
-}
-
-static tree elna_langhook_builtin_function(tree decl)
-{
- elna_global_decls->put(IDENTIFIER_POINTER(DECL_NAME(decl)), decl);
- return decl;
-}
-
-static unsigned int elna_langhook_option_lang_mask(void)
-{
- return CL_Elna;
-}
-
-/* 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"
-
-#undef LANG_HOOKS_INIT
-#define LANG_HOOKS_INIT elna_langhook_init
-
-#undef LANG_HOOKS_PARSE_FILE
-#define LANG_HOOKS_PARSE_FILE elna_langhook_parse_file
-
-#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
-
-#undef LANG_HOOKS_IDENTIFIER_SIZE
-#define LANG_HOOKS_IDENTIFIER_SIZE sizeof(struct tree_identifier)
-
-#undef LANG_HOOKS_OPTION_LANG_MASK
-#define LANG_HOOKS_OPTION_LANG_MASK elna_langhook_option_lang_mask
-
-struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
-
-#include "gt-elna-elna1.h"
-#include "gtype-elna.h"
diff --git a/gcc/gelna.texi b/gcc/gelna.texi
deleted file mode 100644
index e4bc6ce..0000000
--- a/gcc/gelna.texi
+++ /dev/null
@@ -1,135 +0,0 @@
-\input texinfo @c -*-texinfo-*-
-@setfilename gelna.info
-@settitle The GNU Elna Compiler
-
-@c Create a separate index for command line options
-@defcodeindex op
-@c Merge the standard indexes into a single one.
-@syncodeindex fn cp
-@syncodeindex vr cp
-@syncodeindex ky cp
-@syncodeindex pg cp
-@syncodeindex tp cp
-
-@include gcc-common.texi
-
-@c Copyright years for this manual.
-@set copyrights-elna 2025
-
-@copying
-@c man begin COPYRIGHT
-Copyright @copyright{} @value{copyrights-elna} Free Software Foundation, Inc.
-
-Permission is granted to copy, distribute and/or modify this document
-under the terms of the GNU Free Documentation License, Version 1.3 or
-any later version published by the Free Software Foundation; with no
-Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
-A copy of the license is included in the
-@c man end
-section entitled ``GNU Free Documentation License''.
-@ignore
-@c man begin COPYRIGHT
-man page gfdl(7).
-@c man end
-@end ignore
-@end copying
-
-@ifinfo
-@format
-@dircategory Software development
-@direntry
-* Gelna: (gelna). A GCC-based compiler for the Elna language
-@end direntry
-@end format
-
-@insertcopying
-@end ifinfo
-
-@titlepage
-@title The GNU Elna Compiler
-@versionsubtitle
-@author Eugen Wissner
-
-@page
-@vskip 0pt plus 1filll
-Published by the Free Software Foundation @*
-51 Franklin Street, Fifth Floor@*
-Boston, MA 02110-1301, USA@*
-@sp 1
-@insertcopying
-@end titlepage
-@contents
-@page
-
-@node Top
-@top Introduction
-
-This manual describes how to use @command{gelna}, the GNU compiler for
-the Elna programming language. This manual is specifically about how to
-invoke @command{gelna}.
-
-@menu
-* Copying:: The GNU General Public License.
-* GNU Free Documentation License::
- How you can share and copy this manual.
-* Invoking gelna:: How to run gelna.
-* Option Index:: Index of command line options.
-* Keyword Index:: Index of concepts.
-@end menu
-
-
-@include gpl_v3.texi
-
-@include fdl.texi
-
-
-@node Invoking gelna
-@chapter Invoking gelna
-
-@c man title gelna A GCC-based compiler for the Elna language
-
-@ignore
-@c man begin SYNOPSIS gelna
-gelna [@option{-c}|@option{-S}]
- [@option{-g}] [@option{-pg}]
- [@option{-o} @var{outfile}] @var{infile}@dots{}
-
-Only the most useful options are listed here; see below for the
-remainder.
-@c man end
-@c man begin SEEALSO
-gpl(7), gfdl(7), fsf-funding(7), gcc(1)
-and the Info entries for @file{gelna} and @file{gcc}.
-@c man end
-@end ignore
-
-@c man begin DESCRIPTION gelna
-
-The @command{gelna} command is a frontend to @command{gcc} and
-supports many of the same options. @xref{Option Summary, , Option
-Summary, gcc, Using the GNU Compiler Collection (GCC)}. This manual
-only documents the options specific to @command{gelna}.
-
-@c man end
-
-@c man begin OPTIONS gelna
-
-@c man end
-
-@node Option Index
-@unnumbered Option Index
-
-@command{gelna}'s command line options are indexed here without any
-initial @samp{-} or @samp{--}. Where an option has both positive and
-negative forms (such as -foption and -fno-option), relevant entries in
-the manual are indexed under the most appropriate form; it may sometimes
-be useful to look up both forms.
-
-@printindex op
-
-@node Keyword Index
-@unnumbered Keyword Index
-
-@printindex cp
-
-@bye
diff --git a/gcc/lang-specs.h b/gcc/lang-specs.h
deleted file mode 100644
index ac3611d..0000000
--- a/gcc/lang-specs.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/* GCC driver specs for Elna frontend.
- 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
-. */
-
-/* gcc/gcc.cc */
-{".elna", "@elna", nullptr, 0, 0},
-{"@elna",
- "elna1 %i \
- %{!Q:-quiet} " DUMPS_OPTIONS("") " %{m*} %{aux-info*} \
- %{g*} %{O*} %{W*&pedantic*} %{w} %{std*&ansi&trigraphs} \
- %{pg:-p} %{p} %{f*} %{undef} \
- %{!fsyntax-only:%{S:%W{o*}%{!o*:-o %w%b.s}}} \
- %{fsyntax-only:-o %j} %{-param*} \
- %{!fsyntax-only:%(invoke_as)}",
- nullptr, 0, 0},
diff --git a/gcc/lang.opt b/gcc/lang.opt
deleted file mode 100644
index 1c8c95c..0000000
--- a/gcc/lang.opt
+++ /dev/null
@@ -1,23 +0,0 @@
-; lang.opt -- Options for the Elna front end.
-; 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
-; .
-
-; See the GCC internals manual for a description of this file's format.
-
-; Please try to keep this file in ASCII collating order.
-
-Language
-Elna
diff --git a/gcc/lang.opt.urls b/gcc/lang.opt.urls
deleted file mode 100644
index a383952..0000000
--- a/gcc/lang.opt.urls
+++ /dev/null
@@ -1,2 +0,0 @@
-; Autogenerated by regenerate-opt-urls.py from gcc/lang.opt and generated HTML
-
diff --git a/include/elna/gcc/elna-builtins.h b/include/elna/gcc/elna-builtins.h
deleted file mode 100644
index 60baab7..0000000
--- a/include/elna/gcc/elna-builtins.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/* 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
-
-#include "config.h"
-#include "system.h"
-#include "coretypes.h"
-#include "tree.h"
-#include "tree-iterator.h"
-
-#include "elna/gcc/elna-tree.h"
-
-namespace elna::gcc
-{
- void init_ttree();
- std::shared_ptr builtin_symbol_table();
-
- void rewrite_symbol_table(std::shared_ptr info_table, std::shared_ptr symbols);
- tree handle_symbol(const std::string& symbol_name, std::shared_ptr reference,
- std::shared_ptr symbols);
- tree get_inner_alias(const frontend::type& type, std::shared_ptr symbols);
- void declare_procedure(const std::string& name, const frontend::procedure_info& info,
- std::shared_ptr symbols);
- tree declare_variable(const std::string& name, const frontend::variable_info& info,
- std::shared_ptr symbols);
-}
diff --git a/include/elna/gcc/elna-diagnostic.h b/include/elna/gcc/elna-diagnostic.h
deleted file mode 100644
index 83f768e..0000000
--- a/include/elna/gcc/elna-diagnostic.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/* Elna frontend specific diagnostic 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
-. */
-
-#pragma once
-
-#include "config.h"
-#include "system.h"
-#include "coretypes.h"
-#include "input.h"
-#include "tree.h"
-#include "diagnostic.h"
-
-#include
-#include
-
-#include "elna/frontend/result.h"
-
-namespace elna::gcc
-{
- struct linemap_guard
- {
- explicit linemap_guard(const char *filename);
- linemap_guard(const linemap_guard&) = delete;
- linemap_guard(linemap_guard&&) = delete;
-
- ~linemap_guard();
- };
-
- location_t get_location(const frontend::position *position);
- std::string print_type(tree type);
- void report_errors(const std::deque>& errors);
-}
diff --git a/include/elna/gcc/elna-generic.h b/include/elna/gcc/elna-generic.h
deleted file mode 100644
index 97cd512..0000000
--- a/include/elna/gcc/elna-generic.h
+++ /dev/null
@@ -1,97 +0,0 @@
-/* Visitor generating a GENERIC tree.
- 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
-. */
-
-#pragma once
-
-#include "elna/frontend/ast.h"
-#include "elna/frontend/symbol.h"
-#include "elna/frontend/semantic.h"
-#include "elna/gcc/elna-tree.h"
-
-#include "config.h"
-#include "system.h"
-#include "coretypes.h"
-#include "tree.h"
-#include "tree-iterator.h"
-
-#include
-#include
-
-namespace elna::gcc
-{
- class generic_visitor final : public frontend::empty_visitor
- {
- tree current_expression{ NULL_TREE };
- elna::frontend::symbol_bag bag;
- std::shared_ptr symbols;
-
- void enter_scope();
- tree leave_scope();
-
- void make_if_branch(frontend::conditional_statements& branch, tree goto_endif);
-
- tree build_arithmetic_operation(frontend::binary_expression *expression,
- tree_code operator_code, tree left, tree right);
- tree build_comparison_operation(frontend::binary_expression *expression,
- tree_code operator_code, tree left, tree right);
- tree build_bit_logic_operation(frontend::binary_expression *expression, tree left, tree right);
- tree build_equality_operation(frontend::binary_expression *expression, tree left, tree right);
- void build_procedure_call(location_t call_location,
- tree procedure_address, const std::vector& arguments);
- void build_record_call(location_t call_location,
- tree symbol, const std::vector& arguments);
- bool build_builtin_procedures(frontend::procedure_call *call);
- void build_assert_builtin(location_t call_location, const std::vector& arguments);
-
- bool expect_trait_type_only(frontend::traits_expression *trait);
- bool expect_trait_for_integral_type(frontend::traits_expression *trait);
- void visit_statements(const std::vector& statements);
- bool assert_constant(location_t expression_location);
-
- public:
- generic_visitor(std::shared_ptr symbol_table, elna::frontend::symbol_bag bag);
-
- void visit(frontend::program *program) override;
- void visit(frontend::procedure_declaration *definition) override;
- void visit(frontend::procedure_call *call) override;
- void visit(frontend::cast_expression *expression) override;
- void visit(frontend::traits_expression *trait) override;
- void visit(frontend::literal *literal) override;
- void visit(frontend::literal *literal) override;
- void visit(frontend::literal *literal) override;
- void visit(frontend::literal *boolean) override;
- void visit(frontend::literal *character) override;
- void visit(frontend::literal *) override;
- void visit(frontend::literal *string) override;
- void visit(frontend::binary_expression *expression) override;
- void visit(frontend::unary_expression *expression) override;
- void visit(frontend::constant_declaration *definition) override;
- void visit(frontend::variable_declaration *declaration) override;
- void visit(frontend::variable_expression *expression) override;
- void visit(frontend::array_access_expression *expression) override;
- void visit(frontend::field_access_expression *expression) override;
- void visit(frontend::dereference_expression *expression) override;
- void visit(frontend::unit *unit) override;
- void visit(frontend::assign_statement *statement) override;
- void visit(frontend::if_statement *statement) override;
- void visit(frontend::import_declaration *) override;
- void visit(frontend::while_statement *statement) override;
- void visit(frontend::return_statement *statement) override;
- void visit(frontend::defer_statement *statement) override;
- void visit(frontend::case_statement *statement) override;
- };
-}
diff --git a/include/elna/gcc/elna-tree.h b/include/elna/gcc/elna-tree.h
deleted file mode 100644
index 48dfeb5..0000000
--- a/include/elna/gcc/elna-tree.h
+++ /dev/null
@@ -1,105 +0,0 @@
-/* Utilities to manipulate GCC trees.
- 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
-. */
-
-#pragma once
-
-#include
-
-#include "config.h"
-#include "system.h"
-#include "coretypes.h"
-#include "tree.h"
-#include "tree-iterator.h"
-#include "stringpool.h"
-#include "fold-const.h"
-
-#include "elna/frontend/ast.h"
-#include "elna/frontend/symbol.h"
-#include "elna/gcc/elna1.h"
-
-namespace elna::gcc
-{
- using symbol_table = frontend::symbol_map;
-
- bool is_integral_type(tree type);
- bool is_numeric_type(tree type);
- bool is_unique_type(tree type);
- bool is_void_type(tree type);
-
- /**
- * \param type The type to evaluate.
- * \return Whether this type can be converted to another type.
- */
- bool is_castable_type(tree type);
-
- /**
- * \param lhs Left hand value.
- * \param rhs Right hand value.
- * \return Whether rhs can be assigned to lhs.
- */
- bool are_compatible_pointers(tree lhs_type, tree rhs);
-
- /**
- * Prepares a value to be bound to a variable or parameter.
- *
- * If rvalue is a procedure declaration, builds a procedure pointer.
- *
- * \param rvalue Value to be assigned.
- * \return Processed value.
- */
- tree prepare_rvalue(tree rvalue);
-
- /**
- * \param assignee Assignee.
- * \param assignee Assignment.
- * \return Whether an expression assignment can be assigned to a variable of type assignee.
- */
- bool is_assignable_from(tree assignee, tree assignment);
-
- void append_statement(tree statement_tree);
- void defer(tree statement_tree);
- tree chain_defer();
-
- tree do_pointer_arithmetic(frontend::binary_operator binary_operator,
- tree left, tree right, location_t expression_location);
- tree build_binary_operation(bool condition, frontend::binary_expression *expression,
- tree_code operator_code, tree left, tree right, tree target_type);
- tree build_arithmetic_operation(frontend::binary_expression *expression,
- tree_code operator_code, tree left, tree right);
- tree build_field(location_t location, tree record_type, const std::string name, tree type);
- tree find_field_by_name(location_t expression_location, tree type, const std::string& field_name);
- tree build_global_pointer_type(tree type);
- tree build_static_array_type(tree type, const std::uint64_t size);
- tree build_enumeration_type(const std::vector& members);
- tree build_label_decl(const char *name, location_t loc);
-
- tree extract_constant(tree expression);
-
- template
- tree call_built_in(location_t call_location, const char *name, tree return_type, Args... arguments)
- {
- tree *builtin = elna_global_decls->get(name);
- gcc_assert(builtin != nullptr);
-
- tree fndecl_type = build_function_type(return_type, TYPE_ARG_TYPES(*builtin));
- tree builtin_addr = build1_loc(call_location, ADDR_EXPR, build_pointer_type(fndecl_type), *builtin);
-
- tree argument_trees[sizeof...(Args)] = {arguments...};
-
- return fold_build_call_array(return_type, builtin_addr, sizeof...(Args), argument_trees);
- }
-}
diff --git a/include/elna/gcc/elna1.h b/include/elna/gcc/elna1.h
deleted file mode 100644
index 91d0e6f..0000000
--- a/include/elna/gcc/elna1.h
+++ /dev/null
@@ -1,94 +0,0 @@
-/* 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
-. */
-
-#pragma once
-
-enum elna_tree_index
-{
- ELNA_TI_INT_TYPE,
- ELNA_TI_WORD_TYPE,
- ELNA_TI_CHAR_TYPE,
- ELNA_TI_BOOL_TYPE,
- ELNA_TI_POINTER_TYPE,
- ELNA_TI_FLOAT_TYPE,
- ELNA_TI_STRING_TYPE,
- ELNA_TI_BOOL_TRUE,
- ELNA_TI_BOOL_FALSE,
- ELNA_TI_POINTER_NIL,
- ELNA_TI_STRING_PTR_FIELD,
- ELNA_TI_STRING_LENGTH_FIELD,
- ELNA_TI_MAX
-};
-
-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]
-#define elna_char_type_node elna_global_trees[ELNA_TI_CHAR_TYPE]
-#define elna_bool_type_node elna_global_trees[ELNA_TI_BOOL_TYPE]
-#define elna_pointer_type_node elna_global_trees[ELNA_TI_POINTER_TYPE]
-#define elna_float_type_node elna_global_trees[ELNA_TI_FLOAT_TYPE]
-#define elna_string_type_node elna_global_trees[ELNA_TI_STRING_TYPE]
-#define elna_bool_true_node elna_global_trees[ELNA_TI_BOOL_TRUE]
-#define elna_bool_false_node elna_global_trees[ELNA_TI_BOOL_FALSE]
-#define elna_pointer_nil_node elna_global_trees[ELNA_TI_POINTER_NIL]
-#define elna_string_ptr_field_node elna_global_trees[ELNA_TI_STRING_PTR_FIELD]
-#define elna_string_length_field_node elna_global_trees[ELNA_TI_STRING_LENGTH_FIELD]
-
-/* Language-dependent contents of a type. */
-struct GTY (()) lang_type
-{
-};
-
-/* Language-dependent contents of a decl. */
-struct GTY (()) lang_decl
-{
-};
-
-struct GTY (()) defer_scope
-{
- 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
-#define f_names DECL_STRUCT_FUNCTION(current_function_decl)->language->names
diff --git a/rakelib/gcc.rake b/rakelib/gcc.rake
deleted file mode 100644
index 39b4442..0000000
--- a/rakelib/gcc.rake
+++ /dev/null
@@ -1,113 +0,0 @@
-# This Source Code Form is subject to the terms of the Mozilla Public License,
-# v. 2.0. If a copy of the MPL was not distributed with this file, You can
-# obtain one at https://mozilla.org/MPL/2.0/. -}
-# frozen_string_literal: true
-
-require 'uri'
-require 'net/http'
-require 'open3'
-require 'pathname'
-
-def gcc_verbose(gcc_binary)
- read, write = IO.pipe
- sh({'LANG' => 'C'}, gcc_binary, '--verbose', err: write)
- write.close
- output = read.read
- read.close
- output
-end
-
-def find_build_target
- gcc_verbose(ENV.fetch 'CC', 'gcc')
- .lines
- .find { |line| line.start_with? 'Target: ' }
- .split(' ')
- .last
- .strip
-end
-
-def download_and_pipe(url, target, command)
- target.mkpath
-
- Net::HTTP.start(url.host, url.port, use_ssl: url.scheme == 'https') do |http|
- request = Net::HTTP::Get.new url.request_uri
-
- http.request request do |response|
- case response
- when Net::HTTPRedirection
- download_and_pipe URI.parse(response['location']), target, command
- when Net::HTTPSuccess
- Dir.chdir target.to_path do
- Open3.popen2(*command) do |stdin, stdout, wait_thread|
- Thread.new do
- stdout.each { |line| puts line }
- end
-
- response.read_body do |chunk|
- stdin.write chunk
- end
- stdin.close
-
- wait_thread.value
- end
- end
- else
- response.error!
- end
- end
- end
-end
-
-namespace :gcc do
- # Dependencies.
- GCC_VERSION = "15.2.0"
- HOST_GCC = 'build/host/gcc'
- HOST_INSTALL = 'build/host/install'
- GCC_PATCH = 'https://raw.githubusercontent.com/Homebrew/formula-patches/575ffcaed6d3112916fed77d271dd3799a7255c4/gcc/gcc-15.1.0.diff'
-
- directory HOST_GCC
- directory HOST_INSTALL
- directory 'build/tools'
-
- desc 'Download and configure the bootstrap compiler'
- task configure: ['build/tools', HOST_GCC, HOST_INSTALL] do
- url = URI.parse "https://gcc.gnu.org/pub/gcc/releases/gcc-#{GCC_VERSION}/gcc-#{GCC_VERSION}.tar.xz"
- build_target = find_build_target
- source_directory = Pathname.new "build/tools/gcc-#{GCC_VERSION}"
- frontend_link = source_directory + 'gcc'
-
- download_and_pipe url, source_directory.dirname, ['tar', '-Jxv']
- download_and_pipe URI.parse(GCC_PATCH), source_directory, ['patch', '-p1']
-
- sh 'contrib/download_prerequisites', chdir: source_directory.to_path
- File.symlink Pathname.new('.').relative_path_from(frontend_link), (frontend_link + 'elna')
-
- configure_options = [
- "--prefix=#{File.realpath HOST_INSTALL}",
- '--enable-languages=c,c++,elna',
- '--disable-bootstrap',
- '--disable-multilib',
- '--with-system-zlib',
- "--target=#{build_target}",
- "--build=#{build_target}",
- "--host=#{build_target}"
- ]
- if File.symlink? '/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk'
- configure_options << '--with-sysroot=/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk'
- end
- env = ENV.slice 'CC', 'CXX'
- env['CFLAGS'] = env['CXXFLAGS'] = '-O0 -g -fPIC -I/opt/homebrew/opt/flex/include'
-
- configure = source_directory.relative_path_from(HOST_GCC) + 'configure'
- sh env, configure.to_path, *configure_options, chdir: HOST_GCC
- end
-
- desc 'Make and install the bootstrap compiler'
- task :make do
- sh 'make', '-j', Etc.nprocessors.to_s, chdir: HOST_GCC
- sh 'make', 'install', chdir: HOST_GCC
- end
-end
-
-desc 'Build the bootstrap compiler'
-task gcc: %w[gcc:configure gcc:make]
diff --git a/rakelib/modula.rake b/rakelib/modula.rake
deleted file mode 100644
index 746ebb8..0000000
--- a/rakelib/modula.rake
+++ /dev/null
@@ -1,36 +0,0 @@
-# This Source Code Form is subject to the terms of the Mozilla Public License,
-# v. 2.0. If a copy of the MPL was not distributed with this file, You can
-# obtain one at https://mozilla.org/MPL/2.0/. -}
-# frozen_string_literal: true
-
-require 'pathname'
-require 'rake/clean'
-
-CLEAN.include 'build/gcc'
-
-task source: ['source/main.elna', 'build/gcc/elna'] do |t|
- sources, compiler = t.prerequisites.partition { |f| f.end_with? '.elna' }
-
- sh *compiler, '--parse', *sources
-end
-
-rule(/gcc\/.+\.o$/ => ->(file) {
- source = Pathname.new('source') +
- Pathname.new(file).relative_path_from('build/gcc').sub_ext('.elna')
-
- ['build/host/install/bin/gelna', source]
-}) do |t|
- Pathname.new(t.name).dirname.mkpath
- sources, compiler = t.prerequisites.partition { |source| source.end_with? '.elna' }
-
- sh *compiler, '-c', '-O0', '-g', '-o', t.name, *sources
-end
-
-file 'build/gcc/elna' => FileList['source/**/*.elna'].reject { |file|
- file != file.downcase
-}.map { |file|
- Pathname.new('build/gcc') +
- Pathname.new(file).relative_path_from('source').sub_ext('.o')
-} do |t|
- sh 'build/host/install/bin/gcc', '-o', t.name, *t.prerequisites
-end