@@ -2290,6 +2290,72 @@ 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_width_expr =
2333+ minus_exprt (width_expr, distance_modulo_width);
2334+ // lhs and rhs components defined according to rol/ror
2335+ exprt lhs_expr;
2336+ exprt rhs_expr;
2337+ if (src.id () == ID_rol)
2338+ {
2339+ // AAAA << (n % width(AAAA))
2340+ lhs_expr = shl_exprt (op0, distance_modulo_width);
2341+ // AAAA >> complement_width_expr
2342+ rhs_expr = ashr_exprt (op0, complement_width_expr);
2343+ }
2344+ else if (src.id () == ID_ror)
2345+ {
2346+ // AAAA >> (n % width(AAAA))
2347+ lhs_expr = ashr_exprt (op0, distance_modulo_width);
2348+ // AAAA << complement_width_expr
2349+ rhs_expr = shl_exprt (op0, complement_width_expr);
2350+ }
2351+ else
2352+ {
2353+ // Someone called this function when they shouldn't have.
2354+ UNREACHABLE;
2355+ }
2356+ return convert_with_precedence (bitor_exprt (lhs_expr, rhs_expr), precedence);
2357+ }
2358+
22932359std::string expr2ct::convert_designated_initializer (const exprt &src)
22942360{
22952361 if (src.operands ().size ()!=1 )
@@ -3794,6 +3860,9 @@ std::string expr2ct::convert_with_precedence(
37943860 else if (src.id ()==ID_type)
37953861 return convert (src.type ());
37963862
3863+ else if (src.id () == ID_rol || src.id () == ID_ror)
3864+ return convert_rox (src, precedence);
3865+
37973866 auto function_string_opt = convert_function (src);
37983867 if (function_string_opt.has_value ())
37993868 return *function_string_opt;
0 commit comments