int Expr::evaluateAsInteger(){ if (isIntExpr()){ return ((IntExpr*)this)->getValue(); } if (isBinaryExpr()){ BinaryExpr* binExpr = (BinaryExpr*)this; int e1 = binExpr->getE1()->evaluateAsInteger(); int e2 = binExpr->getE1()->evaluateAsInteger(); BinaryOp* op = binExpr->getOp(); switch(op->getType()){ case BinaryOp::TIMES: return e1*e2; break; case BinaryOp::MINUS: return e1-e2; break; case BinaryOp::PLUS: return e1+e2; break; default : cerr << "Unsupported binary expression for evaluation" << endl; exit(1); } } cerr << "Can't evaluate this expression"; exit(1); }
void IRGenerator::accept(BinaryExpr& expr) { FNTRACE(); static const std::unordered_map< int /*FlowVM::Opcode*/, Value* (IRGenerator::*)(Value*, Value*, const std::string&) > ops = { // numerical { FlowVM::Opcode::NADD, &IRGenerator::createAdd }, { FlowVM::Opcode::NSUB, &IRGenerator::createSub }, { FlowVM::Opcode::NMUL, &IRGenerator::createMul }, { FlowVM::Opcode::NDIV, &IRGenerator::createDiv }, { FlowVM::Opcode::NREM, &IRGenerator::createRem }, { FlowVM::Opcode::NSHL, &IRGenerator::createShl }, { FlowVM::Opcode::NSHR, &IRGenerator::createShr }, { FlowVM::Opcode::NPOW, &IRGenerator::createPow }, { FlowVM::Opcode::NAND, &IRGenerator::createAnd }, { FlowVM::Opcode::NOR, &IRGenerator::createOr }, { FlowVM::Opcode::NXOR, &IRGenerator::createXor }, { FlowVM::Opcode::NCMPEQ, &IRGenerator::createNCmpEQ }, { FlowVM::Opcode::NCMPNE, &IRGenerator::createNCmpNE }, { FlowVM::Opcode::NCMPLE, &IRGenerator::createNCmpLE }, { FlowVM::Opcode::NCMPGE, &IRGenerator::createNCmpGE }, { FlowVM::Opcode::NCMPLT, &IRGenerator::createNCmpLT }, { FlowVM::Opcode::NCMPGT, &IRGenerator::createNCmpGT }, // string { FlowVM::Opcode::SADD, &IRGenerator::createSAdd }, { FlowVM::Opcode::SCMPEQ, &IRGenerator::createSCmpEQ }, { FlowVM::Opcode::SCMPNE, &IRGenerator::createSCmpNE }, { FlowVM::Opcode::SCMPLE, &IRGenerator::createSCmpLE }, { FlowVM::Opcode::SCMPGE, &IRGenerator::createSCmpGE }, { FlowVM::Opcode::SCMPLT, &IRGenerator::createSCmpLT }, { FlowVM::Opcode::SCMPGT, &IRGenerator::createSCmpGT }, { FlowVM::Opcode::SCMPBEG, &IRGenerator::createSCmpEB }, { FlowVM::Opcode::SCMPEND, &IRGenerator::createSCmpEE }, //{ FlowVM::Opcode::SCONTAINS, &IRGenerator::createSContains }, // regex { FlowVM::Opcode::SREGMATCH, &IRGenerator::createSCmpRE }, }; Value* lhs = codegen(expr.leftExpr()); Value* rhs = codegen(expr.rightExpr()); auto i = ops.find(expr.op()); if (i != ops.end()) { result_ = (this->*i->second)(lhs, rhs, ""); } else { // fall back to generic VmInstr result_ = insert(new VmInstr(expr.op(), {lhs, rhs})); } }
Expr* BinaryExpr::CreateSubExprForPushdown(const std::vector<std::string> &inTableNameList) const { PDASSERT(mpLeftOperand && mpRightOperand); Expr *result = NULL; Expr *leftExpr = NULL; if (mpLeftOperand) { leftExpr = mpLeftOperand->CreateSubExprForPushdown(inTableNameList); } if (leftExpr) { Expr *rightExpr = NULL; if (mpRightOperand) { rightExpr = mpRightOperand->CreateSubExprForPushdown(inTableNameList); } if (rightExpr) { BinaryExpr *newBinaryExpr = new BinaryExpr(); newBinaryExpr->SetOpType(this->GetOpType()); newBinaryExpr->SetLeftOperand(leftExpr); newBinaryExpr->SetRightOperand(rightExpr); result = newBinaryExpr; } else { delete leftExpr; leftExpr = NULL; } } return result; }
std::string process_impl(BinaryExpr const & e, bool use_parenthesis, rt_latex_translator<InterfaceType> const & translator) const { std::stringstream ss; viennamath::rt_expr<InterfaceType> lhs(e.lhs()->clone()); viennamath::rt_expr<InterfaceType> rhs(e.rhs()->clone()); if (dynamic_cast< const op_binary<op_div<NumericType>, InterfaceType> * >(e.op()) != NULL) //division -> \frac{}{} { if (use_parenthesis) ss << " \\left( "; ss << " \\frac{" << translator(lhs) << "}{" << translator(rhs) << "} "; if (use_parenthesis) ss << " \\right) "; } else { bool is_op_mult = false; if (dynamic_cast< const op_binary<op_mult<NumericType>, InterfaceType> * >(e.op()) != NULL) is_op_mult = true; bool is_op_minus = false; if (dynamic_cast< const op_binary<op_minus<NumericType>, InterfaceType> * >(e.op()) != NULL) is_op_minus = true; if (use_parenthesis) ss << "("; ss << translator(lhs, is_op_mult); if (is_op_mult) ss << " \\cdot "; else ss << " " << e.op()->str() << " "; ss << translator(rhs, is_op_mult || is_op_minus); if (use_parenthesis) ss << ")"; } return ss.str(); }
// we need to check for div by zero during partial evaluation, // if this occurs then simply ignore the 0 divisor and use the // original expression. ExprVisitor::Action ExprEvaluator::protectedDivOperation(const BinaryExpr &e) { ref<Expr> kids[2] = { visit(e.left), visit(e.right) }; if (ConstantExpr *CE = dyn_cast<ConstantExpr>(kids[1])) if (CE->isZero()) kids[1] = e.right; if (kids[0]!=e.left || kids[1]!=e.right) { return Action::changeTo(e.rebuild(kids)); } else { return Action::skipChildren(); } }
void FlowCallVisitor::accept(BinaryExpr& expr) { visit(expr.leftExpr()); visit(expr.rightExpr()); }
void IRGenerator::accept(BinaryExpr& expr) { FNTRACE(); static const std::unordered_map< int /*FlowVM::Opcode*/, Value* (IRGenerator::*)(Value*, Value*, const std::string&) > ops = { // numerical { FlowVM::Opcode::NADD, &IRGenerator::createAdd }, { FlowVM::Opcode::NSUB, &IRGenerator::createSub }, { FlowVM::Opcode::NMUL, &IRGenerator::createMul }, { FlowVM::Opcode::NDIV, &IRGenerator::createDiv }, { FlowVM::Opcode::NREM, &IRGenerator::createRem }, { FlowVM::Opcode::NSHL, &IRGenerator::createShl }, { FlowVM::Opcode::NSHR, &IRGenerator::createShr }, { FlowVM::Opcode::NPOW, &IRGenerator::createPow }, { FlowVM::Opcode::NAND, &IRGenerator::createAnd }, { FlowVM::Opcode::NOR, &IRGenerator::createOr }, { FlowVM::Opcode::NXOR, &IRGenerator::createXor }, { FlowVM::Opcode::NCMPEQ, &IRGenerator::createNCmpEQ }, { FlowVM::Opcode::NCMPNE, &IRGenerator::createNCmpNE }, { FlowVM::Opcode::NCMPLE, &IRGenerator::createNCmpLE }, { FlowVM::Opcode::NCMPGE, &IRGenerator::createNCmpGE }, { FlowVM::Opcode::NCMPLT, &IRGenerator::createNCmpLT }, { FlowVM::Opcode::NCMPGT, &IRGenerator::createNCmpGT }, // string { FlowVM::Opcode::SADD, &IRGenerator::createSAdd }, { FlowVM::Opcode::SCMPEQ, &IRGenerator::createSCmpEQ }, { FlowVM::Opcode::SCMPNE, &IRGenerator::createSCmpNE }, { FlowVM::Opcode::SCMPLE, &IRGenerator::createSCmpLE }, { FlowVM::Opcode::SCMPGE, &IRGenerator::createSCmpGE }, { FlowVM::Opcode::SCMPLT, &IRGenerator::createSCmpLT }, { FlowVM::Opcode::SCMPGT, &IRGenerator::createSCmpGT }, { FlowVM::Opcode::SCMPBEG, &IRGenerator::createSCmpEB }, { FlowVM::Opcode::SCMPEND, &IRGenerator::createSCmpEE }, { FlowVM::Opcode::SCONTAINS, &IRGenerator::createSIn }, // regex { FlowVM::Opcode::SREGMATCH, &IRGenerator::createSCmpRE }, // ip { FlowVM::Opcode::PCMPEQ, &IRGenerator::createPCmpEQ }, { FlowVM::Opcode::PCMPNE, &IRGenerator::createPCmpNE }, { FlowVM::Opcode::PINCIDR, &IRGenerator::createPInCidr }, }; if (expr.op() == FlowVM::Opcode::BOR) { // (lhs || rhs) // // L = lhs(); // if (L) goto end; // R = rhs(); // L = R; // end: // result = L; BasicBlock* borLeft = createBlock("bor.left"); BasicBlock* borRight = createBlock("bor.right"); BasicBlock* borCont = createBlock("bor.cont"); AllocaInstr* result = createAlloca(FlowType::Boolean, get(1), "bor"); Value* lhs = codegen(expr.leftExpr()); createCondBr(lhs, borLeft, borRight); setInsertPoint(borLeft); createStore(result, lhs, "bor.left"); createBr(borCont); setInsertPoint(borRight); Value* rhs = codegen(expr.rightExpr()); createStore(result, rhs, "bor.right"); createBr(borCont); setInsertPoint(borCont); result_ = result; return; } Value* lhs = codegen(expr.leftExpr()); Value* rhs = codegen(expr.rightExpr()); auto i = ops.find(expr.op()); if (i != ops.end()) { result_ = (this->*i->second)(lhs, rhs, ""); } else { fprintf(stderr, "BUG: Binary operation `%s` not implemented.\n", mnemonic(expr.op())); assert(!"Unimplemented"); result_ = nullptr; } }
// 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; } }
void InstantiationVisitor::visit(BinaryExpr& b) { _expr.reset(new BinaryExpr(b.sloc(), clone(b.left()), b.op(), clone(b.right()))); }