@@ -2290,6 +2290,72 @@ std::string expr2ct::convert_initializer_list(const exprt &src)
2290
2290
return dest;
2291
2291
}
2292
2292
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
+
2293
2359
std::string expr2ct::convert_designated_initializer (const exprt &src)
2294
2360
{
2295
2361
if (src.operands ().size ()!=1 )
@@ -3794,6 +3860,9 @@ std::string expr2ct::convert_with_precedence(
3794
3860
else if (src.id ()==ID_type)
3795
3861
return convert (src.type ());
3796
3862
3863
+ else if (src.id () == ID_rol || src.id () == ID_ror)
3864
+ return convert_rox (src, precedence);
3865
+
3797
3866
auto function_string_opt = convert_function (src);
3798
3867
if (function_string_opt.has_value ())
3799
3868
return *function_string_opt;
0 commit comments