Remove GCC glue code

This commit is contained in:
2026-02-01 19:01:06 +01:00
parent a00f0d57b8
commit 39197fe88a
22 changed files with 2 additions and 3314 deletions

View File

@@ -21,6 +21,8 @@ def run(exe)
ENV.fetch('QEMU', '').split << exe ENV.fetch('QEMU', '').split << exe
end end
directory 'build'
task default: :boot task default: :boot
desc 'Final stage' desc 'Final stage'

View File

@@ -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
# <http://www.gnu.org/licenses/>.
language="elna"
gcc_subdir="elna/gcc"
. ${srcdir}/elna/gcc/config-lang.in

View File

@@ -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
# <http://www.gnu.org/licenses/>.
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 $@ $<

View File

@@ -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`.

View File

@@ -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
# <http://www.gnu.org/licenses/>.
# 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"

View File

@@ -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
<http://www.gnu.org/licenses/>. */
#include <algorithm>
#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> 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<symbol_table> builtin_symbol_table()
{
std::shared_ptr<elna::gcc::symbol_table> symbol_table = std::make_shared<elna::gcc::symbol_table>();
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<frontend::type_field>& fields, tree composite_type_node,
std::shared_ptr<symbol_table> 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<symbol_table> symbols)
{
std::vector<tree> 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<symbol_table> symbols)
{
if (auto reference = type.get<frontend::primitive_type>())
{
auto looked_up = symbols->lookup(reference->identifier);
gcc_assert(looked_up != NULL_TREE);
return TREE_TYPE(looked_up);
}
else if (auto reference = type.get<frontend::record_type>())
{
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<frontend::union_type>())
{
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<frontend::enumeration_type>())
{
return build_enumeration_type(reference->members);
}
else if (auto reference = type.get<frontend::pointer_type>())
{
return build_global_pointer_type(get_inner_alias(reference->base, symbols));
}
else if (auto reference = type.get<frontend::array_type>())
{
tree base = get_inner_alias(reference->base, symbols);
return build_static_array_type(base, reference->size);
}
else if (auto reference = type.get<frontend::procedure_type>())
{
auto procedure = build_procedure_type(*reference, symbols);
return build_global_pointer_type(procedure);
}
else if (auto reference = type.get<frontend::alias_type>())
{
return TREE_TYPE(handle_symbol(reference->name, reference, symbols));
}
return error_mark_node;
}
tree handle_symbol(const std::string& symbol_name, std::shared_ptr<frontend::alias_type> reference,
std::shared_ptr<symbol_table> 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<symbol_table> 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(&parameter_type, declaration_type);
std::vector<std::string>::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(&parameter_type));
DECL_CONTEXT(declaration_tree) = fndecl;
DECL_ARG_TYPE(declaration_tree) = function_args_iter_cond(&parameter_type);
argument_chain = chainon(argument_chain, declaration_tree);
function_args_iter_next(&parameter_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<symbol_table> 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<symbol_table> symbols)
{
// The top level symbol table has basic (builtin) types in it which are not aliases.
if (auto alias_type = info.symbol.get<frontend::alias_type>())
{
tree type_declaration = handle_symbol(name, alias_type, symbols);
TREE_PUBLIC(type_declaration) = info.exported;
}
}
void rewrite_symbol_table(std::shared_ptr<frontend::symbol_table> info_table, std::shared_ptr<symbol_table> 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);
}
}
}
}

View File

@@ -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
<http://www.gnu.org/licenses/>. */
#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 "<<unknown-type>>";
}
gcc_unreachable();
}
void report_errors(const std::deque<std::unique_ptr<frontend::error>>& 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());
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -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
<http://www.gnu.org/licenses/>. */
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;

View File

@@ -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
<http://www.gnu.org/licenses/>. */
#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<std::string>& 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;
}
}

View File

@@ -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
<http://www.gnu.org/licenses/>. */
#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 <fstream>
#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<nofree_string_hash, tree> *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<nofree_string_hash, tree>::create_ggc(default_hash_map_size);
build_common_builtin_nodes();
return true;
}
using dependency_state = elna::frontend::dependency_state<std::shared_ptr<elna::gcc::symbol_table>>;
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<std::filesystem::path, elna::frontend::symbol_bag>::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"

View File

@@ -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

View File

@@ -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
<http://www.gnu.org/licenses/>. */
/* 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},

View File

@@ -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
; <http://www.gnu.org/licenses/>.
; 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

View File

@@ -1,2 +0,0 @@
; Autogenerated by regenerate-opt-urls.py from gcc/lang.opt and generated HTML

View File

@@ -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
<http://www.gnu.org/licenses/>. */
#include <memory>
#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<symbol_table> builtin_symbol_table();
void rewrite_symbol_table(std::shared_ptr<frontend::symbol_table> info_table, std::shared_ptr<symbol_table> symbols);
tree handle_symbol(const std::string& symbol_name, std::shared_ptr<frontend::alias_type> reference,
std::shared_ptr<symbol_table> symbols);
tree get_inner_alias(const frontend::type& type, std::shared_ptr<symbol_table> symbols);
void declare_procedure(const std::string& name, const frontend::procedure_info& info,
std::shared_ptr<symbol_table> symbols);
tree declare_variable(const std::string& name, const frontend::variable_info& info,
std::shared_ptr<symbol_table> symbols);
}

View File

@@ -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
<http://www.gnu.org/licenses/>. */
#pragma once
#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "input.h"
#include "tree.h"
#include "diagnostic.h"
#include <deque>
#include <memory>
#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<std::unique_ptr<frontend::error>>& errors);
}

View File

@@ -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
<http://www.gnu.org/licenses/>. */
#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 <string>
#include <forward_list>
namespace elna::gcc
{
class generic_visitor final : public frontend::empty_visitor
{
tree current_expression{ NULL_TREE };
elna::frontend::symbol_bag bag;
std::shared_ptr<symbol_table> 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<frontend::expression *>& arguments);
void build_record_call(location_t call_location,
tree symbol, const std::vector<frontend::expression *>& arguments);
bool build_builtin_procedures(frontend::procedure_call *call);
void build_assert_builtin(location_t call_location, const std::vector<frontend::expression *>& 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<frontend::statement *>& statements);
bool assert_constant(location_t expression_location);
public:
generic_visitor(std::shared_ptr<symbol_table> 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<std::int32_t> *literal) override;
void visit(frontend::literal<std::uint32_t> *literal) override;
void visit(frontend::literal<double> *literal) override;
void visit(frontend::literal<bool> *boolean) override;
void visit(frontend::literal<unsigned char> *character) override;
void visit(frontend::literal<std::nullptr_t> *) override;
void visit(frontend::literal<std::string> *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;
};
}

View File

@@ -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
<http://www.gnu.org/licenses/>. */
#pragma once
#include <forward_list>
#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<tree, tree, NULL_TREE>;
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<std::string>& members);
tree build_label_decl(const char *name, location_t loc);
tree extract_constant(tree expression);
template<typename... Args>
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);
}
}

View File

@@ -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
<http://www.gnu.org/licenses/>. */
#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<nofree_string_hash, tree> *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<defer_scope, va_gc> *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

View File

@@ -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]

View File

@@ -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