GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/theory/bv/int_blaster.cpp Lines: 226 377 59.9 %
Date: 2021-11-07 Branches: 410 1652 24.8 %

Line Exec Source
1
/******************************************************************************
2
 * Top contributors (to current version):
3
 *   Yoni Zohar
4
 *
5
 * This file is part of the cvc5 project.
6
 *
7
 * Copyright (c) 2009-2021 by the authors listed in the file AUTHORS
8
 * in the top-level source directory and their institutional affiliations.
9
 * All rights reserved.  See the file COPYING in the top-level source
10
 * directory for licensing information.
11
 * ****************************************************************************
12
 *
13
 * Int-blasting utility
14
 */
15
16
#include "theory/bv/int_blaster.h"
17
18
#include <cmath>
19
#include <sstream>
20
#include <string>
21
#include <unordered_map>
22
#include <vector>
23
24
#include "expr/node.h"
25
#include "expr/node_traversal.h"
26
#include "expr/skolem_manager.h"
27
#include "options/option_exception.h"
28
#include "options/uf_options.h"
29
#include "theory/bv/theory_bv_utils.h"
30
#include "theory/logic_info.h"
31
#include "util/bitvector.h"
32
#include "util/iand.h"
33
#include "util/rational.h"
34
35
namespace cvc5 {
36
using namespace cvc5::theory;
37
38
namespace {
39
40
// A helper function to compute 2^b as a Rational
41
18
Rational intpow2(uint64_t b) { return Rational(Integer(2).pow(b), Integer(1)); }
42
43
}  // namespace
44
45
8
IntBlaster::IntBlaster(Env& env,
46
                       options::SolveBVAsIntMode mode,
47
                       uint64_t granularity,
48
8
                       bool introduceFreshIntVars)
49
    : EnvObj(env),
50
8
      d_binarizeCache(userContext()),
51
8
      d_intblastCache(userContext()),
52
8
      d_rangeAssertions(userContext()),
53
8
      d_bitwiseAssertions(userContext()),
54
      d_mode(mode),
55
      d_granularity(granularity),
56
8
      d_context(userContext()),
57
48
      d_introduceFreshIntVars(introduceFreshIntVars)
58
{
59
8
  d_nm = NodeManager::currentNM();
60
8
  d_zero = d_nm->mkConst<Rational>(0);
61
8
  d_one = d_nm->mkConst<Rational>(1);
62
8
};
63
64
8
IntBlaster::~IntBlaster() {}
65
66
8
void IntBlaster::addRangeConstraint(Node node,
67
                                    uint64_t size,
68
                                    std::vector<Node>& lemmas)
69
{
70
8
}
71
72
void IntBlaster::addBitwiseConstraint(Node bitwiseConstraint,
73
                                      std::vector<Node>& lemmas)
74
{
75
}
76
77
Node IntBlaster::mkRangeConstraint(Node newVar, uint64_t k) { return Node(); }
78
79
2
Node IntBlaster::maxInt(uint64_t k)
80
{
81
2
  Assert(k > 0);
82
4
  Rational max_value = intpow2(k) - 1;
83
4
  return d_nm->mkConst<Rational>(max_value);
84
}
85
86
12
Node IntBlaster::pow2(uint64_t k)
87
{
88
12
  Assert(k >= 0);
89
12
  return d_nm->mkConst<Rational>(intpow2(k));
90
}
91
92
4
Node IntBlaster::modpow2(Node n, uint64_t exponent)
93
{
94
8
  Node p2 = d_nm->mkConst<Rational>(intpow2(exponent));
95
8
  return d_nm->mkNode(kind::INTS_MODULUS_TOTAL, n, p2);
96
}
97
98
Node IntBlaster::makeBinary(Node n)
99
{
100
  if (d_binarizeCache.find(n) != d_binarizeCache.end())
101
  {
102
    return d_binarizeCache[n];
103
  }
104
  uint64_t numChildren = n.getNumChildren();
105
  kind::Kind_t k = n.getKind();
106
  Node result = n;
107
  if ((numChildren > 2)
108
      && (k == kind::BITVECTOR_ADD || k == kind::BITVECTOR_MULT
109
          || k == kind::BITVECTOR_AND || k == kind::BITVECTOR_OR
110
          || k == kind::BITVECTOR_XOR || k == kind::BITVECTOR_CONCAT))
111
  {
112
    result = n[0];
113
    for (uint64_t i = 1; i < numChildren; i++)
114
    {
115
      result = d_nm->mkNode(n.getKind(), result, n[i]);
116
    }
117
  }
118
  d_binarizeCache[n] = result;
119
  Trace("int-blaster-debug") << "binarization result: " << result << std::endl;
120
  return result;
121
}
122
123
/**
124
 * Translate n to Integers via post-order traversal.
125
 */
126
Node IntBlaster::intBlast(Node n,
127
                          std::vector<Node>& lemmas,
128
                          std::map<Node, Node>& skolems)
129
{
130
  // make sure the node is re-written
131
  n = rewrite(n);
132
133
  // helper vector for traversal.
134
  std::vector<Node> toVisit;
135
  toVisit.push_back(makeBinary(n));
136
137
  while (!toVisit.empty())
138
  {
139
    Node current = toVisit.back();
140
    uint64_t currentNumChildren = current.getNumChildren();
141
    if (d_intblastCache.find(current) == d_intblastCache.end())
142
    {
143
      // This is the first time we visit this node and it is not in the cache.
144
      // We mark this node as visited but not translated by assiging
145
      // a null node to it.
146
      d_intblastCache[current] = Node();
147
      // all the node's children are added to the stack to be visited
148
      // before visiting this node again.
149
      for (const Node& child : current)
150
      {
151
        toVisit.push_back(makeBinary(child));
152
      }
153
      // If this is a UF applicatinon, we also add the function to
154
      // toVisit.
155
      if (current.getKind() == kind::APPLY_UF)
156
      {
157
        toVisit.push_back(current.getOperator());
158
      }
159
    }
160
    else
161
    {
162
      // We already visited and translated this node
163
      if (!d_intblastCache[current].get().isNull())
164
      {
165
        // We are done computing the translation for current
166
        toVisit.pop_back();
167
      }
168
      else
169
      {
170
        // We are now visiting current on the way back up.
171
        // This is when we do the actual translation.
172
        Node translation;
173
        if (currentNumChildren == 0)
174
        {
175
          translation = translateNoChildren(current, lemmas, skolems);
176
        }
177
        else
178
        {
179
          /**
180
           * The current node has children.
181
           * Since we are on the way back up,
182
           * these children were already translated.
183
           * We save their translation for easy access.
184
           * If the node's kind is APPLY_UF,
185
           * we also need to include the translated uninterpreted function in
186
           * this list.
187
           */
188
          std::vector<Node> translated_children;
189
          if (current.getKind() == kind::APPLY_UF)
190
          {
191
            translated_children.push_back(
192
                d_intblastCache[current.getOperator()]);
193
          }
194
          for (uint64_t i = 0; i < currentNumChildren; i++)
195
          {
196
            translated_children.push_back(d_intblastCache[current[i]]);
197
          }
198
          translation =
199
              translateWithChildren(current, translated_children, lemmas);
200
        }
201
202
        Assert(!translation.isNull());
203
        // Map the current node to its translation in the cache.
204
        d_intblastCache[current] = translation;
205
        // Also map the translation to itself.
206
        d_intblastCache[translation] = translation;
207
        toVisit.pop_back();
208
      }
209
    }
210
  }
211
  return d_intblastCache[n].get();
212
}
213
214
Node IntBlaster::uts(Node n, uint64_t bw) { return Node(); }
215
216
38
Node IntBlaster::translateWithChildren(
217
    Node original,
218
    const std::vector<Node>& translated_children,
219
    std::vector<Node>& lemmas)
220
{
221
  // The translation of the original node is determined by the kind of
222
  // the node.
223
38
  kind::Kind_t oldKind = original.getKind();
224
225
  // Some BV operators were eliminated before this point.
226
38
  Assert(oldKind != kind::BITVECTOR_SDIV);
227
38
  Assert(oldKind != kind::BITVECTOR_SREM);
228
38
  Assert(oldKind != kind::BITVECTOR_SMOD);
229
38
  Assert(oldKind != kind::BITVECTOR_XNOR);
230
38
  Assert(oldKind != kind::BITVECTOR_NAND);
231
38
  Assert(oldKind != kind::BITVECTOR_SUB);
232
38
  Assert(oldKind != kind::BITVECTOR_REPEAT);
233
38
  Assert(oldKind != kind::BITVECTOR_ROTATE_RIGHT);
234
38
  Assert(oldKind != kind::BITVECTOR_ROTATE_LEFT);
235
38
  Assert(oldKind != kind::BITVECTOR_COMP);
236
38
  Assert(oldKind != kind::BITVECTOR_SGT);
237
38
  Assert(oldKind != kind::BITVECTOR_SLE);
238
38
  Assert(oldKind != kind::BITVECTOR_SGE);
239
38
  Assert(oldKind != kind::EXISTS);
240
241
  // BV division by zero was eliminated before this point.
242
38
  Assert(oldKind != kind::BITVECTOR_UDIV
243
         || !(original[1].isConst()
244
              && original[1].getConst<BitVector>().getValue().isZero()));
245
246
  // Store the translated node
247
38
  Node returnNode;
248
249
  // Translate according to the kind of the original node.
250
38
  switch (oldKind)
251
  {
252
2
    case kind::BITVECTOR_ADD:
253
    {
254
2
      Assert(original.getNumChildren() == 2);
255
2
      uint64_t bvsize = original[0].getType().getBitVectorSize();
256
4
      returnNode = createBVAddNode(
257
4
          translated_children[0], translated_children[1], bvsize);
258
2
      break;
259
    }
260
2
    case kind::BITVECTOR_MULT:
261
    {
262
2
      Assert(original.getNumChildren() == 2);
263
2
      uint64_t bvsize = original[0].getType().getBitVectorSize();
264
4
      Node mult = d_nm->mkNode(kind::MULT, translated_children);
265
4
      Node p2 = pow2(bvsize);
266
2
      returnNode = d_nm->mkNode(kind::INTS_MODULUS_TOTAL, mult, p2);
267
2
      break;
268
    }
269
2
    case kind::BITVECTOR_UDIV:
270
    {
271
      // we use an ITE for the case where the second operand is 0.
272
2
      uint64_t bvsize = original[0].getType().getBitVectorSize();
273
4
      Node pow2BvSize = pow2(bvsize);
274
      Node divNode =
275
4
          d_nm->mkNode(kind::INTS_DIVISION_TOTAL, translated_children);
276
10
      returnNode = d_nm->mkNode(
277
          kind::ITE,
278
4
          d_nm->mkNode(kind::EQUAL, translated_children[1], d_zero),
279
4
          d_nm->mkNode(kind::MINUS, pow2BvSize, d_one),
280
          divNode);
281
2
      break;
282
    }
283
2
    case kind::BITVECTOR_UREM:
284
    {
285
      // we use an ITE for the case where the second operand is 0.
286
      Node modNode =
287
4
          d_nm->mkNode(kind::INTS_MODULUS_TOTAL, translated_children);
288
8
      returnNode = d_nm->mkNode(
289
          kind::ITE,
290
4
          d_nm->mkNode(kind::EQUAL, translated_children[1], d_zero),
291
2
          translated_children[0],
292
          modNode);
293
2
      break;
294
    }
295
2
    case kind::BITVECTOR_NOT:
296
    {
297
2
      uint64_t bvsize = original[0].getType().getBitVectorSize();
298
2
      returnNode = createBVNotNode(translated_children[0], bvsize);
299
2
      break;
300
    }
301
2
    case kind::BITVECTOR_NEG:
302
    {
303
2
      uint64_t bvsize = original[0].getType().getBitVectorSize();
304
2
      returnNode = createBVNegNode(translated_children[0], bvsize);
305
2
      break;
306
    }
307
2
    case kind::BITVECTOR_TO_NAT:
308
    {
309
      // In this case, we already translated the child to integer.
310
      // The result is simply the translated child.
311
2
      returnNode = translated_children[0];
312
2
      break;
313
    }
314
2
    case kind::INT_TO_BITVECTOR:
315
    {
316
      // In this case we take the original integer,
317
      // modulo 2 to the power of the bit-width
318
2
      returnNode =
319
4
          modpow2(translated_children[0],
320
4
                  original.getOperator().getConst<IntToBitVector>().d_size);
321
2
      break;
322
    }
323
    case kind::BITVECTOR_OR:
324
    {
325
      Assert(translated_children.size() == 2);
326
      uint64_t bvsize = original[0].getType().getBitVectorSize();
327
      returnNode = createBVOrNode(
328
          translated_children[0], translated_children[1], bvsize, lemmas);
329
      break;
330
    }
331
    case kind::BITVECTOR_XOR:
332
    {
333
      Assert(translated_children.size() == 2);
334
      uint64_t bvsize = original[0].getType().getBitVectorSize();
335
      // Based on Hacker's Delight section 2-2 equation n:
336
      // x xor y = x|y - x&y
337
      Node bvor = createBVOrNode(
338
          translated_children[0], translated_children[1], bvsize, lemmas);
339
      Node bvand = createBVAndNode(
340
          translated_children[0], translated_children[1], bvsize, lemmas);
341
      returnNode = createBVSubNode(bvor, bvand, bvsize);
342
      break;
343
    }
344
    case kind::BITVECTOR_AND:
345
    {
346
      Assert(translated_children.size() == 2);
347
      uint64_t bvsize = original[0].getType().getBitVectorSize();
348
      returnNode = createBVAndNode(
349
          translated_children[0], translated_children[1], bvsize, lemmas);
350
      break;
351
    }
352
    case kind::BITVECTOR_SHL:
353
    {
354
      uint64_t bvsize = original[0].getType().getBitVectorSize();
355
      returnNode = createShiftNode(translated_children, bvsize, true);
356
      break;
357
    }
358
    case kind::BITVECTOR_LSHR:
359
    {
360
      uint64_t bvsize = original[0].getType().getBitVectorSize();
361
      returnNode = createShiftNode(translated_children, bvsize, false);
362
      break;
363
    }
364
    case kind::BITVECTOR_ASHR:
365
    {
366
      /*  From SMT-LIB2:
367
       *  (bvashr s t) abbreviates
368
       *     (ite (= ((_ extract |m-1| |m-1|) s) #b0)
369
       *          (bvlshr s t)
370
       *          (bvnot (bvlshr (bvnot s) t)))
371
       *
372
       *  Equivalently:
373
       *  (bvashr s t) abbreviates
374
       *      (ite (bvult s 100000...)
375
       *           (bvlshr s t)
376
       *           (bvnot (bvlshr (bvnot s) t)))
377
       *
378
       */
379
      // signed_min is 100000...
380
      uint64_t bvsize = original[0].getType().getBitVectorSize();
381
      Node signed_min = pow2(bvsize - 1);
382
      Node condition =
383
          d_nm->mkNode(kind::LT, translated_children[0], signed_min);
384
      Node thenNode = createShiftNode(translated_children, bvsize, false);
385
      std::vector<Node> children = {
386
          createBVNotNode(translated_children[0], bvsize),
387
          translated_children[1]};
388
      Node elseNode =
389
          createBVNotNode(createShiftNode(children, bvsize, false), bvsize);
390
      returnNode = d_nm->mkNode(kind::ITE, condition, thenNode, elseNode);
391
      break;
392
    }
393
2
    case kind::BITVECTOR_ITE:
394
    {
395
      // Lifted to a boolean ite.
396
4
      Node cond = d_nm->mkNode(kind::EQUAL, translated_children[0], d_one);
397
6
      returnNode = d_nm->mkNode(
398
4
          kind::ITE, cond, translated_children[1], translated_children[2]);
399
2
      break;
400
    }
401
2
    case kind::BITVECTOR_ZERO_EXTEND:
402
    {
403
      // zero extension does not change the integer translation.
404
2
      returnNode = translated_children[0];
405
2
      break;
406
    }
407
    case kind::BITVECTOR_SIGN_EXTEND:
408
    {
409
      uint64_t bvsize = original[0].getType().getBitVectorSize();
410
      returnNode =
411
          createSignExtendNode(translated_children[0],
412
                               bvsize,
413
                               bv::utils::getSignExtendAmount(original));
414
      break;
415
    }
416
2
    case kind::BITVECTOR_CONCAT:
417
    {
418
      // (concat a b) translates to a*2^k+b, k being the bitwidth of b.
419
2
      uint64_t bvsizeRight = original[1].getType().getBitVectorSize();
420
4
      Node pow2BvSizeRight = pow2(bvsizeRight);
421
      Node a =
422
4
          d_nm->mkNode(kind::MULT, translated_children[0], pow2BvSizeRight);
423
4
      Node b = translated_children[1];
424
2
      returnNode = d_nm->mkNode(kind::PLUS, a, b);
425
2
      break;
426
    }
427
2
    case kind::BITVECTOR_EXTRACT:
428
    {
429
      // ((_ extract i j) a) is a / 2^j mod 2^{i-j+1}
430
      // original = a[i:j]
431
2
      uint64_t i = bv::utils::getExtractHigh(original);
432
2
      uint64_t j = bv::utils::getExtractLow(original);
433
2
      Assert(i >= j);
434
2
      Node div = d_nm->mkNode(
435
4
          kind::INTS_DIVISION_TOTAL, translated_children[0], pow2(j));
436
2
      returnNode = modpow2(div, i - j + 1);
437
2
      break;
438
    }
439
2
    case kind::EQUAL:
440
    {
441
2
      returnNode = d_nm->mkNode(kind::EQUAL, translated_children);
442
2
      break;
443
    }
444
2
    case kind::BITVECTOR_ULT:
445
    {
446
2
      returnNode = d_nm->mkNode(kind::LT, translated_children);
447
2
      break;
448
    }
449
    case kind::BITVECTOR_SLT:
450
    {
451
      uint64_t bvsize = original[0].getType().getBitVectorSize();
452
      returnNode = d_nm->mkNode(kind::LT,
453
                                uts(translated_children[0], bvsize),
454
                                uts(translated_children[1], bvsize));
455
      break;
456
    }
457
2
    case kind::BITVECTOR_ULE:
458
    {
459
2
      returnNode = d_nm->mkNode(kind::LEQ, translated_children);
460
2
      break;
461
    }
462
2
    case kind::BITVECTOR_UGT:
463
    {
464
2
      returnNode = d_nm->mkNode(kind::GT, translated_children);
465
2
      break;
466
    }
467
2
    case kind::BITVECTOR_UGE:
468
    {
469
2
      returnNode = d_nm->mkNode(kind::GEQ, translated_children);
470
2
      break;
471
    }
472
2
    case kind::BITVECTOR_ULTBV:
473
    {
474
6
      returnNode = d_nm->mkNode(kind::ITE,
475
4
                                d_nm->mkNode(kind::LT, translated_children),
476
                                d_one,
477
                                d_zero);
478
2
      break;
479
    }
480
    case kind::BITVECTOR_SLTBV:
481
    {
482
      uint64_t bvsize = original[0].getType().getBitVectorSize();
483
      returnNode =
484
          d_nm->mkNode(kind::ITE,
485
                       d_nm->mkNode(kind::LT,
486
                                    uts(translated_children[0], bvsize),
487
                                    uts(translated_children[1], bvsize)),
488
                       d_one,
489
                       d_zero);
490
      break;
491
    }
492
    case kind::ITE:
493
    {
494
      returnNode = d_nm->mkNode(oldKind, translated_children);
495
      break;
496
    }
497
2
    case kind::APPLY_UF:
498
    {
499
      /**
500
       * higher order logic allows comparing between functions
501
       * The translation does not support this,
502
       * as the translated functions may be different outside
503
       * of the bounds that were relevant for the original
504
       * bit-vectors.
505
       */
506
2
      if (childrenTypesChanged(original) && logicInfo().isHigherOrder())
507
      {
508
        throw OptionException("bv-to-int does not support higher order logic ");
509
      }
510
      // Insert the translated application term to the cache
511
2
      returnNode = d_nm->mkNode(kind::APPLY_UF, translated_children);
512
      // Add range constraints if necessary.
513
      // If the original range was a BV sort, the original application of
514
      // the function must be within the range determined by the
515
      // bitwidth.
516
2
      if (original.getType().isBitVector())
517
      {
518
2
        addRangeConstraint(
519
4
            returnNode, original.getType().getBitVectorSize(), lemmas);
520
      }
521
2
      break;
522
    }
523
    case kind::BOUND_VAR_LIST:
524
    {
525
      returnNode = d_nm->mkNode(oldKind, translated_children);
526
      break;
527
    }
528
    case kind::FORALL:
529
    {
530
      returnNode = translateQuantifiedFormula(original);
531
      break;
532
    }
533
    default:
534
    {
535
      // first, verify that we haven't missed
536
      // any bv operator
537
      Assert(theory::kindToTheoryId(oldKind) != THEORY_BV);
538
539
      // In the default case, we have reached an operator that we do not
540
      // translate directly to integers. The children whose types have
541
      // changed from bv to int should be adjusted back to bv and then
542
      // this term is reconstructed.
543
      TypeNode resultingType;
544
      if (original.getType().isBitVector())
545
      {
546
        resultingType = d_nm->integerType();
547
      }
548
      else
549
      {
550
        resultingType = original.getType();
551
      }
552
      Node reconstruction =
553
          reconstructNode(original, resultingType, translated_children);
554
      returnNode = reconstruction;
555
      break;
556
    }
557
  }
558
38
  Trace("int-blaster-debug") << "original: " << original << std::endl;
559
38
  Trace("int-blaster-debug") << "returnNode: " << returnNode << std::endl;
560
38
  return returnNode;
561
}
562
563
Node IntBlaster::createSignExtendNode(Node x, uint64_t bvsize, uint64_t amount)
564
{
565
  return Node();
566
}
567
568
16
Node IntBlaster::translateNoChildren(Node original,
569
                                     std::vector<Node>& lemmas,
570
                                     std::map<Node, Node>& skolems)
571
{
572
32
  Trace("int-blaster-debug")
573
32
      << "translating leaf: " << original << "; of type: " << original.getType()
574
16
      << std::endl;
575
576
  // The result of the translation
577
16
  Node translation;
578
579
  // The translation is done differently for variables (bound or free)  and
580
  // constants (values)
581
16
  Assert(original.isVar() || original.isConst());
582
16
  if (original.isVar())
583
  {
584
12
    if (original.getType().isBitVector())
585
    {
586
      // For bit-vector variables, we create fresh integer variables.
587
6
      if (original.getKind() == kind::BOUND_VARIABLE)
588
      {
589
        // Range constraints for the bound integer variables are not added now.
590
        // they will be added once the quantifier itself is handled.
591
        std::stringstream ss;
592
        ss << original;
593
        translation = d_nm->mkBoundVar(ss.str() + "_int", d_nm->integerType());
594
      }
595
      else
596
      {
597
        // original is a bit-vector variable (symbolic constant).
598
        // Either we translate it to a fresh integer variable,
599
        // or we translate it to (bv2nat original).
600
        // In the former case, we must include range lemmas, while in the
601
        // latter we don't.
602
        // This is determined by the option bv-to-int-fresh-vars.
603
        // The variables intCast and bvCast are used for models:
604
        // even if we introduce a fresh variable,
605
        // it is associated with intCast (which is (bv2nat original)).
606
        // bvCast is either ( (_ nat2bv k) original) or just original.
607
12
        Node intCast = castToType(original, d_nm->integerType());
608
12
        Node bvCast;
609
6
        if (d_introduceFreshIntVars)
610
        {
611
          // we introduce a fresh variable, add range constraints, and save the
612
          // connection between original and the new variable via intCast
613
12
          translation = d_nm->getSkolemManager()->mkPurifySkolem(
614
              intCast,
615
              "__intblast__var",
616
12
              "Variable introduced in intblasting for " + original.toString());
617
6
          uint64_t bvsize = original.getType().getBitVectorSize();
618
6
          addRangeConstraint(translation, bvsize, lemmas);
619
          // put new definition of old variable in skolems
620
6
          bvCast = castToType(translation, original.getType());
621
        }
622
        else
623
        {
624
          // we just translate original to (bv2nat original)
625
          translation = intCast;
626
          // no need to do any casting back to bit-vector in this case.
627
          bvCast = original;
628
        }
629
630
        // add bvCast to skolems if it is not already there.
631
6
        if (skolems.find(original) == skolems.end())
632
        {
633
6
          skolems[original] = bvCast;
634
        }
635
        else
636
        {
637
          Assert(skolems[original] == bvCast);
638
        }
639
      }
640
    }
641
6
    else if (original.getType().isFunction())
642
    {
643
      // translate function symbol
644
4
      translation = translateFunctionSymbol(original, skolems);
645
    }
646
    else
647
    {
648
      // leave other variables intact
649
2
      translation = original;
650
    }
651
  }
652
  else
653
  {
654
    // original is a constant (value)
655
4
    if (original.getKind() == kind::CONST_BITVECTOR)
656
    {
657
      // Bit-vector constants are transformed into their integer value.
658
4
      BitVector constant(original.getConst<BitVector>());
659
4
      Integer c = constant.toInteger();
660
2
      translation = d_nm->mkConst<Rational>(c);
661
    }
662
    else
663
    {
664
      // Other constants stay the same.
665
2
      translation = original;
666
    }
667
  }
668
16
  return translation;
669
}
670
671
4
Node IntBlaster::translateFunctionSymbol(Node bvUF,
672
                                         std::map<Node, Node>& skolems)
673
{
674
  // construct the new function symbol.
675
4
  Node intUF;
676
677
  // old and new types of domain and result
678
8
  TypeNode tn = bvUF.getType();
679
8
  TypeNode bvRange = tn.getRangeType();
680
8
  std::vector<TypeNode> bvDomain = tn.getArgTypes();
681
8
  std::vector<TypeNode> intDomain;
682
683
  // if the original range is a bit-vector sort,
684
  // the new range should be an integer sort.
685
  // Otherwise, we keep the original range.
686
  // Similarly for the domain sorts.
687
8
  TypeNode intRange = bvRange.isBitVector() ? d_nm->integerType() : bvRange;
688
10
  for (const TypeNode& d : bvDomain)
689
  {
690
6
    intDomain.push_back(d.isBitVector() ? d_nm->integerType() : d);
691
  }
692
693
  // create the new function symbol as a skolem
694
8
  std::ostringstream os;
695
4
  os << "__intblast_fun_" << bvUF << "_int";
696
4
  SkolemManager* sm = d_nm->getSkolemManager();
697
12
  intUF = sm->mkDummySkolem(
698
8
      os.str(), d_nm->mkFunctionType(intDomain, intRange), "bv2int function");
699
700
  // add definition of old function symbol to skolems.
701
702
  // formal arguments of the lambda expression.
703
8
  std::vector<Node> args;
704
705
  // arguments to be passed in the application.
706
8
  std::vector<Node> achildren;
707
4
  achildren.push_back(intUF);
708
709
  // iterate the arguments, cast BV arguments to integers
710
4
  int i = 0;
711
10
  for (const TypeNode& d : bvDomain)
712
  {
713
    // Each bit-vector argument is casted to a natural number
714
    // Other arguments are left intact.
715
12
    Node fresh_bound_var = d_nm->mkBoundVar(d);
716
6
    args.push_back(fresh_bound_var);
717
12
    Node castedArg = args[i];
718
6
    if (d.isBitVector())
719
    {
720
4
      castedArg = castToType(castedArg, d_nm->integerType());
721
    }
722
6
    achildren.push_back(castedArg);
723
6
    i++;
724
  }
725
726
  // create the lambda expression, and add it to skolems
727
8
  Node app = d_nm->mkNode(kind::APPLY_UF, achildren);
728
8
  Node body = castToType(app, bvRange);
729
8
  Node bvlist = d_nm->mkNode(kind::BOUND_VAR_LIST, args);
730
8
  Node result = d_nm->mkNode(kind::LAMBDA, bvlist, body);
731
4
  if (skolems.find(bvUF) == skolems.end())
732
  {
733
4
    skolems[bvUF] = result;
734
  }
735
8
  return intUF;
736
}
737
738
2
bool IntBlaster::childrenTypesChanged(Node n) { return true; }
739
740
20
Node IntBlaster::castToType(Node n, TypeNode tn)
741
{
742
  // If there is no reason to cast, return the
743
  // original node.
744
20
  if (n.getType().isSubtypeOf(tn))
745
  {
746
2
    return n;
747
  }
748
  // We only case int to bv or vice verse.
749
18
  Assert((n.getType().isBitVector() && tn.isInteger())
750
         || (n.getType().isInteger() && tn.isBitVector()));
751
36
  Trace("int-blaster") << "castToType from " << n.getType() << " to " << tn
752
18
                       << std::endl;
753
754
  // casting integers to bit-vectors
755
18
  if (n.getType().isInteger())
756
  {
757
8
    Assert(tn.isBitVector());
758
8
    unsigned bvsize = tn.getBitVectorSize();
759
16
    Node intToBVOp = d_nm->mkConst<IntToBitVector>(IntToBitVector(bvsize));
760
8
    return d_nm->mkNode(intToBVOp, n);
761
  }
762
763
  // casting bit-vectors to ingers
764
10
  Assert(n.getType().isBitVector());
765
10
  Assert(tn.isInteger());
766
10
  return d_nm->mkNode(kind::BITVECTOR_TO_NAT, n);
767
}
768
769
Node IntBlaster::reconstructNode(Node originalNode,
770
                                 TypeNode resultType,
771
                                 const std::vector<Node>& translated_children)
772
{
773
  return Node();
774
}
775
776
Node IntBlaster::createShiftNode(std::vector<Node> children,
777
                                 uint64_t bvsize,
778
                                 bool isLeftShift)
779
{
780
  return Node();
781
}
782
783
Node IntBlaster::translateQuantifiedFormula(Node quantifiedNode)
784
{
785
  return Node();
786
}
787
788
Node IntBlaster::createBVAndNode(Node x,
789
                                 Node y,
790
                                 uint64_t bvsize,
791
                                 std::vector<Node>& lemmas)
792
{
793
  return Node();
794
}
795
796
Node IntBlaster::createBVOrNode(Node x,
797
                                Node y,
798
                                uint64_t bvsize,
799
                                std::vector<Node>& lemmas)
800
{
801
  // Based on Hacker's Delight section 2-2 equation h:
802
  // x+y = x|y + x&y
803
  // from which we deduce:
804
  // x|y = x+y - x&y
805
  Node plus = createBVAddNode(x, y, bvsize);
806
  Node bvand = createBVAndNode(x, y, bvsize, lemmas);
807
  return createBVSubNode(plus, bvand, bvsize);
808
}
809
810
Node IntBlaster::createBVSubNode(Node x, Node y, uint64_t bvsize)
811
{
812
  Node minus = d_nm->mkNode(kind::MINUS, x, y);
813
  Node p2 = pow2(bvsize);
814
  return d_nm->mkNode(kind::INTS_MODULUS_TOTAL, minus, p2);
815
}
816
817
2
Node IntBlaster::createBVAddNode(Node x, Node y, uint64_t bvsize)
818
{
819
4
  Node plus = d_nm->mkNode(kind::PLUS, x, y);
820
4
  Node p2 = pow2(bvsize);
821
4
  return d_nm->mkNode(kind::INTS_MODULUS_TOTAL, plus, p2);
822
}
823
824
2
Node IntBlaster::createBVNegNode(Node n, uint64_t bvsize)
825
{
826
  // Based on Hacker's Delight section 2-2 equation a:
827
  // -x = ~x+1
828
4
  Node p2 = pow2(bvsize);
829
4
  return d_nm->mkNode(kind::MINUS, p2, n);
830
}
831
832
2
Node IntBlaster::createBVNotNode(Node n, uint64_t bvsize)
833
{
834
2
  return d_nm->mkNode(kind::MINUS, maxInt(bvsize), n);
835
}
836
837
31137
}  // namespace cvc5