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 16251 : fncontext (tree fndecl, ::Bvariable *ret_addr, TyTy::BaseType *retty)
40 16251 : : 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 294014 : tree insert_compiled_type (tree type)
76 : {
77 294014 : hashval_t h = type_hasher (type);
78 294014 : auto it = compiled_type_map.find (h);
79 294014 : if (it != compiled_type_map.end ())
80 201995 : return it->second;
81 :
82 92019 : compiled_type_map.insert ({h, type});
83 :
84 92019 : if (TYPE_NAME (type) != NULL)
85 92019 : push_type (type);
86 :
87 : return type;
88 : }
89 :
90 22525 : bool lookup_compiled_adt (const TyTy::ADTType &adt, tree *type) const
91 : {
92 22525 : auto it = compiled_adt_types.find (compiled_adt_key (adt));
93 22525 : if (it == compiled_adt_types.end ())
94 : return false;
95 :
96 38 : *type = it->second;
97 38 : return true;
98 : }
99 :
100 19 : void insert_compiled_adt (const TyTy::ADTType &adt, tree type)
101 : {
102 19 : auto key = compiled_adt_key (adt);
103 19 : rust_assert (compiled_adt_types.find (key) == compiled_adt_types.end ());
104 19 : compiled_adt_types.insert ({key, type});
105 19 : }
106 :
107 : void erase_compiled_adt (const TyTy::ADTType &adt)
108 : {
109 : rust_assert (compiled_adt_types.erase (compiled_adt_key (adt)) == 1);
110 : }
111 :
112 13899 : tree insert_main_variant (tree type)
113 : {
114 13899 : hashval_t h = type_hasher (type);
115 13899 : auto it = main_variants.find (h);
116 13899 : if (it != main_variants.end ())
117 8877 : return it->second;
118 :
119 5022 : main_variants.insert ({h, type});
120 5022 : return type;
121 : }
122 :
123 392929 : Resolver::TypeCheckContext *get_tyctx () { return tyctx; }
124 247382 : Analysis::Mappings &get_mappings () { return mappings; }
125 :
126 46164 : void push_block (tree scope)
127 : {
128 46164 : scope_stack.push_back (scope);
129 46164 : statements.push_back ({});
130 46164 : block_drop_candidates.emplace_back ();
131 46164 : }
132 :
133 6845 : tree pop_block () { return pop_block_impl (NULL_TREE, UNKNOWN_LOCATION); }
134 :
135 39303 : tree pop_block_with_cleanup (tree cleanup, location_t cleanup_locus)
136 : {
137 39303 : return pop_block_impl (cleanup, cleanup_locus);
138 : }
139 :
140 30384 : tree peek_enclosing_scope ()
141 : {
142 30384 : if (scope_stack.size () == 0)
143 : return nullptr;
144 :
145 30384 : return scope_stack.back ();
146 : }
147 :
148 : void add_statement_to_enclosing_scope (tree stmt)
149 : {
150 : statements.at (statements.size () - 2).push_back (stmt);
151 : }
152 :
153 126853 : void add_statement (tree stmt) { statements.back ().push_back (stmt); }
154 :
155 26517 : void insert_var_decl (HirId id, ::Bvariable *decl)
156 : {
157 26517 : compiled_var_decls[id] = decl;
158 : }
159 :
160 58457 : bool lookup_var_decl (HirId id, ::Bvariable **decl)
161 : {
162 58457 : auto it = compiled_var_decls.find (id);
163 58457 : if (it == compiled_var_decls.end ())
164 : return false;
165 :
166 44561 : *decl = it->second;
167 44561 : return true;
168 : }
169 :
170 1 : void insert_drop_flag (HirId id, ::Bvariable *flag)
171 : {
172 1 : drop_flags[{peek_fn ().fndecl, id}] = flag;
173 1 : }
174 :
175 12029 : bool lookup_drop_flag (HirId id, ::Bvariable **flag)
176 : {
177 12029 : auto it = drop_flags.find ({peek_fn ().fndecl, id});
178 12029 : if (it == drop_flags.end ())
179 : return false;
180 :
181 4 : *flag = it->second;
182 4 : return true;
183 : }
184 :
185 15901 : void insert_function_decl (const TyTy::FnType *ref, tree fn)
186 : {
187 15901 : auto id = ref->get_ty_ref ();
188 15901 : auto dId = ref->get_id ();
189 :
190 15901 : rust_assert (compiled_fn_map.find (id) == compiled_fn_map.end ());
191 15901 : compiled_fn_map[id] = fn;
192 :
193 15901 : auto it = mono_fns.find (dId);
194 15901 : if (it == mono_fns.end ())
195 15636 : mono_fns[dId] = {};
196 :
197 15901 : mono_fns[dId].emplace_back (ref, fn);
198 15901 : }
199 :
200 61 : void insert_closure_decl (const TyTy::ClosureType *ref, tree fn)
201 : {
202 61 : auto dId = ref->get_def_id ();
203 61 : auto it = mono_closure_fns.find (dId);
204 61 : if (it == mono_closure_fns.end ())
205 61 : mono_closure_fns[dId] = {};
206 :
207 61 : mono_closure_fns[dId].emplace_back (ref, fn);
208 61 : }
209 :
210 : tree lookup_closure_decl (const TyTy::ClosureType *ref)
211 : {
212 : auto dId = ref->get_def_id ();
213 : auto it = mono_closure_fns.find (dId);
214 : if (it == mono_closure_fns.end ())
215 : return error_mark_node;
216 :
217 : for (auto &i : it->second)
218 : {
219 : const TyTy::ClosureType *t = i.first;
220 : tree fn = i.second;
221 :
222 : if (ref->is_equal (*t))
223 : return fn;
224 : }
225 :
226 : return error_mark_node;
227 : }
228 :
229 34785 : bool lookup_function_decl (HirId id, tree *fn, DefId dId = UNKNOWN_DEFID,
230 : const TyTy::BaseType *ref = nullptr,
231 : const std::string &asm_name = std::string ())
232 : {
233 : // for for any monomorphized fns
234 34785 : if (ref != nullptr)
235 : {
236 23365 : rust_assert (dId != UNKNOWN_DEFID);
237 :
238 23365 : auto it = mono_fns.find (dId);
239 23365 : if (it == mono_fns.end ())
240 : return false;
241 :
242 4909 : for (auto &e : mono_fns[dId])
243 : {
244 4651 : const TyTy::BaseType *r = e.first;
245 4651 : tree f = e.second;
246 :
247 4651 : if (ref->is_equal (*r))
248 : {
249 4280 : *fn = f;
250 4280 : return true;
251 : }
252 :
253 371 : if (DECL_ASSEMBLER_NAME_SET_P (f) && !asm_name.empty ())
254 : {
255 332 : tree raw = DECL_ASSEMBLER_NAME_RAW (f);
256 332 : const char *rptr = IDENTIFIER_POINTER (raw);
257 :
258 332 : bool lengths_match_p
259 332 : = IDENTIFIER_LENGTH (raw) == asm_name.size ();
260 332 : if (lengths_match_p
261 332 : && strncmp (rptr, asm_name.c_str (),
262 331 : IDENTIFIER_LENGTH (raw))
263 : == 0)
264 : {
265 0 : *fn = f;
266 0 : return true;
267 : }
268 : }
269 : }
270 : return false;
271 : }
272 :
273 11420 : auto it = compiled_fn_map.find (id);
274 11420 : if (it == compiled_fn_map.end ())
275 : return false;
276 :
277 5877 : *fn = it->second;
278 5877 : return true;
279 : }
280 :
281 533 : void insert_const_decl (HirId id, tree expr) { compiled_consts[id] = expr; }
282 :
283 47573 : bool lookup_const_decl (HirId id, tree *expr)
284 : {
285 47573 : auto it = compiled_consts.find (id);
286 47573 : if (it == compiled_consts.end ())
287 : return false;
288 :
289 641 : *expr = it->second;
290 641 : return true;
291 : }
292 :
293 : void insert_label_decl (HirId id, tree label) { compiled_labels[id] = label; }
294 :
295 0 : bool lookup_label_decl (HirId id, tree *label)
296 : {
297 0 : auto it = compiled_labels.find (id);
298 0 : if (it == compiled_labels.end ())
299 : return false;
300 :
301 0 : *label = it->second;
302 0 : return true;
303 : }
304 :
305 54 : void insert_break_label (HirId id, tree label)
306 : {
307 54 : compiled_break_labels[id] = label;
308 : }
309 :
310 33 : tl::optional<tree> lookup_break_label (HirId id)
311 : {
312 33 : auto it = compiled_break_labels.find (id);
313 33 : if (it == compiled_break_labels.end ())
314 0 : return tl::nullopt;
315 33 : return it->second;
316 : }
317 :
318 51 : void insert_continue_label (HirId id, tree label)
319 : {
320 51 : compiled_continue_labels[id] = label;
321 : }
322 :
323 6 : tl::optional<tree> lookup_continue_label (HirId id)
324 : {
325 6 : auto it = compiled_continue_labels.find (id);
326 6 : if (it == compiled_continue_labels.end ())
327 0 : return tl::nullopt;
328 6 : return it->second;
329 : }
330 :
331 933 : void insert_pattern_binding (HirId id, tree binding)
332 : {
333 933 : implicit_pattern_bindings[id] = binding;
334 : }
335 :
336 13841 : bool lookup_pattern_binding (HirId id, tree *binding)
337 : {
338 13841 : auto it = implicit_pattern_bindings.find (id);
339 13841 : if (it == implicit_pattern_bindings.end ())
340 : return false;
341 :
342 877 : *binding = it->second;
343 877 : return true;
344 : }
345 :
346 167 : void insert_vtable (std::pair<size_t, size_t> pair, ::Bvariable *vtable)
347 : {
348 167 : compiled_vtables[pair] = vtable;
349 : }
350 :
351 174 : bool lookup_vtable (std::pair<size_t, size_t> pair, ::Bvariable **vtable)
352 : {
353 174 : auto it = compiled_vtables.find (pair);
354 174 : if (it == compiled_vtables.end ())
355 : return false;
356 :
357 7 : *vtable = it->second;
358 7 : return true;
359 : }
360 :
361 16251 : void push_fn (tree fn, ::Bvariable *ret_addr, TyTy::BaseType *retty)
362 : {
363 16251 : fn_stack.emplace_back (fn, ret_addr, retty);
364 : }
365 16251 : void pop_fn () { fn_stack.pop_back (); }
366 :
367 4435 : bool in_fn () { return fn_stack.size () != 0; }
368 :
369 : // Note: it is undefined behavior to call peek_fn () if fn_stack is empty.
370 71506 : fncontext peek_fn ()
371 : {
372 71506 : rust_assert (!fn_stack.empty ());
373 71506 : return fn_stack.back ();
374 : }
375 :
376 92019 : void push_type (tree t) { type_decls.push_back (t); }
377 222 : void push_var (::Bvariable *v) { var_decls.push_back (v); }
378 533 : void push_const (tree c) { const_decls.push_back (c); }
379 17622 : void push_function (tree f) { func_decls.push_back (f); }
380 :
381 4415 : void write_to_backend ()
382 : {
383 4415 : Backend::write_global_definitions (type_decls, const_decls, func_decls,
384 4415 : var_decls);
385 : }
386 :
387 0 : bool function_completed (tree fn)
388 : {
389 0 : for (auto it = func_decls.begin (); it != func_decls.end (); it++)
390 : {
391 0 : tree i = (*it);
392 0 : if (i == fn)
393 : {
394 : return true;
395 : }
396 : }
397 : return false;
398 : }
399 :
400 244 : void push_loop_context (Bvariable *var) { loop_value_stack.push_back (var); }
401 :
402 42 : bool have_loop_context () const { return !loop_value_stack.empty (); }
403 :
404 17 : Bvariable *peek_loop_context ()
405 : {
406 17 : rust_assert (!loop_value_stack.empty ());
407 17 : return loop_value_stack.back ();
408 : }
409 :
410 147 : Bvariable *pop_loop_context ()
411 : {
412 147 : auto back = loop_value_stack.back ();
413 147 : loop_value_stack.pop_back ();
414 147 : return back;
415 : }
416 :
417 244 : void push_loop_begin_label (tree label)
418 : {
419 244 : loop_begin_labels.push_back (label);
420 : }
421 :
422 25 : tree peek_loop_begin_label ()
423 : {
424 25 : rust_assert (!loop_begin_labels.empty ());
425 25 : return loop_begin_labels.back ();
426 : }
427 :
428 244 : tree pop_loop_begin_label ()
429 : {
430 244 : tree pop = loop_begin_labels.back ();
431 244 : loop_begin_labels.pop_back ();
432 244 : return pop;
433 : }
434 :
435 244 : void push_loop_end_label (tree label) { loop_end_labels.push_back (label); }
436 :
437 : tree peek_loop_end_label ()
438 : {
439 : rust_assert (!loop_end_labels.empty ());
440 : return loop_end_labels.back ();
441 : }
442 :
443 244 : tree pop_loop_end_label ()
444 : {
445 244 : rust_assert (!loop_end_labels.empty ());
446 244 : tree pop = loop_end_labels.back ();
447 244 : loop_end_labels.pop_back ();
448 244 : return pop;
449 : }
450 :
451 3932 : void push_const_context (void) { const_context++; }
452 3932 : void pop_const_context (void)
453 : {
454 3932 : if (const_context > 0)
455 3932 : const_context--;
456 : }
457 27443 : bool const_context_p (void) { return (const_context > 0); }
458 :
459 35091 : std::string mangle_item (const TyTy::BaseType *ty,
460 : const Resolver::CanonicalPath &path)
461 : {
462 35091 : return mangler.mangle_item (this, ty, path);
463 : }
464 :
465 : void push_closure_context (HirId id);
466 : void pop_closure_context ();
467 : void insert_closure_binding (HirId id, tree expr);
468 : bool lookup_closure_binding (HirId id, tree *expr);
469 :
470 : std::vector<tree> &get_type_decls () { return type_decls; }
471 4394 : std::vector<::Bvariable *> &get_var_decls () { return var_decls; }
472 4394 : std::vector<tree> &get_const_decls () { return const_decls; }
473 4394 : std::vector<tree> &get_func_decls () { return func_decls; }
474 :
475 : static hashval_t type_hasher (tree type);
476 :
477 0 : void collect_attribute_proc_macro (tree fndecl)
478 : {
479 0 : attribute_macros.push_back (fndecl);
480 : }
481 :
482 0 : void collect_bang_proc_macro (tree fndecl) { bang_macros.push_back (fndecl); }
483 :
484 0 : void collect_derive_proc_macro (CustomDeriveInfo macro)
485 : {
486 0 : custom_derive_macros.push_back (macro);
487 : }
488 :
489 0 : const std::vector<tree> &get_bang_proc_macros () const { return bang_macros; }
490 : const std::vector<tree> &get_attribute_proc_macros () const
491 : {
492 0 : return attribute_macros;
493 : }
494 : const std::vector<CustomDeriveInfo> &get_derive_proc_macros () const
495 : {
496 0 : return custom_derive_macros;
497 : }
498 :
499 : private:
500 : friend class DropBuilder;
501 : Context ();
502 :
503 : static hashval_t type_hasher (tree type, hash_set<tree> &active_types);
504 :
505 46148 : tree pop_block_impl (tree cleanup, location_t cleanup_locus)
506 : {
507 46148 : auto block = scope_stack.back ();
508 46148 : scope_stack.pop_back ();
509 :
510 46148 : auto stmts = statements.back ();
511 46148 : statements.pop_back ();
512 :
513 46148 : rust_assert (!block_drop_candidates.empty ());
514 46148 : block_drop_candidates.pop_back ();
515 :
516 46148 : if (cleanup != NULL_TREE)
517 : {
518 50 : tree body = Backend::statement_list (stmts);
519 50 : if (body == NULL_TREE)
520 0 : body = build_empty_stmt (cleanup_locus);
521 :
522 50 : tree exceptional_cleanup = build_empty_stmt (cleanup_locus);
523 50 : tree cleanup_selector
524 50 : = build2_loc (cleanup_locus, EH_ELSE_EXPR, void_type_node, cleanup,
525 : exceptional_cleanup);
526 :
527 50 : tree try_finally
528 50 : = Backend::exception_handler_statement (body, NULL_TREE,
529 : cleanup_selector,
530 : cleanup_locus);
531 50 : Backend::block_add_statements (block, {try_finally});
532 : }
533 : else
534 46098 : Backend::block_add_statements (block, stmts);
535 :
536 46148 : return block;
537 46148 : }
538 :
539 : // we cant just use DefId because we can setup Adt<u32> vs Adt<i32> so the
540 : // tyref gets us the uniqueness we need
541 22544 : static std::pair<DefId, HirId> compiled_adt_key (const TyTy::ADTType &adt)
542 : {
543 22544 : HirId substitution
544 22544 : = adt.has_substitutions_defined () ? adt.get_ty_ref () : UNKNOWN_HIRID;
545 22544 : return {adt.get_id (), substitution};
546 : }
547 :
548 : Resolver::TypeCheckContext *tyctx;
549 : Analysis::Mappings &mappings;
550 : Mangler mangler;
551 :
552 : // state
553 : std::vector<fncontext> fn_stack;
554 : std::map<HirId, ::Bvariable *> compiled_var_decls;
555 : std::map<std::pair<tree, HirId>, ::Bvariable *> drop_flags;
556 : std::map<hashval_t, tree> compiled_type_map;
557 : std::map<std::pair<DefId, HirId>, tree> compiled_adt_types;
558 : std::map<HirId, tree> compiled_fn_map;
559 : std::map<HirId, tree> compiled_consts;
560 : std::map<HirId, tree> compiled_labels;
561 : std::map<std::pair<size_t, size_t>, ::Bvariable *> compiled_vtables;
562 : std::map<HirId, tree> compiled_break_labels;
563 : std::map<HirId, tree> compiled_continue_labels;
564 : std::vector<::std::vector<tree>> statements;
565 : std::vector<tree> scope_stack;
566 : std::vector<::std::vector<DropCandidate>> block_drop_candidates;
567 : std::vector<::Bvariable *> loop_value_stack;
568 : std::vector<tree> loop_begin_labels;
569 : std::vector<tree> loop_end_labels;
570 : std::map<DefId, std::vector<std::pair<const TyTy::BaseType *, tree>>>
571 : mono_fns;
572 : std::map<DefId, std::vector<std::pair<const TyTy::ClosureType *, tree>>>
573 : mono_closure_fns;
574 : std::map<HirId, tree> implicit_pattern_bindings;
575 : std::map<hashval_t, tree> main_variants;
576 :
577 : std::vector<CustomDeriveInfo> custom_derive_macros;
578 : std::vector<tree> attribute_macros;
579 : std::vector<tree> bang_macros;
580 :
581 : // closure bindings
582 : std::vector<HirId> closure_scope_bindings;
583 : std::map<HirId, std::map<HirId, tree>> closure_bindings;
584 :
585 : // To GCC middle-end
586 : std::vector<tree> type_decls;
587 : std::vector<::Bvariable *> var_decls;
588 : std::vector<tree> const_decls;
589 : std::vector<tree> func_decls;
590 :
591 : // Nonzero iff we are currently compiling something inside a constant context.
592 : unsigned int const_context = 0;
593 : };
594 :
595 : } // namespace Compile
596 : } // namespace Rust
597 :
598 : #endif // RUST_COMPILE_CONTEXT
|