@@ -343,6 +343,100 @@ expr2smvt::resultt expr2smvt::convert_typecast(const typecast_exprt &expr)
343
343
344
344
/* ******************************************************************\
345
345
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
+
346
440
Function: expr2smvt::convert_rtctl
347
441
348
442
Inputs:
@@ -839,6 +933,11 @@ expr2smvt::resultt expr2smvt::convert_rec(const exprt &src)
839
933
return convert_typecast (to_typecast_expr (src));
840
934
}
841
935
936
+ else if (src.id () == ID_zero_extend)
937
+ {
938
+ return convert_zero_extend (to_zero_extend_expr (src));
939
+ }
940
+
842
941
else // no SMV language expression for internal representation
843
942
return convert_norep (src);
844
943
}
0 commit comments