diff options
| author | Eugen Wissner <belka@caraus.de> | 2026-08-25 23:41:18 +0200 |
|---|---|---|
| committer | Eugen Wissner <belka@caraus.de> | 2026-08-25 23:41:18 +0200 |
| commit | 81370291c039593a9886c7b3f776ca55a2858f0d (patch) | |
| tree | 47e12c5263e7784d3f0fc75fbbf6d791291e2230 /gcc | |
| parent | df51f9c4ee0ee4ac22206513bcd60e6928b7eaeb (diff) | |
| download | elna-81370291c039593a9886c7b3f776ca55a2858f0d.tar.gz | |
Reject circular imports
Diffstat (limited to 'gcc')
| -rw-r--r-- | gcc/Make-lang.in | 1 | ||||
| -rw-r--r-- | gcc/gcc/elna-module-loader.cc | 102 | ||||
| -rw-r--r-- | gcc/gcc/elna1.cc | 102 |
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; |
