diff options
Diffstat (limited to 'gcc/rust/rust-session-manager.h')
-rw-r--r-- | gcc/rust/rust-session-manager.h | 358 |
1 files changed, 358 insertions, 0 deletions
diff --git a/gcc/rust/rust-session-manager.h b/gcc/rust/rust-session-manager.h new file mode 100644 index 0000000..99dd107 --- /dev/null +++ b/gcc/rust/rust-session-manager.h @@ -0,0 +1,358 @@ +// Copyright (C) 2020-2022 Free Software Foundation, Inc. + +// This file is part of GCC. + +// 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 "rust-session-manager.h" + +#ifndef RUST_SESSION_MANAGER_H +#define RUST_SESSION_MANAGER_H + +#include "rust-linemap.h" +#include "rust-backend.h" +#include "rust-hir-map.h" +#include "safe-ctype.h" + +#include "config.h" +#include "rust-system.h" +#include "coretypes.h" +#include "options.h" + +namespace Rust { +// parser forward decl +template <typename ManagedTokenSource> class Parser; +class Lexer; +// crate forward decl +namespace AST { +struct Crate; +} +// crate forward decl +namespace HIR { +struct Crate; +} + +/* Data related to target, most useful for conditional compilation and + * whatever. */ +struct TargetOptions +{ + /* TODO: maybe make private and access through helpers to allow changes to + * impl */ + std::unordered_map<std::string, std::unordered_set<std::string> > features; + +public: + // Returns whether a key is defined in the feature set. + bool has_key (std::string key) const + { + return features.find (key) != features.end (); + } + + // Returns whether a key exists with the given value in the feature set. + bool has_key_value_pair (std::string key, std::string value) const + { + auto it = features.find (key); + if (it != features.end ()) + { + auto set = it->second; + auto it2 = set.find (value); + if (it2 != set.end ()) + return true; + } + return false; + } + + /* Returns the singular value from the key, or if the key has multiple, an + * empty string. */ + std::string get_singular_value (std::string key) const + { + auto it = features.find (key); + if (it != features.end ()) + { + auto set = it->second; + if (set.size () == 1) + return *set.begin (); + } + return ""; + } + + /* Returns all values associated with a key (including none), or an empty + * set if no key is found. */ + std::unordered_set<std::string> get_values_for_key (std::string key) const + { + auto it = features.find (key); + if (it != features.end ()) + return it->second; + return {}; + } + + /* Inserts a key (no value) into the feature set. This will do nothing if + * the key already exists. This returns whether the insertion was successful + * (i.e. whether key already existed). */ + bool insert_key (std::string key) + { + return features + .insert (std::make_pair (key, std::unordered_set<std::string> ())) + .second; + } + + // Inserts a key-value pair into the feature set. + void insert_key_value_pair (std::string key, std::string value) + { + auto existing_set = get_values_for_key (key); + existing_set.insert (std::move (value)); + features[std::move (key)] = std::move (existing_set); + } + + // Dump all target options to stderr. + void dump_target_options () const; + + /* Creates derived values and implicit enables after all target info is + * added (e.g. "unix"). */ + void init_derived_values (); + + /* Enables all requirements for the feature given, and will enable feature + * itself if not enabled. */ + void enable_implicit_feature_reqs (std::string feature); + + /* According to reference, Rust uses either multi-map key-values or just + * values (although values may be aliases for a key-value value). This seems + * like overkill. Thus, depending on whether the attributes used in cfg are + * fixed or not, I think I'll either put each non-multimap "key-value" as a + * separate field and have the multimap "key-values" in a regular map for + * that one key, or actually use a multimap. + * + * rustc itself uses a set of key-value tuples where the second tuple + * element is optional. This gets rid of the requirement to make a + * multi-map, I guess, but seems like it might make search slow (unless all + * "is defined"-only ones have empty string as second element). */ + /* cfg attributes: + * - target_arch: single value + * - target_feature: multiple values possible + * - target_os: single value + * - target_family: single value (or no value?) + * - unix: set when target_family = "unix" + * - windows: set when target_family = "windows" + * - if these are just syntactic sugar, then maybe have a separate set or + * map for this kind of stuff + * - target_env: set when needed for disambiguation about ABI - usually + * empty string for GNU, complicated + * - seems to be a single value (if any) + * - target_endian: single value; "little" or "big" + * - target_pointer_width: single value, "32" for 32-bit pointers, etc. + * - target_vendor, single value + * - test: set when testing is being done + * - again, seems similar to a "is defined" rather than "is equal to" like + * unix + * - debug_assertions: seems to "is defined" + * - proc_macro: no idea, bad docs. seems to be boolean, so maybe "is + * defined" + */ +}; + +// Defines compiler options (e.g. dump, etc.). +struct CompileOptions +{ + enum DumpOption + { + LEXER_DUMP, + PARSER_AST_DUMP, + AST_DUMP_PRETTY, + REGISTER_PLUGINS_DUMP, + INJECTION_DUMP, + EXPANSION_DUMP, + RESOLUTION_DUMP, + TARGET_OPTION_DUMP, + HIR_DUMP, + HIR_DUMP_PRETTY, + TYPE_RESOLUTION_DUMP, + }; + + std::set<DumpOption> dump_options; + + /* configuration options - actually useful for conditional compilation and + * whatever data related to target arch, features, os, family, env, endian, + * pointer width, vendor */ + TargetOptions target_data; + std::string crate_name; + bool crate_name_set_manually = false; + bool enable_test = false; + bool debug_assertions = false; + bool proc_macro = false; + std::string metadata_output_path; + + enum class Edition + { + E2015 = 0, + E2018, + E2021, + } edition + = Edition::E2015; + + bool dump_option_enabled (DumpOption option) const + { + return dump_options.find (option) != dump_options.end (); + } + + void enable_dump_option (DumpOption option) { dump_options.insert (option); } + + void enable_all_dump_options () + { + enable_dump_option (DumpOption::LEXER_DUMP); + enable_dump_option (DumpOption::PARSER_AST_DUMP); + enable_dump_option (DumpOption::AST_DUMP_PRETTY); + enable_dump_option (DumpOption::REGISTER_PLUGINS_DUMP); + enable_dump_option (DumpOption::INJECTION_DUMP); + enable_dump_option (DumpOption::EXPANSION_DUMP); + enable_dump_option (DumpOption::RESOLUTION_DUMP); + enable_dump_option (DumpOption::TARGET_OPTION_DUMP); + enable_dump_option (DumpOption::HIR_DUMP); + enable_dump_option (DumpOption::HIR_DUMP_PRETTY); + enable_dump_option (DumpOption::TYPE_RESOLUTION_DUMP); + } + + void set_crate_name (std::string name) + { + rust_assert (!name.empty ()); + + crate_name = std::move (name); + } + + const std::string &get_crate_name () const + { + rust_assert (!crate_name.empty ()); + return crate_name; + } + + void set_edition (int raw_edition) + { + edition = static_cast<Edition> (raw_edition); + } + + const Edition &get_edition () { return edition; } + + void set_metadata_output (const std::string &path) + { + metadata_output_path = path; + } + + const std::string &get_metadata_output () const + { + return metadata_output_path; + } + + bool metadata_output_path_set () const + { + return !metadata_output_path.empty (); + } +}; + +/* Defines a compiler session. This is for a single compiler invocation, so + * potentially includes parsing multiple crates. */ +struct Session +{ + CompileOptions options; + /* This should really be in a per-crate storage area but it is wiped with + * every file so eh. */ + std::string injected_crate_name; + + /* extra files get included during late stages of compilation (e.g. macro + * expansion) */ + std::vector<std::string> extra_files; + + // backend wrapper to GCC GENERIC + Backend *backend; + + // backend linemap + Linemap *linemap; + + // mappings + Analysis::Mappings *mappings; + +public: + /* Get a reference to the static session instance */ + static Session &get_instance (); + + Session () = default; + ~Session () = default; + + /* This initializes the compiler session. Corresponds to langhook + * grs_langhook_init(). Note that this is called after option handling. */ + void init (); + + // delete those constructors so we don't access the singleton in any + // other way than via `get_instance()` + Session (Session const &) = delete; + void operator= (Session const &) = delete; + + bool handle_option (enum opt_code code, const char *arg, HOST_WIDE_INT value, + int kind, location_t loc, + const struct cl_option_handlers *handlers); + void handle_input_files (int num_files, const char **files); + void init_options (); + void handle_crate_name (const AST::Crate &parsed_crate); + + /* This function saves the filename data into the session manager using the + * `move` semantics, and returns a C-style string referencing the input + * std::string */ + inline const char *include_extra_file (std::string filename) + { + extra_files.push_back (std::move (filename)); + return extra_files.back ().c_str (); + } + + NodeId load_extern_crate (const std::string &crate_name, Location locus); + +private: + void compile_crate (const char *filename); + bool enable_dump (std::string arg); + + void dump_lex (Parser<Lexer> &parser) const; + void dump_ast (Parser<Lexer> &parser, AST::Crate &crate) const; + void dump_ast_pretty (AST::Crate &crate) const; + void dump_ast_expanded (Parser<Lexer> &parser, AST::Crate &crate) const; + void dump_hir (HIR::Crate &crate) const; + void dump_hir_pretty (HIR::Crate &crate) const; + void dump_type_resolution (HIR::Crate &crate) const; + + // pipeline stages - TODO maybe move? + /* Register plugins pipeline stage. TODO maybe move to another object? + * Currently dummy stage. In future will handle attribute injection + * (top-level inner attribute creation from command line arguments), setting + * options maybe, registering lints maybe, loading plugins maybe. */ + void register_plugins (AST::Crate &crate); + + /* Injection pipeline stage. TODO maybe move to another object? Maybe have + * some lint checks (in future, obviously), register builtin macros, crate + * injection. */ + void injection (AST::Crate &crate); + + /* Expansion pipeline stage. TODO maybe move to another object? Expands all + * macros, maybe build test harness in future, AST validation, maybe create + * macro crate (if not rustdoc).*/ + void expansion (AST::Crate &crate); + + // handle cfg_option + bool handle_cfg_option (std::string &data); +}; + +} // namespace Rust + +#if CHECKING_P +namespace selftest { +extern void +rust_crate_name_validation_test (void); +} +#endif // CHECKING_P + +#endif |