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-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 14534 : fncontext (tree fndecl, ::Bvariable *ret_addr, TyTy::BaseType *retty)
38 14534 : : 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 262389 : tree insert_compiled_type (tree type)
72 : {
73 262389 : hashval_t h = type_hasher (type);
74 262389 : auto it = compiled_type_map.find (h);
75 262389 : if (it != compiled_type_map.end ())
76 179025 : return it->second;
77 :
78 83364 : compiled_type_map.insert ({h, type});
79 :
80 83364 : if (TYPE_NAME (type) != NULL)
81 83364 : push_type (type);
82 :
83 : return type;
84 : }
85 :
86 12725 : tree insert_main_variant (tree type)
87 : {
88 12725 : hashval_t h = type_hasher (type);
89 12725 : auto it = main_variants.find (h);
90 12725 : if (it != main_variants.end ())
91 8212 : return it->second;
92 :
93 4513 : main_variants.insert ({h, type});
94 4513 : return type;
95 : }
96 :
97 346373 : Resolver::TypeCheckContext *get_tyctx () { return tyctx; }
98 193074 : Analysis::Mappings &get_mappings () { return mappings; }
99 :
100 27201 : void push_block (tree scope)
101 : {
102 27201 : scope_stack.push_back (scope);
103 27201 : statements.push_back ({});
104 27201 : }
105 :
106 27187 : tree pop_block ()
107 : {
108 27187 : auto block = scope_stack.back ();
109 27187 : scope_stack.pop_back ();
110 :
111 27187 : auto stmts = statements.back ();
112 27187 : statements.pop_back ();
113 :
114 27187 : Backend::block_add_statements (block, stmts);
115 :
116 27187 : return block;
117 27187 : }
118 :
119 27039 : tree peek_enclosing_scope ()
120 : {
121 27039 : if (scope_stack.size () == 0)
122 : return nullptr;
123 :
124 27039 : 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 89530 : void add_statement (tree stmt) { statements.back ().push_back (stmt); }
133 :
134 23902 : void insert_var_decl (HirId id, ::Bvariable *decl)
135 : {
136 23902 : compiled_var_decls[id] = decl;
137 : }
138 :
139 52152 : bool lookup_var_decl (HirId id, ::Bvariable **decl)
140 : {
141 52152 : auto it = compiled_var_decls.find (id);
142 52152 : if (it == compiled_var_decls.end ())
143 : return false;
144 :
145 40813 : *decl = it->second;
146 40813 : return true;
147 : }
148 :
149 14176 : void insert_function_decl (const TyTy::FnType *ref, tree fn)
150 : {
151 14176 : auto id = ref->get_ty_ref ();
152 14176 : auto dId = ref->get_id ();
153 :
154 14176 : rust_assert (compiled_fn_map.find (id) == compiled_fn_map.end ());
155 14176 : compiled_fn_map[id] = fn;
156 :
157 14176 : auto it = mono_fns.find (dId);
158 14176 : if (it == mono_fns.end ())
159 13931 : mono_fns[dId] = {};
160 :
161 14176 : mono_fns[dId].emplace_back (ref, fn);
162 14176 : }
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 29157 : 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 29157 : if (ref != nullptr)
199 : {
200 20125 : rust_assert (dId != UNKNOWN_DEFID);
201 :
202 20125 : auto it = mono_fns.find (dId);
203 20125 : 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 9032 : auto it = compiled_fn_map.find (id);
238 9032 : if (it == compiled_fn_map.end ())
239 : return false;
240 :
241 4900 : *fn = it->second;
242 4900 : return true;
243 : }
244 :
245 506 : void insert_const_decl (HirId id, tree expr) { compiled_consts[id] = expr; }
246 :
247 42129 : bool lookup_const_decl (HirId id, tree *expr)
248 : {
249 42129 : auto it = compiled_consts.find (id);
250 42129 : if (it == compiled_consts.end ())
251 : return false;
252 :
253 629 : *expr = it->second;
254 629 : return true;
255 : }
256 :
257 36 : void insert_label_decl (HirId id, tree label) { compiled_labels[id] = label; }
258 :
259 20 : bool lookup_label_decl (HirId id, tree *label)
260 : {
261 20 : auto it = compiled_labels.find (id);
262 20 : if (it == compiled_labels.end ())
263 : return false;
264 :
265 20 : *label = it->second;
266 20 : return true;
267 : }
268 :
269 892 : void insert_pattern_binding (HirId id, tree binding)
270 : {
271 892 : implicit_pattern_bindings[id] = binding;
272 : }
273 :
274 11289 : bool lookup_pattern_binding (HirId id, tree *binding)
275 : {
276 11289 : auto it = implicit_pattern_bindings.find (id);
277 11289 : if (it == implicit_pattern_bindings.end ())
278 : return false;
279 :
280 840 : *binding = it->second;
281 840 : return true;
282 : }
283 :
284 14534 : void push_fn (tree fn, ::Bvariable *ret_addr, TyTy::BaseType *retty)
285 : {
286 14534 : fn_stack.emplace_back (fn, ret_addr, retty);
287 : }
288 14534 : void pop_fn () { fn_stack.pop_back (); }
289 :
290 4074 : 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 43317 : fncontext peek_fn ()
294 : {
295 43317 : rust_assert (!fn_stack.empty ());
296 43317 : return fn_stack.back ();
297 : }
298 :
299 83364 : void push_type (tree t) { type_decls.push_back (t); }
300 50 : void push_var (::Bvariable *v) { var_decls.push_back (v); }
301 506 : void push_const (tree c) { const_decls.push_back (c); }
302 14959 : void push_function (tree f) { func_decls.push_back (f); }
303 :
304 4024 : void write_to_backend ()
305 : {
306 4024 : Backend::write_global_definitions (type_decls, const_decls, func_decls,
307 4024 : 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 121 : void push_loop_context (Bvariable *var) { loop_value_stack.push_back (var); }
324 :
325 29 : 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 121 : Bvariable *pop_loop_context ()
334 : {
335 121 : auto back = loop_value_stack.back ();
336 121 : loop_value_stack.pop_back ();
337 121 : return back;
338 : }
339 :
340 202 : void push_loop_begin_label (tree label)
341 : {
342 202 : loop_begin_labels.push_back (label);
343 : }
344 :
345 13 : tree peek_loop_begin_label ()
346 : {
347 13 : rust_assert (!loop_begin_labels.empty ());
348 13 : return loop_begin_labels.back ();
349 : }
350 :
351 202 : tree pop_loop_begin_label ()
352 : {
353 202 : tree pop = loop_begin_labels.back ();
354 202 : loop_begin_labels.pop_back ();
355 202 : return pop;
356 : }
357 :
358 3496 : void push_const_context (void) { const_context++; }
359 3496 : void pop_const_context (void)
360 : {
361 3496 : if (const_context > 0)
362 3496 : const_context--;
363 : }
364 13249 : bool const_context_p (void) { return (const_context > 0); }
365 :
366 29713 : std::string mangle_item (const TyTy::BaseType *ty,
367 : const Resolver::CanonicalPath &path)
368 : {
369 29713 : 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 4019 : std::vector<::Bvariable *> &get_var_decls () { return var_decls; }
379 4019 : std::vector<tree> &get_const_decls () { return const_decls; }
380 4019 : 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
|