]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/rust/rust-session-manager.h
Update copyright years.
[thirdparty/gcc.git] / gcc / rust / rust-session-manager.h
CommitLineData
83ffe9cd 1// Copyright (C) 2020-2023 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"
27
28#include "config.h"
29#include "rust-system.h"
30#include "coretypes.h"
31#include "options.h"
32
33namespace Rust {
34// parser forward decl
35template <typename ManagedTokenSource> class Parser;
36class Lexer;
37// crate forward decl
38namespace AST {
39struct Crate;
40}
41// crate forward decl
42namespace HIR {
43struct Crate;
44}
45
46/* Data related to target, most useful for conditional compilation and
47 * whatever. */
48struct TargetOptions
49{
50 /* TODO: maybe make private and access through helpers to allow changes to
51 * impl */
52 std::unordered_map<std::string, std::unordered_set<std::string> > features;
53
54public:
55 // Returns whether a key is defined in the feature set.
56 bool has_key (std::string key) const
57 {
58 return features.find (key) != features.end ();
59 }
60
61 // Returns whether a key exists with the given value in the feature set.
62 bool has_key_value_pair (std::string key, std::string value) const
63 {
64 auto it = features.find (key);
65 if (it != features.end ())
66 {
67 auto set = it->second;
68 auto it2 = set.find (value);
69 if (it2 != set.end ())
70 return true;
71 }
72 return false;
73 }
74
75 /* Returns the singular value from the key, or if the key has multiple, an
76 * empty string. */
77 std::string get_singular_value (std::string key) const
78 {
79 auto it = features.find (key);
80 if (it != features.end ())
81 {
82 auto set = it->second;
83 if (set.size () == 1)
84 return *set.begin ();
85 }
86 return "";
87 }
88
89 /* Returns all values associated with a key (including none), or an empty
90 * set if no key is found. */
91 std::unordered_set<std::string> get_values_for_key (std::string key) const
92 {
93 auto it = features.find (key);
94 if (it != features.end ())
95 return it->second;
96 return {};
97 }
98
99 /* Inserts a key (no value) into the feature set. This will do nothing if
100 * the key already exists. This returns whether the insertion was successful
101 * (i.e. whether key already existed). */
102 bool insert_key (std::string key)
103 {
104 return features
105 .insert (std::make_pair (key, std::unordered_set<std::string> ()))
106 .second;
107 }
108
109 // Inserts a key-value pair into the feature set.
110 void insert_key_value_pair (std::string key, std::string value)
111 {
112 auto existing_set = get_values_for_key (key);
113 existing_set.insert (std::move (value));
114 features[std::move (key)] = std::move (existing_set);
115 }
116
117 // Dump all target options to stderr.
118 void dump_target_options () const;
119
120 /* Creates derived values and implicit enables after all target info is
121 * added (e.g. "unix"). */
122 void init_derived_values ();
123
124 /* Enables all requirements for the feature given, and will enable feature
125 * itself if not enabled. */
126 void enable_implicit_feature_reqs (std::string feature);
127
128 /* According to reference, Rust uses either multi-map key-values or just
129 * values (although values may be aliases for a key-value value). This seems
130 * like overkill. Thus, depending on whether the attributes used in cfg are
131 * fixed or not, I think I'll either put each non-multimap "key-value" as a
132 * separate field and have the multimap "key-values" in a regular map for
133 * that one key, or actually use a multimap.
134 *
135 * rustc itself uses a set of key-value tuples where the second tuple
136 * element is optional. This gets rid of the requirement to make a
137 * multi-map, I guess, but seems like it might make search slow (unless all
138 * "is defined"-only ones have empty string as second element). */
139 /* cfg attributes:
140 * - target_arch: single value
141 * - target_feature: multiple values possible
142 * - target_os: single value
143 * - target_family: single value (or no value?)
144 * - unix: set when target_family = "unix"
145 * - windows: set when target_family = "windows"
146 * - if these are just syntactic sugar, then maybe have a separate set or
147 * map for this kind of stuff
148 * - target_env: set when needed for disambiguation about ABI - usually
149 * empty string for GNU, complicated
150 * - seems to be a single value (if any)
151 * - target_endian: single value; "little" or "big"
152 * - target_pointer_width: single value, "32" for 32-bit pointers, etc.
153 * - target_vendor, single value
154 * - test: set when testing is being done
155 * - again, seems similar to a "is defined" rather than "is equal to" like
156 * unix
157 * - debug_assertions: seems to "is defined"
158 * - proc_macro: no idea, bad docs. seems to be boolean, so maybe "is
159 * defined"
160 */
161};
162
163// Defines compiler options (e.g. dump, etc.).
164struct CompileOptions
165{
166 enum DumpOption
167 {
168 LEXER_DUMP,
169 PARSER_AST_DUMP,
170 AST_DUMP_PRETTY,
171 REGISTER_PLUGINS_DUMP,
172 INJECTION_DUMP,
173 EXPANSION_DUMP,
174 RESOLUTION_DUMP,
175 TARGET_OPTION_DUMP,
176 HIR_DUMP,
177 HIR_DUMP_PRETTY,
178 TYPE_RESOLUTION_DUMP,
179 };
180
181 std::set<DumpOption> dump_options;
182
183 /* configuration options - actually useful for conditional compilation and
184 * whatever data related to target arch, features, os, family, env, endian,
185 * pointer width, vendor */
186 TargetOptions target_data;
187 std::string crate_name;
188 bool crate_name_set_manually = false;
189 bool enable_test = false;
190 bool debug_assertions = false;
191 bool proc_macro = false;
192 std::string metadata_output_path;
193
194 enum class Edition
195 {
196 E2015 = 0,
197 E2018,
198 E2021,
199 } edition
200 = Edition::E2015;
201
202 bool dump_option_enabled (DumpOption option) const
203 {
204 return dump_options.find (option) != dump_options.end ();
205 }
206
207 void enable_dump_option (DumpOption option) { dump_options.insert (option); }
208
209 void enable_all_dump_options ()
210 {
211 enable_dump_option (DumpOption::LEXER_DUMP);
212 enable_dump_option (DumpOption::PARSER_AST_DUMP);
213 enable_dump_option (DumpOption::AST_DUMP_PRETTY);
214 enable_dump_option (DumpOption::REGISTER_PLUGINS_DUMP);
215 enable_dump_option (DumpOption::INJECTION_DUMP);
216 enable_dump_option (DumpOption::EXPANSION_DUMP);
217 enable_dump_option (DumpOption::RESOLUTION_DUMP);
218 enable_dump_option (DumpOption::TARGET_OPTION_DUMP);
219 enable_dump_option (DumpOption::HIR_DUMP);
220 enable_dump_option (DumpOption::HIR_DUMP_PRETTY);
221 enable_dump_option (DumpOption::TYPE_RESOLUTION_DUMP);
222 }
223
224 void set_crate_name (std::string name)
225 {
226 rust_assert (!name.empty ());
227
228 crate_name = std::move (name);
229 }
230
231 const std::string &get_crate_name () const
232 {
233 rust_assert (!crate_name.empty ());
234 return crate_name;
235 }
236
237 void set_edition (int raw_edition)
238 {
239 edition = static_cast<Edition> (raw_edition);
240 }
241
242 const Edition &get_edition () { return edition; }
243
244 void set_metadata_output (const std::string &path)
245 {
246 metadata_output_path = path;
247 }
248
249 const std::string &get_metadata_output () const
250 {
251 return metadata_output_path;
252 }
253
254 bool metadata_output_path_set () const
255 {
256 return !metadata_output_path.empty ();
257 }
258};
259
260/* Defines a compiler session. This is for a single compiler invocation, so
261 * potentially includes parsing multiple crates. */
262struct Session
263{
264 CompileOptions options;
265 /* This should really be in a per-crate storage area but it is wiped with
266 * every file so eh. */
267 std::string injected_crate_name;
268
269 /* extra files get included during late stages of compilation (e.g. macro
270 * expansion) */
271 std::vector<std::string> extra_files;
272
273 // backend wrapper to GCC GENERIC
274 Backend *backend;
275
276 // backend linemap
277 Linemap *linemap;
278
279 // mappings
280 Analysis::Mappings *mappings;
281
282public:
283 /* Get a reference to the static session instance */
284 static Session &get_instance ();
285
286 Session () = default;
287 ~Session () = default;
288
289 /* This initializes the compiler session. Corresponds to langhook
290 * grs_langhook_init(). Note that this is called after option handling. */
291 void init ();
292
293 // delete those constructors so we don't access the singleton in any
294 // other way than via `get_instance()`
295 Session (Session const &) = delete;
296 void operator= (Session const &) = delete;
297
298 bool handle_option (enum opt_code code, const char *arg, HOST_WIDE_INT value,
299 int kind, location_t loc,
300 const struct cl_option_handlers *handlers);
301 void handle_input_files (int num_files, const char **files);
302 void init_options ();
303 void handle_crate_name (const AST::Crate &parsed_crate);
304
305 /* This function saves the filename data into the session manager using the
306 * `move` semantics, and returns a C-style string referencing the input
307 * std::string */
308 inline const char *include_extra_file (std::string filename)
309 {
310 extra_files.push_back (std::move (filename));
311 return extra_files.back ().c_str ();
312 }
313
314 NodeId load_extern_crate (const std::string &crate_name, Location locus);
315
316private:
317 void compile_crate (const char *filename);
318 bool enable_dump (std::string arg);
319
320 void dump_lex (Parser<Lexer> &parser) const;
321 void dump_ast (Parser<Lexer> &parser, AST::Crate &crate) const;
322 void dump_ast_pretty (AST::Crate &crate) const;
323 void dump_ast_expanded (Parser<Lexer> &parser, AST::Crate &crate) const;
324 void dump_hir (HIR::Crate &crate) const;
325 void dump_hir_pretty (HIR::Crate &crate) const;
326 void dump_type_resolution (HIR::Crate &crate) const;
327
328 // pipeline stages - TODO maybe move?
329 /* Register plugins pipeline stage. TODO maybe move to another object?
330 * Currently dummy stage. In future will handle attribute injection
331 * (top-level inner attribute creation from command line arguments), setting
332 * options maybe, registering lints maybe, loading plugins maybe. */
333 void register_plugins (AST::Crate &crate);
334
335 /* Injection pipeline stage. TODO maybe move to another object? Maybe have
336 * some lint checks (in future, obviously), register builtin macros, crate
337 * injection. */
338 void injection (AST::Crate &crate);
339
340 /* Expansion pipeline stage. TODO maybe move to another object? Expands all
341 * macros, maybe build test harness in future, AST validation, maybe create
342 * macro crate (if not rustdoc).*/
343 void expansion (AST::Crate &crate);
344
345 // handle cfg_option
346 bool handle_cfg_option (std::string &data);
347};
348
349} // namespace Rust
350
351#if CHECKING_P
352namespace selftest {
353extern void
354rust_crate_name_validation_test (void);
355}
356#endif // CHECKING_P
357
358#endif