@@ -825,7 +825,7 @@ inline unary_overflow_exprt &to_unary_overflow_expr(exprt &expr)
825825// / \brief The count leading zeros (counting the number of zero bits starting
826826// / from the most-significant bit) expression. When \c zero_permitted is set to
827827// / false, goto_checkt must generate an assertion that the operand does not
828- // / evaluates to zero. The result is always defined, even for zero (where the
828+ // / evaluate to zero. The result is always defined, even for zero (where the
829829// / result is the bit width).
830830class count_leading_zeros_exprt : public unary_exprt
831831{
@@ -915,4 +915,97 @@ inline count_leading_zeros_exprt &to_count_leading_zeros_expr(exprt &expr)
915915 return ret;
916916}
917917
918+ // / \brief The count trailing zeros (counting the number of zero bits starting
919+ // / from the least-significant bit) expression. When \c zero_permitted is set to
920+ // / false, goto_checkt must generate an assertion that the operand does not
921+ // / evaluate to zero. The result is always defined, even for zero (where the
922+ // / result is the bit width).
923+ class count_trailing_zeros_exprt : public unary_exprt
924+ {
925+ public:
926+ count_trailing_zeros_exprt (exprt _op, bool _zero_permitted, typet _type)
927+ : unary_exprt(ID_count_trailing_zeros, std::move(_op), std::move(_type))
928+ {
929+ zero_permitted (_zero_permitted);
930+ }
931+
932+ explicit count_trailing_zeros_exprt (const exprt &_op)
933+ : count_trailing_zeros_exprt(_op, true , _op.type())
934+ {
935+ }
936+
937+ bool zero_permitted () const
938+ {
939+ return !get_bool (ID_C_bounds_check);
940+ }
941+
942+ void zero_permitted (bool value)
943+ {
944+ set (ID_C_bounds_check, !value);
945+ }
946+
947+ static void check (
948+ const exprt &expr,
949+ const validation_modet vm = validation_modet::INVARIANT)
950+ {
951+ DATA_CHECK (
952+ vm,
953+ expr.operands ().size () == 1 ,
954+ " unary expression must have a single operand" );
955+ DATA_CHECK (
956+ vm,
957+ can_cast_type<bitvector_typet>(to_unary_expr (expr).op ().type ()),
958+ " operand must be of bitvector type" );
959+ }
960+
961+ static void validate (
962+ const exprt &expr,
963+ const namespacet &,
964+ const validation_modet vm = validation_modet::INVARIANT)
965+ {
966+ check (expr, vm);
967+ }
968+
969+ // / Lower a count_trailing_zeros_exprt to arithmetic and logic expressions.
970+ // / \return Semantically equivalent expression
971+ exprt lower () const ;
972+ };
973+
974+ template <>
975+ inline bool can_cast_expr<count_trailing_zeros_exprt>(const exprt &base)
976+ {
977+ return base.id () == ID_count_trailing_zeros;
978+ }
979+
980+ inline void validate_expr (const count_trailing_zeros_exprt &value)
981+ {
982+ validate_operands (value, 1 , " count_trailing_zeros must have one operand" );
983+ }
984+
985+ // / \brief Cast an exprt to a \ref count_trailing_zeros_exprt
986+ // /
987+ // / \a expr must be known to be \ref count_trailing_zeros_exprt.
988+ // /
989+ // / \param expr: Source expression
990+ // / \return Object of type \ref count_trailing_zeros_exprt
991+ inline const count_trailing_zeros_exprt &
992+ to_count_trailing_zeros_expr (const exprt &expr)
993+ {
994+ PRECONDITION (expr.id () == ID_count_trailing_zeros);
995+ const count_trailing_zeros_exprt &ret =
996+ static_cast <const count_trailing_zeros_exprt &>(expr);
997+ validate_expr (ret);
998+ return ret;
999+ }
1000+
1001+ // / \copydoc to_count_trailing_zeros_expr(const exprt &)
1002+ inline count_trailing_zeros_exprt &to_count_trailing_zeros_expr (exprt &expr)
1003+ {
1004+ PRECONDITION (expr.id () == ID_count_trailing_zeros);
1005+ count_trailing_zeros_exprt &ret =
1006+ static_cast <count_trailing_zeros_exprt &>(expr);
1007+ validate_expr (ret);
1008+ return ret;
1009+ }
1010+
9181011#endif // CPROVER_UTIL_BITVECTOR_EXPR_H
0 commit comments