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