1 // Copyright (C) 2020-2023 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"
29 #include "rust-system.h"
30 #include "coretypes.h"
34 // parser forward decl
35 template <typename ManagedTokenSource
> class Parser
;
46 /* Data related to target, most useful for conditional compilation and
50 /* TODO: maybe make private and access through helpers to allow changes to
52 std::unordered_map
<std::string
, std::unordered_set
<std::string
> > features
;
55 // Returns whether a key is defined in the feature set.
56 bool has_key (std::string key
) const
58 return features
.find (key
) != features
.end ();
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
64 auto it
= features
.find (key
);
65 if (it
!= features
.end ())
67 auto set
= it
->second
;
68 auto it2
= set
.find (value
);
69 if (it2
!= set
.end ())
75 /* Returns the singular value from the key, or if the key has multiple, an
77 std::string
get_singular_value (std::string key
) const
79 auto it
= features
.find (key
);
80 if (it
!= features
.end ())
82 auto set
= it
->second
;
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
93 auto it
= features
.find (key
);
94 if (it
!= features
.end ())
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
)
105 .insert (std::make_pair (key
, std::unordered_set
<std::string
> ()))
109 // Inserts a key-value pair into the feature set.
110 void insert_key_value_pair (std::string key
, std::string value
)
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
);
117 // Dump all target options to stderr.
118 void dump_target_options () const;
120 /* Creates derived values and implicit enables after all target info is
121 * added (e.g. "unix"). */
122 void init_derived_values ();
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
);
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.
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). */
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
157 * - debug_assertions: seems to "is defined"
158 * - proc_macro: no idea, bad docs. seems to be boolean, so maybe "is
163 // Defines compiler options (e.g. dump, etc.).
164 struct CompileOptions
171 REGISTER_PLUGINS_DUMP
,
178 TYPE_RESOLUTION_DUMP
,
181 std::set
<DumpOption
> dump_options
;
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
;
202 enum class CompileStep
218 bool dump_option_enabled (DumpOption option
) const
220 return dump_options
.find (option
) != dump_options
.end ();
223 void enable_dump_option (DumpOption option
) { dump_options
.insert (option
); }
225 void enable_all_dump_options ()
227 enable_dump_option (DumpOption::LEXER_DUMP
);
228 enable_dump_option (DumpOption::PARSER_AST_DUMP
);
229 enable_dump_option (DumpOption::AST_DUMP_PRETTY
);
230 enable_dump_option (DumpOption::REGISTER_PLUGINS_DUMP
);
231 enable_dump_option (DumpOption::INJECTION_DUMP
);
232 enable_dump_option (DumpOption::EXPANSION_DUMP
);
233 enable_dump_option (DumpOption::RESOLUTION_DUMP
);
234 enable_dump_option (DumpOption::TARGET_OPTION_DUMP
);
235 enable_dump_option (DumpOption::HIR_DUMP
);
236 enable_dump_option (DumpOption::HIR_DUMP_PRETTY
);
237 enable_dump_option (DumpOption::TYPE_RESOLUTION_DUMP
);
240 void set_crate_name (std::string name
)
242 rust_assert (!name
.empty ());
244 crate_name
= std::move (name
);
247 const std::string
&get_crate_name () const
249 rust_assert (!crate_name
.empty ());
253 void set_edition (int raw_edition
)
255 edition
= static_cast<Edition
> (raw_edition
);
258 const Edition
&get_edition () const { return edition
; }
260 void set_compile_step (int raw_step
)
262 compile_until
= static_cast<CompileStep
> (raw_step
);
265 const CompileStep
&get_compile_until () const { return compile_until
; }
267 void set_metadata_output (const std::string
&path
)
269 metadata_output_path
= path
;
272 const std::string
&get_metadata_output () const
274 return metadata_output_path
;
277 bool metadata_output_path_set () const
279 return !metadata_output_path
.empty ();
283 /* Defines a compiler session. This is for a single compiler invocation, so
284 * potentially includes parsing multiple crates. */
287 CompileOptions options
;
288 /* This should really be in a per-crate storage area but it is wiped with
289 * every file so eh. */
290 std::string injected_crate_name
;
292 /* extra files get included during late stages of compilation (e.g. macro
294 std::vector
<std::string
> extra_files
;
296 // backend wrapper to GCC GENERIC
303 Analysis::Mappings
*mappings
;
306 /* Get a reference to the static session instance */
307 static Session
&get_instance ();
309 Session () = default;
310 ~Session () = default;
312 /* This initializes the compiler session. Corresponds to langhook
313 * grs_langhook_init(). Note that this is called after option handling. */
316 // delete those constructors so we don't access the singleton in any
317 // other way than via `get_instance()`
318 Session (Session
const &) = delete;
319 void operator= (Session
const &) = delete;
321 bool handle_option (enum opt_code code
, const char *arg
, HOST_WIDE_INT value
,
322 int kind
, location_t loc
,
323 const struct cl_option_handlers
*handlers
);
324 void handle_input_files (int num_files
, const char **files
);
325 void init_options ();
326 void handle_crate_name (const AST::Crate
&parsed_crate
);
328 /* This function saves the filename data into the session manager using the
329 * `move` semantics, and returns a C-style string referencing the input
331 inline const char *include_extra_file (std::string filename
)
333 extra_files
.push_back (std::move (filename
));
334 return extra_files
.back ().c_str ();
337 NodeId
load_extern_crate (const std::string
&crate_name
, Location locus
);
340 void compile_crate (const char *filename
);
341 bool enable_dump (std::string arg
);
343 void dump_lex (Parser
<Lexer
> &parser
) const;
344 void dump_ast (Parser
<Lexer
> &parser
, AST::Crate
&crate
) const;
345 void dump_ast_pretty (AST::Crate
&crate
, bool expanded
= false) const;
346 void dump_ast_expanded (Parser
<Lexer
> &parser
, AST::Crate
&crate
) const;
347 void dump_hir (HIR::Crate
&crate
) const;
348 void dump_hir_pretty (HIR::Crate
&crate
) const;
349 void dump_type_resolution (HIR::Crate
&crate
) const;
351 // pipeline stages - TODO maybe move?
352 /* Register plugins pipeline stage. TODO maybe move to another object?
353 * Currently dummy stage. In future will handle attribute injection
354 * (top-level inner attribute creation from command line arguments), setting
355 * options maybe, registering lints maybe, loading plugins maybe. */
356 void register_plugins (AST::Crate
&crate
);
358 /* Injection pipeline stage. TODO maybe move to another object? Maybe have
359 * some lint checks (in future, obviously), register builtin macros, crate
361 void injection (AST::Crate
&crate
);
363 /* Expansion pipeline stage. TODO maybe move to another object? Expands all
364 * macros, maybe build test harness in future, AST validation, maybe create
365 * macro crate (if not rustdoc).*/
366 void expansion (AST::Crate
&crate
);
369 bool handle_cfg_option (std::string
&data
);
377 rust_crate_name_validation_test (void);