LCOV - code coverage report
Current view: top level - gcc/rust/backend - rust-compile-context.h (source / functions) Coverage Total Hit
Test: gcc.info Lines: 88.5 % 200 177
Test Date: 2026-08-22 16:33:35 Functions: 94.4 % 18 17
Legend: Lines:     hit not hit

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

Generated by: LCOV version 2.4-beta

LCOV profile is generated on x86_64 machine using following configure options: configure --disable-bootstrap --enable-coverage=opt --enable-languages=c,c++,fortran,go,jit,lto,rust,m2 --enable-host-shared. GCC test suite is run with the built compiler.