diff options
| author | Eugen Wissner <belka@caraus.de> | 2025-12-02 10:22:06 +0100 |
|---|---|---|
| committer | Eugen Wissner <belka@caraus.de> | 2025-12-02 17:14:18 +0100 |
| commit | 23b6f074c7f560d701e9a1fa5713a965af3a18a3 (patch) | |
| tree | 87549a4eba3da8d8ed6e3fbb2e337e152a8bc96a /gcc/elna1.cc | |
| parent | 5f7d83974114c73327ce9fff3635927df050b5e4 (diff) | |
| download | elna-23b6f074c7f560d701e9a1fa5713a965af3a18a3.tar.gz | |
Merge GCC frontend into the branch
Diffstat (limited to 'gcc/elna1.cc')
| -rw-r--r-- | gcc/elna1.cc | 256 |
1 files changed, 256 insertions, 0 deletions
diff --git a/gcc/elna1.cc b/gcc/elna1.cc new file mode 100644 index 0000000..448a24c --- /dev/null +++ b/gcc/elna1.cc @@ -0,0 +1,256 @@ +/* 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" |
