1  // Copyright (C) 2021-2023 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_HIR_LIVENESS
      20  #define RUST_HIR_LIVENESS
      21  
      22  #include "rust-hir-full-decls.h"
      23  #include "rust-hir-map.h"
      24  #include "rust-lint-marklive-base.h"
      25  #include "rust-name-resolver.h"
      26  
      27  namespace Rust {
      28  namespace Analysis {
      29  
      30  class MarkLive : public MarkLiveBase
      31  {
      32    using Rust::Analysis::MarkLiveBase::visit;
      33  
      34  public:
      35    static std::set<HirId> Analysis (HIR::Crate &crate);
      36    void go (HIR::Crate &crate);
      37  
      38    void visit (HIR::PathInExpression &expr) override;
      39    void visit (HIR::FieldAccessExpr &expr) override;
      40    void visit (HIR::TupleIndexExpr &expr) override;
      41    void visit (HIR::MethodCallExpr &expr) override;
      42    void visit (HIR::TypeAlias &alias) override;
      43  
      44    void visit (HIR::BorrowExpr &expr) override
      45    {
      46      expr.get_expr ()->accept_vis (*this);
      47    }
      48  
      49    void visit (HIR::DereferenceExpr &expr) override
      50    {
      51      expr.get_expr ()->accept_vis (*this);
      52    }
      53  
      54    void visit (HIR::NegationExpr &expr) override
      55    {
      56      expr.get_expr ()->accept_vis (*this);
      57    }
      58  
      59    void visit (HIR::LazyBooleanExpr &expr) override
      60    {
      61      expr.get_lhs ()->accept_vis (*this);
      62      expr.get_rhs ()->accept_vis (*this);
      63    }
      64  
      65    void visit (HIR::TypeCastExpr &expr) override
      66    {
      67      expr.get_expr ()->accept_vis (*this);
      68    }
      69  
      70    void visit (HIR::GroupedExpr &expr) override
      71    {
      72      expr.get_expr_in_parens ()->accept_vis (*this);
      73    }
      74  
      75    void visit (HIR::ArrayExpr &expr) override
      76    {
      77      expr.get_internal_elements ()->accept_vis (*this);
      78    }
      79  
      80    void visit (HIR::ArrayIndexExpr &expr) override
      81    {
      82      expr.get_array_expr ()->accept_vis (*this);
      83      expr.get_index_expr ()->accept_vis (*this);
      84    }
      85  
      86    void visit (HIR::ArrayElemsValues &expr) override
      87    {
      88      for (auto &elem : expr.get_values ())
      89        {
      90  	elem->accept_vis (*this);
      91        }
      92    }
      93  
      94    void visit (HIR::TupleExpr &expr) override
      95    {
      96      for (auto &elem : expr.get_tuple_elems ())
      97        {
      98  	elem->accept_vis (*this);
      99        }
     100    }
     101  
     102    void visit (HIR::BlockExpr &expr) override
     103    {
     104      for (auto &s : expr.get_statements ())
     105        {
     106  	s->accept_vis (*this);
     107        }
     108      if (expr.has_expr ())
     109        {
     110  	expr.get_final_expr ()->accept_vis (*this);
     111        }
     112    }
     113  
     114    void visit (HIR::UnsafeBlockExpr &expr) override
     115    {
     116      expr.get_block_expr ()->accept_vis (*this);
     117    }
     118  
     119    void visit (HIR::LoopExpr &expr) override
     120    {
     121      expr.get_loop_block ()->accept_vis (*this);
     122    }
     123  
     124    void visit (HIR::BreakExpr &expr) override
     125    {
     126      if (expr.has_break_expr ())
     127        expr.get_expr ()->accept_vis (*this);
     128    }
     129  
     130    void visit (HIR::WhileLoopExpr &expr) override
     131    {
     132      expr.get_loop_block ()->accept_vis (*this);
     133      expr.get_predicate_expr ()->accept_vis (*this);
     134    }
     135  
     136    void visit (HIR::Function &function) override
     137    {
     138      function.get_definition ()->accept_vis (*this);
     139    }
     140  
     141    void visit (HIR::ReturnExpr &expr) override
     142    {
     143      if (expr.has_return_expr ())
     144        expr.get_expr ()->accept_vis (*this);
     145    }
     146  
     147    void visit (HIR::WhileLetLoopExpr &expr) override
     148    {
     149      expr.get_loop_block ()->accept_vis (*this);
     150      expr.get_cond ()->accept_vis (*this);
     151    }
     152  
     153    void visit (HIR::ForLoopExpr &expr) override
     154    {
     155      expr.get_loop_block ()->accept_vis (*this);
     156      expr.get_iterator_expr ()->accept_vis (*this);
     157    }
     158  
     159    void visit (HIR::ExprStmtWithoutBlock &stmt) override
     160    {
     161      stmt.get_expr ()->accept_vis (*this);
     162    }
     163  
     164    void visit (HIR::ExprStmtWithBlock &stmt) override
     165    {
     166      stmt.get_expr ()->accept_vis (*this);
     167    }
     168  
     169    void visit (HIR::CallExpr &expr) override
     170    {
     171      expr.get_fnexpr ()->accept_vis (*this);
     172      for (auto &argument : expr.get_arguments ())
     173        argument->accept_vis (*this);
     174    }
     175  
     176    void visit (HIR::ArithmeticOrLogicalExpr &expr) override
     177    {
     178      expr.visit_lhs (*this);
     179      expr.visit_rhs (*this);
     180    }
     181    void visit (HIR::ComparisonExpr &expr) override
     182    {
     183      expr.get_lhs ()->accept_vis (*this);
     184      expr.get_rhs ()->accept_vis (*this);
     185    }
     186  
     187    void visit (HIR::AssignmentExpr &expr) override
     188    {
     189      expr.visit_lhs (*this);
     190      expr.visit_rhs (*this);
     191    }
     192  
     193    void visit (HIR::CompoundAssignmentExpr &expr) override
     194    {
     195      expr.visit_lhs (*this);
     196      expr.visit_rhs (*this);
     197    }
     198  
     199    void visit (HIR::IfExpr &expr) override
     200    {
     201      expr.get_if_condition ()->accept_vis (*this);
     202      expr.get_if_block ()->accept_vis (*this);
     203    }
     204  
     205    void visit (HIR::IfExprConseqElse &expr) override
     206    {
     207      expr.get_if_condition ()->accept_vis (*this);
     208      expr.get_if_block ()->accept_vis (*this);
     209      expr.get_else_block ()->accept_vis (*this);
     210    }
     211  
     212    void visit (HIR::MatchExpr &expr) override
     213    {
     214      expr.get_scrutinee_expr ()->accept_vis (*this);
     215      std::vector<HIR::MatchCase> &cases = expr.get_match_cases ();
     216      for (auto &&caz : cases)
     217        {
     218  	auto case_arm = caz.get_arm ();
     219  	if (case_arm.has_match_arm_guard ())
     220  	  case_arm.get_guard_expr ()->accept_vis (*this);
     221  	caz.get_expr ()->accept_vis (*this);
     222        }
     223    }
     224  
     225    void visit (HIR::IfExprConseqIf &expr) override
     226    {
     227      expr.get_if_condition ()->accept_vis (*this);
     228      expr.get_if_block ()->accept_vis (*this);
     229      expr.get_conseq_if_expr ()->accept_vis (*this);
     230    }
     231  
     232    void visit (HIR::TraitItemFunc &item) override
     233    {
     234      item.get_block_expr ()->accept_vis (*this);
     235    }
     236  
     237    void visit (HIR::ImplBlock &impl) override
     238    {
     239      for (auto &&item : impl.get_impl_items ())
     240        {
     241  	item->accept_vis (*this);
     242        }
     243    }
     244  
     245    void visit (HIR::LetStmt &stmt) override
     246    {
     247      if (stmt.has_init_expr ())
     248        {
     249  	stmt.get_init_expr ()->accept_vis (*this);
     250        }
     251    }
     252  
     253    void visit (HIR::StructExprStruct &stct) override
     254    {
     255      stct.get_struct_name ().accept_vis (*this);
     256    }
     257  
     258    void visit (HIR::StructExprStructFields &stct) override
     259    {
     260      for (auto &field : stct.get_fields ())
     261        {
     262  	field->accept_vis (*this);
     263        }
     264  
     265      stct.get_struct_name ().accept_vis (*this);
     266      if (stct.has_struct_base ())
     267        {
     268  	stct.struct_base->base_struct->accept_vis (*this);
     269        }
     270    }
     271  
     272    virtual void visit (HIR::StructExprFieldIdentifierValue &field) override
     273    {
     274      field.get_value ()->accept_vis (*this);
     275    }
     276  
     277    void visit (HIR::StructExprStructBase &stct) override
     278    {
     279      stct.get_struct_base ()->base_struct->accept_vis (*this);
     280    }
     281  
     282    void visit (HIR::Module &module) override
     283    {
     284      for (auto &item : module.get_items ())
     285        item->accept_vis (*this);
     286    }
     287  
     288    void visit (HIR::ClosureExpr &expr) override
     289    {
     290      expr.get_expr ()->accept_vis (*this);
     291    }
     292  
     293  private:
     294    std::vector<HirId> worklist;
     295    std::set<HirId> liveSymbols;
     296    std::set<HirId> scannedSymbols;
     297    Analysis::Mappings *mappings;
     298    Resolver::Resolver *resolver;
     299    Resolver::TypeCheckContext *tyctx;
     300    MarkLive (std::vector<HirId> worklist)
     301      : worklist (worklist), mappings (Analysis::Mappings::get ()),
     302        resolver (Resolver::Resolver::get ()),
     303        tyctx (Resolver::TypeCheckContext::get ()){};
     304  
     305    void mark_hir_id (HirId);
     306    bool visit_path_segment (HIR::PathExprSegment);
     307    void find_ref_node_id (NodeId ast_node_id, NodeId &ref_node_id);
     308  };
     309  
     310  } // namespace Analysis
     311  } // namespace Rust
     312  
     313  #endif