@@ -2118,6 +2118,33 @@ void verilog_typecheck_exprt::convert_range(
21182118
21192119/* ******************************************************************\
21202120
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+
21212148Function: verilog_typecheck_exprt::tc_binary_expr
21222149
21232150 Inputs:
@@ -2132,20 +2159,7 @@ void verilog_typecheck_exprt::tc_binary_expr(
21322159 const exprt &expr,
21332160 exprt &op0, exprt &op1)
21342161{
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
21492163 const typet new_type =
21502164 max_type (enum_decay (op0.type ()), enum_decay (op1.type ()));
21512165
@@ -2163,6 +2177,85 @@ void verilog_typecheck_exprt::tc_binary_expr(
21632177
21642178/* ******************************************************************\
21652179
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
2194+ : to_bitvector_type (expr.type ()).get_width ();
2195+
2196+ // first make unsigned
2197+ typet tmp_type;
2198+
2199+ if (type.id () == ID_unsignedbv)
2200+ tmp_type = unsignedbv_typet{old_width};
2201+ else if (type.id () == ID_verilog_unsignedbv)
2202+ tmp_type = verilog_unsignedbv_typet{old_width};
2203+ else
2204+ PRECONDITION (false );
2205+
2206+ return typecast_exprt::conditional_cast (
2207+ typecast_exprt::conditional_cast (expr, tmp_type), type);
2208+ }
2209+
2210+ /* ******************************************************************\
2211+
2212+ Function: verilog_typecheck_exprt::typecheck_relation
2213+
2214+ Inputs:
2215+
2216+ Outputs:
2217+
2218+ Purpose:
2219+
2220+ \*******************************************************************/
2221+
2222+ void verilog_typecheck_exprt::typecheck_relation (binary_exprt &expr)
2223+ {
2224+ auto &lhs = expr.lhs ();
2225+ auto &rhs = expr.rhs ();
2226+
2227+ // Relations are special-cased in 1800-2017 11.8.2.
2228+ const typet new_type =
2229+ max_type (enum_decay (lhs.type ()), enum_decay (rhs.type ()));
2230+
2231+ if (new_type.is_nil ())
2232+ {
2233+ throw errort ().with_location (expr.source_location ())
2234+ << " expected operands of compatible type but got:\n "
2235+ << " " << to_string (lhs.type ()) << ' \n '
2236+ << " " << to_string (rhs.type ());
2237+ }
2238+
2239+ // If both operands are signed, both are sign-extended to the max width.
2240+ // Otherwise, both are zero-extended to the max width.
2241+ // In particular, signed operands are then _not_ sign extended,
2242+ // which a typecast would do.
2243+ if (new_type.id () == ID_verilog_unsignedbv || new_type.id () == ID_unsignedbv)
2244+ {
2245+ // zero extend both operands
2246+ lhs = zero_extend (lhs, new_type);
2247+ rhs = zero_extend (rhs, new_type);
2248+ }
2249+ else
2250+ {
2251+ // convert
2252+ implicit_typecast (lhs, new_type);
2253+ implicit_typecast (rhs, new_type);
2254+ }
2255+ }
2256+
2257+ /* ******************************************************************\
2258+
21662259Function: verilog_typecheck_exprt::max_type
21672260
21682261 Inputs:
@@ -2585,7 +2678,7 @@ exprt verilog_typecheck_exprt::convert_binary_expr(binary_exprt expr)
25852678 Forall_operands (it, expr)
25862679 convert_expr (*it);
25872680
2588- tc_binary_expr (expr);
2681+ typecheck_relation (expr);
25892682
25902683 return std::move (expr);
25912684 }
@@ -2597,7 +2690,7 @@ exprt verilog_typecheck_exprt::convert_binary_expr(binary_exprt expr)
25972690 Forall_operands (it, expr)
25982691 convert_expr (*it);
25992692
2600- tc_binary_expr (expr);
2693+ typecheck_relation (expr);
26012694
26022695 // This returns 'x' if either of the operands contains x or z.
26032696 if (
@@ -2648,7 +2741,7 @@ exprt verilog_typecheck_exprt::convert_binary_expr(binary_exprt expr)
26482741 Forall_operands (it, expr)
26492742 convert_expr (*it);
26502743
2651- tc_binary_expr (expr);
2744+ typecheck_relation (expr);
26522745
26532746 return std::move (expr);
26542747 }
@@ -2660,7 +2753,7 @@ exprt verilog_typecheck_exprt::convert_binary_expr(binary_exprt expr)
26602753 Forall_operands (it, expr)
26612754 convert_expr (*it);
26622755
2663- tc_binary_expr (expr);
2756+ typecheck_relation (expr);
26642757 no_bool_ops (expr);
26652758
26662759 return std::move (expr);
0 commit comments