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