Commit 52c031d1 authored by Julien Signoles's avatar Julien Signoles
Browse files

[interval] improve non-recursive logic functions case

parent 1cf3c003
......@@ -208,7 +208,7 @@ let rec infer t =
let i2 = infer t2 in
Ival.meet i1 i2
| Tapp (li, _, _args) ->
| Tapp (li, _, args) ->
(match li.l_type with
| None -> assert false (* [None] only possible for predicates *)
| Some Linteger ->
......@@ -216,53 +216,47 @@ let rec infer t =
| LBpred _ ->
Ival.zero_or_one
| LBterm t' ->
let i =
if Misc.is_recursive li then
(* 1) Build a system of interval equations that
constrain the solution:
do so by returning a variable when encoutering
a call of a recursive function instead of
performing the usual interval inference
BEWARE: we might be tempted to memoize the
solution for a given function signature
HOWEVER: it cannot be done in a straightforward
manner due to the cases of functions that use
C (global) variables in their definition (as the values of
those variables can change between two function calls). *)
let ieqs = Fixpoint.Ieqs.empty in
let ivar, ieqs, _ = build_ieqs t ieqs [] in
(* 2) Solve it:
The problem is probably undecidable in the general case.
Thus we just look for reasonably precise approximations
without being too computationally expensive:
simply iterate over a finite set of pre-defined intervals.
See [Fixpoint.solve] for details. *)
let chain_of_ivalmax =
[| Integer.one; Integer.billion_one; Integer.max_int64 |]
(* This set can be changed based on experimental evidences,
but it works fine for now. *)
in
let i = Fixpoint.solve ieqs ivar chain_of_ivalmax in
i
else begin
List.iter2
(fun lv arg ->
try
let i = interv_of_typ_containing_interv (infer arg) in
Env.add lv i
with Not_an_integer ->
())
li.l_profile
_args;
let i =
try infer t'
with Not_an_integer -> Ival.inject_range None None
in
List.iter (fun lv -> Env.remove lv) li.l_profile;
i
end
in
i
(* TODO: should not be necessary to distinguish the recursive case.
Stack overflow if not distingued *)
if Misc.is_recursive li then
(* 1) Build a system of interval equations that constrain the
solution: do so by returning a variable when encoutering a call
of a recursive function instead of performing the usual interval
inference BEWARE: we might be tempted to memoize the solution
for a given function signature HOWEVER: it cannot be done in a
straightforward manner due to the cases of functions that use C
(global) variables in their definition (as the values of those
variables can change between two function calls). *)
let ieqs = Fixpoint.Ieqs.empty in
let ivar, ieqs, _ = build_ieqs t ieqs [] in
(* 2) Solve it:
The problem is probably undecidable in the general case.
Thus we just look for reasonably precise approximations
without being too computationally expensive:
simply iterate over a finite set of pre-defined intervals.
See [Fixpoint.solve] for details. *)
let chain_of_ivalmax =
[| Integer.one; Integer.billion_one; Integer.max_int64 |]
(* This set can be changed based on experimental evidences,
but it works fine for now. *)
in
Fixpoint.solve ieqs ivar chain_of_ivalmax
else begin (* non-recursive case *)
(* add the arguments to the context *)
List.iter2
(fun lv arg ->
try
let i = infer arg in
Env.add lv i
with Not_an_integer ->
())
li.l_profile
args;
let i = infer t' in
(* remove arguments from the context *)
List.iter (fun lv -> Env.remove lv) li.l_profile;
i
end
| LBnone ->
Error.not_yet "logic functions with no definition nor reads clause"
| LBreads _ ->
......
......@@ -20,7 +20,7 @@ typedef struct mystruct mystruct;
/*@ logic mystruct t1(mystruct m) = m; */
/*@ logic integer t2(mystruct m) = m.k + m.l; */
// To test function call in other than assert:
// To test function call in other clauses than assert:
/*@ predicate k_pred(integer x) = x > 0; */
/*@ requires k_pred(x); */
void k(int x) {}
......@@ -68,4 +68,4 @@ int main (void) {
/*@ assert f2(d) > 0; */ ;
/*@ assert p_notyet(27); */ ;
/*@ assert f_notyet(27) == 27; */ ;
}
\ No newline at end of file
}
......@@ -32,8 +32,6 @@
[eva] using specification for function __gmpz_clear
[eva:alarm] tests/gmp/functions.c:44: Warning:
function __e_acsl_assert: precondition got status unknown.
[eva:alarm] tests/gmp/functions.c:47: Warning:
function __e_acsl_assert: precondition got status unknown.
[eva:alarm] tests/gmp/functions.c:48: Warning:
accessing uninitialized left-value.
assert \initialized((__e_acsl_mpz_struct *)__gen_e_acsl_f1_tapp_3);
......
......@@ -17,19 +17,19 @@ int __gen_e_acsl_p1(int __gen_e_acsl_x_arg, int __gen_e_acsl_y_arg);
*/
int __gen_e_acsl_p2(int __gen_e_acsl_x_arg, int __gen_e_acsl_y_arg);
int __gen_e_acsl_p2_3(int __gen_e_acsl_x_arg, long __gen_e_acsl_y_arg);
int __gen_e_acsl_p2_2(int __gen_e_acsl_x_arg,
__e_acsl_mpz_struct * __gen_e_acsl_y_arg);
/*@ logic ℤ f1(ℤ x, ℤ y) = x + y;
*/
void __gen_e_acsl_f1_3(__e_acsl_mpz_struct * __retres_arg,
void __gen_e_acsl_f1_4(__e_acsl_mpz_struct * __retres_arg,
__e_acsl_mpz_struct * __gen_e_acsl_x_arg,
__e_acsl_mpz_struct * __gen_e_acsl_y_arg);
void __gen_e_acsl_f1_2(__e_acsl_mpz_struct * __retres_arg,
int __gen_e_acsl_f1_2(int __gen_e_acsl_x_arg, int __gen_e_acsl_y_arg);
void __gen_e_acsl_f1_3(__e_acsl_mpz_struct * __retres_arg,
int __gen_e_acsl_x_arg,
__e_acsl_mpz_struct * __gen_e_acsl_y_arg);
......@@ -126,59 +126,59 @@ int main(void)
}
/*@ assert p2(x, f1(3, 4)); */
{
long __gen_e_acsl_f1_tapp_2;
int __gen_e_acsl_f1_tapp_2;
int __gen_e_acsl_p2_tapp_3;
__gen_e_acsl_f1_tapp_2 = __gen_e_acsl_f1(3,4);
__gen_e_acsl_p2_tapp_3 = __gen_e_acsl_p2_3(x,__gen_e_acsl_f1_tapp_2);
__gen_e_acsl_f1_tapp_2 = __gen_e_acsl_f1_2(3,4);
__gen_e_acsl_p2_tapp_3 = __gen_e_acsl_p2(x,__gen_e_acsl_f1_tapp_2);
__e_acsl_assert(__gen_e_acsl_p2_tapp_3,(char *)"Assertion",
(char *)"main",(char *)"p2(x, f1(3, 4))",47);
}
/*@ assert f1(9, 99999999999999999999999999999) > 0; */
{
__e_acsl_mpz_t __gen_e_acsl__4;
__e_acsl_mpz_t __gen_e_acsl__3;
__e_acsl_mpz_t __gen_e_acsl_f1_tapp_3;
__e_acsl_mpz_t __gen_e_acsl__5;
int __gen_e_acsl_gt_3;
__gmpz_init_set_str(__gen_e_acsl__4,"99999999999999999999999999999",10);
__e_acsl_mpz_t __gen_e_acsl__4;
int __gen_e_acsl_gt_2;
__gmpz_init_set_str(__gen_e_acsl__3,"99999999999999999999999999999",10);
__gmpz_init(__gen_e_acsl_f1_tapp_3);
/*@ assert
Eva: initialization:
\initialized((__e_acsl_mpz_struct *)__gen_e_acsl_f1_tapp_3);
*/
__gen_e_acsl_f1_2((__e_acsl_mpz_struct *)__gen_e_acsl_f1_tapp_3,9,
(__e_acsl_mpz_struct *)__gen_e_acsl__4);
__gmpz_init_set_si(__gen_e_acsl__5,0L);
__gen_e_acsl_gt_3 = __gmpz_cmp((__e_acsl_mpz_struct const *)(__gen_e_acsl_f1_tapp_3),
(__e_acsl_mpz_struct const *)(__gen_e_acsl__5));
__e_acsl_assert(__gen_e_acsl_gt_3 > 0,(char *)"Assertion",(char *)"main",
__gen_e_acsl_f1_3((__e_acsl_mpz_struct *)__gen_e_acsl_f1_tapp_3,9,
(__e_acsl_mpz_struct *)__gen_e_acsl__3);
__gmpz_init_set_si(__gen_e_acsl__4,0L);
__gen_e_acsl_gt_2 = __gmpz_cmp((__e_acsl_mpz_struct const *)(__gen_e_acsl_f1_tapp_3),
(__e_acsl_mpz_struct const *)(__gen_e_acsl__4));
__e_acsl_assert(__gen_e_acsl_gt_2 > 0,(char *)"Assertion",(char *)"main",
(char *)"f1(9, 99999999999999999999999999999) > 0",48);
__gmpz_clear(__gen_e_acsl__4);
__gmpz_clear(__gen_e_acsl__3);
__gmpz_clear(__gen_e_acsl_f1_tapp_3);
__gmpz_clear(__gen_e_acsl__5);
__gmpz_clear(__gen_e_acsl__4);
}
/*@ assert
f1(99999999999999999999999999999, 99999999999999999999999999999) ≡
199999999999999999999999999998;
*/
{
__e_acsl_mpz_t __gen_e_acsl__6;
__e_acsl_mpz_t __gen_e_acsl__5;
__e_acsl_mpz_t __gen_e_acsl_f1_tapp_4;
__e_acsl_mpz_t __gen_e_acsl__7;
__e_acsl_mpz_t __gen_e_acsl__6;
int __gen_e_acsl_eq;
__gmpz_init_set_str(__gen_e_acsl__6,"99999999999999999999999999999",10);
__gmpz_init_set_str(__gen_e_acsl__5,"99999999999999999999999999999",10);
__gmpz_init(__gen_e_acsl_f1_tapp_4);
__gen_e_acsl_f1_3((__e_acsl_mpz_struct *)__gen_e_acsl_f1_tapp_4,
(__e_acsl_mpz_struct *)__gen_e_acsl__6,
(__e_acsl_mpz_struct *)__gen_e_acsl__6);
__gmpz_init_set_str(__gen_e_acsl__7,"199999999999999999999999999998",10);
__gen_e_acsl_f1_4((__e_acsl_mpz_struct *)__gen_e_acsl_f1_tapp_4,
(__e_acsl_mpz_struct *)__gen_e_acsl__5,
(__e_acsl_mpz_struct *)__gen_e_acsl__5);
__gmpz_init_set_str(__gen_e_acsl__6,"199999999999999999999999999998",10);
__gen_e_acsl_eq = __gmpz_cmp((__e_acsl_mpz_struct const *)(__gen_e_acsl_f1_tapp_4),
(__e_acsl_mpz_struct const *)(__gen_e_acsl__7));
(__e_acsl_mpz_struct const *)(__gen_e_acsl__6));
__e_acsl_assert(__gen_e_acsl_eq == 0,(char *)"Assertion",(char *)"main",
(char *)"f1(99999999999999999999999999999, 99999999999999999999999999999) ==\n199999999999999999999999999998",
49);
__gmpz_clear(__gen_e_acsl__6);
__gmpz_clear(__gen_e_acsl__5);
__gmpz_clear(__gen_e_acsl_f1_tapp_4);
__gmpz_clear(__gen_e_acsl__7);
__gmpz_clear(__gen_e_acsl__6);
}
/*@ assert g(x) ≡ x; */
{
......@@ -309,51 +309,58 @@ long __gen_e_acsl_f1(int __gen_e_acsl_x_arg, int __gen_e_acsl_y_arg)
return __retres;
}
void __gen_e_acsl_f1_2(__e_acsl_mpz_struct * __retres_arg,
void __gen_e_acsl_f1_3(__e_acsl_mpz_struct * __retres_arg,
int __gen_e_acsl_x_arg,
__e_acsl_mpz_struct * __gen_e_acsl_y_arg)
{
__e_acsl_mpz_t __gen_e_acsl_y_3;
__e_acsl_mpz_t __gen_e_acsl_y_2;
__e_acsl_mpz_t __gen_e_acsl_x_2;
__e_acsl_mpz_t __gen_e_acsl_add_2;
__gmpz_init_set(__gen_e_acsl_y_2,
(__e_acsl_mpz_struct const *)(__gen_e_acsl_y_arg));
__gmpz_init_set_si(__gen_e_acsl_x_2,(long)__gen_e_acsl_x_arg);
__gmpz_init(__gen_e_acsl_add_2);
__gmpz_add(__gen_e_acsl_add_2,
(__e_acsl_mpz_struct const *)(__gen_e_acsl_x_2),
(__e_acsl_mpz_struct const *)(__gen_e_acsl_y_2));
__gmpz_init_set(__retres_arg,
(__e_acsl_mpz_struct const *)(__gen_e_acsl_add_2));
__gmpz_clear(__gen_e_acsl_y_2);
__gmpz_clear(__gen_e_acsl_x_2);
__gmpz_clear(__gen_e_acsl_add_2);
return;
}
int __gen_e_acsl_f1_2(int __gen_e_acsl_x_arg, int __gen_e_acsl_y_arg)
{
long __retres;
__retres = (int)(__gen_e_acsl_x_arg + (long)__gen_e_acsl_y_arg);
return __retres;
}
void __gen_e_acsl_f1_4(__e_acsl_mpz_struct * __retres_arg,
__e_acsl_mpz_struct * __gen_e_acsl_x_arg,
__e_acsl_mpz_struct * __gen_e_acsl_y_arg)
{
__e_acsl_mpz_t __gen_e_acsl_x_3;
__e_acsl_mpz_t __gen_e_acsl_y_3;
__e_acsl_mpz_t __gen_e_acsl_add_3;
__gmpz_init_set(__gen_e_acsl_x_3,
(__e_acsl_mpz_struct const *)(__gen_e_acsl_x_arg));
__gmpz_init_set(__gen_e_acsl_y_3,
(__e_acsl_mpz_struct const *)(__gen_e_acsl_y_arg));
__gmpz_init_set_si(__gen_e_acsl_x_3,(long)__gen_e_acsl_x_arg);
__gmpz_init(__gen_e_acsl_add_3);
__gmpz_add(__gen_e_acsl_add_3,
(__e_acsl_mpz_struct const *)(__gen_e_acsl_x_3),
(__e_acsl_mpz_struct const *)(__gen_e_acsl_y_3));
__gmpz_init_set(__retres_arg,
(__e_acsl_mpz_struct const *)(__gen_e_acsl_add_3));
__gmpz_clear(__gen_e_acsl_y_3);
__gmpz_clear(__gen_e_acsl_x_3);
__gmpz_clear(__gen_e_acsl_y_3);
__gmpz_clear(__gen_e_acsl_add_3);
return;
}
void __gen_e_acsl_f1_3(__e_acsl_mpz_struct * __retres_arg,
__e_acsl_mpz_struct * __gen_e_acsl_x_arg,
__e_acsl_mpz_struct * __gen_e_acsl_y_arg)
{
__e_acsl_mpz_t __gen_e_acsl_x_4;
__e_acsl_mpz_t __gen_e_acsl_y_4;
__e_acsl_mpz_t __gen_e_acsl_add_4;
__gmpz_init_set(__gen_e_acsl_x_4,
(__e_acsl_mpz_struct const *)(__gen_e_acsl_x_arg));
__gmpz_init_set(__gen_e_acsl_y_4,
(__e_acsl_mpz_struct const *)(__gen_e_acsl_y_arg));
__gmpz_init(__gen_e_acsl_add_4);
__gmpz_add(__gen_e_acsl_add_4,
(__e_acsl_mpz_struct const *)(__gen_e_acsl_x_4),
(__e_acsl_mpz_struct const *)(__gen_e_acsl_y_4));
__gmpz_init_set(__retres_arg,
(__e_acsl_mpz_struct const *)(__gen_e_acsl_add_4));
__gmpz_clear(__gen_e_acsl_x_4);
__gmpz_clear(__gen_e_acsl_y_4);
__gmpz_clear(__gen_e_acsl_add_4);
return;
}
int __gen_e_acsl_p2_2(int __gen_e_acsl_x_arg,
__e_acsl_mpz_struct * __gen_e_acsl_y_arg)
{
......@@ -380,31 +387,6 @@ int __gen_e_acsl_p2_2(int __gen_e_acsl_x_arg,
return __retres;
}
int __gen_e_acsl_p2_3(int __gen_e_acsl_x_arg, long __gen_e_acsl_y_arg)
{
int __retres;
__e_acsl_mpz_t __gen_e_acsl_x_2;
__e_acsl_mpz_t __gen_e_acsl_y_2;
__e_acsl_mpz_t __gen_e_acsl_add_2;
__e_acsl_mpz_t __gen_e_acsl__3;
int __gen_e_acsl_gt_2;
__gmpz_init_set_si(__gen_e_acsl_x_2,(long)__gen_e_acsl_x_arg);
__gmpz_init_set_si(__gen_e_acsl_y_2,__gen_e_acsl_y_arg);
__gmpz_init(__gen_e_acsl_add_2);
__gmpz_add(__gen_e_acsl_add_2,
(__e_acsl_mpz_struct const *)(__gen_e_acsl_x_2),
(__e_acsl_mpz_struct const *)(__gen_e_acsl_y_2));
__gmpz_init_set_si(__gen_e_acsl__3,0L);
__gen_e_acsl_gt_2 = __gmpz_cmp((__e_acsl_mpz_struct const *)(__gen_e_acsl_add_2),
(__e_acsl_mpz_struct const *)(__gen_e_acsl__3));
__retres = __gen_e_acsl_gt_2 > 0;
__gmpz_clear(__gen_e_acsl_x_2);
__gmpz_clear(__gen_e_acsl_y_2);
__gmpz_clear(__gen_e_acsl_add_2);
__gmpz_clear(__gen_e_acsl__3);
return __retres;
}
int __gen_e_acsl_p2(int __gen_e_acsl_x_arg, int __gen_e_acsl_y_arg)
{
int __retres;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment