@@ -2118,6 +2118,33 @@ void verilog_typecheck_exprt::convert_range(
2118
2118
2119
2119
/* ******************************************************************\
2120
2120
2121
+ Function: verilog_typecheck_exprt::enum_decay
2122
+
2123
+ Inputs:
2124
+
2125
+ Outputs:
2126
+
2127
+ Purpose:
2128
+
2129
+ \*******************************************************************/
2130
+
2131
+ typet verilog_typecheck_exprt::enum_decay (const typet &type)
2132
+ {
2133
+ // Verilog enum types decay to their base type when used in relational
2134
+ // or arithmetic expressions.
2135
+ if (type.get (ID_C_verilog_type) == ID_verilog_enum)
2136
+ {
2137
+ typet result = type;
2138
+ result.remove (ID_C_verilog_type);
2139
+ result.remove (ID_C_identifier);
2140
+ return result;
2141
+ }
2142
+ else
2143
+ return type;
2144
+ }
2145
+
2146
+ /* ******************************************************************\
2147
+
2121
2148
Function: verilog_typecheck_exprt::tc_binary_expr
2122
2149
2123
2150
Inputs:
@@ -2132,20 +2159,7 @@ void verilog_typecheck_exprt::tc_binary_expr(
2132
2159
const exprt &expr,
2133
2160
exprt &op0, exprt &op1)
2134
2161
{
2135
- // Verilog enum types decay to their base type when used in relational
2136
- // or arithmetic expressions.
2137
- auto enum_decay = [](const typet &type) {
2138
- if (type.get (ID_C_verilog_type) == ID_verilog_enum)
2139
- {
2140
- typet result = type;
2141
- result.remove (ID_C_verilog_type);
2142
- result.remove (ID_C_identifier);
2143
- return result;
2144
- }
2145
- else
2146
- return type;
2147
- };
2148
-
2162
+ // follows 1800-2017 11.8.2
2149
2163
const typet new_type =
2150
2164
max_type (enum_decay (op0.type ()), enum_decay (op1.type ()));
2151
2165
@@ -2163,6 +2177,84 @@ void verilog_typecheck_exprt::tc_binary_expr(
2163
2177
2164
2178
/* ******************************************************************\
2165
2179
2180
+ Function: zero_extend
2181
+
2182
+ Inputs:
2183
+
2184
+ Outputs:
2185
+
2186
+ Purpose:
2187
+
2188
+ \*******************************************************************/
2189
+
2190
+ static exprt zero_extend (const exprt &expr, const typet &type)
2191
+ {
2192
+ auto old_width = expr.type ().id () == ID_bool ?
2193
+ 1 : to_bitvector_type (expr.type ()).get_width ();
2194
+
2195
+ // first make unsigned
2196
+ typet tmp_type;
2197
+
2198
+ if (type.id () == ID_unsignedbv)
2199
+ tmp_type = unsignedbv_typet{old_width};
2200
+ else if (type.id () == ID_verilog_unsignedbv)
2201
+ tmp_type = verilog_unsignedbv_typet{old_width};
2202
+ else
2203
+ PRECONDITION (false );
2204
+
2205
+ return typecast_exprt::conditional_cast (
2206
+ typecast_exprt::conditional_cast (expr, tmp_type), type);
2207
+ }
2208
+
2209
+ /* ******************************************************************\
2210
+
2211
+ Function: verilog_typecheck_exprt::typecheck_relation
2212
+
2213
+ Inputs:
2214
+
2215
+ Outputs:
2216
+
2217
+ Purpose:
2218
+
2219
+ \*******************************************************************/
2220
+
2221
+ void verilog_typecheck_exprt::typecheck_relation (binary_exprt &expr)
2222
+ {
2223
+ auto &lhs = expr.lhs ();
2224
+ auto &rhs = expr.rhs ();
2225
+
2226
+ // Relations are special-cased in 1800-2017 11.8.2.
2227
+ const typet new_type =
2228
+ max_type (enum_decay (lhs.type ()), enum_decay (rhs.type ()));
2229
+
2230
+ if (new_type.is_nil ())
2231
+ {
2232
+ throw errort ().with_location (expr.source_location ())
2233
+ << " expected operands of compatible type but got:\n "
2234
+ << " " << to_string (lhs.type ()) << ' \n '
2235
+ << " " << to_string (rhs.type ());
2236
+ }
2237
+
2238
+ // If both operands are signed, both are sign-extended to the max width.
2239
+ // Otherwise, both are zero-extended to the max width.
2240
+ // In particular, signed operands are then _not_ sign extended,
2241
+ // which a typecast would do.
2242
+ if (new_type.id () == ID_verilog_unsignedbv || new_type.id () == ID_unsignedbv)
2243
+ {
2244
+ // zero extend both operands
2245
+ lhs = zero_extend (lhs, new_type);
2246
+ rhs = zero_extend (rhs, new_type);
2247
+ }
2248
+ else
2249
+ {
2250
+ // convert
2251
+ implicit_typecast (lhs, new_type);
2252
+ implicit_typecast (rhs, new_type);
2253
+ }
2254
+ }
2255
+
2256
+ /* ******************************************************************\
2257
+
2166
2258
Function: verilog_typecheck_exprt::max_type
2167
2259
2168
2260
Inputs:
@@ -2561,7 +2653,7 @@ exprt verilog_typecheck_exprt::convert_binary_expr(binary_exprt expr)
2561
2653
Forall_operands (it, expr)
2562
2654
convert_expr (*it);
2563
2655
2564
- tc_binary_expr (expr);
2656
+ typecheck_relation (expr);
2565
2657
2566
2658
return std::move (expr);
2567
2659
}
@@ -2573,7 +2665,7 @@ exprt verilog_typecheck_exprt::convert_binary_expr(binary_exprt expr)
2573
2665
Forall_operands (it, expr)
2574
2666
convert_expr (*it);
2575
2667
2576
- tc_binary_expr (expr);
2668
+ typecheck_relation (expr);
2577
2669
2578
2670
// This returns 'x' if either of the operands contains x or z.
2579
2671
if (
@@ -2610,7 +2702,7 @@ exprt verilog_typecheck_exprt::convert_binary_expr(binary_exprt expr)
2610
2702
Forall_operands (it, expr)
2611
2703
convert_expr (*it);
2612
2704
2613
- tc_binary_expr (expr);
2705
+ typecheck_relation (expr);
2614
2706
2615
2707
return std::move (expr);
2616
2708
}
@@ -2622,7 +2714,7 @@ exprt verilog_typecheck_exprt::convert_binary_expr(binary_exprt expr)
2622
2714
Forall_operands (it, expr)
2623
2715
convert_expr (*it);
2624
2716
2625
- tc_binary_expr (expr);
2717
+ typecheck_relation (expr);
2626
2718
no_bool_ops (expr);
2627
2719
2628
2720
return std::move (expr);
0 commit comments