LCOV - code coverage report
Current view: top level - gcc/rust - rust-session-manager.h (source / functions) Coverage Total Hit
Test: gcc.info Lines: 69.0 % 84 58
Test Date: 2026-02-28 14:20:25 Functions: 80.0 % 10 8
Legend: Lines:     hit not hit

            Line data    Source code
       1              : // Copyright (C) 2020-2026 Free Software Foundation, Inc.
       2              : 
       3              : // This file is part of GCC.
       4              : 
       5              : // GCC is free software; you can redistribute it and/or modify it under
       6              : // the terms of the GNU General Public License as published by the Free
       7              : // Software Foundation; either version 3, or (at your option) any later
       8              : // version.
       9              : 
      10              : // GCC is distributed in the hope that it will be useful, but WITHOUT ANY
      11              : // WARRANTY; without even the implied warranty of MERCHANTABILITY or
      12              : // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      13              : // for more details.
      14              : 
      15              : // You should have received a copy of the GNU General Public License
      16              : // along with GCC; see the file COPYING3.  If not see
      17              : // <http://www.gnu.org/licenses/>.
      18              : // #include "rust-session-manager.h"
      19              : 
      20              : #ifndef RUST_SESSION_MANAGER_H
      21              : #define RUST_SESSION_MANAGER_H
      22              : 
      23              : #include "rust-linemap.h"
      24              : #include "rust-backend.h"
      25              : #include "rust-hir-map.h"
      26              : #include "safe-ctype.h"
      27              : #include "rust-name-resolution-context.h"
      28              : 
      29              : #include "config.h"
      30              : #include "rust-system.h"
      31              : #include "coretypes.h"
      32              : #include "options.h"
      33              : 
      34              : #include "optional.h"
      35              : 
      36              : namespace Rust {
      37              : // parser forward decl
      38              : template <typename ManagedTokenSource> class Parser;
      39              : class Lexer;
      40              : // crate forward decl
      41              : namespace AST {
      42              : struct Crate;
      43              : }
      44              : // crate forward decl
      45              : namespace HIR {
      46              : class Crate;
      47              : }
      48              : 
      49              : /* Data related to target, most useful for conditional compilation and
      50              :  * whatever. */
      51              : struct TargetOptions
      52              : {
      53              :   /* TODO: maybe make private and access through helpers to allow changes to
      54              :    * impl */
      55              :   std::unordered_map<std::string, std::unordered_set<tl::optional<std::string>>>
      56              :     features;
      57              : 
      58              :   enum class CrateType
      59              :   {
      60              :     BIN = 0,
      61              :     LIB,
      62              :     RLIB,
      63              :     DYLIB,
      64              :     CDYLIB,
      65              :     STATICLIB,
      66              :     PROC_MACRO
      67              :   } crate_type
      68              :     = CrateType::BIN;
      69              : 
      70              : public:
      71           21 :   void set_crate_type (int raw_type)
      72              :   {
      73           21 :     crate_type = static_cast<CrateType> (raw_type);
      74              :   }
      75              : 
      76              :   const CrateType &get_crate_type () const { return crate_type; }
      77              : 
      78              :   // Returns whether a key is defined in the feature set.
      79          318 :   bool has_key (std::string key) const
      80              :   {
      81          318 :     auto it = features.find (key);
      82          318 :     return it != features.end ()
      83          513 :            && it->second.find (tl::nullopt) != it->second.end ();
      84              :   }
      85              : 
      86              :   // Returns whether a key exists with the given value in the feature set.
      87         3764 :   bool has_key_value_pair (std::string key, std::string value) const
      88              :   {
      89         3764 :     auto it = features.find (key);
      90         3764 :     if (it != features.end ())
      91              :       {
      92         3736 :         auto set = it->second;
      93         7472 :         auto it2 = set.find (value);
      94         3736 :         if (it2 != set.end ())
      95         3702 :           return true;
      96         3736 :       }
      97              :     return false;
      98              :   }
      99              : 
     100              :   /* Returns the singular value from the key, or if the key has multiple, an
     101              :    * empty string. */
     102              :   std::string get_singular_value (std::string key) const
     103              :   {
     104              :     auto it = features.find (key);
     105              :     if (it != features.end ())
     106              :       {
     107              :         auto set = it->second;
     108              :         if (set.size () == 1 && set.begin ()->has_value ())
     109              :           return set.begin ()->value ();
     110              :       }
     111              :     return "";
     112              :   }
     113              : 
     114              :   /* Returns all values associated with a key (including none), or an empty
     115              :    * set if no key is found. */
     116              :   std::unordered_set<std::string> get_values_for_key (std::string key) const
     117              :   {
     118              :     std::unordered_set<std::string> ret;
     119              : 
     120              :     auto it = features.find (key);
     121              :     if (it == features.end ())
     122              :       return {};
     123              : 
     124              :     for (auto &val : it->second)
     125              :       if (val.has_value ())
     126              :         ret.insert (val.value ());
     127              : 
     128              :     return ret;
     129              :   }
     130              : 
     131              :   /* Inserts a key (no value) into the feature set. This will do nothing if
     132              :    * the key already exists. This returns whether the insertion was successful
     133              :    * (i.e. whether key already existed). */
     134           66 :   bool insert_key (std::string key)
     135              :   {
     136           66 :     auto it = features.find (key);
     137              : 
     138           66 :     if (it == features.end ())
     139           66 :       it
     140           66 :         = features
     141           66 :             .insert (
     142          132 :               std::make_pair (std::move (key),
     143          132 :                               std::unordered_set<tl::optional<std::string>> ()))
     144              :             .first;
     145              : 
     146           66 :     return it->second.insert (tl::nullopt).second;
     147              :   }
     148              : 
     149              :   // Inserts a key-value pair into the feature set.
     150        50987 :   void insert_key_value_pair (std::string key, std::string value)
     151              :   {
     152        50987 :     auto it = features.find (key);
     153              : 
     154        50987 :     if (it == features.end ())
     155        37082 :       it
     156        37082 :         = features
     157        37082 :             .insert (
     158        74164 :               std::make_pair (std::move (key),
     159        74164 :                               std::unordered_set<tl::optional<std::string>> ()))
     160              :             .first;
     161              : 
     162        50987 :     it->second.insert (std::move (value));
     163        50987 :   }
     164              : 
     165              :   // Dump all target options to stderr.
     166              :   void dump_target_options () const;
     167              : 
     168              :   /* Creates derived values and implicit enables after all target info is
     169              :    * added (e.g. "unix"). */
     170              :   void init_derived_values ();
     171              : 
     172              :   /* Enables all requirements for the feature given, and will enable feature
     173              :    * itself if not enabled. */
     174              :   void enable_implicit_feature_reqs (std::string feature);
     175              : 
     176              :   /* According to reference, Rust uses either multi-map key-values or just
     177              :    * values (although values may be aliases for a key-value value). This seems
     178              :    * like overkill. Thus, depending on whether the attributes used in cfg are
     179              :    * fixed or not, I think I'll either put each non-multimap "key-value" as a
     180              :    * separate field and have the multimap "key-values" in a regular map for
     181              :    * that one key, or actually use a multimap.
     182              :    *
     183              :    * rustc itself uses a set of key-value tuples where the second tuple
     184              :    * element is optional. This gets rid of the requirement to make a
     185              :    * multi-map, I guess, but seems like it might make search slow (unless all
     186              :    * "is defined"-only ones have empty string as second element). */
     187              :   /* cfg attributes:
     188              :    * - target_arch: single value
     189              :    * - target_feature: multiple values possible
     190              :    * - target_os: single value
     191              :    * - target_family: single value (or no value?)
     192              :    * - unix: set when target_family = "unix"
     193              :    * - windows: set when target_family = "windows"
     194              :    *  - if these are just syntactic sugar, then maybe have a separate set or
     195              :    * map for this kind of stuff
     196              :    * - target_env: set when needed for disambiguation about ABI - usually
     197              :    * empty string for GNU, complicated
     198              :    *  - seems to be a single value (if any)
     199              :    * - target_endian: single value; "little" or "big"
     200              :    * - target_pointer_width: single value, "32" for 32-bit pointers, etc.
     201              :    * - target_vendor, single value
     202              :    * - test: set when testing is being done
     203              :    *  - again, seems similar to a "is defined" rather than "is equal to" like
     204              :    * unix
     205              :    * - debug_assertions: seems to "is defined"
     206              :    * - proc_macro: no idea, bad docs. seems to be boolean, so maybe "is
     207              :    * defined"
     208              :    */
     209              : };
     210              : 
     211              : // Defines compiler options (e.g. dump, etc.).
     212              : struct CompileOptions
     213              : {
     214              :   enum DumpOption
     215              :   {
     216              :     LEXER_DUMP,
     217              :     AST_DUMP_PRETTY,
     218              :     REGISTER_PLUGINS_DUMP,
     219              :     INJECTION_DUMP,
     220              :     EXPANSION_DUMP,
     221              :     RESOLUTION_DUMP,
     222              :     TARGET_OPTION_DUMP,
     223              :     HIR_DUMP,
     224              :     HIR_DUMP_PRETTY,
     225              :     BIR_DUMP,
     226              :     INTERNAL_DUMP,
     227              :   };
     228              : 
     229              :   std::set<DumpOption> dump_options;
     230              : 
     231              :   /* List of node that is not print during the dump of the ast with internal
     232              :    * comment */
     233              :   std::set<std::string> excluded_node;
     234              : 
     235              :   /* configuration options - actually useful for conditional compilation and
     236              :    * whatever data related to target arch, features, os, family, env, endian,
     237              :    * pointer width, vendor */
     238              :   TargetOptions target_data;
     239              :   std::string crate_name;
     240              :   bool crate_name_set_manually = false;
     241              :   bool enable_test = false;
     242              :   bool debug_assertions = false;
     243              :   std::string metadata_output_path;
     244              : 
     245              :   enum class Edition
     246              :   {
     247              :     E2015 = 0,
     248              :     E2018,
     249              :     E2021,
     250              :   } edition
     251              :     = Edition::E2015;
     252              : 
     253              :   enum class CompileStep
     254              :   {
     255              :     Ast,
     256              :     AttributeCheck,
     257              :     Expansion,
     258              :     ASTValidation,
     259              :     FeatureGating,
     260              :     NameResolution,
     261              :     Lowering,
     262              :     TypeCheck,
     263              :     Privacy,
     264              :     Unsafety,
     265              :     Const,
     266              :     BorrowCheck,
     267              :     Compilation,
     268              :     End,
     269              :   } compile_until
     270              :     = CompileStep::End;
     271              : 
     272              :   enum class PanicStrategy
     273              :   {
     274              :     Unwind,
     275              :     Abort,
     276              :   } panic_strategy
     277              :     = PanicStrategy::Unwind;
     278              : 
     279        45003 :   bool dump_option_enabled (DumpOption option) const
     280              :   {
     281        36160 :     return dump_options.find (option) != dump_options.end ();
     282              :   }
     283              : 
     284            0 :   void enable_dump_option (DumpOption option) { dump_options.insert (option); }
     285              : 
     286            0 :   void enable_all_dump_options ()
     287              :   {
     288            0 :     enable_dump_option (DumpOption::LEXER_DUMP);
     289            0 :     enable_dump_option (DumpOption::AST_DUMP_PRETTY);
     290            0 :     enable_dump_option (DumpOption::REGISTER_PLUGINS_DUMP);
     291            0 :     enable_dump_option (DumpOption::INJECTION_DUMP);
     292            0 :     enable_dump_option (DumpOption::EXPANSION_DUMP);
     293            0 :     enable_dump_option (DumpOption::RESOLUTION_DUMP);
     294            0 :     enable_dump_option (DumpOption::TARGET_OPTION_DUMP);
     295            0 :     enable_dump_option (DumpOption::HIR_DUMP);
     296            0 :     enable_dump_option (DumpOption::HIR_DUMP_PRETTY);
     297            0 :     enable_dump_option (DumpOption::BIR_DUMP);
     298            0 :     enable_dump_option (DumpOption::INTERNAL_DUMP);
     299            0 :   }
     300              : 
     301            0 :   void add_excluded (std::string node)
     302              :   {
     303            0 :     rust_assert (!node.empty ());
     304            0 :     excluded_node.insert (node);
     305            0 :   }
     306              : 
     307            0 :   const std::set<std::string> get_excluded () const { return excluded_node; }
     308              : 
     309         4635 :   void set_crate_name (std::string name)
     310              :   {
     311         4635 :     rust_assert (!name.empty ());
     312              : 
     313         4635 :     crate_name = std::move (name);
     314         4635 :   }
     315              : 
     316         9150 :   const std::string &get_crate_name () const
     317              :   {
     318         9150 :     rust_assert (!crate_name.empty ());
     319         9150 :     return crate_name;
     320              :   }
     321              : 
     322            8 :   void set_edition (int raw_edition)
     323              :   {
     324            8 :     edition = static_cast<Edition> (raw_edition);
     325            8 :   }
     326              : 
     327              :   const Edition &get_edition () const { return edition; }
     328              : 
     329           21 :   void set_crate_type (int raw_type) { target_data.set_crate_type (raw_type); }
     330              : 
     331        17036 :   bool is_proc_macro () const
     332              :   {
     333        17036 :     return target_data.get_crate_type ()
     334              :            == TargetOptions::CrateType::PROC_MACRO;
     335              :   }
     336              : 
     337           46 :   void set_compile_step (int raw_step)
     338              :   {
     339           46 :     compile_until = static_cast<CompileStep> (raw_step);
     340           46 :   }
     341              : 
     342              :   const CompileStep &get_compile_until () const { return compile_until; }
     343              : 
     344            0 :   void set_panic_strategy (int strategy)
     345              :   {
     346            0 :     panic_strategy = static_cast<PanicStrategy> (strategy);
     347            0 :   }
     348              : 
     349              :   const PanicStrategy &get_panic_strategy () const { return panic_strategy; }
     350              : 
     351            0 :   void set_metadata_output (const std::string &path)
     352              :   {
     353            0 :     metadata_output_path = path;
     354              :   }
     355              : 
     356            0 :   const std::string &get_metadata_output () const
     357              :   {
     358            0 :     return metadata_output_path;
     359              :   }
     360              : 
     361         4028 :   bool metadata_output_path_set () const
     362              :   {
     363         4028 :     return !metadata_output_path.empty ();
     364              :   }
     365              : };
     366              : 
     367              : /* Defines a compiler session. This is for a single compiler invocation, so
     368              :  * potentially includes parsing multiple crates. */
     369              : struct Session
     370              : {
     371              :   CompileOptions options;
     372              :   /* This should really be in a per-crate storage area but it is wiped with
     373              :    * every file so eh. */
     374              :   std::string injected_crate_name;
     375              :   std::map<std::string, std::string> extern_crates;
     376              : 
     377              :   /* extra files get included during late stages of compilation (e.g. macro
     378              :    * expansion) */
     379              :   std::vector<std::string> extra_files;
     380              : 
     381              :   // backend linemap
     382              :   Linemap *linemap;
     383              : 
     384              :   // mappings
     385              :   Analysis::Mappings &mappings;
     386              : 
     387              : public:
     388              :   /* Get a reference to the static session instance */
     389              :   static Session &get_instance ();
     390              : 
     391         4636 :   ~Session () = default;
     392              : 
     393              :   /* This initializes the compiler session. Corresponds to langhook
     394              :    * grs_langhook_init(). Note that this is called after option handling. */
     395              :   void init ();
     396              : 
     397              :   // delete those constructors so we don't access the singleton in any
     398              :   // other way than via `get_instance()`
     399              :   Session (Session const &) = delete;
     400              :   void operator= (Session const &) = delete;
     401              : 
     402              :   bool handle_option (enum opt_code code, const char *arg, HOST_WIDE_INT value,
     403              :                       int kind, location_t loc,
     404              :                       const struct cl_option_handlers *handlers);
     405              :   void handle_input_files (int num_files, const char **files);
     406              :   void init_options ();
     407              :   void handle_crate_name (const char *filename, const AST::Crate &parsed_crate);
     408              : 
     409              :   /* This function saves the filename data into the session manager using the
     410              :    * `move` semantics, and returns a C-style string referencing the input
     411              :    * std::string */
     412            5 :   inline const char *include_extra_file (std::string filename)
     413              :   {
     414            5 :     extra_files.push_back (std::move (filename));
     415            5 :     return extra_files.back ().c_str ();
     416              :   }
     417              : 
     418              :   NodeId load_extern_crate (const std::string &crate_name, location_t locus);
     419              : 
     420              : private:
     421         4636 :   Session () : mappings (Analysis::Mappings::get ()) {}
     422              :   void compile_crate (const char *filename);
     423              :   bool enable_dump (std::string arg);
     424              : 
     425              :   void dump_lex (Parser<Lexer> &parser) const;
     426              :   void dump_ast_pretty (AST::Crate &crate, bool expanded = false) const;
     427              :   void dump_ast_pretty_internal (AST::Crate &crate) const;
     428              :   void dump_name_resolution (Resolver2_0::NameResolutionContext &ctx) const;
     429              :   void dump_hir (HIR::Crate &crate) const;
     430              :   void dump_hir_pretty (HIR::Crate &crate) const;
     431              : 
     432              :   void handle_excluded_node (std::string arg);
     433              : 
     434              :   // pipeline stages - TODO maybe move?
     435              :   /* Register plugins pipeline stage. TODO maybe move to another object?
     436              :    * Currently dummy stage. In future will handle attribute injection
     437              :    * (top-level inner attribute creation from command line arguments), setting
     438              :    * options maybe, registering lints maybe, loading plugins maybe. */
     439              :   void register_plugins (AST::Crate &crate);
     440              : 
     441              :   /* Injection pipeline stage. TODO maybe move to another object? Maybe have
     442              :    * some lint checks (in future, obviously), register builtin macros, crate
     443              :    * injection. */
     444              :   void injection (AST::Crate &crate);
     445              : 
     446              :   /* Expansion pipeline stage. TODO maybe move to another object? Expands all
     447              :    * macros, maybe build test harness in future, AST validation, maybe create
     448              :    * macro crate (if not rustdoc).*/
     449              :   void expansion (AST::Crate &crate, Resolver2_0::NameResolutionContext &ctx);
     450              : 
     451              :   // handle cfg_option
     452              :   bool handle_cfg_option (std::string &data);
     453              : 
     454              :   bool handle_extern_option (std::string &data);
     455              : };
     456              : 
     457              : } // namespace Rust
     458              : 
     459              : #if CHECKING_P
     460              : namespace selftest {
     461              : extern void rust_crate_name_validation_test (void);
     462              : }
     463              : #endif // CHECKING_P
     464              : 
     465              : #endif
        

Generated by: LCOV version 2.4-beta

LCOV profile is generated on x86_64 machine using following configure options: configure --disable-bootstrap --enable-coverage=opt --enable-languages=c,c++,fortran,go,jit,lto,rust,m2 --enable-host-shared. GCC test suite is run with the built compiler.