LCOV - code coverage report
Current view: top level - gcc/rust/backend - rust-compile-context.h (source / functions) Coverage Total Hit
Test: gcc.info Lines: 89.9 % 208 187
Test Date: 2026-09-19 16:22:48 Functions: 95.0 % 20 19
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        16211 :   fncontext (tree fndecl, ::Bvariable *ret_addr, TyTy::BaseType *retty)
      40        16211 :     : 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       292866 :   tree insert_compiled_type (tree type)
      76              :   {
      77       292866 :     hashval_t h = type_hasher (type);
      78       292866 :     auto it = compiled_type_map.find (h);
      79       292866 :     if (it != compiled_type_map.end ())
      80       201508 :       return it->second;
      81              : 
      82        91358 :     compiled_type_map.insert ({h, type});
      83              : 
      84        91358 :     if (TYPE_NAME (type) != NULL)
      85        91358 :       push_type (type);
      86              : 
      87              :     return type;
      88              :   }
      89              : 
      90        13861 :   tree insert_main_variant (tree type)
      91              :   {
      92        13861 :     hashval_t h = type_hasher (type);
      93        13861 :     auto it = main_variants.find (h);
      94        13861 :     if (it != main_variants.end ())
      95         8876 :       return it->second;
      96              : 
      97         4985 :     main_variants.insert ({h, type});
      98         4985 :     return type;
      99              :   }
     100              : 
     101       391907 :   Resolver::TypeCheckContext *get_tyctx () { return tyctx; }
     102       248684 :   Analysis::Mappings &get_mappings () { return mappings; }
     103              : 
     104        46105 :   void push_block (tree scope)
     105              :   {
     106        46105 :     scope_stack.push_back (scope);
     107        46105 :     statements.push_back ({});
     108        46105 :     block_drop_candidates.emplace_back ();
     109        46105 :   }
     110              : 
     111         6845 :   tree pop_block () { return pop_block_impl (NULL_TREE, UNKNOWN_LOCATION); }
     112              : 
     113        39244 :   tree pop_block_with_cleanup (tree cleanup, location_t cleanup_locus)
     114              :   {
     115        39244 :     return pop_block_impl (cleanup, cleanup_locus);
     116              :   }
     117              : 
     118        30367 :   tree peek_enclosing_scope ()
     119              :   {
     120        30367 :     if (scope_stack.size () == 0)
     121              :       return nullptr;
     122              : 
     123        30367 :     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       126716 :   void add_statement (tree stmt) { statements.back ().push_back (stmt); }
     132              : 
     133        26489 :   void insert_var_decl (HirId id, ::Bvariable *decl)
     134              :   {
     135        26489 :     compiled_var_decls[id] = decl;
     136              :   }
     137              : 
     138        58411 :   bool lookup_var_decl (HirId id, ::Bvariable **decl)
     139              :   {
     140        58411 :     auto it = compiled_var_decls.find (id);
     141        58411 :     if (it == compiled_var_decls.end ())
     142              :       return false;
     143              : 
     144        44524 :     *decl = it->second;
     145        44524 :     return true;
     146              :   }
     147              : 
     148            1 :   void insert_drop_flag (HirId id, ::Bvariable *flag)
     149              :   {
     150            1 :     drop_flags[{peek_fn ().fndecl, id}] = flag;
     151            1 :   }
     152              : 
     153        12015 :   bool lookup_drop_flag (HirId id, ::Bvariable **flag)
     154              :   {
     155        12015 :     auto it = drop_flags.find ({peek_fn ().fndecl, id});
     156        12015 :     if (it == drop_flags.end ())
     157              :       return false;
     158              : 
     159            4 :     *flag = it->second;
     160            4 :     return true;
     161              :   }
     162              : 
     163        15881 :   void insert_function_decl (const TyTy::FnType *ref, tree fn)
     164              :   {
     165        15881 :     auto id = ref->get_ty_ref ();
     166        15881 :     auto dId = ref->get_id ();
     167              : 
     168        15881 :     rust_assert (compiled_fn_map.find (id) == compiled_fn_map.end ());
     169        15881 :     compiled_fn_map[id] = fn;
     170              : 
     171        15881 :     auto it = mono_fns.find (dId);
     172        15881 :     if (it == mono_fns.end ())
     173        15616 :       mono_fns[dId] = {};
     174              : 
     175        15881 :     mono_fns[dId].emplace_back (ref, fn);
     176        15881 :   }
     177              : 
     178           61 :   void insert_closure_decl (const TyTy::ClosureType *ref, tree fn)
     179              :   {
     180           61 :     auto dId = ref->get_def_id ();
     181           61 :     auto it = mono_closure_fns.find (dId);
     182           61 :     if (it == mono_closure_fns.end ())
     183           61 :       mono_closure_fns[dId] = {};
     184              : 
     185           61 :     mono_closure_fns[dId].emplace_back (ref, fn);
     186           61 :   }
     187              : 
     188              :   tree lookup_closure_decl (const TyTy::ClosureType *ref)
     189              :   {
     190              :     auto dId = ref->get_def_id ();
     191              :     auto it = mono_closure_fns.find (dId);
     192              :     if (it == mono_closure_fns.end ())
     193              :       return error_mark_node;
     194              : 
     195              :     for (auto &i : it->second)
     196              :       {
     197              :         const TyTy::ClosureType *t = i.first;
     198              :         tree fn = i.second;
     199              : 
     200              :         if (ref->is_equal (*t))
     201              :           return fn;
     202              :       }
     203              : 
     204              :     return error_mark_node;
     205              :   }
     206              : 
     207        34760 :   bool lookup_function_decl (HirId id, tree *fn, DefId dId = UNKNOWN_DEFID,
     208              :                              const TyTy::BaseType *ref = nullptr,
     209              :                              const std::string &asm_name = std::string ())
     210              :   {
     211              :     // for for any monomorphized fns
     212        34760 :     if (ref != nullptr)
     213              :       {
     214        23343 :         rust_assert (dId != UNKNOWN_DEFID);
     215              : 
     216        23343 :         auto it = mono_fns.find (dId);
     217        23343 :         if (it == mono_fns.end ())
     218              :           return false;
     219              : 
     220         4907 :         for (auto &e : mono_fns[dId])
     221              :           {
     222         4649 :             const TyTy::BaseType *r = e.first;
     223         4649 :             tree f = e.second;
     224              : 
     225         4649 :             if (ref->is_equal (*r))
     226              :               {
     227         4277 :                 *fn = f;
     228         4277 :                 return true;
     229              :               }
     230              : 
     231          372 :             if (DECL_ASSEMBLER_NAME_SET_P (f) && !asm_name.empty ())
     232              :               {
     233          333 :                 tree raw = DECL_ASSEMBLER_NAME_RAW (f);
     234          333 :                 const char *rptr = IDENTIFIER_POINTER (raw);
     235              : 
     236          333 :                 bool lengths_match_p
     237          333 :                   = IDENTIFIER_LENGTH (raw) == asm_name.size ();
     238          333 :                 if (lengths_match_p
     239          333 :                     && strncmp (rptr, asm_name.c_str (),
     240          332 :                                 IDENTIFIER_LENGTH (raw))
     241              :                          == 0)
     242              :                   {
     243            1 :                     *fn = f;
     244            1 :                     return true;
     245              :                   }
     246              :               }
     247              :           }
     248              :         return false;
     249              :       }
     250              : 
     251        11417 :     auto it = compiled_fn_map.find (id);
     252        11417 :     if (it == compiled_fn_map.end ())
     253              :       return false;
     254              : 
     255         5876 :     *fn = it->second;
     256         5876 :     return true;
     257              :   }
     258              : 
     259          527 :   void insert_const_decl (HirId id, tree expr) { compiled_consts[id] = expr; }
     260              : 
     261        47524 :   bool lookup_const_decl (HirId id, tree *expr)
     262              :   {
     263        47524 :     auto it = compiled_consts.find (id);
     264        47524 :     if (it == compiled_consts.end ())
     265              :       return false;
     266              : 
     267          639 :     *expr = it->second;
     268          639 :     return true;
     269              :   }
     270              : 
     271              :   void insert_label_decl (HirId id, tree label) { compiled_labels[id] = label; }
     272              : 
     273            0 :   bool lookup_label_decl (HirId id, tree *label)
     274              :   {
     275            0 :     auto it = compiled_labels.find (id);
     276            0 :     if (it == compiled_labels.end ())
     277              :       return false;
     278              : 
     279            0 :     *label = it->second;
     280            0 :     return true;
     281              :   }
     282              : 
     283           54 :   void insert_break_label (HirId id, tree label)
     284              :   {
     285           54 :     compiled_break_labels[id] = label;
     286              :   }
     287              : 
     288           33 :   tl::optional<tree> lookup_break_label (HirId id)
     289              :   {
     290           33 :     auto it = compiled_break_labels.find (id);
     291           33 :     if (it == compiled_break_labels.end ())
     292            0 :       return tl::nullopt;
     293           33 :     return it->second;
     294              :   }
     295              : 
     296           51 :   void insert_continue_label (HirId id, tree label)
     297              :   {
     298           51 :     compiled_continue_labels[id] = label;
     299              :   }
     300              : 
     301            6 :   tl::optional<tree> lookup_continue_label (HirId id)
     302              :   {
     303            6 :     auto it = compiled_continue_labels.find (id);
     304            6 :     if (it == compiled_continue_labels.end ())
     305            0 :       return tl::nullopt;
     306            6 :     return it->second;
     307              :   }
     308              : 
     309          933 :   void insert_pattern_binding (HirId id, tree binding)
     310              :   {
     311          933 :     implicit_pattern_bindings[id] = binding;
     312              :   }
     313              : 
     314        13833 :   bool lookup_pattern_binding (HirId id, tree *binding)
     315              :   {
     316        13833 :     auto it = implicit_pattern_bindings.find (id);
     317        13833 :     if (it == implicit_pattern_bindings.end ())
     318              :       return false;
     319              : 
     320          877 :     *binding = it->second;
     321          877 :     return true;
     322              :   }
     323              : 
     324          167 :   void insert_vtable (std::pair<size_t, size_t> pair, ::Bvariable *vtable)
     325              :   {
     326          167 :     compiled_vtables[pair] = vtable;
     327              :   }
     328              : 
     329          174 :   bool lookup_vtable (std::pair<size_t, size_t> pair, ::Bvariable **vtable)
     330              :   {
     331          174 :     auto it = compiled_vtables.find (pair);
     332          174 :     if (it == compiled_vtables.end ())
     333              :       return false;
     334              : 
     335            7 :     *vtable = it->second;
     336            7 :     return true;
     337              :   }
     338              : 
     339        16211 :   void push_fn (tree fn, ::Bvariable *ret_addr, TyTy::BaseType *retty)
     340              :   {
     341        16211 :     fn_stack.emplace_back (fn, ret_addr, retty);
     342              :   }
     343        16211 :   void pop_fn () { fn_stack.pop_back (); }
     344              : 
     345         4420 :   bool in_fn () { return fn_stack.size () != 0; }
     346              : 
     347              :   // Note: it is undefined behavior to call peek_fn () if fn_stack is empty.
     348        71447 :   fncontext peek_fn ()
     349              :   {
     350        71447 :     rust_assert (!fn_stack.empty ());
     351        71447 :     return fn_stack.back ();
     352              :   }
     353              : 
     354        91358 :   void push_type (tree t) { type_decls.push_back (t); }
     355          221 :   void push_var (::Bvariable *v) { var_decls.push_back (v); }
     356          527 :   void push_const (tree c) { const_decls.push_back (c); }
     357        17603 :   void push_function (tree f) { func_decls.push_back (f); }
     358              : 
     359         4390 :   void write_to_backend ()
     360              :   {
     361         4390 :     Backend::write_global_definitions (type_decls, const_decls, func_decls,
     362         4390 :                                        var_decls);
     363              :   }
     364              : 
     365            0 :   bool function_completed (tree fn)
     366              :   {
     367            0 :     for (auto it = func_decls.begin (); it != func_decls.end (); it++)
     368              :       {
     369            0 :         tree i = (*it);
     370            0 :         if (i == fn)
     371              :           {
     372              :             return true;
     373              :           }
     374              :       }
     375              :     return false;
     376              :   }
     377              : 
     378          244 :   void push_loop_context (Bvariable *var) { loop_value_stack.push_back (var); }
     379              : 
     380           42 :   bool have_loop_context () const { return !loop_value_stack.empty (); }
     381              : 
     382           17 :   Bvariable *peek_loop_context ()
     383              :   {
     384           17 :     rust_assert (!loop_value_stack.empty ());
     385           17 :     return loop_value_stack.back ();
     386              :   }
     387              : 
     388          147 :   Bvariable *pop_loop_context ()
     389              :   {
     390          147 :     auto back = loop_value_stack.back ();
     391          147 :     loop_value_stack.pop_back ();
     392          147 :     return back;
     393              :   }
     394              : 
     395          244 :   void push_loop_begin_label (tree label)
     396              :   {
     397          244 :     loop_begin_labels.push_back (label);
     398              :   }
     399              : 
     400           25 :   tree peek_loop_begin_label ()
     401              :   {
     402           25 :     rust_assert (!loop_begin_labels.empty ());
     403           25 :     return loop_begin_labels.back ();
     404              :   }
     405              : 
     406          244 :   tree pop_loop_begin_label ()
     407              :   {
     408          244 :     tree pop = loop_begin_labels.back ();
     409          244 :     loop_begin_labels.pop_back ();
     410          244 :     return pop;
     411              :   }
     412              : 
     413          244 :   void push_loop_end_label (tree label) { loop_end_labels.push_back (label); }
     414              : 
     415              :   tree peek_loop_end_label ()
     416              :   {
     417              :     rust_assert (!loop_end_labels.empty ());
     418              :     return loop_end_labels.back ();
     419              :   }
     420              : 
     421          244 :   tree pop_loop_end_label ()
     422              :   {
     423          244 :     rust_assert (!loop_end_labels.empty ());
     424          244 :     tree pop = loop_end_labels.back ();
     425          244 :     loop_end_labels.pop_back ();
     426          244 :     return pop;
     427              :   }
     428              : 
     429         3908 :   void push_const_context (void) { const_context++; }
     430         3908 :   void pop_const_context (void)
     431              :   {
     432         3908 :     if (const_context > 0)
     433         3908 :       const_context--;
     434              :   }
     435        27421 :   bool const_context_p (void) { return (const_context > 0); }
     436              : 
     437        35061 :   std::string mangle_item (const TyTy::BaseType *ty,
     438              :                            const Resolver::CanonicalPath &path)
     439              :   {
     440        35061 :     return mangler.mangle_item (this, ty, path);
     441              :   }
     442              : 
     443              :   void push_closure_context (HirId id);
     444              :   void pop_closure_context ();
     445              :   void insert_closure_binding (HirId id, tree expr);
     446              :   bool lookup_closure_binding (HirId id, tree *expr);
     447              : 
     448              :   std::vector<tree> &get_type_decls () { return type_decls; }
     449         4368 :   std::vector<::Bvariable *> &get_var_decls () { return var_decls; }
     450         4368 :   std::vector<tree> &get_const_decls () { return const_decls; }
     451         4368 :   std::vector<tree> &get_func_decls () { return func_decls; }
     452              : 
     453              :   static hashval_t type_hasher (tree type);
     454              : 
     455            0 :   void collect_attribute_proc_macro (tree fndecl)
     456              :   {
     457            0 :     attribute_macros.push_back (fndecl);
     458              :   }
     459              : 
     460            0 :   void collect_bang_proc_macro (tree fndecl) { bang_macros.push_back (fndecl); }
     461              : 
     462            0 :   void collect_derive_proc_macro (CustomDeriveInfo macro)
     463              :   {
     464            0 :     custom_derive_macros.push_back (macro);
     465              :   }
     466              : 
     467            0 :   const std::vector<tree> &get_bang_proc_macros () const { return bang_macros; }
     468              :   const std::vector<tree> &get_attribute_proc_macros () const
     469              :   {
     470            0 :     return attribute_macros;
     471              :   }
     472              :   const std::vector<CustomDeriveInfo> &get_derive_proc_macros () const
     473              :   {
     474            0 :     return custom_derive_macros;
     475              :   }
     476              : 
     477              : private:
     478              :   friend class DropBuilder;
     479              :   Context ();
     480              : 
     481        46089 :   tree pop_block_impl (tree cleanup, location_t cleanup_locus)
     482              :   {
     483        46089 :     auto block = scope_stack.back ();
     484        46089 :     scope_stack.pop_back ();
     485              : 
     486        46089 :     auto stmts = statements.back ();
     487        46089 :     statements.pop_back ();
     488              : 
     489        46089 :     rust_assert (!block_drop_candidates.empty ());
     490        46089 :     block_drop_candidates.pop_back ();
     491              : 
     492        46089 :     if (cleanup != NULL_TREE)
     493              :       {
     494           50 :         tree body = Backend::statement_list (stmts);
     495           50 :         if (body == NULL_TREE)
     496            0 :           body = build_empty_stmt (cleanup_locus);
     497              : 
     498           50 :         tree exceptional_cleanup = build_empty_stmt (cleanup_locus);
     499           50 :         tree cleanup_selector
     500           50 :           = build2_loc (cleanup_locus, EH_ELSE_EXPR, void_type_node, cleanup,
     501              :                         exceptional_cleanup);
     502              : 
     503           50 :         tree try_finally
     504           50 :           = Backend::exception_handler_statement (body, NULL_TREE,
     505              :                                                   cleanup_selector,
     506              :                                                   cleanup_locus);
     507           50 :         Backend::block_add_statements (block, {try_finally});
     508              :       }
     509              :     else
     510        46039 :       Backend::block_add_statements (block, stmts);
     511              : 
     512        46089 :     return block;
     513        46089 :   }
     514              : 
     515              :   Resolver::TypeCheckContext *tyctx;
     516              :   Analysis::Mappings &mappings;
     517              :   Mangler mangler;
     518              : 
     519              :   // state
     520              :   std::vector<fncontext> fn_stack;
     521              :   std::map<HirId, ::Bvariable *> compiled_var_decls;
     522              :   std::map<std::pair<tree, HirId>, ::Bvariable *> drop_flags;
     523              :   std::map<hashval_t, tree> compiled_type_map;
     524              :   std::map<HirId, tree> compiled_fn_map;
     525              :   std::map<HirId, tree> compiled_consts;
     526              :   std::map<HirId, tree> compiled_labels;
     527              :   std::map<std::pair<size_t, size_t>, ::Bvariable *> compiled_vtables;
     528              :   std::map<HirId, tree> compiled_break_labels;
     529              :   std::map<HirId, tree> compiled_continue_labels;
     530              :   std::vector<::std::vector<tree>> statements;
     531              :   std::vector<tree> scope_stack;
     532              :   std::vector<::std::vector<DropCandidate>> block_drop_candidates;
     533              :   std::vector<::Bvariable *> loop_value_stack;
     534              :   std::vector<tree> loop_begin_labels;
     535              :   std::vector<tree> loop_end_labels;
     536              :   std::map<DefId, std::vector<std::pair<const TyTy::BaseType *, tree>>>
     537              :     mono_fns;
     538              :   std::map<DefId, std::vector<std::pair<const TyTy::ClosureType *, tree>>>
     539              :     mono_closure_fns;
     540              :   std::map<HirId, tree> implicit_pattern_bindings;
     541              :   std::map<hashval_t, tree> main_variants;
     542              : 
     543              :   std::vector<CustomDeriveInfo> custom_derive_macros;
     544              :   std::vector<tree> attribute_macros;
     545              :   std::vector<tree> bang_macros;
     546              : 
     547              :   // closure bindings
     548              :   std::vector<HirId> closure_scope_bindings;
     549              :   std::map<HirId, std::map<HirId, tree>> closure_bindings;
     550              : 
     551              :   // To GCC middle-end
     552              :   std::vector<tree> type_decls;
     553              :   std::vector<::Bvariable *> var_decls;
     554              :   std::vector<tree> const_decls;
     555              :   std::vector<tree> func_decls;
     556              : 
     557              :   // Nonzero iff we are currently compiling something inside a constant context.
     558              :   unsigned int const_context = 0;
     559              : };
     560              : 
     561              : } // namespace Compile
     562              : } // namespace Rust
     563              : 
     564              : #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.