Line data Source code
1 : // Copyright (C) 2020-2026 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 :
19 : #ifndef RUST_COMPILE_CONTEXT
20 : #define RUST_COMPILE_CONTEXT
21 :
22 : #include "optional.h"
23 : #include "rust-system.h"
24 : #include "rust-compile-drop-candidate.h"
25 : #include "rust-hir-map.h"
26 : #include "rust-name-resolver.h"
27 : #include "rust-hir-type-check.h"
28 : #include "rust-backend.h"
29 : #include "rust-hir-full.h"
30 : #include "rust-mangle.h"
31 : #include "rust-tree.h"
32 : #include "rust-finalized-name-resolution-context.h"
33 :
34 : namespace Rust {
35 : namespace Compile {
36 :
37 : struct fncontext
38 : {
39 15027 : fncontext (tree fndecl, ::Bvariable *ret_addr, TyTy::BaseType *retty)
40 15027 : : fndecl (fndecl), ret_addr (ret_addr), retty (retty)
41 : {}
42 :
43 : tree fndecl;
44 : ::Bvariable *ret_addr;
45 : TyTy::BaseType *retty;
46 : };
47 :
48 0 : struct CustomDeriveInfo
49 : {
50 : tree fndecl;
51 : std::string trait_name;
52 : std::vector<std::string> attributes;
53 : };
54 :
55 : class DropBuilder;
56 :
57 : class Context
58 : {
59 : public:
60 : static Context *get ();
61 :
62 : void setup_builtins ();
63 :
64 : bool lookup_compiled_types (tree t, tree *type)
65 : {
66 : hashval_t h = type_hasher (t);
67 : auto it = compiled_type_map.find (h);
68 : if (it == compiled_type_map.end ())
69 : return false;
70 :
71 : *type = it->second;
72 : return true;
73 : }
74 :
75 277625 : tree insert_compiled_type (tree type)
76 : {
77 277625 : hashval_t h = type_hasher (type);
78 277625 : auto it = compiled_type_map.find (h);
79 277625 : if (it != compiled_type_map.end ())
80 188510 : return it->second;
81 :
82 89115 : compiled_type_map.insert ({h, type});
83 :
84 89115 : if (TYPE_NAME (type) != NULL)
85 89115 : push_type (type);
86 :
87 : return type;
88 : }
89 :
90 13465 : tree insert_main_variant (tree type)
91 : {
92 13465 : hashval_t h = type_hasher (type);
93 13465 : auto it = main_variants.find (h);
94 13465 : if (it != main_variants.end ())
95 8596 : return it->second;
96 :
97 4869 : main_variants.insert ({h, type});
98 4869 : return type;
99 : }
100 :
101 369202 : Resolver::TypeCheckContext *get_tyctx () { return tyctx; }
102 220813 : Analysis::Mappings &get_mappings () { return mappings; }
103 :
104 42779 : void push_block (tree scope)
105 : {
106 42779 : scope_stack.push_back (scope);
107 42779 : statements.push_back ({});
108 42779 : block_drop_candidates.emplace_back ();
109 42779 : }
110 :
111 6295 : tree pop_block () { return pop_block_impl (NULL_TREE, UNKNOWN_LOCATION); }
112 :
113 36468 : tree pop_block_with_cleanup (tree cleanup, location_t cleanup_locus)
114 : {
115 36468 : return pop_block_impl (cleanup, cleanup_locus);
116 : }
117 :
118 27627 : tree peek_enclosing_scope ()
119 : {
120 28747 : if (scope_stack.size () == 0)
121 : return nullptr;
122 :
123 28747 : return scope_stack.back ();
124 : }
125 :
126 : void add_statement_to_enclosing_scope (tree stmt)
127 : {
128 : statements.at (statements.size () - 2).push_back (stmt);
129 : }
130 :
131 118815 : void add_statement (tree stmt) { statements.back ().push_back (stmt); }
132 :
133 24477 : void insert_var_decl (HirId id, ::Bvariable *decl)
134 : {
135 24477 : compiled_var_decls[id] = decl;
136 : }
137 :
138 54746 : bool lookup_var_decl (HirId id, ::Bvariable **decl)
139 : {
140 54746 : auto it = compiled_var_decls.find (id);
141 54746 : if (it == compiled_var_decls.end ())
142 : return false;
143 :
144 41724 : *decl = it->second;
145 41724 : return true;
146 : }
147 :
148 14816 : void insert_function_decl (const TyTy::FnType *ref, tree fn)
149 : {
150 14816 : auto id = ref->get_ty_ref ();
151 14816 : auto dId = ref->get_id ();
152 :
153 14816 : rust_assert (compiled_fn_map.find (id) == compiled_fn_map.end ());
154 14816 : compiled_fn_map[id] = fn;
155 :
156 14816 : auto it = mono_fns.find (dId);
157 14816 : if (it == mono_fns.end ())
158 14569 : mono_fns[dId] = {};
159 :
160 14816 : mono_fns[dId].emplace_back (ref, fn);
161 14816 : }
162 :
163 61 : void insert_closure_decl (const TyTy::ClosureType *ref, tree fn)
164 : {
165 61 : auto dId = ref->get_def_id ();
166 61 : auto it = mono_closure_fns.find (dId);
167 61 : if (it == mono_closure_fns.end ())
168 61 : mono_closure_fns[dId] = {};
169 :
170 61 : mono_closure_fns[dId].emplace_back (ref, fn);
171 61 : }
172 :
173 : tree lookup_closure_decl (const TyTy::ClosureType *ref)
174 : {
175 : auto dId = ref->get_def_id ();
176 : auto it = mono_closure_fns.find (dId);
177 : if (it == mono_closure_fns.end ())
178 : return error_mark_node;
179 :
180 : for (auto &i : it->second)
181 : {
182 : const TyTy::ClosureType *t = i.first;
183 : tree fn = i.second;
184 :
185 : if (ref->is_equal (*t))
186 : return fn;
187 : }
188 :
189 : return error_mark_node;
190 : }
191 :
192 32241 : bool lookup_function_decl (HirId id, tree *fn, DefId dId = UNKNOWN_DEFID,
193 : const TyTy::BaseType *ref = nullptr,
194 : const std::string &asm_name = std::string ())
195 : {
196 : // for for any monomorphized fns
197 32241 : if (ref != nullptr)
198 : {
199 21568 : rust_assert (dId != UNKNOWN_DEFID);
200 :
201 21568 : auto it = mono_fns.find (dId);
202 21568 : if (it == mono_fns.end ())
203 : return false;
204 :
205 4554 : for (auto &e : mono_fns[dId])
206 : {
207 4314 : const TyTy::BaseType *r = e.first;
208 4314 : tree f = e.second;
209 :
210 4314 : if (ref->is_equal (*r))
211 : {
212 3971 : *fn = f;
213 3971 : return true;
214 : }
215 :
216 343 : if (DECL_ASSEMBLER_NAME_SET_P (f) && !asm_name.empty ())
217 : {
218 304 : tree raw = DECL_ASSEMBLER_NAME_RAW (f);
219 304 : const char *rptr = IDENTIFIER_POINTER (raw);
220 :
221 304 : bool lengths_match_p
222 304 : = IDENTIFIER_LENGTH (raw) == asm_name.size ();
223 304 : if (lengths_match_p
224 304 : && strncmp (rptr, asm_name.c_str (),
225 303 : IDENTIFIER_LENGTH (raw))
226 : == 0)
227 : {
228 0 : *fn = f;
229 0 : return true;
230 : }
231 : }
232 : }
233 : return false;
234 : }
235 :
236 10673 : auto it = compiled_fn_map.find (id);
237 10673 : if (it == compiled_fn_map.end ())
238 : return false;
239 :
240 5779 : *fn = it->second;
241 5779 : return true;
242 : }
243 :
244 511 : void insert_const_decl (HirId id, tree expr) { compiled_consts[id] = expr; }
245 :
246 44371 : bool lookup_const_decl (HirId id, tree *expr)
247 : {
248 44371 : auto it = compiled_consts.find (id);
249 44371 : if (it == compiled_consts.end ())
250 : return false;
251 :
252 631 : *expr = it->second;
253 631 : return true;
254 : }
255 :
256 : void insert_label_decl (HirId id, tree label) { compiled_labels[id] = label; }
257 :
258 0 : bool lookup_label_decl (HirId id, tree *label)
259 : {
260 0 : auto it = compiled_labels.find (id);
261 0 : if (it == compiled_labels.end ())
262 : return false;
263 :
264 0 : *label = it->second;
265 0 : return true;
266 : }
267 :
268 53 : void insert_break_label (HirId id, tree label)
269 : {
270 53 : compiled_break_labels[id] = label;
271 : }
272 :
273 32 : tl::optional<tree> lookup_break_label (HirId id)
274 : {
275 32 : auto it = compiled_break_labels.find (id);
276 32 : if (it == compiled_break_labels.end ())
277 0 : return tl::nullopt;
278 32 : return it->second;
279 : }
280 :
281 50 : void insert_continue_label (HirId id, tree label)
282 : {
283 50 : compiled_continue_labels[id] = label;
284 : }
285 :
286 6 : tl::optional<tree> lookup_continue_label (HirId id)
287 : {
288 6 : auto it = compiled_continue_labels.find (id);
289 6 : if (it == compiled_continue_labels.end ())
290 0 : return tl::nullopt;
291 6 : return it->second;
292 : }
293 :
294 905 : void insert_pattern_binding (HirId id, tree binding)
295 : {
296 905 : implicit_pattern_bindings[id] = binding;
297 : }
298 :
299 12971 : bool lookup_pattern_binding (HirId id, tree *binding)
300 : {
301 12971 : auto it = implicit_pattern_bindings.find (id);
302 12971 : if (it == implicit_pattern_bindings.end ())
303 : return false;
304 :
305 842 : *binding = it->second;
306 842 : return true;
307 : }
308 :
309 162 : void insert_vtable (std::pair<size_t, size_t> pair, ::Bvariable *vtable)
310 : {
311 162 : compiled_vtables[pair] = vtable;
312 : }
313 :
314 169 : bool lookup_vtable (std::pair<size_t, size_t> pair, ::Bvariable **vtable)
315 : {
316 169 : auto it = compiled_vtables.find (pair);
317 169 : if (it == compiled_vtables.end ())
318 : return false;
319 :
320 7 : *vtable = it->second;
321 7 : return true;
322 : }
323 :
324 15027 : void push_fn (tree fn, ::Bvariable *ret_addr, TyTy::BaseType *retty)
325 : {
326 15027 : fn_stack.emplace_back (fn, ret_addr, retty);
327 : }
328 15027 : void pop_fn () { fn_stack.pop_back (); }
329 :
330 4161 : bool in_fn () { return fn_stack.size () != 0; }
331 :
332 : // Note: it is undefined behavior to call peek_fn () if fn_stack is empty.
333 56024 : fncontext peek_fn ()
334 : {
335 56024 : rust_assert (!fn_stack.empty ());
336 56024 : return fn_stack.back ();
337 : }
338 :
339 89115 : void push_type (tree t) { type_decls.push_back (t); }
340 213 : void push_var (::Bvariable *v) { var_decls.push_back (v); }
341 511 : void push_const (tree c) { const_decls.push_back (c); }
342 16149 : void push_function (tree f) { func_decls.push_back (f); }
343 :
344 4301 : void write_to_backend ()
345 : {
346 4301 : Backend::write_global_definitions (type_decls, const_decls, func_decls,
347 4301 : var_decls);
348 : }
349 :
350 0 : bool function_completed (tree fn)
351 : {
352 0 : for (auto it = func_decls.begin (); it != func_decls.end (); it++)
353 : {
354 0 : tree i = (*it);
355 0 : if (i == fn)
356 : {
357 : return true;
358 : }
359 : }
360 : return false;
361 : }
362 :
363 221 : void push_loop_context (Bvariable *var) { loop_value_stack.push_back (var); }
364 :
365 38 : bool have_loop_context () const { return !loop_value_stack.empty (); }
366 :
367 16 : Bvariable *peek_loop_context ()
368 : {
369 16 : rust_assert (!loop_value_stack.empty ());
370 16 : return loop_value_stack.back ();
371 : }
372 :
373 133 : Bvariable *pop_loop_context ()
374 : {
375 133 : auto back = loop_value_stack.back ();
376 133 : loop_value_stack.pop_back ();
377 133 : return back;
378 : }
379 :
380 221 : void push_loop_begin_label (tree label)
381 : {
382 221 : loop_begin_labels.push_back (label);
383 : }
384 :
385 22 : tree peek_loop_begin_label ()
386 : {
387 22 : rust_assert (!loop_begin_labels.empty ());
388 22 : return loop_begin_labels.back ();
389 : }
390 :
391 221 : tree pop_loop_begin_label ()
392 : {
393 221 : tree pop = loop_begin_labels.back ();
394 221 : loop_begin_labels.pop_back ();
395 221 : return pop;
396 : }
397 :
398 221 : void push_loop_end_label (tree label) { loop_end_labels.push_back (label); }
399 :
400 : tree peek_loop_end_label ()
401 : {
402 : rust_assert (!loop_end_labels.empty ());
403 : return loop_end_labels.back ();
404 : }
405 :
406 221 : tree pop_loop_end_label ()
407 : {
408 221 : rust_assert (!loop_end_labels.empty ());
409 221 : tree pop = loop_end_labels.back ();
410 221 : loop_end_labels.pop_back ();
411 221 : return pop;
412 : }
413 :
414 3585 : void push_const_context (void) { const_context++; }
415 3585 : void pop_const_context (void)
416 : {
417 3585 : if (const_context > 0)
418 3585 : const_context--;
419 : }
420 14988 : bool const_context_p (void) { return (const_context > 0); }
421 :
422 31914 : std::string mangle_item (const TyTy::BaseType *ty,
423 : const Resolver::CanonicalPath &path)
424 : {
425 31914 : return mangler.mangle_item (this, ty, path);
426 : }
427 :
428 : void push_closure_context (HirId id);
429 : void pop_closure_context ();
430 : void insert_closure_binding (HirId id, tree expr);
431 : bool lookup_closure_binding (HirId id, tree *expr);
432 :
433 : std::vector<tree> &get_type_decls () { return type_decls; }
434 4284 : std::vector<::Bvariable *> &get_var_decls () { return var_decls; }
435 4284 : std::vector<tree> &get_const_decls () { return const_decls; }
436 4284 : std::vector<tree> &get_func_decls () { return func_decls; }
437 :
438 : static hashval_t type_hasher (tree type);
439 :
440 0 : void collect_attribute_proc_macro (tree fndecl)
441 : {
442 0 : attribute_macros.push_back (fndecl);
443 : }
444 :
445 0 : void collect_bang_proc_macro (tree fndecl) { bang_macros.push_back (fndecl); }
446 :
447 0 : void collect_derive_proc_macro (CustomDeriveInfo macro)
448 : {
449 0 : custom_derive_macros.push_back (macro);
450 : }
451 :
452 0 : const std::vector<tree> &get_bang_proc_macros () const { return bang_macros; }
453 : const std::vector<tree> &get_attribute_proc_macros () const
454 : {
455 0 : return attribute_macros;
456 : }
457 : const std::vector<CustomDeriveInfo> &get_derive_proc_macros () const
458 : {
459 0 : return custom_derive_macros;
460 : }
461 :
462 : private:
463 : friend class DropBuilder;
464 : Context ();
465 :
466 42763 : tree pop_block_impl (tree cleanup, location_t cleanup_locus)
467 : {
468 42763 : auto block = scope_stack.back ();
469 42763 : scope_stack.pop_back ();
470 :
471 42763 : auto stmts = statements.back ();
472 42763 : statements.pop_back ();
473 :
474 42763 : rust_assert (!block_drop_candidates.empty ());
475 42763 : block_drop_candidates.pop_back ();
476 :
477 42763 : if (cleanup != NULL_TREE)
478 : {
479 21 : tree body = Backend::statement_list (stmts);
480 21 : if (body == NULL_TREE)
481 0 : body = build_empty_stmt (cleanup_locus);
482 :
483 21 : tree exceptional_cleanup = build_empty_stmt (cleanup_locus);
484 21 : tree cleanup_selector
485 21 : = build2_loc (cleanup_locus, EH_ELSE_EXPR, void_type_node, cleanup,
486 : exceptional_cleanup);
487 :
488 21 : tree try_finally
489 21 : = Backend::exception_handler_statement (body, NULL_TREE,
490 : cleanup_selector,
491 : cleanup_locus);
492 21 : Backend::block_add_statements (block, {try_finally});
493 : }
494 : else
495 42742 : Backend::block_add_statements (block, stmts);
496 :
497 42763 : return block;
498 42763 : }
499 :
500 : Resolver::TypeCheckContext *tyctx;
501 : Analysis::Mappings &mappings;
502 : Mangler mangler;
503 :
504 : // state
505 : std::vector<fncontext> fn_stack;
506 : std::map<HirId, ::Bvariable *> compiled_var_decls;
507 : std::map<hashval_t, tree> compiled_type_map;
508 : std::map<HirId, tree> compiled_fn_map;
509 : std::map<HirId, tree> compiled_consts;
510 : std::map<HirId, tree> compiled_labels;
511 : std::map<std::pair<size_t, size_t>, ::Bvariable *> compiled_vtables;
512 : std::map<HirId, tree> compiled_break_labels;
513 : std::map<HirId, tree> compiled_continue_labels;
514 : std::vector<::std::vector<tree>> statements;
515 : std::vector<tree> scope_stack;
516 : std::vector<::std::vector<DropCandidate>> block_drop_candidates;
517 : std::vector<::Bvariable *> loop_value_stack;
518 : std::vector<tree> loop_begin_labels;
519 : std::vector<tree> loop_end_labels;
520 : std::map<DefId, std::vector<std::pair<const TyTy::BaseType *, tree>>>
521 : mono_fns;
522 : std::map<DefId, std::vector<std::pair<const TyTy::ClosureType *, tree>>>
523 : mono_closure_fns;
524 : std::map<HirId, tree> implicit_pattern_bindings;
525 : std::map<hashval_t, tree> main_variants;
526 :
527 : std::vector<CustomDeriveInfo> custom_derive_macros;
528 : std::vector<tree> attribute_macros;
529 : std::vector<tree> bang_macros;
530 :
531 : // closure bindings
532 : std::vector<HirId> closure_scope_bindings;
533 : std::map<HirId, std::map<HirId, tree>> closure_bindings;
534 :
535 : // To GCC middle-end
536 : std::vector<tree> type_decls;
537 : std::vector<::Bvariable *> var_decls;
538 : std::vector<tree> const_decls;
539 : std::vector<tree> func_decls;
540 :
541 : // Nonzero iff we are currently compiling something inside a constant context.
542 : unsigned int const_context = 0;
543 : };
544 :
545 : } // namespace Compile
546 : } // namespace Rust
547 :
548 : #endif // RUST_COMPILE_CONTEXT
|