1 // Copyright (C) 2020-2025 Free Software Foundation, Inc.
3 // This file is part of GCC.
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
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
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"
20 #ifndef RUST_SESSION_MANAGER_H
21 #define RUST_SESSION_MANAGER_H
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"
30 #include "rust-system.h"
31 #include "coretypes.h"
37 // parser forward decl
38 template <typename ManagedTokenSource
> class Parser
;
49 /* Data related to target, most useful for conditional compilation and
53 /* TODO: maybe make private and access through helpers to allow changes to
55 std::unordered_map
<std::string
, std::unordered_set
<tl::optional
<std::string
>>>
71 void set_crate_type (int raw_type
)
73 crate_type
= static_cast<CrateType
> (raw_type
);
76 const CrateType
&get_crate_type () const { return crate_type
; }
78 // Returns whether a key is defined in the feature set.
79 bool has_key (std::string key
) const
81 auto it
= features
.find (key
);
82 return it
!= features
.end ()
83 && it
->second
.find (tl::nullopt
) != it
->second
.end ();
86 // Returns whether a key exists with the given value in the feature set.
87 bool has_key_value_pair (std::string key
, std::string value
) const
89 auto it
= features
.find (key
);
90 if (it
!= features
.end ())
92 auto set
= it
->second
;
93 auto it2
= set
.find (value
);
94 if (it2
!= set
.end ())
100 /* Returns the singular value from the key, or if the key has multiple, an
102 std::string
get_singular_value (std::string key
) const
104 auto it
= features
.find (key
);
105 if (it
!= features
.end ())
107 auto set
= it
->second
;
108 if (set
.size () == 1 && set
.begin ()->has_value ())
109 return set
.begin ()->value ();
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
118 std::unordered_set
<std::string
> ret
;
120 auto it
= features
.find (key
);
121 if (it
== features
.end ())
124 for (auto &val
: it
->second
)
125 if (val
.has_value ())
126 ret
.insert (val
.value ());
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 bool insert_key (std::string key
)
136 auto it
= features
.find (key
);
138 if (it
== features
.end ())
142 std::make_pair (std::move (key
),
143 std::unordered_set
<tl::optional
<std::string
>> ()))
146 return it
->second
.insert (tl::nullopt
).second
;
149 // Inserts a key-value pair into the feature set.
150 void insert_key_value_pair (std::string key
, std::string value
)
152 auto it
= features
.find (key
);
154 if (it
== features
.end ())
158 std::make_pair (std::move (key
),
159 std::unordered_set
<tl::optional
<std::string
>> ()))
162 it
->second
.insert (std::move (value
));
165 // Dump all target options to stderr.
166 void dump_target_options () const;
168 /* Creates derived values and implicit enables after all target info is
169 * added (e.g. "unix"). */
170 void init_derived_values ();
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
);
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.
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). */
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
205 * - debug_assertions: seems to "is defined"
206 * - proc_macro: no idea, bad docs. seems to be boolean, so maybe "is
211 // Defines compiler options (e.g. dump, etc.).
212 struct CompileOptions
218 REGISTER_PLUGINS_DUMP
,
228 std::set
<DumpOption
> dump_options
;
230 /* configuration options - actually useful for conditional compilation and
231 * whatever data related to target arch, features, os, family, env, endian,
232 * pointer width, vendor */
233 TargetOptions target_data
;
234 std::string crate_name
;
235 bool crate_name_set_manually
= false;
236 bool enable_test
= false;
237 bool debug_assertions
= false;
238 std::string metadata_output_path
;
248 enum class CompileStep
267 enum class PanicStrategy
272 = PanicStrategy::Unwind
;
274 bool dump_option_enabled (DumpOption option
) const
276 return dump_options
.find (option
) != dump_options
.end ();
279 void enable_dump_option (DumpOption option
) { dump_options
.insert (option
); }
281 void enable_all_dump_options ()
283 enable_dump_option (DumpOption::LEXER_DUMP
);
284 enable_dump_option (DumpOption::AST_DUMP_PRETTY
);
285 enable_dump_option (DumpOption::REGISTER_PLUGINS_DUMP
);
286 enable_dump_option (DumpOption::INJECTION_DUMP
);
287 enable_dump_option (DumpOption::EXPANSION_DUMP
);
288 enable_dump_option (DumpOption::RESOLUTION_DUMP
);
289 enable_dump_option (DumpOption::TARGET_OPTION_DUMP
);
290 enable_dump_option (DumpOption::HIR_DUMP
);
291 enable_dump_option (DumpOption::HIR_DUMP_PRETTY
);
292 enable_dump_option (DumpOption::BIR_DUMP
);
295 void set_crate_name (std::string name
)
297 rust_assert (!name
.empty ());
299 crate_name
= std::move (name
);
302 const std::string
&get_crate_name () const
304 rust_assert (!crate_name
.empty ());
308 void set_edition (int raw_edition
)
310 edition
= static_cast<Edition
> (raw_edition
);
313 const Edition
&get_edition () const { return edition
; }
315 void set_crate_type (int raw_type
) { target_data
.set_crate_type (raw_type
); }
317 bool is_proc_macro () const
319 return target_data
.get_crate_type ()
320 == TargetOptions::CrateType::PROC_MACRO
;
323 void set_compile_step (int raw_step
)
325 compile_until
= static_cast<CompileStep
> (raw_step
);
328 const CompileStep
&get_compile_until () const { return compile_until
; }
330 void set_panic_strategy (int strategy
)
332 panic_strategy
= static_cast<PanicStrategy
> (strategy
);
335 const PanicStrategy
&get_panic_strategy () const { return panic_strategy
; }
337 void set_metadata_output (const std::string
&path
)
339 metadata_output_path
= path
;
342 const std::string
&get_metadata_output () const
344 return metadata_output_path
;
347 bool metadata_output_path_set () const
349 return !metadata_output_path
.empty ();
353 /* Defines a compiler session. This is for a single compiler invocation, so
354 * potentially includes parsing multiple crates. */
357 CompileOptions options
;
358 /* This should really be in a per-crate storage area but it is wiped with
359 * every file so eh. */
360 std::string injected_crate_name
;
361 std::map
<std::string
, std::string
> extern_crates
;
363 /* extra files get included during late stages of compilation (e.g. macro
365 std::vector
<std::string
> extra_files
;
371 Analysis::Mappings
&mappings
;
374 /* Get a reference to the static session instance */
375 static Session
&get_instance ();
377 ~Session () = default;
379 /* This initializes the compiler session. Corresponds to langhook
380 * grs_langhook_init(). Note that this is called after option handling. */
383 // delete those constructors so we don't access the singleton in any
384 // other way than via `get_instance()`
385 Session (Session
const &) = delete;
386 void operator= (Session
const &) = delete;
388 bool handle_option (enum opt_code code
, const char *arg
, HOST_WIDE_INT value
,
389 int kind
, location_t loc
,
390 const struct cl_option_handlers
*handlers
);
391 void handle_input_files (int num_files
, const char **files
);
392 void init_options ();
393 void handle_crate_name (const char *filename
, const AST::Crate
&parsed_crate
);
395 /* This function saves the filename data into the session manager using the
396 * `move` semantics, and returns a C-style string referencing the input
398 inline const char *include_extra_file (std::string filename
)
400 extra_files
.push_back (std::move (filename
));
401 return extra_files
.back ().c_str ();
404 NodeId
load_extern_crate (const std::string
&crate_name
, location_t locus
);
407 Session () : mappings (Analysis::Mappings::get ()) {}
408 void compile_crate (const char *filename
);
409 bool enable_dump (std::string arg
);
411 void dump_lex (Parser
<Lexer
> &parser
) const;
412 void dump_ast_pretty (AST::Crate
&crate
, bool expanded
= false) const;
413 void dump_name_resolution (Resolver2_0::NameResolutionContext
&ctx
) const;
414 void dump_hir (HIR::Crate
&crate
) const;
415 void dump_hir_pretty (HIR::Crate
&crate
) const;
417 // pipeline stages - TODO maybe move?
418 /* Register plugins pipeline stage. TODO maybe move to another object?
419 * Currently dummy stage. In future will handle attribute injection
420 * (top-level inner attribute creation from command line arguments), setting
421 * options maybe, registering lints maybe, loading plugins maybe. */
422 void register_plugins (AST::Crate
&crate
);
424 /* Injection pipeline stage. TODO maybe move to another object? Maybe have
425 * some lint checks (in future, obviously), register builtin macros, crate
427 void injection (AST::Crate
&crate
);
429 /* Expansion pipeline stage. TODO maybe move to another object? Expands all
430 * macros, maybe build test harness in future, AST validation, maybe create
431 * macro crate (if not rustdoc).*/
432 void expansion (AST::Crate
&crate
, Resolver2_0::NameResolutionContext
&ctx
);
435 bool handle_cfg_option (std::string
&data
);
437 bool handle_extern_option (std::string
&data
);
445 rust_crate_name_validation_test (void);