]> git.ipfire.org Git - thirdparty/gcc.git/blame_incremental - gcc/rust/rust-session-manager.h
sh: Recognize >> 31 in treg_set_expr_not_const01
[thirdparty/gcc.git] / gcc / rust / rust-session-manager.h
... / ...
CommitLineData
1// Copyright (C) 2020-2025 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
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 {
46class Crate;
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 */
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
70public:
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
78 // Returns whether a key is defined in the feature set.
79 bool has_key (std::string key) const
80 {
81 auto it = features.find (key);
82 return it != features.end ()
83 && 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 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;
93 auto it2 = set.find (value);
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;
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 bool insert_key (std::string key)
135 {
136 auto it = features.find (key);
137
138 if (it == features.end ())
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;
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 {
152 auto it = features.find (key);
153
154 if (it == features.end ())
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));
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,
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 };
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;
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
248 enum class CompileStep
249 {
250 Ast,
251 AttributeCheck,
252 Expansion,
253 ASTValidation,
254 FeatureGating,
255 NameResolution,
256 Lowering,
257 TypeCheck,
258 Privacy,
259 Unsafety,
260 Const,
261 BorrowCheck,
262 Compilation,
263 End,
264 } compile_until
265 = CompileStep::End;
266
267 enum class PanicStrategy
268 {
269 Unwind,
270 Abort,
271 } panic_strategy
272 = PanicStrategy::Unwind;
273
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);
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);
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
313 const Edition &get_edition () const { return edition; }
314
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
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; }
329
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
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;
361 std::map<std::string, std::string> extern_crates;
362
363 /* extra files get included during late stages of compilation (e.g. macro
364 * expansion) */
365 std::vector<std::string> extra_files;
366
367 // backend linemap
368 Linemap *linemap;
369
370 // mappings
371 Analysis::Mappings &mappings;
372
373public:
374 /* Get a reference to the static session instance */
375 static Session &get_instance ();
376
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 ();
393 void handle_crate_name (const char *filename, const AST::Crate &parsed_crate);
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
404 NodeId load_extern_crate (const std::string &crate_name, location_t locus);
405
406private:
407 Session () : mappings (Analysis::Mappings::get ()) {}
408 void compile_crate (const char *filename);
409 bool enable_dump (std::string arg);
410
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;
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).*/
432 void expansion (AST::Crate &crate, Resolver2_0::NameResolutionContext &ctx);
433
434 // handle cfg_option
435 bool handle_cfg_option (std::string &data);
436
437 bool handle_extern_option (std::string &data);
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