@@ -14,6 +14,8 @@ Author: Daniel Kroening, kroening@kroening.com
1414#include < util/arith_tools.h>
1515#include < util/c_types.h>
1616#include < util/expr_initializer.h>
17+ #include < util/expr_util.h>
18+ #include < util/fresh_symbol.h>
1719#include < util/invariant_utils.h>
1820#include < util/optional.h>
1921#include < util/pointer_offset_size.h>
@@ -203,24 +205,7 @@ void goto_symext::symex_allocate(
203205 code_assignt (lhs, typecast_exprt::conditional_cast (rhs, lhs.type ())));
204206}
205207
206- irep_idt get_symbol (const exprt &src)
207- {
208- if (src.id ()==ID_typecast)
209- return get_symbol (to_typecast_expr (src).op ());
210- else if (src.id ()==ID_address_of)
211- {
212- exprt op=to_address_of_expr (src).object ();
213- if (op.id ()==ID_symbol &&
214- op.get_bool (ID_C_SSA_symbol))
215- return to_ssa_expr (op).get_object_name ();
216- else
217- return irep_idt ();
218- }
219- else
220- return irep_idt ();
221- }
222-
223- void goto_symext::symex_gcc_builtin_va_arg_next (
208+ void goto_symext::symex_gcc_builtin_va_start (
224209 statet &state,
225210 const exprt &lhs,
226211 const side_effect_exprt &code)
@@ -230,42 +215,48 @@ void goto_symext::symex_gcc_builtin_va_arg_next(
230215 if (lhs.is_nil ())
231216 return ; // ignore
232217
233- exprt tmp=code.op0 ();
234- state.rename (tmp, ns); // to allow constant propagation
235- do_simplify (tmp);
236- irep_idt id=get_symbol (tmp);
237-
238- const auto zero = zero_initializer (lhs.type (), code.source_location (), ns);
239- CHECK_RETURN (zero.has_value ());
240- exprt rhs (*zero);
218+ // create an array holding pointers to the parameters, starting with the
219+ // parameter that the operand points to
220+ const exprt &op = skip_typecast (code.op0 ());
221+ // this must be the address of a symbol
222+ const irep_idt &start_parameter =
223+ to_symbol_expr (to_address_of_expr (op).object ()).get_identifier ();
241224
242- if (!id.empty ())
225+ exprt::operandst va_arg_operands;
226+ bool parameter_id_found = false ;
227+ for (auto ¶meter : state.top ().parameter_names )
243228 {
244- // strip last name off id to get function name
245- std::size_t pos=id2string (id).rfind (" ::" );
246- if (pos!=std::string::npos)
247- {
248- irep_idt function_identifier=std::string (id2string (id), 0 , pos);
249- std::string base=id2string (function_identifier)+" ::va_arg" ;
250-
251- if (has_prefix (id2string (id), base))
252- id=base+std::to_string (
253- safe_string2unsigned (
254- std::string (id2string (id), base.size (), std::string::npos))+1 );
255- else
256- id=base+" 0" ;
257-
258- const symbolt *symbol;
259- if (!ns.lookup (id, symbol))
260- {
261- const symbol_exprt symbol_expr (symbol->name , symbol->type );
262- rhs = typecast_exprt::conditional_cast (
263- address_of_exprt (symbol_expr), lhs.type ());
264- }
265- }
266- }
229+ if (!parameter_id_found && parameter == start_parameter)
230+ parameter_id_found = true ;
267231
268- symex_assign (state, code_assignt (lhs, rhs));
232+ va_arg_operands.push_back (typecast_exprt::conditional_cast (
233+ address_of_exprt{ns.lookup (parameter).symbol_expr ()},
234+ pointer_type (empty_typet{})));
235+ }
236+ const std::size_t va_arg_size = va_arg_operands.size ();
237+ array_exprt array{std::move (va_arg_operands),
238+ array_typet{pointer_type (empty_typet{}),
239+ from_integer (va_arg_size, size_type ())}};
240+
241+ symbolt &va_array = get_fresh_aux_symbol (
242+ array.type (),
243+ id2string (state.source .function_id ),
244+ " va_args" ,
245+ state.source .pc ->source_location ,
246+ ns.lookup (state.source .function_id ).mode ,
247+ state.symbol_table );
248+ va_array.value = array;
249+
250+ state.rename (array, ns);
251+ do_simplify (array);
252+ symex_assign (state, code_assignt{va_array.symbol_expr (), std::move (array)});
253+
254+ address_of_exprt rhs{
255+ index_exprt{va_array.symbol_expr (), from_integer (0 , index_type ())}};
256+ state.rename (rhs, ns);
257+ symex_assign (
258+ state,
259+ code_assignt{lhs, typecast_exprt::conditional_cast (rhs, lhs.type ())});
269260}
270261
271262irep_idt get_string_argument_rec (const exprt &src)
0 commit comments