@@ -2290,6 +2290,71 @@ std::string expr2ct::convert_initializer_list(const exprt &src)
22902290 return dest;
22912291}
22922292
2293+ std::string expr2ct::convert_rox (const exprt &src, unsigned precedence)
2294+ {
2295+ // AAAA rox n == (AAAA lhs_op n % width(AAAA))
2296+ // | (AAAA rhs_op (width(AAAA) - n % width(AAAA)))
2297+ // Where lhs_op and rhs_op depend on whether it is rol or ror
2298+ // auto rotate_expr = to_binary_expr(src);
2299+ auto rotate_expr = expr_checked_cast<shift_exprt>(src);
2300+ // Get AAAA and if it's signed wrap it in a cast to remove
2301+ // the sign since this messes with C shifts
2302+ exprt &op0 = rotate_expr.op ();
2303+ size_t type_width;
2304+ if (can_cast_type<signedbv_typet>(op0.type ()))
2305+ {
2306+ // Set the type width
2307+ type_width = to_signedbv_type (op0.type ()).get_width ();
2308+ // Shifts in C are arithmetic and care about sign, by forcing
2309+ // a cast to unsigned we force the shifts to perform rol/r
2310+ op0 = typecast_exprt (op0, unsignedbv_typet (type_width));
2311+ }
2312+ else if (can_cast_type<unsignedbv_typet>(op0.type ()))
2313+ {
2314+ // Set the type width
2315+ type_width = to_unsignedbv_type (op0.type ()).get_width ();
2316+ }
2317+ else
2318+ {
2319+ // Type that can't be represented as bitvector
2320+ // get some kind of width in a potentially unsafe way
2321+ type_width = op0.type ().get_size_t (" width" );
2322+ }
2323+ // Construct the "width(AAAA)" constant
2324+ const exprt width_expr =
2325+ from_integer (type_width, rotate_expr.distance ().type ());
2326+ // Apply modulo to n since shifting will overflow
2327+ // That is: 0001 << 4 == 0, but 0001 rol 4 == 0001
2328+ const exprt distance_modulo_width =
2329+ mod_exprt (rotate_expr.distance (), width_expr);
2330+ // Now put the pieces together
2331+ // width(AAAA) - (n % width(AAAA))
2332+ const auto complement_expr = minus_exprt (width_expr, distance_modulo_width);
2333+ // lhs and rhs components defined according to rol/ror
2334+ exprt lhs_expr;
2335+ exprt rhs_expr;
2336+ if (src.id () == ID_rol)
2337+ {
2338+ // AAAA << (n % width(AAAA))
2339+ lhs_expr = shl_exprt (op0, distance_modulo_width);
2340+ // AAAA >> complement_expr
2341+ rhs_expr = ashr_exprt (op0, complement_expr);
2342+ }
2343+ else if (src.id () == ID_ror)
2344+ {
2345+ // AAAA >> (n % width(AAAA))
2346+ lhs_expr = ashr_exprt (op0, distance_modulo_width);
2347+ // AAAA << complement_expr
2348+ rhs_expr = shl_exprt (op0, complement_expr);
2349+ }
2350+ else
2351+ {
2352+ // Someone called this function when they shouldn't have.
2353+ UNREACHABLE;
2354+ }
2355+ return convert_with_precedence (bitor_exprt (lhs_expr, rhs_expr), precedence);
2356+ }
2357+
22932358std::string expr2ct::convert_designated_initializer (const exprt &src)
22942359{
22952360 if (src.operands ().size ()!=1 )
@@ -3794,6 +3859,9 @@ std::string expr2ct::convert_with_precedence(
37943859 else if (src.id ()==ID_type)
37953860 return convert (src.type ());
37963861
3862+ else if (src.id () == ID_rol || src.id () == ID_ror)
3863+ return convert_rox (src, precedence);
3864+
37973865 auto function_string_opt = convert_function (src);
37983866 if (function_string_opt.has_value ())
37993867 return *function_string_opt;
0 commit comments