@@ -3794,6 +3794,77 @@ std::string expr2ct::convert_with_precedence(
37943794 else if (src.id ()==ID_type)
37953795 return convert (src.type ());
37963796
3797+ else if (src.id () == ID_rol)
3798+ {
3799+ // AAAA rol n == (AAAA << n % width(AAAA))
3800+ // | (AAAA >> (width(AAAA) - n % width(AAAA)))
3801+ auto bin_expr = to_binary_expr (src);
3802+ // Get AAAA and if it's signed wrap it in a cast to remove
3803+ // the sign since this messes with C shifts
3804+ exprt &op0 = bin_expr.op0 ();
3805+ if (can_cast_type<signedbv_typet>(op0.type ()))
3806+ {
3807+ // Shifts in C are arithmetic and care about sign, by forcing
3808+ // a cast to unsigned we force the shifts to perform rol/r
3809+ size_t ws = op0.type ().get_size_t (" width" );
3810+ op0 = typecast_exprt (op0, unsignedbv_typet (ws));
3811+ }
3812+ // Get n because we need its type to construct the "width(AAAA)"
3813+ // value to use in operations below.
3814+ exprt &op1 = bin_expr.op1 ();
3815+ // Construct the "width(AAAA)" constant
3816+ irep_idt width_val = op0.type ().get (" width" );
3817+ auto width = constant_exprt (width_val, op1.type ());
3818+ // Apply modulo to n since shifting will overflow
3819+ // That is: 0001 << 4 == 0, but 0001 rol 4 == 0001
3820+ op1 = mod_exprt (op1, width);
3821+ // Now put the pieces together
3822+ // width(AAAA) - (n % width(AAAA))
3823+ auto complement_expr = minus_exprt (width, op1);
3824+ // AAAA >> complement_expr
3825+ auto rhs_expr = ashr_exprt (op0, complement_expr);
3826+ // AAAA << (n % width(AAAA))
3827+ auto lhs_exprt = shl_exprt (op0, op1);
3828+ // The whole thing
3829+ auto the_expr = bitor_exprt (lhs_exprt, rhs_expr);
3830+ return convert_with_precedence (the_expr, precedence);
3831+ }
3832+ else if (src.id () == ID_ror)
3833+ {
3834+ // AAAA rol n == (AAAA >> n % width(AAAA))
3835+ // | (AAAA << (width(AAAA) - n % width(AAAA)))
3836+ auto bin_expr = to_binary_expr (src);
3837+ // Get AAAA and if it's signed wrap it in a cast to remove
3838+ // the sign since this messes with C shifts
3839+ exprt &op0 = bin_expr.op0 ();
3840+ if (can_cast_type<signedbv_typet>(op0.type ()))
3841+ {
3842+ // Shifts in C are arithmetic and care about sign, by forcing
3843+ // a cast to unsigned we force the shifts to perform rol/r
3844+ size_t ws = op0.type ().get_size_t (" width" );
3845+ op0 = typecast_exprt (op0, unsignedbv_typet (ws));
3846+ }
3847+ // Get n because we need its type to construct the "width(AAAA)"
3848+ // value to use in operations below.
3849+ exprt &op1 = bin_expr.op1 ();
3850+ // Construct the "width(AAAA)" constant
3851+ irep_idt width_val = op0.type ().get (" width" );
3852+ auto width = constant_exprt (width_val, op1.type ());
3853+ // Apply modulo to n since shifting will overflow
3854+ // That is: 0001 >> 4 == 0, but 0001 ror 4 == 0001
3855+ op1 = mod_exprt (op1, width);
3856+ // Now put the pieces together
3857+ // width(AAAA) - (n % width(AAAA))
3858+ auto complement_expr = minus_exprt (width, op1);
3859+ // AAAA << complement_expr
3860+ auto rhs_expr = shl_exprt (op0, complement_expr);
3861+ // AAAA >> (n % width(AAAA))
3862+ auto lhs_exprt = ashr_exprt (op0, op1);
3863+ // The whole thing
3864+ auto the_expr = bitor_exprt (lhs_exprt, rhs_expr);
3865+ return convert_with_precedence (the_expr, precedence);
3866+ }
3867+
37973868 auto function_string_opt = convert_function (src);
37983869 if (function_string_opt.has_value ())
37993870 return *function_string_opt;
0 commit comments