@@ -172,113 +172,144 @@ abstract_object_pointert abstract_value_objectt::expression_transform(
172172 return transform (expr, operands, environment, ns);
173173}
174174
175- // constant_abstract_value expresion transfrom
176- static abstract_object_pointert try_transform_expr_with_all_rounding_modes (
177- const exprt &expr,
178- const abstract_environmentt &environment,
179- const namespacet &ns);
180-
181- abstract_object_pointert constants_expression_transform (
182- const exprt &expr,
183- const std::vector<abstract_object_pointert> &operands,
184- const abstract_environmentt &environment,
185- const namespacet &ns)
175+ // constant_abstract_value expression transfrom
176+ class constants_evaluator
186177{
187- // try finding the rounding mode. If it's not constant, try
188- // seeing if we can get the same result with all rounding modes
189- auto rounding_mode_symbol =
190- symbol_exprt (CPROVER_PREFIX " rounding_mode" , signedbv_typet (32 ));
191- auto rounding_mode_value = environment.eval (rounding_mode_symbol, ns);
192- auto rounding_mode_constant = rounding_mode_value->to_constant ();
193- if (rounding_mode_constant.is_nil ())
178+ public:
179+ constants_evaluator (
180+ const exprt &e,
181+ const abstract_environmentt &env,
182+ const namespacet &n)
183+ : expression(e), environment(env), ns(n)
194184 {
195- return try_transform_expr_with_all_rounding_modes (expr, environment, ns);
196185 }
197186
198- exprt adjusted_expr = expr;
199- adjust_float_expressions (adjusted_expr, ns);
200- exprt constant_replaced_expr = adjusted_expr;
201- constant_replaced_expr.operands ().clear ();
187+ abstract_object_pointert operator ()() const
188+ {
189+ // try finding the rounding mode. If it's not constant, try
190+ // seeing if we can get the same result with all rounding modes
191+ if (rounding_mode_is_not_set ())
192+ return try_transform_expr_with_all_rounding_modes ();
202193
203- // Two passes over the expression - one for simplification,
204- // another to check if there are any top subexpressions left
205- for (const exprt &op : adjusted_expr.operands ())
194+ return transform ();
195+ }
196+
197+ private:
198+ abstract_object_pointert transform () const
206199 {
207- abstract_object_pointert lhs_abstract_object = environment.eval (op, ns);
208- const exprt &lhs_value = lhs_abstract_object->to_constant ();
209- if (lhs_value.is_nil ())
200+ exprt expr = adjust_expression_for_rounding_mode ();
201+ auto operands = expr.operands ();
202+ expr.operands ().clear ();
203+
204+ // Two passes over the expression - one for simplification,
205+ // another to check if there are any top subexpressions left
206+ for (const exprt &op : operands)
210207 {
208+ auto lhs_value = eval_constant (op);
209+
211210 // do not give up if a sub-expression is not a constant,
212211 // because the whole expression may still be simplified in some cases
213- constant_replaced_expr .operands ().push_back (op );
212+ expr .operands ().push_back (lhs_value. is_nil () ? op : lhs_value );
214213 }
215- else
214+
215+ exprt simplified = simplify_expr (expr, ns);
216+ for (const exprt &op : simplified.operands ())
216217 {
217- // rebuild the operands list with constant versions of
218- // any symbols
219- constant_replaced_expr. operands (). push_back (lhs_value );
218+ auto lhs_value = eval_constant (op);
219+ if (lhs_value. is_nil ())
220+ return top (simplified. type () );
220221 }
222+
223+ // the expression is fully simplified
224+ return environment.abstract_object_factory (
225+ simplified.type (), simplified, ns);
221226 }
222- exprt simplified = simplify_expr (constant_replaced_expr, ns);
223227
224- for ( const exprt &op : simplified. operands ())
228+ abstract_object_pointert try_transform_expr_with_all_rounding_modes () const
225229 {
226- abstract_object_pointert lhs_abstract_object = environment.eval (op, ns);
227- const exprt &lhs_value = lhs_abstract_object->to_constant ();
228- if (lhs_value.is_nil ())
230+ std::vector<abstract_object_pointert> possible_results;
231+ for (auto rounding_mode : all_rounding_modes)
229232 {
230- return environment.abstract_object_factory (
231- simplified.type (), ns, true , false );
233+ auto child_env (environment_with_rounding_mode (rounding_mode));
234+ possible_results.push_back (
235+ constants_evaluator (expression, child_env, ns)());
232236 }
233- }
234237
235- return environment.abstract_object_factory (simplified.type (), simplified, ns);
236- }
238+ auto first = possible_results.front ()->to_constant ();
239+ for (auto const &possible_result : possible_results)
240+ {
241+ auto current = possible_result->to_constant ();
242+ if (current.is_nil () || current != first)
243+ return top (expression.type ());
244+ }
245+ return possible_results.front ();
246+ }
237247
238- static abstract_object_pointert try_transform_expr_with_all_rounding_modes (
239- const exprt &expr,
240- const abstract_environmentt &environment,
241- const namespacet &ns)
242- {
243- const symbol_exprt rounding_mode_symbol =
244- symbol_exprt (CPROVER_PREFIX " rounding_mode" , signedbv_typet (32 ));
245- // NOLINTNEXTLINE (whitespace/braces)
246- auto rounding_modes = std::array<ieee_floatt::rounding_modet, 4 >{
247- // NOLINTNEXTLINE (whitespace/braces)
248- {ieee_floatt::ROUND_TO_EVEN,
249- ieee_floatt::ROUND_TO_ZERO,
250- ieee_floatt::ROUND_TO_MINUS_INF,
251- // NOLINTNEXTLINE (whitespace/braces)
252- ieee_floatt::ROUND_TO_PLUS_INF}};
253- std::vector<abstract_object_pointert> possible_results;
254- for (auto current_rounding_mode : rounding_modes)
248+ abstract_environmentt
249+ environment_with_rounding_mode (ieee_floatt::rounding_modet rm) const
255250 {
256251 abstract_environmentt child_env (environment);
257252 child_env.assign (
258253 rounding_mode_symbol,
259254 child_env.abstract_object_factory (
260255 signedbv_typet (32 ),
261256 from_integer (
262- mp_integer (static_cast <unsigned long >(current_rounding_mode)),
263- signedbv_typet (32 )),
257+ mp_integer (static_cast <unsigned long >(rm)), signedbv_typet (32 )),
264258 ns),
265259 ns);
260+ return child_env;
261+ }
266262
267- // Dummy vector as the called expression_transform() ignores it
268- std::vector<abstract_object_pointert> dummy;
269- possible_results.push_back (
270- constants_expression_transform (expr, dummy, child_env, ns));
263+ exprt adjust_expression_for_rounding_mode () const
264+ {
265+ exprt adjusted_expr = expression;
266+ adjust_float_expressions (adjusted_expr, ns);
267+ return adjusted_expr;
271268 }
272- auto first = possible_results. front ()-> to_constant ();
273- for ( auto const &possible_result : possible_results)
269+
270+ exprt eval_constant ( const exprt &op) const
274271 {
275- auto current = possible_result->to_constant ();
276- if (current.is_nil () || current != first)
277- {
278- return environment.abstract_object_factory (expr.type (), ns, true , false );
279- }
272+ return environment.eval (op, ns)->to_constant ();
280273 }
281- return possible_results.front ();
274+
275+ abstract_object_pointert top (const typet &type) const
276+ {
277+ return environment.abstract_object_factory (type, ns, true , false );
278+ }
279+
280+ bool rounding_mode_is_not_set () const
281+ {
282+ auto rounding_mode = eval_constant (rounding_mode_symbol);
283+ return rounding_mode.is_nil ();
284+ }
285+
286+ const exprt &expression;
287+ const abstract_environmentt &environment;
288+ const namespacet &ns;
289+
290+ static const symbol_exprt rounding_mode_symbol;
291+
292+ using rounding_modes = std::vector<ieee_floatt::rounding_modet>;
293+ static const rounding_modes all_rounding_modes;
294+ };
295+
296+ const symbol_exprt constants_evaluator::rounding_mode_symbol =
297+ symbol_exprt (CPROVER_PREFIX " rounding_mode" , signedbv_typet(32 ));
298+
299+ const constants_evaluator::rounding_modes
300+ constants_evaluator::all_rounding_modes{ieee_floatt::ROUND_TO_EVEN,
301+ ieee_floatt::ROUND_TO_ZERO,
302+ ieee_floatt::ROUND_TO_MINUS_INF,
303+ ieee_floatt::ROUND_TO_PLUS_INF};
304+
305+ abstract_object_pointert constants_expression_transform (
306+ const exprt &expr,
307+ const std::vector<abstract_object_pointert> &operands,
308+ const abstract_environmentt &environment,
309+ const namespacet &ns)
310+ {
311+ auto evaluator = constants_evaluator (expr, environment, ns);
312+ return evaluator ();
282313}
283314
284315// /////////////////////////////////////////////////////
@@ -660,13 +691,7 @@ resolve_values(const abstract_object_sett &new_values)
660691 auto unwrapped_values = unwrap_and_extract_values (new_values);
661692
662693 if (unwrapped_values.size () > value_set_abstract_objectt::max_value_set_size)
663- {
664694 return unwrapped_values.to_interval ();
665- }
666- // if(unwrapped_values.size() == 1)
667- // {
668- // return (*unwrapped_values.begin());
669- // }
670695
671696 const auto &type = new_values.first ()->type ();
672697 auto result = std::make_shared<value_set_abstract_objectt>(type);
0 commit comments