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 : : Context ();
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 : 253236 : tree insert_compiled_type (tree type)
68 : : {
69 : 253236 : hashval_t h = type_hasher (type);
70 : 253236 : auto it = compiled_type_map.find (h);
71 : 253236 : if (it != compiled_type_map.end ())
72 : 170991 : return it->second;
73 : :
74 : 82245 : compiled_type_map.insert ({h, type});
75 : :
76 : 82245 : if (TYPE_NAME (type) != NULL)
77 : 81736 : push_type (type);
78 : :
79 : : return type;
80 : : }
81 : :
82 : 12030 : tree insert_main_variant (tree type)
83 : : {
84 : 12030 : hashval_t h = type_hasher (type);
85 : 12030 : auto it = main_variants.find (h);
86 : 12030 : if (it != main_variants.end ())
87 : 7570 : return it->second;
88 : :
89 : 4460 : main_variants.insert ({h, type});
90 : 4460 : return type;
91 : : }
92 : :
93 : 31047 : Resolver::Resolver *get_resolver () { return resolver; }
94 : 326239 : Resolver::TypeCheckContext *get_tyctx () { return tyctx; }
95 : 161527 : Analysis::Mappings &get_mappings () { return mappings; }
96 : :
97 : 27274 : void push_block (tree scope)
98 : : {
99 : 27274 : scope_stack.push_back (scope);
100 : 27274 : statements.push_back ({});
101 : 27274 : }
102 : :
103 : 27258 : tree pop_block ()
104 : : {
105 : 27258 : auto block = scope_stack.back ();
106 : 27258 : scope_stack.pop_back ();
107 : :
108 : 27258 : auto stmts = statements.back ();
109 : 27258 : statements.pop_back ();
110 : :
111 : 27258 : Backend::block_add_statements (block, stmts);
112 : :
113 : 27258 : return block;
114 : 27258 : }
115 : :
116 : 23611 : tree peek_enclosing_scope ()
117 : : {
118 : 23611 : if (scope_stack.size () == 0)
119 : : return nullptr;
120 : :
121 : 23611 : return scope_stack.back ();
122 : : }
123 : :
124 : : void add_statement_to_enclosing_scope (tree stmt)
125 : : {
126 : : statements.at (statements.size () - 2).push_back (stmt);
127 : : }
128 : :
129 : 82202 : void add_statement (tree stmt) { statements.back ().push_back (stmt); }
130 : :
131 : 21244 : void insert_var_decl (HirId id, ::Bvariable *decl)
132 : : {
133 : 21244 : compiled_var_decls[id] = decl;
134 : : }
135 : :
136 : 44221 : bool lookup_var_decl (HirId id, ::Bvariable **decl)
137 : : {
138 : 44221 : auto it = compiled_var_decls.find (id);
139 : 44221 : if (it == compiled_var_decls.end ())
140 : : return false;
141 : :
142 : 33776 : *decl = it->second;
143 : 33776 : return true;
144 : : }
145 : :
146 : 13000 : void insert_function_decl (const TyTy::FnType *ref, tree fn)
147 : : {
148 : 13000 : auto id = ref->get_ty_ref ();
149 : 13000 : auto dId = ref->get_id ();
150 : :
151 : 13000 : rust_assert (compiled_fn_map.find (id) == compiled_fn_map.end ());
152 : 13000 : compiled_fn_map[id] = fn;
153 : :
154 : 13000 : auto it = mono_fns.find (dId);
155 : 13000 : if (it == mono_fns.end ())
156 : 12742 : mono_fns[dId] = {};
157 : :
158 : 13000 : mono_fns[dId].push_back ({ref, fn});
159 : 13000 : }
160 : :
161 : 55 : void insert_closure_decl (const TyTy::ClosureType *ref, tree fn)
162 : : {
163 : 55 : auto dId = ref->get_def_id ();
164 : 55 : auto it = mono_closure_fns.find (dId);
165 : 55 : if (it == mono_closure_fns.end ())
166 : 55 : mono_closure_fns[dId] = {};
167 : :
168 : 55 : mono_closure_fns[dId].push_back ({ref, fn});
169 : 55 : }
170 : :
171 : : tree lookup_closure_decl (const TyTy::ClosureType *ref)
172 : : {
173 : : auto dId = ref->get_def_id ();
174 : : auto it = mono_closure_fns.find (dId);
175 : : if (it == mono_closure_fns.end ())
176 : : return error_mark_node;
177 : :
178 : : for (auto &i : it->second)
179 : : {
180 : : const TyTy::ClosureType *t = i.first;
181 : : tree fn = i.second;
182 : :
183 : : if (ref->is_equal (*t))
184 : : return fn;
185 : : }
186 : :
187 : : return error_mark_node;
188 : : }
189 : :
190 : 28045 : bool lookup_function_decl (HirId id, tree *fn, DefId dId = UNKNOWN_DEFID,
191 : : const TyTy::BaseType *ref = nullptr,
192 : : const std::string &asm_name = std::string ())
193 : : {
194 : : // for for any monomorphized fns
195 : 28045 : if (ref != nullptr)
196 : : {
197 : 18386 : rust_assert (dId != UNKNOWN_DEFID);
198 : :
199 : 18386 : auto it = mono_fns.find (dId);
200 : 18386 : if (it == mono_fns.end ())
201 : : return false;
202 : :
203 : 2508 : for (auto &e : mono_fns[dId])
204 : : {
205 : 2257 : const TyTy::BaseType *r = e.first;
206 : 2257 : tree f = e.second;
207 : :
208 : 2257 : if (ref->is_equal (*r))
209 : : {
210 : 1888 : *fn = f;
211 : 1888 : return true;
212 : : }
213 : :
214 : 369 : if (DECL_ASSEMBLER_NAME_SET_P (f) && !asm_name.empty ())
215 : : {
216 : 327 : tree raw = DECL_ASSEMBLER_NAME_RAW (f);
217 : 327 : const char *rptr = IDENTIFIER_POINTER (raw);
218 : :
219 : 327 : bool lengths_match_p
220 : 327 : = IDENTIFIER_LENGTH (raw) == asm_name.size ();
221 : 327 : if (lengths_match_p
222 : 327 : && strncmp (rptr, asm_name.c_str (),
223 : 325 : IDENTIFIER_LENGTH (raw))
224 : : == 0)
225 : : {
226 : 0 : *fn = f;
227 : 0 : return true;
228 : : }
229 : : }
230 : : }
231 : : return false;
232 : : }
233 : :
234 : 9659 : auto it = compiled_fn_map.find (id);
235 : 9659 : if (it == compiled_fn_map.end ())
236 : : return false;
237 : :
238 : 4227 : *fn = it->second;
239 : 4227 : return true;
240 : : }
241 : :
242 : 543 : void insert_const_decl (HirId id, tree expr) { compiled_consts[id] = expr; }
243 : :
244 : 34740 : bool lookup_const_decl (HirId id, tree *expr)
245 : : {
246 : 34740 : auto it = compiled_consts.find (id);
247 : 34740 : if (it == compiled_consts.end ())
248 : : return false;
249 : :
250 : 911 : *expr = it->second;
251 : 911 : return true;
252 : : }
253 : :
254 : 36 : void insert_label_decl (HirId id, tree label) { compiled_labels[id] = label; }
255 : :
256 : 20 : bool lookup_label_decl (HirId id, tree *label)
257 : : {
258 : 20 : auto it = compiled_labels.find (id);
259 : 20 : if (it == compiled_labels.end ())
260 : : return false;
261 : :
262 : 20 : *label = it->second;
263 : 20 : return true;
264 : : }
265 : :
266 : 422 : void insert_pattern_binding (HirId id, tree binding)
267 : : {
268 : 422 : implicit_pattern_bindings[id] = binding;
269 : : }
270 : :
271 : 10390 : bool lookup_pattern_binding (HirId id, tree *binding)
272 : : {
273 : 10390 : auto it = implicit_pattern_bindings.find (id);
274 : 10390 : if (it == implicit_pattern_bindings.end ())
275 : : return false;
276 : :
277 : 392 : *binding = it->second;
278 : 392 : return true;
279 : : }
280 : :
281 : 16274 : void push_fn (tree fn, ::Bvariable *ret_addr, TyTy::BaseType *retty)
282 : : {
283 : 16274 : fn_stack.push_back (fncontext{fn, ret_addr, retty});
284 : : }
285 : 16274 : void pop_fn () { fn_stack.pop_back (); }
286 : :
287 : 3669 : bool in_fn () { return fn_stack.size () != 0; }
288 : :
289 : : // Note: it is undefined behavior to call peek_fn () if fn_stack is empty.
290 : 38788 : fncontext peek_fn ()
291 : : {
292 : 38788 : rust_assert (!fn_stack.empty ());
293 : 38788 : return fn_stack.back ();
294 : : }
295 : :
296 : 81736 : void push_type (tree t) { type_decls.push_back (t); }
297 : 55 : void push_var (::Bvariable *v) { var_decls.push_back (v); }
298 : 543 : void push_const (tree c) { const_decls.push_back (c); }
299 : 15332 : void push_function (tree f) { func_decls.push_back (f); }
300 : :
301 : 4253 : void write_to_backend ()
302 : : {
303 : 4253 : Backend::write_global_definitions (type_decls, const_decls, func_decls,
304 : : var_decls);
305 : : }
306 : :
307 : 0 : bool function_completed (tree fn)
308 : : {
309 : 0 : for (auto it = func_decls.begin (); it != func_decls.end (); it++)
310 : : {
311 : 0 : tree i = (*it);
312 : 0 : if (i == fn)
313 : : {
314 : : return true;
315 : : }
316 : : }
317 : : return false;
318 : : }
319 : :
320 : 124 : void push_loop_context (Bvariable *var) { loop_value_stack.push_back (var); }
321 : :
322 : 18 : Bvariable *peek_loop_context () { return loop_value_stack.back (); }
323 : :
324 : 124 : Bvariable *pop_loop_context ()
325 : : {
326 : 124 : auto back = loop_value_stack.back ();
327 : 124 : loop_value_stack.pop_back ();
328 : 124 : return back;
329 : : }
330 : :
331 : 190 : void push_loop_begin_label (tree label)
332 : : {
333 : 190 : loop_begin_labels.push_back (label);
334 : : }
335 : :
336 : 8 : tree peek_loop_begin_label () { return loop_begin_labels.back (); }
337 : :
338 : 190 : tree pop_loop_begin_label ()
339 : : {
340 : 190 : tree pop = loop_begin_labels.back ();
341 : 190 : loop_begin_labels.pop_back ();
342 : 190 : return pop;
343 : : }
344 : :
345 : 5829 : void push_const_context (void) { const_context++; }
346 : 5829 : void pop_const_context (void)
347 : : {
348 : 5829 : if (const_context > 0)
349 : 5829 : const_context--;
350 : : }
351 : 3679 : bool const_context_p (void) { return (const_context > 0); }
352 : :
353 : 28534 : std::string mangle_item (const TyTy::BaseType *ty,
354 : : const Resolver::CanonicalPath &path)
355 : : {
356 : 28534 : return mangler.mangle_item (this, ty, path);
357 : : }
358 : :
359 : : void push_closure_context (HirId id);
360 : : void pop_closure_context ();
361 : : void insert_closure_binding (HirId id, tree expr);
362 : : bool lookup_closure_binding (HirId id, tree *expr);
363 : :
364 : : std::vector<tree> &get_type_decls () { return type_decls; }
365 : 8406 : std::vector<::Bvariable *> &get_var_decls () { return var_decls; }
366 : 8406 : std::vector<tree> &get_const_decls () { return const_decls; }
367 : 8406 : std::vector<tree> &get_func_decls () { return func_decls; }
368 : :
369 : : static hashval_t type_hasher (tree type);
370 : :
371 : 0 : void collect_attribute_proc_macro (tree fndecl)
372 : : {
373 : 0 : attribute_macros.push_back (fndecl);
374 : : }
375 : :
376 : 0 : void collect_bang_proc_macro (tree fndecl) { bang_macros.push_back (fndecl); }
377 : :
378 : 0 : void collect_derive_proc_macro (CustomDeriveInfo macro)
379 : : {
380 : 0 : custom_derive_macros.push_back (macro);
381 : : }
382 : :
383 : 0 : const std::vector<tree> &get_bang_proc_macros () const { return bang_macros; }
384 : : const std::vector<tree> &get_attribute_proc_macros () const
385 : : {
386 : 0 : return attribute_macros;
387 : : }
388 : : const std::vector<CustomDeriveInfo> &get_derive_proc_macros () const
389 : : {
390 : 0 : return custom_derive_macros;
391 : : }
392 : :
393 : : private:
394 : : Resolver::Resolver *resolver;
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
|