rs6000: Error on CPUs and ABIs that don't support the ROP protection insns [PR114759]
[official-gcc.git] / gcc / rust / rust-session-manager.h
blob41aad6079058dab822ca58aee7b48222d610105e
1 // Copyright (C) 2020-2024 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
8 // version.
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.
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"
28 #include "config.h"
29 #include "rust-system.h"
30 #include "coretypes.h"
31 #include "options.h"
33 #include "optional.h"
35 namespace Rust {
36 // parser forward decl
37 template <typename ManagedTokenSource> class Parser;
38 class Lexer;
39 // crate forward decl
40 namespace AST {
41 struct Crate;
43 // crate forward decl
44 namespace HIR {
45 class Crate;
48 /* Data related to target, most useful for conditional compilation and
49 * whatever. */
50 struct TargetOptions
52 /* TODO: maybe make private and access through helpers to allow changes to
53 * impl */
54 std::unordered_map<std::string, std::unordered_set<tl::optional<std::string>>>
55 features;
57 enum class CrateType
59 BIN = 0,
60 LIB,
61 RLIB,
62 DYLIB,
63 CDYLIB,
64 STATICLIB,
65 PROC_MACRO
66 } crate_type
67 = CrateType::BIN;
69 public:
70 void set_crate_type (int raw_type)
72 crate_type = static_cast<CrateType> (raw_type);
75 const CrateType &get_crate_type () const { return crate_type; }
77 // Returns whether a key is defined in the feature set.
78 bool has_key (std::string key) const
80 auto it = features.find (key);
81 return it != features.end ()
82 && it->second.find (tl::nullopt) != it->second.end ();
85 // Returns whether a key exists with the given value in the feature set.
86 bool has_key_value_pair (std::string key, std::string value) const
88 auto it = features.find (key);
89 if (it != features.end ())
91 auto set = it->second;
92 auto it2 = set.find (value);
93 if (it2 != set.end ())
94 return true;
96 return false;
99 /* Returns the singular value from the key, or if the key has multiple, an
100 * empty string. */
101 std::string get_singular_value (std::string key) const
103 auto it = features.find (key);
104 if (it != features.end ())
106 auto set = it->second;
107 if (set.size () == 1 && set.begin ()->has_value ())
108 return set.begin ()->value ();
110 return "";
113 /* Returns all values associated with a key (including none), or an empty
114 * set if no key is found. */
115 std::unordered_set<std::string> get_values_for_key (std::string key) const
117 std::unordered_set<std::string> ret;
119 auto it = features.find (key);
120 if (it == features.end ())
121 return {};
123 for (auto &val : it->second)
124 if (val.has_value ())
125 ret.insert (val.value ());
127 return ret;
130 /* Inserts a key (no value) into the feature set. This will do nothing if
131 * the key already exists. This returns whether the insertion was successful
132 * (i.e. whether key already existed). */
133 bool insert_key (std::string key)
135 auto it = features.find (key);
137 if (it == features.end ())
139 = features
140 .insert (
141 std::make_pair (std::move (key),
142 std::unordered_set<tl::optional<std::string>> ()))
143 .first;
145 return it->second.insert (tl::nullopt).second;
148 // Inserts a key-value pair into the feature set.
149 void insert_key_value_pair (std::string key, std::string value)
151 auto it = features.find (key);
153 if (it == features.end ())
155 = features
156 .insert (
157 std::make_pair (std::move (key),
158 std::unordered_set<tl::optional<std::string>> ()))
159 .first;
161 it->second.insert (std::move (value));
164 // Dump all target options to stderr.
165 void dump_target_options () const;
167 /* Creates derived values and implicit enables after all target info is
168 * added (e.g. "unix"). */
169 void init_derived_values ();
171 /* Enables all requirements for the feature given, and will enable feature
172 * itself if not enabled. */
173 void enable_implicit_feature_reqs (std::string feature);
175 /* According to reference, Rust uses either multi-map key-values or just
176 * values (although values may be aliases for a key-value value). This seems
177 * like overkill. Thus, depending on whether the attributes used in cfg are
178 * fixed or not, I think I'll either put each non-multimap "key-value" as a
179 * separate field and have the multimap "key-values" in a regular map for
180 * that one key, or actually use a multimap.
182 * rustc itself uses a set of key-value tuples where the second tuple
183 * element is optional. This gets rid of the requirement to make a
184 * multi-map, I guess, but seems like it might make search slow (unless all
185 * "is defined"-only ones have empty string as second element). */
186 /* cfg attributes:
187 * - target_arch: single value
188 * - target_feature: multiple values possible
189 * - target_os: single value
190 * - target_family: single value (or no value?)
191 * - unix: set when target_family = "unix"
192 * - windows: set when target_family = "windows"
193 * - if these are just syntactic sugar, then maybe have a separate set or
194 * map for this kind of stuff
195 * - target_env: set when needed for disambiguation about ABI - usually
196 * empty string for GNU, complicated
197 * - seems to be a single value (if any)
198 * - target_endian: single value; "little" or "big"
199 * - target_pointer_width: single value, "32" for 32-bit pointers, etc.
200 * - target_vendor, single value
201 * - test: set when testing is being done
202 * - again, seems similar to a "is defined" rather than "is equal to" like
203 * unix
204 * - debug_assertions: seems to "is defined"
205 * - proc_macro: no idea, bad docs. seems to be boolean, so maybe "is
206 * defined"
210 // Defines compiler options (e.g. dump, etc.).
211 struct CompileOptions
213 enum DumpOption
215 LEXER_DUMP,
216 AST_DUMP_PRETTY,
217 REGISTER_PLUGINS_DUMP,
218 INJECTION_DUMP,
219 EXPANSION_DUMP,
220 RESOLUTION_DUMP,
221 TARGET_OPTION_DUMP,
222 HIR_DUMP,
223 HIR_DUMP_PRETTY,
224 BIR_DUMP,
227 std::set<DumpOption> dump_options;
229 /* configuration options - actually useful for conditional compilation and
230 * whatever data related to target arch, features, os, family, env, endian,
231 * pointer width, vendor */
232 TargetOptions target_data;
233 std::string crate_name;
234 bool crate_name_set_manually = false;
235 bool enable_test = false;
236 bool debug_assertions = false;
237 std::string metadata_output_path;
239 enum class Edition
241 E2015 = 0,
242 E2018,
243 E2021,
244 } edition
245 = Edition::E2015;
247 enum class CompileStep
249 Ast,
250 AttributeCheck,
251 Expansion,
252 ASTValidation,
253 FeatureGating,
254 NameResolution,
255 Lowering,
256 TypeCheck,
257 Privacy,
258 Unsafety,
259 Const,
260 BorrowCheck,
261 Compilation,
262 End,
263 } compile_until
264 = CompileStep::End;
266 bool dump_option_enabled (DumpOption option) const
268 return dump_options.find (option) != dump_options.end ();
271 void enable_dump_option (DumpOption option) { dump_options.insert (option); }
273 void enable_all_dump_options ()
275 enable_dump_option (DumpOption::LEXER_DUMP);
276 enable_dump_option (DumpOption::AST_DUMP_PRETTY);
277 enable_dump_option (DumpOption::REGISTER_PLUGINS_DUMP);
278 enable_dump_option (DumpOption::INJECTION_DUMP);
279 enable_dump_option (DumpOption::EXPANSION_DUMP);
280 enable_dump_option (DumpOption::RESOLUTION_DUMP);
281 enable_dump_option (DumpOption::TARGET_OPTION_DUMP);
282 enable_dump_option (DumpOption::HIR_DUMP);
283 enable_dump_option (DumpOption::HIR_DUMP_PRETTY);
284 enable_dump_option (DumpOption::BIR_DUMP);
287 void set_crate_name (std::string name)
289 rust_assert (!name.empty ());
291 crate_name = std::move (name);
294 const std::string &get_crate_name () const
296 rust_assert (!crate_name.empty ());
297 return crate_name;
300 void set_edition (int raw_edition)
302 edition = static_cast<Edition> (raw_edition);
305 const Edition &get_edition () const { return edition; }
307 void set_crate_type (int raw_type) { target_data.set_crate_type (raw_type); }
309 bool is_proc_macro () const
311 return target_data.get_crate_type ()
312 == TargetOptions::CrateType::PROC_MACRO;
315 void set_compile_step (int raw_step)
317 compile_until = static_cast<CompileStep> (raw_step);
320 const CompileStep &get_compile_until () const { return compile_until; }
322 void set_metadata_output (const std::string &path)
324 metadata_output_path = path;
327 const std::string &get_metadata_output () const
329 return metadata_output_path;
332 bool metadata_output_path_set () const
334 return !metadata_output_path.empty ();
338 /* Defines a compiler session. This is for a single compiler invocation, so
339 * potentially includes parsing multiple crates. */
340 struct Session
342 CompileOptions options;
343 /* This should really be in a per-crate storage area but it is wiped with
344 * every file so eh. */
345 std::string injected_crate_name;
346 std::map<std::string, std::string> extern_crates;
348 /* extra files get included during late stages of compilation (e.g. macro
349 * expansion) */
350 std::vector<std::string> extra_files;
352 // backend linemap
353 Linemap *linemap;
355 // mappings
356 Analysis::Mappings *mappings;
358 public:
359 /* Get a reference to the static session instance */
360 static Session &get_instance ();
362 Session () = default;
363 ~Session () = default;
365 /* This initializes the compiler session. Corresponds to langhook
366 * grs_langhook_init(). Note that this is called after option handling. */
367 void init ();
369 // delete those constructors so we don't access the singleton in any
370 // other way than via `get_instance()`
371 Session (Session const &) = delete;
372 void operator= (Session const &) = delete;
374 bool handle_option (enum opt_code code, const char *arg, HOST_WIDE_INT value,
375 int kind, location_t loc,
376 const struct cl_option_handlers *handlers);
377 void handle_input_files (int num_files, const char **files);
378 void init_options ();
379 void handle_crate_name (const AST::Crate &parsed_crate);
381 /* This function saves the filename data into the session manager using the
382 * `move` semantics, and returns a C-style string referencing the input
383 * std::string */
384 inline const char *include_extra_file (std::string filename)
386 extra_files.push_back (std::move (filename));
387 return extra_files.back ().c_str ();
390 NodeId load_extern_crate (const std::string &crate_name, location_t locus);
392 private:
393 void compile_crate (const char *filename);
394 bool enable_dump (std::string arg);
396 void dump_lex (Parser<Lexer> &parser) const;
397 void dump_ast_pretty (AST::Crate &crate, bool expanded = false) const;
398 void dump_hir (HIR::Crate &crate) const;
399 void dump_hir_pretty (HIR::Crate &crate) const;
401 // pipeline stages - TODO maybe move?
402 /* Register plugins pipeline stage. TODO maybe move to another object?
403 * Currently dummy stage. In future will handle attribute injection
404 * (top-level inner attribute creation from command line arguments), setting
405 * options maybe, registering lints maybe, loading plugins maybe. */
406 void register_plugins (AST::Crate &crate);
408 /* Injection pipeline stage. TODO maybe move to another object? Maybe have
409 * some lint checks (in future, obviously), register builtin macros, crate
410 * injection. */
411 void injection (AST::Crate &crate);
413 /* Expansion pipeline stage. TODO maybe move to another object? Expands all
414 * macros, maybe build test harness in future, AST validation, maybe create
415 * macro crate (if not rustdoc).*/
416 void expansion (AST::Crate &crate);
418 // handle cfg_option
419 bool handle_cfg_option (std::string &data);
421 bool handle_extern_option (std::string &data);
424 } // namespace Rust
426 #if CHECKING_P
427 namespace selftest {
428 extern void
429 rust_crate_name_validation_test (void);
431 #endif // CHECKING_P
433 #endif