bvt boolbvt::convert_power(const binary_exprt &expr) { const typet &type=ns.follow(expr.type()); std::size_t width=boolbv_width(type); if(width==0) return conversion_failed(expr); if(type.id()==ID_unsignedbv || type.id()==ID_signedbv) { // Let's do the special case 2**x bvt op0=convert_bv(expr.op0()); bvt op1=convert_bv(expr.op1()); literalt eq_2= bv_utils.equal(op0, bv_utils.build_constant(2, op0.size())); bvt one=bv_utils.build_constant(1, width); bvt shift=bv_utils.shift(one, bv_utilst::LEFT, op1); bvt nondet=prop.new_variables(width); return bv_utils.select(eq_2, shift, nondet); } return conversion_failed(expr); }
bvt boolbvt::convert_shift(const binary_exprt &expr) { const irep_idt &type_id=expr.type().id(); if(type_id!=ID_unsignedbv && type_id!=ID_signedbv && type_id!=ID_floatbv && type_id!=ID_pointer && type_id!=ID_bv && type_id!=ID_verilog_signedbv && type_id!=ID_verilog_unsignedbv) return conversion_failed(expr); std::size_t width=boolbv_width(expr.type()); if(width==0) return conversion_failed(expr); if(expr.operands().size()!=2) throw "shifting takes two operands"; const bvt &op=convert_bv(expr.op0()); if(op.size()!=width) throw "convert_shift: unexpected operand 0 width"; bv_utilst::shiftt shift; if(expr.id()==ID_shl) shift=bv_utilst::shiftt::LEFT; else if(expr.id()==ID_ashr) shift=bv_utilst::shiftt::ARIGHT; else if(expr.id()==ID_lshr) shift=bv_utilst::shiftt::LRIGHT; else throw "unexpected shift operator"; // we allow a constant as shift distance if(expr.op1().is_constant()) { mp_integer i; if(to_integer(expr.op1(), i)) throw "convert_shift: failed to convert constant"; std::size_t distance; if(i<0 || i>std::numeric_limits<signed>::max()) distance=0; else distance=integer2size_t(i); if(type_id==ID_verilog_signedbv || type_id==ID_verilog_unsignedbv) distance*=2; return bv_utils.shift(op, shift, distance); } else { const bvt &distance=convert_bv(expr.op1()); return bv_utils.shift(op, shift, distance); } }