|
27 | 27 |
|
28 | 28 | /*******************************************************************\ |
29 | 29 |
|
30 | | -Function: verilog_typecheckt::assignment_conversion |
31 | | -
|
32 | | - Inputs: |
33 | | -
|
34 | | - Outputs: |
35 | | -
|
36 | | - Purpose: |
37 | | -
|
38 | | -\*******************************************************************/ |
39 | | - |
40 | | -void verilog_typecheckt::assignment_conversion( |
41 | | - exprt &rhs, |
42 | | - const typet &lhs_type) |
43 | | -{ |
44 | | - // 1800-2017 10.9 |
45 | | - if(rhs.type().id() == ID_verilog_assignment_pattern) |
46 | | - { |
47 | | - DATA_INVARIANT( |
48 | | - rhs.id() == ID_verilog_assignment_pattern, |
49 | | - "verilog_assignment_pattern expression expected"); |
50 | | - |
51 | | - if(lhs_type.id() == ID_struct) |
52 | | - { |
53 | | - auto &struct_type = to_struct_type(lhs_type); |
54 | | - auto &components = struct_type.components(); |
55 | | - |
56 | | - if( |
57 | | - !rhs.operands().empty() && |
58 | | - rhs.operands().front().id() == ID_member_initializer) |
59 | | - { |
60 | | - exprt::operandst initializers{components.size(), nil_exprt{}}; |
61 | | - |
62 | | - for(auto &op : rhs.operands()) |
63 | | - { |
64 | | - PRECONDITION(op.id() == ID_member_initializer); |
65 | | - auto member_name = op.get(ID_member_name); |
66 | | - if(!struct_type.has_component(member_name)) |
67 | | - { |
68 | | - throw errort().with_location(op.source_location()) |
69 | | - << "struct does not have a member `" << member_name << "'"; |
70 | | - } |
71 | | - auto nr = struct_type.component_number(member_name); |
72 | | - auto value = to_unary_expr(op).op(); |
73 | | - // rec. call |
74 | | - assignment_conversion(value, components[nr].type()); |
75 | | - initializers[nr] = std::move(value); |
76 | | - } |
77 | | - |
78 | | - // Is every member covered? |
79 | | - for(std::size_t i = 0; i < components.size(); i++) |
80 | | - if(initializers[i].is_nil()) |
81 | | - { |
82 | | - throw errort().with_location(rhs.source_location()) |
83 | | - << "assignment pattern does not assign member `" |
84 | | - << components[i].get_name() << "'"; |
85 | | - } |
86 | | - |
87 | | - rhs = struct_exprt{std::move(initializers), struct_type} |
88 | | - .with_source_location(rhs.source_location()); |
89 | | - } |
90 | | - else |
91 | | - { |
92 | | - if(rhs.operands().size() != components.size()) |
93 | | - { |
94 | | - throw errort().with_location(rhs.source_location()) |
95 | | - << "number of expressions does not match number of struct members"; |
96 | | - } |
97 | | - |
98 | | - for(std::size_t i = 0; i < components.size(); i++) |
99 | | - { |
100 | | - // rec. call |
101 | | - assignment_conversion(rhs.operands()[i], components[i].type()); |
102 | | - } |
103 | | - |
104 | | - // turn into struct expression |
105 | | - rhs.id(ID_struct); |
106 | | - rhs.type() = lhs_type; |
107 | | - } |
108 | | - |
109 | | - return; |
110 | | - } |
111 | | - else if(lhs_type.id() == ID_array) |
112 | | - { |
113 | | - auto &array_type = to_array_type(lhs_type); |
114 | | - auto &element_type = array_type.element_type(); |
115 | | - auto array_size = |
116 | | - numeric_cast_v<mp_integer>(to_constant_expr(array_type.size())); |
117 | | - |
118 | | - if(array_size != rhs.operands().size()) |
119 | | - { |
120 | | - throw errort().with_location(rhs.source_location()) |
121 | | - << "number of expressions does not match number of array elements"; |
122 | | - } |
123 | | - |
124 | | - for(std::size_t i = 0; i < array_size; i++) |
125 | | - { |
126 | | - // rec. call |
127 | | - assignment_conversion(rhs.operands()[i], element_type); |
128 | | - } |
129 | | - |
130 | | - // turn into array expression |
131 | | - rhs.id(ID_array); |
132 | | - rhs.type() = lhs_type; |
133 | | - return; |
134 | | - } |
135 | | - else |
136 | | - { |
137 | | - throw errort().with_location(rhs.source_location()) |
138 | | - << "cannot convert assignment pattern to '" << to_string(lhs_type) |
139 | | - << '\''; |
140 | | - } |
141 | | - } |
142 | | - |
143 | | - auto original_rhs_type = rhs.type(); // copy |
144 | | - |
145 | | - auto &verilog_dest_type = lhs_type.get(ID_C_verilog_type); |
146 | | - if(verilog_dest_type == ID_verilog_enum) |
147 | | - { |
148 | | - // IEEE 1800-2017 6.19.3: "a variable of type enum cannot be directly |
149 | | - // assigned a value that lies outside the enumeration set unless an |
150 | | - // explicit cast is used" |
151 | | - if( |
152 | | - rhs.type().get(ID_C_verilog_type) != ID_verilog_enum || |
153 | | - rhs.type().get(ID_C_identifier) != lhs_type.get(ID_C_identifier)) |
154 | | - { |
155 | | - throw errort().with_location(rhs.source_location()) |
156 | | - << "assignment to enum requires enum of the same type, but got " |
157 | | - << to_string(rhs.type()); |
158 | | - } |
159 | | - } |
160 | | - |
161 | | - if(lhs_type == rhs.type()) |
162 | | - return; |
163 | | - |
164 | | - // do enum, union and struct decay |
165 | | - enum_decay(rhs); |
166 | | - struct_decay(rhs); |
167 | | - union_decay(rhs); |
168 | | - |
169 | | - if(rhs.type().id() == ID_struct || rhs.type().id() == ID_union) |
170 | | - { |
171 | | - // not decayed, not equal |
172 | | - throw errort().with_location(rhs.source_location()) |
173 | | - << "failed to convert `" << to_string(original_rhs_type) << "' to `" |
174 | | - << to_string(lhs_type) << "'"; |
175 | | - } |
176 | | - |
177 | | - // Implements 1800-2017 10.7 and 1800-2017 11.8.3. |
178 | | - |
179 | | - if( |
180 | | - lhs_type.id() == ID_verilog_real || lhs_type.id() == ID_verilog_shortreal || |
181 | | - lhs_type.id() == ID_verilog_realtime || |
182 | | - rhs.type().id() == ID_verilog_real || |
183 | | - rhs.type().id() == ID_verilog_shortreal) |
184 | | - { |
185 | | - // from/to real is just a cast |
186 | | - rhs = typecast_exprt::conditional_cast(rhs, lhs_type); |
187 | | - return; |
188 | | - } |
189 | | - |
190 | | - if(rhs.type().id() == ID_verilog_null) |
191 | | - { |
192 | | - if( |
193 | | - lhs_type.id() == ID_verilog_chandle || |
194 | | - lhs_type.id() == ID_verilog_class_type || |
195 | | - lhs_type.id() == ID_verilog_event) |
196 | | - { |
197 | | - rhs = typecast_exprt{rhs, lhs_type}; |
198 | | - return; |
199 | | - } |
200 | | - } |
201 | | - |
202 | | - // "The size of the left-hand side of an assignment forms |
203 | | - // the context for the right-hand expression." |
204 | | - |
205 | | - // Get the width of LHS and RHS |
206 | | - auto lhs_width = get_width(lhs_type); |
207 | | - auto rhs_width = get_width(rhs.type()); |
208 | | - |
209 | | - if(lhs_width > rhs_width) |
210 | | - { |
211 | | - // Need to enlarge the RHS. |
212 | | - // |
213 | | - // "If needed, extend the size of the right-hand side, |
214 | | - // performing sign extension if, and only if, the type |
215 | | - // of the right-hand side is signed. |
216 | | - if( |
217 | | - (rhs.type().id() == ID_signedbv || |
218 | | - rhs.type().id() == ID_verilog_signedbv) && |
219 | | - (lhs_type.id() == ID_unsignedbv || |
220 | | - lhs_type.id() == ID_verilog_unsignedbv)) |
221 | | - { |
222 | | - // LHS is unsigned, RHS is signed. Must sign-extend. |
223 | | - auto new_rhs_type = to_bitvector_type(rhs.type()); |
224 | | - new_rhs_type.set_width(numeric_cast_v<std::size_t>(lhs_width)); |
225 | | - |
226 | | - downwards_type_propagation(rhs, new_rhs_type); |
227 | | - |
228 | | - // then cast |
229 | | - rhs = typecast_exprt::conditional_cast(rhs, lhs_type); |
230 | | - } |
231 | | - else |
232 | | - downwards_type_propagation(rhs, lhs_type); |
233 | | - } |
234 | | - else |
235 | | - { |
236 | | - // no need to enlarge |
237 | | - rhs = typecast_exprt::conditional_cast(rhs, lhs_type); |
238 | | - } |
239 | | -} |
240 | | - |
241 | | -/*******************************************************************\ |
242 | | -
|
243 | 30 | Function: verilog_typecheckt::typecheck_port_connection |
244 | 31 |
|
245 | 32 | Inputs: |
|
0 commit comments