Beispiel #1
0
ExprVisitor::Action
IndexTransformationExprVisitor::visitConcat(const ConcatExpr &ce) {
  if (ReadExpr *re = dyn_cast<ReadExpr>(ce.getKid(0))) {
    if (re->updates.root->hash() == array->hash() && width < ce.getWidth()) {
      if (width == Expr::InvalidWidth)
        width = ce.getWidth();
    }
  } else if (ReadExpr *re = dyn_cast<ReadExpr>(ce.getKid(1))) {
    if (re->updates.root->hash() == array->hash() && width < ce.getWidth()) {
      if (width == Expr::InvalidWidth)
        width = ce.getWidth();
    }
  }
  return Action::doChildren();
}
Beispiel #2
0
z3::expr Z3Builder::makeExpr(ref<Expr> e) {
    ++stats::queryConstructs;

    switch (e->getKind()) {
    case Expr::Constant: {
        ConstantExpr *CE = cast<ConstantExpr>(e);
        unsigned width = CE->getWidth();
        if (width == 1)
            return context_.bool_val(CE->isTrue());
        if (width <= 64)
            return context_.bv_val((__uint64)CE->getZExtValue(), width);

        // This is slower than concatenating 64-bit extractions, like STPBuilder
        // does, but the assumption is that it's quite infrequent.
        // TODO: Log these transformations.
        llvm::SmallString<32> const_repr;
        CE->getAPValue().toStringUnsigned(const_repr, 10);
        return context_.bv_val(const_repr.c_str(), width);
    }

    case Expr::NotOptimized: {
        NotOptimizedExpr *noe = cast<NotOptimizedExpr>(e);
        return getOrMakeExpr(noe->src);
    }

    case Expr::Read: {
        return makeReadExpr(cast<ReadExpr>(e));
    }

    case Expr::Select: {
        SelectExpr *se = cast<SelectExpr>(e);
        // XXX: A bug in Clang prevents us from using z3::ite
        return z3::to_expr(context_, Z3_mk_ite(context_,
                getOrMakeExpr(se->cond),
                getOrMakeExpr(se->trueExpr),
                getOrMakeExpr(se->falseExpr)));
    }

    case Expr::Concat: {
        ConcatExpr *ce = cast<ConcatExpr>(e);

        unsigned numKids = ce->getNumKids();
        z3::expr res = getOrMakeExpr(ce->getKid(numKids-1));
        for (int i = numKids - 2; i >= 0; --i) {
            res = z3::to_expr(context_,
                    Z3_mk_concat(context_, getOrMakeExpr(ce->getKid(i)), res));
        }
        return res;
    }

    case Expr::Extract: {
        ExtractExpr *ee = cast<ExtractExpr>(e);

        z3::expr src = getOrMakeExpr(ee->expr);
        if (ee->getWidth() == 1) {
            return z3::to_expr(context_, Z3_mk_extract(context_,
                    ee->offset, ee->offset, src)) == context_.bv_val(1, 1);
        } else {
            return z3::to_expr(context_, Z3_mk_extract(context_,
                    ee->offset + ee->getWidth() - 1, ee->offset, src));
        }
    }

    // Casting

    case Expr::ZExt: {
        CastExpr *ce = cast<CastExpr>(e);

        z3::expr src = getOrMakeExpr(ce->src);
        if (src.is_bool()) {
            // XXX: A bug in Clang prevents us from using z3::ite
            return z3::to_expr(context_, Z3_mk_ite(context_,
                    src,
                    context_.bv_val(1, ce->getWidth()),
                    context_.bv_val(0, ce->getWidth())));
        } else {
            return z3::to_expr(context_, Z3_mk_zero_ext(context_,
                    ce->getWidth() - src.get_sort().bv_size(), src));
        }
    }

    case Expr::SExt: {
        CastExpr *ce = cast<CastExpr>(e);

        z3::expr src = getOrMakeExpr(ce->src);
        if (src.is_bool()) {
            return z3::to_expr(context_, Z3_mk_ite(context_,
                    src,
                    context_.bv_val(1, ce->getWidth()),
                    context_.bv_val(0, ce->getWidth())));
        } else {
            return z3::to_expr(context_, Z3_mk_sign_ext(context_,
                    ce->getWidth() - src.get_sort().bv_size(), src));
        }
    }

    // Arithmetic

    case Expr::Add: {
        AddExpr *ae = cast<AddExpr>(e);
        return getOrMakeExpr(ae->left) + getOrMakeExpr(ae->right);
    }

    case Expr::Sub: {
        SubExpr *se = cast<SubExpr>(e);

        // STP here takes an extra width parameter, wondering why...
        return getOrMakeExpr(se->left) - getOrMakeExpr(se->right);
    }

    case Expr::Mul: {
        MulExpr *me = cast<MulExpr>(e);

        // Again, we skip some optimizations from STPBuilder; just let the solver
        // do its own set of simplifications.
        return getOrMakeExpr(me->left) * getOrMakeExpr(me->right);
    }

    case Expr::UDiv: {
        UDivExpr *de = cast<UDivExpr>(e);
        return z3::udiv(getOrMakeExpr(de->left), getOrMakeExpr(de->right));
    }

    case Expr::SDiv: {
        SDivExpr *de = cast<SDivExpr>(e);
        return getOrMakeExpr(de->left) / getOrMakeExpr(de->right);
    }

    case Expr::URem: {
        URemExpr *de = cast<URemExpr>(e);
        return z3::to_expr(context_, Z3_mk_bvurem(context_,
                getOrMakeExpr(de->left),
                getOrMakeExpr(de->right)));
    }

    case Expr::SRem: {
        SRemExpr *de = cast<SRemExpr>(e);

        // Assuming the sign follows dividend (otherwise we should have used
        // the Z3_mk_bvsmod() call)
        return z3::to_expr(context_, Z3_mk_bvsrem(context_,
                getOrMakeExpr(de->left),
                getOrMakeExpr(de->right)));
    }

    // Bitwise

    case Expr::Not: {
        NotExpr *ne = cast<NotExpr>(e);

        z3::expr expr = getOrMakeExpr(ne->expr);
        if (expr.is_bool()) {
            return !expr;
        } else {
            return ~expr;
        }
    }

    case Expr::And: {
        AndExpr *ae = cast<AndExpr>(e);

        z3::expr left = getOrMakeExpr(ae->left);
        z3::expr right = getOrMakeExpr(ae->right);

        if (left.is_bool()) {
            return left && right;
        } else {
            return left & right;
        }
    }

    case Expr::Or: {
        OrExpr *oe = cast<OrExpr>(e);

        z3::expr left = getOrMakeExpr(oe->left);
        z3::expr right = getOrMakeExpr(oe->right);

        if (left.is_bool()) {
            return left || right;
        } else {
            return left | right;
        }
    }

    case Expr::Xor: {
        XorExpr *xe = cast<XorExpr>(e);

        z3::expr left = getOrMakeExpr(xe->left);
        z3::expr right = getOrMakeExpr(xe->right);

        if (left.is_bool()) {
            return z3::to_expr(context_, Z3_mk_xor(context_, left, right));
        } else {
            return left ^ right;
        }
    }

    case Expr::Shl: {
        ShlExpr *se = cast<ShlExpr>(e);
        return z3::to_expr(context_, Z3_mk_bvshl(context_,
                getOrMakeExpr(se->left),
                getOrMakeExpr(se->right)));
    }

    case Expr::LShr: {
        LShrExpr *lse = cast<LShrExpr>(e);
        return z3::to_expr(context_, Z3_mk_bvlshr(context_,
                getOrMakeExpr(lse->left),
                getOrMakeExpr(lse->right)));
    }

    case Expr::AShr: {
        AShrExpr *ase = cast<AShrExpr>(e);
        return z3::to_expr(context_, Z3_mk_bvashr(context_,
                getOrMakeExpr(ase->left),
                getOrMakeExpr(ase->right)));
    }

    // Comparison

    case Expr::Eq: {
        EqExpr *ee = cast<EqExpr>(e);
        return getOrMakeExpr(ee->left) == getOrMakeExpr(ee->right);
    }

    case Expr::Ult: {
        UltExpr *ue = cast<UltExpr>(e);
        return z3::ult(getOrMakeExpr(ue->left), getOrMakeExpr(ue->right));
    }

    case Expr::Ule: {
        UleExpr *ue = cast<UleExpr>(e);
        return z3::ule(getOrMakeExpr(ue->left), getOrMakeExpr(ue->right));
    }

    case Expr::Slt: {
        SltExpr *se = cast<SltExpr>(e);
        return getOrMakeExpr(se->left) < getOrMakeExpr(se->right);
    }

    case Expr::Sle: {
        SleExpr *se = cast<SleExpr>(e);
        return getOrMakeExpr(se->left) <= getOrMakeExpr(se->right);
    }

    // unused due to canonicalization
#if 0
    case Expr::Ne:
    case Expr::Ugt:
    case Expr::Uge:
    case Expr::Sgt:
    case Expr::Sge:
#endif

    default:
        assert(0 && "unhandled Expr type");
    }
}
Beispiel #3
0
z3::expr KQuery2Z3::eachExprToZ3(ref<Expr> &ele) {
	z3::expr res = z3_ctx.bool_val(true);

	switch (ele->getKind()) {

	case Expr::Constant: {
		ConstantExpr *ce = cast<ConstantExpr>(ele);
		Expr::Width width = ce->getWidth();

		if (ele.get()->isFloat) {
			//float point number
			//in z3 there is no difference between float and double
			//they are all real value.
			double temp = 1.0;
			if (width == 32) {
				llvm::APFloat resValue(llvm::APFloat::IEEEsingle,
						ce->getAPValue());
				temp = resValue.convertToFloat(); //the real float number,how to establish expr of z3
			} else if (width == 64) {
				llvm::APFloat resValue(llvm::APFloat::IEEEdouble,
						ce->getAPValue());
				temp = resValue.convertToDouble(); // the real double number.
			}
			Fraction frac;
			getFraction(temp, frac);
//			std::stringstream ss;
//			ss << temp;
//				std::cerr << "frac.num = " << frac.num << " "
//						<< "frac.den = " << frac.den << std::endl;
//			res = z3_ctx.real_val(ss.str().c_str());
			res = z3_ctx.real_val(frac.num, frac.den);
//				std::cerr << "float point value = " << res << std::endl;
		} else {
			if (width == Expr::Bool) {
				if (ce->isTrue()) {
					//that is true
					res = z3_ctx.bool_val(true);
				} else {
					//that is false
					res = z3_ctx.bool_val(false);
				}
			} else if (width != Expr::Fl80) {
				int temp = ce->getZExtValue();
//					std::cerr << "temp = " << temp << std::endl;
#if INT_ARITHMETIC
				res = z3_ctx.int_val(temp);
#else
				res = z3_ctx.bv_val(temp, BIT_WIDTH);
#endif

//	     			std::cerr << res;
			} else {
				assert(0 && "The Fl80 out, value bit number extends 64");
			}
		}
		return res;
	}

	case Expr::NotOptimized: {
		assert(0 && "don't handle NotOptimized expression");
		return res;
	}

	case Expr::Read: {
		//type char
		ReadExpr *re = cast<ReadExpr>(ele);
		assert(re && re->updates.root);
		const std::string varName = re->updates.root->name;
		if (re->getWidth() == Expr::Bool) {
			res = z3_ctx.bool_const(varName.c_str());
		} else {
#if INT_ARITHMETIC
				res = z3_ctx.constant(varName.c_str(), z3_ctx.int_sort());
#else
				res = z3_ctx.constant(varName.c_str(), z3_ctx.bv_sort(BIT_WIDTH));
#endif

		}
		return res;
	}

	case Expr::Select: {
		SelectExpr *se = cast<SelectExpr>(ele);

		z3::expr cond = eachExprToZ3(se->cond);
		z3::expr tExpr = eachExprToZ3(se->trueExpr);
		z3::expr fExpr = eachExprToZ3(se->falseExpr);

		res = z3::ite(cond, tExpr, fExpr);
		return res;
	}

	case Expr::Concat: {
		ConcatExpr *ce = cast<ConcatExpr>(ele);
		ReadExpr *re = NULL;
		if (ce->getKid(0)->getKind() == Expr::Read)
			re = cast<ReadExpr>(ce->getKid(0));
		else if (ce->getKid(1)->getKind() == Expr::Read)
			re = cast<ReadExpr>(ce->getKid(1));
		else if (ce->getKid(1)->getKind() == Expr::Concat){
			while (ce->getKid(1)->getKind() == Expr::Concat) {
				ce = cast<ConcatExpr>(ce->getKid(1));
			}
			re = cast<ReadExpr>(ce->getKid(1));
		} else {
			assert("file: kQuery2z3, Expr::Concat" && false);
		}
		const std::string varName = re->updates.root->name;
		if (re->updates.root->isFloat) {  //float point symbolics
//				std::cerr << "build float " << varName << std::endl;
			res = z3_ctx.constant(varName.c_str(), z3_ctx.real_sort());
		} else {

//			std::cerr << "build bitvector" << varName << std::endl;
			if (ele.get()->isFloat)
				res = z3_ctx.constant(varName.c_str(), z3_ctx.real_sort());
			else
#if INT_ARITHMETIC
				res = z3_ctx.constant(varName.c_str(), z3_ctx.int_sort());
#else
				res = z3_ctx.constant(varName.c_str(), z3_ctx.bv_sort(BIT_WIDTH));
#endif

		}
//			else {
//				assert("real concat operation happened in Expr::Concat\n"
//						"need to be handle in minutes");
//			}
		return res;
	}

		//Trunc and FPTrunc and FPtoSI and FPtoUI
	case Expr::Extract: {
		ExtractExpr * ee = cast<ExtractExpr>(ele);
		z3::expr src = eachExprToZ3(ee->expr);

//			std::cerr << "print in the Extract in kquery2z3\n";
//			ele->dump();
//			ee->expr.get()->dump();

		//convert to boolean value, that means the result
		//depends on the ExtractExpr's least significant
		//bytes.
		if (ee->expr.get()->isFloat && !ee->isFloat) {
			//handle fptosi and fptoui
//			std::cerr << "handle fptosi \n";
//			ele.get()->dump();
			try {
#if INT_ARITHMETIC
			z3::expr temp = z3::to_expr(z3_ctx, Z3_mk_real2int(z3_ctx, src));
#else
			z3::expr temp = z3::to_expr(z3_ctx, Z3_mk_real2int(z3_ctx, src));
			z3::expr vecTemp = z3::to_expr(z3_ctx,
					Z3_mk_int2bv(z3_ctx, BIT_WIDTH, temp));
#endif
			if (ee->width == Expr::Bool) {
				//handle double->bool the special
#if INT_ARITHMETIC
				res = z3::ite(temp, z3_ctx.bool_val(1), z3_ctx.bool_val(0));
#else
				res = z3::ite(
						z3::to_expr(z3_ctx,
								Z3_mk_extract(z3_ctx, 0, 0, vecTemp)),
								z3_ctx.bv_val(1, BIT_WIDTH), z3_ctx.bv_val(0, BIT_WIDTH));
#endif
			} else {
#if INT_ARITHMETIC
				res = temp;
#else
				res = vecTemp;
#endif
			}
			} catch (z3::exception &ex) {
				std::cerr << "exception = " << ex << std::endl;
			}
		} else if (!ee->expr.get()->isFloat && !ee->isFloat) {
			//handle trunc and fptrunc, both these instructions
			//have same type before or after convert.
			if (ee->width == Expr::Bool) {
				//handle int->bool the special
#if INT_ARITHMETIC
				res = z3::ite(src, z3_ctx.int_val(1), z3_ctx.int_val(0));
#else
				res = z3::ite(
						z3::to_expr(z3_ctx, Z3_mk_extract(z3_ctx, 0, 0, src)),
						z3_ctx.bv_val(1, BIT_WIDTH), z3_ctx.bv_val(0, BIT_WIDTH));
#endif

			} else {
				res = src;
			}
		} else {
			//float->float;
			res = src;
		}
		return res;
	}

		//ZExt SExt handle methods from encode.cpp
	case Expr::ZExt: {
		CastExpr * ce = cast<CastExpr>(ele);
		z3::expr src = eachExprToZ3(ce->src);

		if (ce->src.get()->getWidth() == Expr::Bool) {
#if INT_ARITHMETIC
				res = z3::ite(src, z3_ctx.int_val(1), z3_ctx.int_val(0));
#else
				res = z3::ite(src, z3_ctx.bv_val(1, BIT_WIDTH), z3_ctx.bv_val(0, BIT_WIDTH));
//				res = z3::ite(
//					z3::to_expr(z3_ctx, Z3_mk_extract(z3_ctx, 0, 0, src)),
//					z3_ctx.bool_val(true), z3_ctx.bool_val(false));
#endif
//			if (Z3_TRUE == Z3_algebraic_is_zero(z3_ctx, src)) {
//				res = z3_ctx.bool_val(false);
//			} else {
//				res = z3_ctx.bool_val(true);
//			}
		} else {
			res = src;
		}
		return res;
	}

	case Expr::SExt: {
		CastExpr * ce = cast<CastExpr>(ele);

		//convert int or unsigned int to float point
		//need to handle alone.
//			if (ce->isFloat) {
//				res = eachExprToZ3(ce->src, true);
//			} else {
		z3::expr src = eachExprToZ3(ce->src);
		if (ce->isFloat && !ce->src.get()->isFloat) {
			try {
#if INT_ARITHMETIC
			z3::expr realTemp = to_expr(z3_ctx, Z3_mk_int2real(z3_ctx, src));

#else
			z3::expr temp = to_expr(z3_ctx, Z3_mk_bv2int(z3_ctx, src, true));
			z3::expr realTemp = to_expr(z3_ctx, Z3_mk_int2real(z3_ctx, temp));
#endif
			res = realTemp;
			} catch (z3::exception &ex) {
				std::cerr << "exception = " << ex << std::endl;
			}
		} else if (!ce->isFloat && !ce->src.get()->isFloat) {
			if (ce->src.get()->getWidth() == Expr::Bool
					&& ce->width != Expr::Bool) {
#if INT_ARITHMETIC
				res = z3::ite(src, z3_ctx.int_val(1), z3_ctx.int_val(0));
#else
				res = z3::ite(src, z3_ctx.bv_val(1, BIT_WIDTH), z3_ctx.bv_val(0, BIT_WIDTH));
#endif
//				res = z3::ite(src, z3_ctx.bool_val(true), z3_ctx.bool_val(false));
//				res = z3::ite(
//						z3::to_expr(z3_ctx, Z3_mk_extract(z3_ctx, 0, 0, src)),
//						z3_ctx.bool_val(true), z3_ctx.bool_val(false));
			} else {
				res = src;
			}
		} else {
			res = src;
		}
//			}
		return res;
	}

	case Expr::Add: {
		AddExpr *ae = cast<AddExpr>(ele);
//			std::cerr << "Is this wrong?\n";
//			ae->left.get()->dump();
//			ae->right.get()->dump();
//			std::cerr << "Add expr show\n";
//			ele.get()->dump();


			// if one of the operand is a float point number
			// then the left and right are all float point number.
			if (ae->left.get()->isFloat || ae->right.get()->isFloat) {
				ae->left.get()->isFloat = true;
				ae->right.get()->isFloat = true;
			}
		z3::expr left = eachExprToZ3(ae->left);
		z3::expr right = eachExprToZ3(ae->right);

//		assert(
//				left.get_sort() == right.get_sort()
//						&& "sort between left and right are different in Expr::Add\n");

			res = left + right;
			return res;
		}

		case Expr::Sub: {
			SubExpr *se = cast<SubExpr>(ele);
			if (se->left.get()->isFloat || se->right.get()->isFloat) {
				se->left.get()->isFloat = true;
				se->right.get()->isFloat = true;
			}
			z3::expr left = eachExprToZ3(se->left);
			z3::expr right = eachExprToZ3(se->right);

//			assert(
//					left.get_sort() == right.get_sort()
//							&& "sort between left and right are different in Expr::Sub\n");

		res = left - right;
		return res;
	}

		case Expr::Mul: {
			MulExpr *me = cast<MulExpr>(ele);
			if (me->left.get()->isFloat || me->right.get()->isFloat) {
				me->left.get()->isFloat = true;
				me->right.get()->isFloat = true;
			}
			z3::expr left = eachExprToZ3(me->left);
			z3::expr right = eachExprToZ3(me->right);
//			std::cerr << left << "\n";
//			std::cerr << right << "\n";
//			assert(
//					left.get_sort() == right.get_sort()
//							&& "sort between left and right are different in Expr::Mul\n");


		res = left * right;
		return res;
	}

	case Expr::UDiv: {
		//could handled with SDiv, but for test just do in here.
			UDivExpr *ue = cast<UDivExpr>(ele);
			if (ue->left.get()->isFloat || ue->right.get()->isFloat) {
				ue->left.get()->isFloat = true;
				ue->right.get()->isFloat = true;
			}
			z3::expr left = eachExprToZ3(ue->left);
			z3::expr right = eachExprToZ3(ue->right);
//			assert(
//					left.get_sort() == right.get_sort()
//							&& "sort between left and right are different in Expr::UDiv\n");
		try {
			if (left.is_bv()) {
				res = z3::to_expr(z3_ctx, Z3_mk_bvudiv(z3_ctx, left, right));
			} else {
				res = z3::to_expr(z3_ctx, Z3_mk_div(z3_ctx, left, right));
			}
		} catch (z3::exception &ex) {
				std::cerr << "UDiv exception = " << ex << std::endl;
		}
		return res;
	}

		case Expr::SDiv: {
			SDivExpr *se = cast<SDivExpr>(ele);
			if (se->left.get()->isFloat || se->right.get()->isFloat) {
				se->left.get()->isFloat = true;
				se->right.get()->isFloat = true;
			}
			z3::expr left = eachExprToZ3(se->left);
			z3::expr right = eachExprToZ3(se->right);
//			assert(
//					left.get_sort() == right.get_sort()
//							&& "sort between left and right are different in Expr::SDiv\n");
			try {
				if (left.is_bv()) {
					res = z3::to_expr(z3_ctx, Z3_mk_bvsdiv(z3_ctx, left, right));
				} else {
					res = z3::to_expr(z3_ctx, Z3_mk_div(z3_ctx, left, right));
				}
			} catch (z3::exception &ex) {
				std::cerr << "SDiv exception = " << ex << std::endl;
			}

		return res;
	}

		case Expr::URem: {
			URemExpr *ur = cast<URemExpr>(ele);
			if (ur->left.get()->isFloat || ur->right.get()->isFloat) {
				ur->left.get()->isFloat = true;
				ur->right.get()->isFloat = true;
			}
			z3::expr left = eachExprToZ3(ur->left);
			z3::expr right = eachExprToZ3(ur->right);
//			assert(
//					left.get_sort() == right.get_sort()
//							&& "sort between left and right are different in Expr::URem\n");
			try {
				if (left.is_bv()) {
					//bitvecotor, all int are bitvector;
					res = z3::to_expr(z3_ctx, Z3_mk_bvurem(z3_ctx, left, right));
				} else {
				//float
					res = z3::to_expr(z3_ctx, Z3_mk_rem(z3_ctx, left, right));
				}
			} catch (z3::exception &ex) {
				std::cerr << "URem exception = " << ex << std::endl;
			}
			return res;
		}

		case Expr::SRem: {
			SRemExpr *sr = cast<SRemExpr>(ele);
			if (sr->left.get()->isFloat || sr->right.get()->isFloat) {
				sr->left.get()->isFloat = true;
				sr->right.get()->isFloat = true;
			}
			z3::expr left = eachExprToZ3(sr->left);
			z3::expr right = eachExprToZ3(sr->right);
//			assert(
//					left.get_sort() == right.get_sort()
//							&& "sort between left and right are different in Expr::SRem\n");
			try {
				if (left.is_bv()) {
					//bitvecotor, all int are bitvector;
					res = z3::to_expr(z3_ctx, Z3_mk_bvsrem(z3_ctx, left, right));
				} else {
					//float
					res = z3::to_expr(z3_ctx, Z3_mk_rem(z3_ctx, left, right));
				}
			} catch (z3::exception &ex) {
				std::cerr << "SRem exception = " << ex << std::endl;
			}
			return res;
		}

	case Expr::Not: {
		NotExpr *ne = cast<NotExpr>(ele);
		res = eachExprToZ3(ne->expr);
		try {
			if (res.is_bv()) {
				res = z3::to_expr(z3_ctx, Z3_mk_bvnot(z3_ctx, res));
			} else {
				res = z3::to_expr(z3_ctx, Z3_mk_not(z3_ctx, res));
			}
		} catch (z3::exception &ex) {
			std::cerr << "Not exception = " << ex << std::endl;
		}
		return res;
	}

		case Expr::And: {
			AndExpr *ae = cast<AndExpr>(ele);
			if (ae->left.get()->isFloat || ae->right.get()->isFloat) {
				ae->left.get()->isFloat = true;
				ae->right.get()->isFloat = true;
			}
			z3::expr left = eachExprToZ3(ae->left);
			z3::expr right = eachExprToZ3(ae->right);
//			assert(
//					left.get_sort() == right.get_sort()
//							&& "sort between left and right are different in Expr::And\n");
//			std::cerr << "And left = " << left << std::endl;
//			std::cerr << "And right = " << right << std::endl;
			if (left.is_bv()) {
				res = z3::to_expr(z3_ctx, Z3_mk_bvand(z3_ctx, left, right));
			} else {
//				std::cerr << "left = " << left << ", left sort = " << left.get_sort() << std::endl;
//				std::cerr << "right = " << right << ", right sort = " << right.get_sort() << std::endl;
#if INT_ARITHMETIC
				try {
					if (left.is_int()) {
						z3::expr tempLeft = z3::to_expr(z3_ctx, Z3_mk_int2bv(z3_ctx, BIT_WIDTH, left));
//						std::cerr << "tempLeft = " << tempLeft << std::endl;
						z3::expr tempRight = z3::to_expr(z3_ctx, Z3_mk_int2bv(z3_ctx, BIT_WIDTH, right));
//						std::cerr << "tempRight = " << tempRight << std::endl;

						z3::expr tempRes = z3::to_expr(z3_ctx, Z3_mk_bvand(z3_ctx, tempLeft, tempRight));
//						std::cerr << "tempRes = " << tempRes << std::endl;
						res = z3::to_expr(z3_ctx, Z3_mk_bv2int(z3_ctx, tempRes, true));
//						std::cerr << "res = " << res << std::endl;
					} else {
						res = left && right;
					}
				} catch (z3::exception &ex) {
					std::cerr << "And exception = " << ex << std::endl;
				}
#else
				res = left && right;
#endif
			}
		return res;
	}


		case Expr::Or: {
			OrExpr *oe = cast<OrExpr>(ele);
			if (oe->left.get()->isFloat || oe->right.get()->isFloat) {
				oe->left.get()->isFloat = true;
				oe->right.get()->isFloat = true;
			}
			z3::expr left = eachExprToZ3(oe->left);
			z3::expr right = eachExprToZ3(oe->right);

//			assert(
//					left.get_sort() == right.get_sort()
//							&& "sort between left and right are different in Expr::Or\n");

			if (left.is_bv()) {
				res = z3::to_expr(z3_ctx, Z3_mk_bvor(z3_ctx, left, right));
			} else {
#if INT_ARITHMETIC
				try {
					if (left.is_int()) {
						z3::expr tempLeft = z3::to_expr(z3_ctx, Z3_mk_int2bv(z3_ctx, BIT_WIDTH, left));
						z3::expr tempRight = z3::to_expr(z3_ctx, Z3_mk_int2bv(z3_ctx, BIT_WIDTH, right));
						z3::expr tempRes = z3::to_expr(z3_ctx, Z3_mk_bvor(z3_ctx, tempLeft, tempRight));
						res = z3::to_expr(z3_ctx, Z3_mk_bv2int(z3_ctx, tempRes, true));
					} else {
						res = left || right;
					}
				} catch(z3::exception &ex) {
					std::cerr << "Or exception : " << ex << std::endl;
				}
#else
				res = left || right;
#endif
			}
		return res;
	}


		case Expr::Xor: {
			XorExpr *xe = cast<XorExpr>(ele);
			if (xe->left.get()->isFloat || xe->right.get()->isFloat) {
				xe->left.get()->isFloat = true;
				xe->right.get()->isFloat = true;
			}
			z3::expr left = eachExprToZ3(xe->left);
			z3::expr right = eachExprToZ3(xe->right);

//			assert(
//					left.get_sort() == right.get_sort()
//							&& "sort between left and right are different in Expr::Xor\n");
			try {
				if (left.is_bv()) {
					res = z3::to_expr(z3_ctx, Z3_mk_bvxor(z3_ctx, left, right));
				} else {
					res = z3::to_expr(z3_ctx, Z3_mk_xor(z3_ctx, left, right));
				}
			} catch(z3::exception &ex) {
				std::cerr << "Xor exception : " << ex << std::endl;
			}
		return res;
	}

		//following shift operation must be bitvector operand.
	case Expr::Shl: {
		ShlExpr * se = cast<ShlExpr>(ele);
		z3::expr left = eachExprToZ3(se->left);
		z3::expr right = eachExprToZ3(se->right);
		//convert bit vector to int in order to binary operation.
//		assert(
//				left.get_sort() == right.get_sort()
//						&& "sort between left and right are different in Expr::Shl\n");
#if INT_ARITHMETIC
		try {
			z3::expr tempLeft = z3::to_expr(z3_ctx, Z3_mk_int2bv(z3_ctx, BIT_WIDTH, left));
			z3::expr tempRight = z3::to_expr(z3_ctx, Z3_mk_int2bv(z3_ctx, BIT_WIDTH, right));

			z3::expr tempRes = z3::to_expr(z3_ctx, Z3_mk_bvshl(z3_ctx, tempLeft, tempRight));
			res = z3::to_expr(z3_ctx, Z3_mk_bv2int(z3_ctx, tempRes, true));
		} catch(z3::exception &ex) {
			std::cerr << "Shl exception : " << ex << std::endl;
		}
#else
		res = z3::to_expr(z3_ctx, Z3_mk_bvshl(z3_ctx, left, right));
//		res = z3::to_expr(z3_ctx, Z3_mk_bv2int(z3_ctx, tempRes, true));
#endif


		return res;
	}

	case Expr::LShr: {
		LShrExpr * lse = cast<LShrExpr>(ele);
		z3::expr left = eachExprToZ3(lse->left);
		z3::expr right = eachExprToZ3(lse->right);
//		assert(
//				left.get_sort() == right.get_sort()
//						&& "sort between left and right are different in Expr::LShr\n");
#if INT_ARITHMETIC
		try {
			z3::expr tempLeft = z3::to_expr(z3_ctx, Z3_mk_int2bv(z3_ctx, BIT_WIDTH, left));
			z3::expr tempRight = z3::to_expr(z3_ctx, Z3_mk_int2bv(z3_ctx, BIT_WIDTH, right));
			z3::expr tempRes = z3::to_expr(z3_ctx, Z3_mk_bvlshr(z3_ctx, tempLeft, tempRight));
			res = z3::to_expr(z3_ctx, Z3_mk_bv2int(z3_ctx, tempRes, true));
		} catch(z3::exception &ex) {
			std::cerr << "LShr exception : " << ex << std::endl;
		}
#else
		res = z3::to_expr(z3_ctx, Z3_mk_bvlshr(z3_ctx, left, right));
//		res = z3::to_expr(z3_ctx, Z3_mk_bv2int(z3_ctx, tempRes, true));
#endif

		return res;
	}

	case Expr::AShr: {
		AShrExpr * ase = cast<AShrExpr>(ele);
		z3::expr left = eachExprToZ3(ase->left);
		z3::expr right = eachExprToZ3(ase->right);
//		assert(
//				left.get_sort() == right.get_sort()
//						&& "sort between left and right are different in Expr::AShr\n");
#if INT_ARITHMETIC
		try {
			z3::expr tempLeft = z3::to_expr(z3_ctx, Z3_mk_int2bv(z3_ctx, BIT_WIDTH, left));
			z3::expr tempRight = z3::to_expr(z3_ctx, Z3_mk_int2bv(z3_ctx, BIT_WIDTH, right));
			z3::expr tempRes = z3::to_expr(z3_ctx, Z3_mk_bvashr(z3_ctx, tempLeft, tempRight));
			res = z3::to_expr(z3_ctx, Z3_mk_bv2int(z3_ctx, tempRes, true));
		} catch(z3::exception &ex) {
			std::cerr << "AShr exception : " << ex << std::endl;
		}
#else
		res = z3::to_expr(z3_ctx, Z3_mk_bvashr(z3_ctx, left, right));
//		res = z3::to_expr(z3_ctx, Z3_mk_bv2int(z3_ctx, tempRes, true));
#endif

		return res;
	}

		case Expr::Eq: {
			EqExpr *ee = cast<EqExpr>(ele);
			if (ee->left.get()->isFloat || ee->right.get()->isFloat) {
				ee->left.get()->isFloat = true;
				ee->right.get()->isFloat = true;
			}
//			std::cerr << "ele = " << ele << std::endl;
			z3::expr left = eachExprToZ3(ee->left);
//			std::cerr << "left = " << left << std::endl;
			z3::expr right = eachExprToZ3(ee->right);
//			assert(
//					Z3_get_sort_kind(z3_ctx, left)
//							&& "sort between left and right are different in Expr::Eq\n");
//			std::cerr << "right = " << right << std::endl;
//			std::cerr << "ee left = " << ee->left << std::endl;
//			std::cerr << "ee right = " << ee->right << std::endl;
//			std::cerr << "left = " << left << ", left sort = " << left.get_sort() << std::endl;
//			std::cerr << "right = " << right << ", right sort = " << right.get_sort() << std::endl;
			res = (left == right);

			return res;
		}

		case Expr::Ult: {
			//probably can float point value's comparison.
			UltExpr *ue = cast<UltExpr>(ele);
			if (ue->left.get()->isFloat || ue->right.get()->isFloat) {
				ue->left.get()->isFloat = true;
				ue->right.get()->isFloat = true;
			}
			z3::expr left = eachExprToZ3(ue->left);
			z3::expr right = eachExprToZ3(ue->right);
//			assert(
//					left.get_sort() == right.get_sort()
//							&& "sort between left and right are different in Expr::Ult\n");
			try {
				if (left.is_bv()) {
					res = z3::to_expr(z3_ctx, Z3_mk_bvult(z3_ctx, left, right));
				} else {
					res = z3::to_expr(z3_ctx, Z3_mk_lt(z3_ctx, left, right));
				}
			} catch(z3::exception &ex) {
				std::cerr << "Ult exception : " << ex << std::endl;
			}
			return res;
		}


		case Expr::Ule: {
			UleExpr *ue = cast<UleExpr>(ele);
			if (ue->left.get()->isFloat || ue->right.get()->isFloat) {
							ue->left.get()->isFloat = true;
							ue->right.get()->isFloat = true;
			}
			z3::expr left = eachExprToZ3(ue->left);
			z3::expr right = eachExprToZ3(ue->right);

//			assert(
//					left.get_sort() == right.get_sort()
//							&& "sort between left and right are different in Expr::Ule\n");
			try {
				if (left.is_bv()) {
					res = z3::to_expr(z3_ctx, Z3_mk_bvule(z3_ctx, left, right));
				} else {
					res = z3::to_expr(z3_ctx, Z3_mk_le(z3_ctx, left, right));
				}
			} catch(z3::exception &ex) {
				std::cerr << "Ule exception : " << ex << std::endl;
			}
		return res;
	}
		case Expr::Slt: {
			SltExpr *se = cast<SltExpr>(ele);
			if (se->left.get()->isFloat || se->right.get()->isFloat) {
				se->left.get()->isFloat = true;
				se->right.get()->isFloat = true;
			}
			z3::expr left = eachExprToZ3(se->left);
			z3::expr right = eachExprToZ3(se->right);

//			assert(
//					left.get_sort() == right.get_sort()
//							&& "sort between left and right are different in Expr::Slt\n");
			try {
				if (left.is_bv()) {
					res = z3::to_expr(z3_ctx, Z3_mk_bvslt(z3_ctx, left, right));
				} else {
					res = z3::to_expr(z3_ctx, Z3_mk_lt(z3_ctx, left, right));
				}
			} catch(z3::exception &ex) {
				std::cerr << "Slt exception : " << ex << std::endl;
			}
		return res;
	}
		case Expr::Sle: {
			SleExpr *se = cast<SleExpr>(ele);
			if (se->left.get()->isFloat || se->right.get()->isFloat) {
							se->left.get()->isFloat = true;
							se->right.get()->isFloat = true;
			}
			z3::expr left = eachExprToZ3(se->left);
			z3::expr right = eachExprToZ3(se->right);

//			assert(
//					left.get_sort() == right.get_sort()
//							&& "sort between left and right are different in Expr::Sle\n");
			try {
				if (left.is_bv()) {
					res = z3::to_expr(z3_ctx, Z3_mk_bvsle(z3_ctx, left, right));
				} else {
					res = z3::to_expr(z3_ctx, Z3_mk_le(z3_ctx, left, right));
				}
			} catch (z3::exception &ex) {
				std::cerr << "Sle exception : " << ex << std::endl;
			}
		return res;
	}

		case Expr::Ne: {
			NeExpr *ne = cast<NeExpr>(ele);
			if (ne->left.get()->isFloat || ne->right.get()->isFloat) {
				ne->left.get()->isFloat = true;
				ne->right.get()->isFloat = true;
			}
			z3::expr left = eachExprToZ3(ne->left);
			z3::expr right = eachExprToZ3(ne->right);

//			assert(
//					left.get_sort() == right.get_sort()
//							&& "sort between left and right are different in Expr::Ne\n");

			res = (left != right);
		return res;
	}

		//stp unhandled type
		/*	  case Expr::Ne:
		 case Expr::Ugt:
		 case Expr::Uge:
		 case Expr::Sgt:
		 case Expr::Sge:
		 */
	default:
		assert(0 && "unhandled Expr type in kueryExpr to Z3Expr");
		return res;

	}
	std::cerr << "end of switch\n";
	return res;
}
Beispiel #4
0
/** if *width_out!=1 then result is a bitvector,
    otherwise it is a bool */
ExprHandle STPBuilder::constructActual(ref<Expr> e, int *width_out) {
    int width;
    if (!width_out) width_out = &width;

    ++stats::queryConstructs;

    switch (e->getKind()) {
    case Expr::Constant: {
        ConstantExpr *CE = cast<ConstantExpr>(e);
        *width_out = CE->getWidth();

        // Coerce to bool if necessary.
        if (*width_out == 1)
            return CE->isTrue() ? getTrue() : getFalse();

        // Fast path.
        if (*width_out <= 32)
            return bvConst32(*width_out, CE->getZExtValue(32));
        if (*width_out <= 64)
            return bvConst64(*width_out, CE->getZExtValue());

        ref<ConstantExpr> Tmp = CE;
        ExprHandle Res = bvConst64(64, Tmp->Extract(0, 64)->getZExtValue());
        while (Tmp->getWidth() > 64) {
            Tmp = Tmp->Extract(64, Tmp->getWidth()-64);
            unsigned Width = std::min(64U, Tmp->getWidth());
            Res = vc_bvConcatExpr(vc, bvConst64(Width,
                                                Tmp->Extract(0, Width)->getZExtValue()),
                                  Res);
        }
        return Res;
    }

    // Special
    case Expr::NotOptimized: {
        NotOptimizedExpr *noe = cast<NotOptimizedExpr>(e);
        return construct(noe->src, width_out);
    }

    case Expr::Read: {
        ReadExpr *re = cast<ReadExpr>(e);
        assert(re && re->updates.root);
        *width_out = re->updates.root->getRange();
        return vc_readExpr(vc,
                           getArrayForUpdate(re->updates.root, re->updates.head),
                           construct(re->index, 0));
    }

    case Expr::Select: {
        SelectExpr *se = cast<SelectExpr>(e);
        ExprHandle cond = construct(se->cond, 0);
        ExprHandle tExpr = construct(se->trueExpr, width_out);
        ExprHandle fExpr = construct(se->falseExpr, width_out);
        return vc_iteExpr(vc, cond, tExpr, fExpr);
    }

    case Expr::Concat: {
        ConcatExpr *ce = cast<ConcatExpr>(e);
        unsigned numKids = ce->getNumKids();
        ExprHandle res = construct(ce->getKid(numKids-1), 0);
        for (int i=numKids-2; i>=0; i--) {
            res = vc_bvConcatExpr(vc, construct(ce->getKid(i), 0), res);
        }
        *width_out = ce->getWidth();
        return res;
    }

    case Expr::Extract: {
        ExtractExpr *ee = cast<ExtractExpr>(e);
        ExprHandle src = construct(ee->expr, width_out);
        *width_out = ee->getWidth();
        if (*width_out==1) {
            return bvBoolExtract(src, ee->offset);
        } else {
            return vc_bvExtract(vc, src, ee->offset + *width_out - 1, ee->offset);
        }
    }

    // Casting

    case Expr::ZExt: {
        int srcWidth;
        CastExpr *ce = cast<CastExpr>(e);
        ExprHandle src = construct(ce->src, &srcWidth);
        *width_out = ce->getWidth();
        if (srcWidth==1) {
            return vc_iteExpr(vc, src, bvOne(*width_out), bvZero(*width_out));
        } else {
            return vc_bvConcatExpr(vc, bvZero(*width_out-srcWidth), src);
        }
    }

    case Expr::SExt: {
        int srcWidth;
        CastExpr *ce = cast<CastExpr>(e);
        ExprHandle src = construct(ce->src, &srcWidth);
        *width_out = ce->getWidth();
        if (srcWidth==1) {
            return vc_iteExpr(vc, src, bvMinusOne(*width_out), bvZero(*width_out));
        } else {
            return vc_bvSignExtend(vc, src, *width_out);
        }
    }

    // Arithmetic

    case Expr::Add: {
        AddExpr *ae = cast<AddExpr>(e);
        ExprHandle left = construct(ae->left, width_out);
        ExprHandle right = construct(ae->right, width_out);
        assert(*width_out!=1 && "uncanonicalized add");
        return vc_bvPlusExpr(vc, *width_out, left, right);
    }

    case Expr::Sub: {
        SubExpr *se = cast<SubExpr>(e);
        ExprHandle left = construct(se->left, width_out);
        ExprHandle right = construct(se->right, width_out);
        assert(*width_out!=1 && "uncanonicalized sub");
        return vc_bvMinusExpr(vc, *width_out, left, right);
    }

    case Expr::Mul: {
        MulExpr *me = cast<MulExpr>(e);
        ExprHandle right = construct(me->right, width_out);
        assert(*width_out!=1 && "uncanonicalized mul");

        if (ConstantExpr *CE = dyn_cast<ConstantExpr>(me->left))
            if (CE->getWidth() <= 64)
                return constructMulByConstant(right, *width_out,
                                              CE->getZExtValue());

        ExprHandle left = construct(me->left, width_out);
        return vc_bvMultExpr(vc, *width_out, left, right);
    }

    case Expr::UDiv: {
        UDivExpr *de = cast<UDivExpr>(e);
        ExprHandle left = construct(de->left, width_out);
        assert(*width_out!=1 && "uncanonicalized udiv");

        if (ConstantExpr *CE = dyn_cast<ConstantExpr>(de->right)) {
            if (CE->getWidth() <= 64) {
                uint64_t divisor = CE->getZExtValue();

                if (bits64::isPowerOfTwo(divisor)) {
                    return bvRightShift(left,
                                        bits64::indexOfSingleBit(divisor));
                } else if (optimizeDivides) {
                    if (*width_out == 32) //only works for 32-bit division
                        return constructUDivByConstant( left, *width_out,
                                                        (uint32_t) divisor);
                }
            }
        }

        ExprHandle right = construct(de->right, width_out);
        return vc_bvDivExpr(vc, *width_out, left, right);
    }

    case Expr::SDiv: {
        SDivExpr *de = cast<SDivExpr>(e);
        ExprHandle left = construct(de->left, width_out);
        assert(*width_out!=1 && "uncanonicalized sdiv");

        if (ConstantExpr *CE = dyn_cast<ConstantExpr>(de->right))
            if (optimizeDivides)
                if (*width_out == 32) //only works for 32-bit division
                    return constructSDivByConstant( left, *width_out,
                                                    CE->getZExtValue(32));

        // XXX need to test for proper handling of sign, not sure I
        // trust STP
        ExprHandle right = construct(de->right, width_out);
        return vc_sbvDivExpr(vc, *width_out, left, right);
    }

    case Expr::URem: {
        URemExpr *de = cast<URemExpr>(e);
        ExprHandle left = construct(de->left, width_out);
        assert(*width_out!=1 && "uncanonicalized urem");

        if (ConstantExpr *CE = dyn_cast<ConstantExpr>(de->right)) {
            if (CE->getWidth() <= 64) {
                uint64_t divisor = CE->getZExtValue();

                if (bits64::isPowerOfTwo(divisor)) {
                    unsigned bits = bits64::indexOfSingleBit(divisor);

                    // special case for modding by 1 or else we bvExtract -1:0
                    if (bits == 0) {
                        return bvZero(*width_out);
                    } else {
                        return vc_bvConcatExpr(vc,
                                               bvZero(*width_out - bits),
                                               bvExtract(left, bits - 1, 0));
                    }
                }

                // Use fast division to compute modulo without explicit division for
                // constant divisor.

                if (optimizeDivides) {
                    if (*width_out == 32) { //only works for 32-bit division
                        ExprHandle quotient = constructUDivByConstant( left, *width_out, (uint32_t)divisor );
                        ExprHandle quot_times_divisor = constructMulByConstant( quotient, *width_out, divisor );
                        ExprHandle rem = vc_bvMinusExpr( vc, *width_out, left, quot_times_divisor );
                        return rem;
                    }
                }
            }
        }

        ExprHandle right = construct(de->right, width_out);
        return vc_bvModExpr(vc, *width_out, left, right);
    }

    case Expr::SRem: {
        SRemExpr *de = cast<SRemExpr>(e);
        ExprHandle left = construct(de->left, width_out);
        ExprHandle right = construct(de->right, width_out);
        assert(*width_out!=1 && "uncanonicalized srem");

#if 0 //not faster per first benchmark
        if (optimizeDivides) {
            if (ConstantExpr *cre = de->right->asConstant()) {
                uint64_t divisor = cre->asUInt64;

                //use fast division to compute modulo without explicit division for constant divisor
                if( *width_out == 32 ) { //only works for 32-bit division
                    ExprHandle quotient = constructSDivByConstant( left, *width_out, divisor );
                    ExprHandle quot_times_divisor = constructMulByConstant( quotient, *width_out, divisor );
                    ExprHandle rem = vc_bvMinusExpr( vc, *width_out, left, quot_times_divisor );
                    return rem;
                }
            }
        }
#endif

        // XXX implement my fast path and test for proper handling of sign
        return vc_sbvModExpr(vc, *width_out, left, right);
    }

    // Bitwise

    case Expr::Not: {
        NotExpr *ne = cast<NotExpr>(e);
        ExprHandle expr = construct(ne->expr, width_out);
        if (*width_out==1) {
            return vc_notExpr(vc, expr);
        } else {
            return vc_bvNotExpr(vc, expr);
        }
    }

    case Expr::And: {
        AndExpr *ae = cast<AndExpr>(e);
        ExprHandle left = construct(ae->left, width_out);
        ExprHandle right = construct(ae->right, width_out);
        if (*width_out==1) {
            return vc_andExpr(vc, left, right);
        } else {
            return vc_bvAndExpr(vc, left, right);
        }
    }

    case Expr::Or: {
        OrExpr *oe = cast<OrExpr>(e);
        ExprHandle left = construct(oe->left, width_out);
        ExprHandle right = construct(oe->right, width_out);
        if (*width_out==1) {
            return vc_orExpr(vc, left, right);
        } else {
            return vc_bvOrExpr(vc, left, right);
        }
    }

    case Expr::Xor: {
        XorExpr *xe = cast<XorExpr>(e);
        ExprHandle left = construct(xe->left, width_out);
        ExprHandle right = construct(xe->right, width_out);

        if (*width_out==1) {
            // XXX check for most efficient?
            return vc_iteExpr(vc, left,
                              ExprHandle(vc_notExpr(vc, right)), right);
        } else {
            return vc_bvXorExpr(vc, left, right);
        }
    }

    case Expr::Shl: {
        ShlExpr *se = cast<ShlExpr>(e);
        ExprHandle left = construct(se->left, width_out);
        assert(*width_out!=1 && "uncanonicalized shl");

        if (ConstantExpr *CE = dyn_cast<ConstantExpr>(se->right)) {
            return bvLeftShift(left, (unsigned) CE->getLimitedValue());
        } else {
            int shiftWidth;
            ExprHandle amount = construct(se->right, &shiftWidth);
            return bvVarLeftShift( left, amount);
        }
    }

    case Expr::LShr: {
        LShrExpr *lse = cast<LShrExpr>(e);
        ExprHandle left = construct(lse->left, width_out);
        assert(*width_out!=1 && "uncanonicalized lshr");

        if (ConstantExpr *CE = dyn_cast<ConstantExpr>(lse->right)) {
            return bvRightShift(left, (unsigned) CE->getLimitedValue());
        } else {
            int shiftWidth;
            ExprHandle amount = construct(lse->right, &shiftWidth);
            return bvVarRightShift( left, amount);
        }
    }

    case Expr::AShr: {
        AShrExpr *ase = cast<AShrExpr>(e);
        ExprHandle left = construct(ase->left, width_out);
        assert(*width_out!=1 && "uncanonicalized ashr");

        if (ConstantExpr *CE = dyn_cast<ConstantExpr>(ase->right)) {
            unsigned shift = (unsigned) CE->getLimitedValue();
            ExprHandle signedBool = bvBoolExtract(left, *width_out-1);
            return constructAShrByConstant(left, shift, signedBool);
        } else {
            int shiftWidth;
            ExprHandle amount = construct(ase->right, &shiftWidth);
            return bvVarArithRightShift( left, amount);
        }
    }

    // Comparison

    case Expr::Eq: {
        EqExpr *ee = cast<EqExpr>(e);
        ExprHandle left = construct(ee->left, width_out);
        ExprHandle right = construct(ee->right, width_out);
        if (*width_out==1) {
            if (ConstantExpr *CE = dyn_cast<ConstantExpr>(ee->left)) {
                if (CE->isTrue())
                    return right;
                return vc_notExpr(vc, right);
            } else {
                return vc_iffExpr(vc, left, right);
            }
        } else {
            *width_out = 1;
            return vc_eqExpr(vc, left, right);
        }
    }

    case Expr::Ult: {
        UltExpr *ue = cast<UltExpr>(e);
        ExprHandle left = construct(ue->left, width_out);
        ExprHandle right = construct(ue->right, width_out);
        assert(*width_out!=1 && "uncanonicalized ult");
        *width_out = 1;
        return vc_bvLtExpr(vc, left, right);
    }

    case Expr::Ule: {
        UleExpr *ue = cast<UleExpr>(e);
        ExprHandle left = construct(ue->left, width_out);
        ExprHandle right = construct(ue->right, width_out);
        assert(*width_out!=1 && "uncanonicalized ule");
        *width_out = 1;
        return vc_bvLeExpr(vc, left, right);
    }

    case Expr::Slt: {
        SltExpr *se = cast<SltExpr>(e);
        ExprHandle left = construct(se->left, width_out);
        ExprHandle right = construct(se->right, width_out);
        assert(*width_out!=1 && "uncanonicalized slt");
        *width_out = 1;
        return vc_sbvLtExpr(vc, left, right);
    }

    case Expr::Sle: {
        SleExpr *se = cast<SleExpr>(e);
        ExprHandle left = construct(se->left, width_out);
        ExprHandle right = construct(se->right, width_out);
        assert(*width_out!=1 && "uncanonicalized sle");
        *width_out = 1;
        return vc_sbvLeExpr(vc, left, right);
    }

        // unused due to canonicalization
#if 0
    case Expr::Ne:
    case Expr::Ugt:
    case Expr::Uge:
    case Expr::Sgt:
    case Expr::Sge:
#endif

    default:
        assert(0 && "unhandled Expr type");
        return vc_trueExpr(vc);
    }
}
Beispiel #5
0
/** if *et_out==etBV then result is a bitvector,
    otherwise it is a bool */
ExprHandle STPBuilder::constructActual(ref<Expr> e, int *width_out, STPExprType *et_out) {
  int width;
  if (!width_out) width_out = &width;

  ++stats::queryConstructs;

  switch (e->getKind()) {
  case Expr::Constant: {
    ConstantExpr *CE = cast<ConstantExpr>(e);
    *width_out = CE->getWidth();

    // Coerce to bool if necessary.
    if (*width_out == 1 && (*et_out == etBOOL || *et_out == etDontCare)) {
      *et_out = etBOOL;
      return CE->isTrue() ? getTrue() : getFalse();
    }

    *et_out = etBV;

    // Fast path.
    if (*width_out <= 32)
      return bvConst32(*width_out, CE->getZExtValue(32));
    if (*width_out <= 64)
      return bvConst64(*width_out, CE->getZExtValue());

    ref<ConstantExpr> Tmp = CE;
    ExprHandle Res = bvConst64(64, Tmp->Extract(0, 64)->getZExtValue());
    while (Tmp->getWidth() > 64) {
      Tmp = Tmp->Extract(64, Tmp->getWidth()-64);
      unsigned Width = std::min(64U, Tmp->getWidth());
      Res = vc_bvConcatExpr(vc, bvConst64(Width,
                                        Tmp->Extract(0, Width)->getZExtValue()),
                            Res);
    }
    return Res;
  }
    
  // Special
  case Expr::NotOptimized: {
    NotOptimizedExpr *noe = cast<NotOptimizedExpr>(e);
    return construct(noe->src, width_out, et_out);
  }

  case Expr::Read: {
    ReadExpr *re = cast<ReadExpr>(e);
    *width_out = 8;
    *et_out = etBV;
    return vc_readExpr(vc,
                       getArrayForUpdate(re->updates.root, re->updates.head),
                       construct(re->index, 0, etBV));
  }
    
  case Expr::Select: {
    SelectExpr *se = cast<SelectExpr>(e);
    ExprHandle cond = construct(se->cond, 0, etBOOL);
    ExprHandle tExpr = construct(se->trueExpr, width_out, etBV);
    ExprHandle fExpr = construct(se->falseExpr, width_out, etBV);
    *et_out = etBV;
    return vc_iteExpr(vc, cond, tExpr, fExpr);
  }

  case Expr::Concat: {
    ConcatExpr *ce = cast<ConcatExpr>(e);
    unsigned numKids = ce->getNumKids();
    ExprHandle res = construct(ce->getKid(numKids-1), 0, etBV);
    for (int i=numKids-2; i>=0; i--) {
      res = vc_bvConcatExpr(vc, construct(ce->getKid(i), 0, etBV), res);
    }
    *width_out = ce->getWidth();
    *et_out = etBV;
    return res;
  }

  case Expr::Extract: {
    ExtractExpr *ee = cast<ExtractExpr>(e);
    ExprHandle src = construct(ee->expr, width_out, etBV);    
    *width_out = ee->getWidth();
    *et_out = etBV;
    return vc_bvExtract(vc, src, ee->offset + *width_out - 1, ee->offset);
  }

    // Casting

  case Expr::ZExt: {
    int srcWidth;
    CastExpr *ce = cast<CastExpr>(e);
    STPExprType src_rt = etDontCare;
    ExprHandle src = construct(ce->src, &srcWidth, &src_rt);
    *width_out = ce->getWidth();
    *et_out = etBV;
    if (src_rt==etBOOL) {
      return vc_iteExpr(vc, src, bvOne(*width_out), bvZero(*width_out));
    } else {
      return vc_bvConcatExpr(vc, bvZero(*width_out-srcWidth), src);
    }
  }

  case Expr::SExt: {
    int srcWidth;
    CastExpr *ce = cast<CastExpr>(e);
    STPExprType src_rt = etDontCare;
    ExprHandle src = construct(ce->src, &srcWidth, &src_rt);
    *width_out = ce->getWidth();
    *et_out = etBV;
    if (src_rt==etBOOL) {
      return vc_iteExpr(vc, src, bvMinusOne(*width_out), bvZero(*width_out));
    } else {
      return vc_bvSignExtend(vc, src, *width_out);
    }
  }

    // Arithmetic

  case Expr::Add: {
    AddExpr *ae = cast<AddExpr>(e);
    ExprHandle left = construct(ae->left, width_out, etBV);
    ExprHandle right = construct(ae->right, width_out, etBV);
    assert(*width_out!=1 && "uncanonicalized add");
    *et_out = etBV;
    return vc_bvPlusExpr(vc, *width_out, left, right);
  }

  case Expr::Sub: {
    SubExpr *se = cast<SubExpr>(e);
    ExprHandle left = construct(se->left, width_out, etBV);
    ExprHandle right = construct(se->right, width_out, etBV);
    assert(*width_out!=1 && "uncanonicalized sub");
    *et_out = etBV;
    return vc_bvMinusExpr(vc, *width_out, left, right);
  } 

  case Expr::Mul: {
    MulExpr *me = cast<MulExpr>(e);
    ExprHandle right = construct(me->right, width_out, etBV);
    assert(*width_out!=1 && "uncanonicalized mul");
    *et_out = etBV;

    if (ConstantExpr *CE = dyn_cast<ConstantExpr>(me->left))
      if (CE->getWidth() <= 64)
        return constructMulByConstant(right, *width_out, 
                                      CE->getZExtValue());

    ExprHandle left = construct(me->left, width_out, etBV);
    return vc_bvMultExpr(vc, *width_out, left, right);
  }

  case Expr::UDiv: {
    UDivExpr *de = cast<UDivExpr>(e);
    ExprHandle left = construct(de->left, width_out, etBV);
    assert(*width_out!=1 && "uncanonicalized udiv");
    *et_out = etBV;
    
    if (ConstantExpr *CE = dyn_cast<ConstantExpr>(de->right)) {
      if (CE->getWidth() <= 64) {
        uint64_t divisor = CE->getZExtValue();
      
        if (bits64::isPowerOfTwo(divisor)) {
          return bvRightShift(left,
                              bits64::indexOfSingleBit(divisor),
                              getShiftBits(*width_out));
        } else if (optimizeDivides) {
          if (*width_out == 32) //only works for 32-bit division
            return constructUDivByConstant( left, *width_out, 
                                            (uint32_t) divisor);
        }
      }
    } 

    ExprHandle right = construct(de->right, width_out, etBV);
    return vc_bvDivExpr(vc, *width_out, left, right);
  }

  case Expr::SDiv: {
    SDivExpr *de = cast<SDivExpr>(e);
    ExprHandle left = construct(de->left, width_out, etBV);
    assert(*width_out!=1 && "uncanonicalized sdiv");
    *et_out = etBV;

    if (ConstantExpr *CE = dyn_cast<ConstantExpr>(de->right))
      if (optimizeDivides)
	if (*width_out == 32) //only works for 32-bit division
	  return constructSDivByConstant( left, *width_out, 
                                          CE->getZExtValue(32));

    // XXX need to test for proper handling of sign, not sure I
    // trust STP
    ExprHandle right = construct(de->right, width_out, etBV);
    return vc_sbvDivExpr(vc, *width_out, left, right);
  }

  case Expr::URem: {
    URemExpr *de = cast<URemExpr>(e);
    ExprHandle left = construct(de->left, width_out, etBV);
    assert(*width_out!=1 && "uncanonicalized urem");
    *et_out = etBV;
    
    if (ConstantExpr *CE = dyn_cast<ConstantExpr>(de->right)) {
      if (CE->getWidth() <= 64) {
        uint64_t divisor = CE->getZExtValue();

        if (bits64::isPowerOfTwo(divisor)) {
          unsigned bits = bits64::indexOfSingleBit(divisor);

          // special case for modding by 1 or else we bvExtract -1:0
          if (bits == 0) {
            return bvZero(*width_out);
          } else {
            return vc_bvConcatExpr(vc,
                                   bvZero(*width_out - bits),
                                   bvExtract(left, bits - 1, 0));
          }
        }

        // Use fast division to compute modulo without explicit division for
        // constant divisor.

        if (optimizeDivides) {
          if (*width_out == 32) { //only works for 32-bit division
            ExprHandle quotient = constructUDivByConstant( left, *width_out, (uint32_t)divisor );
            ExprHandle quot_times_divisor = constructMulByConstant( quotient, *width_out, divisor );
            ExprHandle rem = vc_bvMinusExpr( vc, *width_out, left, quot_times_divisor );
            return rem;
          }
        }
      }
    }
    
    ExprHandle right = construct(de->right, width_out, etBV);
    return vc_bvModExpr(vc, *width_out, left, right);
  }

  case Expr::SRem: {
    SRemExpr *de = cast<SRemExpr>(e);
    ExprHandle left = construct(de->left, width_out, etBV);
    ExprHandle right = construct(de->right, width_out, etBV);
    assert(*width_out!=1 && "uncanonicalized srem");
    *et_out = etBV;

#if 0 //not faster per first benchmark
    if (optimizeDivides) {
      if (ConstantExpr *cre = de->right->asConstant()) {
	uint64_t divisor = cre->asUInt64;

	//use fast division to compute modulo without explicit division for constant divisor
      	if( *width_out == 32 ) { //only works for 32-bit division
	  ExprHandle quotient = constructSDivByConstant( left, *width_out, divisor );
	  ExprHandle quot_times_divisor = constructMulByConstant( quotient, *width_out, divisor );
	  ExprHandle rem = vc_bvMinusExpr( vc, *width_out, left, quot_times_divisor );
	  return rem;
	}
      }
    }
#endif

    // XXX implement my fast path and test for proper handling of sign
    return vc_sbvModExpr(vc, *width_out, left, right);
  }

    // Bitwise

  case Expr::Not: {
    NotExpr *ne = cast<NotExpr>(e);
    ExprHandle expr = construct(ne->expr, width_out, et_out);
    if (*et_out == etBOOL) {
      return vc_notExpr(vc, expr);
    } else {
      return vc_bvNotExpr(vc, expr);
    }
  }    

  case Expr::And: {
    AndExpr *ae = cast<AndExpr>(e);
    ExprHandle left = construct(ae->left, width_out, et_out);
    ExprHandle right = construct(ae->right, width_out, *et_out);
    if (*et_out == etBOOL) {
      return vc_andExpr(vc, left, right);
    } else {
      return vc_bvAndExpr(vc, left, right);
    }
  }

  case Expr::Or: {
    OrExpr *oe = cast<OrExpr>(e);
    ExprHandle left = construct(oe->left, width_out, et_out);
    ExprHandle right = construct(oe->right, width_out, *et_out);
    if (*et_out == etBOOL) {
      return vc_orExpr(vc, left, right);
    } else {
      return vc_bvOrExpr(vc, left, right);
    }
  }

  case Expr::Xor: {
    XorExpr *xe = cast<XorExpr>(e);
    ExprHandle left = construct(xe->left, width_out, et_out);
    ExprHandle right = construct(xe->right, width_out, *et_out);
    
    if (*et_out == etBOOL) {
      // XXX check for most efficient?
      return vc_iteExpr(vc, left, 
                        ExprHandle(vc_notExpr(vc, right)), right);
    } else {
      return vc_bvXorExpr(vc, left, right);
    }
  }

  case Expr::Shl: {
    ShlExpr *se = cast<ShlExpr>(e);
    ExprHandle left = construct(se->left, width_out, etBV);
    assert(*width_out!=1 && "uncanonicalized shl");
    *et_out = etBV;

    if (ConstantExpr *CE = dyn_cast<ConstantExpr>(se->right)) {
      return bvLeftShift(left, (unsigned) CE->getLimitedValue(), 
                         getShiftBits(*width_out));
    } else {
      int shiftWidth;
      ExprHandle amount = construct(se->right, &shiftWidth, etBV);
      return bvVarLeftShift( left, amount, *width_out );
    }
  }

  case Expr::LShr: {
    LShrExpr *lse = cast<LShrExpr>(e);
    ExprHandle left = construct(lse->left, width_out, etBV);
    unsigned shiftBits = getShiftBits(*width_out);
    assert(*width_out!=1 && "uncanonicalized lshr");
    *et_out = etBV;

    if (ConstantExpr *CE = dyn_cast<ConstantExpr>(lse->right)) {
      return bvRightShift(left, (unsigned) CE->getLimitedValue(), 
                          shiftBits);
    } else {
      int shiftWidth;
      ExprHandle amount = construct(lse->right, &shiftWidth, etBV);
      return bvVarRightShift( left, amount, *width_out );
    }
  }

  case Expr::AShr: {
    AShrExpr *ase = cast<AShrExpr>(e);
    ExprHandle left = construct(ase->left, width_out, etBV);
    assert(*width_out!=1 && "uncanonicalized ashr");
    *et_out = etBV;
    
    if (ConstantExpr *CE = dyn_cast<ConstantExpr>(ase->right)) {
      unsigned shift = (unsigned) CE->getLimitedValue();
      ExprHandle signedBool = bvBoolExtract(left, *width_out-1);
      return constructAShrByConstant(left, shift, signedBool, 
                                     getShiftBits(*width_out));
    } else {
      int shiftWidth;
      ExprHandle amount = construct(ase->right, &shiftWidth, etBV);
      return bvVarArithRightShift( left, amount, *width_out );
    }
  }

    // Comparison

  case Expr::Eq: {
    EqExpr *ee = cast<EqExpr>(e);
    STPExprType src_rt = etDontCare;
    ExprHandle left = construct(ee->left, width_out, &src_rt);
    ExprHandle right = construct(ee->right, width_out, src_rt);
    *et_out = etBOOL;
    *width_out = 1;
    if (src_rt == etBOOL) {
      if (ConstantExpr *CE = dyn_cast<ConstantExpr>(ee->left)) {
        if (CE->isTrue())
          return right;
        return vc_notExpr(vc, right);
      } else {
        return vc_iffExpr(vc, left, right);
      }
    } else {
      return vc_eqExpr(vc, left, right);
    }
  }

  case Expr::Ult: {
    UltExpr *ue = cast<UltExpr>(e);
    ExprHandle left = construct(ue->left, width_out, etBV);
    ExprHandle right = construct(ue->right, width_out, etBV);
    assert(*width_out!=1 && "uncanonicalized ult");
    *width_out = 1;
    *et_out = etBOOL;
    return vc_bvLtExpr(vc, left, right);
  }

  case Expr::Ule: {
    UleExpr *ue = cast<UleExpr>(e);
    ExprHandle left = construct(ue->left, width_out, etBV);
    ExprHandle right = construct(ue->right, width_out, etBV);
    assert(*width_out!=1 && "uncanonicalized ule");
    *width_out = 1;
    *et_out = etBOOL;
    return vc_bvLeExpr(vc, left, right);
  }

  case Expr::Slt: {
    SltExpr *se = cast<SltExpr>(e);
    ExprHandle left = construct(se->left, width_out, etBV);
    ExprHandle right = construct(se->right, width_out, etBV);
    assert(*width_out!=1 && "uncanonicalized slt");
    *width_out = 1;
    *et_out = etBOOL;
    return vc_sbvLtExpr(vc, left, right);
  }

  case Expr::Sle: {
    SleExpr *se = cast<SleExpr>(e);
    ExprHandle left = construct(se->left, width_out, etBV);
    ExprHandle right = construct(se->right, width_out, etBV);
    assert(*width_out!=1 && "uncanonicalized sle");
    *width_out = 1;
    *et_out = etBOOL;
    return vc_sbvLeExpr(vc, left, right);
  }

    // unused due to canonicalization
#if 0
  case Expr::Ne:
  case Expr::Ugt:
  case Expr::Uge:
  case Expr::Sgt:
  case Expr::Sge:
#endif

  case Expr::FPToSI:
  case Expr::FPToUI: {
    if (UseFPToIAbstraction) {
      std::ostringstream ss;
      ss << "FPtoI" << fpCount++;
      *width_out = e->getWidth();
      *et_out = etBV;
      return buildVar(ss.str().c_str(), e->getWidth());
    } else {
      F2IConvertExpr *ce = cast<F2IConvertExpr>(e);
      ref<Expr> res = floatUtils(ce->src,
          ce->roundNearest()
            ? ieee_floatt::ROUND_TO_EVEN
            : ieee_floatt::ROUND_TO_ZERO).to_integer(ce->src, ce->getWidth(),
                                                  e->getKind() == Expr::FPToSI);
      return constructActual(res, width_out, et_out);
    }
  }

  case Expr::UIToFP: {
    UIToFPExpr *ue = cast<UIToFPExpr>(e);
    ref<Expr> res = floatUtils(e).from_unsigned_integer(ue->src);
    return constructActual(res, width_out, et_out);
  }

  case Expr::SIToFP: {
    SIToFPExpr *se = cast<SIToFPExpr>(e);
    ref<Expr> res = floatUtils(e).from_signed_integer(se->src);
    return constructActual(res, width_out, et_out);
  }

  case Expr::FCmp: {
    FCmpExpr *ce = cast<FCmpExpr>(e);
    float_utilst &u = floatUtils(ce->left);
    ref<Expr> res;
    switch (ce->getPredicate()) {
    case FCmpExpr::OEQ:
      res = u.relation(ce->left, float_utilst::EQ, ce->right);
      break;
    case FCmpExpr::OGT:
      res = u.relation(ce->left, float_utilst::GT, ce->right);
      break;
    case FCmpExpr::OGE:
      res = u.relation(ce->left, float_utilst::GE, ce->right);
      break;
    case FCmpExpr::OLT:
      res = u.relation(ce->left, float_utilst::LT, ce->right);
      break;
    case FCmpExpr::OLE:
      res = u.relation(ce->left, float_utilst::LE, ce->right);
      break;
    case FCmpExpr::ONE:
      res = OrExpr::create(u.relation(ce->left, float_utilst::LT, ce->right),
                           u.relation(ce->left, float_utilst::GT, ce->right));
      break;
    case FCmpExpr::ORD:
      res = Expr::createIsZero(OrExpr::create(u.is_NaN(ce->left),
                                              u.is_NaN(ce->right)));
      break;
    case FCmpExpr::UNO:
      res = OrExpr::create(u.is_NaN(ce->left),
                           u.is_NaN(ce->right));
      break;
    case FCmpExpr::UEQ:
      res = Expr::createIsZero(
              OrExpr::create(u.relation(ce->left, float_utilst::LT, ce->right),
                            u.relation(ce->left, float_utilst::GT, ce->right)));
      break;
    case FCmpExpr::UGT:
      res = Expr::createIsZero(
              u.relation(ce->left, float_utilst::LE, ce->right));
      break;
    case FCmpExpr::UGE:
      res = Expr::createIsZero(
              u.relation(ce->left, float_utilst::LT, ce->right));
      break;
    case FCmpExpr::ULT:
      res = Expr::createIsZero(
              u.relation(ce->left, float_utilst::GE, ce->right));
      break;
    case FCmpExpr::ULE:
      res = Expr::createIsZero(
              u.relation(ce->left, float_utilst::GT, ce->right));
      break;
    case FCmpExpr::UNE:
      res = Expr::createIsZero(
              u.relation(ce->left, float_utilst::EQ, ce->right));
      break;
    default:
      assert(0 && "fp cmp not implemented yet");
    }
    return constructActual(res, width_out, et_out);
  }

  case Expr::FPExt:
  case Expr::FPTrunc: {
    F2FConvertExpr *ce = cast<F2FConvertExpr>(e);
    float_utilst &fromu = floatUtils(ce->src), &tou = floatUtils(ce);
    ref<Expr> res = fromu.conversion(ce->src, tou.spec);
    return constructActual(res, width_out, et_out);
  }

  case Expr::FAdd: {
    FAddExpr *ae = cast<FAddExpr>(e);
    ref<Expr> res = floatUtils(e).add(ae->left, ae->right);
    return constructActual(res, width_out, et_out);
  }

  case Expr::FSub: {
    FSubExpr *se = cast<FSubExpr>(e);
    ref<Expr> res = floatUtils(e).sub(se->left, se->right);
    return constructActual(res, width_out, et_out);
  }

  case Expr::FMul: {
    FMulExpr *me = cast<FMulExpr>(e);
    ref<Expr> res = floatUtils(e).mul(me->left, me->right);
    return constructActual(res, width_out, et_out);
  }

  case Expr::FDiv: {
    FDivExpr *de = cast<FDivExpr>(e);
    ref<Expr> res = floatUtils(e).div(de->left, de->right);
    return constructActual(res, width_out, et_out);
  }

  default: 
    assert(0 && "unhandled Expr type");
    *et_out = etBOOL;
    return vc_trueExpr(vc);
  }
}
Beispiel #6
0
// XXX we really want to do some sort of canonicalization of exprs
// globally so that cases below become simpler
void ImpliedValue::getImpliedValues(ref<Expr> e,
                                    ref<ConstantExpr> value,
                                    ImpliedValueList &results) {
  switch (e->getKind()) {
  case Expr::Constant: {
    assert(value == cast<ConstantExpr>(e) && 
           "error in implied value calculation");
    break;
  }

    // Special

  case Expr::NotOptimized: break;

  case Expr::Read: {
    // XXX in theory it is possible to descend into a symbolic index
    // under certain circumstances (all values known, known value
    // unique, or range known, max / min hit). Seems unlikely this
    // would work often enough to be worth the effort.
    ReadExpr *re = cast<ReadExpr>(e);
    results.push_back(std::make_pair(re, value));
    break;
  }
    
  case Expr::Select: {
    // not much to do, could improve with range analysis
    SelectExpr *se = cast<SelectExpr>(e);
    
    if (ConstantExpr *TrueCE = dyn_cast<ConstantExpr>(se->trueExpr)) {
      if (ConstantExpr *FalseCE = dyn_cast<ConstantExpr>(se->falseExpr)) {
        if (TrueCE != FalseCE) {
          if (value == TrueCE) {
            getImpliedValues(se->cond, ConstantExpr::alloc(1, Expr::Bool), 
                             results);
          } else {
            assert(value == FalseCE &&
                   "err in implied value calculation");
            getImpliedValues(se->cond, ConstantExpr::alloc(0, Expr::Bool), 
                             results);
          }
        }
      }
    }
    break;
  }

  case Expr::Concat: {
    ConcatExpr *ce = cast<ConcatExpr>(e);
    getImpliedValues(ce->getKid(0), value->Extract(ce->getKid(1)->getWidth(),
                                                   ce->getKid(0)->getWidth()),
                     results);
    getImpliedValues(ce->getKid(1), value->Extract(0,
                                                   ce->getKid(1)->getWidth()),
                     results);
    break;
  }
    
  case Expr::Extract: {
    // XXX, could do more here with "some bits" mask
    break;
  }

    // Casting

  case Expr::ZExt: 
  case Expr::SExt: {
    CastExpr *ce = cast<CastExpr>(e);
    getImpliedValues(ce->src, value->Extract(0, ce->src->getWidth()),
                     results);
    break;
  }

    // Arithmetic

  case Expr::Add: { // constants on left
    BinaryExpr *be = cast<BinaryExpr>(e);
    // C_0 + A = C  =>  A = C - C_0
    if (ConstantExpr *CE = dyn_cast<ConstantExpr>(be->left))
      getImpliedValues(be->right, value->Sub(CE), results);
    break;
  }
  case Expr::Sub: { // constants on left
    BinaryExpr *be = cast<BinaryExpr>(e);
    // C_0 - A = C  =>  A = C_0 - C
    if (ConstantExpr *CE = dyn_cast<ConstantExpr>(be->left))
      getImpliedValues(be->right, CE->Sub(value), results);
    break;
  }
  case Expr::Mul: {
    // FIXME: Can do stuff here, but need valid mask and other things because of
    // bits that might be lost.
    break;
  }

  case Expr::UDiv:
  case Expr::SDiv:
  case Expr::URem:
  case Expr::SRem:
    break;

    // Binary

  case Expr::And: {
    BinaryExpr *be = cast<BinaryExpr>(e);
    if (be->getWidth() == Expr::Bool) {
      if (value->isTrue()) {
        getImpliedValues(be->left, value, results);
        getImpliedValues(be->right, value, results);
      }
    } else {
      // FIXME; We can propogate a mask here where we know "some bits". May or
      // may not be useful.
    }
    break;
  }
  case Expr::Or: {
    BinaryExpr *be = cast<BinaryExpr>(e);
    if (value->isZero()) {
      getImpliedValues(be->left, 0, results);
      getImpliedValues(be->right, 0, results);
    } else {
      // FIXME: Can do more?
    }
    break;
  }
  case Expr::Xor: {
    BinaryExpr *be = cast<BinaryExpr>(e);
    if (ConstantExpr *CE = dyn_cast<ConstantExpr>(be->left))
      getImpliedValues(be->right, value->Xor(CE), results);
    break;
  }

    // Comparison
  case Expr::Ne: 
    value = value->Not();
    /* fallthru */
  case Expr::Eq: {
    EqExpr *ee = cast<EqExpr>(e);
    if (value->isTrue()) {
      if (ConstantExpr *CE = dyn_cast<ConstantExpr>(ee->left))
        getImpliedValues(ee->right, CE, results);
    } else {
      // Look for limited value range.
      //
      // In general anytime one side was restricted to two values we can apply
      // this trick. The only obvious case where this occurs, aside from
      // booleans, is as the result of a select expression where the true and
      // false branches are single valued and distinct.
      
      if (ConstantExpr *CE = dyn_cast<ConstantExpr>(ee->left))
        if (CE->getWidth() == Expr::Bool)
          getImpliedValues(ee->right, CE->Not(), results);
    }
    break;
  }
    
  default:
    break;
  }
}
Beispiel #7
0
uint64_t ExprFrame::SerializeExpr(const ref<Expr> e) {
  data::ExprNode *ser_expr_node = expr_data_->add_expr();
  ser_expr_node->set_id(s_.next_id_++);
  ser_expr_node->set_kind((data::ExprKind)e->getKind());

  switch (e->getKind()) {
  case Expr::Constant: {
    ConstantExpr *ce = cast<ConstantExpr>(e);

    assert(ce->getWidth() <= 64 && "FIXME");
    ser_expr_node->set_value(ce->getZExtValue());
    ser_expr_node->set_width(ce->getWidth());
    break;
  }

  case Expr::NotOptimized: {
    NotOptimizedExpr *noe = cast<NotOptimizedExpr>(e);
    ser_expr_node->add_child_expr_id(GetOrSerializeExpr(noe->src));
    break;
  }

  case Expr::Read: {
    ReadExpr *re = cast<ReadExpr>(e);
    ser_expr_node->add_child_expr_id(GetOrSerializeExpr(re->index));

    if (re->updates.head) {
      ExprSerializer::UpdateNodePosition un_pos = GetOrSerializeUpdateList(re->updates);
      ser_expr_node->set_update_list_id(un_pos.first);
      ser_expr_node->set_update_list_offset(un_pos.second);
    }
    ser_expr_node->set_array_id(GetOrSerializeArray(re->updates.root));
    break;
  }

  case Expr::Select: {
    SelectExpr *se = cast<SelectExpr>(e);
    ser_expr_node->add_child_expr_id(GetOrSerializeExpr(se->cond));
    ser_expr_node->add_child_expr_id(GetOrSerializeExpr(se->trueExpr));
    ser_expr_node->add_child_expr_id(GetOrSerializeExpr(se->falseExpr));
    break;
  }

  case Expr::Concat: {
    ConcatExpr *ce = cast<ConcatExpr>(e);
    for (unsigned i = 0; i < ce->getNumKids(); ++i) {
      ser_expr_node->add_child_expr_id(GetOrSerializeExpr(ce->getKid(i)));
    }
    break;
  }

  case Expr::Extract: {
    ExtractExpr *ee = cast<ExtractExpr>(e);
    ser_expr_node->add_child_expr_id(GetOrSerializeExpr(ee->expr));
    ser_expr_node->set_offset(ee->offset);
    ser_expr_node->set_width(ee->getWidth());
    break;
  }

    // Casting,
  case Expr::ZExt:
  case Expr::SExt: {
    CastExpr *ce = cast<CastExpr>(e);
    ser_expr_node->add_child_expr_id(GetOrSerializeExpr(ce->src));
    ser_expr_node->set_width(ce->getWidth());
    break;
  }

    // All subsequent kinds are binary.

    // Arithmetic
  case Expr::Add:
  case Expr::Sub:
  case Expr::Mul:
  case Expr::UDiv:
  case Expr::SDiv:
  case Expr::URem:
  case Expr::SRem: {
    BinaryExpr *be = cast<BinaryExpr>(e);
    ser_expr_node->add_child_expr_id(GetOrSerializeExpr(be->left));
    ser_expr_node->add_child_expr_id(GetOrSerializeExpr(be->right));
    break;
  }

    // Bit
  case Expr::Not: {
    NotExpr *ne = cast<NotExpr>(e);
    ser_expr_node->add_child_expr_id(GetOrSerializeExpr(ne->expr));
    break;
  }

  case Expr::And:
  case Expr::Or:
  case Expr::Xor:
  case Expr::Shl:
  case Expr::LShr:
  case Expr::AShr: {
    BinaryExpr *be = cast<BinaryExpr>(e);
    ser_expr_node->add_child_expr_id(GetOrSerializeExpr(be->left));
    ser_expr_node->add_child_expr_id(GetOrSerializeExpr(be->right));
    break;
  }

    // Compare
  case Expr::Eq:
  case Expr::Ne:  ///< Not used in canonical form
  case Expr::Ult:
  case Expr::Ule:
  case Expr::Ugt: ///< Not used in canonical form
  case Expr::Uge: ///< Not used in canonical form
  case Expr::Slt:
  case Expr::Sle:
  case Expr::Sgt: ///< Not used in canonical form
  case Expr::Sge: { ///< Not used in canonical form
    BinaryExpr *be = cast<BinaryExpr>(e);
    ser_expr_node->add_child_expr_id(GetOrSerializeExpr(be->left));
    ser_expr_node->add_child_expr_id(GetOrSerializeExpr(be->right));
    break;
  }

  default:
    assert(0 && "Unhandled Expr type");
  }

  return ser_expr_node->id();
}