@@ -343,6 +343,100 @@ 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+ PRECONDITION (dest_width >= src_width);
413+ return convert_rec (smv_signed_cast_exprt{
414+ smv_extend_exprt{
415+ smv_unsigned_cast_exprt{expr.op (), unsignedbv_typet{src_width}},
416+ dest_width - src_width,
417+ unsignedbv_typet{dest_width}},
418+ dest_type});
419+ }
420+ else if (src_type.id () == ID_unsignedbv && dest_type.id () == ID_unsignedbv)
421+ {
422+ // Unsigned to unsigned, possible width change.
423+ auto src_width = to_unsignedbv_type (src_type).get_width ();
424+ auto dest_width = to_unsignedbv_type (dest_type).get_width ();
425+ if (dest_width == src_width)
426+ return convert_rec (expr.op ()); // no change
427+ else
428+ {
429+ PRECONDITION (dest_width > src_width);
430+ return convert_rec (
431+ smv_extend_exprt{expr.op (), dest_width - src_width, dest_type});
432+ }
433+ }
434+ else
435+ return convert_norep (expr);
436+ }
437+
438+ /* ******************************************************************\
439+
346440Function: expr2smvt::convert_rtctl
347441
348442 Inputs:
@@ -839,6 +933,11 @@ expr2smvt::resultt expr2smvt::convert_rec(const exprt &src)
839933 return convert_typecast (to_typecast_expr (src));
840934 }
841935
936+ else if (src.id () == ID_zero_extend)
937+ {
938+ return convert_zero_extend (to_zero_extend_expr (src));
939+ }
940+
842941 else // no SMV language expression for internal representation
843942 return convert_norep (src);
844943}
0 commit comments