@@ -9,6 +9,10 @@ Author: Daniel Kroening, kroening@kroening.com
99#include " expr2smv.h"
1010#include " expr2smv_class.h"
1111
12+ #include < util/mathematical_types.h>
13+
14+ #include " smv_expr.h"
15+
1216/* ******************************************************************\
1317
1418Function: expr2smvt::convert_nondet_choice
@@ -221,6 +225,124 @@ expr2smvt::resultt expr2smvt::convert_function_application(
221225
222226/* ******************************************************************\
223227
228+ Function: expr2smvt::convert_typecast
229+
230+ Inputs:
231+
232+ Outputs:
233+
234+ Purpose:
235+
236+ \*******************************************************************/
237+
238+ expr2smvt::resultt expr2smvt::convert_typecast (const typecast_exprt &expr)
239+ {
240+ // typecasts can repesent a variety of functions
241+ auto &src_type = expr.op ().type ();
242+ auto &dest_type = expr.type ();
243+
244+ if (src_type.id () == ID_unsignedbv && dest_type.id () == ID_signedbv)
245+ {
246+ // unsigned to signed
247+ auto src_width = to_unsignedbv_type (src_type).get_width ();
248+ auto dest_width = to_signedbv_type (dest_type).get_width ();
249+
250+ if (src_width == dest_width)
251+ {
252+ // signedness change only
253+ return convert_rec (smv_signed_cast_exprt{expr.op (), dest_type});
254+ }
255+ else if (dest_width > src_width)
256+ {
257+ // Signedness _and_ width change. First go to signed, then extend.
258+ return convert_rec (smv_extend_exprt{
259+ smv_signed_cast_exprt{expr.op (), signedbv_typet{src_width}},
260+ dest_width - src_width,
261+ dest_type});
262+ }
263+ else
264+ {
265+ // First shrink, then go signed.
266+ return convert_rec (smv_signed_cast_exprt{
267+ smv_resize_exprt{expr.op (), dest_width, unsignedbv_typet{dest_width}},
268+ dest_type});
269+ }
270+ }
271+ else if (src_type.id () == ID_signedbv && dest_type.id () == ID_unsignedbv)
272+ {
273+ // signed to unsigned
274+ auto src_width = to_signedbv_type (src_type).get_width ();
275+ auto dest_width = to_unsignedbv_type (dest_type).get_width ();
276+
277+ if (
278+ to_signedbv_type (src_type).get_width () ==
279+ to_unsignedbv_type (dest_type).get_width ())
280+ {
281+ // signedness change only
282+ return convert_rec (smv_unsigned_cast_exprt{expr.op (), dest_type});
283+ }
284+ else if (dest_width > src_width)
285+ {
286+ // Signedness _and_ width change.
287+ // First enlarge, then go unsigned.
288+ return convert_rec (smv_unsigned_cast_exprt{
289+ smv_extend_exprt{
290+ expr.op (), dest_width - src_width, signedbv_typet{dest_width}},
291+ dest_type});
292+ }
293+ else
294+ {
295+ // First go unsigned, then shrink
296+ return convert_rec (smv_resize_exprt{
297+ smv_unsigned_cast_exprt{expr.op (), unsignedbv_typet{src_width}},
298+ dest_width,
299+ dest_type});
300+ }
301+ }
302+ else if (src_type.id () == ID_signedbv && dest_type.id () == ID_signedbv)
303+ {
304+ // signed to signed, width change.
305+ auto src_width = to_signedbv_type (src_type).get_width ();
306+ auto dest_width = to_signedbv_type (dest_type).get_width ();
307+ if (dest_width > src_width)
308+ {
309+ // enlarge using extend
310+ return convert_rec (
311+ smv_extend_exprt{expr.op (), dest_width - src_width, dest_type});
312+ }
313+ else
314+ {
315+ // Note that SMV's resize(...) preserves the sign bit, unlike our typecast.
316+ // We therefore first go unsigned, then resize, then go signed again.
317+ return convert_rec (smv_signed_cast_exprt{
318+ smv_resize_exprt{
319+ smv_unsigned_cast_exprt{expr.op (), unsignedbv_typet{src_width}},
320+ dest_width,
321+ unsignedbv_typet{dest_width}},
322+ dest_type});
323+ }
324+ }
325+ else if (src_type.id () == ID_unsignedbv && dest_type.id () == ID_unsignedbv)
326+ {
327+ // Unsigned to unsigned, width change. Use extend when enlarging.
328+ auto src_width = to_unsignedbv_type (src_type).get_width ();
329+ auto dest_width = to_unsignedbv_type (dest_type).get_width ();
330+ if (dest_width > src_width)
331+ {
332+ return convert_rec (
333+ smv_extend_exprt{expr.op (), dest_width - src_width, dest_type});
334+ }
335+ else
336+ {
337+ return convert_rec (smv_resize_exprt{expr.op (), dest_width, dest_type});
338+ }
339+ }
340+ else
341+ return convert_norep (expr);
342+ }
343+
344+ /* ******************************************************************\
345+
224346Function: expr2smvt::convert_rtctl
225347
226348 Inputs:
@@ -714,7 +836,7 @@ expr2smvt::resultt expr2smvt::convert_rec(const exprt &src)
714836
715837 else if (src.id () == ID_typecast)
716838 {
717- return convert_rec (to_typecast_expr (src). op ( ));
839+ return convert_typecast (to_typecast_expr (src));
718840 }
719841
720842 else // no SMV language expression for internal representation
0 commit comments