]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/rust/rust-session-manager.h
MAINTAINERS: Add myself as an aarch64 port reviewer
[thirdparty/gcc.git] / gcc / rust / rust-session-manager.h
CommitLineData
6441eb6d 1// Copyright (C) 2020-2025 Free Software Foundation, Inc.
ea346142
PH
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"
c3b40bc6 27#include "rust-name-resolution-context.h"
ea346142
PH
28
29#include "config.h"
30#include "rust-system.h"
31#include "coretypes.h"
32#include "options.h"
33
4e71511a 34#include "optional.h"
fc281773 35
ea346142
PH
36namespace Rust {
37// parser forward decl
38template <typename ManagedTokenSource> class Parser;
39class Lexer;
40// crate forward decl
41namespace AST {
42struct Crate;
43}
44// crate forward decl
45namespace HIR {
a229fcbf 46class Crate;
ea346142
PH
47}
48
49/* Data related to target, most useful for conditional compilation and
50 * whatever. */
51struct TargetOptions
52{
53 /* TODO: maybe make private and access through helpers to allow changes to
54 * impl */
4e71511a 55 std::unordered_map<std::string, std::unordered_set<tl::optional<std::string>>>
fc281773 56 features;
ea346142 57
dcba437a
PEP
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
ea346142 70public:
dcba437a
PEP
71 void set_crate_type (int raw_type)
72 {
73 crate_type = static_cast<CrateType> (raw_type);
74 }
75
76 const CrateType &get_crate_type () const { return crate_type; }
77
ea346142
PH
78 // Returns whether a key is defined in the feature set.
79 bool has_key (std::string key) const
80 {
fc281773
OA
81 auto it = features.find (key);
82 return it != features.end ()
4e71511a 83 && it->second.find (tl::nullopt) != it->second.end ();
ea346142
PH
84 }
85
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
88 {
89 auto it = features.find (key);
90 if (it != features.end ())
91 {
92 auto set = it->second;
4e71511a 93 auto it2 = set.find (value);
ea346142
PH
94 if (it2 != set.end ())
95 return true;
96 }
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;
4e71511a
AC
108 if (set.size () == 1 && set.begin ()->has_value ())
109 return set.begin ()->value ();
ea346142
PH
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 {
fc281773
OA
118 std::unordered_set<std::string> ret;
119
ea346142 120 auto it = features.find (key);
fc281773
OA
121 if (it == features.end ())
122 return {};
123
124 for (auto &val : it->second)
4e71511a
AC
125 if (val.has_value ())
126 ret.insert (val.value ());
fc281773
OA
127
128 return ret;
ea346142
PH
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 bool insert_key (std::string key)
135 {
fc281773
OA
136 auto it = features.find (key);
137
138 if (it == features.end ())
4e71511a
AC
139 it
140 = features
141 .insert (
142 std::make_pair (std::move (key),
143 std::unordered_set<tl::optional<std::string>> ()))
144 .first;
145
146 return it->second.insert (tl::nullopt).second;
ea346142
PH
147 }
148
149 // Inserts a key-value pair into the feature set.
150 void insert_key_value_pair (std::string key, std::string value)
151 {
fc281773
OA
152 auto it = features.find (key);
153
154 if (it == features.end ())
4e71511a
AC
155 it
156 = features
157 .insert (
158 std::make_pair (std::move (key),
159 std::unordered_set<tl::optional<std::string>> ()))
160 .first;
161
162 it->second.insert (std::move (value));
ea346142
PH
163 }
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.).
212struct CompileOptions
213{
214 enum DumpOption
215 {
216 LEXER_DUMP,
ea346142
PH
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,
206fc6de 225 BIR_DUMP,
ea346142
PH
226 };
227
228 std::set<DumpOption> dump_options;
229
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;
ea346142
PH
238 std::string metadata_output_path;
239
240 enum class Edition
241 {
242 E2015 = 0,
243 E2018,
244 E2021,
245 } edition
246 = Edition::E2015;
247
9d6b434e
AC
248 enum class CompileStep
249 {
250 Ast,
251 AttributeCheck,
252 Expansion,
cdf2cd9a
PEP
253 ASTValidation,
254 FeatureGating,
9d6b434e
AC
255 NameResolution,
256 Lowering,
257 TypeCheck,
258 Privacy,
259 Unsafety,
260 Const,
206fc6de 261 BorrowCheck,
9d6b434e
AC
262 Compilation,
263 End,
264 } compile_until
265 = CompileStep::End;
266
165e7575 267 enum class PanicStrategy
268 {
269 Unwind,
270 Abort,
271 } panic_strategy
272 = PanicStrategy::Unwind;
273
ea346142
PH
274 bool dump_option_enabled (DumpOption option) const
275 {
276 return dump_options.find (option) != dump_options.end ();
277 }
278
279 void enable_dump_option (DumpOption option) { dump_options.insert (option); }
280
281 void enable_all_dump_options ()
282 {
283 enable_dump_option (DumpOption::LEXER_DUMP);
ea346142
PH
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);
206fc6de 292 enable_dump_option (DumpOption::BIR_DUMP);
ea346142
PH
293 }
294
295 void set_crate_name (std::string name)
296 {
297 rust_assert (!name.empty ());
298
299 crate_name = std::move (name);
300 }
301
302 const std::string &get_crate_name () const
303 {
304 rust_assert (!crate_name.empty ());
305 return crate_name;
306 }
307
308 void set_edition (int raw_edition)
309 {
310 edition = static_cast<Edition> (raw_edition);
311 }
312
9d6b434e
AC
313 const Edition &get_edition () const { return edition; }
314
dcba437a
PEP
315 void set_crate_type (int raw_type) { target_data.set_crate_type (raw_type); }
316
317 bool is_proc_macro () const
318 {
319 return target_data.get_crate_type ()
320 == TargetOptions::CrateType::PROC_MACRO;
321 }
322
9d6b434e
AC
323 void set_compile_step (int raw_step)
324 {
325 compile_until = static_cast<CompileStep> (raw_step);
326 }
327
328 const CompileStep &get_compile_until () const { return compile_until; }
ea346142 329
165e7575 330 void set_panic_strategy (int strategy)
331 {
332 panic_strategy = static_cast<PanicStrategy> (strategy);
333 }
334
335 const PanicStrategy &get_panic_strategy () const { return panic_strategy; }
336
ea346142
PH
337 void set_metadata_output (const std::string &path)
338 {
339 metadata_output_path = path;
340 }
341
342 const std::string &get_metadata_output () const
343 {
344 return metadata_output_path;
345 }
346
347 bool metadata_output_path_set () const
348 {
349 return !metadata_output_path.empty ();
350 }
351};
352
353/* Defines a compiler session. This is for a single compiler invocation, so
354 * potentially includes parsing multiple crates. */
355struct Session
356{
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;
1ca5d5f8 361 std::map<std::string, std::string> extern_crates;
ea346142
PH
362
363 /* extra files get included during late stages of compilation (e.g. macro
364 * expansion) */
365 std::vector<std::string> extra_files;
366
ea346142
PH
367 // backend linemap
368 Linemap *linemap;
369
370 // mappings
fd788dd5 371 Analysis::Mappings &mappings;
ea346142
PH
372
373public:
374 /* Get a reference to the static session instance */
375 static Session &get_instance ();
376
ea346142
PH
377 ~Session () = default;
378
379 /* This initializes the compiler session. Corresponds to langhook
380 * grs_langhook_init(). Note that this is called after option handling. */
381 void init ();
382
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;
387
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 ();
34ef64d9 393 void handle_crate_name (const char *filename, const AST::Crate &parsed_crate);
ea346142
PH
394
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
397 * std::string */
398 inline const char *include_extra_file (std::string filename)
399 {
400 extra_files.push_back (std::move (filename));
401 return extra_files.back ().c_str ();
402 }
403
d991a3f1 404 NodeId load_extern_crate (const std::string &crate_name, location_t locus);
ea346142
PH
405
406private:
fd788dd5 407 Session () : mappings (Analysis::Mappings::get ()) {}
ea346142
PH
408 void compile_crate (const char *filename);
409 bool enable_dump (std::string arg);
410
411 void dump_lex (Parser<Lexer> &parser) const;
5be4c268 412 void dump_ast_pretty (AST::Crate &crate, bool expanded = false) const;
d403dd2c 413 void dump_name_resolution (Resolver2_0::NameResolutionContext &ctx) const;
ea346142
PH
414 void dump_hir (HIR::Crate &crate) const;
415 void dump_hir_pretty (HIR::Crate &crate) const;
ea346142
PH
416
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);
423
424 /* Injection pipeline stage. TODO maybe move to another object? Maybe have
425 * some lint checks (in future, obviously), register builtin macros, crate
426 * injection. */
427 void injection (AST::Crate &crate);
428
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).*/
c3b40bc6 432 void expansion (AST::Crate &crate, Resolver2_0::NameResolutionContext &ctx);
ea346142
PH
433
434 // handle cfg_option
435 bool handle_cfg_option (std::string &data);
1ca5d5f8
PEP
436
437 bool handle_extern_option (std::string &data);
ea346142
PH
438};
439
440} // namespace Rust
441
442#if CHECKING_P
443namespace selftest {
444extern void
445rust_crate_name_validation_test (void);
446}
447#endif // CHECKING_P
448
449#endif