LCOV - code coverage report
Current view: top level - gcc/rust/backend - rust-compile-context.h (source / functions) Coverage Total Hit
Test: gcc.info Lines: 90.5 % 158 143
Test Date: 2026-02-28 14:20:25 Functions: 100.0 % 14 14
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-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
        

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.