Skip to content

Commit f521bed

Browse files
committed
Add conversion for rol and ror operators to c output
This adds conversion for the rol and ror operators from CBMC internals into C code. This is done by bit-twiddling the values to achieve the outcome. Fixes #6241
1 parent d5c9ef8 commit f521bed

File tree

1 file changed

+71
-0
lines changed

1 file changed

+71
-0
lines changed

src/ansi-c/expr2c.cpp

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)