LCOV - code coverage report
Current view: top level - buildbot/coverage/build/src/theory/bv - int_blaster.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 639 685 93.3 %
Date: 2026-05-08 10:22:53 Functions: 30 32 93.8 %
Branches: 261 470 55.5 %

           Branch data     Line data    Source code
       1                 :            : /******************************************************************************
       2                 :            :  * This file is part of the cvc5 project.
       3                 :            :  *
       4                 :            :  * Copyright (c) 2009-2026 by the authors listed in the file AUTHORS
       5                 :            :  * in the top-level source directory and their institutional affiliations.
       6                 :            :  * All rights reserved.  See the file COPYING in the top-level source
       7                 :            :  * directory for licensing information.
       8                 :            :  * ****************************************************************************
       9                 :            :  *
      10                 :            :  * Int-blasting utility
      11                 :            :  */
      12                 :            : 
      13                 :            : #include "theory/bv/int_blaster.h"
      14                 :            : 
      15                 :            : #include <cmath>
      16                 :            : #include <sstream>
      17                 :            : #include <string>
      18                 :            : #include <unordered_map>
      19                 :            : #include <vector>
      20                 :            : 
      21                 :            : #include "expr/node.h"
      22                 :            : #include "expr/node_algorithm.h"
      23                 :            : #include "expr/node_traversal.h"
      24                 :            : #include "expr/skolem_manager.h"
      25                 :            : #include "options/uf_options.h"
      26                 :            : #include "proof/proof.h"
      27                 :            : #include "smt/logic_exception.h"
      28                 :            : #include "theory/bv/theory_bv_utils.h"
      29                 :            : #include "theory/logic_info.h"
      30                 :            : #include "theory/rewriter.h"
      31                 :            : #include "util/bitvector.h"
      32                 :            : #include "util/iand.h"
      33                 :            : #include "util/rational.h"
      34                 :            : 
      35                 :            : using namespace cvc5::internal::kind;
      36                 :            : using namespace cvc5::internal::theory;
      37                 :            : using namespace cvc5::internal::theory::bv;
      38                 :            : 
      39                 :            : namespace cvc5::internal {
      40                 :            : 
      41                 :            : namespace {
      42                 :            : 
      43                 :            : // A helper function to compute 2^b as a Rational
      44                 :       6010 : Rational intpow2(uint32_t b) { return Rational(Integer(2).pow(b), Integer(1)); }
      45                 :            : 
      46                 :            : }  // namespace
      47                 :            : 
      48                 :      51784 : IntBlaster::IntBlaster(Env& env,
      49                 :            :                        options::SolveBVAsIntMode mode,
      50                 :      51784 :                        uint64_t granularity)
      51                 :            :     : EnvObj(env),
      52                 :      51784 :       d_binarizeCache(userContext()),
      53                 :      51784 :       d_intblastCache(userContext()),
      54                 :      51784 :       d_rangeNodes(userContext()),
      55                 :      51784 :       d_bitwiseAssertions(userContext()),
      56                 :      51784 :       d_iandUtils(nodeManager()),
      57                 :      51784 :       d_mode(mode),
      58                 :     155352 :       d_context(userContext())
      59                 :            : {
      60                 :      51784 :   d_nm = nodeManager();
      61                 :      51784 :   d_zero = d_nm->mkConstInt(0);
      62                 :      51784 :   d_one = d_nm->mkConstInt(1);
      63 [ -  + ][ -  + ]:      51784 :   Assert(granularity <= 8);
                 [ -  - ]
      64                 :      51784 :   d_granularity = static_cast<uint32_t>(granularity);
      65                 :      51784 : };
      66                 :            : 
      67                 :      51436 : IntBlaster::~IntBlaster() {}
      68                 :            : 
      69                 :        625 : std::shared_ptr<ProofNode> IntBlaster::getProofFor(Node fact)
      70                 :            : {
      71                 :            :   // proofs not yet supported
      72                 :       1250 :   CDProof cdp(d_env);
      73                 :        625 :   cdp.addTrustedStep(fact, TrustId::INT_BLASTER, {}, {});
      74                 :       1250 :   return cdp.getProofFor(fact);
      75                 :        625 : }
      76                 :            : 
      77                 :          0 : std::string IntBlaster::identify() const { return "IntBlaster"; }
      78                 :            : 
      79                 :        986 : void IntBlaster::addRangeConstraint(Node node,
      80                 :            :                                     uint32_t size,
      81                 :            :                                     std::vector<TrustNode>& lemmas)
      82                 :            : {
      83                 :        986 :   Node rangeConstraint = mkRangeConstraint(node, size);
      84         [ +  - ]:       1972 :   Trace("int-blaster-debug")
      85                 :        986 :       << "range constraint computed: " << rangeConstraint << std::endl;
      86         [ +  + ]:        986 :   if (d_rangeNodes.find(node) == d_rangeNodes.end())
      87                 :            :   {
      88         [ +  - ]:       1966 :     Trace("int-blaster-debug")
      89                 :        983 :         << "node added to cache and constraints added to lemmas " << std::endl;
      90                 :        983 :     d_rangeNodes.insert(node);
      91                 :        983 :     TrustNode trn = TrustNode::mkTrustLemma(rangeConstraint, this);
      92                 :        983 :     lemmas.push_back(trn);
      93                 :        983 :   }
      94                 :        986 : }
      95                 :            : 
      96                 :         83 : void IntBlaster::addQuantifiedRangeConstraint(Node f,
      97                 :            :                                               uint32_t size,
      98                 :            :                                               std::vector<TrustNode>& lemmas)
      99                 :            : {
     100                 :         83 :   std::vector<TypeNode> argTypes = f.getType().getArgTypes();
     101                 :         83 :   std::vector<Node> boundVars;
     102         [ +  + ]:        202 :   for (const TypeNode& tn : argTypes)
     103                 :            :   {
     104                 :        119 :     Node newBoundVar = NodeManager::mkBoundVar(tn);
     105                 :        119 :     boundVars.push_back(newBoundVar);
     106                 :        119 :   }
     107                 :         83 :   std::vector<Node> inputs = boundVars;
     108                 :         83 :   inputs.insert(inputs.begin(), f);
     109                 :         83 :   Node apply = d_nm->mkNode(Kind::APPLY_UF, inputs);
     110                 :         83 :   Node rangeConstraint = mkRangeConstraint(apply, size);
     111                 :         83 :   Node boundVarList = d_nm->mkNode(Kind::BOUND_VAR_LIST, boundVars);
     112                 :         83 :   rangeConstraint = d_nm->mkNode(Kind::FORALL, boundVarList, rangeConstraint);
     113         [ +  - ]:        166 :   Trace("int-blaster-debug")
     114                 :          0 :       << "quantified range constraint computed: " << rangeConstraint
     115                 :         83 :       << std::endl;
     116         [ +  + ]:         83 :   if (d_rangeNodes.find(f) == d_rangeNodes.end())
     117                 :            :   {
     118         [ +  - ]:        100 :     Trace("int-blaster-debug") << "function added to cache, and quantified "
     119                 :          0 :                                   "range constraint added to cache and lemmas "
     120                 :         50 :                                << std::endl;
     121                 :         50 :     d_rangeNodes.insert(f);
     122                 :         50 :     TrustNode trn = TrustNode::mkTrustLemma(rangeConstraint, this);
     123                 :         50 :     lemmas.push_back(trn);
     124                 :         50 :   }
     125                 :         83 : }
     126                 :            : 
     127                 :         36 : void IntBlaster::addBitwiseConstraint(Node bitwiseConstraint,
     128                 :            :                                       std::vector<TrustNode>& lemmas)
     129                 :            : {
     130         [ +  + ]:         36 :   if (d_bitwiseAssertions.find(bitwiseConstraint) == d_bitwiseAssertions.end())
     131                 :            :   {
     132         [ +  - ]:         60 :     Trace("int-blaster-debug")
     133                 :          0 :         << "bitwise constraint added to cache and lemmas: " << bitwiseConstraint
     134                 :         30 :         << std::endl;
     135                 :         30 :     d_bitwiseAssertions.insert(bitwiseConstraint);
     136                 :         30 :     TrustNode trn = TrustNode::mkTrustLemma(bitwiseConstraint, this);
     137                 :         30 :     lemmas.push_back(trn);
     138                 :         30 :   }
     139                 :         36 : }
     140                 :            : 
     141                 :       1224 : Node IntBlaster::mkRangeConstraint(Node newVar, uint32_t k)
     142                 :            : {
     143                 :       2448 :   Node lower = d_nm->mkNode(Kind::LEQ, d_zero, newVar);
     144                 :       2448 :   Node upper = d_nm->mkNode(Kind::LT, newVar, pow2(k));
     145                 :       2448 :   Node result = d_nm->mkNode(Kind::AND, lower, upper);
     146                 :       2448 :   return rewrite(result);
     147                 :       1224 : }
     148                 :            : 
     149                 :         77 : Node IntBlaster::maxInt(uint32_t k)
     150                 :            : {
     151 [ -  + ][ -  + ]:         77 :   Assert(k > 0);
                 [ -  - ]
     152                 :        154 :   Rational max_value = intpow2(k) - 1;
     153                 :        154 :   return d_nm->mkConstInt(max_value);
     154                 :         77 : }
     155                 :            : 
     156                 :       5780 : Node IntBlaster::pow2(uint32_t k) { return d_nm->mkConstInt(intpow2(k)); }
     157                 :            : 
     158                 :         31 : Node IntBlaster::modpow2(Node n, uint32_t exponent)
     159                 :            : {
     160                 :         31 :   Node p2 = d_nm->mkConstInt(intpow2(exponent));
     161                 :         62 :   return d_nm->mkNode(Kind::INTS_MODULUS_TOTAL, n, p2);
     162                 :         31 : }
     163                 :            : 
     164                 :      16713 : Node IntBlaster::makeBinary(Node n)
     165                 :            : {
     166         [ +  + ]:      16713 :   if (d_binarizeCache.find(n) != d_binarizeCache.end())
     167                 :            :   {
     168                 :       9880 :     return d_binarizeCache[n];
     169                 :            :   }
     170                 :       6833 :   uint64_t numChildren = n.getNumChildren();
     171                 :       6833 :   Kind k = n.getKind();
     172                 :       6833 :   Node result = n;
     173         [ +  + ]:       6833 :   if ((numChildren > 2)
     174 [ +  - ][ +  - ]:        145 :       && (k == Kind::BITVECTOR_ADD || k == Kind::BITVECTOR_MULT
     175 [ +  - ][ +  - ]:        145 :           || k == Kind::BITVECTOR_AND || k == Kind::BITVECTOR_OR
     176 [ +  - ][ +  + ]:        145 :           || k == Kind::BITVECTOR_XOR || k == Kind::BITVECTOR_CONCAT))
     177                 :            :   {
     178                 :          2 :     result = n[0];
     179         [ +  + ]:          6 :     for (uint32_t i = 1; i < numChildren; i++)
     180                 :            :     {
     181                 :          4 :       result = d_nm->mkNode(n.getKind(), result, n[i]);
     182                 :            :     }
     183                 :            :   }
     184                 :       6833 :   d_binarizeCache[n] = result;
     185         [ +  - ]:       6833 :   Trace("int-blaster-debug") << "binarization result: " << result << std::endl;
     186                 :       6833 :   return result;
     187                 :       6833 : }
     188                 :            : 
     189                 :            : /**
     190                 :            :  * Translate n to Integers via post-order traversal.
     191                 :            :  */
     192                 :       1835 : TrustNode IntBlaster::trustedIntBlast(Node n,
     193                 :            :                                       std::vector<TrustNode>& lemmas,
     194                 :            :                                       std::map<Node, Node>& skolems)
     195                 :            : {
     196                 :            :   // make sure the node is re-written
     197         [ +  - ]:       1835 :   Trace("int-blaster-debug") << "n before rewriting: " << n << std::endl;
     198 [ -  + ][ -  + ]:       1835 :   Assert(n == rewrite(n));
                 [ -  - ]
     199         [ +  - ]:       1835 :   Trace("int-blaster-debug") << "n after rewriting: " << n << std::endl;
     200                 :            : 
     201                 :            :   // helper vector for traversal.
     202                 :       1835 :   std::vector<Node> toVisit;
     203                 :       1835 :   toVisit.push_back(makeBinary(n));
     204                 :            : 
     205         [ +  + ]:      18241 :   while (!toVisit.empty())
     206                 :            :   {
     207                 :      16408 :     Node current = toVisit.back();
     208         [ +  - ]:      16408 :     Trace("int-blaster-debug") << "current: " << current << std::endl;
     209                 :      16408 :     uint64_t currentNumChildren = current.getNumChildren();
     210         [ +  + ]:      16408 :     if (d_intblastCache.find(current) == d_intblastCache.end())
     211                 :            :     {
     212                 :            :       // This is the first time we visit this node and it is not in the cache.
     213                 :            :       // We mark this node as visited but not translated by assiging
     214                 :            :       // a null node to it.
     215                 :       6928 :       d_intblastCache[current] = Node();
     216                 :            :       // all the node's children are added to the stack to be visited
     217                 :            :       // before visiting this node again.
     218         [ +  + ]:      14369 :       for (const Node& child : current)
     219                 :            :       {
     220                 :       7441 :         toVisit.push_back(makeBinary(child));
     221                 :       7441 :       }
     222                 :            :       // If this is a UF applicatinon, we also add the function to
     223                 :            :       // toVisit.
     224         [ +  + ]:       6928 :       if (current.getKind() == Kind::APPLY_UF)
     225                 :            :       {
     226                 :        206 :         toVisit.push_back(current.getOperator());
     227                 :            :       }
     228                 :            :     }
     229                 :            :     else
     230                 :            :     {
     231                 :            :       // We already visited and translated this node
     232         [ +  + ]:       9480 :       if (!d_intblastCache[current].get().isNull())
     233                 :            :       {
     234                 :            :         // We are done computing the translation for current
     235                 :       2554 :         toVisit.pop_back();
     236                 :            :       }
     237                 :            :       else
     238                 :            :       {
     239                 :            :         // We are now visiting current on the way back up.
     240                 :            :         // This is when we do the actual translation.
     241                 :       6926 :         Node translation;
     242         [ +  + ]:       6926 :         if (currentNumChildren == 0)
     243                 :            :         {
     244                 :       2749 :           translation = translateNoChildren(current, lemmas, skolems);
     245                 :            :         }
     246                 :            :         else
     247                 :            :         {
     248                 :            :           /**
     249                 :            :            * The current node has children.
     250                 :            :            * Since we are on the way back up,
     251                 :            :            * these children were already translated.
     252                 :            :            * We save their translation for easy access.
     253                 :            :            * If the node's kind is APPLY_UF,
     254                 :            :            * we also need to include the translated uninterpreted function in
     255                 :            :            * this list.
     256                 :            :            */
     257                 :       4177 :           std::vector<Node> translated_children;
     258         [ +  + ]:       4177 :           if (current.getKind() == Kind::APPLY_UF)
     259                 :            :           {
     260 [ -  + ][ -  + ]:        206 :             Assert(d_intblastCache.find(current.getOperator())
                 [ -  - ]
     261                 :            :                    != d_intblastCache.end());
     262                 :        206 :             translated_children.push_back(
     263                 :        412 :                 d_intblastCache[current.getOperator()]);
     264                 :            :           }
     265         [ +  + ]:      11614 :           for (const Node& cc : current)
     266                 :            :           {
     267                 :       7437 :             Node ccb = makeBinary(cc);
     268 [ -  + ][ -  + ]:       7437 :             Assert(d_intblastCache.find(ccb) != d_intblastCache.end());
                 [ -  - ]
     269                 :       7437 :             translated_children.push_back(d_intblastCache[ccb]);
     270                 :       7437 :           }
     271                 :            :           translation =
     272                 :       4179 :               translateWithChildren(current, translated_children, lemmas);
     273                 :       4177 :         }
     274 [ -  + ][ -  + ]:       6924 :         Assert(!translation.isNull());
                 [ -  - ]
     275                 :            :         // Map the current node to its translation in the cache.
     276                 :       6924 :         d_intblastCache[current] = translation;
     277                 :            :         // Also map the translation to itself.
     278                 :       6924 :         d_intblastCache[translation] = translation;
     279                 :       6924 :         toVisit.pop_back();
     280                 :       6926 :       }
     281                 :            :     }
     282                 :      16408 :   }
     283 [ -  + ][ -  + ]:       1833 :   Assert(d_intblastCache.find(n) != d_intblastCache.end());
                 [ -  - ]
     284                 :       1833 :   Node res = d_intblastCache[n].get();
     285         [ +  + ]:       1833 :   if (res == n)
     286                 :            :   {
     287                 :        897 :     return TrustNode::null();
     288                 :            :   }
     289                 :        936 :   return TrustNode::mkTrustRewrite(n, res, this);
     290                 :       1835 : }
     291                 :            : 
     292                 :          1 : Node IntBlaster::intBlast(Node n,
     293                 :            :                           std::vector<Node>& lemmas,
     294                 :            :                           std::map<Node, Node>& skolems)
     295                 :            : {
     296                 :          1 :   std::vector<TrustNode> tlemmas;
     297                 :          1 :   TrustNode tr = trustedIntBlast(n, tlemmas, skolems);
     298         [ -  + ]:          1 :   for (TrustNode& tlem : tlemmas)
     299                 :            :   {
     300                 :          0 :     lemmas.emplace_back(tlem.getProven());
     301                 :            :   }
     302         [ -  + ]:          1 :   if (tr.isNull())
     303                 :            :   {
     304                 :          0 :     return n;
     305                 :            :   }
     306 [ -  + ][ -  + ]:          1 :   Assert(tr.getKind() == TrustNodeKind::REWRITE);
                 [ -  - ]
     307 [ -  + ][ -  + ]:          1 :   Assert(tr.getProven()[0] == n);
                 [ -  - ]
     308                 :          2 :   return tr.getProven()[1];
     309                 :          1 : }
     310                 :            : 
     311                 :       4202 : Node IntBlaster::translateWithChildren(
     312                 :            :     Node original,
     313                 :            :     const std::vector<Node>& translated_children,
     314                 :            :     std::vector<TrustNode>& lemmas)
     315                 :            : {
     316                 :            :   // The translation of the original node is determined by the kind of
     317                 :            :   // the node.
     318                 :       4202 :   Kind oldKind = original.getKind();
     319                 :            :   // Some BV operators were eliminated before this point.
     320 [ -  + ][ -  + ]:       4202 :   Assert(oldKind != Kind::BITVECTOR_SDIV);
                 [ -  - ]
     321 [ -  + ][ -  + ]:       4202 :   Assert(oldKind != Kind::BITVECTOR_SREM);
                 [ -  - ]
     322 [ -  + ][ -  + ]:       4202 :   Assert(oldKind != Kind::BITVECTOR_SMOD);
                 [ -  - ]
     323 [ -  + ][ -  + ]:       4202 :   Assert(oldKind != Kind::BITVECTOR_XNOR);
                 [ -  - ]
     324 [ -  + ][ -  + ]:       4202 :   Assert(oldKind != Kind::BITVECTOR_NOR);
                 [ -  - ]
     325 [ -  + ][ -  + ]:       4202 :   Assert(oldKind != Kind::BITVECTOR_NAND);
                 [ -  - ]
     326 [ -  + ][ -  + ]:       4202 :   Assert(oldKind != Kind::BITVECTOR_SUB);
                 [ -  - ]
     327 [ -  + ][ -  + ]:       4202 :   Assert(oldKind != Kind::BITVECTOR_REPEAT);
                 [ -  - ]
     328 [ -  + ][ -  + ]:       4202 :   Assert(oldKind != Kind::BITVECTOR_ROTATE_RIGHT);
                 [ -  - ]
     329 [ -  + ][ -  + ]:       4202 :   Assert(oldKind != Kind::BITVECTOR_ROTATE_LEFT);
                 [ -  - ]
     330 [ -  + ][ -  + ]:       4202 :   Assert(oldKind != Kind::BITVECTOR_SGT);
                 [ -  - ]
     331 [ -  + ][ -  + ]:       4202 :   Assert(oldKind != Kind::BITVECTOR_SLE);
                 [ -  - ]
     332 [ -  + ][ -  + ]:       4202 :   Assert(oldKind != Kind::BITVECTOR_SGE);
                 [ -  - ]
     333 [ -  + ][ -  + ]:       4202 :   Assert(oldKind != Kind::EXISTS);
                 [ -  - ]
     334                 :            :   // BV division by zero was eliminated before this point.
     335                 :       4202 :   Assert(oldKind != Kind::BITVECTOR_UDIV
     336                 :            :          || !(original[1].isConst()
     337                 :            :               && original[1].getConst<BitVector>().getValue().isZero()));
     338                 :            : 
     339                 :            :   // Store the translated node
     340                 :       4202 :   Node returnNode;
     341                 :            : 
     342                 :            :   /**
     343                 :            :    * higher order logic allows comparing between functions
     344                 :            :    * The translation does not support this,
     345                 :            :    * as the translated functions may be different outside
     346                 :            :    * of the bounds that were relevant for the original
     347                 :            :    * bit-vectors.
     348                 :            :    */
     349 [ +  + ][ +  + ]:       4202 :   if (childrenTypesChanged(original) && logicInfo().isHigherOrder())
         [ +  - ][ +  + ]
                 [ -  - ]
     350                 :            :   {
     351                 :          1 :     throw LogicException("bv-to-int does not support higher order logic ");
     352                 :            :   }
     353                 :            :   // Translate according to the kind of the original node.
     354 [ +  + ][ +  + ]:       4201 :   switch (oldKind)
         [ +  + ][ +  + ]
         [ +  - ][ +  + ]
         [ +  + ][ +  + ]
         [ +  + ][ +  + ]
         [ +  + ][ +  + ]
         [ +  + ][ -  - ]
         [ +  + ][ +  + ]
         [ +  + ][ +  + ]
         [ +  + ][ +  + ]
     355                 :            :   {
     356                 :        124 :     case Kind::BITVECTOR_ADD:
     357                 :            :     {
     358 [ -  + ][ -  + ]:        124 :       Assert(original.getNumChildren() == 2);
                 [ -  - ]
     359                 :        124 :       uint32_t bvsize = original[0].getType().getBitVectorSize();
     360                 :        372 :       returnNode = createBVAddNode(
     361                 :        372 :           translated_children[0], translated_children[1], bvsize);
     362                 :        124 :       break;
     363                 :            :     }
     364                 :         33 :     case Kind::BITVECTOR_MULT:
     365                 :            :     {
     366 [ -  + ][ -  + ]:         33 :       Assert(original.getNumChildren() == 2);
                 [ -  - ]
     367                 :         33 :       uint32_t bvsize = original[0].getType().getBitVectorSize();
     368                 :         33 :       Node mult = d_nm->mkNode(Kind::MULT, translated_children);
     369                 :         33 :       Node p2 = pow2(bvsize);
     370                 :         33 :       returnNode = d_nm->mkNode(Kind::INTS_MODULUS_TOTAL, mult, p2);
     371                 :         33 :       break;
     372                 :         33 :     }
     373                 :         21 :     case Kind::BITVECTOR_UDIV:
     374                 :            :     {
     375                 :            :       // we use an ITE for the case where the second operand is 0.
     376                 :         21 :       uint32_t bvsize = original[0].getType().getBitVectorSize();
     377                 :         21 :       Node pow2BvSize = pow2(bvsize);
     378                 :            :       Node divNode =
     379                 :         21 :           d_nm->mkNode(Kind::INTS_DIVISION_TOTAL, translated_children);
     380 [ +  + ][ -  - ]:        126 :       returnNode = d_nm->mkNode(
     381                 :            :           Kind::ITE,
     382                 :         42 :           {d_nm->mkNode(Kind::EQUAL, translated_children[1], d_zero),
     383                 :         42 :            d_nm->mkNode(Kind::SUB, pow2BvSize, d_one),
     384                 :         21 :            divNode});
     385                 :         21 :       break;
     386                 :         21 :     }
     387                 :          1 :     case Kind::BITVECTOR_UREM:
     388                 :            :     {
     389                 :            :       // we use an ITE for the case where the second operand is 0.
     390                 :            :       Node modNode =
     391                 :          1 :           d_nm->mkNode(Kind::INTS_MODULUS_TOTAL, translated_children);
     392                 :          5 :       returnNode = d_nm->mkNode(
     393                 :            :           Kind::ITE,
     394                 :          2 :           d_nm->mkNode(Kind::EQUAL, translated_children[1], d_zero),
     395                 :          1 :           translated_children[0],
     396                 :          1 :           modNode);
     397                 :          1 :       break;
     398                 :          1 :     }
     399                 :          8 :     case Kind::BITVECTOR_NOT:
     400                 :            :     {
     401                 :          8 :       uint32_t bvsize = original[0].getType().getBitVectorSize();
     402                 :          8 :       returnNode = createBVNotNode(translated_children[0], bvsize);
     403                 :          8 :       break;
     404                 :            :     }
     405                 :         24 :     case Kind::BITVECTOR_NEG:
     406                 :            :     {
     407                 :         24 :       uint32_t bvsize = original[0].getType().getBitVectorSize();
     408                 :         24 :       returnNode = createBVNegNode(translated_children[0], bvsize);
     409                 :         24 :       break;
     410                 :            :     }
     411                 :        100 :     case Kind::BITVECTOR_UBV_TO_INT:
     412                 :            :     {
     413                 :            :       // In this case, we already translated the child to integer.
     414                 :            :       // The result is simply the translated child.
     415                 :        100 :       returnNode = translated_children[0];
     416                 :        100 :       break;
     417                 :            :     }
     418                 :         13 :     case Kind::INT_TO_BITVECTOR:
     419                 :            :     {
     420                 :            :       // In this case we take the original integer,
     421                 :            :       // modulo 2 to the power of the bit-width
     422                 :            :       returnNode =
     423                 :         26 :           modpow2(translated_children[0],
     424                 :         39 :                   original.getOperator().getConst<IntToBitVector>().d_size);
     425                 :         13 :       break;
     426                 :            :     }
     427                 :         15 :     case Kind::BITVECTOR_OR:
     428                 :            :     {
     429 [ -  + ][ -  + ]:         15 :       Assert(translated_children.size() == 2);
                 [ -  - ]
     430                 :         15 :       uint32_t bvsize = original[0].getType().getBitVectorSize();
     431                 :         45 :       returnNode = createBVOrNode(
     432                 :         45 :           translated_children[0], translated_children[1], bvsize, lemmas);
     433                 :         15 :       break;
     434                 :            :     }
     435                 :          0 :     case Kind::BITVECTOR_XOR:
     436                 :            :     {
     437                 :          0 :       Assert(translated_children.size() == 2);
     438                 :          0 :       uint32_t bvsize = original[0].getType().getBitVectorSize();
     439                 :            :       // Based on Hacker's Delight section 2-2 equation n:
     440                 :            :       // x xor y = x|y - x&y
     441                 :            :       Node bvor = createBVOrNode(
     442                 :          0 :           translated_children[0], translated_children[1], bvsize, lemmas);
     443                 :            :       Node bvand = createBVAndNode(
     444                 :          0 :           translated_children[0], translated_children[1], bvsize, lemmas);
     445                 :          0 :       returnNode = createBVSubNode(bvor, bvand, bvsize);
     446                 :          0 :       break;
     447                 :          0 :     }
     448                 :         39 :     case Kind::BITVECTOR_AND:
     449                 :            :     {
     450 [ -  + ][ -  + ]:         39 :       Assert(translated_children.size() == 2);
                 [ -  - ]
     451                 :         39 :       uint32_t bvsize = original[0].getType().getBitVectorSize();
     452                 :        117 :       returnNode = createBVAndNode(
     453                 :        117 :           translated_children[0], translated_children[1], bvsize, lemmas);
     454                 :         39 :       break;
     455                 :            :     }
     456                 :          5 :     case Kind::BITVECTOR_SHL:
     457                 :            :     {
     458                 :          5 :       uint32_t bvsize = original[0].getType().getBitVectorSize();
     459                 :          5 :       returnNode = createShiftNode(translated_children, bvsize, true);
     460                 :          5 :       break;
     461                 :            :     }
     462                 :        185 :     case Kind::BITVECTOR_LSHR:
     463                 :            :     {
     464                 :        185 :       uint32_t bvsize = original[0].getType().getBitVectorSize();
     465                 :        185 :       returnNode = createShiftNode(translated_children, bvsize, false);
     466                 :        185 :       break;
     467                 :            :     }
     468                 :         19 :     case Kind::BITVECTOR_ASHR:
     469                 :            :     {
     470                 :            :       /*  From SMT-LIB2:
     471                 :            :        *  (bvashr s t) abbreviates
     472                 :            :        *     (ite (= ((_ extract |m-1| |m-1|) s) #b0)
     473                 :            :        *          (bvlshr s t)
     474                 :            :        *          (bvnot (bvlshr (bvnot s) t)))
     475                 :            :        *
     476                 :            :        *  Equivalently:
     477                 :            :        *  (bvashr s t) abbreviates
     478                 :            :        *      (ite (bvult s 100000...)
     479                 :            :        *           (bvlshr s t)
     480                 :            :        *           (bvnot (bvlshr (bvnot s) t)))
     481                 :            :        *
     482                 :            :        */
     483                 :            :       // signed_min is 100000...
     484                 :         19 :       uint32_t bvsize = original[0].getType().getBitVectorSize();
     485                 :         19 :       Node signed_min = pow2(bvsize - 1);
     486                 :            :       Node condition =
     487                 :         38 :           d_nm->mkNode(Kind::LT, translated_children[0], signed_min);
     488                 :         19 :       Node thenNode = createShiftNode(translated_children, bvsize, false);
     489                 :            :       std::vector<Node> children = {
     490                 :         19 :           createBVNotNode(translated_children[0], bvsize),
     491                 :         95 :           translated_children[1]};
     492                 :            :       Node elseNode =
     493                 :         38 :           createBVNotNode(createShiftNode(children, bvsize, false), bvsize);
     494                 :         19 :       returnNode = d_nm->mkNode(Kind::ITE, condition, thenNode, elseNode);
     495                 :         19 :       break;
     496                 :         19 :     }
     497                 :          1 :     case Kind::BITVECTOR_ITE:
     498                 :            :     {
     499                 :            :       // Lifted to a boolean ite.
     500                 :          2 :       Node cond = d_nm->mkNode(Kind::EQUAL, translated_children[0], d_one);
     501                 :          3 :       returnNode = d_nm->mkNode(
     502                 :          3 :           Kind::ITE, cond, translated_children[1], translated_children[2]);
     503                 :          1 :       break;
     504                 :          1 :     }
     505                 :          1 :     case Kind::BITVECTOR_ZERO_EXTEND:
     506                 :            :     {
     507                 :            :       // zero extension does not change the integer translation.
     508                 :          1 :       returnNode = translated_children[0];
     509                 :          1 :       break;
     510                 :            :     }
     511                 :         17 :     case Kind::BITVECTOR_SIGN_EXTEND:
     512                 :            :     {
     513                 :         17 :       uint32_t bvsize = original[0].getType().getBitVectorSize();
     514                 :            :       returnNode =
     515                 :         34 :           createSignExtendNode(translated_children[0],
     516                 :            :                                bvsize,
     517                 :         17 :                                bv::utils::getSignExtendAmount(original));
     518                 :         17 :       break;
     519                 :            :     }
     520                 :         70 :     case Kind::BITVECTOR_CONCAT:
     521                 :            :     {
     522                 :            :       // (concat a b) translates to a*2^k+b, k being the bitwidth of b.
     523                 :         70 :       uint32_t bvsizeRight = original[1].getType().getBitVectorSize();
     524                 :         70 :       Node pow2BvSizeRight = pow2(bvsizeRight);
     525                 :            :       Node a =
     526                 :        140 :           d_nm->mkNode(Kind::MULT, translated_children[0], pow2BvSizeRight);
     527                 :         70 :       Node b = translated_children[1];
     528                 :         70 :       returnNode = d_nm->mkNode(Kind::ADD, a, b);
     529                 :         70 :       break;
     530                 :         70 :     }
     531                 :         18 :     case Kind::BITVECTOR_EXTRACT:
     532                 :            :     {
     533                 :            :       // ((_ extract i j) a) is a / 2^j mod 2^{i-j+1}
     534                 :            :       // original = a[i:j]
     535                 :         18 :       uint32_t i = bv::utils::getExtractHigh(original);
     536                 :         18 :       uint32_t j = bv::utils::getExtractLow(original);
     537 [ -  + ][ -  + ]:         18 :       Assert(i >= j);
                 [ -  - ]
     538                 :            :       Node div = d_nm->mkNode(
     539                 :         36 :           Kind::INTS_DIVISION_TOTAL, translated_children[0], pow2(j));
     540                 :         18 :       returnNode = modpow2(div, i - j + 1);
     541                 :         18 :       break;
     542                 :         18 :     }
     543                 :       1023 :     case Kind::EQUAL:
     544                 :            :     {
     545                 :       1023 :       returnNode = d_nm->mkNode(Kind::EQUAL, translated_children);
     546                 :       1023 :       break;
     547                 :            :     }
     548                 :        194 :     case Kind::BITVECTOR_ULT:
     549                 :            :     {
     550                 :        194 :       returnNode = d_nm->mkNode(Kind::LT, translated_children);
     551                 :        194 :       break;
     552                 :            :     }
     553                 :         68 :     case Kind::BITVECTOR_SLT:
     554                 :            :     {
     555                 :         68 :       uint32_t bvsize = original[0].getType().getBitVectorSize();
     556 [ +  + ][ -  - ]:        340 :       returnNode = d_nm->mkNode(Kind::LT,
     557                 :        136 :                                 {uts(translated_children[0], bvsize),
     558                 :        204 :                                  uts(translated_children[1], bvsize)});
     559                 :         68 :       break;
     560                 :            :     }
     561                 :          1 :     case Kind::BITVECTOR_ULE:
     562                 :            :     {
     563                 :          1 :       returnNode = d_nm->mkNode(Kind::LEQ, translated_children);
     564                 :          1 :       break;
     565                 :            :     }
     566                 :          1 :     case Kind::BITVECTOR_UGT:
     567                 :            :     {
     568                 :          1 :       returnNode = d_nm->mkNode(Kind::GT, translated_children);
     569                 :          1 :       break;
     570                 :            :     }
     571                 :          1 :     case Kind::BITVECTOR_UGE:
     572                 :            :     {
     573                 :          1 :       returnNode = d_nm->mkNode(Kind::GEQ, translated_children);
     574                 :          1 :       break;
     575                 :            :     }
     576                 :          1 :     case Kind::BITVECTOR_ULTBV:
     577                 :            :     {
     578                 :          3 :       returnNode = d_nm->mkNode(Kind::ITE,
     579                 :          2 :                                 d_nm->mkNode(Kind::LT, translated_children),
     580                 :          1 :                                 d_one,
     581                 :          2 :                                 d_zero);
     582                 :          1 :       break;
     583                 :            :     }
     584                 :          0 :     case Kind::BITVECTOR_SLTBV:
     585                 :            :     {
     586                 :          0 :       uint32_t bvsize = original[0].getType().getBitVectorSize();
     587                 :            :       returnNode =
     588                 :          0 :           d_nm->mkNode(Kind::ITE,
     589                 :          0 :                        d_nm->mkNode(Kind::LT,
     590                 :          0 :                                     {uts(translated_children[0], bvsize),
     591                 :          0 :                                      uts(translated_children[1], bvsize)}),
     592                 :          0 :                        d_one,
     593                 :          0 :                        d_zero);
     594                 :          0 :       break;
     595                 :            :     }
     596                 :          0 :     case Kind::BITVECTOR_COMP:
     597                 :            :     {
     598                 :          0 :       returnNode = d_nm->mkNode(
     599                 :            :           Kind::ITE,
     600                 :          0 :           d_nm->mkNode(
     601                 :          0 :               Kind::EQUAL, translated_children[0], translated_children[1]),
     602                 :          0 :           d_one,
     603                 :          0 :           d_zero);
     604                 :          0 :       break;
     605                 :            :     }
     606                 :          9 :     case Kind::BITVECTOR_UADDO:
     607                 :            :     {
     608                 :          9 :       uint32_t bvsize = original[0].getType().getBitVectorSize();
     609                 :            :       Node sum = d_nm->mkNode(
     610                 :         18 :           Kind::ADD, translated_children[0], translated_children[1]);
     611                 :          9 :       returnNode = d_nm->mkNode(Kind::GEQ, sum, pow2(bvsize));
     612                 :          9 :       break;
     613                 :          9 :     }
     614                 :          9 :     case Kind::BITVECTOR_SADDO:
     615                 :            :     {
     616                 :          9 :       uint32_t bvsize = original[0].getType().getBitVectorSize();
     617                 :          9 :       Node signed0 = uts(translated_children[0], bvsize);
     618                 :          9 :       Node signed1 = uts(translated_children[1], bvsize);
     619                 :         18 :       Node sum = d_nm->mkNode(Kind::ADD, signed0, signed1);
     620                 :         18 :       Node disj1 = d_nm->mkNode(Kind::GEQ, sum, pow2(bvsize - 1));
     621                 :            :       Node disj2 = d_nm->mkNode(
     622                 :         18 :           Kind::LT, sum, d_nm->mkNode(Kind::NEG, pow2(bvsize - 1)));
     623                 :          9 :       returnNode = d_nm->mkNode(Kind::OR, disj1, disj2);
     624                 :          9 :       break;
     625                 :          9 :     }
     626                 :          9 :     case Kind::BITVECTOR_UMULO:
     627                 :            :     {
     628                 :          9 :       uint32_t bvsize = original[0].getType().getBitVectorSize();
     629                 :            :       Node mul = d_nm->mkNode(
     630                 :         18 :           Kind::MULT, translated_children[0], translated_children[1]);
     631                 :          9 :       returnNode = d_nm->mkNode(Kind::GEQ, mul, pow2(bvsize));
     632                 :          9 :       break;
     633                 :          9 :     }
     634                 :         16 :     case Kind::BITVECTOR_SMULO:
     635                 :            :     {
     636                 :         16 :       uint32_t bvsize = original[0].getType().getBitVectorSize();
     637                 :         16 :       Node signed0 = uts(translated_children[0], bvsize);
     638                 :         16 :       Node signed1 = uts(translated_children[1], bvsize);
     639                 :         32 :       Node mul = d_nm->mkNode(Kind::MULT, signed0, signed1);
     640                 :         32 :       Node disj1 = d_nm->mkNode(Kind::GEQ, mul, pow2(bvsize - 1));
     641                 :            :       Node disj2 = d_nm->mkNode(
     642                 :         32 :           Kind::LT, mul, d_nm->mkNode(Kind::NEG, pow2(bvsize - 1)));
     643                 :         16 :       returnNode = d_nm->mkNode(Kind::OR, disj1, disj2);
     644                 :         16 :       break;
     645                 :         16 :     }
     646                 :          9 :     case Kind::BITVECTOR_USUBO:
     647                 :            :     {
     648                 :         27 :       returnNode = d_nm->mkNode(
     649                 :         27 :           Kind::LT, translated_children[0], translated_children[1]);
     650                 :          9 :       break;
     651                 :            :     }
     652                 :          9 :     case Kind::BITVECTOR_SSUBO:
     653                 :            :     {
     654                 :          9 :       uint32_t bvsize = original[0].getType().getBitVectorSize();
     655                 :          9 :       Node signed0 = uts(translated_children[0], bvsize);
     656                 :          9 :       Node signed1 = uts(translated_children[1], bvsize);
     657                 :         18 :       Node sub = d_nm->mkNode(Kind::SUB, signed0, signed1);
     658                 :         18 :       Node disj1 = d_nm->mkNode(Kind::GEQ, sub, pow2(bvsize - 1));
     659                 :            :       Node disj2 = d_nm->mkNode(
     660                 :         18 :           Kind::LT, sub, d_nm->mkNode(Kind::NEG, pow2(bvsize - 1)));
     661                 :          9 :       returnNode = d_nm->mkNode(Kind::OR, disj1, disj2);
     662                 :          9 :       break;
     663                 :          9 :     }
     664                 :         42 :     case Kind::ITE:
     665                 :            :     {
     666                 :         42 :       returnNode = d_nm->mkNode(oldKind, translated_children);
     667                 :         42 :       break;
     668                 :            :     }
     669                 :        206 :     case Kind::APPLY_UF:
     670                 :            :     {
     671                 :            :       // Insert the translated application term to the cache
     672                 :        206 :       returnNode = d_nm->mkNode(Kind::APPLY_UF, translated_children);
     673                 :            :       // Add range constraints if necessary.
     674                 :            :       // If the original range was a BV sort, the original application of
     675                 :            :       // the function must be within the range determined by the
     676                 :            :       // bitwidth.
     677                 :            :       // function applications that include bound variables
     678                 :            :       // are ignored at this stage.
     679                 :            :       // Their range constraints are added later under the
     680                 :            :       // appropriate quantifier.
     681                 :        206 :       if (original.getType().isBitVector() && !expr::hasBoundVar(original))
     682                 :            :       {
     683                 :         38 :         addRangeConstraint(
     684                 :         76 :             returnNode, original.getType().getBitVectorSize(), lemmas);
     685                 :            :       }
     686                 :        206 :       break;
     687                 :            :     }
     688                 :        195 :     case Kind::BOUND_VAR_LIST:
     689                 :            :     {
     690                 :        195 :       returnNode = d_nm->mkNode(oldKind, translated_children);
     691         [ +  + ]:        195 :       if (d_mode == options::SolveBVAsIntMode::BITWISE)
     692                 :            :       {
     693                 :          1 :         throw LogicException(
     694                 :          2 :             "--solve-bv-as-int=bitwise does not support quantifiers");
     695                 :            :       }
     696                 :        194 :       break;
     697                 :            :     }
     698                 :         38 :     case Kind::INST_PATTERN:
     699                 :            :     case Kind::INST_PATTERN_LIST:
     700                 :            :     {
     701                 :         38 :       returnNode = d_nm->mkNode(oldKind, translated_children);
     702         [ +  - ]:         38 :       Trace("int-blaster-debug") << "pattern or list: " << oldKind << std::endl;
     703         [ +  - ]:         76 :       Trace("int-blaster-debug")
     704                 :         38 :           << "original pattern/list node: " << original << std::endl;
     705         [ +  - ]:         76 :       Trace("int-blaster-debug")
     706                 :         38 :           << "result pattern/list node: " << returnNode << std::endl;
     707                 :         38 :       break;
     708                 :            :     }
     709                 :        206 :     case Kind::FORALL:
     710                 :            :     {
     711                 :            :       returnNode =
     712                 :        206 :           translateQuantifiedFormula(original, translated_children, lemmas);
     713                 :        206 :       break;
     714                 :            :     }
     715                 :       1470 :     default:
     716                 :            :     {
     717                 :            :       // first, verify that we haven't missed
     718                 :            :       // any bv operator
     719 [ -  + ][ -  + ]:       1470 :       Assert(theory::kindToTheoryId(oldKind) != THEORY_BV);
                 [ -  - ]
     720                 :            : 
     721                 :            :       // In the default case, we have reached an operator that we do not
     722                 :            :       // translate directly to integers. The children whose types have
     723                 :            :       // changed from bv to int should be adjusted back to bv and then
     724                 :            :       // this term is reconstructed.
     725                 :       1470 :       TypeNode resultingType;
     726         [ +  + ]:       1470 :       if (original.getType().isBitVector())
     727                 :            :       {
     728                 :         10 :         resultingType = d_nm->integerType();
     729                 :            :       }
     730                 :            :       else
     731                 :            :       {
     732                 :       1460 :         resultingType = original.getType();
     733                 :            :       }
     734                 :            :       Node reconstruction =
     735                 :       2940 :           reconstructNode(original, resultingType, translated_children);
     736                 :       1470 :       returnNode = reconstruction;
     737                 :       1470 :       break;
     738                 :       1470 :     }
     739                 :            :   }
     740         [ +  - ]:       4200 :   Trace("int-blaster-debug") << "original: " << original << std::endl;
     741         [ +  - ]:       4200 :   Trace("int-blaster-debug") << "returnNode: " << returnNode << std::endl;
     742                 :       8400 :   return returnNode;
     743                 :          2 : }
     744                 :            : 
     745                 :        204 : Node IntBlaster::uts(Node x, uint32_t bvsize)
     746                 :            : {
     747                 :        204 :   Node signedMin = pow2(bvsize - 1);
     748                 :        408 :   Node msbOne = d_nm->mkNode(Kind::LT, x, signedMin);
     749                 :        408 :   Node ite = d_nm->mkNode(Kind::ITE, msbOne, d_zero, pow2(bvsize));
     750                 :        408 :   Node result = d_nm->mkNode(Kind::SUB, x, ite);
     751                 :        408 :   return result;
     752                 :        204 : }
     753                 :            : 
     754                 :         17 : Node IntBlaster::createSignExtendNode(Node x, uint32_t bvsize, uint32_t amount)
     755                 :            : {
     756                 :         17 :   Node returnNode;
     757         [ -  + ]:         17 :   if (x.isConst())
     758                 :            :   {
     759                 :          0 :     Rational c(x.getConst<Rational>());
     760                 :          0 :     Rational twoToKMinusOne(intpow2(bvsize - 1));
     761                 :            :     /* if the msb is 0, this is like zero_extend.
     762                 :            :      *  msb is 0 <-> the value is less than 2^{bvsize-1}
     763                 :            :      */
     764                 :          0 :     if (c < twoToKMinusOne || amount == 0)
     765                 :            :     {
     766                 :          0 :       returnNode = x;
     767                 :            :     }
     768                 :            :     else
     769                 :            :     {
     770                 :            :       /* otherwise, we add the integer equivalent of
     771                 :            :        * 11....1 `amount` times
     772                 :            :        */
     773                 :          0 :       Rational max_of_amount = intpow2(amount) - 1;
     774                 :          0 :       Rational mul = max_of_amount * intpow2(bvsize);
     775                 :          0 :       Rational sum = mul + c;
     776                 :          0 :       returnNode = d_nm->mkConstInt(sum);
     777                 :          0 :     }
     778                 :          0 :   }
     779                 :            :   else
     780                 :            :   {
     781         [ +  + ]:         17 :     if (amount == 0)
     782                 :            :     {
     783                 :         10 :       returnNode = x;
     784                 :            :     }
     785                 :            :     else
     786                 :            :     {
     787                 :          7 :       Rational twoToKMinusOne(intpow2(bvsize - 1));
     788                 :          7 :       Node minSigned = d_nm->mkConstInt(twoToKMinusOne);
     789                 :            :       /* condition checks whether the msb is 1.
     790                 :            :        * This holds when the integer value is smaller than
     791                 :            :        * 100...0, which is 2^{bvsize-1}.
     792                 :            :        */
     793                 :         14 :       Node condition = d_nm->mkNode(Kind::LT, x, minSigned);
     794                 :          7 :       Node thenResult = x;
     795                 :          7 :       Node left = maxInt(amount);
     796                 :         14 :       Node mul = d_nm->mkNode(Kind::MULT, left, pow2(bvsize));
     797                 :         14 :       Node sum = d_nm->mkNode(Kind::ADD, mul, x);
     798                 :          7 :       Node elseResult = sum;
     799                 :         14 :       Node ite = d_nm->mkNode(Kind::ITE, condition, thenResult, elseResult);
     800                 :          7 :       returnNode = ite;
     801                 :          7 :     }
     802                 :            :   }
     803                 :         17 :   return returnNode;
     804                 :          0 : }
     805                 :            : 
     806                 :       2758 : Node IntBlaster::translateNoChildren(Node original,
     807                 :            :                                      std::vector<TrustNode>& lemmas,
     808                 :            :                                      std::map<Node, Node>& skolems)
     809                 :            : {
     810         [ +  - ]:       5516 :   Trace("int-blaster-debug")
     811 [ -  + ][ -  - ]:       2758 :       << "translating leaf: " << original << "; of type: " << original.getType()
     812                 :       2758 :       << std::endl;
     813                 :            :   // The result of the translation
     814                 :       2758 :   Node translation;
     815                 :            : 
     816                 :            :   // The translation is done differently for variables (bound or free)  and
     817                 :            :   // constants (values)
     818         [ +  + ]:       2758 :   if (original.isVar())
     819                 :            :   {
     820         [ +  + ]:       1476 :     if (original.getType().isBitVector())
     821                 :            :     {
     822                 :            :       // For bit-vector variables, we create fresh integer variables.
     823         [ +  + ]:       1094 :       if (original.getKind() == Kind::BOUND_VARIABLE)
     824                 :            :       {
     825                 :            :         // Range constraints for the bound integer variables are not added now.
     826                 :            :         // they will be added once the quantifier itself is handled.
     827                 :        156 :         std::stringstream ss;
     828                 :        156 :         ss << original;
     829                 :            :         translation =
     830                 :        156 :             NodeManager::mkBoundVar(ss.str() + "_int", d_nm->integerType());
     831                 :        156 :       }
     832                 :            :       else
     833                 :            :       {
     834                 :       1876 :         Node intCast = castToType(original, d_nm->integerType());
     835                 :        938 :         Node bvCast;
     836                 :            :         // we introduce a fresh variable, add range constraints, and save the
     837                 :            :         // connection between original and the new variable via intCast
     838                 :        938 :         translation = d_nm->getSkolemManager()->mkPurifySkolem(intCast);
     839                 :        938 :         uint32_t bvsize = original.getType().getBitVectorSize();
     840                 :        938 :         addRangeConstraint(translation, bvsize, lemmas);
     841                 :            :         // put new definition of old variable in skolems
     842                 :        938 :         bvCast = castToType(translation, original.getType());
     843                 :            : 
     844                 :            :         // add bvCast to skolems if it is not already there.
     845         [ +  + ]:        938 :         if (skolems.find(original) == skolems.end())
     846                 :            :         {
     847                 :        937 :           skolems[original] = bvCast;
     848                 :            :         }
     849                 :            :         else
     850                 :            :         {
     851 [ -  + ][ -  + ]:          1 :           Assert(skolems[original] == bvCast);
                 [ -  - ]
     852                 :            :         }
     853                 :        938 :       }
     854                 :            :     }
     855         [ +  + ]:        382 :     else if (original.getType().isFunction())
     856                 :            :     {
     857                 :            :       // translate function symbol
     858                 :        131 :       translation = translateFunctionSymbol(original, skolems);
     859                 :            :     }
     860                 :            :     else
     861                 :            :     {
     862                 :            :       // leave other variables intact
     863                 :        251 :       translation = original;
     864                 :            :     }
     865                 :            :   }
     866                 :            :   else
     867                 :            :   {
     868                 :            :     // original is a constant (value) or an operator with no arguments (e.g.,
     869                 :            :     // PI)
     870         [ +  + ]:       1282 :     if (original.getKind() == Kind::CONST_BITVECTOR)
     871                 :            :     {
     872                 :            :       // Bit-vector constants are transformed into their integer value.
     873                 :        413 :       BitVector constant(original.getConst<BitVector>());
     874                 :        413 :       Integer c = constant.toInteger();
     875                 :        413 :       Rational r = Rational(c, Integer(1));
     876                 :        413 :       translation = d_nm->mkConstInt(r);
     877                 :        413 :     }
     878                 :            :     else
     879                 :            :     {
     880                 :            :       // Other constants or operators stay the same.
     881                 :        869 :       translation = original;
     882                 :            :     }
     883                 :            :   }
     884                 :       2758 :   return translation;
     885                 :          0 : }
     886                 :            : 
     887                 :        131 : Node IntBlaster::translateFunctionSymbol(Node bvUF,
     888                 :            :                                          std::map<Node, Node>& skolems)
     889                 :            : {
     890                 :            :   // create the new function symbol as a skolem
     891                 :        131 :   SkolemManager* sm = d_nm->getSkolemManager();
     892                 :        131 :   Node intUF = sm->mkSkolemFunction(SkolemId::BV_TO_INT_UF, bvUF);
     893                 :            : 
     894                 :            :   // formal arguments of the lambda expression.
     895                 :        131 :   std::vector<Node> args;
     896                 :            : 
     897                 :            :   // arguments to be passed in the application.
     898                 :        131 :   std::vector<Node> achildren;
     899                 :        131 :   achildren.push_back(intUF);
     900                 :            : 
     901                 :            :   // iterate the arguments, cast BV arguments to integers
     902                 :        131 :   int i = 0;
     903                 :        131 :   TypeNode tn = bvUF.getType();
     904                 :        131 :   TypeNode bvRange = tn.getRangeType();
     905                 :        131 :   std::vector<TypeNode> bvDomain = tn.getArgTypes();
     906         [ +  + ]:        299 :   for (const TypeNode& d : bvDomain)
     907                 :            :   {
     908                 :            :     // Each bit-vector argument is casted to a natural number
     909                 :            :     // Other arguments are left intact.
     910                 :        168 :     Node fresh_bound_var = NodeManager::mkBoundVar(d);
     911                 :        168 :     args.push_back(fresh_bound_var);
     912                 :        168 :     Node castedArg = args[i];
     913         [ +  + ]:        168 :     if (d.isBitVector())
     914                 :            :     {
     915                 :        106 :       castedArg = castToType(castedArg, d_nm->integerType());
     916                 :            :     }
     917                 :        168 :     achildren.push_back(castedArg);
     918                 :        168 :     i++;
     919                 :        168 :   }
     920                 :            :   // create the lambda expression, and add it to skolems
     921                 :        131 :   Node app = d_nm->mkNode(Kind::APPLY_UF, achildren);
     922                 :        262 :   Node body = castToType(app, bvRange);
     923                 :        131 :   Node bvlist = d_nm->mkNode(Kind::BOUND_VAR_LIST, args);
     924                 :        262 :   Node result = d_nm->mkNode(Kind::LAMBDA, bvlist, body);
     925         [ +  - ]:        131 :   if (skolems.find(bvUF) == skolems.end())
     926                 :            :   {
     927                 :        131 :     skolems[bvUF] = result;
     928                 :            :   }
     929                 :        262 :   return intUF;
     930                 :        131 : }
     931                 :            : 
     932                 :       4202 : bool IntBlaster::childrenTypesChanged(Node n)
     933                 :            : {
     934                 :       4202 :   bool result = false;
     935         [ +  + ]:       8217 :   for (const Node& child : n)
     936                 :            :   {
     937                 :            :     // the child's type has changed only if it has been
     938                 :            :     // processed already
     939         [ +  + ]:       5938 :     if (d_intblastCache.find(child) != d_intblastCache.end())
     940                 :            :     {
     941                 :       5892 :       TypeNode originalType = child.getType();
     942                 :       5892 :       TypeNode newType = d_intblastCache[child].get().getType();
     943         [ +  + ]:       5892 :       if (newType != originalType)
     944                 :            :       {
     945                 :       1923 :         result = true;
     946                 :       1923 :         break;
     947                 :            :       }
     948 [ +  + ][ +  + ]:       7815 :     }
     949         [ +  + ]:       5938 :   }
     950                 :       4202 :   return result;
     951                 :            : }
     952                 :            : 
     953                 :       6019 : Node IntBlaster::castToType(Node n, TypeNode tn)
     954                 :            : {
     955                 :            :   // If there is no reason to cast, return the
     956                 :            :   // original node.
     957         [ +  + ]:       6019 :   if (n.getType() == tn)
     958                 :            :   {
     959                 :       3944 :     return n;
     960                 :            :   }
     961                 :            :   // We only case int to bv or vice verse.
     962                 :       2075 :   Assert((n.getType().isBitVector() && tn.isInteger())
     963                 :            :          || (n.getType().isInteger() && tn.isBitVector()));
     964 [ +  - ][ -  + ]:       4150 :   Trace("int-blaster") << "castToType from " << n.getType() << " to " << tn
                 [ -  - ]
     965                 :       2075 :                        << std::endl;
     966                 :            : 
     967                 :            :   // casting integers to bit-vectors
     968         [ +  + ]:       2075 :   if (n.getType().isInteger())
     969                 :            :   {
     970 [ -  + ][ -  + ]:       1021 :     Assert(tn.isBitVector());
                 [ -  - ]
     971                 :       1021 :     unsigned bvsize = tn.getBitVectorSize();
     972                 :       1021 :     Node intToBVOp = d_nm->mkConst<IntToBitVector>(IntToBitVector(bvsize));
     973                 :       1021 :     return d_nm->mkNode(intToBVOp, n);
     974                 :       1021 :   }
     975                 :            :   // casting bit-vectors to ingers
     976 [ -  + ][ -  + ]:       1054 :   Assert(n.getType().isBitVector());
                 [ -  - ]
     977 [ -  + ][ -  + ]:       1054 :   Assert(tn.isInteger());
                 [ -  - ]
     978                 :       1054 :   return d_nm->mkNode(Kind::BITVECTOR_UBV_TO_INT, n);
     979                 :            : }
     980                 :            : 
     981                 :       1470 : Node IntBlaster::reconstructNode(Node originalNode,
     982                 :            :                                  TypeNode resultType,
     983                 :            :                                  const std::vector<Node>& translated_children)
     984                 :            : {
     985                 :            :   // first, we adjust the children of the node as needed.
     986                 :            :   // re-construct the term with the adjusted children.
     987                 :       1470 :   Kind oldKind = originalNode.getKind();
     988                 :       1470 :   NodeBuilder builder(nodeManager(), oldKind);
     989         [ +  + ]:       1470 :   if (originalNode.getMetaKind() == kind::metakind::PARAMETERIZED)
     990                 :            :   {
     991                 :          7 :     builder << originalNode.getOperator();
     992                 :            :   }
     993         [ +  + ]:       3906 :   for (uint32_t i = 0; i < originalNode.getNumChildren(); i++)
     994                 :            :   {
     995                 :       2436 :     Node originalChild = originalNode[i];
     996                 :       2436 :     Node translatedChild = translated_children[i];
     997                 :       4872 :     Node adjustedChild = castToType(translatedChild, originalChild.getType());
     998                 :       2436 :     builder << adjustedChild;
     999                 :       2436 :   }
    1000                 :       1470 :   Node reconstruction = builder.constructNode();
    1001                 :            :   // cast to tn in case the reconstruction is a bit-vector.
    1002                 :       1470 :   reconstruction = castToType(reconstruction, resultType);
    1003                 :       2940 :   return reconstruction;
    1004                 :       1470 : }
    1005                 :            : 
    1006                 :        228 : Node IntBlaster::createShiftNode(std::vector<Node> children,
    1007                 :            :                                  uint32_t bvsize,
    1008                 :            :                                  bool isLeftShift)
    1009                 :            : {
    1010                 :            :   /**
    1011                 :            :    * from SMT-LIB:
    1012                 :            :    * [[(bvshl s t)]] := nat2bv[m](bv2nat([[s]]) * 2^(bv2nat([[t]])))
    1013                 :            :    * [[(bvlshr s t)]] := nat2bv[m](bv2nat([[s]]) div 2^(bv2nat([[t]])))
    1014                 :            :    * Since we don't have exponentiation, we use an ite.
    1015                 :            :    * Important note: below we use INTS_DIVISION_TOTAL, which is safe here
    1016                 :            :    * because we divide by 2^... which is never 0.
    1017                 :            :    */
    1018                 :        228 :   Node x = children[0];
    1019                 :        228 :   Node y = children[1];
    1020                 :            :   // shifting by const is eliminated by the theory rewriter
    1021 [ -  + ][ -  + ]:        228 :   Assert(!y.isConst());
                 [ -  - ]
    1022                 :            : 
    1023                 :            :   // if we use the internal pow2 operator, the translation does not
    1024                 :            :   // have any ites
    1025         [ +  + ]:        228 :   if (options().smt.bvToIntUsePow2)
    1026                 :            :   {
    1027                 :         55 :     Node pow2Node = d_nm->mkNode(Kind::POW2, y);
    1028         [ -  + ]:         55 :     if (isLeftShift)
    1029                 :            :     {
    1030                 :          0 :       return d_nm->mkNode(
    1031                 :            :           Kind::INTS_MODULUS_TOTAL,
    1032                 :          0 :           {d_nm->mkNode(Kind::MULT, x, pow2Node), pow2(bvsize)});
    1033                 :            :     }
    1034                 :            :     else
    1035                 :            :     {
    1036                 :         55 :       return d_nm->mkNode(Kind::INTS_DIVISION_TOTAL, x, pow2Node);
    1037                 :            :     }
    1038                 :         55 :   }
    1039                 :            : 
    1040                 :            :   // if we do not use the internal pow2 operator, we use ites.
    1041                 :        173 :   Node ite = d_zero;
    1042                 :        173 :   Node body;
    1043         [ +  + ]:        963 :   for (uint32_t i = 0; i < bvsize; i++)
    1044                 :            :   {
    1045         [ +  + ]:        790 :     if (isLeftShift)
    1046                 :            :     {
    1047 [ +  + ][ -  - ]:        180 :       body = d_nm->mkNode(Kind::INTS_MODULUS_TOTAL,
    1048                 :        144 :                           {d_nm->mkNode(Kind::MULT, x, pow2(i)), pow2(bvsize)});
    1049                 :            :     }
    1050                 :            :     else
    1051                 :            :     {
    1052                 :        754 :       body = d_nm->mkNode(Kind::INTS_DIVISION_TOTAL, x, pow2(i));
    1053                 :            :     }
    1054                 :       3160 :     ite = d_nm->mkNode(
    1055                 :            :         Kind::ITE,
    1056                 :       1580 :         d_nm->mkNode(
    1057                 :       1580 :             Kind::EQUAL, y, d_nm->mkConstInt(Rational(Integer(i), Integer(1)))),
    1058                 :            :         body,
    1059                 :        790 :         ite);
    1060                 :            :   }
    1061                 :        173 :   return ite;
    1062                 :        228 : }
    1063                 :            : 
    1064                 :        206 : Node IntBlaster::translateQuantifiedFormula(
    1065                 :            :     Node quantifiedNode,
    1066                 :            :     const std::vector<Node>& translated_children,
    1067                 :            :     std::vector<TrustNode>& lemmas)
    1068                 :            : {
    1069                 :        206 :   Node boundVarList = quantifiedNode[0];
    1070 [ -  + ][ -  + ]:        206 :   Assert(boundVarList.getKind() == Kind::BOUND_VAR_LIST);
                 [ -  - ]
    1071 [ -  + ][ -  + ]:        206 :   Assert(translated_children.size() == quantifiedNode.getNumChildren());
                 [ -  - ]
    1072                 :            : 
    1073                 :            :   // Since bit-vector variables are being translated to
    1074                 :            :   // integer variables, we need to substitute the new ones
    1075                 :            :   // for the old ones.
    1076                 :        206 :   std::vector<Node> oldBoundVars;
    1077                 :        206 :   std::vector<Node> newBoundVars;
    1078                 :            : 
    1079                 :            :   // range constraints for quantified variables and terms
    1080                 :        206 :   std::vector<Node> rangeConstraints;
    1081                 :            : 
    1082                 :            :   // collect range constraints for quantified variables
    1083         [ +  + ]:        474 :   for (Node bv : quantifiedNode[0])
    1084                 :            :   {
    1085                 :        268 :     oldBoundVars.push_back(bv);
    1086         [ +  + ]:        268 :     if (bv.getType().isBitVector())
    1087                 :            :     {
    1088                 :            :       // bit-vector variables are replaced by integer ones.
    1089                 :            :       // the new variables induce range constraints based on the
    1090                 :            :       // original bit-width.
    1091 [ -  + ][ -  + ]:        155 :       Assert(d_intblastCache.find(bv) != d_intblastCache.end());
                 [ -  - ]
    1092                 :        155 :       Node newBoundVar = d_intblastCache[bv];
    1093                 :        155 :       newBoundVars.push_back(newBoundVar);
    1094                 :        155 :       rangeConstraints.push_back(
    1095                 :        310 :           mkRangeConstraint(newBoundVar, bv.getType().getBitVectorSize()));
    1096                 :        155 :     }
    1097                 :            :     else
    1098                 :            :     {
    1099                 :            :       // variables that are not bit-vectors are not changed
    1100                 :        113 :       newBoundVars.push_back(bv);
    1101                 :            :     }
    1102                 :        474 :   }
    1103                 :            : 
    1104                 :            :   // collect range constraints for UF applications
    1105                 :            :   // that involve quantified variables
    1106                 :        206 :   std::unordered_set<Node> applys;
    1107                 :        206 :   expr::getKindSubterms(quantifiedNode[1], Kind::APPLY_UF, false, applys);
    1108         [ +  + ]:        338 :   for (const Node& apply : applys)
    1109                 :            :   {
    1110                 :        132 :     Node f = apply.getOperator();
    1111                 :            : 
    1112                 :        132 :     TypeNode range = f.getType().getRangeType();
    1113         [ +  + ]:        132 :     if (range.isBitVector())
    1114                 :            :     {
    1115 [ -  + ][ -  + ]:         83 :       Assert(d_intblastCache.find(f) != d_intblastCache.end());
                 [ -  - ]
    1116 [ -  + ][ -  + ]:         83 :       Assert(!d_intblastCache[f].get().isNull());
                 [ -  - ]
    1117                 :         83 :       Node translated_f = d_intblastCache[f];
    1118                 :         83 :       addQuantifiedRangeConstraint(
    1119                 :            :           translated_f, range.getBitVectorSize(), lemmas);
    1120                 :         83 :     }
    1121                 :        132 :   }
    1122                 :            : 
    1123                 :            :   // the body of the quantifier
    1124                 :        206 :   Node matrix = translated_children[1];
    1125                 :            :   // make the substitution
    1126                 :        412 :   matrix = matrix.substitute(oldBoundVars.begin(),
    1127                 :            :                              oldBoundVars.end(),
    1128                 :            :                              newBoundVars.begin(),
    1129                 :        206 :                              newBoundVars.end());
    1130                 :            :   // A node to represent all the range constraints.
    1131                 :        206 :   Node ranges = d_nm->mkAnd(rangeConstraints);
    1132                 :            :   // Add the range constraints to the left side of an implication.
    1133 [ -  + ][ -  + ]:        206 :   Assert(quantifiedNode.getKind() == Kind::FORALL);
                 [ -  - ]
    1134                 :        206 :   matrix = d_nm->mkNode(Kind::IMPLIES, ranges, matrix);
    1135                 :            :   // create the new quantified formula and return it.
    1136                 :        206 :   Node newBoundVarsList = d_nm->mkNode(Kind::BOUND_VAR_LIST, newBoundVars);
    1137                 :        206 :   Node result;
    1138                 :            :   // if there was an instantiation pattern, include its translation.
    1139         [ +  + ]:        206 :   if (quantifiedNode.getNumChildren() == 3)
    1140                 :            :   {
    1141                 :         48 :     result = d_nm->mkNode(
    1142                 :         48 :         Kind::FORALL, newBoundVarsList, matrix, translated_children[2]);
    1143                 :            :   }
    1144                 :            :   else
    1145                 :            :   {
    1146                 :        182 :     result = d_nm->mkNode(Kind::FORALL, newBoundVarsList, matrix);
    1147                 :            :   }
    1148                 :        412 :   return result;
    1149                 :        206 : }
    1150                 :            : 
    1151                 :         54 : Node IntBlaster::createBVAndNode(Node x,
    1152                 :            :                                  Node y,
    1153                 :            :                                  uint32_t bvsize,
    1154                 :            :                                  std::vector<TrustNode>& lemmas)
    1155                 :            : {
    1156                 :            :   // We support three configurations:
    1157                 :            :   // 1. translating to IAND
    1158                 :            :   // 2. translating back to BV (using BITVECTOR_UBV_TO_INT and INT_TO_BV
    1159                 :            :   // operators)
    1160                 :            :   // 3. translating into a sum
    1161                 :         54 :   Node returnNode;
    1162         [ +  + ]:         54 :   if (d_mode == options::SolveBVAsIntMode::IAND)
    1163                 :            :   {
    1164                 :         22 :     Node iAndOp = d_nm->mkConst(IntAnd(bvsize));
    1165                 :         22 :     returnNode = d_nm->mkNode(Kind::IAND, iAndOp, x, y);
    1166                 :         22 :   }
    1167         [ +  + ]:         32 :   else if (d_mode == options::SolveBVAsIntMode::BV)
    1168                 :            :   {
    1169                 :            :     // translate the children back to BV
    1170                 :         10 :     Node intToBVOp = d_nm->mkConst<IntToBitVector>(IntToBitVector(bvsize));
    1171                 :         20 :     Node bvx = d_nm->mkNode(intToBVOp, x);
    1172                 :         20 :     Node bvy = d_nm->mkNode(intToBVOp, y);
    1173                 :            :     // perform bvand on the bit-vectors
    1174                 :         20 :     Node bvand = d_nm->mkNode(Kind::BITVECTOR_AND, bvx, bvy);
    1175                 :            :     // translate the result to integers
    1176                 :         10 :     returnNode = d_nm->mkNode(Kind::BITVECTOR_UBV_TO_INT, bvand);
    1177                 :         10 :   }
    1178         [ +  + ]:         22 :   else if (d_mode == options::SolveBVAsIntMode::SUM)
    1179                 :            :   {
    1180                 :            :     // Construct a sum of ites, based on granularity.
    1181                 :         12 :     returnNode = d_iandUtils.createSumNode(x, y, bvsize, d_granularity);
    1182                 :            :   }
    1183                 :            :   else
    1184                 :            :   {
    1185 [ -  + ][ -  + ]:         10 :     Assert(d_mode == options::SolveBVAsIntMode::BITWISE);
                 [ -  - ]
    1186                 :            :     // Enforce semantics over individual bits with iextract and ites
    1187                 :            : 
    1188                 :         10 :     Node iAndOp = d_nm->mkConst(IntAnd(bvsize));
    1189                 :         20 :     Node iAnd = d_nm->mkNode(Kind::IAND, iAndOp, x, y);
    1190                 :            :     // get a skolem so the IAND solver knows not to do work
    1191                 :         10 :     returnNode = d_nm->getSkolemManager()->mkPurifySkolem(iAnd);
    1192                 :         10 :     addRangeConstraint(returnNode, bvsize, lemmas);
    1193                 :            : 
    1194                 :            :     // eagerly add bitwise lemmas according to the provided granularity
    1195                 :            :     uint32_t high_bit;
    1196         [ +  + ]:         46 :     for (uint32_t j = 0; j < bvsize; j += d_granularity)
    1197                 :            :     {
    1198                 :         36 :       high_bit = j + d_granularity - 1;
    1199                 :            :       // don't let high_bit pass bvsize
    1200         [ -  + ]:         36 :       if (high_bit >= bvsize)
    1201                 :            :       {
    1202                 :          0 :         high_bit = bvsize - 1;
    1203                 :            :       }
    1204                 :         36 :       Node extractedReturnNode = d_iandUtils.iextract(high_bit, j, returnNode);
    1205                 :         36 :       addBitwiseConstraint(
    1206                 :         72 :           extractedReturnNode.eqNode(
    1207                 :         72 :               d_iandUtils.createBitwiseIAndNode(x, y, high_bit, j)),
    1208                 :            :           lemmas);
    1209                 :         36 :     }
    1210                 :         10 :   }
    1211                 :         54 :   return returnNode;
    1212                 :          0 : }
    1213                 :            : 
    1214                 :         15 : Node IntBlaster::createBVOrNode(Node x,
    1215                 :            :                                 Node y,
    1216                 :            :                                 uint32_t bvsize,
    1217                 :            :                                 std::vector<TrustNode>& lemmas)
    1218                 :            : {
    1219                 :            :   // Based on Hacker's Delight section 2-2 equation h:
    1220                 :            :   // x+y = x|y + x&y
    1221                 :            :   // from which we deduce:
    1222                 :            :   // x|y = x+y - x&y
    1223                 :         30 :   Node plus = createBVAddNode(x, y, bvsize);
    1224                 :         30 :   Node bvand = createBVAndNode(x, y, bvsize, lemmas);
    1225                 :         30 :   return createBVSubNode(plus, bvand, bvsize);
    1226                 :         15 : }
    1227                 :            : 
    1228                 :         15 : Node IntBlaster::createBVSubNode(Node x, Node y, uint32_t bvsize)
    1229                 :            : {
    1230                 :         30 :   Node minus = d_nm->mkNode(Kind::SUB, x, y);
    1231                 :         15 :   Node p2 = pow2(bvsize);
    1232                 :         30 :   return d_nm->mkNode(Kind::INTS_MODULUS_TOTAL, minus, p2);
    1233                 :         15 : }
    1234                 :            : 
    1235                 :        163 : Node IntBlaster::createBVAddNode(Node x, Node y, uint32_t bvsize)
    1236                 :            : {
    1237                 :        326 :   Node plus = d_nm->mkNode(Kind::ADD, x, y);
    1238                 :        163 :   Node p2 = pow2(bvsize);
    1239                 :        326 :   return d_nm->mkNode(Kind::INTS_MODULUS_TOTAL, plus, p2);
    1240                 :        163 : }
    1241                 :            : 
    1242                 :         24 : Node IntBlaster::createBVNegNode(Node n, uint32_t bvsize)
    1243                 :            : {
    1244                 :            :   // Based on Hacker's Delight section 2-2 equation a:
    1245                 :            :   // -x = ~x+1
    1246                 :         24 :   Node bvNotNode = createBVNotNode(n, bvsize);
    1247                 :         48 :   return createBVAddNode(bvNotNode, d_one, bvsize);
    1248                 :         24 : }
    1249                 :            : 
    1250                 :         70 : Node IntBlaster::createBVNotNode(Node n, uint32_t bvsize)
    1251                 :            : {
    1252                 :         70 :   return d_nm->mkNode(Kind::SUB, maxInt(bvsize), n);
    1253                 :            : }
    1254                 :            : 
    1255                 :            : }  // namespace cvc5::internal

Generated by: LCOV version 1.14