klee
Expr.cpp
Go to the documentation of this file.
1//===-- Expr.cpp ----------------------------------------------------------===//
2//
3// The KLEE Symbolic Virtual Machine
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "klee/Expr/Expr.h"
11
12#include "klee/Config/Version.h"
15// FIXME: We shouldn't need this once fast constant support moves into
16// Core. If we need to do arithmetic, we probably want to use APInt.
18
19#include "llvm/ADT/Hashing.h"
20#if LLVM_VERSION_CODE >= LLVM_VERSION(13, 0)
21#include "llvm/ADT/StringExtras.h"
22#endif
23#include "llvm/Support/CommandLine.h"
24#include "llvm/Support/raw_ostream.h"
25
26#include <sstream>
27
28using namespace klee;
29using namespace llvm;
30
31namespace klee {
32llvm::cl::OptionCategory
33 ExprCat("Expression building and printing options",
34 "These options impact the way expressions are build and printed.");
35}
36
37namespace {
38cl::opt<bool> ConstArrayOpt(
39 "const-array-opt", cl::init(false),
40 cl::desc(
41 "Enable an optimization involving all-constant arrays (default=false)"),
42 cl::cat(klee::ExprCat));
43}
44
45/***/
46
47unsigned Expr::count = 0;
48
49ref<Expr> Expr::createTempRead(const Array *array, Expr::Width w) {
50 UpdateList ul(array, 0);
51
52 switch (w) {
53 default: assert(0 && "invalid width");
54 case Expr::Bool:
55 return ZExtExpr::create(ReadExpr::create(ul,
58 case Expr::Int8:
59 return ReadExpr::create(ul,
61 case Expr::Int16:
66 case Expr::Int32:
75 case Expr::Int64:
92 }
93}
94
95int Expr::compare(const Expr &b) const {
96 static ExprEquivSet equivs;
97 int r = compare(b, equivs);
98 equivs.clear();
99 return r;
100}
101
102// returns 0 if b is structurally equal to *this
103int Expr::compare(const Expr &b, ExprEquivSet &equivs) const {
104 if (this == &b) return 0;
105
106 const Expr *ap, *bp;
107 if (this < &b) {
108 ap = this; bp = &b;
109 } else {
110 ap = &b; bp = this;
111 }
112
113 if (equivs.count(std::make_pair(ap, bp)))
114 return 0;
115
116 Kind ak = getKind(), bk = b.getKind();
117 if (ak!=bk)
118 return (ak < bk) ? -1 : 1;
119
120 if (hashValue != b.hashValue)
121 return (hashValue < b.hashValue) ? -1 : 1;
122
123 if (int res = compareContents(b))
124 return res;
125
126 unsigned aN = getNumKids();
127 for (unsigned i=0; i<aN; i++)
128 if (int res = getKid(i)->compare(*b.getKid(i), equivs))
129 return res;
130
131 equivs.insert(std::make_pair(ap, bp));
132 return 0;
133}
134
135void Expr::printKind(llvm::raw_ostream &os, Kind k) {
136 switch(k) {
137#define X(C) case C: os << #C; break
138 X(Constant);
140 X(Read);
141 X(Select);
142 X(Concat);
143 X(Extract);
144 X(ZExt);
145 X(SExt);
146 X(Add);
147 X(Sub);
148 X(Mul);
149 X(UDiv);
150 X(SDiv);
151 X(URem);
152 X(SRem);
153 X(Not);
154 X(And);
155 X(Or);
156 X(Xor);
157 X(Shl);
158 X(LShr);
159 X(AShr);
160 X(Eq);
161 X(Ne);
162 X(Ult);
163 X(Ule);
164 X(Ugt);
165 X(Uge);
166 X(Slt);
167 X(Sle);
168 X(Sgt);
169 X(Sge);
170#undef X
171 default:
172 assert(0 && "invalid kind");
173 }
174}
175
177//
178// Simple hash functions for various kinds of Exprs
179//
181
183 unsigned res = getKind() * Expr::MAGIC_HASH_CONSTANT;
184
185 int n = getNumKids();
186 for (int i = 0; i < n; i++) {
187 res <<= 1;
189 }
190
191 hashValue = res;
192 return hashValue;
193}
194
196 Expr::Width w = getWidth();
197 if (w <= 64)
198 hashValue = value.getLimitedValue() ^ (w * MAGIC_HASH_CONSTANT);
199 else
200 hashValue = hash_value(value) ^ (w * MAGIC_HASH_CONSTANT);
201
202 return hashValue;
203}
204
206 unsigned res = getWidth() * Expr::MAGIC_HASH_CONSTANT;
208 return hashValue;
209}
210
212 unsigned res = offset * Expr::MAGIC_HASH_CONSTANT;
215 return hashValue;
216}
217
219 unsigned res = index->hash() * Expr::MAGIC_HASH_CONSTANT;
220 res ^= updates.hash();
221 hashValue = res;
222 return hashValue;
223}
224
227 return hashValue;
228}
229
230ref<Expr> Expr::createFromKind(Kind k, std::vector<CreateArg> args) {
231 unsigned numArgs = args.size();
232 (void) numArgs;
233
234 switch(k) {
235 case Constant:
236 case Extract:
237 case Read:
238 default:
239 assert(0 && "invalid kind");
240
241 case NotOptimized:
242 assert(numArgs == 1 && args[0].isExpr() &&
243 "invalid args array for given opcode");
244 return NotOptimizedExpr::create(args[0].expr);
245
246 case Select:
247 assert(numArgs == 3 && args[0].isExpr() &&
248 args[1].isExpr() && args[2].isExpr() &&
249 "invalid args array for Select opcode");
250 return SelectExpr::create(args[0].expr,
251 args[1].expr,
252 args[2].expr);
253
254 case Concat: {
255 assert(numArgs == 2 && args[0].isExpr() && args[1].isExpr() &&
256 "invalid args array for Concat opcode");
257
258 return ConcatExpr::create(args[0].expr, args[1].expr);
259 }
260
261#define CAST_EXPR_CASE(T) \
262 case T: \
263 assert(numArgs == 2 && \
264 args[0].isExpr() && args[1].isWidth() && \
265 "invalid args array for given opcode"); \
266 return T ## Expr::create(args[0].expr, args[1].width); \
267
268#define BINARY_EXPR_CASE(T) \
269 case T: \
270 assert(numArgs == 2 && \
271 args[0].isExpr() && args[1].isExpr() && \
272 "invalid args array for given opcode"); \
273 return T ## Expr::create(args[0].expr, args[1].expr); \
274
277
291
302 }
303}
304
305
306void Expr::printWidth(llvm::raw_ostream &os, Width width) {
307 switch(width) {
308 case Expr::Bool: os << "Expr::Bool"; break;
309 case Expr::Int8: os << "Expr::Int8"; break;
310 case Expr::Int16: os << "Expr::Int16"; break;
311 case Expr::Int32: os << "Expr::Int32"; break;
312 case Expr::Int64: os << "Expr::Int64"; break;
313 case Expr::Fl80: os << "Expr::Fl80"; break;
314 default: os << "<invalid type: " << (unsigned) width << ">";
315 }
316}
317
319 return OrExpr::create(Expr::createIsZero(hyp), conc);
320}
321
323 return EqExpr::create(e, ConstantExpr::create(0, e->getWidth()));
324}
325
326void Expr::print(llvm::raw_ostream &os) const {
327 ExprPPrinter::printSingleExpr(os, const_cast<Expr*>(this));
328}
329
330void Expr::dump() const {
331 this->print(errs());
332 errs() << "\n";
333}
334
335/***/
336
338 switch (width) {
339 case Expr::Bool: return ConstantExpr::create(*(( uint8_t*) address), width);
340 case Expr::Int8: return ConstantExpr::create(*(( uint8_t*) address), width);
341 case Expr::Int16: return ConstantExpr::create(*((uint16_t*) address), width);
342 case Expr::Int32: return ConstantExpr::create(*((uint32_t*) address), width);
343 case Expr::Int64: return ConstantExpr::create(*((uint64_t*) address), width);
344 // FIXME: what about machines without x87 support?
345 default:
346 return ConstantExpr::alloc(
347 llvm::APInt(width,
348 (width + llvm::APFloatBase::integerPartWidth - 1) /
349 llvm::APFloatBase::integerPartWidth,
350 (const uint64_t *)address));
351 }
352}
353
354void ConstantExpr::toMemory(void *address) {
355 switch (getWidth()) {
356 default: assert(0 && "invalid type");
357 case Expr::Bool: *(( uint8_t*) address) = getZExtValue(1); break;
358 case Expr::Int8: *(( uint8_t*) address) = getZExtValue(8); break;
359 case Expr::Int16: *((uint16_t*) address) = getZExtValue(16); break;
360 case Expr::Int32: *((uint32_t*) address) = getZExtValue(32); break;
361 case Expr::Int64: *((uint64_t*) address) = getZExtValue(64); break;
362 // FIXME: what about machines without x87 support?
363 case Expr::Fl80:
364 *((long double*) address) = *(const long double*) value.getRawData();
365 break;
366 }
367}
368
369void ConstantExpr::toString(std::string &Res, unsigned radix) const {
370#if LLVM_VERSION_CODE >= LLVM_VERSION(13, 0)
371 Res = llvm::toString(value, radix, false);
372#else
373 Res = value.toString(radix, false);
374#endif
375}
376
378 Expr::Width W = getWidth() + RHS->getWidth();
379 APInt Tmp(value);
380 Tmp=Tmp.zext(W);
381 Tmp <<= RHS->getWidth();
382 Tmp |= APInt(RHS->value).zext(W);
383
384 return ConstantExpr::alloc(Tmp);
385}
386
388 return ConstantExpr::alloc(APInt(value.ashr(Offset)).zextOrTrunc(W));
389}
390
392 return ConstantExpr::alloc(APInt(value).zextOrTrunc(W));
393}
394
396 return ConstantExpr::alloc(APInt(value).sextOrTrunc(W));
397}
398
400 return ConstantExpr::alloc(value + RHS->value);
401}
402
404 return ConstantExpr::alloc(-value);
405}
406
408 return ConstantExpr::alloc(value - RHS->value);
409}
410
412 return ConstantExpr::alloc(value * RHS->value);
413}
414
416 return ConstantExpr::alloc(value.udiv(RHS->value));
417}
418
420 return ConstantExpr::alloc(value.sdiv(RHS->value));
421}
422
424 return ConstantExpr::alloc(value.urem(RHS->value));
425}
426
428 return ConstantExpr::alloc(value.srem(RHS->value));
429}
430
432 return ConstantExpr::alloc(value & RHS->value);
433}
434
436 return ConstantExpr::alloc(value | RHS->value);
437}
438
440 return ConstantExpr::alloc(value ^ RHS->value);
441}
442
444 return ConstantExpr::alloc(value.shl(RHS->value));
445}
446
448 return ConstantExpr::alloc(value.lshr(RHS->value));
449}
450
452 return ConstantExpr::alloc(value.ashr(RHS->value));
453}
454
456 return ConstantExpr::alloc(~value);
457}
458
460 return ConstantExpr::alloc(value == RHS->value, Expr::Bool);
461}
462
464 return ConstantExpr::alloc(value != RHS->value, Expr::Bool);
465}
466
468 return ConstantExpr::alloc(value.ult(RHS->value), Expr::Bool);
469}
470
472 return ConstantExpr::alloc(value.ule(RHS->value), Expr::Bool);
473}
474
476 return ConstantExpr::alloc(value.ugt(RHS->value), Expr::Bool);
477}
478
480 return ConstantExpr::alloc(value.uge(RHS->value), Expr::Bool);
481}
482
484 return ConstantExpr::alloc(value.slt(RHS->value), Expr::Bool);
485}
486
488 return ConstantExpr::alloc(value.sle(RHS->value), Expr::Bool);
489}
490
492 return ConstantExpr::alloc(value.sgt(RHS->value), Expr::Bool);
493}
494
496 return ConstantExpr::alloc(value.sge(RHS->value), Expr::Bool);
497}
498
499/***/
500
503}
504
505/***/
506
507Array::Array(const std::string &_name, uint64_t _size,
508 const ref<ConstantExpr> *constantValuesBegin,
509 const ref<ConstantExpr> *constantValuesEnd, Expr::Width _domain,
510 Expr::Width _range)
511 : name(_name), size(_size), domain(_domain), range(_range),
512 constantValues(constantValuesBegin, constantValuesEnd) {
513
514 assert((isSymbolicArray() || constantValues.size() == size) &&
515 "Invalid size for constant array!");
516 computeHash();
517#ifndef NDEBUG
518 for (const ref<ConstantExpr> *it = constantValuesBegin;
519 it != constantValuesEnd; ++it)
520 assert((*it)->getWidth() == getRange() &&
521 "Invalid initial constant value!");
522#endif // NDEBUG
523}
524
526}
527
529 unsigned res = 0;
530 for (unsigned i = 0, e = name.size(); i != e; ++i)
531 res = (res * Expr::MAGIC_HASH_CONSTANT) + name[i];
532 res = (res * Expr::MAGIC_HASH_CONSTANT) + size;
533 hashValue = res;
534 return hashValue;
535}
536/***/
537
539 // rollback update nodes if possible
540
541 // Iterate through the update list from the most recent to the
542 // least recent to find a potential written value for a concrete index;
543 // stop if an update with symbolic has been found as we don't know which
544 // array element has been updated
545 auto un = ul.head.get();
546 bool updateListHasSymbolicWrites = false;
547 for (; un; un = un->next.get()) {
548 ref<Expr> cond = EqExpr::create(index, un->index);
549 if (ConstantExpr *CE = dyn_cast<ConstantExpr>(cond)) {
550 if (CE->isTrue())
551 // Return the found value
552 return un->value;
553 } else {
554 // Found write with symbolic index
555 updateListHasSymbolicWrites = true;
556 break;
557 }
558 }
559
560 if (ul.root->isConstantArray() && !updateListHasSymbolicWrites) {
561 // No updates with symbolic index to a constant array have been found
562 if (ConstantExpr *CE = dyn_cast<ConstantExpr>(index)) {
563 assert(CE->getWidth() <= 64 && "Index too large");
564 uint64_t concreteIndex = CE->getZExtValue();
565 uint64_t size = ul.root->size;
566 if (concreteIndex < size) {
567 return ul.root->constantValues[concreteIndex];
568 }
569 }
570 }
571
572 // Now, no update with this concrete index exists
573 // Try to remove any most recent but unimportant updates
574 if (ConstantExpr *CE = dyn_cast<ConstantExpr>(index)) {
575 assert(CE->getWidth() <= 64 && "Index too large");
576 uint64_t concreteIndex = CE->getZExtValue();
577 uint64_t size = ul.root->size;
578 if (concreteIndex < size) {
579 // Create shortened update list
580 UpdateList newUpdateList(ul.root, un);
581 return ReadExpr::alloc(newUpdateList, index);
582 }
583 }
584
585 return ReadExpr::alloc(ul, index);
586}
587
588int ReadExpr::compareContents(const Expr &b) const {
589 return updates.compare(static_cast<const ReadExpr&>(b).updates);
590}
591
593 Expr::Width kt = t->getWidth();
594
595 assert(c->getWidth()==Bool && "type mismatch");
596 assert(kt==f->getWidth() && "type mismatch");
597
598 if (ConstantExpr *CE = dyn_cast<ConstantExpr>(c)) {
599 return CE->isTrue() ? t : f;
600 } else if (t==f) {
601 return t;
602 } else if (kt==Expr::Bool) { // c ? t : f <=> (c and t) or (not c and f)
603 if (ConstantExpr *CE = dyn_cast<ConstantExpr>(t)) {
604 if (CE->isTrue()) {
605 return OrExpr::create(c, f);
606 } else {
607 return AndExpr::create(Expr::createIsZero(c), f);
608 }
609 } else if (ConstantExpr *CE = dyn_cast<ConstantExpr>(f)) {
610 if (CE->isTrue()) {
611 return OrExpr::create(Expr::createIsZero(c), t);
612 } else {
613 return AndExpr::create(c, t);
614 }
615 }
616 }
617
618 return SelectExpr::alloc(c, t, f);
619}
620
621/***/
622
624 Expr::Width w = l->getWidth() + r->getWidth();
625
626 // Fold concatenation of constants.
627 //
628 // FIXME: concat 0 x -> zext x ?
629 if (ConstantExpr *lCE = dyn_cast<ConstantExpr>(l))
630 if (ConstantExpr *rCE = dyn_cast<ConstantExpr>(r))
631 return lCE->Concat(rCE);
632
633 // Merge contiguous Extracts
634 if (ExtractExpr *ee_left = dyn_cast<ExtractExpr>(l)) {
635 if (ExtractExpr *ee_right = dyn_cast<ExtractExpr>(r)) {
636 if (ee_left->expr == ee_right->expr &&
637 ee_right->offset + ee_right->width == ee_left->offset) {
638 return ExtractExpr::create(ee_left->expr, ee_right->offset, w);
639 }
640 }
641 }
642
643 return ConcatExpr::alloc(l, r);
644}
645
647ref<Expr> ConcatExpr::createN(unsigned n_kids, const ref<Expr> kids[]) {
648 assert(n_kids > 0);
649 if (n_kids == 1)
650 return kids[0];
651
652 ref<Expr> r = ConcatExpr::create(kids[n_kids-2], kids[n_kids-1]);
653 for (int i=n_kids-3; i>=0; i--)
654 r = ConcatExpr::create(kids[i], r);
655 return r;
656}
657
660 const ref<Expr> &kid3, const ref<Expr> &kid4) {
661 return ConcatExpr::create(kid1, ConcatExpr::create(kid2, ConcatExpr::create(kid3, kid4)));
662}
663
666 const ref<Expr> &kid3, const ref<Expr> &kid4,
667 const ref<Expr> &kid5, const ref<Expr> &kid6,
668 const ref<Expr> &kid7, const ref<Expr> &kid8) {
670 ConcatExpr::create(kid4, ConcatExpr::create4(kid5, kid6, kid7, kid8)))));
671}
672
673/***/
674
676 unsigned kw = expr->getWidth();
677 assert(w > 0 && off + w <= kw && "invalid extract");
678
679 if (w == kw) {
680 return expr;
681 } else if (ConstantExpr *CE = dyn_cast<ConstantExpr>(expr)) {
682 return CE->Extract(off, w);
683 } else {
684 // Extract(Concat)
685 if (ConcatExpr *ce = dyn_cast<ConcatExpr>(expr)) {
686 // if the extract skips the right side of the concat
687 if (off >= ce->getRight()->getWidth())
688 return ExtractExpr::create(ce->getLeft(), off - ce->getRight()->getWidth(), w);
689
690 // if the extract skips the left side of the concat
691 if (off + w <= ce->getRight()->getWidth())
692 return ExtractExpr::create(ce->getRight(), off, w);
693
694 // E(C(x,y)) = C(E(x), E(y))
695 return ConcatExpr::create(ExtractExpr::create(ce->getKid(0), 0, w - ce->getKid(1)->getWidth() + off),
696 ExtractExpr::create(ce->getKid(1), off, ce->getKid(1)->getWidth() - off));
697 }
698 }
699
700 return ExtractExpr::alloc(expr, off, w);
701}
702
703/***/
704
706 if (ConstantExpr *CE = dyn_cast<ConstantExpr>(e))
707 return CE->Not();
708
709 return NotExpr::alloc(e);
710}
711
712
713/***/
714
715ref<Expr> ZExtExpr::create(const ref<Expr> &e, Width w) {
716 unsigned kBits = e->getWidth();
717 if (w == kBits) {
718 return e;
719 } else if (w < kBits) { // trunc
720 return ExtractExpr::create(e, 0, w);
721 } else if (ConstantExpr *CE = dyn_cast<ConstantExpr>(e)) {
722 return CE->ZExt(w);
723 } else {
724 return ZExtExpr::alloc(e, w);
725 }
726}
727
728ref<Expr> SExtExpr::create(const ref<Expr> &e, Width w) {
729 unsigned kBits = e->getWidth();
730 if (w == kBits) {
731 return e;
732 } else if (w < kBits) { // trunc
733 return ExtractExpr::create(e, 0, w);
734 } else if (ConstantExpr *CE = dyn_cast<ConstantExpr>(e)) {
735 return CE->SExt(w);
736 } else {
737 return SExtExpr::alloc(e, w);
738 }
739}
740
741/***/
742
743static ref<Expr> AndExpr_create(Expr *l, Expr *r);
744static ref<Expr> XorExpr_create(Expr *l, Expr *r);
745
750
752 Expr::Width type = cl->getWidth();
753
754 if (type==Expr::Bool) {
755 return XorExpr_createPartialR(cl, r);
756 } else if (cl->isZero()) {
757 return r;
758 } else {
759 Expr::Kind rk = r->getKind();
760 if (rk==Expr::Add && isa<ConstantExpr>(r->getKid(0))) { // A + (B+c) == (A+B) + c
761 return AddExpr::create(AddExpr::create(cl, r->getKid(0)),
762 r->getKid(1));
763 } else if (rk==Expr::Sub && isa<ConstantExpr>(r->getKid(0))) { // A + (B-c) == (A+B) - c
764 return SubExpr::create(AddExpr::create(cl, r->getKid(0)),
765 r->getKid(1));
766 } else {
767 return AddExpr::alloc(cl, r);
768 }
769 }
770}
772 return AddExpr_createPartialR(cr, l);
773}
775 Expr::Width type = l->getWidth();
776
777 if (type == Expr::Bool) {
778 return XorExpr_create(l, r);
779 } else {
780 Expr::Kind lk = l->getKind(), rk = r->getKind();
781 if (lk==Expr::Add && isa<ConstantExpr>(l->getKid(0))) { // (k+a)+b = k+(a+b)
782 return AddExpr::create(l->getKid(0),
783 AddExpr::create(l->getKid(1), r));
784 } else if (lk==Expr::Sub && isa<ConstantExpr>(l->getKid(0))) { // (k-a)+b = k+(b-a)
785 return AddExpr::create(l->getKid(0),
786 SubExpr::create(r, l->getKid(1)));
787 } else if (rk==Expr::Add && isa<ConstantExpr>(r->getKid(0))) { // a + (k+b) = k+(a+b)
788 return AddExpr::create(r->getKid(0),
789 AddExpr::create(l, r->getKid(1)));
790 } else if (rk==Expr::Sub && isa<ConstantExpr>(r->getKid(0))) { // a + (k-b) = k+(a-b)
791 return AddExpr::create(r->getKid(0),
792 SubExpr::create(l, r->getKid(1)));
793 } else {
794 return AddExpr::alloc(l, r);
795 }
796 }
797}
798
800 Expr::Width type = cl->getWidth();
801
802 if (type==Expr::Bool) {
803 return XorExpr_createPartialR(cl, r);
804 } else {
805 Expr::Kind rk = r->getKind();
806 if (rk==Expr::Add && isa<ConstantExpr>(r->getKid(0))) { // A - (B+c) == (A-B) - c
807 return SubExpr::create(SubExpr::create(cl, r->getKid(0)),
808 r->getKid(1));
809 } else if (rk==Expr::Sub && isa<ConstantExpr>(r->getKid(0))) { // A - (B-c) == (A-B) + c
810 return AddExpr::create(SubExpr::create(cl, r->getKid(0)),
811 r->getKid(1));
812 } else {
813 return SubExpr::alloc(cl, r);
814 }
815 }
816}
818 // l - c => l + (-c)
819 return AddExpr_createPartial(l,
820 ConstantExpr::alloc(0, cr->getWidth())->Sub(cr));
821}
823 Expr::Width type = l->getWidth();
824
825 if (type == Expr::Bool) {
826 return XorExpr_create(l, r);
827 } else if (*l==*r) {
828 return ConstantExpr::alloc(0, type);
829 } else {
830 Expr::Kind lk = l->getKind(), rk = r->getKind();
831 if (lk==Expr::Add && isa<ConstantExpr>(l->getKid(0))) { // (k+a)-b = k+(a-b)
832 return AddExpr::create(l->getKid(0),
833 SubExpr::create(l->getKid(1), r));
834 } else if (lk==Expr::Sub && isa<ConstantExpr>(l->getKid(0))) { // (k-a)-b = k-(a+b)
835 return SubExpr::create(l->getKid(0),
836 AddExpr::create(l->getKid(1), r));
837 } else if (rk==Expr::Add && isa<ConstantExpr>(r->getKid(0))) { // a - (k+b) = (a-c) - k
838 return SubExpr::create(SubExpr::create(l, r->getKid(1)),
839 r->getKid(0));
840 } else if (rk==Expr::Sub && isa<ConstantExpr>(r->getKid(0))) { // a - (k-b) = (a+b) - k
841 return SubExpr::create(AddExpr::create(l, r->getKid(1)),
842 r->getKid(0));
843 } else {
844 return SubExpr::alloc(l, r);
845 }
846 }
847}
848
850 Expr::Width type = cl->getWidth();
851
852 if (type == Expr::Bool) {
853 return AndExpr_createPartialR(cl, r);
854 } else if (cl->isOne()) {
855 return r;
856 } else if (cl->isZero()) {
857 return cl;
858 } else {
859 return MulExpr::alloc(cl, r);
860 }
861}
863 return MulExpr_createPartialR(cr, l);
864}
866 Expr::Width type = l->getWidth();
867
868 if (type == Expr::Bool) {
869 return AndExpr::alloc(l, r);
870 } else {
871 return MulExpr::alloc(l, r);
872 }
873}
874
876 if (cr->isAllOnes()) {
877 return l;
878 } else if (cr->isZero()) {
879 return cr;
880 } else {
881 return AndExpr::alloc(l, cr);
882 }
883}
885 return AndExpr_createPartial(r, cl);
886}
888 return AndExpr::alloc(l, r);
889}
890
892 if (cr->isAllOnes()) {
893 return cr;
894 } else if (cr->isZero()) {
895 return l;
896 } else {
897 return OrExpr::alloc(l, cr);
898 }
899}
901 return OrExpr_createPartial(r, cl);
902}
904 return OrExpr::alloc(l, r);
905}
906
908 if (cl->isZero()) {
909 return r;
910 } else if (cl->getWidth() == Expr::Bool) {
912 } else {
913 return XorExpr::alloc(cl, r);
914 }
915}
916
918 return XorExpr_createPartialR(cr, l);
919}
921 return XorExpr::alloc(l, r);
922}
923
924static ref<Expr> UDivExpr_create(const ref<Expr> &l, const ref<Expr> &r) {
925 if (l->getWidth() == Expr::Bool) { // r must be 1
926 return l;
927 } else{
928 return UDivExpr::alloc(l, r);
929 }
930}
931
932static ref<Expr> SDivExpr_create(const ref<Expr> &l, const ref<Expr> &r) {
933 if (l->getWidth() == Expr::Bool) { // r must be 1
934 return l;
935 } else{
936 return SDivExpr::alloc(l, r);
937 }
938}
939
940static ref<Expr> URemExpr_create(const ref<Expr> &l, const ref<Expr> &r) {
941 if (l->getWidth() == Expr::Bool) { // r must be 1
943 } else{
944 return URemExpr::alloc(l, r);
945 }
946}
947
948static ref<Expr> SRemExpr_create(const ref<Expr> &l, const ref<Expr> &r) {
949 if (l->getWidth() == Expr::Bool) { // r must be 1
951 } else{
952 return SRemExpr::alloc(l, r);
953 }
954}
955
956static ref<Expr> ShlExpr_create(const ref<Expr> &l, const ref<Expr> &r) {
957 if (l->getWidth() == Expr::Bool) { // l & !r
958 return AndExpr::create(l, Expr::createIsZero(r));
959 } else{
960 return ShlExpr::alloc(l, r);
961 }
962}
963
964static ref<Expr> LShrExpr_create(const ref<Expr> &l, const ref<Expr> &r) {
965 if (l->getWidth() == Expr::Bool) { // l & !r
966 return AndExpr::create(l, Expr::createIsZero(r));
967 } else{
968 return LShrExpr::alloc(l, r);
969 }
970}
971
972static ref<Expr> AShrExpr_create(const ref<Expr> &l, const ref<Expr> &r) {
973 if (l->getWidth() == Expr::Bool) { // l
974 return l;
975 } else{
976 return AShrExpr::alloc(l, r);
977 }
978}
979
980#define BCREATE_R(_e_op, _op, partialL, partialR) \
981ref<Expr> _e_op ::create(const ref<Expr> &l, const ref<Expr> &r) { \
982 assert(l->getWidth()==r->getWidth() && "type mismatch"); \
983 if (ConstantExpr *cl = dyn_cast<ConstantExpr>(l)) { \
984 if (ConstantExpr *cr = dyn_cast<ConstantExpr>(r)) \
985 return cl->_op(cr); \
986 return _e_op ## _createPartialR(cl, r.get()); \
987 } else if (ConstantExpr *cr = dyn_cast<ConstantExpr>(r)) { \
988 return _e_op ## _createPartial(l.get(), cr); \
989 } \
990 return _e_op ## _create(l.get(), r.get()); \
991}
992
993#define BCREATE(_e_op, _op) \
994ref<Expr> _e_op ::create(const ref<Expr> &l, const ref<Expr> &r) { \
995 assert(l->getWidth()==r->getWidth() && "type mismatch"); \
996 if (ConstantExpr *cl = dyn_cast<ConstantExpr>(l)) \
997 if (ConstantExpr *cr = dyn_cast<ConstantExpr>(r)) \
998 return cl->_op(cr); \
999 return _e_op ## _create(l, r); \
1000}
1001
1008BCREATE(UDivExpr, UDiv)
1009BCREATE(SDivExpr, SDiv)
1010BCREATE(URemExpr, URem)
1011BCREATE(SRemExpr, SRem)
1012BCREATE(ShlExpr, Shl)
1013BCREATE(LShrExpr, LShr)
1014BCREATE(AShrExpr, AShr)
1015
1016#define CMPCREATE(_e_op, _op) \
1017ref<Expr> _e_op ::create(const ref<Expr> &l, const ref<Expr> &r) { \
1018 assert(l->getWidth()==r->getWidth() && "type mismatch"); \
1019 if (ConstantExpr *cl = dyn_cast<ConstantExpr>(l)) \
1020 if (ConstantExpr *cr = dyn_cast<ConstantExpr>(r)) \
1021 return cl->_op(cr); \
1022 return _e_op ## _create(l, r); \
1023}
1024
1025#define CMPCREATE_T(_e_op, _op, _reflexive_e_op, partialL, partialR) \
1026ref<Expr> _e_op ::create(const ref<Expr> &l, const ref<Expr> &r) { \
1027 assert(l->getWidth()==r->getWidth() && "type mismatch"); \
1028 if (ConstantExpr *cl = dyn_cast<ConstantExpr>(l)) { \
1029 if (ConstantExpr *cr = dyn_cast<ConstantExpr>(r)) \
1030 return cl->_op(cr); \
1031 return partialR(cl, r.get()); \
1032 } else if (ConstantExpr *cr = dyn_cast<ConstantExpr>(r)) { \
1033 return partialL(l.get(), cr); \
1034 } else { \
1035 return _e_op ## _create(l.get(), r.get()); \
1036 } \
1037}
1038
1039
1040static ref<Expr> EqExpr_create(const ref<Expr> &l, const ref<Expr> &r) {
1041 if (l == r) {
1043 } else {
1044 return EqExpr::alloc(l, r);
1045 }
1046}
1047
1048
1054 ReadExpr *rd) {
1055 if (rd->updates.root->isSymbolicArray() || rd->updates.getSize())
1056 return EqExpr_create(cl, rd);
1057
1058 // Number of positions in the array that contain value ct.
1059 unsigned numMatches = 0;
1060
1061 // for now, just assume standard "flushing" of a concrete array,
1062 // where the concrete array has one update for each index, in order
1064 for (unsigned i = 0, e = rd->updates.root->size; i != e; ++i) {
1065 if (cl == rd->updates.root->constantValues[i]) {
1066 // Arbitrary maximum on the size of disjunction.
1067 if (++numMatches > 100)
1068 return EqExpr_create(cl, rd);
1069
1070 ref<Expr> mayBe =
1071 EqExpr::create(rd->index, ConstantExpr::alloc(i,
1072 rd->index->getWidth()));
1073 res = OrExpr::create(res, mayBe);
1074 }
1075 }
1076
1077 return res;
1078}
1079
1081 Expr::Width width = cl->getWidth();
1082
1083 Expr::Kind rk = r->getKind();
1084 if (width == Expr::Bool) {
1085 if (cl->isTrue()) {
1086 return r;
1087 } else {
1088 // 0 == ...
1089
1090 if (rk == Expr::Eq) {
1091 const EqExpr *ree = cast<EqExpr>(r);
1092
1093 // eliminate double negation
1094 if (ConstantExpr *CE = dyn_cast<ConstantExpr>(ree->left)) {
1095 // 0 == (0 == A) => A
1096 if (CE->getWidth() == Expr::Bool &&
1097 CE->isFalse())
1098 return ree->right;
1099 }
1100 } else if (rk == Expr::Or) {
1101 const OrExpr *roe = cast<OrExpr>(r);
1102
1103 // transform not(or(a,b)) to and(not a, not b)
1104 return AndExpr::create(Expr::createIsZero(roe->left),
1105 Expr::createIsZero(roe->right));
1106 }
1107 }
1108 } else if (rk == Expr::SExt) {
1109 // (sext(a,T)==c) == (a==c)
1110 const SExtExpr *see = cast<SExtExpr>(r);
1111 Expr::Width fromBits = see->src->getWidth();
1112 ref<ConstantExpr> trunc = cl->ZExt(fromBits);
1113
1114 // pathological check, make sure it is possible to
1115 // sext to this value *from any value*
1116 if (cl == trunc->SExt(width)) {
1117 return EqExpr::create(see->src, trunc);
1118 } else {
1120 }
1121 } else if (rk == Expr::ZExt) {
1122 // (zext(a,T)==c) == (a==c)
1123 const ZExtExpr *zee = cast<ZExtExpr>(r);
1124 Expr::Width fromBits = zee->src->getWidth();
1125 ref<ConstantExpr> trunc = cl->ZExt(fromBits);
1126
1127 // pathological check, make sure it is possible to
1128 // zext to this value *from any value*
1129 if (cl == trunc->ZExt(width)) {
1130 return EqExpr::create(zee->src, trunc);
1131 } else {
1133 }
1134 } else if (rk==Expr::Add) {
1135 const AddExpr *ae = cast<AddExpr>(r);
1136 if (isa<ConstantExpr>(ae->left)) {
1137 // c0 = c1 + b => c0 - c1 = b
1138 return EqExpr_createPartialR(cast<ConstantExpr>(SubExpr::create(cl,
1139 ae->left)),
1140 ae->right.get());
1141 }
1142 } else if (rk==Expr::Sub) {
1143 const SubExpr *se = cast<SubExpr>(r);
1144 if (isa<ConstantExpr>(se->left)) {
1145 // c0 = c1 - b => c1 - c0 = b
1146 return EqExpr_createPartialR(cast<ConstantExpr>(SubExpr::create(se->left,
1147 cl)),
1148 se->right.get());
1149 }
1150 } else if (rk == Expr::Read && ConstArrayOpt) {
1151 return TryConstArrayOpt(cl, static_cast<ReadExpr*>(r));
1152 }
1153
1154 return EqExpr_create(cl, r);
1155}
1156
1158 return EqExpr_createPartialR(cr, l);
1159}
1160
1161ref<Expr> NeExpr::create(const ref<Expr> &l, const ref<Expr> &r) {
1162 return EqExpr::create(ConstantExpr::create(0, Expr::Bool),
1163 EqExpr::create(l, r));
1164}
1165
1166ref<Expr> UgtExpr::create(const ref<Expr> &l, const ref<Expr> &r) {
1167 return UltExpr::create(r, l);
1168}
1169ref<Expr> UgeExpr::create(const ref<Expr> &l, const ref<Expr> &r) {
1170 return UleExpr::create(r, l);
1171}
1172
1173ref<Expr> SgtExpr::create(const ref<Expr> &l, const ref<Expr> &r) {
1174 return SltExpr::create(r, l);
1175}
1176ref<Expr> SgeExpr::create(const ref<Expr> &l, const ref<Expr> &r) {
1177 return SleExpr::create(r, l);
1178}
1179
1180static ref<Expr> UltExpr_create(const ref<Expr> &l, const ref<Expr> &r) {
1181 Expr::Width t = l->getWidth();
1182 if (t == Expr::Bool) { // !l && r
1183 return AndExpr::create(Expr::createIsZero(l), r);
1184 } else {
1185 return UltExpr::alloc(l, r);
1186 }
1187}
1188
1189static ref<Expr> UleExpr_create(const ref<Expr> &l, const ref<Expr> &r) {
1190 if (l->getWidth() == Expr::Bool) { // !(l && !r)
1191 return OrExpr::create(Expr::createIsZero(l), r);
1192 } else {
1193 return UleExpr::alloc(l, r);
1194 }
1195}
1196
1197static ref<Expr> SltExpr_create(const ref<Expr> &l, const ref<Expr> &r) {
1198 if (l->getWidth() == Expr::Bool) { // l && !r
1199 return AndExpr::create(l, Expr::createIsZero(r));
1200 } else {
1201 return SltExpr::alloc(l, r);
1202 }
1203}
1204
1205static ref<Expr> SleExpr_create(const ref<Expr> &l, const ref<Expr> &r) {
1206 if (l->getWidth() == Expr::Bool) { // !(!l && r)
1207 return OrExpr::create(l, Expr::createIsZero(r));
1208 } else {
1209 return SleExpr::alloc(l, r);
1210 }
1211}
1212
1214CMPCREATE(UltExpr, Ult)
1215CMPCREATE(UleExpr, Ule)
1216CMPCREATE(SltExpr, Slt)
1217CMPCREATE(SleExpr, Sle)
static ref< Expr > EqExpr_createPartialR(const ref< ConstantExpr > &cl, Expr *r)
Definition: Expr.cpp:1080
static ref< Expr > OrExpr_createPartial(Expr *l, const ref< ConstantExpr > &cr)
Definition: Expr.cpp:891
static ref< Expr > XorExpr_createPartial(Expr *l, const ref< ConstantExpr > &cr)
Definition: Expr.cpp:917
static ref< Expr > SubExpr_createPartialR(const ref< ConstantExpr > &cl, Expr *r)
Definition: Expr.cpp:799
static ref< Expr > MulExpr_create(Expr *l, Expr *r)
Definition: Expr.cpp:865
static ref< Expr > AddExpr_createPartialR(const ref< ConstantExpr > &cl, Expr *r)
Definition: Expr.cpp:751
static ref< Expr > UleExpr_create(const ref< Expr > &l, const ref< Expr > &r)
Definition: Expr.cpp:1189
static ref< Expr > AddExpr_createPartial(Expr *l, const ref< ConstantExpr > &cr)
Definition: Expr.cpp:771
static ref< Expr > TryConstArrayOpt(const ref< ConstantExpr > &cl, ReadExpr *rd)
Definition: Expr.cpp:1053
static ref< Expr > EqExpr_createPartial(Expr *l, const ref< ConstantExpr > &cr)
Definition: Expr.cpp:1157
static ref< Expr > MulExpr_createPartial(Expr *l, const ref< ConstantExpr > &cr)
Definition: Expr.cpp:862
#define CMPCREATE_T(_e_op, _op, _reflexive_e_op, partialL, partialR)
Definition: Expr.cpp:1025
static ref< Expr > UDivExpr_create(const ref< Expr > &l, const ref< Expr > &r)
Definition: Expr.cpp:924
static ref< Expr > OrExpr_create(Expr *l, Expr *r)
Definition: Expr.cpp:903
static ref< Expr > URemExpr_create(const ref< Expr > &l, const ref< Expr > &r)
Definition: Expr.cpp:940
static ref< Expr > SubExpr_createPartial(Expr *l, const ref< ConstantExpr > &cr)
Definition: Expr.cpp:817
static ref< Expr > OrExpr_createPartialR(const ref< ConstantExpr > &cl, Expr *r)
Definition: Expr.cpp:900
#define CMPCREATE(_e_op, _op)
Definition: Expr.cpp:1016
static ref< Expr > AndExpr_createPartialR(const ref< ConstantExpr > &cl, Expr *r)
Definition: Expr.cpp:884
static ref< Expr > SDivExpr_create(const ref< Expr > &l, const ref< Expr > &r)
Definition: Expr.cpp:932
static ref< Expr > SltExpr_create(const ref< Expr > &l, const ref< Expr > &r)
Definition: Expr.cpp:1197
static ref< Expr > EqExpr_create(const ref< Expr > &l, const ref< Expr > &r)
Definition: Expr.cpp:1040
#define BCREATE(_e_op, _op)
Definition: Expr.cpp:993
static ref< Expr > MulExpr_createPartialR(const ref< ConstantExpr > &cl, Expr *r)
Definition: Expr.cpp:849
static ref< Expr > ShlExpr_create(const ref< Expr > &l, const ref< Expr > &r)
Definition: Expr.cpp:956
static ref< Expr > AddExpr_create(Expr *l, Expr *r)
Definition: Expr.cpp:774
#define BINARY_EXPR_CASE(T)
static ref< Expr > SleExpr_create(const ref< Expr > &l, const ref< Expr > &r)
Definition: Expr.cpp:1205
static ref< Expr > XorExpr_createPartialR(const ref< ConstantExpr > &cl, Expr *r)
Definition: Expr.cpp:907
static ref< Expr > XorExpr_create(Expr *l, Expr *r)
Definition: Expr.cpp:920
#define CAST_EXPR_CASE(T)
static ref< Expr > AndExpr_createPartial(Expr *l, const ref< ConstantExpr > &cr)
Definition: Expr.cpp:875
static ref< Expr > UltExpr_create(const ref< Expr > &l, const ref< Expr > &r)
Definition: Expr.cpp:1180
static ref< Expr > LShrExpr_create(const ref< Expr > &l, const ref< Expr > &r)
Definition: Expr.cpp:964
static ref< Expr > AndExpr_create(Expr *l, Expr *r)
Definition: Expr.cpp:887
static ref< Expr > SubExpr_create(Expr *l, Expr *r)
Definition: Expr.cpp:822
#define BCREATE_R(_e_op, _op, partialL, partialR)
Definition: Expr.cpp:980
#define X(C)
static ref< Expr > AShrExpr_create(const ref< Expr > &l, const ref< Expr > &r)
Definition: Expr.cpp:972
static ref< Expr > SRemExpr_create(const ref< Expr > &l, const ref< Expr > &r)
Definition: Expr.cpp:948
Array(const Array &array)
unsigned hashValue
Definition: Expr.h:501
Expr::Width getRange() const
Definition: Expr.h:530
bool isConstantArray() const
Definition: Expr.h:525
const unsigned size
Definition: Expr.h:489
bool isSymbolicArray() const
Definition: Expr.h:524
const std::vector< ref< ConstantExpr > > constantValues
Definition: Expr.h:498
unsigned computeHash()
ComputeHash must take into account the name, the size, the domain, and the range.
Definition: Expr.cpp:528
const std::string name
Definition: Expr.h:486
Width getWidth() const
Definition: Expr.h:849
ref< Expr > src
Definition: Expr.h:843
virtual unsigned computeHash()
Definition: Expr.cpp:205
static ref< Expr > createN(unsigned nKids, const ref< Expr > kids[])
Shortcuts to create larger concats. The chain returned is unbalanced to the right.
Definition: Expr.cpp:647
static ref< Expr > alloc(const ref< Expr > &l, const ref< Expr > &r)
Definition: Expr.h:683
static ref< Expr > create(const ref< Expr > &l, const ref< Expr > &r)
Definition: Expr.cpp:623
static ref< Expr > create8(const ref< Expr > &kid1, const ref< Expr > &kid2, const ref< Expr > &kid3, const ref< Expr > &kid4, const ref< Expr > &kid5, const ref< Expr > &kid6, const ref< Expr > &kid7, const ref< Expr > &kid8)
Shortcut to concat 8 kids. The chain returned is unbalanced to the right.
Definition: Expr.cpp:665
static ref< Expr > create4(const ref< Expr > &kid1, const ref< Expr > &kid2, const ref< Expr > &kid3, const ref< Expr > &kid4)
Shortcut to concat 4 kids. The chain returned is unbalanced to the right.
Definition: Expr.cpp:659
ref< ConstantExpr > Not()
Definition: Expr.cpp:455
void toMemory(void *address)
Definition: Expr.cpp:354
virtual unsigned computeHash()
Definition: Expr.cpp:195
Width getWidth() const
Definition: Expr.h:1009
llvm::APInt value
Definition: Expr.h:1002
static ref< ConstantExpr > create(uint64_t v, Width w)
Definition: Expr.h:1079
static ref< ConstantExpr > alloc(const llvm::APInt &v)
Definition: Expr.h:1065
uint64_t getZExtValue(unsigned bits=64) const
Definition: Expr.h:1030
ref< ConstantExpr > Neg()
Definition: Expr.cpp:403
static ref< Expr > fromMemory(void *address, Width w)
Definition: Expr.cpp:337
void toString(std::string &Res, unsigned radix=10) const
Definition: Expr.cpp:369
static void printSingleExpr(llvm::raw_ostream &os, const ref< Expr > &e)
Class representing symbolic expressions.
Definition: Expr.h:91
static const unsigned MAGIC_HASH_CONSTANT
Definition: Expr.h:94
static const Width Int64
Definition: Expr.h:104
static const Width Int32
Definition: Expr.h:103
virtual unsigned computeHash()
Definition: Expr.cpp:182
virtual Kind getKind() const =0
virtual void print(llvm::raw_ostream &os) const
Definition: Expr.cpp:326
int compare(const Expr &b) const
Definition: Expr.cpp:95
static ref< Expr > createIsZero(ref< Expr > e)
Definition: Expr.cpp:322
virtual int compareContents(const Expr &b) const =0
virtual unsigned hash() const
Returns the pre-computed hash of the current expression.
Definition: Expr.h:222
virtual Width getWidth() const =0
virtual unsigned getNumKids() const =0
static void printWidth(llvm::raw_ostream &os, Expr::Width w)
Definition: Expr.cpp:306
@ Xor
Definition: Expr.h:149
@ Not
Definition: Expr.h:133
@ Ule
Definition: Expr.h:158
@ LShr
Definition: Expr.h:151
@ Sge
Not used in canonical form.
Definition: Expr.h:164
@ Add
Definition: Expr.h:138
@ Select
Definition: Expr.h:124
@ Ne
Not used in canonical form.
Definition: Expr.h:156
@ And
Definition: Expr.h:147
@ ZExt
Definition: Expr.h:129
@ URem
Definition: Expr.h:143
@ SDiv
Definition: Expr.h:142
@ NotOptimized
Definition: Expr.h:120
@ Mul
Definition: Expr.h:140
@ AShr
Definition: Expr.h:152
@ Extract
Definition: Expr.h:126
@ Read
Definition: Expr.h:123
@ Constant
Definition: Expr.h:113
@ Ugt
Not used in canonical form.
Definition: Expr.h:159
@ Sub
Definition: Expr.h:139
@ Ult
Definition: Expr.h:157
@ Shl
Definition: Expr.h:150
@ SRem
Definition: Expr.h:144
@ Concat
Definition: Expr.h:125
@ Or
Definition: Expr.h:148
@ Sle
Definition: Expr.h:162
@ Sgt
Not used in canonical form.
Definition: Expr.h:163
@ Slt
Definition: Expr.h:161
@ Uge
Not used in canonical form.
Definition: Expr.h:160
@ SExt
Definition: Expr.h:130
@ UDiv
Definition: Expr.h:141
@ Eq
Definition: Expr.h:155
unsigned Width
The type of an expression is simply its width, in bits.
Definition: Expr.h:97
unsigned hashValue
Definition: Expr.h:180
static const Width Int16
Definition: Expr.h:102
llvm::DenseSet< std::pair< const Expr *, const Expr * > > ExprEquivSet
Definition: Expr.h:289
static const Width Bool
Definition: Expr.h:100
static ref< Expr > createFromKind(Kind k, std::vector< CreateArg > args)
Definition: Expr.cpp:230
static const Width Fl80
Definition: Expr.h:105
virtual ref< Expr > getKid(unsigned i) const =0
static ref< Expr > createImplies(ref< Expr > hyp, ref< Expr > conc)
Definition: Expr.cpp:318
static void printKind(llvm::raw_ostream &os, Kind k)
Definition: Expr.cpp:135
void dump() const
dump - Print the expression to stderr.
Definition: Expr.cpp:330
static const Width Int8
Definition: Expr.h:101
unsigned offset
Definition: Expr.h:746
static ref< Expr > alloc(const ref< Expr > &e, unsigned o, Width w)
Definition: Expr.h:750
Width getWidth() const
Definition: Expr.h:759
static ref< Expr > create(ref< Expr > e, unsigned bitOff, Width w)
Creates an ExtractExpr with the given bit offset and width.
Definition: Expr.cpp:675
ref< Expr > expr
Definition: Expr.h:745
virtual unsigned computeHash()
Definition: Expr.cpp:211
ref< Expr > expr
Definition: Expr.h:798
static ref< Expr > create(const ref< Expr > &e)
Definition: Expr.cpp:705
static ref< Expr > alloc(const ref< Expr > &e)
Definition: Expr.h:801
virtual unsigned computeHash()
Definition: Expr.cpp:225
static ref< Expr > create(ref< Expr > src)
Definition: Expr.cpp:501
static ref< Expr > alloc(const ref< Expr > &src)
Definition: Expr.h:417
ref< Expr > src
Definition: Expr.h:415
Class representing a one byte read from an array.
Definition: Expr.h:565
virtual unsigned computeHash()
Definition: Expr.cpp:218
ref< Expr > index
Definition: Expr.h:572
int compareContents(const Expr &b) const
Definition: Expr.cpp:588
static ref< Expr > alloc(const UpdateList &updates, const ref< Expr > &index)
Definition: Expr.h:575
UpdateList updates
Definition: Expr.h:571
static ref< Expr > create(const UpdateList &updates, ref< Expr > i)
Definition: Expr.cpp:538
static ref< Expr > create(ref< Expr > c, ref< Expr > t, ref< Expr > f)
Definition: Expr.cpp:592
static ref< Expr > alloc(const ref< Expr > &c, const ref< Expr > &t, const ref< Expr > &f)
Definition: Expr.h:619
Class representing a complete list of updates into an array.
Definition: Expr.h:539
ref< UpdateNode > head
pointer to the most recent update node
Definition: Expr.h:546
unsigned getSize() const
size of this update list
Definition: Expr.h:556
int compare(const UpdateList &b) const
Definition: Updates.cpp:61
unsigned hash() const
Definition: Updates.cpp:87
const Array * root
Definition: Expr.h:543
uint64_t trunc(uint64_t l, unsigned outWidth, unsigned inWidth)
Definition: main.cpp:291
llvm::cl::OptionCategory ExprCat