@@ -343,6 +343,94 @@ expr2smvt::resultt expr2smvt::convert_typecast(const typecast_exprt &expr)
343343
344344/* ******************************************************************\
345345
346+ Function: expr2smvt::convert_zero_extend
347+
348+ Inputs:
349+
350+ Outputs:
351+
352+ Purpose:
353+
354+ \*******************************************************************/
355+
356+ expr2smvt::resultt expr2smvt::convert_zero_extend (const zero_extend_exprt &expr)
357+ {
358+ // these may apply to a variety of operand/result types
359+ auto &src_type = expr.op ().type ();
360+ auto &dest_type = expr.type ();
361+
362+ if (src_type.id () == ID_unsignedbv && dest_type.id () == ID_signedbv)
363+ {
364+ // unsigned to signed
365+ auto src_width = to_unsignedbv_type (src_type).get_width ();
366+ auto dest_width = to_signedbv_type (dest_type).get_width ();
367+
368+ if (src_width == dest_width)
369+ {
370+ // signedness change only
371+ return convert_rec (smv_signed_cast_exprt{expr.op (), dest_type});
372+ }
373+ else
374+ {
375+ PRECONDITION (dest_width > src_width);
376+
377+ // Signedness _and_ width change. First extend, then go signed
378+ return convert_rec (smv_signed_cast_exprt{
379+ smv_extend_exprt{
380+ expr.op (), dest_width - src_width, unsignedbv_typet{dest_width}},
381+ dest_type});
382+ }
383+ }
384+ else if (src_type.id () == ID_signedbv && dest_type.id () == ID_unsignedbv)
385+ {
386+ // signed to unsigned
387+ auto src_width = to_signedbv_type (src_type).get_width ();
388+ auto dest_width = to_unsignedbv_type (dest_type).get_width ();
389+
390+ if (src_width == dest_width)
391+ {
392+ // signedness change only
393+ return convert_rec (smv_unsigned_cast_exprt{expr.op (), dest_type});
394+ }
395+ else
396+ {
397+ PRECONDITION (dest_width > src_width);
398+
399+ // Signedness _and_ width change. First go unsigned, then enlarge.
400+ return convert_rec (smv_extend_exprt{
401+ smv_unsigned_cast_exprt{expr.op (), unsignedbv_typet{src_width}},
402+ dest_width - src_width,
403+ dest_type});
404+ }
405+ }
406+ else if (src_type.id () == ID_signedbv && dest_type.id () == ID_signedbv)
407+ {
408+ // Note that SMV's resize(...) preserves the sign bit, unlike our typecast.
409+ // We therefore first go unsigned, then resize, then go signed again.
410+ auto src_width = to_signedbv_type (src_type).get_width ();
411+ auto dest_width = to_signedbv_type (dest_type).get_width ();
412+ return convert_rec (smv_signed_cast_exprt{
413+ smv_resize_exprt{
414+ smv_unsigned_cast_exprt{expr.op (), unsignedbv_typet{src_width}},
415+ dest_width,
416+ unsignedbv_typet{dest_width}},
417+ dest_type});
418+ }
419+ else if (src_type.id () == ID_unsignedbv && dest_type.id () == ID_unsignedbv)
420+ {
421+ // Unsigned to unsigned, possible width change.
422+ auto src_width = to_unsignedbv_type (src_type).get_width ();
423+ auto dest_width = to_unsignedbv_type (dest_type).get_width ();
424+ PRECONDITION (dest_width >= src_width);
425+ return convert_rec (
426+ smv_extend_exprt{expr.op (), dest_width - src_width, dest_type});
427+ }
428+ else
429+ return convert_norep (expr);
430+ }
431+
432+ /* ******************************************************************\
433+
346434Function: expr2smvt::convert_rtctl
347435
348436 Inputs:
0 commit comments