Skip to content

Commit 8c3a4f4

Browse files
Make add_axioms_for_format accept string arguments
Add the possibility to pass argument to the builtin format function as strings instead of structs with fields.
1 parent 8020211 commit 8c3a4f4

File tree

1 file changed

+70
-5
lines changed

1 file changed

+70
-5
lines changed

src/solvers/strings/string_constraint_generator_format.cpp

Lines changed: 70 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -303,7 +303,8 @@ add_axioms_for_format_specifier(
303303
return {res, std::move(return_code.second)};
304304
case format_specifiert::STRING:
305305
{
306-
auto string_expr = get_string_expr(array_pool, get_arg("string_expr"));
306+
const exprt arg_string = get_arg("string_expr");
307+
const array_string_exprt string_expr = to_array_string_expr(arg_string);
307308
return {std::move(string_expr), {}};
308309
}
309310
case format_specifiert::HASHCODE:
@@ -365,6 +366,55 @@ add_axioms_for_format_specifier(
365366
}
366367
}
367368

369+
/// Deserialize an argument for format from \p string.
370+
/// \p id should be one of: string_expr, int, char, boolean, float.
371+
/// The primitive values are expected to all be encoded using 4 characters.
372+
static exprt format_arg_from_string(
373+
const array_string_exprt &string, const irep_idt &id)
374+
{
375+
if(id == "string_expr")
376+
return string;
377+
if(id == ID_int)
378+
{
379+
// Assume the string has length 4
380+
// (int64)string.content[0] << 48 | (int64) string.content[1] << 32 |
381+
// (int64)string.content[2] << 16 | (int64) string.content[3]
382+
const signedbv_typet type{64};
383+
return bitor_exprt{
384+
bitor_exprt{
385+
shl_exprt{typecast_exprt{string[0], type}, 48},
386+
shl_exprt{typecast_exprt{string[1], type}, 32}},
387+
bitor_exprt{
388+
shl_exprt{typecast_exprt{string[2], type}, 16},
389+
typecast_exprt{string[3], type}}};
390+
}
391+
if(id == ID_char)
392+
{
393+
// We assume the string has length exactly 4 and ignore the first 3
394+
// (unsigned16)string.content[3]
395+
const unsignedbv_typet type{16};
396+
return typecast_exprt{
397+
index_exprt{string.content(), from_integer(3, string.length().type())},
398+
type};
399+
}
400+
if(id == ID_boolean)
401+
{
402+
// We assume the string has length exactly 4 and ignore the first 3
403+
// (bool)string.content[3]
404+
const c_bool_typet type{8};
405+
return typecast_exprt{
406+
index_exprt{string.content(), from_integer(3, string.length().type())},
407+
type};
408+
}
409+
if(id == ID_float)
410+
{
411+
// Deserialize an int and cast to float
412+
const exprt as_int = format_arg_from_string(string, ID_int);
413+
return typecast_exprt{as_int, floatbv_typet{}};
414+
}
415+
UNHANDLED_CASE;
416+
}
417+
368418
/// Parse `s` and add axioms ensuring the output corresponds to the output of
369419
/// String.format.
370420
/// \param fresh_symbol: generator of fresh symbols
@@ -406,7 +456,7 @@ std::pair<exprt, string_constraintst> add_axioms_for_format(
406456
{
407457
INVARIANT(
408458
arg_count < args.size(), "number of format must match specifiers");
409-
arg = to_struct_expr(args[arg_count++]);
459+
arg = args[arg_count++];
410460
}
411461
else
412462
{
@@ -419,12 +469,27 @@ std::pair<exprt, string_constraintst> add_axioms_for_format(
419469
arg = to_struct_expr(args[fs.index - 1]);
420470
}
421471

472+
std::function<exprt(const irep_idt &)> get_arg;
473+
if (is_refined_string_type(arg.type())) {
474+
const array_string_exprt string_arg =
475+
get_string_expr(array_pool, arg);
476+
get_arg = [string_arg](const irep_idt &id) {
477+
return format_arg_from_string(string_arg, id);
478+
};
479+
}
480+
else
481+
{
482+
INVARIANT(
483+
arg.id() == ID_struct,
484+
"format argument should be a string or a struct");
485+
get_arg = [&](const irep_idt &id) {
486+
return get_component_in_struct(to_struct_expr(arg), id);
487+
};
488+
}
422489
auto result = add_axioms_for_format_specifier(
423490
fresh_symbol,
424491
fs,
425-
[&](const irep_idt &id) {
426-
return get_component_in_struct(to_struct_expr(arg), id);
427-
},
492+
get_arg,
428493
index_type,
429494
char_type,
430495
array_pool,

0 commit comments

Comments
 (0)