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