Skip to content

Commit 47f4628

Browse files
Make add_axioms_for_format accept string arguments
Add the possibility to pass argument to the builtin format functtion as strings instead structs with fields.
1 parent e4e6b9f commit 47f4628

File tree

1 file changed

+85
-6
lines changed

1 file changed

+85
-6
lines changed

src/solvers/strings/string_constraint_generator_format.cpp

Lines changed: 85 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -316,8 +316,8 @@ add_axioms_for_format_specifier(
316316
return {res, std::move(return_code.second)};
317317
case format_specifiert::STRING:
318318
{
319-
auto string_expr =
320-
get_string_expr(array_pool, get_arg("string_expr"));
319+
const exprt arg_string = get_arg("string_expr");
320+
const array_string_exprt string_expr = to_array_string_expr(arg_string);
321321
return {std::move(string_expr), {}};
322322
}
323323
case format_specifiert::HASHCODE:
@@ -380,6 +380,69 @@ add_axioms_for_format_specifier(
380380
}
381381
}
382382

383+
/// Deserialize an argument for format from an \p string
384+
exprt format_arg_from_string(
385+
const array_string_exprt &string, const irep_idt &id)
386+
{
387+
if(id == "string_expr")
388+
return string;
389+
if(id == ID_int)
390+
{
391+
// Assume the string has length 4
392+
// (int64)string.content[0] << 48 | (int64) string.content[1] << 32 |
393+
// (int64)string.content[2] << 16 | (int64) string.content[3]
394+
const signedbv_typet type{64};
395+
return bitor_exprt{
396+
bitor_exprt{
397+
shl_exprt{
398+
typecast_exprt(
399+
index_exprt(
400+
string.content(), from_integer(0, string.length().type())),
401+
type),
402+
48},
403+
shl_exprt{
404+
typecast_exprt{
405+
index_exprt{string.content(),
406+
from_integer(1, string.length().type())},
407+
type},
408+
32}
409+
},
410+
bitor_exprt{
411+
shl_exprt{
412+
typecast_exprt(
413+
index_exprt(
414+
string.content(), from_integer(1, string.length().type())),
415+
type),
416+
16},
417+
typecast_exprt{
418+
index_exprt{string.content(),
419+
from_integer(3, string.length().type())},
420+
type}}
421+
};
422+
}
423+
if(id == ID_char)
424+
{
425+
// We assume the string has length exactly 1 and return:
426+
// (unsigned16)string.content[0]
427+
const unsignedbv_typet type{16};
428+
return typecast_exprt{
429+
index_exprt(string.content(), from_integer(0, string.length().type())),
430+
type};
431+
}
432+
if(id == ID_boolean)
433+
{
434+
// We assume the string already corresponds to the result
435+
return string;
436+
}
437+
if(id == ID_float)
438+
{
439+
// Deserialize an int and cast to float
440+
const exprt as_int = format_arg_from_string(string, ID_int);
441+
return typecast_exprt{as_int, floatbv_typet{}};
442+
}
443+
UNHANDLED_CASE;
444+
}
445+
383446
/// Parse `s` and add axioms ensuring the output corresponds to the output of
384447
/// String.format.
385448
/// \param fresh_symbol: generator of fresh symbols
@@ -421,7 +484,7 @@ std::pair<exprt, string_constraintst> add_axioms_for_format(
421484
{
422485
INVARIANT(
423486
arg_count < args.size(), "number of format must match specifiers");
424-
arg = to_struct_expr(args[arg_count++]);
487+
arg = args[arg_count++];
425488
}
426489
else
427490
{
@@ -434,12 +497,28 @@ std::pair<exprt, string_constraintst> add_axioms_for_format(
434497
arg = to_struct_expr(args[fs.index - 1]);
435498
}
436499

500+
std::function<exprt(const irep_idt &)> get_arg;
501+
if(is_refined_string_type(arg.type()))
502+
{
503+
const array_string_exprt string_arg =
504+
get_string_expr(array_pool, arg);
505+
get_arg = [string_arg](const irep_idt &id){
506+
return format_arg_from_string(string_arg, id);
507+
};
508+
}
509+
else
510+
{
511+
INVARIANT(
512+
arg.id() == ID_struct,
513+
"format argument should be a string or a struct");
514+
get_arg = [&](const irep_idt &id){
515+
return get_component_in_struct(to_struct_expr(arg), id);
516+
};
517+
}
437518
auto result = add_axioms_for_format_specifier(
438519
fresh_symbol,
439520
fs,
440-
[&](const irep_idt &id) {
441-
return get_component_in_struct(to_struct_expr(arg), id);
442-
},
521+
get_arg,
443522
index_type,
444523
char_type,
445524
array_pool,

0 commit comments

Comments
 (0)