@@ -89,7 +89,7 @@ void verilog_typecheck_exprt::enter_named_block(const irep_idt &name)
8989
9090/* ******************************************************************\
9191
92- Function: verilog_typecheck_exprt::propagate_type
92+ Function: verilog_typecheck_exprt::assignment_conversion
9393
9494 Inputs:
9595
@@ -99,125 +99,205 @@ Function: verilog_typecheck_exprt::propagate_type
9999
100100\*******************************************************************/
101101
102- void verilog_typecheck_exprt::propagate_type (
103- exprt &expr ,
104- const typet &type )
102+ void verilog_typecheck_exprt::assignment_conversion (
103+ exprt &rhs ,
104+ const typet &lhs_type )
105105{
106- auto &verilog_dest_type = type.get (ID_C_verilog_type);
106+ // 1800-2017 10.9
107+ if (rhs.type ().id () == ID_verilog_assignment_pattern)
108+ {
109+ DATA_INVARIANT (
110+ rhs.id () == ID_verilog_assignment_pattern,
111+ " verilog_assignment_pattern expression expected" );
112+
113+ if (lhs_type.id () == ID_struct)
114+ {
115+ auto &struct_type = to_struct_type (lhs_type);
116+ auto &components = struct_type.components ();
117+
118+ if (
119+ !rhs.operands ().empty () &&
120+ rhs.operands ().front ().id () == ID_member_initializer)
121+ {
122+ exprt::operandst initializers{components.size (), nil_exprt{}};
123+
124+ for (auto &op : rhs.operands ())
125+ {
126+ PRECONDITION (op.id () == ID_member_initializer);
127+ auto member_name = op.get (ID_member_name);
128+ if (!struct_type.has_component (member_name))
129+ {
130+ throw errort ().with_location (op.source_location ())
131+ << " struct does not have a member `" << member_name << " '" ;
132+ }
133+ auto nr = struct_type.component_number (member_name);
134+ auto value = to_unary_expr (op).op ();
135+ // rec. call
136+ assignment_conversion (value, components[nr].type ());
137+ initializers[nr] = std::move (value);
138+ }
139+
140+ // Is every member covered?
141+ for (std::size_t i = 0 ; i < components.size (); i++)
142+ if (initializers[i].is_nil ())
143+ {
144+ throw errort ().with_location (rhs.source_location ())
145+ << " assignment pattern does not assign member `"
146+ << components[i].get_name () << " '" ;
147+ }
148+
149+ rhs = struct_exprt{std::move (initializers), struct_type}
150+ .with_source_location (rhs.source_location ());
151+ }
152+ else
153+ {
154+ if (rhs.operands ().size () != components.size ())
155+ {
156+ throw errort ().with_location (rhs.source_location ())
157+ << " number of expressions does not match number of struct members" ;
158+ }
159+
160+ for (std::size_t i = 0 ; i < components.size (); i++)
161+ {
162+ // rec. call
163+ assignment_conversion (rhs.operands ()[i], components[i].type ());
164+ }
165+
166+ // turn into struct expression
167+ rhs.id (ID_struct);
168+ rhs.type () = lhs_type;
169+ }
170+
171+ return ;
172+ }
173+ else if (lhs_type.id () == ID_array)
174+ {
175+ auto &array_type = to_array_type (lhs_type);
176+ auto &element_type = array_type.element_type ();
177+ auto array_size =
178+ numeric_cast_v<mp_integer>(to_constant_expr (array_type.size ()));
179+
180+ if (array_size != rhs.operands ().size ())
181+ {
182+ throw errort ().with_location (rhs.source_location ())
183+ << " number of expressions does not match number of array elements" ;
184+ }
185+
186+ for (std::size_t i = 0 ; i < array_size; i++)
187+ {
188+ // rec. call
189+ assignment_conversion (rhs.operands ()[i], element_type);
190+ }
191+
192+ // turn into array expression
193+ rhs.id (ID_array);
194+ rhs.type () = lhs_type;
195+ return ;
196+ }
197+ else
198+ {
199+ throw errort ().with_location (rhs.source_location ())
200+ << " cannot convert assignment pattern to '" << to_string (lhs_type)
201+ << ' \' ' ;
202+ }
203+ }
204+
205+ auto original_rhs_type = rhs.type (); // copy
206+
207+ auto &verilog_dest_type = lhs_type.get (ID_C_verilog_type);
107208 if (verilog_dest_type == ID_verilog_enum)
108209 {
109210 // IEEE 1800-2017 6.19.3: "a variable of type enum cannot be directly
110211 // assigned a value that lies outside the enumeration set unless an
111212 // explicit cast is used"
112213 if (
113- expr .type ().get (ID_C_verilog_type) != ID_verilog_enum ||
114- expr .type ().get (ID_C_identifier) != type .get (ID_C_identifier))
214+ rhs .type ().get (ID_C_verilog_type) != ID_verilog_enum ||
215+ rhs .type ().get (ID_C_identifier) != lhs_type .get (ID_C_identifier))
115216 {
116- throw errort ().with_location (expr .source_location ())
217+ throw errort ().with_location (rhs .source_location ())
117218 << " assignment to enum requires enum of the same type, but got "
118- << to_string (expr .type ());
219+ << to_string (rhs .type ());
119220 }
120221 }
121222
122- if (expr .type ()==type )
223+ if (lhs_type == rhs .type ())
123224 return ;
124225
125- if (expr. type (). id () == ID_verilog_sva_sequence)
126- {
127- throw errort{}. with_location (expr. source_location ())
128- << " cannot use SVA sequence as an expression " ;
129- }
130- else if (expr .type ().id () == ID_verilog_sva_property )
226+ // do enum, union and struct decay
227+ enum_decay (rhs);
228+ struct_decay (rhs);
229+ union_decay (rhs) ;
230+
231+ if (rhs .type ().id () == ID_struct || rhs. type (). id () == ID_union )
131232 {
132- throw errort{}.with_location (expr.source_location ())
133- << " cannot use SVA property as an expression" ;
233+ // not decayed, not equal
234+ throw errort ().with_location (rhs.source_location ())
235+ << " failed to convert `" << to_string (original_rhs_type) << " ' to `"
236+ << to_string (lhs_type) << " '" ;
134237 }
135238
136- vtypet vt_from=vtypet (expr.type ());
137- vtypet vt_to =vtypet (type);
239+ // Implements 1800-2017 10.7 and 1800-2017 11.8.3.
138240
139- if (!vt_from.is_other () && !vt_to.is_other () &&
140- expr.has_operands ())
241+ if (
242+ lhs_type.id () == ID_verilog_real || lhs_type.id () == ID_verilog_shortreal ||
243+ lhs_type.id () == ID_verilog_realtime ||
244+ rhs.type ().id () == ID_verilog_real ||
245+ rhs.type ().id () == ID_verilog_shortreal)
141246 {
142- // arithmetic
247+ // from/to real is just a cast
248+ rhs = typecast_exprt::conditional_cast (rhs, lhs_type);
249+ return ;
250+ }
143251
252+ if (rhs.type ().id () == ID_verilog_null)
253+ {
144254 if (
145- expr .id () == ID_plus || expr. id () == ID_minus || expr. id () == ID_mult ||
146- expr .id () == ID_div || expr. id () == ID_unary_minus ||
147- expr .id () == ID_unary_plus )
255+ lhs_type .id () == ID_verilog_chandle ||
256+ lhs_type .id () == ID_verilog_class_type ||
257+ lhs_type .id () == ID_verilog_event )
148258 {
149- if (type.id ()!=ID_bool)
150- {
151- Forall_operands (it, expr)
152- propagate_type (*it, type);
153-
154- expr.type ()=type;
155-
156- return ;
157- }
259+ rhs = typecast_exprt{rhs, lhs_type};
260+ return ;
158261 }
159- else if (expr.id ()==ID_bitand ||
160- expr.id ()==ID_bitor ||
161- expr.id ()==ID_bitnand ||
162- expr.id ()==ID_bitnor ||
163- expr.id ()==ID_bitxor ||
164- expr.id ()==ID_bitxnor ||
165- expr.id ()==ID_bitnot)
166- {
167- Forall_operands (it, expr)
168- propagate_type (*it, type);
262+ }
169263
170- expr.type ()=type;
264+ // "The size of the left-hand side of an assignment forms
265+ // the context for the right-hand expression."
171266
172- if (type.id ()==ID_bool)
173- {
174- if (expr.id ()==ID_bitand)
175- expr.id (ID_and);
176- else if (expr.id ()==ID_bitor)
177- expr.id (ID_or);
178- else if (expr.id ()==ID_bitnand)
179- expr.id (ID_nand);
180- else if (expr.id ()==ID_bitnor)
181- expr.id (ID_nor);
182- else if (expr.id ()==ID_bitxor)
183- expr.id (ID_xor);
184- else if (expr.id ()==ID_bitxnor)
185- expr.id (ID_xnor);
186- else if (expr.id ()==ID_bitnot)
187- expr.id (ID_not);
188- }
267+ // Get the width of LHS and RHS
268+ auto lhs_width = get_width (lhs_type);
269+ auto rhs_width = get_width (rhs.type ());
189270
190- return ;
191- }
192- else if (expr.id ()==ID_if)
271+ if (lhs_width > rhs_width)
272+ {
273+ // Need to enlarge the RHS.
274+ //
275+ // "If needed, extend the size of the right-hand side,
276+ // performing sign extension if, and only if, the type
277+ // of the right-hand side is signed.
278+ if (
279+ (rhs.type ().id () == ID_signedbv ||
280+ rhs.type ().id () == ID_verilog_signedbv) &&
281+ (lhs_type.id () == ID_unsignedbv ||
282+ lhs_type.id () == ID_verilog_unsignedbv))
193283 {
194- if (expr.operands ().size ()==3 )
195- {
196- propagate_type (to_if_expr (expr).true_case (), type);
197- propagate_type (to_if_expr (expr).false_case (), type);
284+ // LHS is unsigned, RHS is signed. Must sign-extend.
285+ auto new_rhs_type = to_bitvector_type (rhs.type ());
286+ new_rhs_type.set_width (numeric_cast_v<std::size_t >(lhs_width));
198287
199- expr.type ()=type;
200- return ;
201- }
202- }
203- else if (expr.id ()==ID_shl) // does not work with shr
204- {
205- // does not work with boolean
206- if (type.id ()!=ID_bool)
207- {
208- if (expr.operands ().size ()==2 )
209- {
210- propagate_type (to_binary_expr (expr).op0 (), type);
211- // not applicable to second operand
288+ downwards_type_propagation (rhs, new_rhs_type);
212289
213- expr.type ()=type;
214- return ;
215- }
216- }
290+ // then cast
291+ rhs = typecast_exprt::conditional_cast (rhs, lhs_type);
217292 }
293+ else
294+ downwards_type_propagation (rhs, lhs_type);
295+ }
296+ else
297+ {
298+ // no need to enlarge
299+ rhs = typecast_exprt::conditional_cast (rhs, lhs_type);
218300 }
219-
220- implicit_typecast (expr, type);
221301}
222302
223303/* ******************************************************************\
@@ -612,7 +692,7 @@ exprt verilog_typecheck_exprt::convert_expr_function_call(
612692 }
613693
614694 for (unsigned i=0 ; i<arguments.size (); i++)
615- propagate_type (arguments[i], parameter_types[i].type ());
695+ assignment_conversion (arguments[i], parameter_types[i].type ());
616696
617697 return std::move (expr);
618698}
0 commit comments