LCOV - code coverage report
Current view: top level - buildbot/coverage/build/src/expr - node_value.h (source / functions) Hit Total Coverage
Test: coverage.info Lines: 105 114 92.1 %
Date: 2025-01-05 12:38:24 Functions: 62 64 96.9 %
Branches: 30 42 71.4 %

           Branch data     Line data    Source code
       1                 :            : /******************************************************************************
       2                 :            :  * Top contributors (to current version):
       3                 :            :  *   Morgan Deters, Aina Niemetz, Andres Noetzli
       4                 :            :  *
       5                 :            :  * This file is part of the cvc5 project.
       6                 :            :  *
       7                 :            :  * Copyright (c) 2009-2024 by the authors listed in the file AUTHORS
       8                 :            :  * in the top-level source directory and their institutional affiliations.
       9                 :            :  * All rights reserved.  See the file COPYING in the top-level source
      10                 :            :  * directory for licensing information.
      11                 :            :  * ****************************************************************************
      12                 :            :  *
      13                 :            :  * A node value.
      14                 :            :  *
      15                 :            :  * The actual node implementation.
      16                 :            :  * Instances of this class are generally referenced through cvc5::internal::Node
      17                 :            :  * rather than by pointer. Note that cvc5::internal::Node maintains the
      18                 :            :  * reference count on NodeValue instances.
      19                 :            :  */
      20                 :            : 
      21                 :            : #include "cvc5_private.h"
      22                 :            : 
      23                 :            : #ifndef CVC5__EXPR__NODE_VALUE_H
      24                 :            : #define CVC5__EXPR__NODE_VALUE_H
      25                 :            : 
      26                 :            : #include <iterator>
      27                 :            : #include <string>
      28                 :            : 
      29                 :            : #include "expr/kind.h"
      30                 :            : #include "expr/metakind.h"
      31                 :            : #include "options/language.h"
      32                 :            : 
      33                 :            : namespace cvc5::internal {
      34                 :            : 
      35                 :            : template <bool ref_count> class NodeTemplate;
      36                 :            : class TypeNode;
      37                 :            : class NodeBuilder;
      38                 :            : class NodeManager;
      39                 :            : 
      40                 :            : namespace expr {
      41                 :            :   class NodeValue;
      42                 :            : }
      43                 :            : 
      44                 :            : namespace kind {
      45                 :            :   namespace metakind {
      46                 :            : 
      47                 :            :   template <cvc5::internal::Kind k, class T, bool pool>
      48                 :            :   struct NodeValueConstCompare;
      49                 :            : 
      50                 :            :   struct NodeValueCompare;
      51                 :            : 
      52                 :            :   }  // namespace metakind
      53                 :            :   }  // namespace kind
      54                 :            : 
      55                 :            : namespace expr {
      56                 :            : 
      57                 :            : /**
      58                 :            :  * This is a NodeValue.
      59                 :            :  */
      60                 :            : class CVC5_EXPORT NodeValue
      61                 :            : {
      62                 :            :   template <bool>
      63                 :            :   friend class cvc5::internal::NodeTemplate;
      64                 :            :   friend class cvc5::internal::TypeNode;
      65                 :            :   friend class cvc5::internal::NodeBuilder;
      66                 :            :   friend class cvc5::internal::NodeManager;
      67                 :            : 
      68                 :            :   template <Kind k, class T, bool pool>
      69                 :            :   friend struct kind::metakind::NodeValueConstCompare;
      70                 :            : 
      71                 :            :   friend struct kind::metakind::NodeValueCompare;
      72                 :            : 
      73                 :            :   friend void kind::metakind::nodeValueConstantToStream(std::ostream& out,
      74                 :            :                                                         const NodeValue* nv);
      75                 :            :   friend void kind::metakind::deleteNodeValueConstant(NodeValue* nv);
      76                 :            : 
      77                 :            :   friend class RefCountGuard;
      78                 :            : 
      79                 :            :   /* ------------------------------------------------------------------------ */
      80                 :            :  public:
      81                 :            :   /* ------------------------------------------------------------------------ */
      82                 :            : 
      83                 :            :   using nv_iterator = NodeValue**;
      84                 :            :   using const_nv_iterator = NodeValue const* const*;
      85                 :            : 
      86                 :            :   template <class T>
      87                 :            :   class iterator
      88                 :            :   {
      89                 :            :    public:
      90                 :            :     using iterator_category = std::random_access_iterator_tag;
      91                 :            :     using value_type = T;
      92                 :            :     using difference_type = std::ptrdiff_t;
      93                 :            :     using pointer = T*;
      94                 :            :     using reference = T;
      95                 :            : 
      96                 :  263168301 :     iterator() : d_i(nullptr) {}
      97                 : 2617812194 :     explicit iterator(const_nv_iterator i) : d_i(i) {}
      98                 :            : 
      99                 :            :     /** Conversion of a TNode iterator to a Node iterator. */
     100                 :  269025002 :     inline operator NodeValue::iterator<NodeTemplate<true> >()
     101                 :            :     {
     102                 :  269025002 :       return iterator<NodeTemplate<true> >(d_i);
     103                 :            :     }
     104                 :            : 
     105                 : 2554101015 :     T operator*() const { return T(*d_i); }
     106                 :            : 
     107                 :  581374012 :     bool operator==(const iterator& i) const { return d_i == i.d_i; }
     108                 :            : 
     109                 : 2910607773 :     bool operator!=(const iterator& i) const { return d_i != i.d_i; }
     110                 :            : 
     111                 : 2285937426 :     iterator& operator++()
     112                 :            :     {
     113                 : 2285937426 :       ++d_i;
     114                 : 2285937426 :       return *this;
     115                 :            :     }
     116                 :            : 
     117                 :     123936 :     iterator operator++(int) { return iterator(d_i++); }
     118                 :            : 
     119                 :   56716290 :     iterator& operator--()
     120                 :            :     {
     121                 :   56716290 :       --d_i;
     122                 :   56716290 :       return *this;
     123                 :            :     }
     124                 :            : 
     125                 :            :     iterator operator--(int) { return iterator(d_i--); }
     126                 :            : 
     127                 :   53529067 :     iterator& operator+=(difference_type p)
     128                 :            :     {
     129                 :   53529067 :       d_i += p;
     130                 :   53529067 :       return *this;
     131                 :            :     }
     132                 :            : 
     133                 :    2658453 :     iterator& operator-=(difference_type p)
     134                 :            :     {
     135                 :    2658453 :       d_i -= p;
     136                 :    2658453 :       return *this;
     137                 :            :     }
     138                 :            : 
     139                 :     649101 :     iterator operator+(difference_type p) { return iterator(d_i + p); }
     140                 :            : 
     141                 :     740540 :     iterator operator-(difference_type p) { return iterator(d_i - p); }
     142                 :            : 
     143                 :  436553443 :     difference_type operator-(iterator i) { return d_i - i.d_i; }
     144                 :            : 
     145                 :            :    private:
     146                 :            :     const_nv_iterator d_i;
     147                 :            : 
     148                 :            :   }; /* class NodeValue::iterator<T> */
     149                 :            : 
     150                 :13857526271 :   uint64_t getId() const { return d_id; }
     151                 :            : 
     152                 :17132743111 :   Kind getKind() const { return dKindToKind(d_kind); }
     153                 :            : 
     154                 :11669168035 :   kind::MetaKind getMetaKind() const { return kind::metaKindOf(getKind()); }
     155                 :            : 
     156                 : 5966404114 :   NodeManager* getNodeManager() const { return d_nm; }
     157                 :            : 
     158                 : 2902617531 :   uint32_t getNumChildren() const
     159                 :            :   {
     160         [ +  + ]: 2902617531 :     return (getMetaKind() == kind::metakind::PARAMETERIZED) ? d_nchildren - 1
     161                 : 2902617531 :                                                             : d_nchildren;
     162                 :            :   }
     163                 :            : 
     164                 :            :   /* ------------------------------ Header ---------------------------------- */
     165                 :            :   /** Number of bits reserved for reference counting. */
     166                 :            :   static constexpr uint32_t NBITS_REFCOUNT = 20;
     167                 :            :   /** Number of bits reserved for node kind. */
     168                 :            :   static constexpr uint32_t NBITS_KIND = 10;
     169                 :            :   /** Number of bits reserved for node id. */
     170                 :            :   static constexpr uint32_t NBITS_ID = 40;
     171                 :            :   /** Number of bits reserved for number of children. */
     172                 :            :   static const uint32_t NBITS_NCHILDREN = 26;
     173                 :            :   static_assert(NBITS_REFCOUNT + NBITS_KIND + NBITS_ID + NBITS_NCHILDREN == 96,
     174                 :            :                 "NodeValue header bit assignment does not sum to 96 !");
     175                 :            :   /* ------------------- This header fits into 96 bits ---------------------- */
     176                 :            : 
     177                 :            :   /** Maximum number of children possible. */
     178                 :            :   static constexpr uint32_t MAX_CHILDREN =
     179                 :            :       (static_cast<uint32_t>(1) << NBITS_NCHILDREN) - 1;
     180                 :            : 
     181                 :            :   uint32_t getRefCount() const { return d_rc; }
     182                 :            : 
     183                 :            :   NodeValue* getOperator() const;
     184                 :            :   NodeValue* getChild(int i) const;
     185                 :            : 
     186                 :            :   /** If this is a CONST_* Node, extract the constant from it.  */
     187                 :            :   template <class T>
     188                 :            :   const T& getConst() const;
     189                 :            : 
     190                 :17588240378 :   static inline NodeValue& null()
     191                 :            :   {
     192 [ +  + ][ +  - ]:17588240378 :     static NodeValue* s_null = new NodeValue(0);
                 [ -  - ]
     193                 :17588240378 :     return *s_null;
     194                 :            :   }
     195                 :            : 
     196                 :            :   /**
     197                 :            :    * Hash this NodeValue.  For hash_maps, hash_sets, etc.. but this is
     198                 :            :    * for expr package internal use only at present!  This is likely to
     199                 :            :    * be POORLY PERFORMING for other uses!  For example, this gives
     200                 :            :    * collisions for all VARIABLEs.
     201                 :            :    * @return the hash value of this expression.
     202                 :            :    */
     203                 : 1444930000 :   size_t poolHash() const
     204                 :            :   {
     205         [ +  + ]: 1444930000 :     if (getMetaKind() == kind::metakind::CONSTANT)
     206                 :            :     {
     207                 :  400505000 :       return kind::metakind::NodeValueCompare::constHash(this);
     208                 :            :     }
     209                 :            : 
     210                 : 1044420000 :     size_t hash = d_kind;
     211                 : 1044420000 :     const_nv_iterator i = nv_begin();
     212                 : 1044420000 :     const_nv_iterator i_end = nv_end();
     213         [ +  + ]: 3819860000 :     while (i != i_end)
     214                 :            :     {
     215                 : 2775440000 :       hash ^= (*i)->d_id + 0x9e3779b9 + (hash << 6) + (hash >> 2);
     216                 : 2775440000 :       ++i;
     217                 :            :     }
     218                 : 1044420000 :     return hash;
     219                 :            :   }
     220                 :            : 
     221                 :  758596000 :   static inline uint32_t kindToDKind(Kind k)
     222                 :            :   {
     223                 :  758596000 :     return ((uint32_t)k) & kindMask;
     224                 :            :   }
     225                 :            : 
     226                 :17132743111 :   static inline Kind dKindToKind(uint32_t d)
     227                 :            :   {
     228         [ +  + ]:17132743111 :     return (d == kindMask) ? Kind::UNDEFINED_KIND : Kind(d);
     229                 :            :   }
     230                 :            : 
     231                 :            :   std::string toString() const;
     232                 :            : 
     233                 :            :   void toStream(std::ostream& out) const;
     234                 :            : 
     235                 :            :   void printAst(std::ostream& out, int indent = 0) const;
     236                 :            : 
     237                 :            :   template <typename T>
     238                 :            :   inline iterator<T> begin() const;
     239                 :            :   template <typename T>
     240                 :            :   inline iterator<T> end() const;
     241                 :            : 
     242                 :            :   /* ------------------------------------------------------------------------ */
     243                 :            :  private:
     244                 :            :   /* ------------------------------------------------------------------------ */
     245                 :            : 
     246                 :            :   /**
     247                 :            :    * RAII guard that increases the reference count if the reference count to be
     248                 :            :    * > 0.  Otherwise, this does nothing. This does not just increment the
     249                 :            :    * reference count to avoid maxing out the d_rc field. This is only for low
     250                 :            :    * level functions.
     251                 :            :    */
     252                 :            :   class RefCountGuard
     253                 :            :   {
     254                 :            :    public:
     255                 :   10957000 :     RefCountGuard(const NodeValue* nv) : d_nv(const_cast<NodeValue*>(nv))
     256                 :            :     {
     257                 :   10957000 :       d_increased = (d_nv->d_rc == 0);
     258         [ -  + ]:   10957000 :       if (d_increased)
     259                 :            :       {
     260                 :          0 :         d_nv->d_rc = 1;
     261                 :            :       }
     262                 :   10957000 :     }
     263                 :   10957000 :     ~RefCountGuard()
     264                 :   10957000 :     {
     265                 :            :       // dec() without marking for deletion: we don't want to garbage
     266                 :            :       // collect this NodeValue if ours is the last reference to it.
     267                 :            :       // E.g., this can happen when debugging code calls the print
     268                 :            :       // routines below.  As RefCountGuards are scoped on the stack,
     269                 :            :       // this should be fine---but not in multithreaded contexts!
     270         [ -  + ]:   10957000 :       if (d_increased)
     271                 :            :       {
     272                 :          0 :         --d_nv->d_rc;
     273                 :            :       }
     274                 :   10957000 :     }
     275                 :            : 
     276                 :            :    private:
     277                 :            :     NodeValue* d_nv;
     278                 :            :     bool d_increased;
     279                 :            :   }; /* NodeValue::RefCountGuard */
     280                 :            : 
     281                 :            :   /** Maximum reference count possible.  Used for sticky
     282                 :            :    *  reference-counting.  Should be (1 << num_bits(d_rc)) - 1 */
     283                 :            :   static constexpr uint32_t MAX_RC =
     284                 :            :       (static_cast<uint32_t>(1) << NBITS_REFCOUNT) - 1;
     285                 :            : 
     286                 :            :   /** A mask for d_kind */
     287                 :            :   static constexpr uint32_t kindMask =
     288                 :            :       (static_cast<uint32_t>(1) << NBITS_KIND) - 1;
     289                 :            : 
     290                 :            :   /** Uninitializing constructor for NodeBuilder's use.  */
     291                 : 1177450000 :   NodeValue()
     292                 : 1177450000 :   { /* do not initialize! */
     293                 : 1177450000 :   }
     294                 :            :   /** Private constructor for the null value. */
     295                 :            :   NodeValue(int);
     296                 :            : 
     297                 :40508939382 :   void inc()
     298                 :            :   {
     299         [ +  + ]:40508939382 :     if (__builtin_expect((d_rc < MAX_RC - 1), true))
     300                 :            :     {
     301                 :32070625353 :       ++d_rc;
     302                 :            :     }
     303         [ +  + ]: 8438374111 :     else if (__builtin_expect((d_rc == MAX_RC - 1), false))
     304                 :            :     {
     305                 :          4 :       ++d_rc;
     306                 :          4 :       markRefCountMaxedOut();
     307                 :            :     }
     308                 :40508939382 :   }
     309                 :            : 
     310                 :47440598230 :   void dec()
     311                 :            :   {
     312                 :            :     // FIXME multithreading
     313         [ +  + ]:47440598230 :     if (__builtin_expect((d_rc < MAX_RC), true))
     314                 :            :     {
     315                 :32066241633 :       --d_rc;
     316         [ +  + ]:32066241633 :       if (__builtin_expect((d_rc == 0), false))
     317                 :            :       {
     318                 :  165936692 :         markForDeletion();
     319                 :            :       }
     320                 :            :     }
     321                 :47440598230 :   }
     322                 :            : 
     323                 :            :   void markRefCountMaxedOut();
     324                 :            :   void markForDeletion();
     325                 :            : 
     326                 :            :   /** Decrement ref counts of children */
     327                 :            :   inline void decrRefCounts();
     328                 :            : 
     329                 :            :   /** Returns true if the reference count is maximized. */
     330                 :          8 :   inline bool HasMaximizedReferenceCount() { return d_rc == MAX_RC; }
     331                 :            : 
     332                 :            :   nv_iterator nv_begin();
     333                 :            :   nv_iterator nv_end();
     334                 :            : 
     335                 :            :   const_nv_iterator nv_begin() const;
     336                 :            :   const_nv_iterator nv_end() const;
     337                 :            : 
     338                 :            :   /**
     339                 :            :    * Indents the given stream a given amount of spaces.
     340                 :            :    * @param out the stream to indent
     341                 :            :    * @param indent the numer of spaces
     342                 :            :    */
     343                 :          0 :   static inline void indent(std::ostream& out, int indent)
     344                 :            :   {
     345         [ -  - ]:          0 :     for (int i = 0; i < indent; i++)
     346                 :            :     {
     347                 :          0 :       out << ' ';
     348                 :            :     }
     349                 :          0 :   }
     350                 :            : 
     351                 :            :   /** The ID (0 is reserved for the null value) */
     352                 :            :   uint64_t d_id : NBITS_ID;
     353                 :            : 
     354                 :            :   /** The expression's reference count. */
     355                 :            :   uint32_t d_rc : NBITS_REFCOUNT;
     356                 :            : 
     357                 :            :   /** Kind of the expression */
     358                 :            :   uint32_t d_kind : NBITS_KIND;
     359                 :            : 
     360                 :            :   /** Number of children */
     361                 :            :   uint32_t d_nchildren : NBITS_NCHILDREN;
     362                 :            : 
     363                 :            :   /** Associated node manager. */
     364                 :            :   NodeManager* d_nm = nullptr;
     365                 :            : 
     366                 :            :   /** Variable number of child nodes */
     367                 :            :   NodeValue* d_children[0];
     368                 :            : }; /* class NodeValue */
     369                 :            : 
     370                 :            : /**
     371                 :            :  * Provides a symmetric addition operator to that already defined in
     372                 :            :  * the iterator class.
     373                 :            :  */
     374                 :            : NodeValue::iterator<NodeTemplate<true> > operator+(
     375                 :            :     NodeValue::iterator<NodeTemplate<true> >::difference_type p,
     376                 :            :     NodeValue::iterator<NodeTemplate<true> > i);
     377                 :            : 
     378                 :            : /**
     379                 :            :  * Provides a symmetric addition operator to that already defined in
     380                 :            :  * the iterator class.
     381                 :            :  */
     382                 :            : NodeValue::iterator<NodeTemplate<false> > operator+(
     383                 :            :     NodeValue::iterator<NodeTemplate<false> >::difference_type p,
     384                 :            :     NodeValue::iterator<NodeTemplate<false> > i);
     385                 :            : 
     386                 :            : /**
     387                 :            :  * For hash_maps, hash_sets, etc.. but this is for expr package
     388                 :            :  * internal use only at present!  This is likely to be POORLY
     389                 :            :  * PERFORMING for other uses!  NodeValue::poolHash() will lead to
     390                 :            :  * collisions for all VARIABLEs.
     391                 :            :  */
     392                 :            : struct NodeValuePoolHashFunction {
     393                 : 1444930000 :   inline size_t operator()(const NodeValue* nv) const {
     394                 : 1444930000 :     return (size_t) nv->poolHash();
     395                 :            :   }
     396                 :            : };/* struct NodeValuePoolHashFunction */
     397                 :            : 
     398                 :            : /**
     399                 :            :  * For hash_maps, hash_sets, etc.
     400                 :            :  */
     401                 :            : struct NodeValueIDHashFunction {
     402                 :  374137000 :   inline size_t operator()(const NodeValue* nv) const {
     403                 :  374137000 :     return (size_t) nv->getId();
     404                 :            :   }
     405                 :            : };/* struct NodeValueIDHashFunction */
     406                 :            : 
     407                 :            : 
     408                 :            : /**
     409                 :            :  * An equality predicate that is applicable between pointers to fully
     410                 :            :  * constructed NodeValues.
     411                 :            :  */
     412                 :            : struct NodeValueIDEquality {
     413                 :  126792000 :   inline bool operator()(const NodeValue* a, const NodeValue* b) const {
     414                 :  126792000 :     return a->getId() == b->getId();
     415                 :            :   }
     416                 :            : };
     417                 :            : 
     418                 :            : std::ostream& operator<<(std::ostream& out, const NodeValue& nv);
     419                 :            : 
     420                 :      27835 : inline NodeValue::NodeValue(int)
     421                 :            :     : d_id(0),
     422                 :            :       d_rc(MAX_RC),
     423                 :            :       d_kind(static_cast<uint32_t>(Kind::NULL_EXPR)),
     424                 :      27835 :       d_nchildren(0)
     425                 :            : {
     426                 :      27835 : }
     427                 :            : 
     428                 :  121934000 : inline void NodeValue::decrRefCounts() {
     429         [ +  + ]:  440402000 :   for(nv_iterator i = nv_begin(); i != nv_end(); ++i) {
     430                 :  318467000 :     (*i)->dec();
     431                 :            :   }
     432                 :  121934000 : }
     433                 :            : 
     434                 : 1221560000 : inline NodeValue::nv_iterator NodeValue::nv_begin() {
     435                 : 1221560000 :   return d_children;
     436                 :            : }
     437                 :            : 
     438                 : 2658100000 : inline NodeValue::nv_iterator NodeValue::nv_end() {
     439                 : 2658100000 :   return d_children + d_nchildren;
     440                 :            : }
     441                 :            : 
     442                 : 2583930000 : inline NodeValue::const_nv_iterator NodeValue::nv_begin() const {
     443                 : 2583930000 :   return d_children;
     444                 :            : }
     445                 :            : 
     446                 : 1814180000 : inline NodeValue::const_nv_iterator NodeValue::nv_end() const {
     447                 : 1814180000 :   return d_children + d_nchildren;
     448                 :            : }
     449                 :            : 
     450                 :            : template <typename T>
     451                 :  892790803 : inline NodeValue::iterator<T> NodeValue::begin() const {
     452                 :  892790803 :   NodeValue* const* firstChild = d_children;
     453         [ +  + ]:  892790803 :   if(getMetaKind() == kind::metakind::PARAMETERIZED) {
     454                 :   52790421 :     ++firstChild;
     455                 :            :   }
     456                 :  892790803 :   return iterator<T>(firstChild);
     457                 :            : }
     458                 :            : 
     459                 :            : template <typename T>
     460                 : 1454482380 : inline NodeValue::iterator<T> NodeValue::end() const {
     461                 : 1454482380 :   return iterator<T>(d_children + d_nchildren);
     462                 :            : }
     463                 :            : 
     464                 :          0 : inline NodeValue* NodeValue::getOperator() const {
     465                 :          0 :   Assert(getMetaKind() == kind::metakind::PARAMETERIZED);
     466                 :          0 :   return d_children[0];
     467                 :            : }
     468                 :            : 
     469                 : 2705704126 : inline NodeValue* NodeValue::getChild(int i) const {
     470         [ +  + ]: 2705704126 :   if(getMetaKind() == kind::metakind::PARAMETERIZED) {
     471                 :  126515832 :     ++i;
     472                 :            :   }
     473                 :            : 
     474 [ +  - ][ +  - ]: 5411418242 :   Assert(i >= 0 && unsigned(i) < d_nchildren);
         [ -  + ][ -  - ]
     475                 : 2705704126 :   return d_children[i];
     476                 :            : }
     477                 :            : 
     478                 :            : }  // namespace expr
     479                 :            : }  // namespace cvc5::internal
     480                 :            : 
     481                 :            : #endif /* CVC5__EXPR__NODE_VALUE_H */

Generated by: LCOV version 1.14