Example #1
0
void TritonToZ3Ast::operator()(triton::ast::BvashrNode& e) {
    Z3Result op1      = this->eval(*e.getChilds()[0]);
    Z3Result op2      = this->eval(*e.getChilds()[1]);
    z3::expr newexpr  = to_expr(this->result.getContext(), Z3_mk_bvashr(this->result.getContext(), op1.getExpr(), op2.getExpr()));

    this->result.setExpr(newexpr);
}
Example #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");
    }
}