aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/Make-lang.in1
-rw-r--r--gcc/gcc/elna-module-loader.cc102
-rw-r--r--gcc/gcc/elna1.cc102
3 files changed, 107 insertions, 98 deletions
diff --git a/gcc/Make-lang.in b/gcc/Make-lang.in
index bf1893d..b9d8b5e 100644
--- a/gcc/Make-lang.in
+++ b/gcc/Make-lang.in
@@ -47,6 +47,7 @@ elna_OBJS = \
elna/elna-diagnostic.o \
elna/elna-tree.o \
elna/elna-builtins.o \
+ elna/elna-module-loader.o \
elna/ast.o \
elna/evaluator.o \
elna/dependency.o \
diff --git a/gcc/gcc/elna-module-loader.cc b/gcc/gcc/elna-module-loader.cc
new file mode 100644
index 0000000..1dd7596
--- /dev/null
+++ b/gcc/gcc/elna-module-loader.cc
@@ -0,0 +1,102 @@
+/* Module loading glue between the boot pipeline and the GCC driver.
+ 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-module-loader.h"
+
+#include <fstream>
+
+#include "elna/gcc/elna-builtins.h"
+#include "elna/gcc/elna-diagnostic.h"
+#include "elna/gcc/elna-generic.h"
+
+namespace elna::gcc
+{
+ std::vector<std::string> elna_include_dirs;
+
+ module_loader::module_loader(const std::shared_ptr<symbol_table>& symbols)
+ : symbols(symbols)
+ {
+ }
+
+ std::filesystem::path module_loader::resolve(const std::filesystem::path& relative,
+ const boot::source_position& position)
+ {
+ std::vector<std::filesystem::path> found;
+
+ for (const auto& include_path : elna_include_dirs)
+ {
+ std::filesystem::path full_path = include_path / relative;
+
+ if (std::filesystem::exists(full_path))
+ {
+ found.push_back(std::move(full_path));
+ }
+ }
+ if (found.empty())
+ {
+ return relative;
+ }
+ if (found.size() > 1)
+ {
+ const location_t gcc_location = get_location(&position);
+ error_at(gcc_location, "Module %s was found in more than one include path",
+ relative.native().c_str());
+ }
+ return std::filesystem::weakly_canonical(found.front());
+ }
+
+ boot::dependency module_loader::read(const std::filesystem::path& key)
+ {
+ std::ifstream entry_point{ key, std::ios::in };
+
+ if (!entry_point)
+ {
+ fatal_error(UNKNOWN_LOCATION, "Cannot open filename %s: %m", key.native().c_str());
+ }
+ const linemap_guard guard(key);
+ return boot::read_source(entry_point, get_host_target());
+ }
+
+ void module_loader::finalize(const std::filesystem::path&,
+ const std::shared_ptr<boot::symbol_table>& module_scope) const
+ {
+ rewrite_symbol_table(module_scope, this->symbols);
+ }
+
+ void compile_files(const char *const *filenames, unsigned int count)
+ {
+ const boot::target_info target = get_host_target();
+ boot::dependency_state<std::shared_ptr<symbol_table>> state{ builtin_symbol_table(), target };
+ module_loader loader{ state.custom };
+
+ for (unsigned int i = 0; i < count; i++)
+ {
+ const std::filesystem::path key = std::filesystem::weakly_canonical(filenames[i]);
+ boot::dependency result = state.compile(key, loader, target);
+
+ report_errors(result.errors);
+
+ if (result.value != nullptr)
+ {
+ linemap_add(line_table, LC_ENTER, 0, key.native().c_str(), 1);
+ generic_visitor visitor{ state.custom, state.find(key)->second, target };
+ result.value->accept(&visitor);
+ linemap_add(line_table, LC_LEAVE, 0, nullptr, 0);
+ }
+ }
+ }
+}
diff --git a/gcc/gcc/elna1.cc b/gcc/gcc/elna1.cc
index 180c839..2c43178 100644
--- a/gcc/gcc/elna1.cc
+++ b/gcc/gcc/elna1.cc
@@ -15,13 +15,9 @@ 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 <fstream>
-
-#include "elna/gcc/elna-diagnostic.h"
-#include "elna/boot/dependency.h"
-#include "elna/gcc/elna-tree.h"
-#include "elna/gcc/elna-generic.h"
+#include "elna/gcc/elna-module-loader.h"
#include "elna/gcc/elna-builtins.h"
+#include "elna/gcc/elna-tree.h"
#include "config.h"
#include "system.h"
@@ -38,7 +34,6 @@ along with GCC; see the file COPYING3. If not see
tree elna_global_trees[ELNA_TI_MAX];
hash_map<nofree_string_hash, tree> *elna_global_decls = nullptr;
-std::vector<std::string> elna_include_dirs;
/* The resulting tree type. */
@@ -64,98 +59,9 @@ static bool elna_langhook_init()
return true;
}
-using dependency_state = elna::boot::dependency_state<std::shared_ptr<elna::gcc::symbol_table>>;
-
-static std::vector<std::filesystem::path> find_module(const elna::boot::import_declaration* declaration)
-{
- std::filesystem::path relative_path = elna::boot::build_path(declaration->segments);
- std::vector<std::filesystem::path> found;
-
- for (const auto& include_path : elna_include_dirs)
- {
- std::filesystem::path full_path = include_path / relative_path;
-
- if (std::filesystem::exists(full_path))
- {
- found.push_back(std::move(full_path));
- }
- }
- if (found.empty())
- {
- found.push_back(std::move(relative_path));
- }
- else if (found.size() > 1)
- {
- const location_t gcc_location = elna::gcc::get_location(&declaration->position());
- error_at(gcc_location, "Module %s was found in more than one include path",
- relative_path.native().c_str());
- }
- return found;
-}
-
-static elna::boot::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);
- }
- const elna::gcc::linemap_guard guard(filename);
- elna::boot::dependency outcome = elna::boot::read_source(entry_point,
- elna::gcc::get_host_target());
-
- elna::boot::symbol_bag outcome_bag{ std::move(outcome.unresolved), state.globals };
-
- if (!outcome.has_errors())
- {
- for (const elna::boot::import_declaration* sub_tree : outcome.tree->imports)
- {
- const std::filesystem::path sub_path = find_module(sub_tree)[0];
- dependency_state::const_iterator cached_import = state.find(sub_path);
-
- if (cached_import == std::cend(state))
- {
- const char *filename_pointer = ggc_strdup(sub_path.native().c_str());
-
- elna_parse_file(state, filename_pointer);
- cached_import = state.find(sub_path);
- }
- if (cached_import != std::cend(state))
- {
- outcome_bag.add_import(cached_import->second);
- }
- }
- outcome.errors() = analyze_semantics(outcome.tree, outcome_bag, elna::gcc::get_host_target());
- }
- if (outcome.has_errors())
- {
- elna::gcc::report_errors(outcome.errors());
- }
- state.insert(filename, outcome_bag);
- elna::gcc::rewrite_symbol_table(outcome_bag.leave(), state.custom);
-
- return outcome;
-}
-
static void elna_langhook_parse_file()
{
- elna::boot::target_info target = elna::gcc::get_host_target();
- dependency_state state{ elna::gcc::builtin_symbol_table(), target };
-
- for (unsigned int i = 0; i < num_in_fnames; i++)
- {
- elna::boot::dependency outcome = elna_parse_file(state, in_fnames[i]);
-
- if (!outcome.has_errors())
- {
- linemap_add(line_table, LC_ENTER, 0, in_fnames[i], 1);
- elna::gcc::generic_visitor generic_visitor{ state.custom,
- state.find(in_fnames[i])->second, target };
- outcome.tree->accept(&generic_visitor);
- linemap_add(line_table, LC_LEAVE, 0, nullptr, 0);
- }
- }
+ elna::gcc::compile_files(in_fnames, num_in_fnames);
}
static tree elna_langhook_type_for_mode(enum machine_mode mode, int unsignedp)
@@ -259,7 +165,7 @@ static bool elna_langhook_handle_option(
switch (static_cast<opt_code>(scode))
{
case OPT_I:
- elna_include_dirs.emplace_back(arg);
+ elna::gcc::elna_include_dirs.emplace_back(arg);
return true;
default:
return true;