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 "rust-system.h"
23 : #include "rust-compile-drop-candidate.h"
24 : #include "rust-hir-map.h"
25 : #include "rust-name-resolver.h"
26 : #include "rust-hir-type-check.h"
27 : #include "rust-backend.h"
28 : #include "rust-hir-full.h"
29 : #include "rust-mangle.h"
30 : #include "rust-tree.h"
31 : #include "rust-finalized-name-resolution-context.h"
32 :
33 : namespace Rust {
34 : namespace Compile {
35 :
36 : struct fncontext
37 : {
38 14882 : fncontext (tree fndecl, ::Bvariable *ret_addr, TyTy::BaseType *retty)
39 14882 : : fndecl (fndecl), ret_addr (ret_addr), retty (retty)
40 : {}
41 :
42 : tree fndecl;
43 : ::Bvariable *ret_addr;
44 : TyTy::BaseType *retty;
45 : };
46 :
47 0 : struct CustomDeriveInfo
48 : {
49 : tree fndecl;
50 : std::string trait_name;
51 : std::vector<std::string> attributes;
52 : };
53 :
54 : class DropBuilder;
55 :
56 : class Context
57 : {
58 : public:
59 : static Context *get ();
60 :
61 : void setup_builtins ();
62 :
63 : bool lookup_compiled_types (tree t, tree *type)
64 : {
65 : hashval_t h = type_hasher (t);
66 : auto it = compiled_type_map.find (h);
67 : if (it == compiled_type_map.end ())
68 : return false;
69 :
70 : *type = it->second;
71 : return true;
72 : }
73 :
74 274398 : tree insert_compiled_type (tree type)
75 : {
76 274398 : hashval_t h = type_hasher (type);
77 274398 : auto it = compiled_type_map.find (h);
78 274398 : if (it != compiled_type_map.end ())
79 186597 : return it->second;
80 :
81 87801 : compiled_type_map.insert ({h, type});
82 :
83 87801 : if (TYPE_NAME (type) != NULL)
84 87801 : push_type (type);
85 :
86 : return type;
87 : }
88 :
89 13278 : tree insert_main_variant (tree type)
90 : {
91 13278 : hashval_t h = type_hasher (type);
92 13278 : auto it = main_variants.find (h);
93 13278 : if (it != main_variants.end ())
94 8492 : return it->second;
95 :
96 4786 : main_variants.insert ({h, type});
97 4786 : return type;
98 : }
99 :
100 366893 : Resolver::TypeCheckContext *get_tyctx () { return tyctx; }
101 212967 : Analysis::Mappings &get_mappings () { return mappings; }
102 :
103 29350 : void push_block (tree scope)
104 : {
105 29350 : scope_stack.push_back (scope);
106 29350 : statements.push_back ({});
107 29350 : block_drop_candidates.emplace_back ();
108 29350 : }
109 :
110 29336 : tree pop_block ()
111 : {
112 29336 : auto block = scope_stack.back ();
113 29336 : scope_stack.pop_back ();
114 :
115 29336 : auto stmts = statements.back ();
116 29336 : statements.pop_back ();
117 :
118 29336 : rust_assert (!block_drop_candidates.empty ());
119 29336 : block_drop_candidates.pop_back ();
120 :
121 29336 : Backend::block_add_statements (block, stmts);
122 :
123 29336 : return block;
124 29336 : }
125 :
126 28489 : tree peek_enclosing_scope ()
127 : {
128 28489 : if (scope_stack.size () == 0)
129 : return nullptr;
130 :
131 28489 : return scope_stack.back ();
132 : }
133 :
134 : void add_statement_to_enclosing_scope (tree stmt)
135 : {
136 : statements.at (statements.size () - 2).push_back (stmt);
137 : }
138 :
139 95103 : void add_statement (tree stmt) { statements.back ().push_back (stmt); }
140 :
141 24281 : void insert_var_decl (HirId id, ::Bvariable *decl)
142 : {
143 24281 : compiled_var_decls[id] = decl;
144 : }
145 :
146 54312 : bool lookup_var_decl (HirId id, ::Bvariable **decl)
147 : {
148 54312 : auto it = compiled_var_decls.find (id);
149 54312 : if (it == compiled_var_decls.end ())
150 : return false;
151 :
152 41421 : *decl = it->second;
153 41421 : return true;
154 : }
155 :
156 14655 : void insert_function_decl (const TyTy::FnType *ref, tree fn)
157 : {
158 14655 : auto id = ref->get_ty_ref ();
159 14655 : auto dId = ref->get_id ();
160 :
161 14655 : rust_assert (compiled_fn_map.find (id) == compiled_fn_map.end ());
162 14655 : compiled_fn_map[id] = fn;
163 :
164 14655 : auto it = mono_fns.find (dId);
165 14655 : if (it == mono_fns.end ())
166 14408 : mono_fns[dId] = {};
167 :
168 14655 : mono_fns[dId].emplace_back (ref, fn);
169 14655 : }
170 :
171 61 : void insert_closure_decl (const TyTy::ClosureType *ref, tree fn)
172 : {
173 61 : auto dId = ref->get_def_id ();
174 61 : auto it = mono_closure_fns.find (dId);
175 61 : if (it == mono_closure_fns.end ())
176 61 : mono_closure_fns[dId] = {};
177 :
178 61 : mono_closure_fns[dId].emplace_back (ref, fn);
179 61 : }
180 :
181 : tree lookup_closure_decl (const TyTy::ClosureType *ref)
182 : {
183 : auto dId = ref->get_def_id ();
184 : auto it = mono_closure_fns.find (dId);
185 : if (it == mono_closure_fns.end ())
186 : return error_mark_node;
187 :
188 : for (auto &i : it->second)
189 : {
190 : const TyTy::ClosureType *t = i.first;
191 : tree fn = i.second;
192 :
193 : if (ref->is_equal (*t))
194 : return fn;
195 : }
196 :
197 : return error_mark_node;
198 : }
199 :
200 31952 : bool lookup_function_decl (HirId id, tree *fn, DefId dId = UNKNOWN_DEFID,
201 : const TyTy::BaseType *ref = nullptr,
202 : const std::string &asm_name = std::string ())
203 : {
204 : // for for any monomorphized fns
205 31952 : if (ref != nullptr)
206 : {
207 21392 : rust_assert (dId != UNKNOWN_DEFID);
208 :
209 21392 : auto it = mono_fns.find (dId);
210 21392 : if (it == mono_fns.end ())
211 : return false;
212 :
213 4541 : for (auto &e : mono_fns[dId])
214 : {
215 4301 : const TyTy::BaseType *r = e.first;
216 4301 : tree f = e.second;
217 :
218 4301 : if (ref->is_equal (*r))
219 : {
220 3958 : *fn = f;
221 3958 : return true;
222 : }
223 :
224 343 : if (DECL_ASSEMBLER_NAME_SET_P (f) && !asm_name.empty ())
225 : {
226 304 : tree raw = DECL_ASSEMBLER_NAME_RAW (f);
227 304 : const char *rptr = IDENTIFIER_POINTER (raw);
228 :
229 304 : bool lengths_match_p
230 304 : = IDENTIFIER_LENGTH (raw) == asm_name.size ();
231 304 : if (lengths_match_p
232 304 : && strncmp (rptr, asm_name.c_str (),
233 303 : IDENTIFIER_LENGTH (raw))
234 : == 0)
235 : {
236 0 : *fn = f;
237 0 : return true;
238 : }
239 : }
240 : }
241 : return false;
242 : }
243 :
244 10560 : auto it = compiled_fn_map.find (id);
245 10560 : if (it == compiled_fn_map.end ())
246 : return false;
247 :
248 5684 : *fn = it->second;
249 5684 : return true;
250 : }
251 :
252 508 : void insert_const_decl (HirId id, tree expr) { compiled_consts[id] = expr; }
253 :
254 44059 : bool lookup_const_decl (HirId id, tree *expr)
255 : {
256 44059 : auto it = compiled_consts.find (id);
257 44059 : if (it == compiled_consts.end ())
258 : return false;
259 :
260 630 : *expr = it->second;
261 630 : return true;
262 : }
263 :
264 40 : void insert_label_decl (HirId id, tree label) { compiled_labels[id] = label; }
265 :
266 24 : bool lookup_label_decl (HirId id, tree *label)
267 : {
268 24 : auto it = compiled_labels.find (id);
269 24 : if (it == compiled_labels.end ())
270 : return false;
271 :
272 24 : *label = it->second;
273 24 : return true;
274 : }
275 :
276 881 : void insert_pattern_binding (HirId id, tree binding)
277 : {
278 881 : implicit_pattern_bindings[id] = binding;
279 : }
280 :
281 12841 : bool lookup_pattern_binding (HirId id, tree *binding)
282 : {
283 12841 : auto it = implicit_pattern_bindings.find (id);
284 12841 : if (it == implicit_pattern_bindings.end ())
285 : return false;
286 :
287 842 : *binding = it->second;
288 842 : return true;
289 : }
290 :
291 162 : void insert_vtable (std::pair<size_t, size_t> pair, ::Bvariable *vtable)
292 : {
293 162 : compiled_vtables[pair] = vtable;
294 : }
295 :
296 169 : bool lookup_vtable (std::pair<size_t, size_t> pair, ::Bvariable **vtable)
297 : {
298 169 : auto it = compiled_vtables.find (pair);
299 169 : if (it == compiled_vtables.end ())
300 : return false;
301 :
302 7 : *vtable = it->second;
303 7 : return true;
304 : }
305 :
306 14882 : void push_fn (tree fn, ::Bvariable *ret_addr, TyTy::BaseType *retty)
307 : {
308 14882 : fn_stack.emplace_back (fn, ret_addr, retty);
309 : }
310 14882 : void pop_fn () { fn_stack.pop_back (); }
311 :
312 4104 : bool in_fn () { return fn_stack.size () != 0; }
313 :
314 : // Note: it is undefined behavior to call peek_fn () if fn_stack is empty.
315 45820 : fncontext peek_fn ()
316 : {
317 45820 : rust_assert (!fn_stack.empty ());
318 45820 : return fn_stack.back ();
319 : }
320 :
321 87801 : void push_type (tree t) { type_decls.push_back (t); }
322 212 : void push_var (::Bvariable *v) { var_decls.push_back (v); }
323 508 : void push_const (tree c) { const_decls.push_back (c); }
324 16014 : void push_function (tree f) { func_decls.push_back (f); }
325 :
326 4240 : void write_to_backend ()
327 : {
328 4240 : Backend::write_global_definitions (type_decls, const_decls, func_decls,
329 4240 : var_decls);
330 : }
331 :
332 0 : bool function_completed (tree fn)
333 : {
334 0 : for (auto it = func_decls.begin (); it != func_decls.end (); it++)
335 : {
336 0 : tree i = (*it);
337 0 : if (i == fn)
338 : {
339 : return true;
340 : }
341 : }
342 : return false;
343 : }
344 :
345 123 : void push_loop_context (Bvariable *var) { loop_value_stack.push_back (var); }
346 :
347 29 : bool have_loop_context () const { return !loop_value_stack.empty (); }
348 :
349 15 : Bvariable *peek_loop_context ()
350 : {
351 15 : rust_assert (!loop_value_stack.empty ());
352 15 : return loop_value_stack.back ();
353 : }
354 :
355 123 : Bvariable *pop_loop_context ()
356 : {
357 123 : auto back = loop_value_stack.back ();
358 123 : loop_value_stack.pop_back ();
359 123 : return back;
360 : }
361 :
362 205 : void push_loop_begin_label (tree label)
363 : {
364 205 : loop_begin_labels.push_back (label);
365 : }
366 :
367 13 : tree peek_loop_begin_label ()
368 : {
369 13 : rust_assert (!loop_begin_labels.empty ());
370 13 : return loop_begin_labels.back ();
371 : }
372 :
373 205 : tree pop_loop_begin_label ()
374 : {
375 205 : tree pop = loop_begin_labels.back ();
376 205 : loop_begin_labels.pop_back ();
377 205 : return pop;
378 : }
379 :
380 3561 : void push_const_context (void) { const_context++; }
381 3561 : void pop_const_context (void)
382 : {
383 3561 : if (const_context > 0)
384 3561 : const_context--;
385 : }
386 14808 : bool const_context_p (void) { return (const_context > 0); }
387 :
388 31672 : std::string mangle_item (const TyTy::BaseType *ty,
389 : const Resolver::CanonicalPath &path)
390 : {
391 31672 : return mangler.mangle_item (this, ty, path);
392 : }
393 :
394 : void push_closure_context (HirId id);
395 : void pop_closure_context ();
396 : void insert_closure_binding (HirId id, tree expr);
397 : bool lookup_closure_binding (HirId id, tree *expr);
398 :
399 : std::vector<tree> &get_type_decls () { return type_decls; }
400 4231 : std::vector<::Bvariable *> &get_var_decls () { return var_decls; }
401 4231 : std::vector<tree> &get_const_decls () { return const_decls; }
402 4231 : std::vector<tree> &get_func_decls () { return func_decls; }
403 :
404 : static hashval_t type_hasher (tree type);
405 :
406 0 : void collect_attribute_proc_macro (tree fndecl)
407 : {
408 0 : attribute_macros.push_back (fndecl);
409 : }
410 :
411 0 : void collect_bang_proc_macro (tree fndecl) { bang_macros.push_back (fndecl); }
412 :
413 0 : void collect_derive_proc_macro (CustomDeriveInfo macro)
414 : {
415 0 : custom_derive_macros.push_back (macro);
416 : }
417 :
418 0 : const std::vector<tree> &get_bang_proc_macros () const { return bang_macros; }
419 : const std::vector<tree> &get_attribute_proc_macros () const
420 : {
421 0 : return attribute_macros;
422 : }
423 : const std::vector<CustomDeriveInfo> &get_derive_proc_macros () const
424 : {
425 0 : return custom_derive_macros;
426 : }
427 :
428 : private:
429 : friend class DropBuilder;
430 : Context ();
431 :
432 : Resolver::TypeCheckContext *tyctx;
433 : Analysis::Mappings &mappings;
434 : Mangler mangler;
435 :
436 : // state
437 : std::vector<fncontext> fn_stack;
438 : std::map<HirId, ::Bvariable *> compiled_var_decls;
439 : std::map<hashval_t, tree> compiled_type_map;
440 : std::map<HirId, tree> compiled_fn_map;
441 : std::map<HirId, tree> compiled_consts;
442 : std::map<HirId, tree> compiled_labels;
443 : std::map<std::pair<size_t, size_t>, ::Bvariable *> compiled_vtables;
444 : std::vector<::std::vector<tree>> statements;
445 : std::vector<tree> scope_stack;
446 : std::vector<::std::vector<DropCandidate>> block_drop_candidates;
447 : std::vector<::Bvariable *> loop_value_stack;
448 : std::vector<tree> loop_begin_labels;
449 : std::map<DefId, std::vector<std::pair<const TyTy::BaseType *, tree>>>
450 : mono_fns;
451 : std::map<DefId, std::vector<std::pair<const TyTy::ClosureType *, tree>>>
452 : mono_closure_fns;
453 : std::map<HirId, tree> implicit_pattern_bindings;
454 : std::map<hashval_t, tree> main_variants;
455 :
456 : std::vector<CustomDeriveInfo> custom_derive_macros;
457 : std::vector<tree> attribute_macros;
458 : std::vector<tree> bang_macros;
459 :
460 : // closure bindings
461 : std::vector<HirId> closure_scope_bindings;
462 : std::map<HirId, std::map<HirId, tree>> closure_bindings;
463 :
464 : // To GCC middle-end
465 : std::vector<tree> type_decls;
466 : std::vector<::Bvariable *> var_decls;
467 : std::vector<tree> const_decls;
468 : std::vector<tree> func_decls;
469 :
470 : // Nonzero iff we are currently compiling something inside a constant context.
471 : unsigned int const_context = 0;
472 : };
473 :
474 : } // namespace Compile
475 : } // namespace Rust
476 :
477 : #endif // RUST_COMPILE_CONTEXT
|