From ceb0444f7fe17be11b988bf752ee2f5c5dbd4532 Mon Sep 17 00:00:00 2001 From: Peter Schrammel Date: Sat, 23 Apr 2016 16:27:48 +0100 Subject: [PATCH 01/82] all commits of old branch --- regression/modular/Makefile | 20 + regression/modular/cex-struct1/main.c | 180 +++++ regression/modular/cex-struct1/test.desc | 6 + regression/modular/cex-struct2/main.c | 22 + regression/modular/cex-struct2/test.desc | 6 + regression/modular/cex-struct3/main.c | 23 + regression/modular/cex-struct3/test.desc | 6 + regression/modular/cex1/main.c | 15 + regression/modular/cex1/test.desc | 6 + regression/modular/cex10/main.c | 21 + regression/modular/cex10/test.desc | 6 + regression/modular/cex11/main.c | 35 + regression/modular/cex12/main.c | 40 + regression/modular/cex13/main.c | 16 + regression/modular/cex13/main.c~ | 16 + regression/modular/cex13/test.desc | 6 + regression/modular/cex2/main.c | 16 + regression/modular/cex2/test.desc | 6 + regression/modular/cex3/main.c | 16 + regression/modular/cex3/test.desc | 6 + regression/modular/cex4/main.c | 11 + regression/modular/cex4/test.desc | 6 + regression/modular/cex5/main.c | 15 + regression/modular/cex5/test.desc | 6 + regression/modular/cex6/main.c | 20 + regression/modular/cex6/test.desc | 6 + regression/modular/cex7/main.c | 15 + regression/modular/cex7/test.desc | 6 + regression/modular/cex8/main.c | 20 + regression/modular/cex8/test.desc | 6 + regression/modular/cex9/main.c | 24 + regression/modular/cex9/test.desc | 6 + regression/modular/nocex1/main.c | 15 + regression/modular/nocex1/test.desc | 6 + regression/modular/nocex2/main.c | 16 + regression/modular/nocex2/test.desc | 6 + regression/modular/nocex3/main.c | 18 + regression/modular/nocex3/test.desc | 6 + regression/modular/nocex4/main.c | 20 + regression/modular/nocex4/test.desc | 6 + regression/modular/nocex5/main.c | 30 + regression/modular/nocex5/test.desc | 6 + regression/modular/nocex6/main.c | 15 + regression/modular/nocex6/test.desc | 6 + regression/modular/nocex7/main.c | 34 + regression/modular/nocex7/test.desc | 6 + regression/modular/nocex8/main.c | 16 + regression/modular/nocex8/test.desc | 6 + src/2ls/cover_goals_ext.cpp | 123 ++-- src/2ls/cover_goals_ext.h | 17 +- src/domains/domain.h | 2 + src/domains/ssa_analyzer.cpp | 66 +- src/domains/ssa_analyzer.h | 16 +- src/domains/strategy_solver_base.h | 8 +- src/domains/strategy_solver_binsearch.cpp | 20 +- src/domains/strategy_solver_binsearch.h | 5 +- src/domains/strategy_solver_binsearch2.cpp | 13 +- src/domains/strategy_solver_binsearch2.h | 5 +- src/domains/strategy_solver_binsearch3.cpp | 12 +- src/domains/strategy_solver_binsearch3.h | 2 +- src/domains/strategy_solver_enumeration.cpp | 16 +- src/domains/strategy_solver_enumeration.h | 11 +- src/domains/strategy_solver_equality.cpp | 7 +- src/domains/strategy_solver_equality.h | 5 +- src/domains/template_generator_base.h | 4 +- src/domains/tpolyhedra_domain.cpp | 122 ++- src/domains/tpolyhedra_domain.h | 18 +- src/domains/util.cpp | 6 +- src/solver/Makefile | 2 + src/solver/summary.h | 26 + src/solver/summary_db.h | 2 + src/ssa/local_ssa.cpp | 106 ++- src/ssa/local_ssa.h | 20 +- src/ssa/ssa_db.cpp | 9 + src/ssa/ssa_domain.cpp | 2 +- src/ssa/ssa_inliner.cpp | 775 +++++++++++++------- src/ssa/ssa_inliner.h | 108 ++- src/ssa/ssa_object.cpp | 12 + 78 files changed, 1895 insertions(+), 466 deletions(-) create mode 100644 regression/modular/Makefile create mode 100644 regression/modular/cex-struct1/main.c create mode 100644 regression/modular/cex-struct1/test.desc create mode 100644 regression/modular/cex-struct2/main.c create mode 100644 regression/modular/cex-struct2/test.desc create mode 100644 regression/modular/cex-struct3/main.c create mode 100644 regression/modular/cex-struct3/test.desc create mode 100644 regression/modular/cex1/main.c create mode 100644 regression/modular/cex1/test.desc create mode 100644 regression/modular/cex10/main.c create mode 100644 regression/modular/cex10/test.desc create mode 100644 regression/modular/cex11/main.c create mode 100644 regression/modular/cex12/main.c create mode 100644 regression/modular/cex13/main.c create mode 100644 regression/modular/cex13/main.c~ create mode 100644 regression/modular/cex13/test.desc create mode 100644 regression/modular/cex2/main.c create mode 100644 regression/modular/cex2/test.desc create mode 100644 regression/modular/cex3/main.c create mode 100644 regression/modular/cex3/test.desc create mode 100644 regression/modular/cex4/main.c create mode 100644 regression/modular/cex4/test.desc create mode 100644 regression/modular/cex5/main.c create mode 100644 regression/modular/cex5/test.desc create mode 100644 regression/modular/cex6/main.c create mode 100644 regression/modular/cex6/test.desc create mode 100644 regression/modular/cex7/main.c create mode 100644 regression/modular/cex7/test.desc create mode 100644 regression/modular/cex8/main.c create mode 100644 regression/modular/cex8/test.desc create mode 100644 regression/modular/cex9/main.c create mode 100644 regression/modular/cex9/test.desc create mode 100644 regression/modular/nocex1/main.c create mode 100644 regression/modular/nocex1/test.desc create mode 100644 regression/modular/nocex2/main.c create mode 100644 regression/modular/nocex2/test.desc create mode 100644 regression/modular/nocex3/main.c create mode 100644 regression/modular/nocex3/test.desc create mode 100644 regression/modular/nocex4/main.c create mode 100644 regression/modular/nocex4/test.desc create mode 100644 regression/modular/nocex5/main.c create mode 100644 regression/modular/nocex5/test.desc create mode 100644 regression/modular/nocex6/main.c create mode 100644 regression/modular/nocex6/test.desc create mode 100644 regression/modular/nocex7/main.c create mode 100644 regression/modular/nocex7/test.desc create mode 100644 regression/modular/nocex8/main.c create mode 100644 regression/modular/nocex8/test.desc diff --git a/regression/modular/Makefile b/regression/modular/Makefile new file mode 100644 index 000000000..19c23b682 --- /dev/null +++ b/regression/modular/Makefile @@ -0,0 +1,20 @@ +default: tests.log + +FLAGS = --verbosity 10 --spurious-check concrete + +test: + @../test.pl -c "../../../src/summarizer/summarizer $(FLAGS)" + +tests.log: ../test.pl + @../test.pl -c "../../../src/summarizer/summarizer $(FLAGS)" + +show: + @for dir in *; do \ + if [ -d "$$dir" ]; then \ + vim -o "$$dir/*.c" "$$dir/*.out"; \ + fi; \ + done; + +clean: + @rm -f *.log + @for dir in *; do rm -f $$dir/*.out; done; diff --git a/regression/modular/cex-struct1/main.c b/regression/modular/cex-struct1/main.c new file mode 100644 index 000000000..a9a9139fa --- /dev/null +++ b/regression/modular/cex-struct1/main.c @@ -0,0 +1,180 @@ + +#include +#include + +typedef struct{ int x; int y; int z; int w; int p; int q; int a; } foo; + +foo func_1(foo f); +foo func_2(foo f); +foo func_3(foo f); +foo func_4(foo f); +foo func_5(foo f); +foo func_6(foo f); +foo func_7(foo f); +foo func_8(foo f); + +foo func_1(foo f) +{ + f.x = 23 + 12; + f.x = 4 - 1; + if(f.w > f.x) {f.q = 21 * f.z;} else {f.q = 4 / f.p;} + f.a = f.a + 1; + f.z = f.y * f.x; + f.x = 11 - f.p; + f.y = 1 - 19; + f.y = f.w - 14; + return f; +} + +/**********************************************************************/ + +foo func_2(foo f) +{ + if(f.y < f.q) {f.x = f.w / 24;} else {f.w = 18 / 3;} + f.w = f.p * f.q; + if(f.q < 6) {f.y = 25 - f.x;} else {f.q = f.y / f.w;} + f.a = f.a + 1; + if(f.x <= f.x) {f.z = 9 + f.x;} else {f.y = 1 + f.x;} + f.x = f.q / 25; + f.w = f.x - f.y; + f.x = 9 + f.y; + f.y = 24 - 2; + f.w = 10 + f.z; + return f; +} + +/**********************************************************************/ + +foo func_3(foo f) +{ + if(f.p == 12) {f.w = 22 + 7;} else {f.p = f.x + f.q;} + f.y = f.p + f.x; + f.w = 6 * f.y; + if(f.z <= 20) {f.q = 21 / 24;} else {f.w = f.q * f.w;} + f.w = f.y - 10; + f.q = 2 - 20; + f.x = f.x / 10; + f.p = 16 * 23; + f.w = 18 - 13; + f.w = f.p - 2; + f.z = 7 + f.w; + f.a = f.a + 1; + f.x = 16 / f.x; + return f; +} + +/**********************************************************************/ + +foo func_4(foo f) +{ + f.w = f.y + f.y; + f.q = 18 * 13; + f.y = f.z * f.y; + f.x = 1 * 25; + f.y = 4 / f.q; + f.x = f.p / 9; + f.a = f.a + 1; + if(f.x >= 7) {f.q = f.q / 8;} else {if(f.x < 9) {f.z = 16 + f.p;} else {f.x = f.w - 18;}} + f.y = 2 * 4; + f.q = 16 + f.x; + f.q = 16 * f.w; + if(f.w > 14) {f.q = 20 + 20;} else {f.x = 25 + 9;} + return f; +} + +/**********************************************************************/ + +foo func_5(foo f) +{ + f.a = f.a + 1; + if(f.x == 13) {f.p = 13 * f.x;} else {f.w = f.q / f.w;} + f.y = 21 * f.x; + f.p = 4 * 25; + if(f.p >= 24) {f.x = 11 * 6;} else {f.p = 9 * f.p;} + f.x = 3 + f.z; + f.x = f.x + 22; + f.z = 8 / 8; + f.q = 18 + f.x; + f.x = 5 * f.z; + f.y = f.w + f.w; + return f; +} + +/**********************************************************************/ + +foo func_6(foo f) +{ + f.y = f.w / f.q; + f.p = f.x + 8; + f.a = f.a + 1; + f.z = f.w * 20; + if(f.x < f.p) {f.x = f.z + 2;} else {f.y = f.y * f.x;} + if(f.y <= f.y) {f.q = f.y * f.w;} else {f.q = f.w - 13;} + f.p = 9 + f.y; + f.q = f.y / 14; + f.p = 18 / f.z; + if(f.w < f.p) {f.w = 17 * f.p;} else {f.p = f.y - 10;} + f.p = 3 / 14; + f.q = 10 - f.w; + if(f.y > 12) {f.z = f.q - 24;} else {f.x = f.z / 17;} + return f; +} + +/**********************************************************************/ + +foo func_7(foo f) +{ + f.q = f.q * 23; + f.w = 25 - f.w; + if(f.q < f.y) {f.w = 21 + f.z;} else {f.p = 16 - 1;} + f.y = f.z * f.z; + f.x = 5 * 16; + f.x = 11 + f.x; + f.z = f.y - f.y; + f.q = 11 - f.z; + f.a = f.a + 1; + return f; +} + +/**********************************************************************/ + +foo func_8(foo f) +{ + f.w = f.y - 15; + f.q = f.x + f.z; + f.y = 5 / 1; + if(f.q < 3) {f.p = 6 * f.x; } else {f.w = 8 + 21;} + f.p = 19 / f.p; + f.z = 4 / f.z; + if(f.x < 12) {f.p = f.y - 4; } else {f.x = 15 + 2;} + f.q = 19 / f.w; + if(f.p > 24) {f.z = 5 / 9;} else {f.w = f.x + f.z;} + f.z = f.z + 1; + f.a = f.a + 1; + if(f.z > f.y) {f.y = f.y + f.x;} else {f.y = 13 - 18;} + return f; +} + + +/**********************************************************************/ + +int main() +{ + foo f0, f1, f2, f3, f4, f5, f6, f7, f8; + +// __CPROVER_assume((f0.a >= 0) && (f0.a <= 9)); + f0.a = 0; + + f1 = func_1(f0); +/* f2 = func_2(f1); + f3 = func_3(f2); + f4 = func_4(f3); + f5 = func_5(f4); + f6 = func_6(f5); + f7 = func_7(f6); + f8 = func_8(f7);*/ + + assert(/*(f8.x + f8.y + f8.z + f8.w + f8.p + f8.q > 0) &&*/ (f1.a != 1)); // unsafe assertion + + return 0; +} diff --git a/regression/modular/cex-struct1/test.desc b/regression/modular/cex-struct1/test.desc new file mode 100644 index 000000000..429367b44 --- /dev/null +++ b/regression/modular/cex-struct1/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--havoc +^EXIT=10$ +^SIGNAL=0$ +^VERIFICATION FAILED$ diff --git a/regression/modular/cex-struct2/main.c b/regression/modular/cex-struct2/main.c new file mode 100644 index 000000000..a5d7032f4 --- /dev/null +++ b/regression/modular/cex-struct2/main.c @@ -0,0 +1,22 @@ + +#include +#include + +typedef struct{ int a; } foo; + +foo func_1(foo f) +{ + f.a = f.a + 1; + return f; +} + +int main() +{ + foo f0, f1; + f0.a = 0; + + f1 = func_1(f0); + + assert((f1.a) != 1); + return 0; +} diff --git a/regression/modular/cex-struct2/test.desc b/regression/modular/cex-struct2/test.desc new file mode 100644 index 000000000..429367b44 --- /dev/null +++ b/regression/modular/cex-struct2/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--havoc +^EXIT=10$ +^SIGNAL=0$ +^VERIFICATION FAILED$ diff --git a/regression/modular/cex-struct3/main.c b/regression/modular/cex-struct3/main.c new file mode 100644 index 000000000..1715861bf --- /dev/null +++ b/regression/modular/cex-struct3/main.c @@ -0,0 +1,23 @@ + +#include +#include + +typedef struct{ int x; int a; } foo; + +foo func_1(foo f) +{ + f.a = f.a + 1; + f.x = f.a; + return f; +} + +int main() +{ + foo f0, f1; + f0.a = 0; + + f1 = func_1(f0); + assert(f1.a != 1); // unsafe assertion + + return 0; +} diff --git a/regression/modular/cex-struct3/test.desc b/regression/modular/cex-struct3/test.desc new file mode 100644 index 000000000..429367b44 --- /dev/null +++ b/regression/modular/cex-struct3/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--havoc +^EXIT=10$ +^SIGNAL=0$ +^VERIFICATION FAILED$ diff --git a/regression/modular/cex1/main.c b/regression/modular/cex1/main.c new file mode 100644 index 000000000..53451cf50 --- /dev/null +++ b/regression/modular/cex1/main.c @@ -0,0 +1,15 @@ +#include + +int foo(int x) +{ + assert(x>5); +} + +int main(int argc, char** argv) +{ + int y; + if(y<=0) foo(y); + + return 0; +} + diff --git a/regression/modular/cex1/test.desc b/regression/modular/cex1/test.desc new file mode 100644 index 000000000..429367b44 --- /dev/null +++ b/regression/modular/cex1/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--havoc +^EXIT=10$ +^SIGNAL=0$ +^VERIFICATION FAILED$ diff --git a/regression/modular/cex10/main.c b/regression/modular/cex10/main.c new file mode 100644 index 000000000..5908a46cc --- /dev/null +++ b/regression/modular/cex10/main.c @@ -0,0 +1,21 @@ +#include + +int error(int k){ + assert(k != 3); +} + +int inc(int x){ + return (x+1); +}; + +int main(){ + int num = 0; + num = inc(num); + num = inc(num); + num = inc(num); + error(num); + return 0; +} + + + diff --git a/regression/modular/cex10/test.desc b/regression/modular/cex10/test.desc new file mode 100644 index 000000000..429367b44 --- /dev/null +++ b/regression/modular/cex10/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--havoc +^EXIT=10$ +^SIGNAL=0$ +^VERIFICATION FAILED$ diff --git a/regression/modular/cex11/main.c b/regression/modular/cex11/main.c new file mode 100644 index 000000000..30592979f --- /dev/null +++ b/regression/modular/cex11/main.c @@ -0,0 +1,35 @@ + +// for complete to work faster: introduce a function call to modify an irrelevant variable + +#include + +unsigned nondet_int(); + +int foo(int a){ + + a = a + (2*a) + (3*a); + a = a - (2*a) - (3*a); + a = -a; + + return a; + +} + +int main(){ + + int x; + int y; + + __CPROVER_assume(x > 0 and x < 10); + + while(x < 10000){ + x = x + 1; + y = foo(y); + + if(nondet_int()) + break; + } + + assert(x < 10001); + +} diff --git a/regression/modular/cex12/main.c b/regression/modular/cex12/main.c new file mode 100644 index 000000000..dbebaeb45 --- /dev/null +++ b/regression/modular/cex12/main.c @@ -0,0 +1,40 @@ + +// for concrete to work faster: a false assertion such that all counterexamples are valid counterexamples + +#include + +unsigned nondet_int(); + +int bar(int x){ + if((x > 0) || (x <= 0)) + assert(0); + + return 0; +} + +int inc_or_dec(int x){ + if(nondet_int()) + x = x + 1; + else + x = x - 1; + + return x; +} + +int main(){ + + int k; + int counter = 0 + + while(counter < 100000){ + k = inc_or_dec(k); + if(nondet_int()) + break; + counter++; + } + + bar(k); + + return 0; + +} diff --git a/regression/modular/cex13/main.c b/regression/modular/cex13/main.c new file mode 100644 index 000000000..242217d45 --- /dev/null +++ b/regression/modular/cex13/main.c @@ -0,0 +1,16 @@ + +#include + +void foo(int x) +{ + assert(x==5); +} + +int main(int argc, char** argv) +{ + int y = 4; + foo(y); + + return 0; +} + diff --git a/regression/modular/cex13/main.c~ b/regression/modular/cex13/main.c~ new file mode 100644 index 000000000..cd18d78fc --- /dev/null +++ b/regression/modular/cex13/main.c~ @@ -0,0 +1,16 @@ + +#include + +void foo(int x) +{ + assert(x!=5); +} + +int main(int argc, char** argv) +{ + int y = 5; + foo(y); + + return 0; +} + diff --git a/regression/modular/cex13/test.desc b/regression/modular/cex13/test.desc new file mode 100644 index 000000000..429367b44 --- /dev/null +++ b/regression/modular/cex13/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--havoc +^EXIT=10$ +^SIGNAL=0$ +^VERIFICATION FAILED$ diff --git a/regression/modular/cex2/main.c b/regression/modular/cex2/main.c new file mode 100644 index 000000000..cd18d78fc --- /dev/null +++ b/regression/modular/cex2/main.c @@ -0,0 +1,16 @@ + +#include + +void foo(int x) +{ + assert(x!=5); +} + +int main(int argc, char** argv) +{ + int y = 5; + foo(y); + + return 0; +} + diff --git a/regression/modular/cex2/test.desc b/regression/modular/cex2/test.desc new file mode 100644 index 000000000..429367b44 --- /dev/null +++ b/regression/modular/cex2/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--havoc +^EXIT=10$ +^SIGNAL=0$ +^VERIFICATION FAILED$ diff --git a/regression/modular/cex3/main.c b/regression/modular/cex3/main.c new file mode 100644 index 000000000..952a3137b --- /dev/null +++ b/regression/modular/cex3/main.c @@ -0,0 +1,16 @@ + +#include + +int foo(int x) +{ + assert(x!=5); +} + +int main(int argc, char** argv) +{ + int y; + if(y > 0) foo(y); + + return 0; +} + diff --git a/regression/modular/cex3/test.desc b/regression/modular/cex3/test.desc new file mode 100644 index 000000000..429367b44 --- /dev/null +++ b/regression/modular/cex3/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--havoc +^EXIT=10$ +^SIGNAL=0$ +^VERIFICATION FAILED$ diff --git a/regression/modular/cex4/main.c b/regression/modular/cex4/main.c new file mode 100644 index 000000000..8463fe610 --- /dev/null +++ b/regression/modular/cex4/main.c @@ -0,0 +1,11 @@ + +#include + +int main(int argc, char** argv) +{ + int y = 5; + assert(y != 5); + + return 0; +} + diff --git a/regression/modular/cex4/test.desc b/regression/modular/cex4/test.desc new file mode 100644 index 000000000..429367b44 --- /dev/null +++ b/regression/modular/cex4/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--havoc +^EXIT=10$ +^SIGNAL=0$ +^VERIFICATION FAILED$ diff --git a/regression/modular/cex5/main.c b/regression/modular/cex5/main.c new file mode 100644 index 000000000..0eabc5796 --- /dev/null +++ b/regression/modular/cex5/main.c @@ -0,0 +1,15 @@ +#include + +int foo(int x) +{ + assert(x>5); +} + +int main(int argc, char** argv) +{ + int y; + if(y>0) foo(y); + + return 0; +} + diff --git a/regression/modular/cex5/test.desc b/regression/modular/cex5/test.desc new file mode 100644 index 000000000..429367b44 --- /dev/null +++ b/regression/modular/cex5/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--havoc +^EXIT=10$ +^SIGNAL=0$ +^VERIFICATION FAILED$ diff --git a/regression/modular/cex6/main.c b/regression/modular/cex6/main.c new file mode 100644 index 000000000..80de0138d --- /dev/null +++ b/regression/modular/cex6/main.c @@ -0,0 +1,20 @@ + +#include + +void foo(int x) +{ + assert(x<1); +} + +int main() +{ + int y; + + while(y < 2){ + y++; + foo(y); + } + + return 0; +} + diff --git a/regression/modular/cex6/test.desc b/regression/modular/cex6/test.desc new file mode 100644 index 000000000..429367b44 --- /dev/null +++ b/regression/modular/cex6/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--havoc +^EXIT=10$ +^SIGNAL=0$ +^VERIFICATION FAILED$ diff --git a/regression/modular/cex7/main.c b/regression/modular/cex7/main.c new file mode 100644 index 000000000..309c06dd9 --- /dev/null +++ b/regression/modular/cex7/main.c @@ -0,0 +1,15 @@ + +#include + +int main(int argc, char** argv) +{ + int y = 1; + + while(y<30){ + y++; + assert(y<5); + } + + return 0; +} + diff --git a/regression/modular/cex7/test.desc b/regression/modular/cex7/test.desc new file mode 100644 index 000000000..696fce3b5 --- /dev/null +++ b/regression/modular/cex7/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--havoc --unwind 3 +^EXIT=10$ +^SIGNAL=0$ +^VERIFICATION FAILED$ diff --git a/regression/modular/cex8/main.c b/regression/modular/cex8/main.c new file mode 100644 index 000000000..3bb7e471c --- /dev/null +++ b/regression/modular/cex8/main.c @@ -0,0 +1,20 @@ +#include + +int error(int k){ + assert(k != 2); +} + +int inc(int x){ + return (x+1); +}; + +int main(){ + int num = 0; + num = inc(num); + num = inc(num); + error(num); + return 0; +} + + + diff --git a/regression/modular/cex8/test.desc b/regression/modular/cex8/test.desc new file mode 100644 index 000000000..429367b44 --- /dev/null +++ b/regression/modular/cex8/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--havoc +^EXIT=10$ +^SIGNAL=0$ +^VERIFICATION FAILED$ diff --git a/regression/modular/cex9/main.c b/regression/modular/cex9/main.c new file mode 100644 index 000000000..675f72f26 --- /dev/null +++ b/regression/modular/cex9/main.c @@ -0,0 +1,24 @@ +#include + +int error(int k){ + assert(k != 2); +} + +int inc(int x){ + return (x+1); +}; + +int inc_copy(int x){ + return (x+1); +}; + +int main(){ + int num = 0; + num = inc_copy(num); + num = inc(num); + error(num); + return 0; +} + + + diff --git a/regression/modular/cex9/test.desc b/regression/modular/cex9/test.desc new file mode 100644 index 000000000..429367b44 --- /dev/null +++ b/regression/modular/cex9/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--havoc +^EXIT=10$ +^SIGNAL=0$ +^VERIFICATION FAILED$ diff --git a/regression/modular/nocex1/main.c b/regression/modular/nocex1/main.c new file mode 100644 index 000000000..6faa3e65d --- /dev/null +++ b/regression/modular/nocex1/main.c @@ -0,0 +1,15 @@ +#include + +int foo(int x) +{ + assert(x>5); +} + +int main(int argc, char** argv) +{ + int y; + if(y>10) foo(y); + + return 0; +} + diff --git a/regression/modular/nocex1/test.desc b/regression/modular/nocex1/test.desc new file mode 100644 index 000000000..dc053e6ab --- /dev/null +++ b/regression/modular/nocex1/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--havoc +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ diff --git a/regression/modular/nocex2/main.c b/regression/modular/nocex2/main.c new file mode 100644 index 000000000..100ddaec6 --- /dev/null +++ b/regression/modular/nocex2/main.c @@ -0,0 +1,16 @@ + +#include + +void foo(int x) +{ + assert(x==5); +} + +int main(int argc, char** argv) +{ + int y = 5; + foo(y); + + return 0; +} + diff --git a/regression/modular/nocex2/test.desc b/regression/modular/nocex2/test.desc new file mode 100644 index 000000000..dc053e6ab --- /dev/null +++ b/regression/modular/nocex2/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--havoc +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ diff --git a/regression/modular/nocex3/main.c b/regression/modular/nocex3/main.c new file mode 100644 index 000000000..257e8fc7a --- /dev/null +++ b/regression/modular/nocex3/main.c @@ -0,0 +1,18 @@ + +#include + +int bar(){ + return 1; +} + +void foo(int x) { + assert(x != 5); +} + +int main() { + int y = bar(); + foo(y); + return 0; +} + + diff --git a/regression/modular/nocex3/test.desc b/regression/modular/nocex3/test.desc new file mode 100644 index 000000000..dc053e6ab --- /dev/null +++ b/regression/modular/nocex3/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--havoc +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ diff --git a/regression/modular/nocex4/main.c b/regression/modular/nocex4/main.c new file mode 100644 index 000000000..4e96e8e89 --- /dev/null +++ b/regression/modular/nocex4/main.c @@ -0,0 +1,20 @@ + +#include + +int bar(int k){ + return (k+1); +} + +void foo(int x) { + x = bar(x); + assert(x>5); +} + +int main() { + int y; + __CPROVER_assume(y<100000); + if(y > 10) foo(y); + return 0; +} + + diff --git a/regression/modular/nocex4/test.desc b/regression/modular/nocex4/test.desc new file mode 100644 index 000000000..dc053e6ab --- /dev/null +++ b/regression/modular/nocex4/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--havoc +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ diff --git a/regression/modular/nocex5/main.c b/regression/modular/nocex5/main.c new file mode 100644 index 000000000..b225c7ce8 --- /dev/null +++ b/regression/modular/nocex5/main.c @@ -0,0 +1,30 @@ + +#include + +int foobar(int a){ + int i; + if(i < a) + return i+a; + else + return i-a; +} + +int bar(int k){ + return (k+1); +} + +void foo(int x, int s) { + int m; + s = foobar(m); + x = bar(x); + assert(x>5); +} + +int main() { + int y,k; + __CPROVER_assume(y<100000); + if(y > 10) foo(y,k); + return 0; +} + + diff --git a/regression/modular/nocex5/test.desc b/regression/modular/nocex5/test.desc new file mode 100644 index 000000000..dc053e6ab --- /dev/null +++ b/regression/modular/nocex5/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--havoc +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ diff --git a/regression/modular/nocex6/main.c b/regression/modular/nocex6/main.c new file mode 100644 index 000000000..309c06dd9 --- /dev/null +++ b/regression/modular/nocex6/main.c @@ -0,0 +1,15 @@ + +#include + +int main(int argc, char** argv) +{ + int y = 1; + + while(y<30){ + y++; + assert(y<5); + } + + return 0; +} + diff --git a/regression/modular/nocex6/test.desc b/regression/modular/nocex6/test.desc new file mode 100644 index 000000000..895f3abe9 --- /dev/null +++ b/regression/modular/nocex6/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--havoc --unwind 2 +^EXIT=10$ +^SIGNAL=0$ +^VERIFICATION FAILED$ diff --git a/regression/modular/nocex7/main.c b/regression/modular/nocex7/main.c new file mode 100644 index 000000000..4b957b301 --- /dev/null +++ b/regression/modular/nocex7/main.c @@ -0,0 +1,34 @@ + +#include + +int inc(int c) +{ + return c+1; +} + +int dec(int b) +{ + return b-1; +} + +int add(int i, int j) +{ + int b = i; + int c = j; + int ret = c; + + while(b > 0){ + b = dec(b); + c = inc(c); + ret = c; + assert((ret + b) == (i + j)); //loop invariant + } + assert(ret == (i + j)); + return ret; +} + +void main() { + int x = 5; + int y = 3; + int result = add(x, y); +} diff --git a/regression/modular/nocex7/test.desc b/regression/modular/nocex7/test.desc new file mode 100644 index 000000000..dc053e6ab --- /dev/null +++ b/regression/modular/nocex7/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--havoc +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ diff --git a/regression/modular/nocex8/main.c b/regression/modular/nocex8/main.c new file mode 100644 index 000000000..d9ee4be0c --- /dev/null +++ b/regression/modular/nocex8/main.c @@ -0,0 +1,16 @@ + +#include + +void fail(void) +{ + assert(0); +} + +int main(void) +{ + int tmp = 0; + if(tmp) + fail(); + return 0; +} + diff --git a/regression/modular/nocex8/test.desc b/regression/modular/nocex8/test.desc new file mode 100644 index 000000000..dc053e6ab --- /dev/null +++ b/regression/modular/nocex8/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--havoc +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ diff --git a/src/2ls/cover_goals_ext.cpp b/src/2ls/cover_goals_ext.cpp index 60c06909f..706410331 100644 --- a/src/2ls/cover_goals_ext.cpp +++ b/src/2ls/cover_goals_ext.cpp @@ -174,84 +174,53 @@ Function: cover_goals_extt::assignment void cover_goals_extt::assignment() { - // check loop head choices in model - bool invariants_involved=false; - if(spurious_check) - { - for(exprt::operandst::const_iterator l_it=loophead_selects.begin(); - l_it!=loophead_selects.end(); l_it++) - { - if(solver.get(l_it->op0()).is_true()) - { - invariants_involved=true; - break; - } - } - } - if(!invariants_involved || !spurious_check) - { - std::list::const_iterator g_it=goals.begin(); - for(goal_mapt::const_iterator it=goal_map.begin(); - it!=goal_map.end(); it++, g_it++) + std::list::const_iterator g_it=goals.begin(); + for(goal_mapt::const_iterator it=goal_map.begin(); + it!=goal_map.end(); it++, g_it++) { if(property_map[it->first].result==property_checkert::UNKNOWN && - solver.l_get(g_it->condition).is_true()) - { - property_map[it->first].result=property_checkert::FAIL; - if(build_error_trace) - { - ssa_build_goto_tracet build_goto_trace(SSA, solver.get_solver()); - build_goto_trace(property_map[it->first].error_trace); - if(!all_properties) - break; - } - } + solver.l_get(g_it->condition).is_true()) + { + if(spurious_check) + { + assert((g_it->cond_expression).id()==ID_not); + exprt conjunct_expr=(g_it->cond_expression).op0(); + + if(conjunct_expr.id()!=ID_and) + { + solver.pop_context(); //otherwise this would interfere with necessary preconditions + summarizer_bw_cex.summarize(g_it->cond_expression); + property_map[it->first].result=summarizer_bw_cex.check(); + solver.new_context(); + } + else + { + exprt::operandst failed_exprs; + for(exprt::operandst::const_iterator c_it= + conjunct_expr.operands().begin(); + c_it!=conjunct_expr.operands().end(); c_it++) + { + literalt conjunct_literal=solver.convert(*c_it); + if(solver.l_get(conjunct_literal).is_false()) + failed_exprs.push_back(*c_it); + } + solver.pop_context(); // otherwise this would interfere with necessary preconditions + for(const auto &failed_expr : failed_exprs) + { + summarizer_bw_cex.summarize( + not_exprt(failed_expr)); + property_map[it->first].result=summarizer_bw_cex.check(); + if(property_map[it->first].result== + property_checkert::FAIL) + break; + } + solver.new_context(); + } + } + else + property_map[it->first].result=property_checkert::FAIL; + } } - return; - } - - solver.new_context(); - // force avoiding paths going through invariants - - solver << conjunction(loophead_selects); - - switch(solver()) - { - case decision_proceduret::D_SATISFIABLE: - { - std::list::const_iterator g_it=goals.begin(); - for(goal_mapt::const_iterator it=goal_map.begin(); - it!=goal_map.end(); it++, g_it++) - { - if(property_map[it->first].result==property_checkert::UNKNOWN && - solver.l_get(g_it->condition).is_true()) - { - property_map[it->first].result=property_checkert::FAIL; - if(build_error_trace) - { - ssa_build_goto_tracet build_goto_trace(SSA, solver.get_solver()); - build_goto_trace(property_map[it->first].error_trace); - -#if 0 - show_raw_countermodel( - it->first, SSA, *solver.solver, debug(), get_message_handler()); -#endif - if(!all_properties) - break; - } - } - } - break; - } - case decision_proceduret::D_UNSATISFIABLE: - break; - - case decision_proceduret::D_ERROR: - default: - throw "error from decision procedure"; - } - - solver.pop_context(); - - _iterations++; // statistics + + _iterations++; //statistics } diff --git a/src/2ls/cover_goals_ext.h b/src/2ls/cover_goals_ext.h index d777a8a66..c6d8ea290 100644 --- a/src/2ls/cover_goals_ext.h +++ b/src/2ls/cover_goals_ext.h @@ -15,6 +15,8 @@ Author: Daniel Kroening, kroening@kroening.com #include "../ssa/local_ssa.h" #include "../ssa/unwindable_local_ssa.h" #include "../domains/incremental_solver.h" +#include "summarizer_bw_cex.h" +#include "summarizer_bw_cex_complete.h" /*******************************************************************\ @@ -53,14 +55,16 @@ class cover_goals_extt:public messaget const exprt::operandst& _loophead_selects, property_checkert::property_mapt &_property_map, bool _spurious_check, bool _all_properties, - bool _build_error_trace): + bool _build_error_trace, + summarizer_bw_cex_baset &_summarizer_bw_cex): SSA(_SSA), solver(_solver), property_map(_property_map), spurious_check(_spurious_check), all_properties(_all_properties), build_error_trace(_build_error_trace), - loophead_selects(_loophead_selects) + loophead_selects(_loophead_selects), + summarizer_bw_cex(_summarizer_bw_cex) { } @@ -74,6 +78,7 @@ class cover_goals_extt:public messaget { literalt condition; bool covered; + exprt cond_expression; cover_goalt():covered(false) { @@ -111,6 +116,13 @@ class cover_goals_extt:public messaget goals.back().condition=condition; } + inline void add(const exprt cond_expression) + { + goals.push_back(cover_goalt()); + goals.back().condition=!solver.convert(not_exprt(cond_expression)); + goals.back().cond_expression=cond_expression; + } + protected: unwindable_local_SSAt &SSA; unsigned _number_covered, _iterations; @@ -118,6 +130,7 @@ class cover_goals_extt:public messaget property_checkert::property_mapt &property_map; bool spurious_check, all_properties, build_error_trace; exprt::operandst loophead_selects; + summarizer_bw_cex_baset &summarizer_bw_cex; // this method is called for each satisfying assignment virtual void assignment(); diff --git a/src/domains/domain.h b/src/domains/domain.h index cdc10fa83..82d54a43e 100644 --- a/src/domains/domain.h +++ b/src/domains/domain.h @@ -109,6 +109,8 @@ class domaint result=true_exprt(); } + virtual bool is_spec_empty() const { assert(false); } + static kindt merge_kinds(kindt k1, kindt k2); static void output_var_specs( diff --git a/src/domains/ssa_analyzer.cpp b/src/domains/ssa_analyzer.cpp index 993ba4eea..3b96fe7f1 100644 --- a/src/domains/ssa_analyzer.cpp +++ b/src/domains/ssa_analyzer.cpp @@ -47,20 +47,20 @@ Function: ssa_analyzert::operator() Inputs: - Outputs: - + Outputs: true if the computation was not aborted due to + assertion_checks that did not pass Purpose: \*******************************************************************/ -void ssa_analyzert::operator()( +bool ssa_analyzert::operator()( incremental_solvert &solver, local_SSAt &SSA, const exprt &precondition, template_generator_baset &template_generator) { if(SSA.goto_function.body.instructions.empty()) - return; + return true; solver << SSA; SSA.mark_nodes(); @@ -73,6 +73,30 @@ void ssa_analyzert::operator()( domain=template_generator.domain(); + // get assertions if check_assertions is requested + literalt assertions_check=const_literal(false); + bvt assertion_literals; + if(check_assertions) + { + exprt::operandst ll; + for(local_SSAt::nodest::iterator n_it=SSA.nodes.begin(); + n_it!=SSA.nodes.end(); n_it++) + { + assert(n_it->assertions.size()<=1); + for(local_SSAt::nodet::assertionst::const_iterator + a_it=n_it->assertions.begin(); + a_it!=n_it->assertions.end(); + a_it++) + { + literalt l=solver.solver->convert(*a_it); + assertion_literals.push_back(!l); + ll.push_back(literal_exprt(!l)); + nonpassed_assertions.push_back(n_it); + } + } + assertions_check = solver.solver->convert(disjunction(ll)); + } + // get strategy solver from options strategy_solver_baset *strategy_solver; if(template_generator.options.get_bool_option("compute-ranking-functions")) @@ -131,17 +155,43 @@ void ssa_analyzert::operator()( // initialize inv domain->initialize(*result); - // iterate - while(strategy_solver->iterate(*result)) {} + strategy_solver_baset::progresst status; + + do + { + status=strategy_solver->iterate(*result); + } + while(status==strategy_solver_baset::CHANGED); + +#ifdef DEBUG + std::cout << "Fixed-point after " << iteration_number + << " iteration(s)\n"; + domain->output_value(std::cout,*result,SSA.ns); +#endif + + //get status of assertions + if(!assertions_check.is_false() && + status==strategy_solver_baset::FAILED) + { + nonpassed_assertionst::iterator it=nonpassed_assertions.begin(); + for(unsigned i=0;il_get(assertion_literals[i]).is_true()) + nonpassed_assertions.erase(it++); + else ++it; + } + } + else nonpassed_assertions.clear(); solver.pop_context(); - // statistics - solver_instances+=strategy_solver->get_number_of_solver_instances(); + //statistics solver_calls+=strategy_solver->get_number_of_solver_calls(); solver_instances+=strategy_solver->get_number_of_solver_instances(); delete strategy_solver; + + return (status==strategy_solver_baset::CONVERGED); } /*******************************************************************\ diff --git a/src/domains/ssa_analyzer.h b/src/domains/ssa_analyzer.h index 1758f4711..35fd52edd 100644 --- a/src/domains/ssa_analyzer.h +++ b/src/domains/ssa_analyzer.h @@ -23,7 +23,7 @@ class ssa_analyzert:public messaget typedef strategy_solver_baset::var_listt var_listt; ssa_analyzert(): - result(NULL), + result(nullptr), solver_instances(0), solver_calls(0) { @@ -31,7 +31,7 @@ class ssa_analyzert:public messaget ~ssa_analyzert() { - if(result!=NULL) + if(result!=nullptr) delete result; } @@ -39,16 +39,25 @@ class ssa_analyzert:public messaget incremental_solvert &solver, local_SSAt &SSA, const exprt &precondition, - template_generator_baset &template_generator); + template_generator_baset &template_generator, + bool check_assertions=false); + //retrieve the result if operator() returned true void get_result(exprt &result, const domaint::var_sett &vars); + //retrieve the non-passed assertions if operator() returned false + typedef std::list + nonpassed_assertionst; + nonpassed_assertionst get_nonpassed_assertions() + { return nonpassed_assertions; } + inline unsigned get_number_of_solver_instances() { return solver_instances; } inline unsigned get_number_of_solver_calls() { return solver_calls; } protected: domaint *domain; // template generator is responsable for the domain object domaint::valuet *result; + nonpassed_assertionst nonpassed_assertions; // statistics unsigned solver_instances; @@ -56,4 +65,3 @@ class ssa_analyzert:public messaget }; #endif - diff --git a/src/domains/strategy_solver_base.h b/src/domains/strategy_solver_base.h index 2e33c0946..7ef72b19c 100644 --- a/src/domains/strategy_solver_base.h +++ b/src/domains/strategy_solver_base.h @@ -19,11 +19,14 @@ class strategy_solver_baset:public messaget typedef std::list constraintst; typedef std::vector var_listt; typedef domaint::valuet invariantt; + typedef enum {CHANGED, CONVERGED, FAILED} progresst; explicit strategy_solver_baset( incremental_solvert &_solver, + literalt _assertion_check, const namespacet &_ns): solver(_solver), + assertion_check(_assertion_check), ns(_ns), solver_instances(0), solver_calls(0) @@ -31,11 +34,12 @@ class strategy_solver_baset:public messaget virtual bool iterate(invariantt &inv) { assert(false); } - inline unsigned get_number_of_solver_calls() { return solver_calls; } - inline unsigned get_number_of_solver_instances() { return solver_instances; } + unsigned get_number_of_solver_calls() { return solver_calls; } + unsigned get_number_of_solver_instances() { return solver_instances; } protected: incremental_solvert &solver; + literalt assertion_check; const namespacet &ns; // handles on values to retrieve from model diff --git a/src/domains/strategy_solver_binsearch.cpp b/src/domains/strategy_solver_binsearch.cpp index 398d66ddd..5a354d3d1 100644 --- a/src/domains/strategy_solver_binsearch.cpp +++ b/src/domains/strategy_solver_binsearch.cpp @@ -25,12 +25,12 @@ Function: strategy_solver_binsearcht::iterate \*******************************************************************/ -bool strategy_solver_binsearcht::iterate(invariantt &_inv) +strategy_solver_baset::progresst strategy_solver_binsearcht::iterate(invariantt &_inv) { tpolyhedra_domaint::templ_valuet &inv= static_cast(_inv); - bool improved=false; + progresst progress=CONVERGED; solver.new_context(); // for improvement check @@ -65,7 +65,8 @@ bool strategy_solver_binsearcht::iterate(invariantt &_inv) debug() << eom; #endif - solver << disjunction(strategy_cond_exprs); + solver << or_exprt(disjunction(strategy_cond_exprs), + literal_exprt(assertion_check)); #if 0 debug() << "solve(): "; @@ -115,6 +116,13 @@ bool strategy_solver_binsearcht::iterate(invariantt &_inv) break; // we've found a row to improve } + if(row==strategy_cond_literals.size()) + { // No, we haven't found one. + // This can only happen if the assertions failed. + solver.pop_context(); + return FAILED; + } + debug() << "improving row: " << row << eom; std::set improve_rows; improve_rows.insert(row); @@ -224,10 +232,8 @@ bool strategy_solver_binsearcht::iterate(invariantt &_inv) debug() << "update value: " << from_expr(ns, "", lower) << eom; - solver.pop_context(); // symbolic value system - tpolyhedra_domain.set_row_value(row, lower, inv); - improved=true; + progress=CHANGED; } else { @@ -248,5 +254,5 @@ bool strategy_solver_binsearcht::iterate(invariantt &_inv) solver.pop_context(); // improvement check } - return improved; + return progress; } diff --git a/src/domains/strategy_solver_binsearch.h b/src/domains/strategy_solver_binsearch.h index 8bcdf7f4b..e47c6cfef 100644 --- a/src/domains/strategy_solver_binsearch.h +++ b/src/domains/strategy_solver_binsearch.h @@ -18,13 +18,14 @@ class strategy_solver_binsearcht:public strategy_solver_baset strategy_solver_binsearcht( tpolyhedra_domaint &_tpolyhedra_domain, incremental_solvert &_solver, + literalt _assertion_check, const namespacet &_ns): - strategy_solver_baset(_solver, _ns), + strategy_solver_baset(_solver, _assertion_check, _ns), tpolyhedra_domain(_tpolyhedra_domain) { } - virtual bool iterate(invariantt &inv); + virtual progresst iterate(invariantt &inv); protected: tpolyhedra_domaint &tpolyhedra_domain; diff --git a/src/domains/strategy_solver_binsearch2.cpp b/src/domains/strategy_solver_binsearch2.cpp index 8aa25032f..6fdb00a1e 100644 --- a/src/domains/strategy_solver_binsearch2.cpp +++ b/src/domains/strategy_solver_binsearch2.cpp @@ -37,7 +37,7 @@ bool strategy_solver_binsearch2t::iterate(invariantt &_inv) tpolyhedra_domaint::templ_valuet &inv= static_cast(_inv); - bool improved=false; + progresst progress=CONVERGED; solver.new_context(); // for improvement check @@ -87,7 +87,7 @@ bool strategy_solver_binsearch2t::iterate(invariantt &_inv) #if 0 debug() << "SAT" << eom; #endif - improved=true; + progress=CHANGED; std::size_t row=0; for(; row(_inv); - bool improved=false; + progresst progress = CONVERGED; solver.new_context(); // for improvement check @@ -84,7 +84,7 @@ bool strategy_solver_binsearch3t::iterate(invariantt &_inv) #if 0 debug() << "SAT" << eom; #endif - improved=true; + progress=CHANGED; std::size_t row=0; for(; row(_inv); - bool improved=false; + progresst progress=CONVERGED; solver.new_context(); @@ -68,7 +68,8 @@ bool strategy_solver_enumerationt::iterate(invariantt &_inv) debug() << eom; #endif - solver << disjunction(strategy_cond_exprs); + solver << or_exprt(disjunction(strategy_cond_exprs), + literal_exprt(assertion_check)); #ifdef DEBUG_OUTPUT debug() << "solve(): "; @@ -144,9 +145,14 @@ bool strategy_solver_enumerationt::iterate(invariantt &_inv) << ", simplified value: " << from_expr(ns, "", v) << eom; tpolyhedra_domain.set_row_value(row, v, inv); + progress=CHANGED; } } - improved=true; + if(!progress==CHANGED) //only possible if assertion check fails + { + solver.pop_context(); + return FAILED; + } } else { @@ -166,5 +172,5 @@ bool strategy_solver_enumerationt::iterate(invariantt &_inv) } solver.pop_context(); - return improved; + return progress; } diff --git a/src/domains/strategy_solver_enumeration.h b/src/domains/strategy_solver_enumeration.h index e4363246c..ff7420833 100644 --- a/src/domains/strategy_solver_enumeration.h +++ b/src/domains/strategy_solver_enumeration.h @@ -17,14 +17,15 @@ class strategy_solver_enumerationt:public strategy_solver_baset public: strategy_solver_enumerationt( tpolyhedra_domaint &_tpolyhedra_domain, - incremental_solvert &_solver, - const namespacet &_ns): - strategy_solver_baset(_solver, _ns), - tpolyhedra_domain(_tpolyhedra_domain) + incremental_solvert &_solver, + literalt _assertion_check, + const namespacet &_ns): + strategy_solver_baset(_solver, _assertion_check, _ns), + tpolyhedra_domain(_tpolyhedra_domain) { } - virtual bool iterate(invariantt &inv); + virtual progresst iterate(invariantt &inv); protected: tpolyhedra_domaint &tpolyhedra_domain; diff --git a/src/domains/strategy_solver_equality.cpp b/src/domains/strategy_solver_equality.cpp index bf83742b7..ff7acca05 100644 --- a/src/domains/strategy_solver_equality.cpp +++ b/src/domains/strategy_solver_equality.cpp @@ -21,11 +21,12 @@ Function: strategy_solver_equalityt::iterate Outputs: - Purpose: + Purpose: Comment: assertion check is not possible + because this is a gfp solver \*******************************************************************/ -bool strategy_solver_equalityt::iterate(invariantt &_inv) +strategy_solver_baset::progresst strategy_solver_equalityt::iterate(invariantt &_inv) { equality_domaint::equ_valuet &inv= static_cast(_inv); @@ -122,5 +123,5 @@ bool strategy_solver_equalityt::iterate(invariantt &_inv) todo_disequs.erase(e_it); } - return true; + return CHANGED; } diff --git a/src/domains/strategy_solver_equality.h b/src/domains/strategy_solver_equality.h index 6a7407a75..ae011cdf9 100644 --- a/src/domains/strategy_solver_equality.h +++ b/src/domains/strategy_solver_equality.h @@ -18,14 +18,15 @@ class strategy_solver_equalityt:public strategy_solver_baset strategy_solver_equalityt( equality_domaint &_equality_domain, incremental_solvert &_solver, + literalt _assertion_check, const namespacet &_ns): - strategy_solver_baset(_solver, _ns), + strategy_solver_baset(_solver, _assertion_check, _ns), equality_domain(_equality_domain) { equality_domain.get_index_set(todo_equs); } - virtual bool iterate(invariantt &inv); + virtual progresst iterate(invariantt &inv); protected: equality_domaint &equality_domain; diff --git a/src/domains/template_generator_base.h b/src/domains/template_generator_base.h index 1c9428da2..231154986 100644 --- a/src/domains/template_generator_base.h +++ b/src/domains/template_generator_base.h @@ -50,8 +50,8 @@ class template_generator_baset:public messaget } virtual domaint::var_sett all_vars(); - - inline domaint *domain() { assert(domain_ptr!=NULL); return domain_ptr; } + bool empty() { assert(domain_ptr!=nullptr); return domain_ptr->is_spec_empty(); } + domaint *domain() { assert(domain_ptr!=nullptr); return domain_ptr; } domaint::var_specst var_specs; replace_mapt post_renaming_map; diff --git a/src/domains/tpolyhedra_domain.cpp b/src/domains/tpolyhedra_domain.cpp index 470931c05..a7c4de1c3 100644 --- a/src/domains/tpolyhedra_domain.cpp +++ b/src/domains/tpolyhedra_domain.cpp @@ -50,6 +50,8 @@ void tpolyhedra_domaint::initialize(valuet &value) else v[row]=false_exprt(); // marker for -oo } + + refine(); //initialise refinements } /*******************************************************************\ @@ -731,7 +733,7 @@ void tpolyhedra_domaint::set_row_value( \*******************************************************************/ tpolyhedra_domaint::row_valuet tpolyhedra_domaint::get_max_row_value( - const tpolyhedra_domaint::rowt &row) + const tpolyhedra_domaint::rowt &row) const { const template_rowt &templ_row=templ[row]; if(templ_row.expr.type().id()==ID_signedbv) @@ -764,7 +766,7 @@ tpolyhedra_domaint::row_valuet tpolyhedra_domaint::get_max_row_value( \*******************************************************************/ tpolyhedra_domaint::row_valuet tpolyhedra_domaint::get_min_row_value( - const tpolyhedra_domaint::rowt &row) + const tpolyhedra_domaint::rowt &row) const { const template_rowt &templ_row=templ[row]; if(templ_row.expr.type().id()==ID_signedbv) @@ -907,6 +909,25 @@ bool tpolyhedra_domaint::is_row_value_neginf( return row_value.get(ID_value)==ID_false; } +/*******************************************************************\ + + Function: tpolyhedra_domaint::is_row_value_neginf + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +bool tpolyhedra_domaint::is_row_value_neginf( + const valuet &value, const rowt &row) const +{ + const templ_valuet &v=static_cast(value); + return v.at(row).get(ID_value)==ID_false; +} + /*******************************************************************\ Function: tpolyhedra_domaint::is_row_value_inf @@ -924,6 +945,48 @@ bool tpolyhedra_domaint::is_row_value_inf(const row_valuet & row_value) const return row_value.get(ID_value)==ID_true; } +/*******************************************************************\ + + Function: tpolyhedra_domaint::is_row_value_inf + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +bool tpolyhedra_domaint::is_row_value_inf( + const valuet &value, const rowt &row) const +{ + const templ_valuet &v=static_cast(value); + const row_valuet &row_value=v.at(row); + if(row_value.get(ID_value)==ID_true) + return true; + if(row_value==get_max_row_value(row)) + return true; + const row_exprt &row_expr=templ[row].expr; + if(row_expr.id()==ID_unary_minus && + row_expr.op0().id()==ID_typecast) + { + mp_integer rvalue; + to_integer(row_value, rvalue); + const typet &inner_type=row_expr.op0().op0().type(); + mp_integer smallest; + if(inner_type.id()==ID_unsignedbv) + smallest=to_unsignedbv_type(inner_type).smallest(); + else if(inner_type.id()==ID_signedbv) + smallest=to_signedbv_type(inner_type).smallest(); + else + return false; + if(smallest==rvalue) + return true; + } + + return false; +} + /*******************************************************************\ Function: tpolyhedra_domaint::rename_for_row @@ -962,7 +1025,7 @@ void tpolyhedra_domaint::rename_for_row(exprt &expr, const rowt &row) Outputs: - Purpose: + Purpose: +-x<=c \*******************************************************************/ @@ -1166,3 +1229,56 @@ void tpolyhedra_domaint::add_sum_template( } } } + +/*******************************************************************\ + +Function: tpolyhedra_domaint::refine + + Inputs: + + Outputs: + + Purpose: non-monotone condition refinement + +\*******************************************************************/ + +void tpolyhedra_domaint::replace_comparison(exprt &expr, bool greater) +{ + //TODO +} + +bool tpolyhedra_domaint::refine() +{ + return false; + + //TODO + if(current_refinement==0) //initialise + { + if(refinement_exprs.size()==0) + { + max_refinements = 0; + return false; + } + max_refinements = 3; + current_refinement = 1; + exprt::operandst c; + //TODO + current_refinement_expr = conjunction(c); + return true; + } + + if(current_refinement>max_refinements) + return false; + + if(current_refinement==1) + { + exprt::operandst c; + //TODO + current_refinement_expr = conjunction(c); + } + else if(current_refinement==2) + current_refinement_expr = true_exprt(); + + current_refinement++; + return true; +} diff --git a/src/domains/tpolyhedra_domain.h b/src/domains/tpolyhedra_domain.h index 866a5accb..8aa852ece 100644 --- a/src/domains/tpolyhedra_domain.h +++ b/src/domains/tpolyhedra_domain.h @@ -50,6 +50,10 @@ class tpolyhedra_domaint:public domaint // initialize value virtual void initialize(valuet &value); + virtual void reset_refinements() { current_refinement = 0; } + virtual bool refine(); //non-monotone condition refinement + std::vector &refinement_expressions() { return refinement_exprs; } + virtual void join(valuet &value1, const valuet &value2); // value -> constraints @@ -88,12 +92,14 @@ class tpolyhedra_domaint:public domaint templ_valuet &value); // max, min, comparison - row_valuet get_max_row_value(const rowt &row); - row_valuet get_min_row_value(const rowt &row); + row_valuet get_max_row_value(const rowt &row) const; + row_valuet get_min_row_value(const rowt &row) const; row_valuet between(const row_valuet &lower, const row_valuet &upper); bool less_than(const row_valuet &v1, const row_valuet &v2); bool is_row_value_inf(const row_valuet & row_value) const; bool is_row_value_neginf(const row_valuet & row_value) const; + bool is_row_value_inf(const valuet &value, const rowt & row) const; + bool is_row_value_neginf(const valuet &value, const rowt & row) const; // printing virtual void output_value( @@ -106,6 +112,7 @@ class tpolyhedra_domaint:public domaint valuet &value, const var_sett &vars, exprt &result); unsigned template_size(); + virtual bool is_spec_empty() const { return templ.size()==0; } // generating templates template_rowt &add_template_row( @@ -133,6 +140,13 @@ class tpolyhedra_domaint:public domaint friend class strategy_solver_enumerationt; templatet templ; + + //non-monotone condition refinement + std::vector refinement_exprs; + unsigned current_refinement, max_refinements; + exprt current_refinement_expr; + + void replace_comparison(exprt &expr, bool greater); }; #endif diff --git a/src/domains/util.cpp b/src/domains/util.cpp index ec12ad55a..e763be350 100644 --- a/src/domains/util.cpp +++ b/src/domains/util.cpp @@ -244,7 +244,7 @@ mp_integer simplify_const_int(const exprt &expr) if(expr.id()==ID_symbol) { #if 0 - std::cout << "substituting default value for " << expr << std::endl; + std::cerr << "substituting default value for " << expr << std::endl; #endif return 0; // default value if not substituted in expr } @@ -336,9 +336,11 @@ ieee_floatt simplify_const_float(const exprt &expr) { ieee_floatt v; v.make_zero(); + #if 0 - std::cout << "substituting default value for " << expr << std::endl; + std::cerr << "substituting default value for " << expr << std::endl; #endif + return v; } if(expr.id()==ID_index) diff --git a/src/solver/Makefile b/src/solver/Makefile index bd0fe97b7..fee456366 100644 --- a/src/solver/Makefile +++ b/src/solver/Makefile @@ -12,6 +12,8 @@ CP_CXXFLAGS += $(TWOLSFLAGS) INCLUDES= -I $(CBMC)/src -I .. +CP_CXXFLAGS += $(SUMMARIZERFLAGS) + CLEANFILES = solver$(LIBEXT) all: solver$(LIBEXT) diff --git a/src/solver/summary.h b/src/solver/summary.h index 840a42230..ad991e00a 100644 --- a/src/solver/summary.h +++ b/src/solver/summary.h @@ -9,6 +9,7 @@ Author: Daniel Kroening, kroening@kroening.com #ifndef CPROVER_2LS_SOLVER_SUMMARY_H #define CPROVER_2LS_SOLVER_SUMMARY_H +#include #include #include @@ -51,6 +52,31 @@ class summaryt predicatet termination_argument; threevalt terminates; + //-------------- + // the following is for generating interprocedural counterexample + + bool has_assertion; + + std::list nonpassed_assertions; + + struct call_sitet { //TODO: we also need unwinding information here + call_sitet() + : location_number(UINT_MAX) {} + explicit call_sitet(local_SSAt::locationt loc) + : location_number(loc->location_number) {} + unsigned location_number; + + bool operator<(const call_sitet &other) const + { return (location_number error_summariest; + error_summariest error_summaries; + //-------------- + bool mark_recompute; // to force recomputation of the summary // (used for invariant reuse in k-induction) diff --git a/src/solver/summary_db.h b/src/solver/summary_db.h index 44264bead..34c761335 100644 --- a/src/solver/summary_db.h +++ b/src/solver/summary_db.h @@ -25,6 +25,8 @@ class summary_dbt:public messaget summaryt get(const function_namet &function_name) const { return store.at(function_name); } + void set(const function_namet &function_name, const summaryt &summary) + { store[function_name] = summary; } bool exists(const function_namet &function_name) const { return store.find(function_name)!=store.end(); } void put(const function_namet &function_name, const summaryt &summary); diff --git a/src/ssa/local_ssa.cpp b/src/ssa/local_ssa.cpp index f86fbb092..938b98486 100644 --- a/src/ssa/local_ssa.cpp +++ b/src/ssa/local_ssa.cpp @@ -57,6 +57,7 @@ void local_SSAt::build_SSA() build_cond(i_it); build_guard(i_it); build_assertions(i_it); + build_assumptions(i_it); build_function_call(i_it); } @@ -94,7 +95,18 @@ void local_SSAt::get_entry_exit_vars() if(ns.lookup(identifier, symbol)) continue; - params.push_back(symbol->symbol_expr()); + if(ns.follow(symbol->type).id()==ID_struct) + { + exprt param=read_rhs(symbol->symbol_expr(), first); +#if 0 + std::cout << "param: " + << from_expr(ns, "", param) << std::endl; +#endif + forall_operands(it, param) + params.push_back(to_symbol_expr(*it)); + } + else + params.push_back(symbol->symbol_expr()); } // get globals in @@ -271,6 +283,28 @@ void local_SSAt::find_nodes( /*******************************************************************\ +Function: local_SSAt::find_location_by_number + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +local_SSAt::locationt local_SSAt::find_location_by_number(unsigned location_number) const +{ + local_SSAt::nodest::const_iterator n_it =nodes.begin(); + for(; n_it != nodes.end(); n_it++) + { + if(n_it->location->location_number == location_number) break; + } + return n_it->location; +} + +/*******************************************************************\ + Function: local_SSAt::edge_guard Inputs: @@ -333,7 +367,8 @@ void local_SSAt::build_phi_nodes(locationt loc) // ignore custom template variables if(id2string(o_it->get_identifier()). - find(TEMPLATE_PREFIX)!=std::string::npos) continue; + find(TEMPLATE_PREFIX)!=std::string::npos) + continue; // Yes. Get the source -> def map. const ssa_domaint::loc_def_mapt &incoming=p_it->second; @@ -679,6 +714,27 @@ void local_SSAt::build_assertions(locationt loc) /*******************************************************************\ +Function: local_SSAt::build_assumptions + + Inputs: + + Outputs: + + Purpose: collect assumptions (required for backwards analysis) + +\*******************************************************************/ + +void local_SSAt::build_assumptions(locationt loc) +{ + if(loc->is_assume()) + { + exprt c=read_rhs(loc->guard, loc); + (--nodes.end())->assumptions.push_back(c); + } +} + +/*******************************************************************\ + Function: local_SSAt::assertions_to_constraints Inputs: @@ -800,7 +856,6 @@ exprt local_SSAt::read_lhs( #ifdef DEBUG std::cout << from_expr(ns, "", tmp1) << "is_object" << '\n'; #endif - // yes, it is if(assignments.assigns(loc, object)) return name(object, OUT, loc); @@ -1442,6 +1497,8 @@ void local_SSAt::nodet::output( std::ostream &out, const namespacet &ns) const { + if(!enabling_expr.is_true()) + out << "(enable) " << from_expr(ns, "", enabling_expr) << "\n"; #if 0 if(!marked) out << "(not marked)" << "\n"; @@ -1535,10 +1592,6 @@ std::list &operator<<( std::list &dest, const local_SSAt &src) { -#ifdef SLICING - ssa_slicert ssa_slicer; - ssa_slicer(dest, src); -#else for(local_SSAt::nodest::const_iterator n_it=src.nodes.begin(); n_it!=src.nodes.end(); n_it++) { @@ -1549,7 +1602,10 @@ std::list &operator<<( e_it!=n_it->equalities.end(); e_it++) { - dest.push_back(*e_it); + if(!n_it->enabling_expr.is_true()) + dest.push_back(implies_exprt(n_it->enabling_expr,*e_it)); + else + dest.push_back(*e_it); } for(local_SSAt::nodet::constraintst::const_iterator @@ -1557,11 +1613,12 @@ std::list &operator<<( c_it!=n_it->constraints.end(); c_it++) { - dest.push_back(*c_it); + if(!n_it->enabling_expr.is_true()) + dest.push_back(implies_exprt(n_it->enabling_expr,*c_it)); + else + dest.push_back(*c_it); } } -#endif - return dest; } @@ -1581,13 +1638,6 @@ decision_proceduret &operator<<( decision_proceduret &dest, const local_SSAt &src) { -#ifdef SLICING - std::list tmp; - tmp << src; - for(std::list::const_iterator it=tmp.begin(); - it!=tmp.end(); it++) - dest << *it; -#else for(local_SSAt::nodest::const_iterator n_it=src.nodes.begin(); n_it!=src.nodes.end(); n_it++) { @@ -1598,7 +1648,10 @@ decision_proceduret &operator<<( e_it!=n_it->equalities.end(); e_it++) { - dest << *e_it; + if(!n_it->enabling_expr.is_true()) + dest.push_back(implies_exprt(n_it->enabling_expr,*e_it)); + else + dest.push_back(*e_it); } for(local_SSAt::nodet::constraintst::const_iterator @@ -1606,10 +1659,12 @@ decision_proceduret &operator<<( c_it!=n_it->constraints.end(); c_it++) { - dest << *c_it; + if(!n_it->enabling_expr.is_true()) + dest.push_back(implies_exprt(n_it->enabling_expr,*c_it)); + else + dest.push_back(*c_it); } } -#endif return dest; } @@ -1629,13 +1684,6 @@ incremental_solvert &operator<<( incremental_solvert &dest, const local_SSAt &src) { -#ifdef SLICING - std::list tmp; - tmp << src; - for(std::list::const_iterator it=tmp.begin(); - it!=tmp.end(); it++) - dest << *it; -#else for(local_SSAt::nodest::const_iterator n_it=src.nodes.begin(); n_it!=src.nodes.end(); n_it++) { @@ -1677,7 +1725,6 @@ incremental_solvert &operator<<( dest << *c_it; } } -#endif return dest; } @@ -1735,4 +1782,3 @@ bool local_SSAt::has_function_calls() const } return found; } - diff --git a/src/ssa/local_ssa.h b/src/ssa/local_ssa.h index 0f8fcc477..5f9d54006 100644 --- a/src/ssa/local_ssa.h +++ b/src/ssa/local_ssa.h @@ -75,6 +75,9 @@ class local_SSAt typedef std::vector assertionst; assertionst assertions; + typedef std::vector assumptionst; + assertionst assumptions; + typedef std::vector function_callst; function_callst function_calls; @@ -107,13 +110,13 @@ class local_SSAt void mark_nodes() { - for(nodest::iterator n_it=nodes.begin(); - n_it!=nodes.end(); n_it++) n_it->marked=true; + for(auto &n : nodes) + marked=true; } void unmark_nodes() { - for(nodest::iterator n_it=nodes.begin(); - n_it!=nodes.end(); n_it++) n_it->marked=false; + for(auto &n : nodes) + marked=false; } // for incremental unwinding @@ -198,7 +201,8 @@ class local_SSAt assert(it!=location_map.end()); return it->second; } - + locationt find_location_by_number(unsigned location_number) const; + protected: typedef std::map location_mapt; location_mapt location_map; @@ -212,13 +216,17 @@ class local_SSAt void build_guard(locationt loc); void build_function_call(locationt loc); void build_assertions(locationt loc); - + void build_assumptions(locationt loc); + // custom templates void collect_custom_templates(); replace_mapt template_newvars; exprt template_last_newvar; }; +std::vector & operator << + (std::vector &dest, const local_SSAt &src); + std::list & operator << (std::list &dest, const local_SSAt &src); diff --git a/src/ssa/ssa_db.cpp b/src/ssa/ssa_db.cpp index 669fdae28..fbbb80ef3 100644 --- a/src/ssa/ssa_db.cpp +++ b/src/ssa/ssa_db.cpp @@ -7,3 +7,12 @@ Author: Peter Schrammel \*******************************************************************/ #include "ssa_db.h" + +//void ssa_dbt::depgraph_create(const function_namet &function_name, const namespacet &ns, ssa_inlinert &ssa_inliner) +void ssa_dbt::depgraph_create(const function_namet &function_name, const namespacet &ns, ssa_inlinert &ssa_inliner, bool entry) +{ + depgraph_store[function_name] = new ssa_dependency_grapht(*this,ns); + const local_SSAt &SSA=this->get(function_name); + depgraph_store[function_name]->create(SSA, ssa_inliner, entry); +} + diff --git a/src/ssa/ssa_domain.cpp b/src/ssa/ssa_domain.cpp index a9848e8af..193551c75 100644 --- a/src/ssa/ssa_domain.cpp +++ b/src/ssa/ssa_domain.cpp @@ -135,7 +135,7 @@ bool ssa_domaint::merge( d_it_b++) { const irep_idt &id=d_it_b->first; - + // check if we have a phi node for 'id' phi_nodest::iterator p_it=phi_nodes.find(id); diff --git a/src/ssa/ssa_inliner.cpp b/src/ssa/ssa_inliner.cpp index 2f68901a0..50db93b1e 100644 --- a/src/ssa/ssa_inliner.cpp +++ b/src/ssa/ssa_inliner.cpp @@ -13,6 +13,93 @@ Author: Peter Schrammel /*******************************************************************\ +Function: ssa_inlinert::get_guard_binding + + Inputs: + + Outputs: + + Purpose: get guard binding for function call + +\*******************************************************************/ + +void ssa_inlinert::get_guard_binding( + const local_SSAt &SSA, + const local_SSAt &fSSA, + local_SSAt::nodest::const_iterator n_it, + exprt &guard_binding, + int counter) +{ + exprt callee_guard, caller_guard; + callee_guard=fSSA.guard_symbol(fSSA.goto_function.body.instructions.begin()); + rename(callee_guard, counter); + caller_guard=SSA.guard_symbol(n_it->location); + + guard_binding=equal_exprt(callee_guard, caller_guard); +} + +/*******************************************************************\ + +Function: ssa_inlinert::get_bindings + + Inputs: + + Outputs: + + Purpose: get bindings for function call + +\*******************************************************************/ + +void ssa_inlinert::get_bindings( + const local_SSAt &SSA, + const local_SSAt &fSSA, + local_SSAt::nodest::const_iterator n_it, + local_SSAt::nodet::function_callst::const_iterator f_it, + exprt::operandst &bindings_in, + exprt::operandst &bindings_out, + int counter) +{ + //getting globals at call site + local_SSAt::var_sett cs_globals_in, cs_globals_out; + goto_programt::const_targett loc=n_it->location; + + SSA.get_globals(loc, cs_globals_in); + SSA.get_globals(loc, cs_globals_out, false); + +#if 0 + std::cout << "cs_globals_in: "; + for(summaryt::var_sett::const_iterator it=cs_globals_in.begin(); + it!=cs_globals_in.end(); it++) + std::cout << from_expr(SSA.ns, "", *it) << " "; + std::cout << std::endl; + + std::cout << "cs_globals_out: "; + for(summaryt::var_sett::const_iterator it=cs_globals_out.begin(); + it!=cs_globals_out.end(); it++) + std::cout << from_expr(SSA.ns, "", *it) << " "; + std::cout << std::endl; +#endif + + // equalities for arguments + // bindings_in.push_back(get_replace_params(SSA.params, *f_it)); + get_replace_params(SSA,fSSA.params, n_it, *f_it,bindings_in,counter); + + // equalities for globals_in + // bindings_in.push_back(get_replace_globals_in(SSA.globals_in, cs_globals_in)); + + // get_replace_globals_in(fSSA.globals_in, cs_globals_in, bindings_in, counter); + get_replace_globals_in(fSSA.globals_in, *f_it, cs_globals_in, bindings_in, counter); + + // equalities for globals out (including unmodified globals) + // bindings_out.push_back(get_replace_globals_out(SSA.globals_out, cs_globals_in, cs_globals_out)); + + // get_replace_globals_out(fSSA.globals_out, cs_globals_in, cs_globals_out, bindings_out, counter); + get_replace_globals_out(fSSA.globals_out, *f_it, cs_globals_in, cs_globals_out, bindings_out, counter); + +} + +/*******************************************************************\ + Function: ssa_inlinert::get_summary Inputs: @@ -30,10 +117,10 @@ void ssa_inlinert::get_summary( const summaryt &summary, bool forward, exprt::operandst &summaries, - exprt::operandst &bindings) + exprt::operandst &bindings, + int counter, + bool error_summ) { - counter++; - // getting globals at call site local_SSAt::var_sett cs_globals_in, cs_globals_out; goto_programt::const_targett loc=n_it->location; @@ -62,44 +149,60 @@ void ssa_inlinert::get_summary( std::cout << std::endl; #endif - // equalities for arguments - bindings.push_back(get_replace_params(summary.params, *f_it)); + //equalities for arguments + get_replace_params(SSA,summary.params, n_it, *f_it, bindings, counter); - // equalities for globals_in + //equalities for globals_in if(forward) - bindings.push_back( - get_replace_globals_in(summary.globals_in, cs_globals_in)); + { + //get_replace_globals_in(summary.globals_in, cs_globals_in, bindings, counter); + get_replace_globals_in(summary.globals_in, *f_it, cs_globals_in, bindings, counter); + } else - bindings.push_back( - get_replace_globals_in(summary.globals_out, cs_globals_out)); + { + //get_replace_globals_in(summary.globals_out, cs_globals_out, bindings, counter); + get_replace_globals_in(summary.globals_out, *f_it, cs_globals_out, bindings, counter); + } // constraints for transformer + exprt transformer; - if(forward) - transformer=summary.fw_transformer.is_nil() ? true_exprt() : - summary.fw_transformer; - else - { - transformer=summary.bw_transformer.is_nil() ? true_exprt() : - summary.bw_transformer; - } - rename(transformer); - summaries.push_back( - implies_exprt(SSA.guard_symbol(n_it->location), transformer)); - // equalities for globals out (including unmodified globals) - if(forward) - bindings.push_back( - get_replace_globals_out( - summary.globals_out, - cs_globals_in, - cs_globals_out)); + if(error_summ) + { + // update transformer using the error_summaries map + summaryt::call_sitet call_site(loc); + summaryt::error_summariest::const_iterator e_it = + summary.error_summaries.find(call_site); + if(e_it!=summary.error_summaries.end() && + !e_it->second.is_nil()) + transformer=e_it->second; + else + transformer=true_exprt(); + } else - bindings.push_back( - get_replace_globals_out( - summary.globals_in, - cs_globals_out, - cs_globals_in)); + { + if(forward) + transformer = summary.fw_transformer.is_nil() ? true_exprt() : + summary.fw_transformer; + else + transformer = summary.bw_transformer.is_nil() ? true_exprt() : + summary.bw_transformer; + } + + rename(transformer,counter); + summaries.push_back(implies_exprt(SSA.guard_symbol(n_it->location), + transformer)); + + //equalities for globals out (including unmodified globals) + if(forward){ + //get_replace_globals_out(summary.globals_out,cs_globals_in,cs_globals_out,bindings,counter); + get_replace_globals_out(summary.globals_out,*f_it,cs_globals_in,cs_globals_out,bindings,counter); + } + else{ + //get_replace_globals_out(summary.globals_in,cs_globals_out,cs_globals_in,bindings,counter); + get_replace_globals_out(summary.globals_in,*f_it,cs_globals_out,cs_globals_in,bindings,counter); + } } /*******************************************************************\ @@ -121,6 +224,32 @@ exprt ssa_inlinert::get_summaries(const local_SSAt &SSA) return and_exprt(conjunction(bindings), conjunction(summaries)); } +void ssa_inlinert::get_summaries( + const local_SSAt &SSA, + bool forward, + exprt::operandst &summaries, + exprt::operandst &bindings) +{ + for(local_SSAt::nodest::const_iterator n_it=SSA.nodes.begin(); + n_it!=SSA.nodes.end(); n_it++) + { + for(local_SSAt::nodet::function_callst::const_iterator f_it= + n_it->function_calls.begin(); + f_it!=n_it->function_calls.end(); f_it++) + { + assert(f_it->function().id()==ID_symbol); // no function pointers + irep_idt fname=to_symbol_expr(f_it->function()).get_identifier(); + + if(summary_db.exists(fname)) + { + counter++; + get_summary(SSA, n_it, f_it,summary_db.get(fname), + forward, summaries, bindings, counter); + } + } + } +} + /*******************************************************************\ Function: ssa_inlinert::get_summaries @@ -133,31 +262,50 @@ Function: ssa_inlinert::get_summaries \*******************************************************************/ -void ssa_inlinert::get_summaries( +bool ssa_inlinert::get_summaries( const local_SSAt &SSA, + const summaryt::call_sitet ¤t_call_site, bool forward, - exprt::operandst &summaries, + exprt::operandst &assert_summaries, + exprt::operandst &noassert_summaries, exprt::operandst &bindings) { + bool assertion_flag = false; for(local_SSAt::nodest::const_iterator n_it=SSA.nodes.begin(); n_it!=SSA.nodes.end(); n_it++) { - for(local_SSAt::nodet::function_callst::const_iterator f_it= - n_it->function_calls.begin(); + for(local_SSAt::nodet::function_callst::const_iterator f_it = + n_it->function_calls.begin(); f_it!=n_it->function_calls.end(); f_it++) - { - assert(f_it->function().id()==ID_symbol); // no function pointers - irep_idt fname=to_symbol_expr(f_it->function()).get_identifier(); - - if(summary_db.exists(fname)) { - get_summary(SSA, n_it, f_it, summary_db.get(fname), - forward, summaries, bindings); + //do not use summary for current call site + summaryt::call_sitet this_call_site(n_it->location); + if(current_call_site==this_call_site) + continue; + + assert(f_it->function().id()==ID_symbol); //no function pointers + irep_idt fname=to_symbol_expr(f_it->function()).get_identifier(); + + //TODO: we need a get_summary variant that retrieves the summary according the call_site from summary.error_summaries + if(summary_db.exists(fname)) + { + summaryt summary=summary_db.get(fname); + if(summary.has_assertion==true){ + counter++; + get_summary(SSA, n_it, f_it, summary_db.get(fname),forward,assert_summaries,bindings,counter,true); + assertion_flag=true; + } + else{ + counter++; + get_summary(SSA, n_it, f_it, summary_db.get(fname),forward,noassert_summaries,bindings,counter,true); + } + } } - } } + return assertion_flag; } + /*******************************************************************\ Function: ssa_inlinert::replace @@ -232,57 +380,58 @@ Function: ssa_inlinert::replace void ssa_inlinert::replace( local_SSAt &SSA, const ssa_dbt &ssa_db, - bool recursive, bool rename) + int counter, + bool recursive, + bool rename) { - for(local_SSAt::nodest::iterator n_it=SSA.nodes.begin(); - n_it!=SSA.nodes.end(); n_it++) - { - for(local_SSAt::nodet::function_callst::iterator - f_it=n_it->function_calls.begin(); - f_it!=n_it->function_calls.end(); f_it++) + for(local_SSAt::nodest::iterator n_it = SSA.nodes.begin(); + n_it != SSA.nodes.end(); n_it++) { - assert(f_it->function().id()==ID_symbol); // no function pointers - irep_idt fname=to_symbol_expr(f_it->function()).get_identifier(); - - if(ssa_db.exists(fname)) - { - status() << "Inlining function " << fname << eom; - local_SSAt fSSA=ssa_db.get(fname); // copy - - if(rename) - { - // getting globals at call site - local_SSAt::var_sett cs_globals_in, cs_globals_out; - goto_programt::const_targett loc=n_it->location; - SSA.get_globals(loc, cs_globals_in); - SSA.get_globals(loc, cs_globals_out, false); - - if(recursive) - { - replace(fSSA, ssa_db, true); - } - - // replace - replace(SSA.nodes, n_it, f_it, cs_globals_in, cs_globals_out, fSSA); - } - else // just add to nodes - { - for(local_SSAt::nodest::const_iterator fn_it=fSSA.nodes.begin(); - fn_it!=fSSA.nodes.end(); fn_it++) - { - debug() << "new node: "; fn_it->output(debug(), fSSA.ns); - debug() << eom; - - new_nodes.push_back(*fn_it); - } - } - } - else - debug() << "No body available for function " << fname << eom; - commit_node(n_it); + for(local_SSAt::nodet::function_callst::iterator + f_it = n_it->function_calls.begin(); + f_it != n_it->function_calls.end(); f_it++) + { + assert(f_it->function().id()==ID_symbol); //no function pointers + irep_idt fname = to_symbol_expr(f_it->function()).get_identifier(); + + if(ssa_db.exists(fname)) + { + status() << "Inlining function " << fname << eom; + local_SSAt fSSA = ssa_db.get(fname); //copy + + if(rename) + { + //getting globals at call site + local_SSAt::var_sett cs_globals_in, cs_globals_out; + goto_programt::const_targett loc = n_it->location; + SSA.get_globals(loc,cs_globals_in); + SSA.get_globals(loc,cs_globals_out,false); + + if(recursive) + { + replace(fSSA,ssa_db,true,counter); + } + + //replace + replace(SSA.nodes,n_it,f_it,cs_globals_in,cs_globals_out,fSSA,counter); + } + else // just add to nodes + { + for(local_SSAt::nodest::const_iterator fn_it = fSSA.nodes.begin(); + fn_it != fSSA.nodes.end(); fn_it++) + { + debug() << "new node: "; fn_it->output(debug(),fSSA.ns); + debug() << eom; + + new_nodes.push_back(*fn_it); + } + } + } + else debug() << "No body available for function " << fname << eom; + commit_node(n_it); + } + commit_nodes(SSA.nodes,n_it); } - commit_nodes(SSA.nodes, n_it); - } } /*******************************************************************\ @@ -305,10 +454,9 @@ void ssa_inlinert::replace( const local_SSAt::var_sett &cs_globals_out, const summaryt &summary, bool forward, - bool preconditions_as_assertions) + bool preconditions_as_assertions, + int counter) { - counter++; - // equalities for arguments replace_params(summary.params, *f_it); @@ -342,7 +490,7 @@ void ssa_inlinert::replace( transformer=summary.bw_transformer; node->constraints.push_back(transformer); // copy exprt &_transformer=node->constraints.back(); - rename(_transformer); + rename(_transformer, counter); // remove function call rm_function_calls.insert(f_it); @@ -373,9 +521,9 @@ void ssa_inlinert::replace( local_SSAt::nodet::function_callst::iterator f_it, const local_SSAt::var_sett &cs_globals_in, const local_SSAt::var_sett &cs_globals_out, - const local_SSAt &function) + const local_SSAt &function, + int counter) { - counter++; // equalities for arguments replace_params(function.params, *f_it); @@ -386,9 +534,9 @@ void ssa_inlinert::replace( // add function body for(local_SSAt::nodest::const_iterator n_it=function.nodes.begin(); n_it!=function.nodes.end(); n_it++) - { + { local_SSAt::nodet n=*n_it; // copy - rename(n); + rename(n,counter); new_nodes.push_back(n); } @@ -411,65 +559,59 @@ Function: ssa_inlinert::get_replace_globals_in \*******************************************************************/ -exprt ssa_inlinert::get_replace_globals_in( +void ssa_inlinert::get_replace_globals_in( const local_SSAt::var_sett &globals_in, - const local_SSAt::var_sett &globals) + const function_application_exprt &funapp_expr, + const local_SSAt::var_sett &globals, + exprt::operandst &c, + int counter) { - // equalities for globals_in - exprt::operandst c; - for(summaryt::var_sett::const_iterator it=globals_in.begin(); - it!=globals_in.end(); it++) - { - symbol_exprt lhs=*it; // copy - rename(lhs); - symbol_exprt rhs; - if(find_corresponding_symbol(*it, globals, rhs)) + std::string suffix = id2string(funapp_expr.get(ID_suffix)); + + //equalities for globals_in + for(summaryt::var_sett::const_iterator it = globals_in.begin(); + it != globals_in.end(); it++) { - debug() << "binding: " << lhs.get_identifier() << "==" - << rhs.get_identifier() << eom; - c.push_back(equal_exprt(lhs, rhs)); - } + symbol_exprt lhs = *it; //copy + rename(lhs,counter); + symbol_exprt rhs; + if(find_corresponding_symbol(*it,globals,rhs)) + { + rhs.set_identifier(id2string(rhs.get_identifier())+suffix); + + debug() << "binding: " << lhs.get_identifier() << " == " + << rhs.get_identifier() << eom; + c.push_back(equal_exprt(lhs,rhs)); + } #if 0 - else - warning() << "'" << it->get_identifier() - << "' not bound in caller" << eom; + else + warning() << "'" << it->get_identifier() + << "' not bound in caller" << eom; #endif - } - return conjunction(c); + } + //return conjunction(c); } -/*******************************************************************\ - -Function: ssa_inlinert::replace_globals_in - - Inputs: - - Outputs: - - Purpose: - -\*******************************************************************/ - -void ssa_inlinert::replace_globals_in( - const local_SSAt::var_sett &globals_in, - const local_SSAt::var_sett &globals) +void ssa_inlinert::replace_globals_in(const local_SSAt::var_sett &globals_in, + const local_SSAt::var_sett &globals, + int counter) { - // equalities for globals_in - for(summaryt::var_sett::const_iterator it=globals_in.begin(); - it!=globals_in.end(); it++) + //equalities for globals_in + for(summaryt::var_sett::const_iterator it = globals_in.begin(); + it != globals_in.end(); it++) { - symbol_exprt lhs=*it; // copy - rename(lhs); + symbol_exprt lhs = *it; //copy + rename(lhs,counter); symbol_exprt rhs; - if(find_corresponding_symbol(*it, globals, rhs)) - { - debug() << "binding: " << lhs.get_identifier() << "==" - << rhs.get_identifier() << eom; - new_equs.push_back(equal_exprt(lhs, rhs)); - } + if(find_corresponding_symbol(*it,globals,rhs)) + { + debug() << "binding: " << lhs.get_identifier() << " == " + << rhs.get_identifier() << eom; + new_equs.push_back(equal_exprt(lhs,rhs)); + } #if 0 else - warning() << "'" << it->get_identifier() + warning() << "'" << it->get_identifier() << "' not bound in caller" << eom; #endif } @@ -487,133 +629,192 @@ Function: ssa_inlinert::get_replace_params \*******************************************************************/ -exprt ssa_inlinert::get_replace_params( +void ssa_inlinert::get_replace_params( + const local_SSAt &SSA, const local_SSAt::var_listt ¶ms, - const function_application_exprt &funapp_expr) + local_SSAt::nodest::const_iterator n_it, + const function_application_exprt &funapp_expr, + exprt::operandst &c, + int counter) { - // equalities for arguments - exprt::operandst c; - local_SSAt::var_listt::const_iterator p_it=params.begin(); - for(exprt::operandst::const_iterator it=funapp_expr.arguments().begin(); - it!=funapp_expr.arguments().end(); it++, p_it++) - { - local_SSAt::var_listt::const_iterator next_p_it=p_it; - if(funapp_expr.arguments().size()!=params.size() && - ++next_p_it==params.end()) // TODO: handle ellipsis + //std::string suffix = id2string(funapp_expr.get(ID_suffix)); + + //equalities for arguments + local_SSAt::var_listt::const_iterator p_it = params.begin(); + for(exprt::operandst::const_iterator it = funapp_expr.arguments().begin(); + it != funapp_expr.arguments().end(); it++, p_it++) { - warning() << "ignoring excess function arguments" << eom; - break; +#if 0 + std::cout << "replace param " << from_expr(SSA.ns,"",*p_it) + << " == " << from_expr(SSA.ns,"",*it) << std::endl; +#endif + +#if 0 + local_SSAt::var_listt::const_iterator next_p_it = p_it; + if(funapp_expr.arguments().size() != params.size() && + ++next_p_it==params.end()) //TODO: handle ellipsis + { + warning() << "ignoring excess function arguments" << eom; + break; + } +#endif + + if(SSA.ns.follow(it->type()).id()==ID_struct) + { + exprt rhs = SSA.read_rhs(*it, n_it->location); //copy +#if 0 + std::cout << "split param " << from_expr(SSA.ns,"",*it) + << " into " << from_expr(SSA.ns,"",rhs) << std::endl; +#endif + forall_operands(o_it, rhs) + { + assert(p_it!=params.end()); + exprt lhs = *p_it; //copy + rename(lhs,counter); +#if 0 + std::cout << "split replace param " << from_expr(SSA.ns,"",*p_it) + << " == " << from_expr(SSA.ns,"",*o_it) << std::endl; +#endif + c.push_back(equal_exprt(lhs,*o_it)); + ++p_it; + } + } + else + { + exprt lhs = *p_it; //copy + rename(lhs,counter); + c.push_back(equal_exprt(lhs,*it)); + //symbol_exprt sexpr = to_symbol_expr(*it); + //sexpr.set_identifier(id2string(sexpr.get_identifier())+suffix); + //c.push_back(equal_exprt(lhs,sexpr)); + } } +} - exprt lhs=*p_it; // copy - rename(lhs); - c.push_back(equal_exprt(lhs, *it)); - } - return conjunction(c); +void ssa_inlinert::replace_params(const local_SSAt::var_listt ¶ms, + const function_application_exprt &funapp_expr, + int counter) +{ + //equalities for arguments + local_SSAt::var_listt::const_iterator p_it = params.begin(); + for(exprt::operandst::const_iterator it = funapp_expr.arguments().begin(); + it != funapp_expr.arguments().end(); it++, p_it++) + { + local_SSAt::var_listt::const_iterator next_p_it = p_it; + if(funapp_expr.arguments().size() != params.size() && + ++next_p_it==params.end()) //TODO: handle ellipsis + { + warning() << "ignoring excess function arguments" << eom; + break; + } + + exprt lhs = *p_it; //copy + rename(lhs,counter); + new_equs.push_back(equal_exprt(lhs,*it)); + } } /*******************************************************************\ -Function: ssa_inlinert::replace_params +Function: ssa_inlinert::replace_globals_out Inputs: Outputs: - Purpose: + Purpose: equalities for globals out (including unmodified globals) \*******************************************************************/ -void ssa_inlinert::replace_params( - const local_SSAt::var_listt ¶ms, - const function_application_exprt &funapp_expr) +void ssa_inlinert::get_replace_globals_out( + const local_SSAt::var_sett &globals_out, + const function_application_exprt &funapp_expr, + const local_SSAt::var_sett &cs_globals_in, + const local_SSAt::var_sett &cs_globals_out, + exprt::operandst &c, + int counter) { - // equalities for arguments - local_SSAt::var_listt::const_iterator p_it=params.begin(); - for(exprt::operandst::const_iterator it=funapp_expr.arguments().begin(); - it!=funapp_expr.arguments().end(); it++, p_it++) - { - local_SSAt::var_listt::const_iterator next_p_it=p_it; - if(funapp_expr.arguments().size()!=params.size() && - ++next_p_it==params.end()) // TODO: handle ellipsis + std::string suffix = id2string(funapp_expr.get(ID_suffix)); + + //equalities for globals_out + for(summaryt::var_sett::const_iterator it = cs_globals_out.begin(); + it != cs_globals_out.end(); it++) { - warning() << "ignoring excess function arguments" << eom; - break; + symbol_exprt lhs = *it; //copy + + lhs.set_identifier(id2string(lhs.get_identifier())+suffix); + + symbol_exprt rhs; + if(find_corresponding_symbol(*it,globals_out,rhs)) + rename(rhs,counter); + else{ + bool found = find_corresponding_symbol(*it,cs_globals_in,rhs); + assert(found); + rhs.set_identifier(id2string(rhs.get_identifier())+suffix); + } + c.push_back(equal_exprt(lhs,rhs)); } +} - exprt lhs=*p_it; // copy - rename(lhs); - new_equs.push_back(equal_exprt(lhs, *it)); - } +void ssa_inlinert::replace_globals_out(const local_SSAt::var_sett &globals_out, + const local_SSAt::var_sett &cs_globals_in, + const local_SSAt::var_sett &cs_globals_out, + int counter) +{ + //equalities for globals_out + for(summaryt::var_sett::const_iterator it = cs_globals_out.begin(); + it != cs_globals_out.end(); it++) + { + symbol_exprt rhs = *it; //copy + symbol_exprt lhs; + if(find_corresponding_symbol(*it,globals_out,lhs)) + rename(lhs,counter); + else + assert(find_corresponding_symbol(*it,cs_globals_in,lhs)); + new_equs.push_back(equal_exprt(lhs,rhs)); + } } /*******************************************************************\ -Function: ssa_inlinert::get_replace_globals_out +Function: ssa_inlinert::havoc Inputs: Outputs: - Purpose: equalities for globals out (including unmodified globals) + Purpose: \*******************************************************************/ -exprt ssa_inlinert::get_replace_globals_out( - const local_SSAt::var_sett &globals_out, - const local_SSAt::var_sett &cs_globals_in, - const local_SSAt::var_sett &cs_globals_out) +void ssa_inlinert::havoc( + local_SSAt::nodet &node, + local_SSAt::nodet::function_callst::iterator f_it) { - // equalities for globals_out - exprt::operandst c; - for(summaryt::var_sett::const_iterator it=cs_globals_out.begin(); - it!=cs_globals_out.end(); it++) - { - symbol_exprt rhs=*it; // copy - symbol_exprt lhs; - if(find_corresponding_symbol(*it, globals_out, lhs)) - rename(lhs); - else - assert(find_corresponding_symbol(*it, cs_globals_in, lhs)); - c.push_back(equal_exprt(lhs, rhs)); - } - return conjunction (c); + //remove function call + rm_function_calls.insert(f_it); } /*******************************************************************\ -Function: ssa_inlinert::replace_globals_out +Function: ssa_inlinert::rename Inputs: Outputs: - Purpose: equalities for globals out (including unmodified globals) + Purpose: \*******************************************************************/ -void ssa_inlinert::replace_globals_out( - const local_SSAt::var_sett &globals_out, - const local_SSAt::var_sett &cs_globals_in, - const local_SSAt::var_sett &cs_globals_out) +irep_idt ssa_inlinert::rename(irep_idt &id, int counter) { - // equalities for globals_out - for(summaryt::var_sett::const_iterator it=cs_globals_out.begin(); - it!=cs_globals_out.end(); it++) - { - symbol_exprt rhs=*it; // copy - symbol_exprt lhs; - if(find_corresponding_symbol(*it, globals_out, lhs)) - rename(lhs); - else - assert(find_corresponding_symbol(*it, cs_globals_in, lhs)); - new_equs.push_back(equal_exprt(lhs, rhs)); - } + return id2string(id)+"@"+i2string(counter); } /*******************************************************************\ -Function: ssa_inlinert::havoc +Function: ssa_inlinert::rename Inputs: @@ -623,12 +824,38 @@ Function: ssa_inlinert::havoc \*******************************************************************/ -void ssa_inlinert::havoc( - local_SSAt::nodet &node, - local_SSAt::nodet::function_callst::iterator f_it) -{ - // remove function call - rm_function_calls.insert(f_it); +irep_idt ssa_inlinert::rename(irep_idt &id, int counter, bool attach){ + + std::string id_str = id2string(id); + + if(attach == false){ + //find first @ where afterwards there are no letters + size_t pos = std::string::npos; + for(size_t i=0;iarguments().size()); @@ -772,14 +1022,19 @@ void ssa_inlinert::rename_to_callee( replace_map[*it]=*p_it; } - for(summaryt::var_sett::const_iterator it=cs_globals_in.begin(); - it!=cs_globals_in.end(); it++) - { - symbol_exprt cg; - if(find_corresponding_symbol(*it, globals_in, cg)) - replace_map[*it]=cg; - else + /* replace_expr(replace_map,expr); + + replace_map.clear(); //arguments might contain globals, + // thus, we have to replace them separately + */ + for(summaryt::var_sett::const_iterator it = cs_globals_in.begin(); + it != cs_globals_in.end(); it++) { + symbol_exprt cg; + if(find_corresponding_symbol(*it,globals_in,cg)) + replace_map[*it] = cg; + else + { #if 0 warning() << "'" << it->get_identifier() << "' not bound in caller" << eom; diff --git a/src/ssa/ssa_inliner.h b/src/ssa/ssa_inliner.h index 7cf8d0730..beefe4e35 100644 --- a/src/ssa/ssa_inliner.h +++ b/src/ssa/ssa_inliner.h @@ -21,26 +21,54 @@ class ssa_inlinert:public messaget { public: explicit ssa_inlinert(summary_dbt &_summary_db): - counter(0), + counter(0), summary_db(_summary_db) { } + void get_guard_binding( + const local_SSAt &SSA, + const local_SSAt &fSSA, + local_SSAt::nodest::const_iterator n_it, + exprt &guard_binding, + int counter); + + void get_bindings( + const local_SSAt &SSA, + const local_SSAt &fSSA, + local_SSAt::nodest::const_iterator n_it, + local_SSAt::nodet::function_callst::const_iterator f_it, + exprt::operandst &bindings_in, + exprt::operandst &bindings_out, + int counter); + void get_summary( const local_SSAt &SSA, local_SSAt::nodest::const_iterator n_it, - local_SSAt::nodet::function_callst::const_iterator f_it, + local_SSAt::nodet::function_callst::const_iterator f_it, const summaryt &summary, - bool forward, + bool forward, exprt::operandst &summaries, - exprt::operandst &bindings); + exprt::operandst &bindings, + int counter, + bool error_summ=false); + void get_summaries( const local_SSAt &SSA, bool forward, exprt::operandst &summaries, - exprt::operandst &bindings); - exprt get_summaries(const local_SSAt &SSA); + exprt::operandst &bindings); //TODO: need to explicitly pass the correct counter + + bool get_summaries( + const local_SSAt &SSA, + const summaryt::call_sitet ¤t_call_site, + bool forward, + exprt::operandst &assert_summaries, + exprt::operandst &noassert_summaries, + exprt::operandst &bindings); //TODO: need to explicitly pass the correct counter + exprt get_summaries(const local_SSAt &SSA); //TODO: need to explicitly pass the correct counter + void replace( local_SSAt &SSA, local_SSAt::nodest::iterator node, @@ -51,12 +79,14 @@ class ssa_inlinert:public messaget // outgoing globals at call site const summaryt &summary, bool forward, - bool preconditions_as_assertions); + bool preconditions_as_assertions, + int counter); void replace( local_SSAt &SSA, bool forward, - bool preconditions_as_assertions); + bool preconditions_as_assertions, + int counte); void replace( local_SSAt::nodest &nodes, @@ -66,7 +96,8 @@ class ssa_inlinert:public messaget // incoming globals at call site const local_SSAt::var_sett &cs_globals_out, // outgoing globals at call site - const local_SSAt &function); + const local_SSAt &function, + int counte); void replace( local_SSAt &SSA, @@ -104,7 +135,20 @@ class ssa_inlinert:public messaget symbol_exprt &s_found); static irep_idt get_original_identifier(const symbol_exprt &s); + + irep_idt rename(irep_idt &id, int counter); + + irep_idt rename(irep_idt &id, int counter, bool attach); + int get_rename_counter() + { + counter++; + return counter; + } + + // moved from protected to public, for use in summarizer_bw_cex_complete + void rename(exprt &expr, int counter); + protected: unsigned counter; summary_dbt &summary_db; @@ -114,29 +158,41 @@ class ssa_inlinert:public messaget std::set rm_function_calls; void replace_globals_in( - const local_SSAt::var_sett &globals_in, - const local_SSAt::var_sett &globals); + const local_SSAt::var_sett &globals_in, + const local_SSAt::var_sett &globals, + int counter); void replace_params( const local_SSAt::var_listt ¶ms, - const function_application_exprt &funapp_expr); + const function_application_exprt &funapp_expr, + int counter); void replace_globals_out( - const local_SSAt::var_sett &globals_out, - const local_SSAt::var_sett &cs_globals_in, - const local_SSAt::var_sett &cs_globals_out); + const local_SSAt::var_sett &globals_out, + const local_SSAt::var_sett &cs_globals_in, + const local_SSAt::var_sett &cs_globals_out, + int counter); - exprt get_replace_globals_in( - const local_SSAt::var_sett &globals_in, - const local_SSAt::var_sett &globals); - exprt get_replace_params( + void get_replace_globals_in( + const local_SSAt::var_sett &globals_in, + const function_application_exprt &funapp_expr, + const local_SSAt::var_sett &globals, + exprt::operandst &c, + int counter); + void get_replace_params( + const local_SSAt &SSA, const local_SSAt::var_listt ¶ms, - const function_application_exprt &funapp_expr); - exprt get_replace_globals_out( - const local_SSAt::var_sett &globals_out, - const local_SSAt::var_sett &cs_globals_in, - const local_SSAt::var_sett &cs_globals_out); + local_SSAt::nodest::const_iterator n_it, + const function_application_exprt &funapp_expr, + exprt::operandst &c, + int counter); + void get_replace_globals_out( + const local_SSAt::var_sett &globals_out, + const function_application_exprt &funapp_expr, + const local_SSAt::var_sett &cs_globals_in, + const local_SSAt::var_sett &cs_globals_out, + exprt::operandst &c, + int counter); - void rename(exprt &expr); - void rename(local_SSAt::nodet &node); + void rename(local_SSAt::nodet &node, int counter); }; #endif diff --git a/src/ssa/ssa_object.cpp b/src/ssa/ssa_object.cpp index d3aa56993..4f27c722c 100644 --- a/src/ssa/ssa_object.cpp +++ b/src/ssa/ssa_object.cpp @@ -37,6 +37,18 @@ bool is_ptr_object(const exprt &src) src.get(ID_ptr_object)!=irep_idt(); } +/*******************************************************************\ + +Function: collect_objects_rec + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + void collect_objects_rec( const exprt &src, const namespacet &ns, From 5c2e297ce447d079a9030d8204c2b5bae98c8c06 Mon Sep 17 00:00:00 2001 From: Peter Schrammel Date: Sat, 23 Apr 2016 16:31:04 +0100 Subject: [PATCH 02/82] all commits of old branch --- src/deltacheck/deltacheck_parse_options.cpp | 347 +++++ src/deltacheck/deltacheck_parse_options.h | 52 + src/deltagit/deltagit_parse_options.cpp | 206 +++ src/deltagit/deltagit_parse_options.h | 30 + src/domains/disjunctive_analyzer.cpp | 302 ++++ src/domains/disjunctive_analyzer.h | 51 + src/domains/domain_refinement.h | 39 + src/domains/domain_refinement_variables.cpp | 20 + src/html/syntax_highlighting.cpp | 306 ++++ src/html/syntax_highlighting.h | 35 + src/ssa/const_propagator.cpp | 467 ++++++ src/ssa/const_propagator.h | 101 ++ src/ssa/replace_symbol_ext.cpp | 82 + src/ssa/replace_symbol_ext.h | 20 + src/ssa/ssa_const_propagator.cpp | 305 ++++ src/ssa/ssa_const_propagator.h | 80 + src/ssa/ssa_dependency_graph.cpp | 385 +++++ src/ssa/ssa_dependency_graph.h | 62 + src/ssa/ssa_slicer.cpp | 181 +++ src/ssa/ssa_slicer.h | 44 + src/ssa/ssa_value_set.cpp | 3 +- src/storefront/data.cpp | 84 + src/storefront/data.h | 40 + src/storefront/file_view.cpp | 147 ++ src/storefront/file_view.h | 14 + src/storefront/property_view.cpp | 30 + src/storefront/property_view.h | 14 + src/storefront/storefront_main.cpp | 38 + src/storefront/storefront_parse_options.cpp | 121 ++ src/storefront/storefront_parse_options.h | 29 + src/storefront/trace_view.cpp | 29 + src/storefront/trace_view.h | 14 + src/summarizer/function_signature.cpp | 78 + src/summarizer/function_signature.h | 17 + src/summarizer/instrument_goto.cpp | 180 +++ src/summarizer/instrument_goto.h | 55 + src/summarizer/preprocessing_util.cpp | 265 ++++ src/summarizer/summarizer.cpp | 125 ++ src/summarizer/summarizer.h | 45 + src/summarizer/summarizer_bw_cex.cpp | 100 ++ src/summarizer/summarizer_bw_cex.h | 51 + src/summarizer/summarizer_bw_cex_ai.cpp | 511 ++++++ src/summarizer/summarizer_bw_cex_ai.h | 76 + src/summarizer/summarizer_bw_cex_all.cpp | 75 + src/summarizer/summarizer_bw_cex_all.h | 73 + src/summarizer/summarizer_bw_cex_complete.cpp | 525 +++++++ src/summarizer/summarizer_bw_cex_complete.h | 64 + src/summarizer/summarizer_bw_cex_concrete.cpp | 614 ++++++++ src/summarizer/summarizer_bw_cex_concrete.h | 77 + src/summarizer/summarizer_bw_cex_wp.cpp | 645 ++++++++ src/summarizer/summarizer_bw_cex_wp.h | 76 + src/summarizer/summarizer_fw_contexts.cpp | 174 +++ src/summarizer/summarizer_fw_contexts.h | 59 + src/summarizer/summarizer_parse_options.cpp | 1380 +++++++++++++++++ src/summarizer/summarizer_parse_options.h | 142 ++ src/summarizer/summary_checker_ai.cpp | 145 ++ src/summarizer/summary_checker_ai.h | 29 + src/summarizer/summary_checker_base.cpp | 684 ++++++++ src/summarizer/summary_checker_base.h | 102 ++ src/summarizer/summary_checker_bmc.cpp | 63 + src/summarizer/summary_checker_bmc.h | 26 + src/summarizer/summary_checker_kind.cpp | 76 + src/summarizer/summary_checker_kind.h | 26 + 63 files changed, 10234 insertions(+), 2 deletions(-) create mode 100644 src/deltacheck/deltacheck_parse_options.cpp create mode 100644 src/deltacheck/deltacheck_parse_options.h create mode 100644 src/deltagit/deltagit_parse_options.cpp create mode 100644 src/deltagit/deltagit_parse_options.h create mode 100644 src/domains/disjunctive_analyzer.cpp create mode 100644 src/domains/disjunctive_analyzer.h create mode 100644 src/domains/domain_refinement.h create mode 100644 src/domains/domain_refinement_variables.cpp create mode 100644 src/html/syntax_highlighting.cpp create mode 100644 src/html/syntax_highlighting.h create mode 100644 src/ssa/const_propagator.cpp create mode 100644 src/ssa/const_propagator.h create mode 100644 src/ssa/replace_symbol_ext.cpp create mode 100644 src/ssa/replace_symbol_ext.h create mode 100644 src/ssa/ssa_const_propagator.cpp create mode 100644 src/ssa/ssa_const_propagator.h create mode 100644 src/ssa/ssa_dependency_graph.cpp create mode 100644 src/ssa/ssa_dependency_graph.h create mode 100644 src/ssa/ssa_slicer.cpp create mode 100644 src/ssa/ssa_slicer.h create mode 100644 src/storefront/data.cpp create mode 100644 src/storefront/data.h create mode 100644 src/storefront/file_view.cpp create mode 100644 src/storefront/file_view.h create mode 100644 src/storefront/property_view.cpp create mode 100644 src/storefront/property_view.h create mode 100644 src/storefront/storefront_main.cpp create mode 100644 src/storefront/storefront_parse_options.cpp create mode 100644 src/storefront/storefront_parse_options.h create mode 100644 src/storefront/trace_view.cpp create mode 100644 src/storefront/trace_view.h create mode 100644 src/summarizer/function_signature.cpp create mode 100644 src/summarizer/function_signature.h create mode 100644 src/summarizer/instrument_goto.cpp create mode 100644 src/summarizer/instrument_goto.h create mode 100644 src/summarizer/preprocessing_util.cpp create mode 100644 src/summarizer/summarizer.cpp create mode 100644 src/summarizer/summarizer.h create mode 100644 src/summarizer/summarizer_bw_cex.cpp create mode 100644 src/summarizer/summarizer_bw_cex.h create mode 100644 src/summarizer/summarizer_bw_cex_ai.cpp create mode 100644 src/summarizer/summarizer_bw_cex_ai.h create mode 100644 src/summarizer/summarizer_bw_cex_all.cpp create mode 100644 src/summarizer/summarizer_bw_cex_all.h create mode 100644 src/summarizer/summarizer_bw_cex_complete.cpp create mode 100644 src/summarizer/summarizer_bw_cex_complete.h create mode 100644 src/summarizer/summarizer_bw_cex_concrete.cpp create mode 100644 src/summarizer/summarizer_bw_cex_concrete.h create mode 100644 src/summarizer/summarizer_bw_cex_wp.cpp create mode 100644 src/summarizer/summarizer_bw_cex_wp.h create mode 100644 src/summarizer/summarizer_fw_contexts.cpp create mode 100644 src/summarizer/summarizer_fw_contexts.h create mode 100644 src/summarizer/summarizer_parse_options.cpp create mode 100644 src/summarizer/summarizer_parse_options.h create mode 100644 src/summarizer/summary_checker_ai.cpp create mode 100644 src/summarizer/summary_checker_ai.h create mode 100644 src/summarizer/summary_checker_base.cpp create mode 100644 src/summarizer/summary_checker_base.h create mode 100644 src/summarizer/summary_checker_bmc.cpp create mode 100644 src/summarizer/summary_checker_bmc.h create mode 100644 src/summarizer/summary_checker_kind.cpp create mode 100644 src/summarizer/summary_checker_kind.h diff --git a/src/deltacheck/deltacheck_parse_options.cpp b/src/deltacheck/deltacheck_parse_options.cpp new file mode 100644 index 000000000..4938e4300 --- /dev/null +++ b/src/deltacheck/deltacheck_parse_options.cpp @@ -0,0 +1,347 @@ +/*******************************************************************\ + +Module: Command Line Interface + +Author: Daniel Kroening, kroening@kroening.com + +\*******************************************************************/ + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "deltacheck_parse_options.h" +#include "version.h" +#include "analyzer.h" +#include "change_impact.h" +#include "../functions/path_util.h" + +/*******************************************************************\ + +Function: deltacheck_parse_optionst::deltacheck_parse_optionst + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +deltacheck_parse_optionst::deltacheck_parse_optionst( + int argc, const char **argv): + parse_options_baset(DELTACHECK_OPTIONS, argc, argv), + xml_interfacet(cmdline), + ui_message_handler( + cmdline.isset("xml-ui")?ui_message_handlert::XML_UI:ui_message_handlert::PLAIN, + "DeltaCheck " DELTACHECK_VERSION) +{ +} + +/*******************************************************************\ + +Function: deltacheck_parse_optionst::eval_verbosity + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +void deltacheck_parse_optionst::eval_verbosity() +{ + // our default verbosity + int v=messaget::M_STATISTICS; + + if(cmdline.isset("verbosity")) + { + v=unsafe_string2int(cmdline.get_value("verbosity")); + if(v<0) + v=0; + else if(v>10) + v=10; + } + + ui_message_handler.set_verbosity(v); +} + +/*******************************************************************\ + +Function: deltacheck_parse_optionst::get_command_line_options + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +void deltacheck_parse_optionst::get_command_line_options(optionst &options) +{ + if(config.set(cmdline)) + { + usage_error(); + exit(1); + } + + if(cmdline.isset("debug-level")) + options.set_option("debug-level", cmdline.get_value("debug-level")); + + // check array bounds + if(cmdline.isset("bounds-check")) + options.set_option("bounds-check", true); + else + options.set_option("bounds-check", false); + + // check division by zero + if(cmdline.isset("div-by-zero-check")) + options.set_option("div-by-zero-check", true); + else + options.set_option("div-by-zero-check", false); + + // check overflow/underflow + if(cmdline.isset("signed-overflow-check")) + options.set_option("signed-overflow-check", true); + else + options.set_option("signed-overflow-check", false); + + // check overflow/underflow + if(cmdline.isset("unsigned-overflow-check")) + options.set_option("unsigned-overflow-check", true); + else + options.set_option("unsigned-overflow-check", false); + + // check for NaN (not a number) + if(cmdline.isset("nan-check")) + options.set_option("nan-check", true); + else + options.set_option("nan-check", false); + + // check pointers + if(cmdline.isset("pointer-check")) + options.set_option("pointer-check", true); + else + options.set_option("pointer-check", false); + + // do we do inlining? + if(cmdline.isset("no-inlining")) + options.set_option("partial-inlining", false); + else + options.set_option("partial-inlining", true); + + // check assertions + options.set_option("assertions", true); + + // use assumptions + options.set_option("assumptions", true); +} + +/*******************************************************************\ + +Function: deltacheck_parse_optionst::register_langauges + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +void deltacheck_parse_optionst::register_languages() +{ + register_language(new_ansi_c_language); + register_language(new_cpp_language); +} + +/*******************************************************************\ + +Function: deltacheck_parse_optionst::doit + + Inputs: + + Outputs: + + Purpose: invoke main modules + +\*******************************************************************/ + +int deltacheck_parse_optionst::doit() +{ + if(cmdline.isset("version")) + { + std::cout << DELTACHECK_VERSION << std::endl; + return 0; + } + + register_languages(); + + // command line options + + optionst options; + get_command_line_options(options); + set_message_handler(ui_message_handler); + eval_verbosity(); + + try + { + options.set_option("simplify", true); + options.set_option("assertions", true); + options.set_option("assumptions", true); + + if(cmdline.isset("function")) + options.set_option("function", cmdline.get_value("function")); + + if(cmdline.args.size()!=2) + { + usage_error(); + return 10; + } + + if(cmdline.isset("description-old")) + options.set_option("description-old", cmdline.get_value("description-old")); + else + options.set_option("description-old", cmdline.args[0]); + + if(cmdline.isset("description-new")) + options.set_option("description-new", cmdline.get_value("description-new")); + else + options.set_option("description-new", cmdline.args[1]); + + status() << "Reading first GOTO program from file" << eom; + + goto_modelt goto_model1; + + if(read_goto_binary(cmdline.args[0], + goto_model1, get_message_handler())) + return 10; + + status() << "Reading second GOTO program from file" << eom; + + goto_modelt goto_model2; + + if(read_goto_binary(cmdline.args[1], + goto_model2, get_message_handler())) + return 10; + + if(cmdline.isset("show-diff")) + { + change_impactt change_impact; + change_impact.set_message_handler(get_message_handler()); + + change_impact.diff(goto_model1, goto_model2); + change_impact.output_diff(std::cout); + } + else if(cmdline.isset("show-change-impact")) + { + change_impactt change_impact; + change_impact.set_message_handler(get_message_handler()); + + status() << "Computing syntactic difference" << eom; + change_impact.diff(goto_model1, goto_model2); + + status() << "Change-impact analysis" << eom; + change_impact.change_impact(goto_model2); + + change_impact.output_change_impact(std::cout); + } + else + { + std::string path1=get_directory(cmdline.args[0]); + std::string path2=get_directory(cmdline.args[1]); + + deltacheck_analyzer( + path1, goto_model1, + path2, goto_model2, + options, get_message_handler()); + } + + return 0; + } + + catch(const char *e) + { + error() << e << eom; + return 13; + } + + catch(const std::string &e) + { + error() << e << eom; + return 13; + } + + catch(int) + { + return 13; + } + + catch(std::bad_alloc) + { + error() << "Out of memory" << eom; + return 14; + } + + return 0; +} + +/*******************************************************************\ + +Function: deltacheck_parse_optionst::help + + Inputs: + + Outputs: + + Purpose: display command line help + +\*******************************************************************/ + +void deltacheck_parse_optionst::help() +{ + std::cout << + "\n" + "* * DELTACHECK " DELTACHECK_VERSION " - Copyright (C) 2011-2015 * *\n" + "* * based on CBMC " CBMC_VERSION " * *\n" + "* * Daniel Kroening * *\n" + "* * Oxford University, Computer Science Department * *\n" + "* * kroening@kroening.com * *\n" + "\n" + "Usage: Purpose:\n" + "\n" + " deltacheck [-?] [-h] [--help] show help\n" + " deltacheck prog1 prog2 delta check two programs\n" + "\n" + "Delta checking options:\n" + " --show-change-impact show syntactic change-impact\n" + " --description-old text description of old version\n" + " --description-new text description of new version\n" + "\n" + "Safety checks:\n" + " --bounds-check add array bounds checks\n" + " --div-by-zero-check add division by zero checks\n" + " --pointer-check add pointer checks\n" + " --signed-overflow-check add arithmetic over- and underflow checks\n" + " --unsigned-overflow-check add arithmetic over- and underflow checks\n" + " --nan-check add floating-point NaN checks\n" + "\n" + "Other options:\n" + " --version show version and exit\n" + " --xml-ui use XML-formatted output\n" + " --xml-interface stdio-XML interface\n" + "\n"; +} diff --git a/src/deltacheck/deltacheck_parse_options.h b/src/deltacheck/deltacheck_parse_options.h new file mode 100644 index 000000000..dbeb2fa6d --- /dev/null +++ b/src/deltacheck/deltacheck_parse_options.h @@ -0,0 +1,52 @@ +/*******************************************************************\ + +Module: Command Line Interface + +Author: Daniel Kroening, kroening@kroening.com + +\*******************************************************************/ + +#ifndef CPROVER_DELTACHECK_PARSE_OPTIONS_H +#define CPROVER_DELTACHECK_PARSE_OPTIONS_H + +#include +#include +#include + +#include +#include + +#define DELTACHECK_OPTIONS \ + "(function):" \ + "(debug-level):" \ + "(xml-ui)(xml-interface)" \ + "(verbosity):(version)(index):(description-old):(description-new):" \ + "(bounds-check)(pointer-check)(div-by-zero-check)" \ + "(signed-overflow-check)(unsigned-overflow-check)(nan-check)" \ + "(show-ssa)(show-defs)(show-guards)(show-fixed-points)" \ + "(show-properties)(show-change-impact)(show-diff)" \ + "(no-inline)(sat)" + +class deltacheck_parse_optionst: + public parse_options_baset, + public xml_interfacet, + public messaget +{ +public: + virtual int doit(); + virtual void help(); + + deltacheck_parse_optionst( + int argc, const char **argv); + +protected: + virtual void register_languages(); + + virtual void get_command_line_options(optionst &options); + + void eval_verbosity(); + + ui_message_handlert ui_message_handler; +}; + +#endif diff --git a/src/deltagit/deltagit_parse_options.cpp b/src/deltagit/deltagit_parse_options.cpp new file mode 100644 index 000000000..bbd8f4e1d --- /dev/null +++ b/src/deltagit/deltagit_parse_options.cpp @@ -0,0 +1,206 @@ +/*******************************************************************\ + +Module: Command Line Interface + +Author: Daniel Kroening, kroening@kroening.com + +\*******************************************************************/ + +#include + +#include + +#include + +#include "../deltacheck/version.h" + +#include "show_jobs.h" +#include "do_job.h" +#include "init.h" +#include "reset.h" +#include "reanalyse.h" +#include "deltagit_parse_options.h" +#include "revisions_report.h" + +/*******************************************************************\ + +Function: deltagit_parse_optionst::deltagit_parse_optionst + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +deltagit_parse_optionst::deltagit_parse_optionst( + int argc, const char **argv): + parse_options_baset(DELTACHECK_OPTIONS, argc, argv) +{ +} + +/*******************************************************************\ + +Function: deltagit_parse_optionst::doit + + Inputs: + + Outputs: + + Purpose: invoke main modules + +\*******************************************************************/ + +int deltagit_parse_optionst::doit() +{ + if(cmdline.isset("version")) + { + std::cout << DELTACHECK_VERSION << std::endl; + return 0; + } + + try + { + if(cmdline.args.size()==0) + { + usage_error(); + return 10; + } + + const std::string command=cmdline.args[0]; + + if(command=="jobs") + { + show_jobs(std::cout); + } + else if(command=="init") + { + if(cmdline.args.size()==1) + { + init(0); + } + else if(cmdline.args.size()==2) + { + init(atoi(cmdline.args[1].c_str())); + } + else + { + usage_error(); + return 10; + } + } + else if(command=="do") + { + if(cmdline.args.size()==2) + { + do_job(cmdline.args[1]); + } + else if(cmdline.args.size()==1) + { + do_job(); + } + else + { + usage_error(); + return 10; + } + } + else if(command=="reset") + { + if(cmdline.args.size()==2) + reset(cmdline.args[1]); + else if(cmdline.args.size()==1) + reset(); + else + { + usage_error(); + return 10; + } + } + else if(command=="reanalyse") + { + if(cmdline.args.size()==2) + reanalyse(cmdline.args[1]); + else if(cmdline.args.size()==1) + reanalyse(); + else + { + usage_error(); + return 10; + } + } + else if(command=="report") + { + bool partial_html=cmdline.isset("partial-html"); + unsigned max_revs=0; + std::string rel_path; + if(cmdline.isset("max-revs")) + max_revs=unsafe_string2unsigned(cmdline.get_value("max-revs")); + if(partial_html) + rel_path=cmdline.get_value("partial-html"); + revisions_report(partial_html, rel_path, max_revs); + } + else + { + usage_error(); + return 10; + } + } + + catch(const std::string &e) + { + std::cerr << e << std::endl; + return 13; + } + + catch(std::bad_alloc) + { + std::cerr << "Out of memory" << std::endl; + return 14; + } + + return 0; +} + +/*******************************************************************\ + +Function: deltagit_parse_optionst::help + + Inputs: + + Outputs: + + Purpose: display command line help + +\*******************************************************************/ + +void deltagit_parse_optionst::help() +{ + std::cout << + "\n" + "* * DELTAGIT " DELTACHECK_VERSION " - Copyright (C) 2012-2013 * *\n" + "* * Daniel Kroening * *\n" + "* * Oxford University, Computer Science Department * *\n" + "* * kroening@kroening.com * *\n" + "\n" + "Usage: Purpose:\n" + "\n" + " deltagit [-?] [-h] [--help] show help\n" + " deltagit init set up the jobs\n" + " deltagit jobs list the jobs\n" + " deltagit do do given job\n" + " deltagit do do a job that needs work\n" + " deltagit reset clear failure bit on all jobs\n" + " deltagit reanalyse redo analysis\n" + " deltagit report generate top-level report\n" + "\n" + "Reporting options:\n" + " --partial-html generate a partial HTML file \"include.html\"\n" + " --max-revs report on the last revisions\n" + "\n" + "Other options:\n" + " --version show version and exit\n" + " --xml-ui use XML-formatted output\n" + "\n"; +} diff --git a/src/deltagit/deltagit_parse_options.h b/src/deltagit/deltagit_parse_options.h new file mode 100644 index 000000000..357f563ab --- /dev/null +++ b/src/deltagit/deltagit_parse_options.h @@ -0,0 +1,30 @@ +/*******************************************************************\ + +Module: Command Line Interface + +Author: Daniel Kroening, kroening@kroening.com + +\*******************************************************************/ + +#ifndef CPROVER_DELTACHECK_PARSE_OPTIONS_H +#define CPROVER_DELTACHECK_PARSE_OPTIONS_H + +#include + +#define DELTACHECK_OPTIONS \ + "(verbosity):(version)(description):" \ + "(max-revs):(partial-html):" + +class deltagit_parse_optionst:public parse_options_baset +{ +public: + virtual int doit(); + virtual void help(); + + deltagit_parse_optionst( + int argc, const char **argv); + +protected: +}; + +#endif diff --git a/src/domains/disjunctive_analyzer.cpp b/src/domains/disjunctive_analyzer.cpp new file mode 100644 index 000000000..b82e3cfa0 --- /dev/null +++ b/src/domains/disjunctive_analyzer.cpp @@ -0,0 +1,302 @@ +/*******************************************************************\ + +Module: Data Flow Analysis + +Author: Peter Schrammel, Kumar Madhukar + +\*******************************************************************/ + +#include +#include + +#include "ssa_analyzer.h" +#include "disjunctive_analyzer.h" + + +/*******************************************************************\ + +Function: disjunctive_analyzert::eliminate_implication() + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +void disjunctive_analyzert::eliminate_implication(exprt &formula) +{ + if(formula.id() == ID_implies) + formula = or_exprt(not_exprt(formula.op0()), formula.op1()); + + Forall_operands(it, formula) + eliminate_implication(*it); + + return; +} + +/*******************************************************************\ + +Function: disjunctive_analyzert::push_negation_to_atoms() + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +void disjunctive_analyzert::push_negation_to_atoms(exprt &formula) +{ + if(formula.id() == ID_not){ + if((formula.op0()).id() == ID_not){ + formula = (formula.op0()).op0(); + } + else{ + exprt::operandst operands; + Forall_operands(it, formula.op0()) + operands.push_back(not_exprt(*it)); + + if((formula.op0()).id() == ID_and){ + formula = disjunction(operands); + } + else{ + if((formula.op0()).id() == ID_or){ + formula = conjunction(operands); + } + } + } + } + + Forall_operands(it, formula) + push_negation_to_atoms(*it); + + return; +} + +/*******************************************************************\ + +Function: disjunctive_analyzert::convert_to_dnf() + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +void disjunctive_analyzert::convert_to_dnf(exprt &formula) +{ + this->eliminate_implication(formula); + this->push_negation_to_atoms(formula); + this->convert_to_dnf_rec(formula); + + return; +} + +/*******************************************************************\ + +Function: disjunctive_analyzert::convert_to_dnf_rec() + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +void disjunctive_analyzert::convert_to_dnf_rec(exprt &formula) +{ + if(formula.id() == ID_or){ + Forall_operands(it, formula) + convert_to_dnf_rec(*it); + } + else{ + if(formula.id() == ID_and){ + + Forall_operands(it, formula) + convert_to_dnf_rec(*it); + + while((formula.operands()).size() > 1){ + exprt::operandst first_operands, second_operands, combination; + + if(((formula.operands()).back()).id() == ID_or) + first_operands = ((formula.operands()).back()).operands(); + else + first_operands.push_back((formula.operands()).back()); + formula.operands().pop_back(); + + if(((formula.operands()).back()).id() == ID_or) + second_operands = ((formula.operands()).back()).operands(); + else + second_operands.push_back((formula.operands()).back()); + formula.operands().pop_back(); + + for(exprt::operandst::iterator f_it=first_operands.begin();f_it!=first_operands.end();f_it++){ + for(exprt::operandst::iterator s_it=second_operands.begin();s_it!=second_operands.end();s_it++){ + combination.push_back(and_exprt(*f_it,*s_it)); + } + } + + (formula.operands()).push_back(disjunction(combination)); + } + formula = formula.op0(); + } + } + + return; +} + +/*******************************************************************\ + +Function: disjunctive_analyzert::operator() + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +bool disjunctive_analyzert::operator()( + incremental_solvert &solver, + local_SSAt &SSA, + const exprt &side_conditions, + template_generator_baset &template_generator, + const exprt &disjunctive_conditions, + exprt &result_expr, + const domaint::var_sett &vars + ) +{ + bool response = true; + exprt::operandst result; + + //std::cout << "unsimplified disjunctive cond: " << from_expr(SSA.ns, "", disjunctive_conditions) << "\n\n"; + exprt simple_disjunctive_conditions = simplify_expr(disjunctive_conditions, SSA.ns); //disjunctive_conditions; + //std::cout << "simplified disjunctive cond: " << from_expr(SSA.ns, "", simple_disjunctive_conditions) << "\n\n"; + + //converting simple_disjunctive_conditions into DNF + //std::cout << "before conversion: " << from_expr(SSA.ns, "", simple_disjunctive_conditions) << "\n\n\n"; + this->convert_to_dnf(simple_disjunctive_conditions); + //std::cout << "after conversion: " << from_expr(SSA.ns, "", simple_disjunctive_conditions) << "\n\n\n"; + + if(simple_disjunctive_conditions.id() == ID_or){ + + exprt::operandst processed_disjuncts; + + exprt::operandst disjuncts=simple_disjunctive_conditions.operands(); + for(exprt::operandst::iterator d_it=disjuncts.begin();d_it!=disjuncts.end();d_it++){ + if((*d_it).id() == ID_not){ + exprt::operandst ops = (*d_it).operands(); + for(exprt::operandst::iterator o_it=ops.begin();o_it!=ops.end();o_it++){ + if((*o_it).id() == ID_equal){ + exprt::operandst ops_equality = (*o_it).operands(); + + equal_exprt equal_expr_in_not = to_equal_expr(*o_it); + + bool constant_comparison = false; + for(exprt::operandst::iterator oe_it=ops_equality.begin();oe_it!=ops_equality.end();oe_it++){ + if((*oe_it).id() == ID_constant) + constant_comparison = true; + } + if(constant_comparison){ + processed_disjuncts.push_back(binary_relation_exprt(equal_expr_in_not.rhs(),ID_gt,equal_expr_in_not.lhs())); + processed_disjuncts.push_back(binary_relation_exprt(equal_expr_in_not.rhs(),ID_lt,equal_expr_in_not.lhs())); + } + else{ + processed_disjuncts.push_back(*d_it); + } + } + } + } + else{ + processed_disjuncts.push_back(*d_it); + } + } + + for(exprt::operandst::iterator it=processed_disjuncts.begin();it!=processed_disjuncts.end();it++){ + + //std::cout << "disjunct: " << from_expr(SSA.ns, "", *it) << "\n"; + + std::set disjunct_symbols; + find_symbols(*it,disjunct_symbols); + + //TODO: decompose into convex regions for all variables + //assert(disjunct_symbols.size() == 1); + + symbol_exprt var; + for(std::set::const_iterator ds_it=disjunct_symbols.begin(); + ds_it!=disjunct_symbols.end(); ds_it++){ + var = *ds_it; + } + //std::cout << "symbol expr in disjunct: " << var << "\n\n"; + + exprt::operandst split_disjuncts; + + if((var.type().id() == ID_signedbv) || (var.type().id() == ID_unsignedbv)){ + + exprt smallest; + if(var.type().id()==ID_signedbv) + smallest = to_signedbv_type(var.type()).smallest_expr(); + if(var.type().id()==ID_unsignedbv) + smallest = to_unsignedbv_type(var.type()).smallest_expr(); + + split_disjuncts.push_back + (and_exprt(*it,binary_relation_exprt(var,ID_ge,plus_exprt(smallest,from_integer(mp_integer(1),var.type()))))); + + split_disjuncts.push_back(and_exprt(*it,binary_relation_exprt(var,ID_equal,smallest))); + } + else{ + split_disjuncts.push_back(*it); + } + + for(exprt::operandst::iterator s_it=split_disjuncts.begin();s_it!=split_disjuncts.end();s_it++){ + ssa_analyzert analyzer; + analyzer.set_message_handler(get_message_handler()); + exprt cc = simplify_expr((and_exprt(side_conditions, *s_it)), SSA.ns); + response = response && (analyzer(solver,SSA,cc,template_generator)); + + exprt res; + analyzer.get_result(res, vars); + result.push_back(res); + + //std::cout << "disjunct passed: " << from_expr(SSA.ns, "", cc) << "\n"; + //std::cout << "disjunct's result: " << from_expr(SSA.ns, "", res) << "\n"; + + //statistics + solver_instances += analyzer.get_number_of_solver_instances(); + solver_calls += analyzer.get_number_of_solver_calls(); + } + } + } + else{ + //for the complete disjunctive_conditions at once + //std::cout << "disjunction not at top-level" << "\n"; + + ssa_analyzert analyzer; + analyzer.set_message_handler(get_message_handler()); + exprt cc = simplify_expr((and_exprt(side_conditions, simple_disjunctive_conditions)), SSA.ns); + + response = analyzer(solver,SSA,cc,template_generator); + + exprt res; + analyzer.get_result(res, vars); + result.push_back(res); + + //std::cout << "disjunct passed: " << from_expr(SSA.ns, "", cc) << "\n"; + //std::cout << "disjunct's result: " << from_expr(SSA.ns, "", res) << "\n"; + + //statistics + solver_instances += analyzer.get_number_of_solver_instances(); + solver_calls += analyzer.get_number_of_solver_calls(); + } + + result_expr = disjunction(result); + return response; +} + diff --git a/src/domains/disjunctive_analyzer.h b/src/domains/disjunctive_analyzer.h new file mode 100644 index 000000000..322d4a0a6 --- /dev/null +++ b/src/domains/disjunctive_analyzer.h @@ -0,0 +1,51 @@ +/*******************************************************************\ + +Module: Data Flow Analysis + +Author: Peter Schrammel, Kumar Madhukar + +\*******************************************************************/ + +#ifndef DELTACHECK_DISJUNCTIVE_ANALYZER_H +#define DELTACHECK_DISJUNCTIVE_ANALYZER_H + +class disjunctive_analyzert : public messaget +{ + public: + explicit disjunctive_analyzert() + : + solver_instances(0), + solver_calls(0) + { + } + + ~disjunctive_analyzert() + { + } + + void eliminate_implication(exprt &formula); + void push_negation_to_atoms(exprt &formula); + void convert_to_dnf(exprt &formula); + void convert_to_dnf_rec(exprt &formula); + + bool operator()(incremental_solvert &solver, + local_SSAt &SSA, + const exprt &side_conditions, + template_generator_baset &template_generator, + const exprt &disjunctive_conditions, + exprt &result_expr, + const domaint::var_sett &vars + ); + + unsigned get_number_of_solver_instances() { return solver_instances; } + unsigned get_number_of_solver_calls() { return solver_calls; } + +protected: + //statistics + unsigned solver_instances; + unsigned solver_calls; +}; + + +#endif + diff --git a/src/domains/domain_refinement.h b/src/domains/domain_refinement.h new file mode 100644 index 000000000..58d53cf9b --- /dev/null +++ b/src/domains/domain_refinement.h @@ -0,0 +1,39 @@ +/*******************************************************************\ + +Module: Domain Refinement Interface + +Author: Peter Schrammel + +\*******************************************************************/ + +#ifndef CPROVER_DOMAIN_REFINEMENT_H +#define CPROVER_DOMAIN_REFINEMENT_H + +#include "incremental_solver.h" +#include "template_generator_base.h" +#include "../ssa/local_SSA.h" + +class domain_refinementt +{ +public: + explicit domain_refinementt( + const local_SSAt &_SSA, + incremental_solvert &_solver) + : + SSA(_SSA), + solver(_solver) + {} + + //refine, returns true if there are no more refinements + virtual bool operator()() { return true; } + + //template generators associated with this SSA and solver + typedef std::map template_generatorst; + template_generatorst template_generators; + +protected: + const local_SSAt &SSA; + incremental_solvert &solver; +}; + +#endif diff --git a/src/domains/domain_refinement_variables.cpp b/src/domains/domain_refinement_variables.cpp new file mode 100644 index 000000000..f8e313ea4 --- /dev/null +++ b/src/domains/domain_refinement_variables.cpp @@ -0,0 +1,20 @@ +/*******************************************************************\ + +Module: Domain Refinement: Choice of Variables + +Author: Peter Schrammel + +\*******************************************************************/ + +bool domain_refinementt::operator()() +{ + //TODO: analyze counterexample + for(template_generatorst::iterator it = template_generators.begin(); + it != template_generators.end(); ++it) + { + //TODO: select refinement to be performed + + //TODO: update template and domain + //it->add_template(); + } +} diff --git a/src/html/syntax_highlighting.cpp b/src/html/syntax_highlighting.cpp new file mode 100644 index 000000000..5c6e078d0 --- /dev/null +++ b/src/html/syntax_highlighting.cpp @@ -0,0 +1,306 @@ +/*******************************************************************\ + +Module: Syntax Highlighting + +Author: Daniel Kroening, kroening@kroening.com + +\*******************************************************************/ + +// may wish to try http://www.gnu.org/software/src-highlite/ + +#include +#include +#include +#include + +#include "../html/html_escape.h" +#include "syntax_highlighting.h" + +/*******************************************************************\ + +Function: is_keyword + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +const char *keywords[]= +{ + "auto", "_Bool", "break", "case", "char", "_Complex", "const", "continue", + "default", "do", "double", "else", "enum", "extern", "float", "for", + "goto", "if", "inline", "int", "long", "register", "restrict", "return", + "short", "signed", "sizeof", "static", "struct", "switch", "typedef", + "union", "unsigned", "void", "volatile", "while", "__float128", + "__int128", "__int8", "__int16", "__int32", "__int64", "__ptr32", + "__ptr64", "__complex__", "__complex", "__real__" , "__real", "__imag__" , + "__imag", "offsetof", "__asm", "asm", "__asm__", "bool", "catch", "class", + "constexpr", "delete", "decltype", "explicit", "friend", "mutable", + "namespace", "new", "nullptr", "operator", "private", "protected", + "public", "static_assert", "template", "this", "thread_local", "throw", + "typeid", "typename", "using", "virtual", "wchar_t", "typeof", NULL +}; + +bool is_keyword(const std::string &token) +{ + for(unsigned i=0; keywords[i]!=NULL; i++) + { + if(strcmp(keywords[i], token.c_str())==0) + return true; + } + + return false; +} + +/*******************************************************************\ + + Class: tokenizert + + Purpose: + +\*******************************************************************/ + +const char *tokens[]= +{ "++", "+=", "--", "-=", "&&", "&=", "||", "|=", "/*", + "*/", "//", "%=", "/=", "<<", ">>", "<<=", ">>=", "==", + "!=", "<=", ">=", "::", "->", "##", ".*", "->*", NULL }; + +class tokenizert +{ +public: + explicit tokenizert(const std::string &_buf):buf(_buf) + { + } + + std::string get(); + std::string peek(); + std::string buf; + bool eol() const { return buf.empty(); } + + char get_char() + { + if(buf.empty()) return 0; + char result=buf[0]; + buf.erase(0, 1); + return result; + } + + static inline bool is_identifier_char(char ch) + { + return isalnum(ch) || ch=='_'; + } +}; + +/*******************************************************************\ + +Function: tokenizert::peek + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +std::string tokenizert::peek() +{ + if(buf.empty()) return buf; + + char first=buf[0]; + + unsigned pos=1; + + if(is_identifier_char(first)) + { + // identifier or keyword or number + for(pos=1; pos"; + + if(comment) out << ""; + + std::string token; + + std::map var_count; + + while(!tokenizer.eol()) + { + if(comment) + { + std::string buf; + bool end_of_comment=false; + + while(!end_of_comment) + { + char ch=tokenizer.get_char(); + if(ch==0) break; + buf+=ch; + if(buf.size()>=2 && buf[buf.size()-2]=='*' && buf[buf.size()-1]=='/') + end_of_comment=true; + } + + out << html_escape(buf); + + if(end_of_comment) + { + out << ""; + comment=false; + } + } + else + { + token=tokenizer.get(); + assert(!token.empty()); + + if(isdigit(token[0])) // numeral + { + out << html_escape(token); + } + else if(isalpha(token[0])) + { + if(is_keyword(token)) + out << "" << html_escape(token) << ""; + else + { + if(identifier_tooltip) + out << ""; + else + out << ""; + + out << html_escape(token); + + out << ""; + } + } + else if(token=="/*") + { + comment=true; + out << "" << token; + } + else if(token=="//") + { + out << "" << token; + while(!(token=tokenizer.get()).empty()) + out << html_escape(token); + out << ""; + } + else if(token[0]=='"' || token[0]=='\'') + { + out << "" << html_escape(token) << ""; + } + else + { + // hack to distinguish lhs from rhs without parsing + #if 0 + if(token=="+=" || token=="=" || + token=="-=" || token=="<<=" || + token==">>=" || token=="&=" || + token=="^=" || token=="|=") + lhs=false; + else if(token==";") + lhs=true; + #endif + + out << html_escape(token); + } + } + } + + // close tags + if(comment) out << ""; + if(!strong_class.empty()) out << ""; + + out << "\n"; +} + diff --git a/src/html/syntax_highlighting.h b/src/html/syntax_highlighting.h new file mode 100644 index 000000000..159abcc28 --- /dev/null +++ b/src/html/syntax_highlighting.h @@ -0,0 +1,35 @@ +/*******************************************************************\ + +Module: Syntax Highlighting + +Author: Daniel Kroening, kroening@kroening.com + +\*******************************************************************/ + +#ifndef CPROVER_SYNTAX_HIGHLIGHTING_H +#define CPROVER_SYNTAX_HIGHLIGHTING_H + +#include +#include + +class syntax_highlightingt +{ +public: + explicit syntax_highlightingt(std::ostream &_out): + line_no(0), identifier_tooltip(false), + out(_out), comment(false) { } + + std::string strong_class; + unsigned line_no; + std::string id_suffix; + + bool identifier_tooltip; + + void operator()(const std::string &line); + +protected: + std::ostream &out; + bool comment; +}; + +#endif diff --git a/src/ssa/const_propagator.cpp b/src/ssa/const_propagator.cpp new file mode 100644 index 000000000..747f2af93 --- /dev/null +++ b/src/ssa/const_propagator.cpp @@ -0,0 +1,467 @@ +/*******************************************************************\ + +Module: Constant Propagation + +Author: Peter Schrammel + +\*******************************************************************/ + +//#define DEBUG + +#include + +#include +#include + +#include "const_propagator.h" + +/*******************************************************************\ + +Function: const_propagator_domaint::assign_rec + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +void const_propagator_domaint::assign_rec(const exprt &lhs, const exprt &rhs, + const namespacet &ns) +{ + const typet & rhs_type = ns.follow(rhs.type()); + +#ifdef DEBUG + std::cout << "assign: " << from_expr(ns, "", lhs) + << " := " << from_type(ns, "", rhs_type) << std::endl; +#endif + + if(lhs.id()==ID_symbol && rhs_type.id()!=ID_array + && rhs_type.id()!=ID_struct + && rhs_type.id()!=ID_union) + { + if(!values.maps_to_top(rhs)) + assign(values,lhs,rhs,ns); + else + values.set_to_top(lhs); + } +#if 0 + else //TODO: could make field or array element-sensitive + { + } +#endif +} + +/*******************************************************************\ + +Function: const_propagator_domaint::transform + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +void const_propagator_domaint::transform( + locationt from, + locationt to, + ai_baset &ai, + const namespacet &ns) +{ +#ifdef DEBUG + std::cout << from->location_number << " --> " + << to->location_number << std::endl; +#endif + + if(from->is_decl()) + { + values.set_to_top(to_code_decl(from->code).symbol()); + } + else if(from->is_assign()) + { + const code_assignt &assignment=to_code_assign(from->code); + const exprt &lhs = assignment.lhs(); + const exprt &rhs = assignment.rhs(); + assign_rec(lhs,rhs,ns); + } + else if(from->is_goto()) + { + if(from->guard.id()==ID_equal && from->get_target()==to) + { + const exprt &lhs = from->guard.op0(); + const exprt &rhs = from->guard.op1(); + + assign_rec(lhs,rhs,ns); + assign_rec(rhs,lhs,ns); + } + } + else if(from->is_dead()) + { + const code_deadt &code_dead=to_code_dead(from->code); + values.set_to_top(code_dead.symbol()); + } + else if(from->is_function_call()) + { + values.set_all_to_top(); + } + +#ifdef DEBUG + output(std::cout,ai,ns); +#endif +} + +/*******************************************************************\ + +Function: const_propagator_domaint::assign + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +void const_propagator_domaint::assign( + valuest &dest, + const exprt &lhs, + exprt rhs, + const namespacet &ns) const +{ +#ifdef DEBUG + std::cout << "assign: " << from_expr(ns, "", lhs) + << " := " << from_expr(ns, "", rhs) << std::endl; +#endif + + values.replace_const(rhs); + + //this is to remove casts in constants propagated into the size of array types + bool valid = true; + exprt rhs_val = evaluate_casts_in_constants(rhs,lhs.type(),valid); + if(valid) + dest.set_to(lhs,rhs_val); +} + +/*******************************************************************\ + +Function: const_propagator_domaint::valuest::maps_to_top + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +bool const_propagator_domaint::valuest::maps_to_top(const exprt &expr) const +{ + if(expr.id()==ID_side_effect && + to_side_effect_expr(expr).get_statement()==ID_nondet) + return true; + if(expr.id()==ID_symbol) + if(replace_const.expr_map.find(expr.get(ID_identifier)) + == replace_const.expr_map.end()) + return true; + forall_operands(it,expr) + { + if(maps_to_top(*it)) + return true; + } + return false; +} + +/*******************************************************************\ + +Function: const_propagator_domaint::valuest::set_to_top + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +bool const_propagator_domaint::valuest::set_to_top(const irep_idt &id) +{ + bool result = false; + replace_symbolt::expr_mapt::iterator r_it = + replace_const.expr_map.find(id); + if(r_it != replace_const.expr_map.end()) + { + replace_const.expr_map.erase(r_it); + result = true; + } + if(top_ids.find(id)==top_ids.end()) + { + top_ids.insert(id); + result = true; + } + return result; +} + +bool const_propagator_domaint::valuest::set_to_top(const exprt &expr) +{ + return set_to_top(to_symbol_expr(expr).get_identifier()); +} + +void const_propagator_domaint::valuest::set_all_to_top() +{ + for(replace_symbolt::expr_mapt::iterator it = + replace_const.expr_map.begin(); + it != replace_const.expr_map.end(); ++it) + top_ids.insert(it->first); + replace_const.expr_map.clear(); +} + + +/*******************************************************************\ + +Function: const_propagator_domaint::valuest::add + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +void const_propagator_domaint::valuest::set_to(const irep_idt &lhs_id, + const exprt &rhs_val) +{ + replace_const.expr_map[lhs_id] = rhs_val; + std::set::iterator it = top_ids.find(lhs_id); + if(it!=top_ids.end()) top_ids.erase(it); +} + +void const_propagator_domaint::valuest::set_to(const exprt &lhs, + const exprt &rhs_val) +{ + const irep_idt &lhs_id = to_symbol_expr(lhs).get_identifier(); + set_to(lhs_id,rhs_val); +} + +/*******************************************************************\ + +Function: const_propagator_domaint::valuest::output + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +void const_propagator_domaint::valuest::output( + std::ostream &out, + const namespacet &ns) const +{ + out << "const map: " << std::endl; + for(replace_symbolt::expr_mapt::const_iterator + it=replace_const.expr_map.begin(); + it!=replace_const.expr_map.end(); + ++it) + out << ' ' << it->first << "=" << + from_expr(ns, "", it->second) << std::endl; + out << "top ids: " << std::endl; + for(std::set::const_iterator + it=top_ids.begin(); + it!=top_ids.end(); + ++it) + out << ' ' << *it << std::endl; +} + +/*******************************************************************\ + +Function: const_propagator_domaint::output + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +void const_propagator_domaint::output( + std::ostream &out, + const ai_baset &ai, + const namespacet &ns) const +{ + values.output(out,ns); +} + +/*******************************************************************\ + +Function: const_propagator_domaint::valuest::merge + + Inputs: + + Outputs: Return true if "this" has changed. + + Purpose: + +\*******************************************************************/ + +bool const_propagator_domaint::valuest::merge(const valuest &src) +{ + bool changed = false; + for(replace_symbolt::expr_mapt::const_iterator + it=src.replace_const.expr_map.begin(); + it!=src.replace_const.expr_map.end(); ++it) + { + replace_symbolt::expr_mapt::iterator + c_it = replace_const.expr_map.find(it->first); + if(c_it != replace_const.expr_map.end()) + { + if(c_it->second != it->second) + { + set_to_top(it->first); + changed = true; + } + } + else if(top_ids.find(it->first)==top_ids.end()) + { + set_to(it->first,it->second); + changed = true; + } + } + for(std::set::const_iterator it=src.top_ids.begin(); + it!=src.top_ids.end(); ++it) + { + bool c = set_to_top(*it); + changed = changed || c; + } + + return changed; +} + +/*******************************************************************\ + +Function: const_propagator_domaint::merge + + Inputs: + + Outputs: Return true if "this" has changed. + + Purpose: + +\*******************************************************************/ + +bool const_propagator_domaint::merge( + const const_propagator_domaint &other, + locationt from, + locationt to) +{ + return values.merge(other.values); +} + +/*******************************************************************\ + +Function: const_propagator_domaint::evaluate_casts_in_constants + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +exprt const_propagator_domaint::evaluate_casts_in_constants(exprt expr, + const typet& parent_type, bool &valid) const +{ + if(expr.id()==ID_side_effect) + { + valid = false; + return expr; + } + if(expr.type().id()!=ID_signedbv && expr.type().id()!=ID_unsignedbv) + return expr; + if(expr.id()==ID_typecast) + expr = evaluate_casts_in_constants(expr.op0(),expr.type(),valid); + if(expr.id()!=ID_constant) + { + if(expr.type()!=parent_type) + return typecast_exprt(expr,parent_type); + else + return expr; + } + //TODO: could be improved to resolve float casts as well... + if(expr.type().id()!=ID_signedbv && expr.type().id()!=ID_unsignedbv) + return expr; + mp_integer v; + to_integer(to_constant_expr(expr), v); + return from_integer(v,parent_type); +} + +/*******************************************************************\ + +Function: const_propagator_ait::replace + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +void const_propagator_ait::replace( + goto_functionst::goto_functiont &goto_function, + const namespacet &ns) +{ + Forall_goto_program_instructions(it, goto_function.body) + { + state_mapt::iterator s_it = state_map.find(it); + if(s_it == state_map.end()) + continue; + replace_types_rec(s_it->second.values.replace_const, it->code); + replace_types_rec(s_it->second.values.replace_const, it->guard); + if(it->is_goto() || it->is_assume() || it->is_assert()) + { + s_it->second.values.replace_const(it->guard); + } + else if(it->is_assign()) + { + exprt &rhs = to_code_assign(it->code).rhs(); + s_it->second.values.replace_const(rhs); + } + else if(it->is_function_call()) + { + exprt::operandst &args = + to_code_function_call(it->code).arguments(); + for(exprt::operandst::iterator o_it = args.begin(); + o_it != args.end(); ++o_it) + s_it->second.values.replace_const(*o_it); + } + } +} + +/*******************************************************************\ + +Function: const_propagator_ait::replace_types_rec + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +void const_propagator_ait::replace_types_rec( + const replace_symbolt &replace_const, + exprt &expr) +{ + replace_const(expr.type()); + Forall_operands(it,expr) + replace_types_rec(replace_const,*it); +} + diff --git a/src/ssa/const_propagator.h b/src/ssa/const_propagator.h new file mode 100644 index 000000000..6d017f8b9 --- /dev/null +++ b/src/ssa/const_propagator.h @@ -0,0 +1,101 @@ +/*******************************************************************\ + +Module: Constant propagation + +Author: Peter Schrammel + +\*******************************************************************/ + +#ifndef CPROVER_CONST_PROPAGATOR_H +#define CPROVER_CONST_PROPAGATOR_H + +#include + +#include +#include "replace_symbol_ext.h" + +class const_propagator_domaint:public ai_domain_baset +{ +public: + virtual void transform(locationt, locationt, ai_baset &, const namespacet &); + virtual void output(std::ostream &, const ai_baset &, const namespacet &) const; + bool merge(const const_propagator_domaint &, locationt, locationt); + + struct valuest + { + public: + // maps variables to constants + replace_symbol_extt replace_const; + std::set top_ids; + + void output(std::ostream &, const namespacet &) const; + + bool merge(const valuest &src); + + inline void clear() + { + replace_const.expr_map.clear(); + replace_const.type_map.clear(); + top_ids.clear(); + } + + bool empty() const + { + return replace_const.expr_map.empty() && + replace_const.type_map.empty() && + top_ids.empty(); + } + + void set_to(const exprt &lhs, const exprt &rhs_val); + void set_to(const irep_idt &lhs_id, const exprt &rhs_val); + + bool maps_to_top(const exprt &expr) const; + bool set_to_top(const exprt &expr); + bool set_to_top(const irep_idt &id); + void set_all_to_top(); + }; + + valuest values; + +protected: + void assign( + valuest &dest, + const exprt &lhs, + exprt rhs, + const namespacet &ns) const; + + void assign_rec(const exprt &lhs, const exprt &rhs, + const namespacet &ns); + + exprt evaluate_casts_in_constants( + exprt expr, + const typet& parent_type, + bool &valid) const; + +}; + +class const_propagator_ait:public ait +{ +public: + const_propagator_ait( + goto_functionst::goto_functiont &goto_function, + const namespacet &ns) + { + operator()(goto_function, ns); +// output(ns,goto_function.body,"",std::cout); + replace(goto_function, ns); + } + +protected: + friend class const_propagator_domaint; + +void replace( + goto_functionst::goto_functiont &goto_function, + const namespacet &ns); + +void replace_types_rec( + const replace_symbolt &replace_const, + exprt &expr); +}; + +#endif diff --git a/src/ssa/replace_symbol_ext.cpp b/src/ssa/replace_symbol_ext.cpp new file mode 100644 index 000000000..7d77633aa --- /dev/null +++ b/src/ssa/replace_symbol_ext.cpp @@ -0,0 +1,82 @@ +/*******************************************************************\ + +Module: Modified expression replacement for constant propagator + +Author: Peter Schrammel + +\*******************************************************************/ + +#include +#include + +#include "replace_symbol_ext.h" + +/*******************************************************************\ + +Function: replace_symbol_extt::replace + + Inputs: + + Outputs: + + Purpose: does not replace object in address_of expressions + +\*******************************************************************/ + +bool replace_symbol_extt::replace(exprt &dest) const +{ + bool result=true; + + // first look at type + + if(have_to_replace(dest.type())) + if(!replace_symbolt::replace(dest.type())) + result=false; + + // now do expression itself + + if(!have_to_replace(dest)) + return result; + + if(dest.id()==ID_address_of) + { + const exprt &object = to_address_of_expr(dest).object(); + if(object.id()==ID_symbol) + { + expr_mapt::const_iterator it= + expr_map.find(object.get(ID_identifier)); + + if(it!=expr_map.end()) + return false; + } + } + else if(dest.id()==ID_symbol) + { + expr_mapt::const_iterator it= + expr_map.find(dest.get(ID_identifier)); + + if(it!=expr_map.end()) + { + dest=it->second; + return false; + } + } + + Forall_operands(it, dest) + if(!replace(*it)) + result=false; + + const irept &c_sizeof_type=dest.find(ID_C_c_sizeof_type); + + if(c_sizeof_type.is_not_nil() && + !replace_symbolt::replace(static_cast(dest.add(ID_C_c_sizeof_type)))) + result=false; + + const irept &va_arg_type=dest.find(ID_C_va_arg_type); + + if(va_arg_type.is_not_nil() && + !replace_symbolt::replace(static_cast(dest.add(ID_C_va_arg_type)))) + result=false; + + return result; +} diff --git a/src/ssa/replace_symbol_ext.h b/src/ssa/replace_symbol_ext.h new file mode 100644 index 000000000..2aac30957 --- /dev/null +++ b/src/ssa/replace_symbol_ext.h @@ -0,0 +1,20 @@ +/*******************************************************************\ + +Module: Modified expression replacement for constant propagator + +Author: Peter Schrammel + +\*******************************************************************/ + +#ifndef CPROVER_REPLACE_SYMBOL_EXT_H +#define CPROVER_REPLACE_SYMBOL_EXT_H + +#include + +class replace_symbol_extt : public replace_symbolt +{ +public: + virtual bool replace(exprt &dest) const; +}; + +#endif diff --git a/src/ssa/ssa_const_propagator.cpp b/src/ssa/ssa_const_propagator.cpp new file mode 100644 index 000000000..4ca296238 --- /dev/null +++ b/src/ssa/ssa_const_propagator.cpp @@ -0,0 +1,305 @@ +/*******************************************************************\ + +Module: SSA Constant Propagator + +Author: Kumar Madhukar, Peter Schrammel + +\*******************************************************************/ + +//#define DEBUG + +#ifdef DEBUG +#include +#include +#endif + +#include +#include +#include + +#include "ssa_const_propagator.h" + + +//bool iterate = true; + + +/*******************************************************************\ + +Function: ssa_const_propagatort::operator() + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +void ssa_const_propagatort::operator()(std::list &dest, + const local_SSAt &src) +{ + values.iterate = true; + while(values.iterate){ + values.iterate = false; + for(local_SSAt::nodest::const_iterator n_it = src.nodes.begin(); + n_it != src.nodes.end(); n_it++) + { + const local_SSAt::nodet &node=*n_it; + + // check if node is active; 'continue' if not active + if(!node.enabling_expr.is_true()) + continue; + + // if src.enabling_exprs does not have a true in the end, then also continue + if(src.enabling_exprs.size() > 0) + if((src.enabling_exprs.back()).is_true()) + continue; + + for(local_SSAt::nodet::equalitiest::const_iterator e_it=node.equalities.begin(); + e_it!=node.equalities.end(); e_it++) + { + equal_exprt e = to_equal_expr(*e_it); + const exprt &lhs = e.lhs(); + exprt &temprhs = e.rhs(); + + // resolving conditional expressions + while(temprhs.id() == ID_if){ + exprt simp_guard; +#ifdef DEBUG + std::cout << "guard: " << from_expr(src.ns, "", temprhs.op0()) << std::endl; +#endif + simp_guard = simplify_expr(temprhs.op0(), src.ns); +#ifdef DEBUG + std::cout << "simplified: " << from_expr(src.ns, "", simp_guard) << std::endl; +#endif + if(simp_guard.is_true()) + temprhs = temprhs.op1(); + else if(simp_guard.is_false()) + temprhs = temprhs.op2(); + else + break; + } + + const exprt &rhs = temprhs; + valuest copy_values = values; + + if(!copy_values.maps_to_top(rhs)) + assign(copy_values,lhs,rhs,src.ns); + else + copy_values.set_to_top(lhs); + +#ifdef DEBUG + copy_values.output(std::cout,src.ns); +#endif + + if(rhs.id() == ID_symbol){ + if(!values.maps_to_top(lhs)) + assign(values,rhs,lhs,src.ns); + else + values.set_to_top(rhs); + } + +#ifdef DEBUG + values.output(std::cout,src.ns); +#endif + + values.merge(copy_values); + +#ifdef DEBUG + values.output(std::cout,src.ns); +#endif + } + + for(local_SSAt::nodet::constraintst::const_iterator c_it=n_it->constraints.begin(); + c_it!=n_it->constraints.end(); c_it++) + { + if(c_it->id()!=ID_equal) + continue; + + const equal_exprt e = to_equal_expr(*c_it); + const exprt &lhs = e.lhs(); + const exprt &rhs = e.rhs(); + + // if lhs is a variable and rhs is a constant expression + + valuest copy_values = values; + + if(!copy_values.maps_to_top(rhs)) + assign(copy_values,lhs,rhs,src.ns); + else + copy_values.set_to_top(lhs); + +#ifdef DEBUG + copy_values.output(std::cout,src.ns); +#endif + + // if rhs is a variable and lhs is a constant expression + + if(!values.maps_to_top(lhs)) + assign(values,rhs,lhs,src.ns); + else + values.set_to_top(rhs); + +#ifdef DEBUG + values.output(std::cout,src.ns); +#endif + + values.merge(copy_values); + +#ifdef DEBUG + values.output(std::cout,src.ns); +#endif + + } + } + } + +#ifdef DEBUG + values.output(std::cout,src.ns); +#endif + + // iterate over values and get all equalities + for(replace_symbolt::expr_mapt::const_iterator + it=values.replace_const.expr_map.begin(); + it!=values.replace_const.expr_map.end(); + ++it){ + + //std::cout << ' ' << it->first << " = " << + // from_expr(src.ns, "", it->second) << std::endl; + + dest.push_back(equal_exprt(symbol_exprt(it->first,it->second.type()),it->second)); + + } +} + +bool ssa_const_propagatort::valuest::maps_to_top(const exprt &expr) const +{ + find_symbols_sett symbols; + find_symbols(expr,symbols); + for(find_symbols_sett::const_iterator it = symbols.begin(); + it != symbols.end(); ++it) + { + if(replace_const.expr_map.find(*it) + == replace_const.expr_map.end()) + return true; + } + return false; +} + + +void ssa_const_propagatort::assign( + valuest &dest, + const exprt &lhs, + exprt rhs, + const namespacet &ns) const +{ +#ifdef DEBUG + std::cout << "assign: " << from_expr(ns, "", lhs) + << " := " << from_expr(ns, "", rhs) << std::endl; +#endif + + values.replace_const(rhs); + +#ifdef DEBUG + std::cout << "replace: " << from_expr(ns, "", lhs) + << " := " << from_expr(ns, "", rhs) << std::endl; +#endif + + rhs = simplify_expr(rhs,ns); + +#ifdef DEBUG + std::cout << "simplified: " << from_expr(ns, "", lhs) + << " := " << from_expr(ns, "", rhs) << std::endl; +#endif + + dest.set_to(lhs,rhs); +} + +bool ssa_const_propagatort::valuest::set_to_top(const irep_idt &id) +{ + bool result = false; + replace_symbolt::expr_mapt::iterator r_it = + replace_const.expr_map.find(id); + if(r_it != replace_const.expr_map.end()) + { + replace_const.expr_map.erase(r_it); + result = true; + } + if(top_ids.find(id)==top_ids.end()) + { + top_ids.insert(id); + result = true; + } + return result; +} + +bool ssa_const_propagatort::valuest::set_to_top(const exprt &expr) +{ + return set_to_top(to_symbol_expr(expr).get_identifier()); +} + +void ssa_const_propagatort::valuest::set_to(const irep_idt &lhs_id, + const exprt &rhs_val) +{ + + if(replace_const.expr_map[lhs_id] != rhs_val){ + replace_const.expr_map[lhs_id] = rhs_val; + iterate = true; + } + std::set::iterator it = top_ids.find(lhs_id); + if(it!=top_ids.end()) top_ids.erase(it); +} + +void ssa_const_propagatort::valuest::set_to(const exprt &lhs, + const exprt &rhs_val) +{ + const irep_idt &lhs_id = to_symbol_expr(lhs).get_identifier(); + set_to(lhs_id,rhs_val); +} + +void ssa_const_propagatort::valuest::output( + std::ostream &out, + const namespacet &ns) const +{ + out << "const map: " << std::endl; + for(replace_symbolt::expr_mapt::const_iterator + it=replace_const.expr_map.begin(); + it!=replace_const.expr_map.end(); + ++it) + out << ' ' << it->first << "=" << + from_expr(ns, "", it->second) << std::endl; + out << "top ids: " << std::endl; + for(std::set::const_iterator + it=top_ids.begin(); + it!=top_ids.end(); + ++it) + out << ' ' << *it << std::endl; +} + +bool ssa_const_propagatort::valuest::merge(const valuest &src) +{ + bool changed = false; + for(replace_symbolt::expr_mapt::const_iterator + it=src.replace_const.expr_map.begin(); + it!=src.replace_const.expr_map.end(); ++it) + { + replace_symbolt::expr_mapt::iterator + c_it = replace_const.expr_map.find(it->first); + if(c_it != replace_const.expr_map.end()) + { + if(c_it->second != it->second) + { + set_to_top(it->first); + changed = true; + } + } + else if(top_ids.find(it->first)==top_ids.end()) + { + set_to(it->first,it->second); + changed = true; + } + } + + return changed; +} + diff --git a/src/ssa/ssa_const_propagator.h b/src/ssa/ssa_const_propagator.h new file mode 100644 index 000000000..ee89071db --- /dev/null +++ b/src/ssa/ssa_const_propagator.h @@ -0,0 +1,80 @@ +/*******************************************************************\ + +Module: SSA Constant Propagator + +Author: Kumar Madhukar, Peter Schrammel + +\*******************************************************************/ + +#ifndef CPROVER_SSA_CONST_PROPAGATOR_H +#define CPROVER_SSA_CONST_PROPAGATOR_H + +#include +#include + +#include "local_ssa.h" + +class ssa_const_propagatort : public messaget +{ + public: + + void operator()(std::list &dest, + const local_SSAt &src); + + struct valuest + { + public: + // maps variables to constants + replace_symbolt replace_const; + std::set top_ids; + + void output(std::ostream &, const namespacet &) const; + + bool merge(const valuest &src); + + + inline void clear() + { + replace_const.expr_map.clear(); + replace_const.type_map.clear(); + top_ids.clear(); + } + + bool empty() const + { + return replace_const.expr_map.empty() && + replace_const.type_map.empty() && + top_ids.empty(); + } + + void set_to(const exprt &lhs, const exprt &rhs_val); + void set_to(const irep_idt &lhs_id, const exprt &rhs_val); + + bool maps_to_top(const exprt &expr) const; + bool set_to_top(const exprt &expr); + bool set_to_top(const irep_idt &id); + + bool iterate; + + }; + + valuest values; + + protected: + + void assign( + valuest &dest, + const exprt &lhs, + exprt rhs, + const namespacet &ns) const; + + exprt evaluate_casts_in_constants( + exprt expr, + const typet& parent_type, + bool &valid) const; + + + +}; + +#endif diff --git a/src/ssa/ssa_dependency_graph.cpp b/src/ssa/ssa_dependency_graph.cpp new file mode 100644 index 000000000..26bf05fba --- /dev/null +++ b/src/ssa/ssa_dependency_graph.cpp @@ -0,0 +1,385 @@ + +#include +#include +#include + +#include "ssa_dependency_graph.h" + +void ssa_dependency_grapht::output(std::ostream &out) const +{ + for(unsigned index = 0; index < depnodes_map.size(); index++) + { + out << "Node#" << index << "; info: " << from_expr(ns, "", depnodes_map[index].node_info) << "\n"; + out << "Node#" << index << "; -> Used Symbols: "; + for(find_symbols_sett::const_iterator u_it=depnodes_map[index].used_symbols.begin(); + u_it!=depnodes_map[index].used_symbols.end(); u_it++){ + out << *u_it << " "; + } + out << "\n"; + + out << "Node#" << index << "; -> Modified Symbols: "; + for(find_symbols_sett::const_iterator m_it=depnodes_map[index].modified_symbols.begin(); + m_it!=depnodes_map[index].modified_symbols.end(); m_it++){ + out << *m_it << " "; + } + out << "\n"; + + out << "Successors: "; + for(unsigned i = 0; i < depnodes_map[index].successors.size(); i++){ + out << depnodes_map[index].successors[i] << " "; + } + out << "\n"; + + out << "Predecessors:\n"; + for(ssa_dependency_grapht::annotated_predecessorst::const_iterator p_it = depnodes_map[index].predecessors.begin(); + p_it != depnodes_map[index].predecessors.end(); p_it++){ + annotated_predecessort pred = *p_it; + int pred_index = pred.predecessor_node_index; + find_symbols_sett pred_annotation = pred.annotation; + out << " " << "Predecessor Node#" << pred_index << "; Annotation: "; + for(find_symbols_sett::const_iterator s_it=pred_annotation.begin(); + s_it!=pred_annotation.end(); s_it++){ out << *s_it << " "; } + out << "\n"; } out << "\n"; + } + out << "\n\n"; +} + +void ssa_dependency_grapht::create(const local_SSAt &SSA, ssa_inlinert &ssa_inliner, bool entry) +{ + depnodet sink_node; + sink_node.is_assertion = false; + sink_node.is_function_call = false; + + // globals_out is the used_symbol of the sink_node + for(local_SSAt::var_sett::const_iterator g_it = SSA.globals_out.begin(); + g_it != SSA.globals_out.end(); g_it++){ + irep_idt id = (*g_it).get(ID_identifier); + sink_node.used_symbols.insert(id); + } + + exprt function_guard = SSA.guard_symbol(SSA.goto_function.body.instructions.begin()); + //std::cout << "function guard: " << from_expr(ns, "", function_guard) << "\n"; + + irep_idt id = function_guard.get(ID_identifier); + //std::cout << "guard identifier: " << id << "\n"; + sink_node.used_symbols.insert(id); + + depnodes_map.push_back(sink_node); + + // collect all the symbols to iterate over it + find_symbols_sett all_ssa_symbols; + + bool first_node = true; + bool ignore_equality = false; + bool ignore_equality_done = false; + + for(local_SSAt::nodest::const_iterator n_it = SSA.nodes.begin(); + n_it != SSA.nodes.end(); n_it++){ + + const local_SSAt::nodet &node=*n_it; + + // collecting symbols from equalities and populating dependency graph nodes + for(local_SSAt::nodet::equalitiest::const_iterator e_it=node.equalities.begin(); + e_it!=node.equalities.end(); e_it++) + { + + find_symbols(*e_it,all_ssa_symbols); + + depnodet temp_node; + temp_node.is_assertion = false; + temp_node.is_function_call = false; + temp_node.node_info = *e_it; + temp_node.location = n_it->location; + + //temp_node.trivial_guard = true; + + equal_exprt e = to_equal_expr(*e_it); + exprt &lhs = e.lhs(); exprt &rhs = e.rhs(); + + find_symbols(rhs,temp_node.used_symbols); + find_symbols(lhs,temp_node.modified_symbols); + + if(!ignore_equality_done){ + std::string var_string = id2string(to_symbol_expr(lhs).get_identifier()); + if(((var_string.substr(0,11)) == "ssa::$guard") && (rhs.is_true())){ + ignore_equality = true; + ignore_equality_done = true; + } + } + + if(first_node && ignore_equality){ + if(entry){ + depnodes_map.push_back(temp_node); + //std::cout << "created equality node, with info: " << from_expr(ns, "", *e_it) << "\n"; + } + ignore_equality = false; + } + else{ + depnodes_map.push_back(temp_node); + //std::cout << "created equality node, with info: " << from_expr(ns, "", *e_it) << "\n"; + } + + } + + // collecting symbols from constraints and populating dependency graph nodes + for(local_SSAt::nodet::constraintst::const_iterator c_it=node.constraints.begin(); + c_it!=node.constraints.end(); c_it++) + { + find_symbols(*c_it,all_ssa_symbols); + + depnodet temp_node; + temp_node.is_assertion = false; + temp_node.is_function_call = false; + temp_node.node_info = *c_it; + temp_node.location = n_it->location; + find_symbols(*c_it,temp_node.used_symbols); + find_symbols(*c_it,temp_node.modified_symbols); + depnodes_map.push_back(temp_node); + //std::cout << "created constraint node, with info: " << from_expr(ns, "", *c_it) << "\n"; + } + + // collecting symbols from assertionst and populating dependency graph nodes + for(local_SSAt::nodet::assertionst::const_iterator a_it=node.assertions.begin(); + a_it!=node.assertions.end(); a_it++) + { + find_symbols(*a_it,all_ssa_symbols); + + depnodet temp_node; + temp_node.is_assertion = true; + temp_node.is_function_call = false; + temp_node.node_info = *a_it; + temp_node.location = n_it->location; + find_symbols(*a_it,temp_node.used_symbols); + depnodes_map.push_back(temp_node); + //std::cout << "created assertion node, with info: " << from_expr(ns, "", *a_it) << "\n"; + } + + /* + // collecting symbols from assumptionst and populating dependency graph nodes + for(local_SSAt::nodet::assumptionst::const_iterator a_it=node.assumptions.begin(); + a_it!=node.assumptions.end(); a_it++) + { + find_symbols(*a_it,all_ssa_symbols); + + depnodet temp_node; + temp_node.is_assertion = false; + temp_node.is_function_call = false; + temp_node.node_info = *a_it; + find_symbols(*a_it,temp_node.used_symbols); + find_symbols(*a_it,temp_node.modified_symbols); + depnodes_map.push_back(temp_node); + //std::cout << "created assumption node, with info: " << from_expr(ns, "", *a_it) << "\n"; + } + */ + + // collecting symbols from function_callst and populating dependency graph nodes + for(local_SSAt::nodet::function_callst::const_iterator f_it=node.function_calls.begin(); + f_it!=node.function_calls.end(); f_it++) + { + //find_symbols(*f_it,all_ssa_symbols); + + irep_idt fname = to_symbol_expr(f_it->function()).get_identifier(); + if(ssa_db.exists(fname)) + { + const local_SSAt &fSSA = ssa_db.get(fname); + + /******************************************************************/ + /******* additional nodes needed to fix the dependency tree *******/ + + exprt guard_binding; + exprt::operandst bindings_in, bindings_out; + int counter = ssa_inliner.get_rename_counter(); + + /**/ + ssa_inliner.get_guard_binding(SSA,fSSA,n_it,guard_binding,counter); + //std::cout << "guard binding: " << from_expr(ns, "", guard_binding) << "\n"; + /* + { + depnodet temp_node; + temp_node.is_assertion = false; + temp_node.is_function_call = false; + temp_node.node_info = guard_binding; + + equal_exprt e = to_equal_expr(guard_binding); + exprt &lhs = e.lhs(); exprt &rhs = e.rhs(); + + find_symbols(rhs,temp_node.used_symbols); + find_symbols(lhs,temp_node.modified_symbols); + depnodes_map.push_back(temp_node); + //std::cout << "created guard binding node, with info: " << from_expr(ns, "", guard_binding) << "\n"; + } + */ + /**/ + + ssa_inliner.get_bindings(SSA,fSSA,n_it,f_it,bindings_in,bindings_out,counter); + + for(exprt::operandst::const_iterator b_it=bindings_in.begin(); + b_it!=bindings_in.end(); b_it++){ + + //std::cout << "binding: " << from_expr(ns, "", *b_it) << "\n"; + + depnodet temp_node; + temp_node.is_assertion = false; + temp_node.is_function_call = false; + temp_node.node_info = *b_it; + temp_node.location = n_it->location; + + equal_exprt e = to_equal_expr(*b_it); + exprt &lhs = e.lhs(); exprt &rhs = e.rhs(); + + find_symbols(rhs,temp_node.used_symbols); + find_symbols(lhs,temp_node.modified_symbols); + depnodes_map.push_back(temp_node); + //std::cout << "created binding in node, with info: " << from_expr(ns, "", *b_it) << "\n"; + } + + for(exprt::operandst::const_iterator b_it=bindings_out.begin(); + b_it!=bindings_out.end(); b_it++){ + + //std::cout << "binding: " << from_expr(ns, "", *b_it) << "\n"; + + depnodet temp_node; + temp_node.is_assertion = false; + temp_node.is_function_call = false; + temp_node.node_info = *b_it; + temp_node.location = n_it->location; + + equal_exprt e = to_equal_expr(*b_it); + exprt &lhs = e.lhs(); exprt &rhs = e.rhs(); + + find_symbols(rhs,temp_node.used_symbols); + find_symbols(lhs,temp_node.modified_symbols); + depnodes_map.push_back(temp_node); + //std::cout << "created binding out node, with info: " << from_expr(ns, "", *b_it) << "\n"; + } + + /******************************************************************/ + + depnodet temp_node; + temp_node.guard = guard_binding; + temp_node.is_assertion = false; + temp_node.is_function_call = true; + temp_node.node_info = *f_it; + temp_node.rename_counter = counter; + temp_node.location = n_it->location; + + find_symbols(guard_binding,temp_node.used_symbols); + + for(local_SSAt::var_listt::const_iterator p_it = fSSA.params.begin(); + p_it != fSSA.params.end(); p_it++){ + irep_idt id = (*p_it).get(ID_identifier); + irep_idt sym = ssa_inliner.rename(id, counter); + all_ssa_symbols.insert(sym); + temp_node.used_symbols.insert(sym); + } + + for(local_SSAt::var_sett::const_iterator g_it = fSSA.globals_in.begin(); + g_it != fSSA.globals_in.end(); g_it++){ + irep_idt id = (*g_it).get(ID_identifier); + irep_idt sym = ssa_inliner.rename(id, counter); + all_ssa_symbols.insert(sym); + temp_node.used_symbols.insert(sym); + } + + for(local_SSAt::var_sett::const_iterator g_it = fSSA.globals_out.begin(); + g_it != fSSA.globals_out.end(); g_it++){ + irep_idt id = (*g_it).get(ID_identifier); + irep_idt sym = ssa_inliner.rename(id, counter); + all_ssa_symbols.insert(sym); + temp_node.modified_symbols.insert(sym); + } + + depnodes_map.push_back(temp_node); + //std::cout << "created function node, with info: " << from_expr(ns, "", *f_it) << "\n"; + } + } + } + first_node = false; + + depnodet source_node; + source_node.is_assertion = false; + source_node.is_function_call = false; + + // params and globals_in are the modified_symbols at source_node + + for(local_SSAt::var_listt::const_iterator p_it = SSA.params.begin(); + p_it != SSA.params.end(); p_it++){ + irep_idt id = (*p_it).get(ID_identifier); + source_node.modified_symbols.insert(id); + } + + for(local_SSAt::var_sett::const_iterator g_it = SSA.globals_in.begin(); + g_it != SSA.globals_in.end(); g_it++){ + irep_idt id = (*g_it).get(ID_identifier); + source_node.modified_symbols.insert(id); + } + + depnodes_map.push_back(source_node); // source_node + //std::cout << "created source node, without any info" << "\n"; + + top_node_index = depnodes_map.size() - 1; + + for(find_symbols_sett::const_iterator + s_it=all_ssa_symbols.begin(); s_it!=all_ssa_symbols.end(); s_it++){ + + for(unsigned m_index = 0; m_index < depnodes_map.size(); m_index++){ + if(depnodes_map[m_index].modified_symbols.find(*s_it) != depnodes_map[m_index].modified_symbols.end()){ + + for(unsigned u_index = 0; u_index < depnodes_map.size(); u_index++){ + + if(m_index != u_index){ + if(depnodes_map[u_index].used_symbols.find(*s_it) != depnodes_map[u_index].used_symbols.end()){ + annotated_predecessort temp_pred; + temp_pred.predecessor_node_index = m_index; + temp_pred.annotation.insert(*s_it); + depnodes_map[u_index].predecessors.push_back(temp_pred); + depnodes_map[m_index].successors.push_back(u_index); + } + } + } + } + } + } + + if(depnodes_map.size() == 2){ + + //sink_node's successor is the source_node + annotated_predecessort def_pred; // successors of the default predecessors + def_pred.predecessor_node_index = top_node_index; + def_pred.annotation = depnodes_map[0].used_symbols; + depnodes_map[0].predecessors.push_back(def_pred); + + //source_node's successor is the sink_node + depnodes_map[top_node_index].successors.push_back(0); + + } + else{ + for(unsigned index = 1; index < depnodes_map.size() - 1; index++) + { + // if node does not have a predecessor + if(depnodes_map[index].predecessors.empty()){ + //its predecessor is the source_node + annotated_predecessort def_pred; // successors of the default predecessors + def_pred.predecessor_node_index = top_node_index; + def_pred.annotation = depnodes_map[index].used_symbols; + depnodes_map[index].predecessors.push_back(def_pred); + + //source_node's successor is this node + depnodes_map[top_node_index].successors.push_back(index); + } + + // if node does not have a successor + if(depnodes_map[index].successors.empty()){ + //its successor is the sink_node + depnodes_map[index].successors.push_back(0); + + //sink_node's predecessor is that node + annotated_predecessort pred_def; // predecessors of the default successor + pred_def.predecessor_node_index = index; + pred_def.annotation = depnodes_map[index].modified_symbols; + depnodes_map[0].predecessors.push_back(pred_def); + } + } + } + +} diff --git a/src/ssa/ssa_dependency_graph.h b/src/ssa/ssa_dependency_graph.h new file mode 100644 index 000000000..7d360f218 --- /dev/null +++ b/src/ssa/ssa_dependency_graph.h @@ -0,0 +1,62 @@ + +#ifndef CPROVER_DELTACHECK_SSA_DEPENDENCY_GRAPH_H +#define CPROVER_DELTACHECK_SSA_DEPENDENCY_GRAPH_H + +#include +#include + +#include "../summarizer/ssa_db.h" +#include "ssa_inliner.h" +#include "local_ssa.h" + +class ssa_inlinert; +class ssa_dbt; + +class ssa_dependency_grapht{ + public: + + inline ssa_dependency_grapht(ssa_dbt &_db, const namespacet &_ns): + ssa_db(_db), + ns(_ns) + {}; + + struct annotated_predecessort{ + int predecessor_node_index; + find_symbols_sett annotation; + }; + + typedef std::list annotated_predecessorst; + + struct depnodet{ + exprt node_info; + exprt guard; + bool is_assertion; + bool is_function_call; + //bool trivial_guard; + int rename_counter; + find_symbols_sett used_symbols; + find_symbols_sett modified_symbols; + annotated_predecessorst predecessors; + std::vector successors; + local_SSAt::locationt location; + }; + + //typedef std::map depnodest; + typedef std::vector depnodest; + depnodest depnodes_map; + + int top_node_index; + + //special source_node and sink_node + //depnodet source_node = depnodes_map[top_node_index]; + //depnodet sink_node = depnodes_map[0]; + + void create(const local_SSAt &SSA, ssa_inlinert &ssa_inliner, bool entry); + void output(std::ostream &) const; + + protected: + ssa_dbt &ssa_db; + const namespacet &ns; +}; + +#endif diff --git a/src/ssa/ssa_slicer.cpp b/src/ssa/ssa_slicer.cpp new file mode 100644 index 000000000..d1eafcb13 --- /dev/null +++ b/src/ssa/ssa_slicer.cpp @@ -0,0 +1,181 @@ +#include + +#include +#include + +#include "local_ssa.cpp" + +void print_symbols(std::string msg, const find_symbols_sett &symbols) +{ + std::cout << msg << ": " << std::endl; + for(find_symbols_sett::const_iterator + s_it=symbols.begin(); s_it!=symbols.end(); s_it++) + std::cout << " " << *s_it << std::endl; + +} + +void ssa_slicert::operator()(std::list &dest, + const local_SSAt &src) +{ + //collect symbols in assertions + find_symbols_sett new_symbols; + for(local_SSAt::nodest::const_iterator n_it = src.nodes.begin(); + n_it != src.nodes.end(); n_it++) + { + if(n_it->marked) continue; + if(n_it->assertions.empty()) continue; + for(local_SSAt::nodet::assertionst::const_iterator + a_it=n_it->assertions.begin(); + a_it!=n_it->assertions.end(); + a_it++) + { + find_symbols(*a_it,new_symbols); + } + } +#ifdef DEBUG + print_symbols("symbols in assertions",new_symbols); +#endif + if(new_symbols.empty()) return; + + //build map symbol -> (definition, constraint set) + symbol_mapt symbol_map; + sliced_equalities = 0; + sliced_constraints = 0; + + for(local_SSAt::nodest::const_iterator n_it = src.nodes.begin(); + n_it != src.nodes.end(); n_it++) + { + for(local_SSAt::nodet::equalitiest::const_iterator + e_it=n_it->equalities.begin(); + e_it!=n_it->equalities.end(); + e_it++) + { + find_symbols_sett e_symbols; + find_symbols(e_it->lhs(),e_symbols); + + for(find_symbols_sett::const_iterator + s_it=e_symbols.begin(); s_it!=e_symbols.end(); s_it++) + { + symbol_map[*s_it]; + symbol_map[*s_it].def = e_it; + symbol_map[*s_it].def_node = n_it; + } + } + for(local_SSAt::nodet::constraintst::const_iterator + c_it=n_it->constraints.begin(); + c_it!=n_it->constraints.end(); + c_it++) + { + find_symbols_sett c_symbols; + find_symbols(*c_it,c_symbols); + for(find_symbols_sett::const_iterator + s_it=c_symbols.begin(); s_it!=c_symbols.end(); s_it++) + { + if(symbol_map.find(*s_it)==symbol_map.end()) continue; + symbol_map[*s_it].constraints.push_back(constr_infot()); + constr_infot &constr_info = symbol_map[*s_it].constraints.back(); + constr_info.constr = c_it; + constr_info.node = n_it; + } + } + //statistics + if(!n_it->marked) + { + sliced_equalities += n_it->equalities.size(); + sliced_constraints += n_it->constraints.size(); + } + } + //statistics + std::cout << "Total equalities: " << sliced_equalities + << ", total constraints: " << sliced_constraints << std::endl; + + //compute backwards dependencies and add to formula on-the-fly + find_symbols_sett symbols_seen; + while(!new_symbols.empty()) + { + find_symbols_sett old_symbols = new_symbols; + +#ifdef DEBUG + print_symbols("new symbols",new_symbols); +#endif + + new_symbols.clear(); + for(find_symbols_sett::const_iterator + s_it=old_symbols.begin(); s_it!=old_symbols.end(); s_it++) + { + irep_idt sym = *s_it; + if(symbols_seen.find(sym)!=symbols_seen.end()) continue; + if(symbol_map.find(sym)==symbol_map.end()) + { + //handle loopback variables + //here it's getting a bit ugly + std::string sym_str = id2string(sym); + size_t pos1 = sym_str.find("#lb"); + if(pos1==std::string::npos) continue; + size_t pos2 = sym_str.find("%",pos1); + irep_idt basename = sym_str.substr(0,pos1); + std::string unwinder_suffix = ""; + if(pos2 + +#include "local_ssa.h" + +class ssa_slicert : public messaget +{ + public: + + void operator()(std::list &dest, + const local_SSAt &src); + + //statistics + unsigned sliced_equalities; + unsigned sliced_constraints; + + protected: + typedef struct + { + local_SSAt::nodet::constraintst::const_iterator constr; + local_SSAt::nodest::const_iterator node; + } constr_infot; + typedef std::list constraint_sett; + typedef struct + { + local_SSAt::nodet::equalitiest::const_iterator def; + local_SSAt::nodest::const_iterator def_node; + constraint_sett constraints; + } symbol_infot; + typedef hash_map_cont symbol_mapt; + +}; + +#endif diff --git a/src/ssa/ssa_value_set.cpp b/src/ssa/ssa_value_set.cpp index aa362160e..315bd1539 100644 --- a/src/ssa/ssa_value_set.cpp +++ b/src/ssa/ssa_value_set.cpp @@ -289,8 +289,7 @@ void ssa_value_domaint::assign_rhs_rec( if(m_it!=value_map.end()) { valuest tmp_values=m_it->second; - if(offset) - tmp_values.offset=true; +(??) tmp_values.alignment=merge_alignment(tmp_values.alignment, alignment); dest.merge(tmp_values); } diff --git a/src/storefront/data.cpp b/src/storefront/data.cpp new file mode 100644 index 000000000..391a40991 --- /dev/null +++ b/src/storefront/data.cpp @@ -0,0 +1,84 @@ +/*******************************************************************\ + +Module: Trace View + +Author: Daniel Kroening, kroening@kroening.com + +\*******************************************************************/ + +#include +#include + +#include + +#include "data.h" + +/*******************************************************************\ + +Function: datat::read + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +void datat::read(const std::string &file) +{ + xmlt xml; + + console_message_handlert message_handler; + parse_xml(file, message_handler, xml); + + read(xml); +} + +/*******************************************************************\ + +Function: datat::read + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +void datat::read(const xmlt &xml) +{ + for(xmlt::elementst::const_iterator + it=xml.elements.begin(); + it!=xml.elements.end(); + it++) + { + if(it->name=="property") + { + propertyt property; + + for(xmlt::elementst::const_iterator + e_it=it->elements.begin(); + e_it!=it->elements.end(); + e_it++) + { + if(e_it->name=="file") + property.file=e_it->data; + else if(e_it->name=="line") + property.line=unsafe_string2unsigned(e_it->data); + else if(e_it->name=="category") + property.category=e_it->data; + else if(e_it->name=="message") + property.message=e_it->data; + } + + properties.push_back(property); + } + else if(it->name=="description") + { + description=it->data; + } + } +} + diff --git a/src/storefront/data.h b/src/storefront/data.h new file mode 100644 index 000000000..046c58ceb --- /dev/null +++ b/src/storefront/data.h @@ -0,0 +1,40 @@ +/*******************************************************************\ + +Module: Data + +Author: Daniel Kroening, kroening@kroening.com + +\*******************************************************************/ + +#ifndef CPROVER_DELTACHECK_DATA_H +#define CPROVER_DELTACHECK_DATA_H + +#include + +class datat +{ +public: + class propertyt + { + public: + irep_idt file; + unsigned line; + irep_idt category; + std::string message; + }; + + typedef std::vector propertiest; + propertiest properties; + + std::string description; + + inline void add(const propertyt &e) + { + properties.push_back(e); + } + + void read(const std::string &file); + void read(const class xmlt &); +}; + +#endif diff --git a/src/storefront/file_view.cpp b/src/storefront/file_view.cpp new file mode 100644 index 000000000..a20041d77 --- /dev/null +++ b/src/storefront/file_view.cpp @@ -0,0 +1,147 @@ +/*******************************************************************\ + +Module: Trace View + +Author: Daniel Kroening, kroening@kroening.com + +\*******************************************************************/ + +#include +#include + +#include + +#include "../html/html_escape.h" +#include "../html/syntax_highlighting.h" + +#include "data.h" + +/*******************************************************************\ + +Function: file_view + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +void print_file(const datat &data, irep_idt file, std::ostream &out) +{ + out << "
\n"; + out << "
" << html_escape(file) << "
\n"; + out << "
\n"; + + std::ifstream in(file.c_str()); + if(!in) + { + } + else + { + // line to property number + std::map > line_map; + + for(datat::propertiest::const_iterator + e_it=data.properties.begin(); + e_it!=data.properties.end(); + e_it++) + if(e_it->file==file) + { + line_map[e_it->line].push_back(e_it-data.properties.begin()); + } + + syntax_highlightingt syntax_highlighting(out); + + unsigned line_no=1; + + std::string line; + while(std::getline(in, line)) + { + syntax_highlighting.strong_class=""; + syntax_highlighting.line_no=line_no; + + std::vector &properties=line_map[line_no]; + + if(!properties.empty()) + { + syntax_highlighting.strong_class="alarm"; + } + + syntax_highlighting(line); + + line_no++; + } + } + + out << "
\n\n"; +} + +/*******************************************************************\ + +Function: file_view + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +void file_view(const datat &data) +{ + std::ofstream out("file_view.html"); + + out << "\n\n"; + out << "" << html_escape(data.description) << "\n"; + + out << "\n"; + out << "\n"; + + out << "\n"; + + out << "
\n"; + + out << "
\n"; + out << html_escape(data.description) << "\n"; + out << "
\n"; + + std::set files; + + for(datat::propertiest::const_iterator + e_it=data.properties.begin(); + e_it!=data.properties.end(); + e_it++) + files.insert(e_it->file); + + for(std::set::const_iterator + f_it=files.begin(); + f_it!=files.end(); + f_it++) + { + if(has_prefix(id2string(*f_it), "/usr/include/")) + continue; + + if(has_prefix(id2string(*f_it), "")) + continue; + + print_file(data, *f_it, out); + } + + out << "\n\n"; +} diff --git a/src/storefront/file_view.h b/src/storefront/file_view.h new file mode 100644 index 000000000..e0c5ca8ee --- /dev/null +++ b/src/storefront/file_view.h @@ -0,0 +1,14 @@ +/*******************************************************************\ + +Module: File View + +Author: Daniel Kroening, kroening@kroening.com + +\*******************************************************************/ + +#ifndef CPROVER_DELTACHECK_FILE_VIEW_H +#define CPROVER_DELTACHECK_FILE_VIEW_H + +void file_view(const class datat &); + +#endif diff --git a/src/storefront/property_view.cpp b/src/storefront/property_view.cpp new file mode 100644 index 000000000..21c5b31e8 --- /dev/null +++ b/src/storefront/property_view.cpp @@ -0,0 +1,30 @@ +/*******************************************************************\ + +Module: Property View + +Author: Daniel Kroening, kroening@kroening.com + +\*******************************************************************/ + +#include "data.h" + +/*******************************************************************\ + +Function: property_view + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +void property_view(const class datat &) +{ + +} + + + + diff --git a/src/storefront/property_view.h b/src/storefront/property_view.h new file mode 100644 index 000000000..83f1eae61 --- /dev/null +++ b/src/storefront/property_view.h @@ -0,0 +1,14 @@ +/*******************************************************************\ + +Module: Property View + +Author: Daniel Kroening, kroening@kroening.com + +\*******************************************************************/ + +#ifndef CPROVER_DELTACHECK_PROPERTY_VIEW_H +#define CPROVER_DELTACHECK_PROPERTY_VIEW_H + +void property_view(const class datat &); + +#endif diff --git a/src/storefront/storefront_main.cpp b/src/storefront/storefront_main.cpp new file mode 100644 index 000000000..3914e4dbd --- /dev/null +++ b/src/storefront/storefront_main.cpp @@ -0,0 +1,38 @@ +/*******************************************************************\ + +Module: Main Module + +Author: Daniel Kroening, kroening@kroening.com + +\*******************************************************************/ + +#include + +#include "storefront_parse_options.h" + +/*******************************************************************\ + +Function: main + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +#ifdef _MSC_VER +int wmain(int argc, const wchar_t **argv_wide) +{ + const char **argv=narrow_argv(argc, argv_wide); + storefront_parse_optionst parse_options(argc, argv); + return parse_options.main(); +} +#else +int main(int argc, const char **argv) +{ + storefront_parse_optionst parse_options(argc, argv); + return parse_options.main(); +} +#endif diff --git a/src/storefront/storefront_parse_options.cpp b/src/storefront/storefront_parse_options.cpp new file mode 100644 index 000000000..2cf35655c --- /dev/null +++ b/src/storefront/storefront_parse_options.cpp @@ -0,0 +1,121 @@ +/*******************************************************************\ + +Module: Command Line Interface + +Author: Daniel Kroening, kroening@kroening.com + +\*******************************************************************/ + +#include + +#include "../deltacheck/version.h" + +#include "storefront_parse_options.h" +#include "data.h" +#include "file_view.h" +#include "trace_view.h" +#include "property_view.h" + +/*******************************************************************\ + +Function: storefront_parse_optionst::storefront_parse_optionst + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +storefront_parse_optionst::storefront_parse_optionst( + int argc, const char **argv): + parse_options_baset(STOREFRONT_OPTIONS, argc, argv) +{ +} + +/*******************************************************************\ + +Function: storefront_parse_optionst::doit + + Inputs: + + Outputs: + + Purpose: invoke main modules + +\*******************************************************************/ + +int storefront_parse_optionst::doit() +{ + if(cmdline.isset("version")) + { + std::cout << DELTACHECK_VERSION << std::endl; + return 0; + } + + try + { + if(cmdline.args.empty()) + { + usage_error(); + return 10; + } + + // read config + datat data; + + for(unsigned i=0; i + +#define STOREFRONT_OPTIONS \ + "(verbosity):(version)" + +class storefront_parse_optionst:public parse_options_baset +{ +public: + virtual int doit(); + virtual void help(); + + storefront_parse_optionst( + int argc, const char **argv); + +protected: +}; + +#endif diff --git a/src/storefront/trace_view.cpp b/src/storefront/trace_view.cpp new file mode 100644 index 000000000..73c2a30b3 --- /dev/null +++ b/src/storefront/trace_view.cpp @@ -0,0 +1,29 @@ +/*******************************************************************\ + +Module: Trace View + +Author: Daniel Kroening, kroening@kroening.com + +\*******************************************************************/ + +#include "data.h" + +/*******************************************************************\ + +Function: trace_view + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +void trace_view(const class datat &) +{ + +} + + + diff --git a/src/storefront/trace_view.h b/src/storefront/trace_view.h new file mode 100644 index 000000000..fcaaf7a4f --- /dev/null +++ b/src/storefront/trace_view.h @@ -0,0 +1,14 @@ +/*******************************************************************\ + +Module: Trace View + +Author: Daniel Kroening, kroening@kroening.com + +\*******************************************************************/ + +#ifndef CPROVER_DELTACHECK_TRACE_VIEW_H +#define CPROVER_DELTACHECK_TRACE_VIEW_H + +void trace_view(const class datat &); + +#endif diff --git a/src/summarizer/function_signature.cpp b/src/summarizer/function_signature.cpp new file mode 100644 index 000000000..df464a847 --- /dev/null +++ b/src/summarizer/function_signature.cpp @@ -0,0 +1,78 @@ +/*******************************************************************\ + +Module: Signature of a Function + +Author: Daniel Kroening, kroening@kroening.com + +\*******************************************************************/ + +#include + +#include "../ssa/local_ssa.h" +#include "function_signature.h" + +/*******************************************************************\ + +Function: update_function_signature + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +void update_function_signature( + const local_SSAt &SSA, + class jsont &dest) +{ + jsont &j_signature=dest["signature"]; + jsont &j_reads=j_signature["reads"]; + jsont &j_modifies=j_signature["modifies"]; + + j_signature.kind=jsont::J_OBJECT; + j_reads=jsont::json_array(); + j_modifies=jsont::json_array(); + + std::set modifies; + std::set reads; + + for(assignmentst::assignment_mapt::const_iterator + a_it=SSA.assignments.assignment_map.begin(); + a_it!=SSA.assignments.assignment_map.end(); + a_it++) + { + for(assignmentst::objectst::const_iterator + o_it=a_it->second.begin(); + o_it!=a_it->second.end(); + o_it++) + { + modifies.insert(o_it->get_identifier()); + } + } + + for(ssa_objectst::objectst::const_iterator + o_it=SSA.ssa_objects.objects.begin(); + o_it!=SSA.ssa_objects.objects.end(); + o_it++) + { + reads.insert(o_it->get_identifier()); + } + + for(std::set::const_iterator it=reads.begin(); + it!=reads.end(); + it++) + { + j_reads.array.push_back(jsont::json_string(id2string(*it))); + } + + for(std::set::const_iterator it=modifies.begin(); + it!=modifies.end(); + it++) + { + j_modifies.array.push_back(jsont::json_string(id2string(*it))); + } + +} + diff --git a/src/summarizer/function_signature.h b/src/summarizer/function_signature.h new file mode 100644 index 000000000..16a7eaf09 --- /dev/null +++ b/src/summarizer/function_signature.h @@ -0,0 +1,17 @@ +/*******************************************************************\ + +Module: Signature of a Function + +Author: Daniel Kroening, kroening@kroening.com + +\*******************************************************************/ + +#ifndef CPROVER_SUMMARIZER_FUNCTION_SIGNATURE_H +#define CPROVER_SUMMARIZER_FUNCTION_SIGNATURE_H + +#include + +void update_function_signature(const class local_SSAt &, jsont &); + +#endif + diff --git a/src/summarizer/instrument_goto.cpp b/src/summarizer/instrument_goto.cpp new file mode 100644 index 000000000..7cd4b4f3f --- /dev/null +++ b/src/summarizer/instrument_goto.cpp @@ -0,0 +1,180 @@ +/*******************************************************************\ + +Module: Instrument Goto Program with Inferred Information + +Author: Peter Schrammel + +\*******************************************************************/ + +#include + +#define DEBUG + +#ifdef DEBUG +#include +#endif + +#include "instrument_goto.h" + + + +local_SSAt::locationt find_loop_by_guard(const local_SSAt &SSA, + const symbol_exprt &guard) +{ + std::string gstr = id2string(guard.get_identifier()); + unsigned pos1 = gstr.find("#")+1; + unsigned pos2 = gstr.find("%",pos1); + unsigned n = safe_string2unsigned(gstr.substr(pos1,pos2)); + + local_SSAt::nodest::const_iterator n_it =SSA.nodes.begin(); + + for(; n_it != SSA.nodes.end(); n_it++) + { + if(n_it->location->location_number == n) { + // find end of loop + break; + } + } + + if(n_it->loophead==SSA.nodes.end()) + return n_it->location; + else + return n_it->loophead->location; +} + + +void instrument_gotot::instrument_instruction( + const exprt &expr, + goto_programt &dest, + goto_programt::targett &target) +{ + + goto_programt::targett where=target; + + std::cout << "target " << target->type << " : " << target->source_location << std::endl; + + for(;;++where) + { + if(where->is_goto() && where->get_target()==target) + break; + } + + + goto_programt tmp; + + goto_programt::targett assumption=tmp.add_instruction(); + assumption->make_assumption(expr); + assumption->source_location=target->source_location; + assumption->source_location.set_comment("invariant generated by 2LS"); + + dest.insert_before_swap(where, tmp); + + #ifdef DEBUG + std::cout << "instrumenting instruction " << std::endl; + #endif + + + //dest.update(); +} + +extern +void purify_identifiers(exprt &expr); + + +void instrument_gotot::instrument_body( + const local_SSAt &SSA, + const exprt &expr, + goto_functionst::goto_functiont &function +) +{ + //expected format (/\_j g_j) => inv + const exprt &impl = expr.op0(); + exprt inv = expr.op1(); //copy + + std::cout << "Invariant " << from_expr(inv) << std::endl; + + purify_identifiers(inv); + + local_SSAt::locationt loc; + if(impl.id()==ID_symbol) + { + loc = find_loop_by_guard(SSA,to_symbol_expr(impl)); + } + else if(impl.id()==ID_and) + { + assert(impl.op0().id()==ID_symbol); + loc = find_loop_by_guard(SSA,to_symbol_expr(impl.op0())); + + } + else assert(false); + + + Forall_goto_program_instructions(it, function.body) + if(it==loc) + { + + instrument_instruction(inv, function.body, it); + break; + } +} + + + +void instrument_gotot::instrument_function( + const irep_idt &function_name, + goto_functionst::goto_functiont &function) +{ + #ifdef DEBUG + std::cout << "instrumenting function " << function_name << std::endl; + #endif + + if(!summary_db.exists(function_name)) + return; + + const summaryt summary=summary_db.get(function_name); + + if(!ssa_db.exists(function_name)) + return; + + const local_SSAt &SSA=ssa_db.get(function_name); + + if(summary.fw_invariant.is_nil()) return; + if(summary.fw_invariant.is_true()) return; + + //expected format /\_i g_i => inv_i + if(summary.fw_invariant.id()==ID_implies) + { + instrument_body(SSA, summary.fw_invariant, function); + } + else if(summary.fw_invariant.id()==ID_and) + { + for(unsigned i=0; i::function_mapt + function_mapt; + + function_mapt + &function_map=goto_functions.function_map; + + for(function_mapt::iterator + fit=function_map.begin(); + fit!=function_map.end(); + ++fit) + { + instrument_function(fit->first, fit->second); + } + + goto_model.goto_functions.update(); +} diff --git a/src/summarizer/instrument_goto.h b/src/summarizer/instrument_goto.h new file mode 100644 index 000000000..dbc3a1b41 --- /dev/null +++ b/src/summarizer/instrument_goto.h @@ -0,0 +1,55 @@ +/*******************************************************************\ + +Module: Instrument Goto Program with Inferred Information + +Author: Peter Schrammel + +\*******************************************************************/ + +#ifndef CPROVER_INSTRUMENT_GOTO_H +#define CPROVER_INSTRUMENT_GOTO_H + +#include +#include + +#include "../ssa/local_ssa.h" +#include "../ssa/ssa_unwinder.h" +#include "ssa_db.h" +#include "summary_db.h" + +class instrument_gotot:public messaget +{ +public: + inline instrument_gotot(optionst &_options, + ssa_dbt &_ssa_db, + summary_dbt &_summary_db): + options(_options), + ssa_db(_ssa_db),summary_db(_summary_db) + { + } + + void operator()(goto_modelt &goto_model); + + protected: + optionst &options; + + ssa_dbt &ssa_db; + summary_dbt &summary_db; + + void instrument_function( + const irep_idt &function_name, + goto_functionst::goto_functiont &function); + + void instrument_body( + const local_SSAt &SSA, + const exprt &expr, + goto_functionst::goto_functiont &function); + + void instrument_instruction( + const exprt &expr, + goto_programt &dest, + goto_programt::targett &target); + +}; + +#endif diff --git a/src/summarizer/preprocessing_util.cpp b/src/summarizer/preprocessing_util.cpp new file mode 100644 index 000000000..a6b125135 --- /dev/null +++ b/src/summarizer/preprocessing_util.cpp @@ -0,0 +1,265 @@ +#include +#include +#include +#include + +#include "../ssa/const_propagator.h" + +#include "summarizer_parse_options.h" + +/*******************************************************************\ + +Function: summarizer_parse_optionst::inline_main + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +void summarizer_parse_optionst::inline_main(goto_modelt &goto_model) +{ + goto_programt &main = goto_model.goto_functions.function_map[ID__start].body; + goto_programt::targett target = main.instructions.begin(); + while(target!=main.instructions.end()) + { + if(target->is_function_call()) + { + const code_function_callt &code_function_call= + to_code_function_call(target->code); + irep_idt fname = code_function_call.function().get(ID_identifier); + + debug() << "Inlining " << fname << eom; + + goto_programt tmp; + tmp.copy_from(goto_model.goto_functions.function_map[fname].body); + (--tmp.instructions.end())->make_skip(); + goto_model.goto_functions.function_map.erase(fname); + + goto_programt::targett next_target(target); + target->make_skip(); + next_target++; + main.instructions.splice(next_target, tmp.instructions); + target=next_target; + } + else target++; + } + + goto_model.goto_functions.update(); + goto_model.goto_functions.compute_loop_numbers(); +} + +/*******************************************************************\ + +Function: summarizer_parse_optionst::propagate_constants + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +void summarizer_parse_optionst::propagate_constants(goto_modelt &goto_model) +{ + namespacet ns(goto_model.symbol_table); + Forall_goto_functions(f_it, goto_model.goto_functions) + { + const_propagator_ait(f_it->second,ns); + } +} + +/*******************************************************************\ + +Function: summarizer_parse_optionst::nondet_locals + + Inputs: + + Outputs: + + Purpose: explicitly assign a nondet_symbol to local variables + this is required by the unwinder, which would be unable + to recognise in which scope variables have been declared + +\*******************************************************************/ + +void summarizer_parse_optionst::nondet_locals(goto_modelt &goto_model) +{ + namespacet ns(goto_model.symbol_table); + Forall_goto_functions(f_it, goto_model.goto_functions) + { + Forall_goto_program_instructions(i_it, f_it->second.body) + { + if(i_it->is_decl()) + { + const code_declt& decl = to_code_decl(i_it->code); + side_effect_expr_nondett nondet(decl.symbol().type()); + goto_programt::targett t = f_it->second.body.insert_after(i_it); + t->make_assignment(); + code_assignt c(decl.symbol(),nondet); + t->code.swap(c); + t->source_location = i_it->source_location; + } + } + } + goto_model.goto_functions.update(); +} + +/*******************************************************************\ + +Function: goto_unwind + + Inputs: + + Outputs: + + Purpose: unwind all loops + +\*******************************************************************/ + +void summarizer_parse_optionst::goto_unwind(goto_modelt &goto_model, unsigned k) +{ + + typedef std::vector > loopst; + + Forall_goto_functions(f_it, goto_model.goto_functions) + { + goto_programt &body=f_it->second.body; + + loopst loops; + Forall_goto_program_instructions(i_it, body) + { + if(i_it->is_backwards_goto()) + { + goto_programt::targett loop_head = i_it->get_target(); + goto_programt::targett loop_exit = i_it; + bool has_goto_into_loop = false; + + goto_programt::targett it = loop_head; + if(it!=loop_exit) it++; + for(; it!=loop_exit; it++) + { + for( std::set::iterator + s_it = it->incoming_edges.begin(); + s_it!=it->incoming_edges.end(); ++s_it) + { + if((*s_it)->is_goto() && + (*s_it)->location_number < loop_head->location_number) + { + has_goto_into_loop = true; + break; + } + } + if(has_goto_into_loop) break; + } + if(has_goto_into_loop) + { + status() << "Unwinding jump into loop" << eom; + loops.push_back(loopst::value_type(++loop_exit,loop_head)); + } + } + } + + for(loopst::iterator l_it = loops.begin(); l_it != loops.end(); ++l_it) + { + std::vector iteration_points; + unwind(body,l_it->second,l_it->first,k,iteration_points); + assert(iteration_points.size()==2); + goto_programt::targett t=body.insert_before(l_it->first); + t->make_goto(); + t->targets.push_back(iteration_points.front()); + } + } + goto_model.goto_functions.update(); + goto_model.goto_functions.compute_loop_numbers(); +} + +/*******************************************************************\ + +Function: remove_multiple_dereferences + + Inputs: + + Outputs: + + Purpose: temporary fix to circumvent ssa_dereference problem + +\*******************************************************************/ + +void summarizer_parse_optionst::remove_multiple_dereferences(goto_modelt &goto_model, goto_programt &body, goto_programt::targett t, exprt &expr, unsigned &var_counter, bool deref_seen) +{ + if(expr.id()==ID_member) + { + member_exprt &member_expr = to_member_expr(expr); + if(member_expr.compound().id()==ID_dereference) + { + dereference_exprt &deref_expr = to_dereference_expr(member_expr.compound()); + remove_multiple_dereferences(goto_model,body,t,deref_expr.pointer(),var_counter,true); + if(deref_seen) + { + symbolt new_symbol; + new_symbol.type=member_expr.type(); + new_symbol.name="$deref"+i2string(var_counter++); + new_symbol.base_name=new_symbol.name; + new_symbol.pretty_name=new_symbol.name; + goto_model.symbol_table.add(new_symbol); + goto_programt::targett t_new = body.insert_before(t); + t_new->make_assignment(); + t_new->code = code_assignt(new_symbol.symbol_expr(),member_expr); + expr = new_symbol.symbol_expr(); + for(std::set::iterator t_it = + t->incoming_edges.begin(); + t_it != t->incoming_edges.end(); ++t_it) + { + (*t_it)->targets.clear(); + (*t_it)->targets.push_back(t_new); + } + body.compute_location_numbers(); + body.compute_target_numbers(); + body.compute_incoming_edges(); + } + } + else + Forall_operands(o_it,expr) + remove_multiple_dereferences(goto_model,body,t,*o_it,var_counter,deref_seen); + } + else + Forall_operands(o_it,expr) + remove_multiple_dereferences(goto_model,body,t,*o_it,var_counter,deref_seen); +} + +void summarizer_parse_optionst::remove_multiple_dereferences(goto_modelt &goto_model) +{ + unsigned var_counter = 0; + namespacet ns(goto_model.symbol_table); + Forall_goto_functions(f_it, goto_model.goto_functions) + { + Forall_goto_program_instructions(i_it, f_it->second.body) + { + if(i_it->is_goto()) + { + remove_multiple_dereferences(goto_model, + f_it->second.body, + i_it, + i_it->guard, + var_counter, false); + } + else if(i_it->is_assign()) + { + remove_multiple_dereferences(goto_model, + f_it->second.body, + i_it, + to_code_assign(i_it->code).lhs(), + var_counter, false); + remove_multiple_dereferences(goto_model, + f_it->second.body, + i_it, + to_code_assign(i_it->code).rhs(), + var_counter, false); + } + } + } +} diff --git a/src/summarizer/summarizer.cpp b/src/summarizer/summarizer.cpp new file mode 100644 index 000000000..04c170e0f --- /dev/null +++ b/src/summarizer/summarizer.cpp @@ -0,0 +1,125 @@ +/*******************************************************************\ + +Module: Summarizer + +Author: Daniel Kroening, kroening@kroening.com + +\*******************************************************************/ + +#include "../ssa/local_ssa.h" +#include "../ssa/simplify_ssa.h" + +#include "function_signature.h" +#include "summary_db.h" +#include "summarizer.h" + +/*******************************************************************\ + +Function: summarizert::operator() + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +void summarizert::operator()(const goto_modelt &goto_model) +{ + // analyze all the functions + forall_goto_functions(f_it, goto_model.goto_functions) + summarize(goto_model, f_it); +} + +/*******************************************************************\ + +Function: summarizert::operator() + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +void summarizert::operator()( + const goto_modelt &goto_model, + const irep_idt &id) +{ + // analyze the given function only + + goto_functionst::function_mapt::const_iterator f_it= + goto_model.goto_functions.function_map.find(id); + + if(f_it==goto_model.goto_functions.function_map.end()) + throw "function not found"; + + summarize(goto_model, f_it); +} + +/*******************************************************************\ + +Function: summarizert::summarize + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +void summarizert::summarize( + const goto_modelt &goto_model, + const goto_functionst::function_mapt::const_iterator f_it) +{ + status() << "** Analyzing " << f_it->first << messaget::eom; + + summary_dbt summary_db; + + summary_db.set_message_handler(get_message_handler()); + summary_db.read(id2string(f_it->first)); + + const namespacet ns(goto_model.symbol_table); + + // build SSA + progress() << "Building SSA" << messaget::eom; + local_SSAt SSA(f_it->second, ns); + + // simplify, if requested + if(simplify) + { + progress() << "Simplifying" << messaget::eom; + ::simplify(SSA, ns); + } + + + // fixed-point for loops + #if 0 + progress() << "Fixed-point" << messaget::eom; + ssa_fixed_point(SSA); + #endif + + update_function_signature(SSA, summary_db.summary); + + summary_db.write(); +} + +/*******************************************************************\ + +Function: summarizert::report_statistics() + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +void summarizert::report_statistics() +{ +} + diff --git a/src/summarizer/summarizer.h b/src/summarizer/summarizer.h new file mode 100644 index 000000000..f4cc72785 --- /dev/null +++ b/src/summarizer/summarizer.h @@ -0,0 +1,45 @@ +/*******************************************************************\ + +Module: Summarizer + +Author: Daniel Kroening, kroening@kroening.com + +\*******************************************************************/ + +#ifndef CPROVER_SUMMARIZER_H +#define CPROVER_SUMMARIZER_H + +#include +#include + +#include + +#include "../ssa/local_ssa.h" + +class summarizert:public messaget +{ +public: + inline summarizert(): + simplify(false), + fixed_point(false) + { + } + + bool simplify, fixed_point; + + void operator()(const goto_modelt &); + void operator()(const goto_modelt &, const irep_idt &); + + // statistics + absolute_timet start_time; + time_periodt sat_time; + +protected: + void report_statistics(); + + void summarize( + const goto_modelt &, + const goto_functionst::function_mapt::const_iterator); +}; + +#endif diff --git a/src/summarizer/summarizer_bw_cex.cpp b/src/summarizer/summarizer_bw_cex.cpp new file mode 100644 index 000000000..424e11248 --- /dev/null +++ b/src/summarizer/summarizer_bw_cex.cpp @@ -0,0 +1,100 @@ +/*******************************************************************\ + +Module: Counterexample-based Backward Analysis + +Author: Kumar Madhukar, Peter Schrammel + +\*******************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include "summarizer_bw_cex.h" +#include "summary_db.h" + +#include "../domains/ssa_analyzer.h" +#include "../domains/template_generator_summary.h" +#include "../domains/template_generator_callingcontext.h" + +#include "../ssa/local_ssa.h" +#include "../ssa/simplify_ssa.h" + + +/*******************************************************************\ + +Function: summarizer_bw_cex_baset::summarize() + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +void summarizer_bw_cex_baset::summarize() +{ + assert(false); //unused +} + +/*******************************************************************\ + +Function: summarizer_bw_cex_baset::summarize() + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +void summarizer_bw_cex_baset::summarize(const function_namet &function_name) +{ + exprt postcondition = true_exprt(); //initial calling context + + status() << "\nSummarizing function " << function_name << eom; + compute_summary_rec(function_name,postcondition,true); +} + +/*******************************************************************\ + +Function: summarizer_bw_cex_baset::summarize() + + Inputs: + + Outputs: + + Purpose: summarize backwards from given assertion + +\*******************************************************************/ + +void summarizer_bw_cex_baset::summarize(const exprt &_error_assertion) +{ + status() << "\nBackward error analysis..." << eom; + error_assertion = _error_assertion; + + summarize(entry_function); +} + +/*******************************************************************\ + +Function: summarizer_bw_cex_baset::check() + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +property_checkert::resultt summarizer_bw_cex_baset::check() +{ + assert(false); +} diff --git a/src/summarizer/summarizer_bw_cex.h b/src/summarizer/summarizer_bw_cex.h new file mode 100644 index 000000000..5cead1add --- /dev/null +++ b/src/summarizer/summarizer_bw_cex.h @@ -0,0 +1,51 @@ +/*******************************************************************\ + +Module: Counterexample-based Backward Analysis Base + +Author: Kumar Madhukar, Peter Schrammel + +\*******************************************************************/ + +#ifndef CPROVER_SUMMARIZER_BW_CEX_H +#define CPROVER_SUMMARIZER_BW_CEX_H + +#include +#include +#include +#include "../ssa/ssa_inliner.h" +#include "../ssa/ssa_unwinder.h" +#include "../ssa/local_ssa.h" +#include "ssa_db.h" + +#include "summarizer_bw.h" + +class summarizer_bw_cex_baset : public summarizer_bwt +{ + public: + virtual void summarize(); + virtual void summarize(const function_namet &entry_function); + virtual void summarize(const exprt &_error_assertion); + + virtual property_checkert::resultt check(); + + protected: + function_namet entry_function; + function_namet error_function; + exprt error_assertion; + + explicit summarizer_bw_cex_baset(optionst &_options, + summary_dbt &_summary_db, + ssa_dbt &_ssa_db, + ssa_unwindert &_ssa_unwinder, + ssa_inlinert &_ssa_inliner, + function_namet _entry_function, + function_namet _error_function): + summarizer_bwt(_options,_summary_db,_ssa_db,_ssa_unwinder,_ssa_inliner), + entry_function(_entry_function), + error_function(_error_function) + {} + +}; + + +#endif diff --git a/src/summarizer/summarizer_bw_cex_ai.cpp b/src/summarizer/summarizer_bw_cex_ai.cpp new file mode 100644 index 000000000..fb5ae3183 --- /dev/null +++ b/src/summarizer/summarizer_bw_cex_ai.cpp @@ -0,0 +1,511 @@ +/*******************************************************************\ + +Module: Summarizer for Backward Analysis + +Author: Peter Schrammel + +\*******************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include "summarizer_bw_cex_ai.h" +#include "summary_db.h" + +#include "../domains/ssa_analyzer.h" +#include "../domains/template_generator_summary.h" +#include "../domains/template_generator_callingcontext.h" + +#include "../domains/disjunctive_analyzer.h" + +#include "../ssa/local_ssa.h" +#include "../ssa/simplify_ssa.h" + + +/*******************************************************************\ + +Function: summarizer_bw_cex_ait::summarize() + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +void summarizer_bw_cex_ait::summarize(const function_namet &function_name) +{ + exprt postcondition = true_exprt(); //initial calling context + + status() << "\nSummarizing function " << function_name << eom; + compute_summary_rec(function_name,summaryt::entry_call_site, + postcondition,true); +} + +/*******************************************************************\ + +Function: summarizer_bw_cex_ait::summarize() + + Inputs: + + Outputs: + + Purpose: summarize backwards from given assertion + +\*******************************************************************/ + +void summarizer_bw_cex_ait::summarize(const exprt &_error_assertion) +{ + status() << "\nBackward error analysis (abstract)..." << eom; + error_assertion = _error_assertion; + + summarize(entry_function); +} + +/*******************************************************************\ + +Function: summarizer_bw_cex_ait::check() + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +property_checkert::resultt summarizer_bw_cex_ait::check() +{ + //TODO: store information about why have UNKNOWN + // we have to distinguish the case when we cannot decide about spuriousness + + if(!summary_db.exists(entry_function)) + return property_checkert::UNKNOWN; + + const summaryt &summary = summary_db.get(entry_function); + if(summary.error_summaries.empty() || + summary.error_summaries.begin()->second.is_nil() || + summary.error_summaries.begin()->second.is_true()) + return property_checkert::UNKNOWN; + + return property_checkert::FAIL; +} + +/*******************************************************************\ + +Function: summarizer_bw_cex_ait::compute_summary_rec() + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +/*******************************************************************\ + +Function: summarizer_bw_cex_ait::compute_summary_rec() + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +void summarizer_bw_cex_ait::compute_summary_rec( + const function_namet &function_name, + const summaryt::call_sitet &call_site, + const exprt &_postcondition, + bool context_sensitive) +{ + local_SSAt &SSA = ssa_db.get(function_name); + + summaryt summary; + if(summary_db.exists(function_name)) + summary = summary_db.get(function_name); + else + { + summary.params = SSA.params; + summary.globals_in = SSA.globals_in; + summary.globals_out = SSA.globals_out; + } + + // insert assertion + exprt end_guard = SSA.guard_symbol(--SSA.goto_function.body.instructions.end()); + exprt postcondition = implies_exprt(end_guard,_postcondition); + if(function_name == error_function) + { + postcondition = and_exprt(postcondition,not_exprt(error_assertion)); + } + + summary.bw_postcondition = _postcondition; + +#if 0 + debug() << "Postcondition: " << + from_expr(SSA.ns, "", postcondition) << eom; +#endif + + if(_postcondition.is_false()){ + + summary.error_summaries[call_site] = false_exprt(); + + } + else{ + + // recursively compute summaries for function calls + inline_summaries(function_name,SSA,summary, + postcondition,context_sensitive, + true); + + status() << "Analyzing function " << function_name << eom; + + do_summary(function_name,call_site,SSA,summary,summary,postcondition,context_sensitive); + + if(function_name == error_function) + summary.has_assertion = true; + + } + + summary_db.set(function_name,summary); + + { + std::ostringstream out; + out << std::endl << "Summary for function " << function_name << std::endl; + summary_db.get(function_name).output(out,SSA.ns); + debug() << out.str() << eom; + } + +} + +/*******************************************************************\ + +Function: summarizer_bw_cex_ait::do_summary() + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +void summarizer_bw_cex_ait::do_summary(const function_namet &function_name, + const summaryt::call_sitet &call_site, + local_SSAt &SSA, + const summaryt &old_summary, + summaryt &summary, + const exprt &postcondition, + bool context_sensitive) +{ + status() << "Computing error summary" << eom; + + // solver + incremental_solvert &solver = ssa_db.get_solver(function_name); + solver.set_message_handler(get_message_handler()); + + //TODO: maybe allow setting this separately on the command line + optionst _options = options; + _options.set_option("intervals",true); + _options.set_option("binsearch-solver",true); + + //TODO: use a template generator without invariants + template_generator_summaryt template_generator( + _options,ssa_db,ssa_unwinder.get(function_name)); + template_generator.set_message_handler(get_message_handler()); + template_generator(solver.next_domain_number(),SSA,false); + + exprt::operandst c; + //add forward information if available + if(!old_summary.fw_precondition.is_nil()) + c.push_back(old_summary.fw_precondition); + if(!old_summary.fw_invariant.is_nil()) + c.push_back(old_summary.fw_invariant); + c.push_back(ssa_inliner.get_summaries(SSA)); //forward summaries + exprt::operandst assert_postcond, noassert_postcond; + // add error summaries for function calls + bool assertion_flag; + assertion_flag = ssa_inliner.get_summaries(SSA,call_site,false, + assert_postcond,noassert_postcond,c); //backward summaries + + assert_postcond.push_back(postcondition); //context + + + // assumptions must hold + for(local_SSAt::nodest::const_iterator + n_it = SSA.nodes.begin(); + n_it != SSA.nodes.end(); + ++n_it) + for(local_SSAt::nodet::assumptionst::const_iterator + a_it = n_it->assumptions.begin(); + a_it != n_it->assumptions.end(); + ++a_it) + c.push_back(*a_it); + + + + +#if 0 + std::cout << from_expr(SSA.ns, "", cc) << std::endl; +#endif + + //TODO: pushing loophead_selects into the solver + + summary.error_summaries[call_site]; + if(!template_generator.empty()) + { + c.push_back(conjunction(assert_postcond)); //with negative information would need: not_exprt + c.push_back(conjunction(noassert_postcond)); //with negative information would need: not_exprt dis + + //std::cout << "unsimplified constraints: " << from_expr(SSA.ns, "", conjunction(c)) << "\n\n\n"; + exprt cc = simplify_expr(conjunction(c), SSA.ns); + //exprt cc = conjunction(c); + //std::cout << "simplified constraints passed: " << from_expr(SSA.ns, "", cc) << "\n\n\n"; + + /* + ssa_analyzert analyzer; + analyzer.set_message_handler(get_message_handler()); + analyzer(solver,SSA,cc,template_generator); + analyzer.get_result(summary.error_summaries[call_site], + template_generator.inout_vars()); + */ + + disjunctive_analyzert disjunctive_analyzer; + disjunctive_analyzer.set_message_handler(get_message_handler()); + disjunctive_analyzer(solver,SSA,cc,template_generator, + cc,summary.error_summaries[call_site], + template_generator.inout_vars()); + +#if 0 + std::cout << "SUM: " << from_expr(SSA.ns, "", summary.error_summaries[call_site]) << std::endl; +#endif + + + summary.error_summaries[call_site] = + simplify_expr(summary.error_summaries[call_site], SSA.ns); + + +#if 0 + std::cout << "SUM (post simplification): " << from_expr(SSA.ns, "", summary.error_summaries[call_site]) << std::endl; +#endif + + //statistics + /* + solver_instances += analyzer.get_number_of_solver_instances(); + solver_calls += analyzer.get_number_of_solver_calls(); + */ + solver_instances += disjunctive_analyzer.get_number_of_solver_instances(); + solver_calls += disjunctive_analyzer.get_number_of_solver_calls(); + + } + else // TODO: yet another workaround for ssa_analyzer not being able to handle empty templates properly + { + c.push_back(not_exprt(conjunction(assert_postcond))); + c.push_back(not_exprt(disjunction(noassert_postcond))); + + //std::cout << "unsimplified constraints: " << from_expr(SSA.ns, "", conjunction(c)) << "\n\n\n"; + exprt cc = simplify_expr(conjunction(c), SSA.ns); + //exprt cc = conjunction(c); + //std::cout << "simplified constraints passed: " << from_expr(SSA.ns, "", cc) << "\n\n\n"; + + solver << SSA; + solver.new_context(); + solver << SSA.get_enabling_exprs(); + solver << cc; + exprt result = false_exprt(); + if(solver()!=decision_proceduret::D_SATISFIABLE) result = true_exprt(); + solver.pop_context(); + summary.error_summaries[call_site] = result; + +#if 0 + std::cout << "SUM: " << from_expr(SSA.ns, "", summary.error_summaries[call_site]) << std::endl; +#endif + } + + summary.error_summaries[call_site] = + simplify_expr((summary.error_summaries[call_site]), SSA.ns); //not_exprt + + summary.has_assertion = assertion_flag; +} + +/*******************************************************************\ + +Function: summarizer_bw_cex_ait::inline_summaries() + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +void summarizer_bw_cex_ait::inline_summaries(const function_namet &function_name, + local_SSAt &SSA, + const summaryt &old_summary, + const exprt &postcondition, + bool context_sensitive, + bool sufficient) +{ + for(local_SSAt::nodest::const_iterator n_it = SSA.nodes.end(); + n_it != SSA.nodes.begin(); ) + { + n_it--; + + for(local_SSAt::nodet::function_callst::const_iterator f_it = + n_it->function_calls.begin(); + f_it != n_it->function_calls.end(); f_it++) + { + assert(f_it->function().id()==ID_symbol); //no function pointers + + exprt postcondition_call = true_exprt(); + postcondition_call = compute_calling_context2( + function_name,SSA,old_summary,n_it,f_it,postcondition,sufficient); + + irep_idt fname = to_symbol_expr(f_it->function()).get_identifier(); + status() << "Recursively summarizing function " << fname << eom; + compute_summary_rec(fname,summaryt::call_sitet(n_it->location), + postcondition_call,context_sensitive); + } + } +} + +/*******************************************************************\ + +Function: summarizer_bw_cex_ait::compute_calling_context2() + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +exprt summarizer_bw_cex_ait::compute_calling_context2( + const function_namet &function_name, + local_SSAt &SSA, + summaryt old_summary, + local_SSAt::nodest::const_iterator n_it, + local_SSAt::nodet::function_callst::const_iterator f_it, + const exprt &postcondition, + bool sufficient) +{ + assert(f_it->function().id()==ID_symbol); //no function pointers + irep_idt fname = to_symbol_expr(f_it->function()).get_identifier(); + + status() << "Computing calling context for function " << fname << eom; + + // solver + incremental_solvert &solver = ssa_db.get_solver(function_name); + solver.set_message_handler(get_message_handler()); + + //analyze + /* + ssa_analyzert analyzer; + analyzer.set_message_handler(get_message_handler()); + */ + + disjunctive_analyzert disjunctive_analyzer; + disjunctive_analyzer.set_message_handler(get_message_handler()); + + //TODO: maybe allow setting this separately on the command line + optionst _options = options; + _options.set_option("intervals",true); + _options.set_option("binsearch-solver",true); + + //TODO: use a template generator without invariants + template_generator_callingcontextt template_generator( + _options,ssa_db,ssa_unwinder.get(function_name)); + template_generator.set_message_handler(get_message_handler()); + template_generator(solver.next_domain_number(),SSA,n_it,f_it,false); + + // collect globals at call site + std::map + cs_globals_out; + SSA.get_globals(n_it->location,cs_globals_out[f_it],false); + + exprt::operandst c; + + //add forward information if available + if(!old_summary.fw_precondition.is_nil()) + c.push_back(old_summary.fw_precondition); + if(!old_summary.fw_invariant.is_nil()) + c.push_back(old_summary.fw_invariant); + c.push_back(ssa_inliner.get_summaries(SSA)); //forward summaries + + exprt::operandst assert_postcond, noassert_postcond; + // add error summaries for function calls + ssa_inliner.get_summaries(SSA,summaryt::call_sitet(n_it->location),false, + assert_postcond,noassert_postcond,c); //backward summaries + assert_postcond.push_back(postcondition); //context + + + //TODO: pushing loophead_selects into the solver + + // set preconditions + local_SSAt &fSSA = ssa_db.get(fname); + + exprt postcondition_call; + + if(!template_generator.empty()){ + + c.push_back(conjunction(assert_postcond)); //with negative information would need: not_exprt + c.push_back(conjunction(noassert_postcond)); //with negative information would need: not_exprt dis + + /* + analyzer(solver,SSA,conjunction(c),template_generator); + analyzer.get_result(postcondition_call, + template_generator.callingcontext_vars()); + */ + + disjunctive_analyzer(solver,SSA,conjunction(c),template_generator, + conjunction(c), postcondition_call, + template_generator.callingcontext_vars()); + + ssa_inliner.rename_to_callee(f_it, fSSA.params, + cs_globals_out[f_it],fSSA.globals_out, + postcondition_call); + + } + else{ // TODO: yet another workaround for ssa_analyzer not being able to handle empty templates properly + + c.push_back(not_exprt(conjunction(assert_postcond))); + c.push_back(not_exprt(disjunction(noassert_postcond))); + + solver << SSA; + solver.new_context(); + solver << SSA.get_enabling_exprs(); + solver << conjunction(c); + + //std::cout << "passed to solver, else branch, calling context: " << from_expr(SSA.ns, "", conjunction(c)) << "\n\n"; + + postcondition_call = false_exprt(); + if(solver()!=decision_proceduret::D_SATISFIABLE) postcondition_call = true_exprt(); + solver.pop_context(); + } + + debug() << "Backward calling context for " << + from_expr(SSA.ns, "", *f_it) << ": " + << from_expr(SSA.ns, "", postcondition_call) << eom; + + //statistics + /* + solver_instances += analyzer.get_number_of_solver_instances(); + solver_calls += analyzer.get_number_of_solver_calls(); + */ + solver_instances += disjunctive_analyzer.get_number_of_solver_instances(); + solver_calls += disjunctive_analyzer.get_number_of_solver_calls(); + + return postcondition_call; +} + + diff --git a/src/summarizer/summarizer_bw_cex_ai.h b/src/summarizer/summarizer_bw_cex_ai.h new file mode 100644 index 000000000..a41b9c122 --- /dev/null +++ b/src/summarizer/summarizer_bw_cex_ai.h @@ -0,0 +1,76 @@ +/*******************************************************************\ + +Module: Summarizer for Backwards Error Analysis + +Author: Peter Schrammel + +\*******************************************************************/ + +#ifndef CPROVER_SUMMARIZER_BW_CEX_AI_H +#define CPROVER_SUMMARIZER_BW_CEX_AI_H + +#include +#include +#include "../ssa/ssa_inliner.h" +#include "../ssa/ssa_unwinder.h" +#include "../ssa/local_ssa.h" +#include "ssa_db.h" + +#include + +#include "summarizer_bw_cex.h" + +class summarizer_bw_cex_ait : public summarizer_bw_cex_baset +{ + public: + explicit summarizer_bw_cex_ait(optionst &_options, + summary_dbt &_summary_db, + ssa_dbt &_ssa_db, + ssa_unwindert &_ssa_unwinder, + ssa_inlinert &_ssa_inliner, + function_namet _entry_function, + function_namet _error_function): + summarizer_bw_cex_baset(_options,_summary_db,_ssa_db, + _ssa_unwinder,_ssa_inliner, + _entry_function,_error_function) + {} + + virtual void summarize(const function_namet &entry_function); + virtual void summarize(const exprt &_error_assertion); + + virtual property_checkert::resultt check(); + + protected: + + virtual void compute_summary_rec(const function_namet &function_name, + const summaryt::call_sitet &call_site, + const exprt &postcondition, + bool context_sensitive); + + virtual void inline_summaries(const function_namet &function_name, + local_SSAt &SSA, + const summaryt &old_summary, + const exprt &postcondition, + bool context_sensitive, + bool sufficient); + + virtual void do_summary(const function_namet &function_name, + const summaryt::call_sitet &call_site, + local_SSAt &SSA, + const summaryt &old_summary, + summaryt &summary, + const exprt &postcondition, + bool context_sensitive); + + virtual exprt compute_calling_context2(const function_namet &function_name, + local_SSAt &SSA, + summaryt old_summary, + local_SSAt::nodest::const_iterator n_it, + local_SSAt::nodet::function_callst::const_iterator f_it, + const exprt &postcondition, + bool sufficient); + +}; + + +#endif diff --git a/src/summarizer/summarizer_bw_cex_all.cpp b/src/summarizer/summarizer_bw_cex_all.cpp new file mode 100644 index 000000000..cefdd8757 --- /dev/null +++ b/src/summarizer/summarizer_bw_cex_all.cpp @@ -0,0 +1,75 @@ +/*******************************************************************\ + +Module: Counterexample-based Backward Analysis + +Author: Kumar Madhukar, Peter Schrammel + +\*******************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include "summarizer_bw_cex_all.h" + +#include "../domains/ssa_analyzer.h" +#include "../domains/template_generator_summary.h" +#include "../domains/template_generator_callingcontext.h" + +#include "../ssa/local_ssa.h" +#include "../ssa/simplify_ssa.h" + + +/*******************************************************************\ + +Function: summarizer_bw_cex_allt::summarize() + + Inputs: + + Outputs: + + Purpose: calls multiple strategies + +\*******************************************************************/ + +void summarizer_bw_cex_allt::summarize(const exprt &_error_assertion) +{ + status() << "\nBackward error analysis (all)..." << eom; + error_assertion = _error_assertion; + + summarizer_bw_cex_concrete.summarize(error_assertion); + result = summarizer_bw_cex_concrete.check(); + + if(result == property_checkert::UNKNOWN) + { + summarizer_bw_cex_ai.summarize(error_assertion); + result = summarizer_bw_cex_ai.check(); + + if(result == property_checkert::UNKNOWN) + { + summarizer_bw_cex_complete.summarize(error_assertion); + result = summarizer_bw_cex_complete.check(); + } + } +} + +/*******************************************************************\ + +Function: summarizer_bw_cex_allt::check() + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +property_checkert::resultt summarizer_bw_cex_allt::check() +{ + return result; +} diff --git a/src/summarizer/summarizer_bw_cex_all.h b/src/summarizer/summarizer_bw_cex_all.h new file mode 100644 index 000000000..b04dae0fb --- /dev/null +++ b/src/summarizer/summarizer_bw_cex_all.h @@ -0,0 +1,73 @@ +/*******************************************************************\ + +Module: Counterexample-based Backward Analysis All + +Author: Kumar Madhukar, Peter Schrammel + +\*******************************************************************/ + +#ifndef CPROVER_SUMMARIZER_BW_CEX_ALL_H +#define CPROVER_SUMMARIZER_BW_CEX_ALL_H + +#include +#include +#include +#include "../ssa/ssa_inliner.h" +#include "../ssa/ssa_unwinder.h" +#include "../ssa/local_ssa.h" +#include "ssa_db.h" + +#include "summarizer_bw_cex.h" +#include "summarizer_bw_cex_concrete.h" +#include "summarizer_bw_cex_ai.h" +#include "summarizer_bw_cex_complete.h" + +class summarizer_bw_cex_allt : public summarizer_bw_cex_baset +{ + public: + explicit summarizer_bw_cex_allt(optionst &_options, + summary_dbt &_summary_db, + ssa_dbt &_ssa_db, + ssa_unwindert &_ssa_unwinder, + ssa_inlinert &_ssa_inliner, + incremental_solvert &_solver, + function_namet _entry_function, + function_namet _error_function): + summarizer_bw_cex_baset(_options,_summary_db,_ssa_db, + _ssa_unwinder,_ssa_inliner, + _entry_function,_error_function), + summarizer_bw_cex_concrete(_options,_summary_db,_ssa_db, + _ssa_unwinder,_ssa_inliner, + _entry_function,_error_function), + summarizer_bw_cex_ai(_options,_summary_db,_ssa_db, + _ssa_unwinder,_ssa_inliner, + _entry_function,_error_function), + summarizer_bw_cex_complete(_options,_summary_db,_ssa_db, + _ssa_unwinder,_ssa_inliner, + _solver,_entry_function,_error_function), + result(property_checkert::UNKNOWN) + {} + + virtual void summarize(const exprt &_error_assertion); + + virtual void set_message_handler(message_handlert &handler) + { + summarizer_bw_cex_concrete.set_message_handler(handler); + summarizer_bw_cex_ai.set_message_handler(handler); + summarizer_bw_cex_complete.set_message_handler(handler); + messaget::set_message_handler(handler); + } + + + virtual property_checkert::resultt check(); + + protected: + summarizer_bw_cex_concretet summarizer_bw_cex_concrete; + summarizer_bw_cex_ait summarizer_bw_cex_ai; + summarizer_bw_cex_completet summarizer_bw_cex_complete; + property_checkert::resultt result; + +}; + + +#endif diff --git a/src/summarizer/summarizer_bw_cex_complete.cpp b/src/summarizer/summarizer_bw_cex_complete.cpp new file mode 100644 index 000000000..cad7b61de --- /dev/null +++ b/src/summarizer/summarizer_bw_cex_complete.cpp @@ -0,0 +1,525 @@ +/*******************************************************************\ + +Module: Simple Complete Counterexample-based Backward Analysis + +Author: Peter Schrammel + +\*******************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include "summary_db.h" + +#include "../domains/ssa_analyzer.h" +#include "../domains/template_generator_summary.h" +#include "../domains/template_generator_callingcontext.h" + +#include "../ssa/local_ssa.h" +#include "../ssa/simplify_ssa.h" +#include "../ssa/ssa_dependency_graph.h" + +#include "summarizer_bw_cex_complete.h" + +/*******************************************************************\ + +Function: summarizer_bw_cex_completet::summarize() + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +void summarizer_bw_cex_completet::summarize +( + const function_namet &entry_function) +{ + // no dependencies to begin with + find_symbols_sett dependency_set; + + status() << "\nSummarizing function " << entry_function << eom; + compute_summary_rec(entry_function,dependency_set,-1); +} + +/*******************************************************************\ + +Function: summarizer_bw_cex_completet::summarize() + + Inputs: + + Outputs: + + Purpose: summarize backwards from given assertion + +\*******************************************************************/ + +void summarizer_bw_cex_completet::summarize(const exprt &_error_assertion) +{ + status() << "\nBackward error analysis (complete)..." << eom; + error_assertion = _error_assertion; + /* + std::cout << "error assertion: " + << from_expr(ssa_db.get(entry_function).ns, "", error_assertion) + << "\n"; + */ + summarize(entry_function); +} + + +/*******************************************************************\ + +Function: summarizer_bw_cex_completet::inline_summaries() + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +find_symbols_sett summarizer_bw_cex_completet::inline_summaries +( + const function_namet &function_name, + find_symbols_sett &dependency_set, + int counter) +{ + local_SSAt &SSA = ssa_db.get(function_name); + //solver << SSA.get_enabling_exprs(); + + exprt::operandst loophead_selects; + loophead_selects = this->get_loophead_selects(SSA,ssa_unwinder.get(function_name),*solver.solver); + exprt c = conjunction(loophead_selects); + + //std::cout << "Solver <-- " << function_name << ": (conjunction of loophead_selects):" + // << "\t original info ~ " << from_expr(ssa_db.get(function_name).ns, "", c) << "\n"; + + ssa_inliner.rename(c, counter); + +#if 0 + std::cout << "Solver <-- " << function_name << ": (conjunction of loophead_selects):" + << "\t renamed info ~ " << from_expr(ssa_db.get(function_name).ns, "", c) << "\n"; +#endif + + solver << c; + + ssa_dependency_grapht &ssa_depgraph = ssa_db.get_depgraph(function_name); + + struct worknodet{ + int node_index; + find_symbols_sett dependency_set; + }; + + worknodet start_node; + start_node.node_index = 0; + start_node.dependency_set = dependency_set; + + typedef std::list worklistt; + worklistt worklist, work_waitlist; + std::vector covered_nodes; + + worklist.push_back(start_node); + + while(!worklist.empty()){ + + /* + std::cout << "worklist: "; + for(worklistt::const_iterator w_it=worklist.begin(); + w_it != worklist.end(); w_it++){ + std::cout << w_it->node_index << " "; + } + std::cout << "\n"; + + std::cout << "\t waitlist: "; + for(worklistt::const_iterator w_it=work_waitlist.begin(); + w_it != work_waitlist.end(); w_it++){ + std::cout << w_it->node_index << " "; + } + std::cout << "\n"; + */ + + worknodet &worknode = worklist.front(); + + //std::cout << "working node: " << function_name << ": " << worknode.node_index << "\n"; + ///////////////////////////////////////////////////////////////////////////////////// + //std::cout << "\t size of dependency set: " << worknode.dependency_set.size() << "\n"; + /* + std::cout << "\t dependency set: "; + for(find_symbols_sett::iterator d_it = worknode.dependency_set.begin(); + d_it != worknode.dependency_set.end(); d_it++){ + std::cout << *d_it; + } + std::cout << "\n\n\n"; + */ + ///////////////////////////////////////////////////////////////////////////////////// + + + // return if the top most node is reached + if(worknode.node_index == ssa_depgraph.top_node_index) + return worknode.dependency_set; + + // modify worknode_dependency_set if the node is an assertion + if(ssa_depgraph.depnodes_map[worknode.node_index].is_assertion == true){ + + //std::cout << "\t\t an assertion node\n"; + for(find_symbols_sett::const_iterator d_it = ssa_depgraph.depnodes_map[worknode.node_index].used_symbols.begin(); + d_it != ssa_depgraph.depnodes_map[worknode.node_index].used_symbols.end(); d_it++){ + worknode.dependency_set.insert(*d_it); + } + + ///////////////////////////////////////////////////////////////////////////////////// + /* + std::cout << "\t size of dependency set: " << worknode.dependency_set.size() << "\n"; + + std::cout << "\t dependency set: "; + for(find_symbols_sett::iterator d_it = worknode.dependency_set.begin(); + d_it != worknode.dependency_set.end(); d_it++){ + std::cout << *d_it; + } + std::cout << "\n"; + */ + ///////////////////////////////////////////////////////////////////////////////////// + + + + } + + // if this is a function call + if(ssa_depgraph.depnodes_map[worknode.node_index].is_function_call == true){ + //std::cout << "fcall: working node: " << function_name << ": " << worknode.node_index << "\n"; + irep_idt fname = + to_symbol_expr((to_function_application_expr(ssa_depgraph.depnodes_map[worknode.node_index].node_info)).function()).get_identifier(); + + find_symbols_sett renamed_dependencies; + + ///////////////////////////////////////////////////////////////////////////////////// + /* + std::cout << "\t size of dependency set: " << worknode.dependency_set.size() << "\n"; + + std::cout << "\t dependency set: "; + for(find_symbols_sett::iterator d_it = worknode.dependency_set.begin(); + d_it != worknode.dependency_set.end(); d_it++){ + std::cout << *d_it; + } + std::cout << "\n"; + */ + ///////////////////////////////////////////////////////////////////////////////////// + + for(find_symbols_sett::iterator d_it = worknode.dependency_set.begin(); + d_it != worknode.dependency_set.end(); d_it++){ + irep_idt id = *d_it; + // detach the '@' symbol if there + irep_idt renamed_id = ssa_inliner.rename + (id, + ssa_depgraph.depnodes_map[worknode.node_index].rename_counter, false); + renamed_dependencies.insert(renamed_id); + } + + worknode.dependency_set = renamed_dependencies; + + if(!worknode.dependency_set.empty()){ + find_symbols_sett guard_dependencies; + find_symbols(ssa_depgraph.depnodes_map[worknode.node_index].guard, + guard_dependencies); + for(find_symbols_sett::const_iterator d_it = guard_dependencies.begin(); + d_it != guard_dependencies.end(); d_it++){ + worknode.dependency_set.insert(*d_it); + } + } + + ///////////////////////////////////////////////////////////////////////////////////// + /* + std::cout << "\t size of dependency set: " << worknode.dependency_set.size() << "\n"; + + std::cout << "\t dependency set: "; + for(find_symbols_sett::iterator d_it = worknode.dependency_set.begin(); + d_it != worknode.dependency_set.end(); d_it++){ + std::cout << *d_it; + } + std::cout << "\n"; + */ + ///////////////////////////////////////////////////////////////////////////////////// + + worknode.dependency_set = + compute_summary_rec(fname,worknode.dependency_set, + ssa_depgraph.depnodes_map[worknode.node_index].rename_counter); + + + renamed_dependencies.clear(); + + for(find_symbols_sett::iterator d_it = worknode.dependency_set.begin(); + d_it != worknode.dependency_set.end(); d_it++){ + irep_idt id = *d_it; + // attach the '@' symbol if not already there + irep_idt renamed_id = ssa_inliner.rename + (id, + ssa_depgraph.depnodes_map[worknode.node_index].rename_counter, true); + renamed_dependencies.insert(renamed_id); + } + + worknode.dependency_set = renamed_dependencies; + + if(!worknode.dependency_set.empty()){ + find_symbols_sett guard_dependencies; + find_symbols(ssa_depgraph.depnodes_map[worknode.node_index].guard, guard_dependencies); + for(find_symbols_sett::const_iterator d_it = guard_dependencies.begin(); + d_it != guard_dependencies.end(); d_it++){ + worknode.dependency_set.insert(*d_it); + } + } + + } + + // if the dependency set is non-empty + if(!worknode.dependency_set.empty()){ + exprt worknode_info = ssa_depgraph.depnodes_map[worknode.node_index].node_info; + if(ssa_depgraph.depnodes_map[worknode.node_index].is_assertion == true) + worknode_info = not_exprt(worknode_info); + + if(worknode.node_index != 0){ + if(!(ssa_depgraph.depnodes_map[worknode.node_index].is_function_call)){ + if((ssa_depgraph.depnodes_map[worknode.node_index].is_assertion == false) || + (worknode_info == error_assertion)){ + /* + std::cout << "Solver <-- " << function_name << ": (node) node#:" + << worknode.node_index << "\t original info ~ " + << from_expr((ssa_db.get(function_name)).ns, "", worknode_info) << "\n"; + */ + ssa_inliner.rename(worknode_info, counter); +#if 0 + std::cout << "Solver <-- renamed assertion: " << from_expr((ssa_db.get(function_name)).ns, "", worknode_info) << "\n"; + std::cout << "Solver <-- " << function_name << ": (node) node#:" + << worknode.node_index << "\t renamed info ~ " + << from_expr((ssa_db.get(function_name)).ns, "", worknode_info) << "\n"; +#endif + solver << worknode_info; + } + } + else{ + exprt guard_binding = ssa_depgraph.depnodes_map[worknode.node_index].guard; + /* + std::cout << "Solver <-- " << function_name << ": (bind) node#:" + << worknode.node_index << "\t original info ~ " + << from_expr(ssa_db.get(function_name).ns, "", guard_binding) << "\n"; + */ + ssa_inliner.rename(guard_binding, counter); +#if 0 + std::cout << "Solver <-- " << function_name << ": (bind) node#:" + << worknode.node_index << "\t renamed info ~ " + << from_expr(ssa_db.get(function_name).ns, "", guard_binding) << "\n"; +#endif + solver << guard_binding; + } + } + } + + // if not a function call and the dependency set is non-empty + if((ssa_depgraph.depnodes_map[worknode.node_index].is_function_call == false) && + (!worknode.dependency_set.empty())){ + + exprt worknode_info = ssa_depgraph.depnodes_map[worknode.node_index].node_info; + if(ssa_depgraph.depnodes_map[worknode.node_index].is_assertion == true) + worknode_info = not_exprt(worknode_info); + + if((ssa_depgraph.depnodes_map[worknode.node_index].is_assertion == false) || + (worknode_info == error_assertion)){ + worknode.dependency_set = + ssa_depgraph.depnodes_map[worknode.node_index].used_symbols; + } + } + + for(ssa_dependency_grapht::annotated_predecessorst::const_iterator + p_it = ssa_depgraph.depnodes_map[worknode.node_index].predecessors.begin(); + p_it != ssa_depgraph.depnodes_map[worknode.node_index].predecessors.end(); + p_it++){ + + ssa_dependency_grapht::annotated_predecessort pred = *p_it; + int pred_node_index = pred.predecessor_node_index; + find_symbols_sett pred_annotation = pred.annotation; + + bool dependencies_merged = false; + for(worklistt::iterator w_it = work_waitlist.begin(); w_it != work_waitlist.end(); w_it++){ + if(w_it->node_index == pred_node_index){ + + dependencies_merged = true; + + for(find_symbols_sett::const_iterator + a_it=pred_annotation.begin(); a_it!=pred_annotation.end(); a_it++) + { + if(worknode.dependency_set.find(*a_it) != worknode.dependency_set.end()){ + if((w_it->dependency_set).find(*a_it) == (w_it->dependency_set).end()){ + (w_it->dependency_set).insert(*a_it); + } + } + } + break; + } + } + + if(dependencies_merged == false){ + worknodet new_worknode; + new_worknode.node_index = pred_node_index; + + for(find_symbols_sett::const_iterator + a_it=pred_annotation.begin(); a_it!=pred_annotation.end(); a_it++) + { + if(worknode.dependency_set.find(*a_it) != worknode.dependency_set.end()) + new_worknode.dependency_set.insert(*a_it); + } + + work_waitlist.push_back(new_worknode); + } + } + +#if 0 + std::cout << function_name << ": worklist: "; + for(worklistt::const_iterator w_it=worklist.begin(); + w_it != worklist.end(); w_it++){ + std::cout << w_it->node_index << " "; + } + std::cout << "\n"; + + + std::cout << "\t" << function_name << ": waitlist: "; + for(worklistt::const_iterator w_it=work_waitlist.begin(); + w_it != work_waitlist.end(); w_it++){ + std::cout << w_it->node_index << " "; + } + std::cout << "\n"; +#endif + + covered_nodes.push_back(worknode.node_index); + worklist.pop_front(); + +#if 0 + std::cout << function_name << ": covered : "; + for(int l = 0; l < covered_nodes.size(); l++){ + std::cout << covered_nodes[l] << " "; + } + std::cout << "\n"; +#endif + + worklistt iterate_work_waitlist = work_waitlist; + work_waitlist.clear(); + + for(worklistt::const_iterator w_it = iterate_work_waitlist.begin(); w_it != iterate_work_waitlist.end(); w_it++){ + worknodet waitlisted_worknode = *w_it; + + bool uncovered_successor = false; + + std::vector &waitlisted_worknode_successors = + ssa_depgraph.depnodes_map[waitlisted_worknode.node_index].successors; + + for(unsigned i = 0; i < waitlisted_worknode_successors.size(); i++){ + bool check_covered = false; + for(unsigned j = 0; j < covered_nodes.size(); j++){ + if(waitlisted_worknode_successors[i] == covered_nodes[j]){ + check_covered = true; + break; + } + } + if(!check_covered){ +#if 0 + std::cout << function_name << ": an uncovered successor of " << waitlisted_worknode.node_index << " : " + << waitlisted_worknode_successors[i] << "\n"; +#endif + uncovered_successor = true; + break; + } + } + + if(!uncovered_successor){ + worklist.push_back(waitlisted_worknode); + } + else{ + work_waitlist.push_back(waitlisted_worknode); + } + + } + } + + /* the following code is to stop a warning; this function must + return from the first if-condition inside the while loop */ + std::cout << "check graph of the function: " << function_name << "\n"; + assert(false); + return dependency_set; +} + +/*******************************************************************\ + +Function: summarizer_bw_cex_completet::compute_summary_rec() + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +find_symbols_sett summarizer_bw_cex_completet::compute_summary_rec + ( + const function_namet &function_name, + find_symbols_sett &dependency_set, + int counter) +{ + // recursively compute summaries for function calls + return inline_summaries(function_name,dependency_set,counter); +} + +/*******************************************************************\ + +Function: summarizer_bw_cex_completet::check() + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +property_checkert::resultt summarizer_bw_cex_completet::check() +{ + solver_calls++; // for statistics + if(solver() == decision_proceduret::D_SATISFIABLE){ + //std::cout << "Solver <-- renamed info ~ SAT\n"; + return property_checkert::FAIL; + } + //std::cout << "Solver <-- renamed info ~ UNSAT\n"; + return property_checkert::UNKNOWN; +} + +/*******************************************************************\ + +Function: summarizer_bw_cex_completet::debug_print() + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +void summarizer_bw_cex_completet::debug_print +( + const function_namet &function_name, + find_symbols_sett &dependency_set) +{ + std::cout << "DebugInfo: function -> " << function_name + << " ; dependency_set -> "; + for(find_symbols_sett::iterator d_it = dependency_set.begin(); + d_it != dependency_set.end(); d_it++){ + std::cout << *d_it << ", "; + } + std::cout << "\n"; +} diff --git a/src/summarizer/summarizer_bw_cex_complete.h b/src/summarizer/summarizer_bw_cex_complete.h new file mode 100644 index 000000000..243120480 --- /dev/null +++ b/src/summarizer/summarizer_bw_cex_complete.h @@ -0,0 +1,64 @@ +/*******************************************************************\ + +Module: Simple Complete Counterexample-based Backward Analysis + +Author: Peter Schrammel + +\*******************************************************************/ + +#ifndef CPROVER_SUMMARIZER_BW_CEX_COMPLETE_H +#define CPROVER_SUMMARIZER_BW_CEX_COMPLETE_H + +#include +#include +#include +#include "../ssa/ssa_inliner.h" +#include "../ssa/ssa_unwinder.h" +#include "../ssa/local_ssa.h" +#include "ssa_db.h" + +#include + +#include "summarizer_bw_cex.h" + +class summarizer_bw_cex_completet : public summarizer_bw_cex_baset +{ + public: + explicit summarizer_bw_cex_completet(optionst &_options, + summary_dbt &_summary_db, + ssa_dbt &_ssa_db, + ssa_unwindert &_ssa_unwinder, + ssa_inlinert &_ssa_inliner, + incremental_solvert &_solver, + function_namet _entry_function, + function_namet _error_function): + summarizer_bw_cex_baset(_options,_summary_db,_ssa_db,_ssa_unwinder,_ssa_inliner, + _entry_function,_error_function), + solver(_solver) + {} + + virtual void summarize(const function_namet &entry_function); + virtual void summarize(const exprt &_error_assertion); + + virtual property_checkert::resultt check(); + + protected: + incremental_solvert &solver; + + virtual find_symbols_sett inline_summaries( + const function_namet &function_name, + find_symbols_sett &dependency_set, + int counter); + + virtual find_symbols_sett compute_summary_rec( + const function_namet &function_name, + find_symbols_sett &dependency_set, + int counter); + virtual void debug_print( + const function_namet &function_name, + find_symbols_sett &dependency_set); + +}; + + +#endif diff --git a/src/summarizer/summarizer_bw_cex_concrete.cpp b/src/summarizer/summarizer_bw_cex_concrete.cpp new file mode 100644 index 000000000..f06da6367 --- /dev/null +++ b/src/summarizer/summarizer_bw_cex_concrete.cpp @@ -0,0 +1,614 @@ +/*******************************************************************\ + +Module: Simple Counterexample-based Backward Analysis + +Author: Kumar Madhukar, Peter Schrammel + +\*******************************************************************/ + +//#define OPT_11 // simplify before pushing to solver +#define OPT_12 // collect, conjunct, simplify and then push to the solver + +//#define OPT_2 // a fresh solver each time + +//TODO: a bug in the fresh solver case; does not compute +//calling contexts (see struct tests in regression) + +#include + +#include +#include +#include +#include +#include + +#include "summarizer_bw_cex_concrete.h" +#include "summary_db.h" + +#include "../domains/ssa_analyzer.h" +#include "../domains/template_generator_summary.h" +#include "../domains/template_generator_callingcontext.h" + +#include "../ssa/local_ssa.h" +#include "../ssa/simplify_ssa.h" + +/*******************************************************************\ + +Function: summarizer_bw_cex_concretet::summarize() + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +void summarizer_bw_cex_concretet::summarize(const function_namet &function_name) +{ + exprt postcondition = true_exprt(); //initial calling context + + status() << "\nSummarizing function " << function_name << eom; + compute_summary_rec(function_name,summaryt::entry_call_site, + postcondition,true); +} + +/*******************************************************************\ + +Function: summarizer_bw_cex_concretet::summarize() + + Inputs: + + Outputs: + + Purpose: summarize backwards from given assertion + +\*******************************************************************/ + +void summarizer_bw_cex_concretet::summarize(const exprt &_error_assertion) +{ + status() << "\nBackward error analysis (concrete)..." << eom; + error_assertion = _error_assertion; + + summarize(entry_function); +} + +/*******************************************************************\ + +Function: summarizer_bw_cex_concretet::check() + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +property_checkert::resultt summarizer_bw_cex_concretet::check() +{ + //TODO: store information about why have UNKNOWN + // we have to distinguish the case when we cannot decide about spuriousness + + if(!summary_db.exists(entry_function)) + return property_checkert::UNKNOWN; + + const summaryt &summary = summary_db.get(entry_function); + if(summary.error_summaries.empty() || + summary.error_summaries.begin()->second.is_nil() || + summary.error_summaries.begin()->second.is_true()) + return property_checkert::UNKNOWN; + + return property_checkert::FAIL; +} + +/*******************************************************************\ + +Function: summarizer_bw_cex_concretet::compute_summary_rec() + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +void summarizer_bw_cex_concretet::compute_summary_rec( + const function_namet &function_name, + const summaryt::call_sitet &call_site, + const exprt &_postcondition, + bool context_sensitive) +{ + local_SSAt &SSA = ssa_db.get(function_name); + + summaryt summary; + if(summary_db.exists(function_name)) + summary = summary_db.get(function_name); + else + { + summary.params = SSA.params; + summary.globals_in = SSA.globals_in; + summary.globals_out = SSA.globals_out; + } + + // insert assertion + exprt end_guard = SSA.guard_symbol(--SSA.goto_function.body.instructions.end()); + exprt postcondition = implies_exprt(end_guard,_postcondition); + if(function_name == error_function) + { + postcondition = and_exprt(postcondition,not_exprt(error_assertion)); + } + + summary.bw_postcondition = _postcondition; + +#if 0 + debug() << "Postcondition: " << + from_expr(SSA.ns, "", postcondition) << eom; +#endif + + // recursively compute summaries for function calls + inline_summaries(function_name,SSA,summary, + postcondition,context_sensitive, + true); + + status() << "Analyzing function " << function_name << eom; + + do_summary(function_name,call_site,SSA,summary,summary,postcondition,context_sensitive); + + if(function_name == error_function) + summary.has_assertion = true; + + summary_db.set(function_name,summary); + + { + std::ostringstream out; + out << std::endl << "Summary for function " << function_name << std::endl; + summary_db.get(function_name).output(out,SSA.ns); + debug() << out.str() << eom; + } + +} + +/*******************************************************************\ + +Function: summarizer_bw_cex_concretet::do_summary() + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +void summarizer_bw_cex_concretet::do_summary( + const function_namet &function_name, + const summaryt::call_sitet &call_site, + local_SSAt &SSA, + const summaryt &old_summary, + summaryt &summary, + const exprt &postcondition, + bool context_sensitive) +{ + status() << "Computing error summary" << eom; + + // solver + +#ifdef OPT_2 + incremental_solvert* fresh_solver = incremental_solvert::allocate(SSA.ns, options.get_bool_option("refine")); + //incremental_solvert &solver = ssa_db.get_solver(function_name); + + incremental_solvert &solver = (*fresh_solver); +#else + incremental_solvert &solver = ssa_db.get_solver(function_name); +#endif + + solver.set_message_handler(get_message_handler()); + + //ENHANCE: we could reuse the solver state, but it's difficult + // (the function maybe called several times) + exprt::operandst c; + +#ifdef OPT_12 + exprt::operandst store; +#endif + + //add forward information if available + if(!old_summary.fw_precondition.is_nil()) + c.push_back(old_summary.fw_precondition); + if(!old_summary.fw_invariant.is_nil()) + c.push_back(old_summary.fw_invariant); + c.push_back(ssa_inliner.get_summaries(SSA)); //forward summaries + + exprt::operandst assert_postcond, noassert_postcond; + // add error summaries for function calls + bool assertion_flag; + assertion_flag = ssa_inliner.get_summaries(SSA,call_site,false,assert_postcond,noassert_postcond,c); //backward summaries + assert_postcond.push_back(postcondition); //context + + //std::cout << "Assert Summary: " << from_expr(SSA.ns, "", conjunction(assert_postcond)) << "\n\n"; + //std::cout << "Noassert Summary: " << from_expr(SSA.ns, "", conjunction(noassert_postcond)) << "\n\n"; + + c.push_back(not_exprt(conjunction(assert_postcond))); + c.push_back(not_exprt(disjunction(noassert_postcond))); + +#if 0 + debug() << "Backward summaries: " << + from_expr(SSA.ns, "", conjunction(c)) << eom; +#endif + +#ifdef OPT_12 + store << SSA; +#else + solver << SSA; +#endif + + solver.new_context(); + + // assumptions must hold + for(local_SSAt::nodest::const_iterator + n_it = SSA.nodes.begin(); + n_it != SSA.nodes.end(); + ++n_it) + for(local_SSAt::nodet::assumptionst::const_iterator + a_it = n_it->assumptions.begin(); + a_it != n_it->assumptions.end(); + ++a_it){ + + /* +#ifdef OPT_11 + solver << simplify_expr(*a_it, SSA.ns); +#elif OPT_12 + store.push_back(*a_it); +#else + solver << *a_it; +#endif + */ + +#ifdef OPT_11 + solver << simplify_expr(*a_it, SSA.ns); +#else +#ifdef OPT_12 + store.push_back(*a_it); +#else + solver << *a_it; +#endif +#endif + + } + +#ifdef OPT_12 + store.push_back(SSA.get_enabling_exprs()); +#else + solver << SSA.get_enabling_exprs(); +#endif + + /* +#ifdef OPT_11 + solver << simplify_expr(conjunction(c), SSA.ns); +#elif OPT_12 + store.push_back(conjunction(c)); +#else + solver << conjunction(c); +#endif + */ + +#ifdef OPT_11 + solver << simplify_expr(conjunction(c), SSA.ns); +#else +#ifdef OPT_12 + store.push_back(conjunction(c)); +#else + solver << conjunction(c); +#endif +#endif + + exprt::operandst loophead_selects; + loophead_selects = this->get_loophead_selects(SSA,ssa_unwinder.get(function_name),*solver.solver); + + /* +#ifdef OPT_11 + solver << simplify_expr(conjunction(loophead_selects), SSA.ns); +#elif OPT_12 + store.push_back(conjunction(loophead_selects)); +#else + solver << conjunction(loophead_selects); +#endif + */ + +#ifdef OPT_11 + solver << simplify_expr(conjunction(loophead_selects), SSA.ns); +#else +#ifdef OPT_12 + store.push_back(conjunction(loophead_selects)); +#else + solver << conjunction(loophead_selects); +#endif +#endif + +#ifdef OPT_12 + std::cout << "\n\n\n pushing to the solver in do_summary:" << from_expr(SSA.ns, "", simplify_expr(conjunction(store), SSA.ns)) << "\n\n\n"; + solver << simplify_expr(conjunction(store), SSA.ns); +#endif + + //statistics + solver_calls++; + + //solve + if(solver() != decision_proceduret::D_SATISFIABLE) + { + summary.error_summaries[call_site] = true_exprt(); //TODO: this is likely to be incomplete + summary.has_assertion = assertion_flag; + solver.pop_context(); + + /**/ + // if the summary is true, print the postcondition and the list of loops in this function + // this postcondition is modified, possibly twice, from what is returned by compute_calling_context2 + // pc = end_guard => original_pc, and + // pc = pc && not(assertion), if this is error function + std::cout << "==>>\n"; + std::cout << "==>> Summary: true\n"; + std::cout << "==>> Postcondition: " << from_expr(SSA.ns, "", postcondition) << "\n"; + std::cout << "==>> Function: " << function_name << "\n"; + std::cout << "==>> Loophead selects: " << from_expr(SSA.ns, "", conjunction(loophead_selects)) << "\n"; + for(local_SSAt::nodest::const_iterator n_it = SSA.nodes.begin(); + n_it != SSA.nodes.end(); n_it++){ + if(n_it->loophead!=SSA.nodes.end()){ + std::cout << "==>> Loop found: " << n_it->loophead->location->location_number << "\n"; + } + } + std::cout << "==>>\n"; + /**/ + return; + } + + //build error summary and add to summary + exprt::operandst var_values; + + for(local_SSAt::var_listt::const_iterator it = SSA.params.begin(); + it != SSA.params.end(); it++){ + exprt summ_value = solver.get(*it); + if(!summ_value.is_nil()) + var_values.push_back(equal_exprt(*it, summ_value)); + } + + for(local_SSAt::var_sett::const_iterator it = SSA.globals_in.begin(); + it != SSA.globals_in.end(); it++){ + exprt summ_value = solver.get(*it); + if(!summ_value.is_nil()) + var_values.push_back(equal_exprt(*it, summ_value)); + } + + for(local_SSAt::var_sett::const_iterator it = SSA.globals_out.begin(); + it != SSA.globals_out.end(); it++){ + exprt summ_value = solver.get(*it); + if(!summ_value.is_nil()) + var_values.push_back(equal_exprt(*it, summ_value)); + } + + summary.error_summaries[call_site] = not_exprt(conjunction(var_values)); + summary.has_assertion = assertion_flag; + + solver.pop_context(); + +#ifdef OPT_2 + delete fresh_solver; +#endif + +} + +/*******************************************************************\ + +Function: summarizer_bw_cex_concretet::inline_summaries() + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +void summarizer_bw_cex_concretet::inline_summaries( + const function_namet &function_name, + local_SSAt &SSA, + const summaryt &old_summary, + const exprt &postcondition, + bool context_sensitive, + bool sufficient) +{ + for(local_SSAt::nodest::const_iterator n_it = SSA.nodes.end(); + n_it != SSA.nodes.begin(); ) + { + n_it--; + + for(local_SSAt::nodet::function_callst::const_iterator f_it = + n_it->function_calls.begin(); + f_it != n_it->function_calls.end(); f_it++) + { + assert(f_it->function().id()==ID_symbol); //no function pointers + + exprt postcondition_call = true_exprt(); + postcondition_call = compute_calling_context2( + function_name,SSA,old_summary,n_it,f_it,postcondition,sufficient); + + irep_idt fname = to_symbol_expr(f_it->function()).get_identifier(); + status() << "Recursively summarizing function " << fname << eom; + compute_summary_rec(fname,summaryt::call_sitet(n_it->location), + postcondition_call,context_sensitive); + } + } +} + +/*******************************************************************\ + +Function: summarizer_bw_cex_concretet::compute_calling_context2() + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +exprt summarizer_bw_cex_concretet::compute_calling_context2( + const function_namet &function_name, + local_SSAt &SSA, + summaryt old_summary, + local_SSAt::nodest::const_iterator n_it, + local_SSAt::nodet::function_callst::const_iterator f_it, + const exprt &postcondition, + bool sufficient) +{ + assert(f_it->function().id()==ID_symbol); //no function pointers + irep_idt fname = to_symbol_expr(f_it->function()).get_identifier(); + + status() << "Computing calling context for function " << fname << eom; + + // solver + +#ifdef OPT_2 + incremental_solvert* fresh_solver = incremental_solvert::allocate(SSA.ns, options.get_bool_option("refine")); + //incremental_solvert &solver = ssa_db.get_solver(function_name); + incremental_solvert &solver = (*fresh_solver); +#else + incremental_solvert &solver = ssa_db.get_solver(function_name); +#endif + + solver.set_message_handler(get_message_handler()); + + // collect globals at call site + std::map + cs_globals_out; + SSA.get_globals(n_it->location,cs_globals_out[f_it],false); + + exprt::operandst c; + +#ifdef OPT_12 + exprt::operandst store; +#endif + + // add forward information if available + if(!old_summary.fw_precondition.is_nil()) + c.push_back(old_summary.fw_precondition); + if(!old_summary.fw_invariant.is_nil()) + c.push_back(old_summary.fw_invariant); + c.push_back(ssa_inliner.get_summaries(SSA)); //forward summaries + + exprt::operandst assert_postcond, noassert_postcond; + // add error summaries for function calls + ssa_inliner.get_summaries(SSA,summaryt::call_sitet(n_it->location),false,assert_postcond,noassert_postcond,c); //backward summaries + assert_postcond.push_back(postcondition); //context + c.push_back(not_exprt(conjunction(assert_postcond))); + c.push_back(not_exprt(disjunction(noassert_postcond))); + +#ifdef OPT_12 + store << SSA; +#else + solver << SSA; +#endif + + solver.new_context(); + +#ifdef OPT_12 + store.push_back(SSA.get_enabling_exprs()); +#else + solver << SSA.get_enabling_exprs(); +#endif + + /* +#ifdef OPT_11 + solver << simplify_expr(conjunction(c), SSA.ns); +#elif OPT_12 + store.push_back(conjunction(c)); +#else + solver << conjunction(c); +#endif + */ + +#ifdef OPT_11 + solver << simplify_expr(conjunction(c), SSA.ns); +#else +#ifdef OPT_12 + store.push_back(conjunction(c)); +#else + solver << conjunction(c); +#endif +#endif + + exprt::operandst loophead_selects; + loophead_selects = this->get_loophead_selects(SSA,ssa_unwinder.get(function_name),*solver.solver); + + /* +#ifdef OPT_11 + solver << simplify_expr(conjunction(loophead_selects), SSA.ns); +#elif OPT_12 + store.push_back(conjunction(loophead_selects)); +#else + solver << conjunction(loophead_selects); +#endif + */ + +#ifdef OPT_11 + solver << simplify_expr(conjunction(loophead_selects), SSA.ns); +#else +#ifdef OPT_12 + store.push_back(conjunction(loophead_selects)); +#else + solver << conjunction(loophead_selects); +#endif +#endif + +#ifdef OPT_12 + std::cout << "\n\n\n pushing to the solver in compute_calling_context2:" << from_expr(SSA.ns, "", conjunction(store)) << "\n\n\n"; + solver << simplify_expr(conjunction(store), SSA.ns); +#endif + + + // build postcondition + exprt postcondition_call; + + if(solver() != decision_proceduret::D_SATISFIABLE) + { + postcondition_call = true_exprt(); //TODO: this is likely to be incomplete + solver.pop_context(); + return postcondition_call; + } + + bool result = solver()==decision_proceduret::D_SATISFIABLE; + assert(result); + + exprt::operandst postcond_values; + for(local_SSAt::var_sett::const_iterator it = cs_globals_out[f_it].begin(); + it != cs_globals_out[f_it].end(); it++) + { + exprt postc_value = solver.get(*it); + postcond_values.push_back(equal_exprt(*it, postc_value)); + } + postcondition_call = conjunction(postcond_values); + + solver.pop_context(); + + // get callee SSA and rename + local_SSAt &fSSA = ssa_db.get(fname); + ssa_inliner.rename_to_callee(f_it, fSSA.params, + cs_globals_out[f_it],fSSA.globals_out, + postcondition_call); + + debug() << "Backward calling context for " << + from_expr(SSA.ns, "", *f_it) << ": " + << from_expr(SSA.ns, "", postcondition_call) << eom; + + //statistics + solver_calls++; + +#ifdef OPT_2 + delete fresh_solver; +#endif + + return not_exprt(postcondition_call); +} + + diff --git a/src/summarizer/summarizer_bw_cex_concrete.h b/src/summarizer/summarizer_bw_cex_concrete.h new file mode 100644 index 000000000..40b7177dd --- /dev/null +++ b/src/summarizer/summarizer_bw_cex_concrete.h @@ -0,0 +1,77 @@ +/*******************************************************************\ + +Module: Simple Counterexample-based Backward Analysis + +Author: Kumar Madhukar, Peter Schrammel + +\*******************************************************************/ + +#ifndef CPROVER_SUMMARIZER_BW_CEX_CONCRETE_H +#define CPROVER_SUMMARIZER_BW_CEX_CONCRETE_H + +#include +#include +#include +#include "../ssa/ssa_inliner.h" +#include "../ssa/ssa_unwinder.h" +#include "../ssa/local_ssa.h" +#include "ssa_db.h" + +#include + +#include "summarizer_bw_cex.h" + +class summarizer_bw_cex_concretet : public summarizer_bw_cex_baset +{ + public: + explicit summarizer_bw_cex_concretet(optionst &_options, + summary_dbt &_summary_db, + ssa_dbt &_ssa_db, + ssa_unwindert &_ssa_unwinder, + ssa_inlinert &_ssa_inliner, + function_namet _entry_function, + function_namet _error_function): + summarizer_bw_cex_baset(_options,_summary_db,_ssa_db, + _ssa_unwinder,_ssa_inliner, + _entry_function,_error_function) + {} + + virtual void summarize(const function_namet &entry_function); + virtual void summarize(const exprt &_error_assertion); + + virtual property_checkert::resultt check(); + + protected: + virtual void compute_summary_rec(const function_namet &function_name, + const summaryt::call_sitet &call_site, + const exprt &postcondition, + bool context_sensitive); + + virtual void inline_summaries(const function_namet &function_name, + local_SSAt &SSA, + const summaryt &old_summary, + const exprt &postcondition, + bool context_sensitive, + bool sufficient); + + virtual void do_summary( + const function_namet &function_name, + const summaryt::call_sitet &call_site, + local_SSAt &SSA, + const summaryt &old_summary, + summaryt &summary, + const exprt &postcondition, + bool context_sensitive); + + virtual exprt compute_calling_context2(const function_namet &function_name, + local_SSAt &SSA, + summaryt old_summary, + local_SSAt::nodest::const_iterator n_it, + local_SSAt::nodet::function_callst::const_iterator f_it, + const exprt &postcondition, + bool sufficient); + +}; + + +#endif diff --git a/src/summarizer/summarizer_bw_cex_wp.cpp b/src/summarizer/summarizer_bw_cex_wp.cpp new file mode 100644 index 000000000..37c629e0a --- /dev/null +++ b/src/summarizer/summarizer_bw_cex_wp.cpp @@ -0,0 +1,645 @@ +/*******************************************************************\ + +Module: Slicing-based WP Counterexample-based Backward Analysis + +Author: Madhukar Kumar, Peter Schrammel + +\*******************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include "summary_db.h" + +#include "../domains/ssa_analyzer.h" +#include "../domains/template_generator_summary.h" +#include "../domains/template_generator_callingcontext.h" + +#include "../ssa/local_ssa.h" +#include "../ssa/simplify_ssa.h" +#include "../ssa/ssa_dependency_graph.h" + +#include "summarizer_bw_cex_wp.h" + +/*******************************************************************\ + +Function: summarizer_bw_cex_wpt::summarize() + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +void summarizer_bw_cex_wpt::summarize +( + const function_namet &entry_function) +{ + // no dependencies to begin with + find_symbols_sett dependency_set; + + status() << "\nSummarizing function " << entry_function << eom; + compute_summary_rec(entry_function,dependency_set,-1, + summaryt::entry_call_site); +} + +/*******************************************************************\ + +Function: summarizer_bw_cex_wpt::summarize() + + Inputs: + + Outputs: + + Purpose: summarize backwards from given assertion + +\*******************************************************************/ + +void summarizer_bw_cex_wpt::summarize(const exprt &_error_assertion) +{ + status() << "\nBackward error analysis (WP)..." << eom; + error_assertion = _error_assertion; + /* + std::cout << "error assertion: " + << from_expr(ssa_db.get(entry_function).ns, "", error_assertion) + << "\n"; + */ + summarize(entry_function); +} + + +/*******************************************************************\ + +Function: summarizer_bw_cex_wpt::inline_summaries() + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +find_symbols_sett summarizer_bw_cex_wpt::inline_summaries +( + const function_namet &function_name, + const find_symbols_sett &dependency_set, + int counter, + exprt &error_summary) +{ + exprt::operandst slice; + + local_SSAt &SSA = ssa_db.get(function_name); + //solver << SSA.get_enabling_exprs(); + + exprt::operandst loophead_selects; + loophead_selects = this->get_loophead_selects(SSA,ssa_unwinder.get(function_name),*solver.solver); + exprt c = conjunction(loophead_selects); + + //std::cout << "Solver <-- " << function_name << ": (conjunction of loophead_selects):" + // << "\t original info ~ " << from_expr(ssa_db.get(function_name).ns, "", c) << "\n"; + + slice.push_back(c); + ssa_inliner.rename(c, counter); + +#if 0 + std::cout << "Solver <-- " << function_name << ": (conjunction of loophead_selects):" + << "\t renamed info ~ " << from_expr(ssa_db.get(function_name).ns, "", c) << "\n"; +#endif + + solver << c; + + ssa_dependency_grapht &ssa_depgraph = ssa_db.get_depgraph(function_name); + + struct worknodet{ + int node_index; + find_symbols_sett dependency_set; + }; + + worknodet start_node; + start_node.node_index = 0; + start_node.dependency_set = dependency_set; + + typedef std::list worklistt; + worklistt worklist, work_waitlist; + std::vector covered_nodes; + + worklist.push_back(start_node); + + while(!worklist.empty()){ + + /* + std::cout << "worklist: "; + for(worklistt::const_iterator w_it=worklist.begin(); + w_it != worklist.end(); w_it++){ + std::cout << w_it->node_index << " "; + } + std::cout << "\n"; + + std::cout << "\t waitlist: "; + for(worklistt::const_iterator w_it=work_waitlist.begin(); + w_it != work_waitlist.end(); w_it++){ + std::cout << w_it->node_index << " "; + } + std::cout << "\n"; + */ + + worknodet &worknode = worklist.front(); + + //std::cout << "working node: " << function_name << ": " << worknode.node_index << "\n"; + ///////////////////////////////////////////////////////////////////////////////////// + //std::cout << "\t size of dependency set: " << worknode.dependency_set.size() << "\n"; + /* + std::cout << "\t dependency set: "; + for(find_symbols_sett::iterator d_it = worknode.dependency_set.begin(); + d_it != worknode.dependency_set.end(); d_it++){ + std::cout << *d_it; + } + std::cout << "\n\n\n"; + */ + ///////////////////////////////////////////////////////////////////////////////////// + + + // return if the top most node is reached + if(worknode.node_index == ssa_depgraph.top_node_index) + { + find_symbols_sett vars = worknode.dependency_set; + vars.insert(dependency_set.begin(), dependency_set.end()); + error_summary = simplify_summary(SSA.ns, conjunction(slice), vars); + return worknode.dependency_set; + } + + // modify worknode_dependency_set if the node is an assertion + if(ssa_depgraph.depnodes_map[worknode.node_index].is_assertion == true){ + + //std::cout << "\t\t an assertion node\n"; + for(find_symbols_sett::const_iterator d_it = ssa_depgraph.depnodes_map[worknode.node_index].used_symbols.begin(); + d_it != ssa_depgraph.depnodes_map[worknode.node_index].used_symbols.end(); d_it++){ + worknode.dependency_set.insert(*d_it); + } + + ///////////////////////////////////////////////////////////////////////////////////// + /* + std::cout << "\t size of dependency set: " << worknode.dependency_set.size() << "\n"; + + std::cout << "\t dependency set: "; + for(find_symbols_sett::iterator d_it = worknode.dependency_set.begin(); + d_it != worknode.dependency_set.end(); d_it++){ + std::cout << *d_it; + } + std::cout << "\n"; + */ + ///////////////////////////////////////////////////////////////////////////////////// + + + + } + + // if this is a function call + if(ssa_depgraph.depnodes_map[worknode.node_index].is_function_call == true){ + //std::cout << "fcall: working node: " << function_name << ": " << worknode.node_index << "\n"; + irep_idt fname = + to_symbol_expr((to_function_application_expr(ssa_depgraph.depnodes_map[worknode.node_index].node_info)).function()).get_identifier(); + + find_symbols_sett renamed_dependencies; + + ///////////////////////////////////////////////////////////////////////////////////// + /* + std::cout << "\t size of dependency set: " << worknode.dependency_set.size() << "\n"; + + std::cout << "\t dependency set: "; + for(find_symbols_sett::iterator d_it = worknode.dependency_set.begin(); + d_it != worknode.dependency_set.end(); d_it++){ + std::cout << *d_it; + } + std::cout << "\n"; + */ + ///////////////////////////////////////////////////////////////////////////////////// + + for(find_symbols_sett::iterator d_it = worknode.dependency_set.begin(); + d_it != worknode.dependency_set.end(); d_it++){ + irep_idt id = *d_it; + // detach the '@' symbol if there + irep_idt renamed_id = ssa_inliner.rename + (id, + ssa_depgraph.depnodes_map[worknode.node_index].rename_counter, false); + renamed_dependencies.insert(renamed_id); + } + + worknode.dependency_set = renamed_dependencies; + + if(!worknode.dependency_set.empty()){ + find_symbols_sett guard_dependencies; + find_symbols(ssa_depgraph.depnodes_map[worknode.node_index].guard, + guard_dependencies); + for(find_symbols_sett::const_iterator d_it = guard_dependencies.begin(); + d_it != guard_dependencies.end(); d_it++){ + worknode.dependency_set.insert(*d_it); + } + } + + ///////////////////////////////////////////////////////////////////////////////////// + /* + std::cout << "\t size of dependency set: " << worknode.dependency_set.size() << "\n"; + + std::cout << "\t dependency set: "; + for(find_symbols_sett::iterator d_it = worknode.dependency_set.begin(); + d_it != worknode.dependency_set.end(); d_it++){ + std::cout << *d_it; + } + std::cout << "\n"; + */ + ///////////////////////////////////////////////////////////////////////////////////// + + worknode.dependency_set = + compute_summary_rec(fname,worknode.dependency_set, + ssa_depgraph.depnodes_map[worknode.node_index].rename_counter,summaryt::call_sitet(ssa_depgraph.depnodes_map[worknode.node_index].location)); + slice.push_back(ssa_depgraph.depnodes_map[worknode.node_index].node_info); + + renamed_dependencies.clear(); + + for(find_symbols_sett::iterator d_it = worknode.dependency_set.begin(); + d_it != worknode.dependency_set.end(); d_it++){ + irep_idt id = *d_it; + // attach the '@' symbol if not already there + irep_idt renamed_id = ssa_inliner.rename + (id, + ssa_depgraph.depnodes_map[worknode.node_index].rename_counter, true); + renamed_dependencies.insert(renamed_id); + } + + worknode.dependency_set = renamed_dependencies; + + if(!worknode.dependency_set.empty()){ + find_symbols_sett guard_dependencies; + find_symbols(ssa_depgraph.depnodes_map[worknode.node_index].guard, guard_dependencies); + for(find_symbols_sett::const_iterator d_it = guard_dependencies.begin(); + d_it != guard_dependencies.end(); d_it++){ + worknode.dependency_set.insert(*d_it); + } + } + + } + + // if the dependency set is non-empty + if(!worknode.dependency_set.empty()){ + exprt worknode_info = ssa_depgraph.depnodes_map[worknode.node_index].node_info; + if(ssa_depgraph.depnodes_map[worknode.node_index].is_assertion == true) + worknode_info = not_exprt(worknode_info); + + if(worknode.node_index != 0){ + if(!(ssa_depgraph.depnodes_map[worknode.node_index].is_function_call)){ + if((ssa_depgraph.depnodes_map[worknode.node_index].is_assertion == false) || + (worknode_info == error_assertion)){ + /* + std::cout << "Solver <-- " << function_name << ": (node) node#:" + << worknode.node_index << "\t original info ~ " + << from_expr((ssa_db.get(function_name)).ns, "", worknode_info) << "\n"; + */ + slice.push_back(worknode_info); + ssa_inliner.rename(worknode_info, counter); +#if 0 + std::cout << "Solver <-- renamed assertion: " << from_expr((ssa_db.get(function_name)).ns, "", worknode_info) << "\n"; + std::cout << "Solver <-- " << function_name << ": (node) node#:" + << worknode.node_index << "\t renamed info ~ " + << from_expr((ssa_db.get(function_name)).ns, "", worknode_info) << "\n"; +#endif + solver << worknode_info; + } + } + else{ + exprt guard_binding = ssa_depgraph.depnodes_map[worknode.node_index].guard; + /* + std::cout << "Solver <-- " << function_name << ": (bind) node#:" + << worknode.node_index << "\t original info ~ " + << from_expr(ssa_db.get(function_name).ns, "", guard_binding) << "\n"; + */ + ssa_inliner.rename(guard_binding, counter); +#if 0 + std::cout << "Solver <-- " << function_name << ": (bind) node#:" + << worknode.node_index << "\t renamed info ~ " + << from_expr(ssa_db.get(function_name).ns, "", guard_binding) << "\n"; +#endif + solver << guard_binding; + slice.push_back(guard_binding); + } + } + } + + // if not a function call and the dependency set is non-empty + if((ssa_depgraph.depnodes_map[worknode.node_index].is_function_call == false) && + (!worknode.dependency_set.empty())){ + + exprt worknode_info = ssa_depgraph.depnodes_map[worknode.node_index].node_info; + if(ssa_depgraph.depnodes_map[worknode.node_index].is_assertion == true) + worknode_info = not_exprt(worknode_info); + + if((ssa_depgraph.depnodes_map[worknode.node_index].is_assertion == false) || + (worknode_info == error_assertion)){ + worknode.dependency_set = + ssa_depgraph.depnodes_map[worknode.node_index].used_symbols; + } + } + + for(ssa_dependency_grapht::annotated_predecessorst::const_iterator + p_it = ssa_depgraph.depnodes_map[worknode.node_index].predecessors.begin(); + p_it != ssa_depgraph.depnodes_map[worknode.node_index].predecessors.end(); + p_it++){ + + ssa_dependency_grapht::annotated_predecessort pred = *p_it; + int pred_node_index = pred.predecessor_node_index; + find_symbols_sett pred_annotation = pred.annotation; + + bool dependencies_merged = false; + for(worklistt::iterator w_it = work_waitlist.begin(); w_it != work_waitlist.end(); w_it++){ + if(w_it->node_index == pred_node_index){ + + dependencies_merged = true; + + for(find_symbols_sett::const_iterator + a_it=pred_annotation.begin(); a_it!=pred_annotation.end(); a_it++) + { + if(worknode.dependency_set.find(*a_it) != worknode.dependency_set.end()){ + if((w_it->dependency_set).find(*a_it) == (w_it->dependency_set).end()){ + (w_it->dependency_set).insert(*a_it); + } + } + } + break; + } + } + + if(dependencies_merged == false){ + worknodet new_worknode; + new_worknode.node_index = pred_node_index; + + for(find_symbols_sett::const_iterator + a_it=pred_annotation.begin(); a_it!=pred_annotation.end(); a_it++) + { + if(worknode.dependency_set.find(*a_it) != worknode.dependency_set.end()) + new_worknode.dependency_set.insert(*a_it); + } + + work_waitlist.push_back(new_worknode); + } + } + +#if 0 + std::cout << function_name << ": worklist: "; + for(worklistt::const_iterator w_it=worklist.begin(); + w_it != worklist.end(); w_it++){ + std::cout << w_it->node_index << " "; + } + std::cout << "\n"; + + + std::cout << "\t" << function_name << ": waitlist: "; + for(worklistt::const_iterator w_it=work_waitlist.begin(); + w_it != work_waitlist.end(); w_it++){ + std::cout << w_it->node_index << " "; + } + std::cout << "\n"; +#endif + + covered_nodes.push_back(worknode.node_index); + worklist.pop_front(); + +#if 0 + std::cout << function_name << ": covered : "; + for(int l = 0; l < covered_nodes.size(); l++){ + std::cout << covered_nodes[l] << " "; + } + std::cout << "\n"; +#endif + + worklistt iterate_work_waitlist = work_waitlist; + work_waitlist.clear(); + + for(worklistt::const_iterator w_it = iterate_work_waitlist.begin(); w_it != iterate_work_waitlist.end(); w_it++){ + worknodet waitlisted_worknode = *w_it; + + bool uncovered_successor = false; + + std::vector &waitlisted_worknode_successors = + ssa_depgraph.depnodes_map[waitlisted_worknode.node_index].successors; + + for(unsigned i = 0; i < waitlisted_worknode_successors.size(); i++){ + bool check_covered = false; + for(unsigned j = 0; j < covered_nodes.size(); j++){ + if(waitlisted_worknode_successors[i] == covered_nodes[j]){ + check_covered = true; + break; + } + } + if(!check_covered){ +#if 0 + std::cout << function_name << ": an uncovered successor of " << waitlisted_worknode.node_index << " : " + << waitlisted_worknode_successors[i] << "\n"; +#endif + uncovered_successor = true; + break; + } + } + + if(!uncovered_successor){ + worklist.push_back(waitlisted_worknode); + } + else{ + work_waitlist.push_back(waitlisted_worknode); + } + + } + } + + /* the following code is to stop a warning; this function must + return from the first if-condition inside the while loop */ + std::cout << "check graph of the function: " << function_name << "\n"; + assert(false); + return dependency_set; +} + +/*******************************************************************\ + +Function: summarizer_bw_cex_wpt::compute_summary_rec() + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +find_symbols_sett summarizer_bw_cex_wpt::compute_summary_rec + ( + const function_namet &function_name, + const find_symbols_sett &dependency_set, + int counter, + const summaryt::call_sitet &call_site) +{ + local_SSAt &SSA = ssa_db.get(function_name); + summaryt summary; + if(summary_db.exists(function_name)) + summary = summary_db.get(function_name); + else + { + summary.params = SSA.params; + summary.globals_in = SSA.globals_in; + summary.globals_out = SSA.globals_out; + } + // recursively compute summaries for function calls + find_symbols_sett new_dependency_set = + inline_summaries(function_name,dependency_set,counter, + summary.error_summaries[call_site]); + + summary_db.set(function_name,summary); + + { + std::ostringstream out; + out << std::endl << "Summary for function " << function_name << std::endl; + summary_db.get(function_name).output(out,SSA.ns); + debug() << out.str() << eom; + } + + return new_dependency_set; +} + +/*******************************************************************\ + +Function: summarizer_bw_cex_wpt::check() + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +property_checkert::resultt summarizer_bw_cex_wpt::check() +{ + solver_calls++; // for statistics + if(solver() == decision_proceduret::D_SATISFIABLE){ + //std::cout << "Solver <-- renamed info ~ SAT\n"; + return property_checkert::FAIL; + } + //std::cout << "Solver <-- renamed info ~ UNSAT\n"; + return property_checkert::UNKNOWN; +} + +/*******************************************************************\ + +Function: summarizer_bw_cex_wpt::debug_print() + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +void summarizer_bw_cex_wpt::debug_print +( + const function_namet &function_name, + find_symbols_sett &dependency_set) +{ + std::cout << "DebugInfo: function -> " << function_name + << " ; dependency_set -> "; + for(find_symbols_sett::iterator d_it = dependency_set.begin(); + d_it != dependency_set.end(); d_it++){ + std::cout << *d_it << ", "; + } + std::cout << "\n"; +} + +/*******************************************************************\ + +Function: summarizer_bw_cex_wpt::simplify_summary() + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ +void summarizer_bw_cex_wpt::simplify_summary_build_map( + replace_mapt &replace_map, const exprt &expr) +{ + if(expr.id()==ID_equal) + { + replace_map[expr.op0()] = expr.op1(); + return; + } + forall_operands(it, expr) + simplify_summary_build_map(replace_map, *it); +} +bool summarizer_bw_cex_wpt::simplify_summary_replace( + const replace_mapt &replace_map, exprt &expr) +{ + if(expr.id()==ID_function_application) + { + bool result = true; + exprt::operandst &args = to_function_application_expr(expr).arguments(); + for(size_t i=0;i +#include +#include +#include "../ssa/ssa_inliner.h" +#include "../ssa/ssa_unwinder.h" +#include "../ssa/local_ssa.h" +#include "ssa_db.h" + +#include + +#include "summarizer_bw_cex.h" + +class summarizer_bw_cex_wpt : public summarizer_bw_cex_baset +{ + public: + explicit summarizer_bw_cex_wpt(optionst &_options, + summary_dbt &_summary_db, + ssa_dbt &_ssa_db, + ssa_unwindert &_ssa_unwinder, + ssa_inlinert &_ssa_inliner, + incremental_solvert &_solver, + function_namet _entry_function, + function_namet _error_function): + summarizer_bw_cex_baset(_options,_summary_db,_ssa_db,_ssa_unwinder,_ssa_inliner, + _entry_function,_error_function), + solver(_solver) + {} + + virtual void summarize(const function_namet &entry_function); + virtual void summarize(const exprt &_error_assertion); + + virtual property_checkert::resultt check(); + + protected: + incremental_solvert &solver; + + virtual find_symbols_sett inline_summaries( + const function_namet &function_name, + const find_symbols_sett &dependency_set, + int counter, + exprt &error_summary); + + virtual find_symbols_sett compute_summary_rec( + const function_namet &function_name, + const find_symbols_sett &dependency_set, + int counter, + const summaryt::call_sitet &call_site); + virtual void debug_print( + const function_namet &function_name, + find_symbols_sett &dependency_set); + + exprt simplify_summary(const namespacet &ns, + exprt summary, + const find_symbols_sett &vars); + void simplify_summary_build_map( + replace_mapt &replace_map, const exprt &expr); + bool simplify_summary_replace( + const replace_mapt &replace_map, exprt &expr); + void simplify_summary_cleanup( + const find_symbols_sett &vars, exprt &expr); + +}; + + +#endif diff --git a/src/summarizer/summarizer_fw_contexts.cpp b/src/summarizer/summarizer_fw_contexts.cpp new file mode 100644 index 000000000..0a78d403e --- /dev/null +++ b/src/summarizer/summarizer_fw_contexts.cpp @@ -0,0 +1,174 @@ +/*******************************************************************\ + +Module: Summarizer for Forward Analysis with Calling Context output + +Author: Peter Schrammel + +\*******************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "summarizer_fw_contexts.h" +#include "summary_db.h" + +#include "../domains/ssa_analyzer.h" +#include "../domains/template_generator_summary.h" +#include "../domains/template_generator_callingcontext.h" + +#include "../ssa/local_ssa.h" +#include "../ssa/simplify_ssa.h" + +/*******************************************************************\ + +Function: summarizer_fw_contextst::summarize() + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +void summarizer_fw_contextst::summarize() +{ + exprt precondition = true_exprt(); //initial calling context + for(functionst::const_iterator it = ssa_db.functions().begin(); + it!=ssa_db.functions().end(); it++) + { + if(excluded_functions.find(it->first)!=excluded_functions.end()) + continue; + status() << "\nSummarizing function " << it->first << eom; + if(!summary_db.exists(it->first) || + summary_db.get(it->first).mark_recompute) + compute_summary_rec(it->first,precondition,false); + else status() << "Summary for function " << it->first << + " exists already" << eom; + } +} + +/*******************************************************************\ + +Function: summarizer_fw_contextst::inline_summaries() + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +void summarizer_fw_contextst::inline_summaries( + const function_namet &function_name, + local_SSAt &SSA, const exprt &precondition, + bool context_sensitive) +{ + for(local_SSAt::nodest::const_iterator n_it = SSA.nodes.begin(); + n_it != SSA.nodes.end(); n_it++) + { + for(local_SSAt::nodet::function_callst::const_iterator f_it = + n_it->function_calls.begin(); + f_it != n_it->function_calls.end(); f_it++) + { + assert(f_it->function().id()==ID_symbol); //no function pointers + if(!check_call_reachable(function_name,SSA,n_it,f_it,precondition,true)) + { + continue; + } + + irep_idt fname = to_symbol_expr(f_it->function()).get_identifier(); + + if(excluded_functions.find(fname)!=excluded_functions.end()) + { + exprt precondition_call = compute_calling_context( + function_name,SSA,n_it,f_it,precondition,true); + + // output calling context + switch(ui) + { + case ui_message_handlert::PLAIN: + break; + + case ui_message_handlert::XML_UI: + { + xmlt xml_cc("calling-context"); + xml_cc.set_attribute("function",id2string(fname)); + xml_cc.set_attribute("goto_location", + i2string(n_it->location->location_number)); + + //location + const source_locationt &source_location = + n_it->location->source_location; + xmlt xml_location; + if(source_location.is_not_nil() && source_location.get_file()!="") + xml_location=xml(source_location); + if(xml_location.name!="") + xml_cc.new_element().swap(xml_location); + + //argument ranges + xmlt xml_args("argument-ranges"); + assert(precondition_call.operands().size()%2==0); + for(unsigned i=0;i +#include +#include + +#include "summarizer_fw.h" + +#include "../ssa/ssa_inliner.h" +#include "../ssa/ssa_unwinder.h" +#include "../ssa/local_ssa.h" +#include "ssa_db.h" + +#include + +class summarizer_fw_contextst : public summarizer_fwt +{ + public: + explicit summarizer_fw_contextst(optionst &_options, + summary_dbt &_summary_db, + ssa_dbt &_ssa_db, + ssa_unwindert &_ssa_unwinder, + ssa_inlinert &_ssa_inliner) : + summarizer_fwt(_options,_summary_db,_ssa_db,_ssa_unwinder,_ssa_inliner), + ui(ui_message_handlert::PLAIN) + { + if(_options.get_bool_option("xml-ui")) + ui = ui_message_handlert::XML_UI; + + optionst::value_listt _excluded_functions = + _options.get_list_option("do-not-analyze-functions"); + excluded_functions.insert(_excluded_functions.begin(), + _excluded_functions.end()); + + } + + virtual void summarize(); + + protected: + language_uit::uit ui; // use gui format + std::set excluded_functions; + + virtual void inline_summaries(const function_namet &function_name, + local_SSAt &SSA, + const exprt &precondition, + bool context_sensitive); +}; + + +#endif diff --git a/src/summarizer/summarizer_parse_options.cpp b/src/summarizer/summarizer_parse_options.cpp new file mode 100644 index 000000000..7dba7d8e1 --- /dev/null +++ b/src/summarizer/summarizer_parse_options.cpp @@ -0,0 +1,1380 @@ +/*******************************************************************\ + +Module: Summarizer Command Line Options Processing + +Author: Daniel Kroening, kroening@kroening.com + +\*******************************************************************/ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "array_abstraction.h" + +#include + +#include + +#include +#include "version.h" + +#include "../ssa/malloc_ssa.h" + +#include "summarizer_parse_options.h" +#include "summary_db.h" +#include "summary_checker_ai.h" +#include "summary_checker_bmc.h" +#include "summary_checker_kind.h" +#include "../ssa/split_loopheads.h" +#include "show.h" + +#define UNWIND_GOTO_INTO_LOOP 1 +#define REMOVE_MULTIPLE_DEREFERENCES 1 + +/*******************************************************************\ + +Function: summarizer_parse_optionst::summarizer_parse_optionst + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +summarizer_parse_optionst::summarizer_parse_optionst(int argc, const char **argv): + parse_options_baset(SUMMARIZER_OPTIONS, argc, argv), + language_uit("Summarizer " CBMC_VERSION, cmdline) +{ +} + +/*******************************************************************\ + +Function: summarizer_parse_optionst::eval_verbosity + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +void summarizer_parse_optionst::eval_verbosity() +{ + // this is our default verbosity + int v=messaget::M_STATISTICS; + + if(cmdline.isset("verbosity")) + { + v=unsafe_string2int(cmdline.get_value("verbosity")); + if(v<0) + v=0; + else if(v>10) + v=10; + } + + ui_message_handler.set_verbosity(v); +} + +/*******************************************************************\ + +Function: summarizer_parse_optionst::get_command_line_options + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +void summarizer_parse_optionst::get_command_line_options(optionst &options) +{ + if(config.set(cmdline)) + { + usage_error(); + exit(1); + } + + if(cmdline.isset("xml-ui")) + options.set_option("xml-ui", true); + + if(cmdline.isset("debug-level")) + options.set_option("debug-level", cmdline.get_value("debug-level")); + + if(cmdline.isset("unwindset")) + options.set_option("unwindset", cmdline.get_value("unwindset")); + + if(cmdline.isset("unwind")) + options.set_option("unwind", cmdline.get_value("unwind")); + + if(cmdline.isset("inline-partial")) + options.set_option("inline-partial", cmdline.get_value("inline-partial")); + + if(cmdline.isset("inline")) + options.set_option("inline", true); + + if(cmdline.isset("spurious-check")) + options.set_option("spurious-check", cmdline.get_value("spurious-check")); + else + options.set_option("spurious-check", "all"); + + if(cmdline.isset("slice") && cmdline.isset("inline")) + options.set_option("slice", true); + else + options.set_option("slice", false); + + // check array bounds + if(cmdline.isset("bounds-check")) + options.set_option("bounds-check", true); + else + options.set_option("bounds-check", false); + + // check division by zero + if(cmdline.isset("div-by-zero-check")) + options.set_option("div-by-zero-check", true); + else + options.set_option("div-by-zero-check", false); + + // check overflow/underflow + if(cmdline.isset("signed-overflow-check")) + options.set_option("signed-overflow-check", true); + else + options.set_option("signed-overflow-check", false); + + // check overflow/underflow + if(cmdline.isset("unsigned-overflow-check")) + options.set_option("unsigned-overflow-check", true); + else + options.set_option("unsigned-overflow-check", false); + + // check overflow on floats + if(cmdline.isset("float-overflow-check")) + options.set_option("float-overflow-check", true); + else + options.set_option("float-overflow-check", false); + + // check for NaN (not a number) + if(cmdline.isset("nan-check")) + options.set_option("nan-check", true); + else + options.set_option("nan-check", false); + + // check pointers + if(cmdline.isset("pointer-check")) + options.set_option("pointer-check", true); + else + options.set_option("pointer-check", false); + + // check for memory leaks + if(cmdline.isset("memory-leak-check")) + options.set_option("memory-leak-check", true); + else + options.set_option("memory-leak-check", false); + + // check assertions + if(cmdline.isset("no-assertions")) + options.set_option("assertions", false); + else + options.set_option("assertions", true); + + // SSA equality propagation + if(cmdline.isset("ssa-propagation")) + options.set_option("ssa-propagation", true); + else + options.set_option("ssa-propagation", false); + + // use assumptions + if(cmdline.isset("no-assumptions")) + options.set_option("assumptions", false); + else + options.set_option("assumptions", true); + + // use arithmetic refinements + if(cmdline.isset("refine")) + options.set_option("refine", true); + else + options.set_option("refine", false); + + if(cmdline.isset("unit-check")) + options.set_option("unit-check", true); + else + options.set_option("unit-check", false); + + // compute standard invariants (include value at loop entry) + if(cmdline.isset("std-invariants")) + options.set_option("std-invariants", true); + else + options.set_option("std-invariants", false); + + // magic error label + if(cmdline.isset("error-label")) + options.set_option("error-label", cmdline.get_value("error-label")); + + if(cmdline.isset("havoc")) + options.set_option("havoc", true); + else if(cmdline.isset("equalities")) + { + options.set_option("equalities", true); + options.set_option("std-invariants", true); + } + else + { + if(cmdline.isset("zones")) + options.set_option("zones", true); + else if(cmdline.isset("qzones")) + options.set_option("qzones", true); + else if(cmdline.isset("octagons")) + options.set_option("octagons", true); + else //if(cmdline.isset("intervals")) //default + options.set_option("intervals", true); + + if(cmdline.isset("enum-solver")) + options.set_option("enum-solver", true); + else //if(cmdline.isset("binsearch-solver")) //default + options.set_option("binsearch-solver", true); + } + + // use incremental assertion checks + if(cmdline.isset("non-incremental")) + options.set_option("incremental", false); + else + options.set_option("incremental", true); + + // compute preconditions + if(cmdline.isset("preconditions")) + options.set_option("preconditions", true); + + // compute necessary/sufficient preconditions + if(cmdline.isset("sufficient")) + options.set_option("sufficient", true); + + // do k-induction refinement + if(cmdline.isset("k-induction")) + { + options.set_option("std-invariants", true); + options.set_option("k-induction", true); +// options.set_option("inline", true); + if(!cmdline.isset("unwind")) + options.set_option("unwind",UINT_MAX); + } + + // do incremental bmc + if(cmdline.isset("incremental-bmc")) + { + options.set_option("incremental-bmc", true); +// options.set_option("inline", true); + options.set_option("havoc", true); + if(!cmdline.isset("unwind")) + options.set_option("unwind",UINT_MAX); + } + + // all properties (default) + if(cmdline.isset("no-all-properties")) + options.set_option("all-properties", false); + else + options.set_option("all-properties", true); + + // competition mode + if(cmdline.isset("competition-mode")) + { + options.set_option("competition-mode", true); + options.set_option("all-properties", false); + } + + // instrumentation / output + if(cmdline.isset("instrument-output")) + options.set_option("instrument-output", + cmdline.get_value("instrument-output")); + + +#ifdef SHOW_CALLING_CONTEXTS + if(cmdline.isset("show-calling-contexts")) + { + if(!options.get_bool_option("intervals")) + throw "--show-calling-contexts only possible with --intervals"; + options.set_option("show-calling-contexts", true); + options.set_option("do-not-analyze-functions", + cmdline.get_value("show-calling-contexts")); + } +#endif +} + +/*******************************************************************\ + +Function: summarizer_parse_optionst::doit + + Inputs: + + Outputs: + + Purpose: invoke main modules + +\*******************************************************************/ + +int summarizer_parse_optionst::doit() +{ + if(cmdline.isset("version")) + { + std::cout << SUMMARIZER_VERSION " (based on CBMC " CBMC_VERSION ")" << std::endl; + return 0; + } + + // + // command line options + // + + optionst options; + get_command_line_options(options); + + eval_verbosity(); + + // + // Print a banner + // + status() << "SUMMARIZER version " SUMMARIZER_VERSION " (based on CBMC " CBMC_VERSION ")" << eom; + + register_language(new_ansi_c_language); + register_language(new_cpp_language); + + goto_modelt goto_model; + + if(get_goto_program(options, goto_model)) + return 6; + + if(cmdline.isset("show-stats")) + { + show_stats(goto_model, std::cout); + return 7; + } + + // options for various debug outputs + + if(cmdline.isset("show-ssa")) + { + bool simplify=!cmdline.isset("no-simplify"); + irep_idt function=cmdline.get_value("function"); + show_ssa(goto_model, function, simplify, std::cout, ui_message_handler); + return 7; + } + + if(cmdline.isset("show-fixed-points")) + { + bool simplify=!cmdline.isset("no-simplify"); + irep_idt function=cmdline.get_value("function"); + show_fixed_points(goto_model, function, simplify, std::cout, ui_message_handler); + return 7; + } + + if(cmdline.isset("show-defs")) + { + irep_idt function=cmdline.get_value("function"); + show_defs(goto_model, function, std::cout, ui_message_handler); + return 7; + } + + if(cmdline.isset("show-assignments")) + { + irep_idt function=cmdline.get_value("function"); + show_assignments(goto_model, function, std::cout, ui_message_handler); + return 7; + } + + if(cmdline.isset("show-guards")) + { + irep_idt function=cmdline.get_value("function"); + show_guards(goto_model, function, std::cout, ui_message_handler); + return 7; + } + + if(cmdline.isset("show-value-sets")) + { + irep_idt function=cmdline.get_value("function"); + show_value_sets(goto_model, function, std::cout, ui_message_handler); + return 7; + } + + if(cmdline.isset("show-invariants")) + { + options.set_option("show-invariants", true); + } + + if(cmdline.isset("context-sensitive")) + { + options.set_option("context-sensitive", true); + status() << "Context-sensitive analysis from " << + goto_model.goto_functions.entry_point() << eom; + } + + if(cmdline.isset("arrays")) + { + options.set_option("arrays", true); + status() << "Do not ignore array contents" << eom; + } + + //TODO: check option inconsistencies, ignored options etc + if(options.get_bool_option("havoc")) + status() << "Havocking loops and function calls" << eom; + else if(options.get_bool_option("equalities")) + status() << "Using (dis)equalities domain" << eom; + else + { + if(options.get_bool_option("intervals")) + status() << "Using intervals domain"; + else if(options.get_bool_option("zones")) + status() << "Using zones domain"; + else if(options.get_bool_option("octagons")) + status() << "Using octagons domain"; + else assert(false); + if(options.get_bool_option("enum-solver")) + status() << " with enumeration solver"; + else if(options.get_bool_option("binsearch-solver")) + status() << " with binary search solver"; + else assert(false); + status() << eom; + } + + try + { + summary_checker_baset *summary_checker = NULL; + if(!options.get_bool_option("k-induction") && + !options.get_bool_option("incremental-bmc")) + summary_checker = new summary_checker_ait(options); + if(options.get_bool_option("k-induction") && + !options.get_bool_option("incremental-bmc")) + summary_checker = new summary_checker_kindt(options); + if(!options.get_bool_option("k-induction") && + options.get_bool_option("incremental-bmc")) + summary_checker = new summary_checker_bmct(options); + + summary_checker->set_message_handler(get_message_handler()); + summary_checker->simplify=!cmdline.isset("no-simplify"); + summary_checker->fixed_point=!cmdline.isset("no-fixed-point"); + + int retval; + if(cmdline.isset("show-vcc")) + { + std::cout << "VERIFICATION CONDITIONS:\n\n"; + summary_checker->show_vcc=true; + (*summary_checker)(goto_model); + retval = 0; + goto clean_up; + } + + // do actual analysis + switch((*summary_checker)(goto_model)) + { + case property_checkert::PASS: + report_properties(goto_model, summary_checker->property_map); + report_success(); + retval = 0; + break; + + case property_checkert::FAIL: + report_properties(goto_model, summary_checker->property_map); + report_failure(); + retval = 10; + break; + + case property_checkert::UNKNOWN: + retval = 5; + if(options.get_bool_option("preconditions")) + goto clean_up; + report_properties(goto_model, summary_checker->property_map); + report_unknown(); + break; + + default: + assert(false); + } + + if(cmdline.isset("instrument-output")) + { + summary_checker->instrument_and_output(goto_model); + } + + clean_up: + delete summary_checker; + return retval; + } + + catch(const std::string error_msg) + { + error() << error_msg << messaget::eom; + return 8; + } + + catch(const char *error_msg) + { + error() << error_msg << messaget::eom; + return 8; + } + + #if 0 + // let's log some more statistics + debug() << "Memory consumption:" << messaget::endl; + memory_info(debug()); + debug() << eom; + #endif +} + + + +void summarizer_parse_optionst::type_stats_rec( + const typet &type, + expr_statst &stats, + const namespacet &ns) +{ + + if(type.id()==ID_symbol) + type_stats_rec(ns.follow(type), stats, ns); + + if(type.id()==ID_pointer || type.id()==ID_array) + { + stats.has_array=true; + + const typet &subtype=ns.follow(type.subtype()); + + if(subtype.id()==ID_signedbv || + subtype.id()==ID_unsignedbv) + { + stats.has_string=(to_bitvector_type(subtype).get_width()==config.ansi_c.char_width); + } + } + + if(type.has_subtypes()) + { + forall_subtypes(it, type) + { + type_stats_rec(*it, stats, ns); + } + } +} + + +/*******************************************************************\ + +Function: summarizer_parse_optionst::expr_stats_rec + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + + +void summarizer_parse_optionst::expr_stats_rec( + const exprt &expr, + expr_statst &stats) +{ + + if(expr.id()==ID_side_effect) + { + const side_effect_exprt &side_effect_expr=to_side_effect_expr(expr); + const irep_idt &statement=side_effect_expr.get_statement(); + + if(statement==ID_malloc) + { + stats.has_malloc=true; + } + else if(statement==ID_nondet) + { + // done in statet:instantiate_rec + } + } + + if(expr.id()==ID_symbol ) + { + + } + + if(expr.has_operands()) + { + forall_operands(it, expr) + { + expr_stats_rec(*it, stats); + } + } +} + + +/*******************************************************************\ + +Function: summarizer_parse_optionst::show_stats + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +void summarizer_parse_optionst::show_stats(const goto_modelt &goto_model, + std::ostream &out) +{ + + const namespacet ns(goto_model.symbol_table); + + expr_statst stats; + + unsigned nr_instructions=0; + unsigned nr_functions=0; + unsigned nr_loops=0; + + // analyze all the functions + forall_goto_functions(f_it, goto_model.goto_functions) + { + if(!f_it->second.body_available()) continue; + + ++nr_functions; + + const goto_programt &goto_program=f_it->second.body; + +#if 0 + statistics() << "function size of " << f_it->first << ": " + << goto_program.instructions.size() << eom; +#endif + + for(goto_programt::instructionst::const_iterator + i_it=goto_program.instructions.begin(); + i_it!=goto_program.instructions.end(); + i_it++) + { + nr_instructions++; + const goto_programt::instructiont &instruction=*i_it; + + if(i_it->is_backwards_goto()) nr_loops++; + + switch(instruction.type) + { + case ASSIGN: + { + const code_assignt &assign=to_code_assign(instruction.code); + expr_stats_rec(assign.lhs(), stats); + expr_stats_rec(assign.rhs(), stats); + } + break; + case ASSUME: + expr_stats_rec(instruction.guard, stats); + break; + case ASSERT: + expr_stats_rec(instruction.guard, stats); + break; + case GOTO: + expr_stats_rec(instruction.guard, stats); + break; + + case DECL: + // someone declaring an array + type_stats_rec(to_code_decl(instruction.code).symbol().type(), stats, ns); + + break; + + default: + // skip + break; + } // switch + } // forall instructions + } // forall functions + + out << " =============== STATS =============== " << std::endl; + out << " nr of instructions: " << nr_instructions << std::endl; + out << " nr of functions: " << nr_functions << std::endl; + out << " nr of loops: " << nr_loops << std::endl; + out << " malloc: " << (stats.has_malloc ? "YES" : "NO") << std::endl; + out << " arrays: " << (stats.has_array ? "YES" : "NO") << std::endl; + out << " strings: " << (stats.has_string ? "YES" : "NO") << std::endl; +} + + +/*******************************************************************\ + +Function: summarizer_parse_optionst::set_properties + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +bool summarizer_parse_optionst::set_properties(goto_modelt &goto_model) +{ + try + { + if(cmdline.isset("property")) + ::set_properties(goto_model, cmdline.get_values("property")); + } + + catch(const char *e) + { + error() << e << eom; + return true; + } + + catch(const std::string e) + { + error() << e << eom; + return true; + } + + catch(int) + { + return true; + } + + return false; +} + +/*******************************************************************\ + +Function: summarizer_parse_optionst::get_goto_program + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +bool summarizer_parse_optionst::get_goto_program( + const optionst &options, + goto_modelt &goto_model) +{ + if(cmdline.args.size()==0) + { + error() << "Please provide a program to verify" << eom; + return true; + } + + try + { + if(cmdline.args.size()==1 && + is_goto_binary(cmdline.args[0])) + { + status() << "Reading GOTO program from file" << eom; + + if(read_goto_binary(cmdline.args[0], + goto_model, get_message_handler())) + return true; + + config.set_from_symbol_table(goto_model.symbol_table); + + if(cmdline.isset("show-symbol-table")) + { + show_symbol_table(); + return true; + } + + irep_idt entry_point=goto_model.goto_functions.entry_point(); + + if(goto_model.symbol_table.symbols.find(entry_point)==symbol_table.symbols.end()) + { + error() << "The goto binary has no entry point; please complete linking" << eom; + return true; + } + } + else if(cmdline.isset("show-parse-tree")) + { + if(cmdline.args.size()!=1) + { + error() << "Please give one source file only" << eom; + return true; + } + + std::string filename=cmdline.args[0]; + + #ifdef _MSC_VER + std::ifstream infile(widen(filename).c_str()); + #else + std::ifstream infile(filename.c_str()); + #endif + + if(!infile) + { + error() << "failed to open input file `" << filename << "'" << eom; + return true; + } + + languaget *language=get_language_from_filename(filename); + + if(language==NULL) + { + error() << "failed to figure out type of file `" << filename << "'" << eom; + return true; + } + + language->set_message_handler(get_message_handler()); + + status("Parsing", filename); + + if(language->parse(infile, filename)) + { + error() << "PARSING ERROR" << eom; + return true; + } + + language->show_parse(std::cout); + return true; + } + else + { + + if(parse()) return true; + if(typecheck()) return true; + if(final()) return true; + + // we no longer need any parse trees or language files + clear_parse(); + + if(cmdline.isset("show-symbol-table")) + { + show_symbol_table(); + return true; + } + + irep_idt entry_point=goto_model.goto_functions.entry_point(); + + if(symbol_table.symbols.find(entry_point)==symbol_table.symbols.end()) + { + error() << "No entry point; please provide a main function" << eom; + return true; + } + + status() << "Generating GOTO Program" << eom; + + goto_convert(symbol_table, goto_model, ui_message_handler); + } + + // finally add the library + status() << "Adding CPROVER library" << eom; + link_to_library(goto_model, ui_message_handler); + + if(process_goto_program(options, goto_model)) + return true; + } + + catch(const char *e) + { + error() << e << eom; + return true; + } + + catch(const std::string e) + { + error() << e << eom; + return true; + } + + catch(int) + { + return true; + } + + catch(std::bad_alloc) + { + error() << "Out of memory" << eom; + return true; + } + + return false; +} + +/*******************************************************************\ + +Function: summarizer_parse_optionst::process_goto_program + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +bool summarizer_parse_optionst::process_goto_program( + const optionst &options, + goto_modelt &goto_model) +{ + try + { + // do partial inlining + if(options.get_bool_option("inline-partial")) + { + unsigned limit = options.get_unsigned_int_option("inline-partial"); + status() << "Performing partial inlining (" << limit << ")" << eom; + goto_partial_inline(goto_model, ui_message_handler, limit/2); + //TODO: where is limit multiplied by 2??? + + //remove inlined functions + Forall_goto_functions(f_it, goto_model.goto_functions) + if(f_it->first!=ID__start && + f_it->second.body.instructions.size()<=2*(limit/2)) + { + f_it->second.body.clear(); + } + } + + // add generic checks + status() << "Generic Property Instrumentation" << eom; + goto_check(options, goto_model); + + status() << "Function Pointer Removal" << eom; + remove_function_pointers( + goto_model, cmdline.isset("pointer-check")); + + // remove returns (must be done after function pointer removal) + remove_returns(goto_model); + + split_loopheads(goto_model); + + // recalculate numbers, etc. + goto_model.goto_functions.update(); + + // add loop ids + goto_model.goto_functions.compute_loop_numbers(); + + // if we aim to cover, replace + // all assertions by false to prevent simplification + if(cmdline.isset("cover-assertions")) + make_assertions_false(goto_model); + + // show it? + if(cmdline.isset("show-loops")) + { + show_loop_ids(get_ui(), goto_model); + return true; + } + +#if UNWIND_GOTO_INTO_LOOP + goto_unwind(goto_model,2); +#endif + + // now do full inlining, if requested + if(options.get_bool_option("inline")) + { + status() << "Performing full inlining" << eom; + goto_inline(goto_model, ui_message_handler); + } + + //inline __CPROVER_initialize and main + if(cmdline.isset("inline-main")) + { + inline_main(goto_model); + } + + if(!cmdline.isset("no-propagation")) + { + status() << "Constant Propagation" << eom; + propagate_constants(goto_model); + } + + //explicitly initialize all local variables + nondet_locals(goto_model); + +#if 1 + //TODO: find a better place for that + replace_malloc(goto_model,""); +#endif + +#if REMOVE_MULTIPLE_DEREFERENCES + remove_multiple_dereferences(goto_model); +#endif + + // do array abstraction + if(cmdline.isset("array-abstraction")) + { + status() << "Performing array abstraction" << eom; + array_abstraction(goto_model.symbol_table, ui_message_handler, + goto_model.goto_functions); + } + + label_properties(goto_model); + + if(cmdline.isset("show-properties")) + { + show_properties(goto_model, get_ui()); + return true; + } + + if(set_properties(goto_model)) + return true; + + // show it? + if(cmdline.isset("show-goto-functions")) + { + const namespacet ns(goto_model.symbol_table); + goto_model.goto_functions.output(ns, std::cout); + return true; + } + } + + catch(const char *e) + { + error() << e << eom; + return true; + } + + catch(const std::string e) + { + error() << e << eom; + return true; + } + + catch(int) + { + return true; + } + + catch(std::bad_alloc) + { + error() << "Out of memory" << eom; + return true; + } + + return false; +} + +/*******************************************************************\ + +Function: summarizer_parse_optionst::report_properties + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +void summarizer_parse_optionst::report_properties( + const goto_modelt &goto_model, + const property_checkert::property_mapt &property_map) +{ + for(property_checkert::property_mapt::const_iterator + it=property_map.begin(); + it!=property_map.end(); + it++) + { + if(it->first=="") //TODO: some properties do not show up in initialize_property_map + continue; + + if(get_ui()==ui_message_handlert::XML_UI) + { + xmlt xml_result("result"); + xml_result.set_attribute("property", id2string(it->first)); + xml_result.set_attribute("status", property_checkert::as_string(it->second.result)); + std::cout << xml_result << "\n"; + } + else + { + status() << "[" << it->first << "] " + << it->second.location->source_location.get_comment() + << ": " + << property_checkert::as_string(it->second.result) + << eom; + } + + if(cmdline.isset("show-trace") && + it->second.result==property_checkert::FAIL) + show_counterexample(goto_model, it->second.error_trace); + } + + if(!cmdline.isset("property")) + { + status() << eom; + + unsigned failed=0; + unsigned unknown=0; + + for(property_checkert::property_mapt::const_iterator + it=property_map.begin(); + it!=property_map.end(); + it++) + { + if(it->second.result==property_checkert::UNKNOWN) + unknown++; + if(it->second.result==property_checkert::FAIL) + failed++; + } + + status() << "** " << unknown + << " of " << property_map.size() << " unknown" + << eom; + status() << "** " << failed + << " of " << property_map.size() << " failed" + << eom; + } +} + +/*******************************************************************\ + +Function: summarizer_parse_optionst::report_success + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +void summarizer_parse_optionst::report_success() +{ + result() << "VERIFICATION SUCCESSFUL" << eom; + + switch(get_ui()) + { + case ui_message_handlert::PLAIN: + break; + + case ui_message_handlert::XML_UI: + { + xmlt xml("cprover-status"); + xml.data="SUCCESS"; + std::cout << xml; + std::cout << std::endl; + } + break; + + default: + assert(false); + } +} + +/*******************************************************************\ + +Function: summarizer_parse_optionst::show_counterexample + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +void summarizer_parse_optionst::show_counterexample( + const goto_modelt &goto_model, + const goto_tracet &error_trace) +{ + const namespacet ns(goto_model.symbol_table); + + switch(get_ui()) + { + case ui_message_handlert::PLAIN: + std::cout << std::endl << "Counterexample:" << std::endl; + show_goto_trace(std::cout, ns, error_trace); + break; + + case ui_message_handlert::XML_UI: + { + xmlt xml; + convert(ns, error_trace, xml); + std::cout << xml << std::endl; + } + break; + + default: + assert(false); + } +} + +/*******************************************************************\ + +Function: summarizer_parse_optionst::report_failure + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +void summarizer_parse_optionst::report_failure() +{ + result() << "VERIFICATION FAILED" << eom; + + switch(get_ui()) + { + case ui_message_handlert::PLAIN: + break; + + case ui_message_handlert::XML_UI: + { + xmlt xml("cprover-status"); + xml.data="FAILURE"; + std::cout << xml; + std::cout << std::endl; + } + break; + + default: + assert(false); + } +} + +/*******************************************************************\ + +Function: summarizer_parse_optionst::report_unknown + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +void summarizer_parse_optionst::report_unknown() +{ + result() << "VERIFICATION INCONCLUSIVE" << eom; + + switch(get_ui()) + { + case ui_message_handlert::PLAIN: + break; + + case ui_message_handlert::XML_UI: + { + xmlt xml("cprover-status"); + xml.data="UNKNOWN"; + std::cout << xml; + std::cout << std::endl; + } + break; + + default: + assert(false); + } +} + +/*******************************************************************\ + +Function: summarizer_parse_optionst::help + + Inputs: + + Outputs: + + Purpose: display command line help + +\*******************************************************************/ + +void summarizer_parse_optionst::help() +{ + std::cout << + "\n" + "* * Summarizer " SUMMARIZER_VERSION " - Copyright (C) 2014 * *\n" + "* * (based on CBMC " CBMC_VERSION " "; + + std::cout << "(" << (sizeof(void *)*8) << "-bit version))"; + + std::cout << " * *\n"; + + std::cout << + "* * Daniel Kroening * *\n" + "* * University of Oxford * *\n" + "* * kroening@kroening.com * *\n" + "\n" + "Usage: Purpose:\n" + "\n" + " summarizer [-?] [-h] [--help] show help\n" + " summarizer file.c ... source file names\n" + "\n" + "Frontend options:\n" + " -I path set include path (C/C++)\n" + " -D macro define preprocessor macro (C/C++)\n" + " --preprocess stop after preprocessing\n" + " --16, --32, --64 set width of int\n" + " --LP64, --ILP64, --LLP64,\n" + " --ILP32, --LP32 set width of int, long and pointers\n" + " --little-endian allow little-endian word-byte conversions\n" + " --big-endian allow big-endian word-byte conversions\n" + " --unsigned-char make \"char\" unsigned by default\n" + " --show-stats show statistics about program\n" + " --show-parse-tree show parse tree\n" + " --show-symbol-table show symbol table\n" + " --show-goto-functions show goto program\n" + " --arch set architecture (default: " + << configt::this_architecture() << ")\n" + " --os set operating system (default: " + << configt::this_operating_system() << ")\n" + #ifdef _WIN32 + " --gcc use GCC as preprocessor\n" + #endif + " --no-arch don't set up an architecture\n" + " --no-library disable built-in abstract C library\n" + " --round-to-nearest IEEE floating point rounding mode (default)\n" + " --round-to-plus-inf IEEE floating point rounding mode\n" + " --round-to-minus-inf IEEE floating point rounding mode\n" + " --round-to-zero IEEE floating point rounding mode\n" + "\n" + "Program instrumentation options:\n" + " --bounds-check enable array bounds checks\n" + " --pointer-check enable pointer checks\n" + " --array-abstraction use array and string abstraction for bounds checks\n" + " --div-by-zero-check enable division by zero checks\n" + " --memory-leak-check enable memory leak checks\n" + " --signed-overflow-check enable arithmetic over- and underflow checks\n" + " --unsigned-overflow-check enable arithmetic over- and underflow checks\n" + " --nan-check check floating-point for NaN\n" + " --error-label label check that label is unreachable\n" + " --show-properties show the properties\n" + " --no-assertions ignore user assertions\n" + " --no-assumptions ignore user assumptions\n" + " --inline inline all functions into main\n" + " --inline-partial nr inline functions smaller than the given nr of instructions\n" + " --instrument-output f output inferred information in goto-binary f\n" + "\n" + "Backend options:\n" + " --k-induction use k-induction\n" + " --unit-check check each function (similar to a unit test)\n" + " --incremental-bmc use incremental-bmc\n" + " --preconditions compute preconditions\n" + " --sufficient sufficient preconditions (default: necessary)\n" + " --context-sensitive context-sensitive analysis from entry point\n" + " --havoc havoc loops and function calls\n" + " --intervals use interval domain\n" + " --equalities use equalities and disequalities domain\n" + " --zones use zone domain\n" + " --octagons use octagon domain\n" + " --enum-solver use solver based on model enumeration\n" + " --binsearch-solver use solver based on binary search\n" + " --arrays do not ignore array contents\n" + "\n" + "Other options:\n" + " --version show version and exit\n" + " --xml-ui use XML-formatted output\n" + "\n"; +} diff --git a/src/summarizer/summarizer_parse_options.h b/src/summarizer/summarizer_parse_options.h new file mode 100644 index 000000000..542817efa --- /dev/null +++ b/src/summarizer/summarizer_parse_options.h @@ -0,0 +1,142 @@ +/*******************************************************************\ + +Module: Command Line Parsing + +Author: Daniel Kroening, kroening@kroening.com + +\*******************************************************************/ + +#ifndef CPROVER_SUMMARIZER_PARSE_OPTIONS_H +#define CPROVER_SUMMARIZER_PARSE_OPTIONS_H + +#include +#include + +#include + +#include + +class goto_modelt; +class optionst; + +#include "summary_checker_base.h" + +#define SUMMARIZER_OPTIONS \ + "(xml-ui)" \ + "(function):" \ + "D:I:" \ + "(depth):(context-bound):(unwind):" \ + "(bounds-check)(pointer-check)(div-by-zero-check)(memory-leak-check)" \ + "(signed-overflow-check)(unsigned-overflow-check)" \ + "(float-overflow-check)(nan-check)" \ + "(array-abstraction)(refine)" \ + "(non-incremental)" \ + "(no-assertions)(no-assumptions)" \ + "(16)(32)(64)(LP64)(ILP64)(LLP64)(ILP32)(LP32)" \ + "(little-endian)(big-endian)" \ + "(error-label):(verbosity):(no-library)" \ + "(version)" \ + "(i386-linux)(i386-macos)(i386-win32)(win32)(winx64)(gcc)" \ + "(ppc-macos)(unsigned-char)" \ + "(havoc)(intervals)(zones)(octagons)(equalities)(qzones)"\ + "(enum-solver)(binsearch-solver)(arrays)"\ + "(string-abstraction)(no-arch)(arch):(floatbv)(fixedbv)" \ + "(round-to-nearest)(round-to-plus-inf)(round-to-minus-inf)(round-to-zero)" \ + "(inline)(inline-main)(inline-partial):" \ + "(context-sensitive)" \ + "(preconditions)(sufficient)" \ + "(instrument-output):" \ + "(show-locs)(show-vcc)(show-properties)(show-trace)(show-fixed-points)(show-stats)" \ + "(show-goto-functions)(show-guards)(show-defs)(show-ssa)(show-assignments)(show-dep-graphs)" \ + "(show-value-sets)" \ + "(show-invariants)(std-invariants)" \ + "(show-calling-contexts):" \ + "(property):(all-properties)(k-induction)(incremental-bmc)" \ + "(no-simplify)(no-fixed-point)" \ + "(no-spurious-check)(no-all-properties)(unit-check)" \ + "(spurious-check):" \ + "(competition-mode)(slice)" \ + "(no-unwinding-assertions)(no-propagation)(ssa-propagation)" + // the last line is for CBMC-regression testing only + +class summarizer_parse_optionst: + public parse_options_baset, + public language_uit +{ +public: + virtual int doit(); + virtual void help(); + + summarizer_parse_optionst(int argc, const char **argv); + summarizer_parse_optionst( + int argc, + const char **argv, + const std::string &extra_options); + +protected: + void get_command_line_options(optionst &options); + + bool get_goto_program( + const optionst &options, + goto_modelt &goto_model); + + bool process_goto_program( + const optionst &options, + goto_modelt &goto_model); + + bool set_properties(goto_modelt &); + + void report_success(); + void report_failure(); + + void report_properties( + const goto_modelt &, + const summary_checker_baset::property_mapt &); + + void show_counterexample( + const goto_modelt &, + const class goto_tracet &); + + struct expr_statst { + bool has_malloc; + bool has_string; + bool has_array; + bool has_pointer; + + expr_statst() + : has_malloc(false) + , has_string(false) + , has_array(false) + , has_pointer(false) + {} + }; + + void type_stats_rec( + const typet &type, + expr_statst &stats, + const namespacet &ns); + + void expr_stats_rec( + const exprt &expr, + expr_statst &stats); + + void show_stats( + const goto_modelt &, + std::ostream &); + + void eval_verbosity(); + void report_unknown(); + + // diverse preprocessing + void inline_main(goto_modelt &goto_model); + void propagate_constants(goto_modelt &goto_model); + void nondet_locals(goto_modelt &goto_model); + void goto_unwind(goto_modelt &goto_model, unsigned k); + void replace_types_rec(const replace_symbolt &replace_const, exprt &expr); + exprt evaluate_casts_in_constants(const exprt &expr, const typet& parent_type, + bool &valid); + void remove_multiple_dereferences(goto_modelt &goto_model); + void remove_multiple_dereferences(goto_modelt &goto_model, goto_programt &body, goto_programt::targett t, exprt &expr, unsigned &var_counter, bool deref_seen); +}; + +#endif diff --git a/src/summarizer/summary_checker_ai.cpp b/src/summarizer/summary_checker_ai.cpp new file mode 100644 index 000000000..06d077777 --- /dev/null +++ b/src/summarizer/summary_checker_ai.cpp @@ -0,0 +1,145 @@ +/*******************************************************************\ + +Module: Summary Checker for AI + +Author: Peter Schrammel + +\*******************************************************************/ + +#include + +#include "summary_checker_ai.h" + +/*******************************************************************\ + +Function: summary_checker_ait::operator() + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +property_checkert::resultt summary_checker_ait::operator()( + const goto_modelt &goto_model) +{ + const namespacet ns(goto_model.symbol_table); + + SSA_functions(goto_model,ns); + + ssa_unwinder.init(false,false); + + unsigned unwind = options.get_unsigned_int_option("unwind"); + if(unwind>0) + { + status() << "Unwinding" << messaget::eom; + + ssa_unwinder.init_localunwinders(); + + ssa_unwinder.unwind_all(unwind+1); + ssa_unwinder.output(debug()); debug() <second.body_available()) continue; + if(has_prefix(id2string(f_it->first),TEMPLATE_DECL)) continue; + + status() << "Computing dependency graph of " << f_it->first << messaget::eom; + + //ssa_db.depgraph_create(f_it->first, ns, ssa_inliner); + + if(entry_function == f_it->first) + ssa_db.depgraph_create(f_it->first, ns, ssa_inliner, true); + else + ssa_db.depgraph_create(f_it->first, ns, ssa_inliner, false); // change to true if all functions are to be treated equal + + ssa_dependency_grapht &ssa_depgraph = ssa_db.get_depgraph(f_it->first); + ssa_depgraph.output(debug()); debug() << eom; + std::cout << "output SSA for function: " << f_it->first << "\n"; + ssa_db.get(f_it->first).output_verbose(std::cout); + } + } + } + + // properties + initialize_property_map(goto_model.goto_functions); + + bool preconditions = options.get_bool_option("preconditions"); + if(!options.get_bool_option("havoc")) + { + //forward analysis + summarize(goto_model,true,false); + } + if(!options.get_bool_option("havoc") && preconditions) + { + //backward analysis + summarize(goto_model,false,false); + } + + if(preconditions) + { + report_statistics(); + report_preconditions(); + return property_checkert::UNKNOWN; + } + +#ifdef SHOW_CALLINGCONTEXTS + if(options.get_bool_option("show-calling-contexts")) + return property_checkert::UNKNOWN; +#endif + +/* + irep_idt entry_function = goto_model.goto_functions.entry_point(); + if(options.get_bool_option("unit-check")) + entry_function = ""; +*/ + + std::set seen_function_calls; + property_checkert::resultt result = check_properties(entry_function, entry_function, seen_function_calls); + report_statistics(); + return result; +} + + +/*******************************************************************\ + +Function: summary_checker_ait::report_preconditions + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +void summary_checker_ait::report_preconditions() +{ + result() << eom; + result() << "** " << (options.get_bool_option("sufficient") ? + "Sufficient" : "Necessary") + << " preconditions: " << eom; + ssa_dbt::functionst &functions = ssa_db.functions(); + for(ssa_dbt::functionst::iterator it = functions.begin(); + it != functions.end(); it++) + { + exprt precondition; + bool computed = summary_db.exists(it->first); + if(computed) precondition = summary_db.get(it->first).bw_precondition; + if(precondition.is_nil()) computed = false; + result() << eom << "[" << it->first << "]: " + << (!computed ? "not computed" : + from_expr(it->second->ns, "", precondition)) << eom; + } +} diff --git a/src/summarizer/summary_checker_ai.h b/src/summarizer/summary_checker_ai.h new file mode 100644 index 000000000..edde3fe34 --- /dev/null +++ b/src/summarizer/summary_checker_ai.h @@ -0,0 +1,29 @@ +/*******************************************************************\ + +Module: Summary Checker for AI + +Author: Peter Schrammel + +\*******************************************************************/ + +#ifndef CPROVER_SUMMARY_CHECKER_AI_H +#define CPROVER_SUMMARY_CHECKER_AI_H + +#include "summary_checker_base.h" + +class summary_checker_ait:public summary_checker_baset +{ +public: + inline summary_checker_ait(optionst &_options): + summary_checker_baset(_options) + { + } + + virtual resultt operator()(const goto_modelt &); + +protected: + void report_preconditions(); + +}; + +#endif diff --git a/src/summarizer/summary_checker_base.cpp b/src/summarizer/summary_checker_base.cpp new file mode 100644 index 000000000..256227f6c --- /dev/null +++ b/src/summarizer/summary_checker_base.cpp @@ -0,0 +1,684 @@ +/*******************************************************************\ + +Module: Summarizer Checker Base + +Author: Peter Schrammel + +\*******************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "../ssa/local_ssa.h" +#include "../ssa/simplify_ssa.h" +#include "../ssa/ssa_build_goto_trace.h" +#include "../domains/ssa_analyzer.h" +#include "../ssa/ssa_unwinder.h" +#include "../ssa/ssa_const_propagator.h" +#include + +#include "show.h" +#include "instrument_goto.h" + +#include "summary_checker_base.h" +#include "summarizer_bw_cex.h" +#include "summarizer_bw_cex_concrete.h" +#include "summarizer_bw_cex_ai.h" +#include "summarizer_bw_cex_complete.h" +#include "summarizer_bw_cex_wp.h" +#include "summarizer_bw_cex_all.h" + +#include "summarizer_fw.h" +#include "summarizer_bw.h" + +#ifdef SHOW_CALLING_CONTEXTS +#include "summarizer_fw_contexts.h" +#endif + +/*******************************************************************\ + +Function: summary_checker_baset::SSA_functions + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +void summary_checker_baset::SSA_functions(const goto_modelt &goto_model, const namespacet &ns) +{ + entry_function = goto_model.goto_functions.entry_point(); + + // compute SSA for all the functions + forall_goto_functions(f_it, goto_model.goto_functions) + { + if(!f_it->second.body_available()) continue; + if(has_prefix(id2string(f_it->first),TEMPLATE_DECL)) continue; + status() << "Computing SSA of " << f_it->first << messaget::eom; + + ssa_db.create(f_it->first, f_it->second, ns); + local_SSAt &SSA = ssa_db.get(f_it->first); + + // simplify, if requested + if(simplify) + { + status() << "Simplifying" << messaget::eom; + ::simplify(SSA, ns); + } + + //SSA.output_verbose(std::cout); + + //SSA.output(debug()); debug() << eom; + } + + // properties + initialize_property_map(goto_model.goto_functions); +} + +/*******************************************************************\ + +Function: summary_checker_baset::summarize + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +void summary_checker_baset::summarize(const goto_modelt &goto_model, + bool forward, + bool termination) +{ + summarizer_baset *summarizer = NULL; + +#ifdef SHOW_CALLING_CONTEXTS + if(options.get_bool_option("show-calling-contexts")) + summarizer = new summarizer_fw_contextst( + options,summary_db,ssa_db,ssa_unwinder,ssa_inliner); + else +#endif + { + if(forward && !termination) + summarizer = new summarizer_fwt( + options,summary_db,ssa_db,ssa_unwinder,ssa_inliner); + if(!forward && !termination) + summarizer = new summarizer_bwt( + options,summary_db,ssa_db,ssa_unwinder,ssa_inliner); + } + assert(summarizer != NULL); + + summarizer->set_message_handler(get_message_handler()); + + if(!options.get_bool_option("context-sensitive")) + summarizer->summarize(); + else + summarizer->summarize(entry_function); + + //statistics + solver_instances += summarizer->get_number_of_solver_instances(); + solver_calls += summarizer->get_number_of_solver_calls(); + summaries_used += summarizer->get_number_of_summaries_used(); + + delete summarizer; +} + +/*******************************************************************\ + +Function: summary_checker_baset::check_properties + + Inputs: function_name != nil + checks all functions in the call graph from the entry point + else + checks all functions + + Outputs: + + Purpose: + +\*******************************************************************/ +summary_checker_baset::resultt summary_checker_baset::check_properties() +{ + std::set seen_function_calls; + return check_properties("", "", seen_function_calls); +} + +summary_checker_baset::resultt summary_checker_baset::check_properties( + irep_idt function_name, irep_idt entry_function, std::set seen_function_calls) +{ + if(function_name!="") + { + ssa_dbt::functionst::const_iterator f_it = + ssa_db.functions().find(function_name); + local_SSAt &SSA = *f_it->second; + + // call recursively for all function calls first + for(local_SSAt::nodest::const_iterator n_it = SSA.nodes.begin(); + n_it != SSA.nodes.end(); ++n_it) + { + for(local_SSAt::nodet::function_callst::const_iterator ff_it = + n_it->function_calls.begin(); + ff_it != n_it->function_calls.end(); ff_it++) + { + assert(ff_it->function().id()==ID_symbol); //no function pointers + irep_idt fname = to_symbol_expr(ff_it->function()).get_identifier(); + //ENHANCE?: can the return value be exploited? + + if(!summary_db.exists(fname) || + summary_db.get(fname).bw_transformer.is_nil()) + { +#if 0 + debug() << "Checking call " << fname << messaget::eom; +#endif + if(seen_function_calls.find(fname) == seen_function_calls.end()){ + seen_function_calls.insert(fname); + check_properties(fname, entry_function, seen_function_calls); + } + } + } + } + + //now check function itself + status() << "Checking properties of " << f_it->first << messaget::eom; + check_properties(f_it, entry_function); + } + else // check all the functions + { + for(ssa_dbt::functionst::const_iterator f_it = ssa_db.functions().begin(); + f_it != ssa_db.functions().end(); f_it++) + { + status() << "Checking properties of " << f_it->first << messaget::eom; + +#if 0 + //for debugging + show_ssa_symbols(*f_it->second,std::cerr); +#endif + + check_properties(f_it); + + if(options.get_bool_option("show-invariants")) + { + if(!summary_db.exists(f_it->first)) continue; + show_invariants(*(f_it->second),summary_db.get(f_it->first),result()); + result() << eom; + } + } + } + + summary_checker_baset::resultt result = property_checkert::PASS; + if(function_name=="" || function_name==entry_function) + { + // determine overall status + for(property_mapt::const_iterator + p_it=property_map.begin(); p_it!=property_map.end(); p_it++) + { + if(p_it->second.result==FAIL) + return property_checkert::FAIL; + if(p_it->second.result==UNKNOWN) + result = property_checkert::UNKNOWN; + } + } + + return result; +} + +/*******************************************************************\ + +Function: summary_checker_baset::check_properties + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +void summary_checker_baset::check_properties( + const ssa_dbt::functionst::const_iterator f_it, + irep_idt entry_function) +{ + local_SSAt &SSA = *f_it->second; + if(!SSA.goto_function.body.has_assertion()) return; + + bool all_properties = options.get_bool_option("all-properties"); + + SSA.output(debug()); debug() << eom; + + // incremental version + + // solver + incremental_solvert &solver = ssa_db.get_solver(f_it->first); + solver.set_message_handler(get_message_handler()); + +#if 1 + // TEST ssa_const_propagation + if(options.get_bool_option("ssa-propagation")) + { + ssa_const_propagatort ssa_const_propagator; + std::list c; + ssa_const_propagator(c,SSA); + solver << c; + debug() << "SSA const propagation: " << eom; + for(std::list::iterator it = c.begin(); + it!=c.end(); it++) + debug() << " " << from_expr(SSA.ns,"",*it) << eom; + } +#endif + + // give SSA to solver + solver << SSA; + SSA.mark_nodes(); + + + solver.new_context(); + + exprt enabling_expr = SSA.get_enabling_exprs(); + solver << enabling_expr; + + // invariant, calling contexts + if(summary_db.exists(f_it->first)) + { + const summaryt &summary = summary_db.get(f_it->first); + if(!summary.fw_invariant.is_nil()) + solver << summary.fw_invariant; + if(!summary.fw_precondition.is_nil()) + solver << summary.fw_precondition; + } + + + //callee summaries + solver << ssa_inliner.get_summaries(SSA); + + //freeze loop head selects + exprt::operandst loophead_selects = + summarizer_baset::get_loophead_selects(SSA,ssa_unwinder.get(f_it->first),*solver.solver); + //check whether loops have been fully unwound + exprt::operandst loop_continues = + get_loop_continues(f_it->first,SSA,*solver.solver); + bool fully_unwound = + is_fully_unwound(loop_continues,loophead_selects,solver); + status() << "Loops " << (fully_unwound ? "" : "not ") + << "fully unwound" << eom; + + + //spuriousness checkers + summarizer_bw_cex_baset *summarizer_bw_cex = NULL; + incremental_solvert* cex_complete_solver = + incremental_solvert::allocate(SSA.ns, + options.get_bool_option("refine")); + if(options.get_option("spurious-check") == "concrete") + { + summarizer_bw_cex = new summarizer_bw_cex_concretet( + options,summary_db,ssa_db, + ssa_unwinder,ssa_inliner, + entry_function,f_it->first); + } + if(options.get_option("spurious-check") == "abstract") + { + summarizer_bw_cex = new summarizer_bw_cex_ait( + options,summary_db,ssa_db, + ssa_unwinder,ssa_inliner, + entry_function,f_it->first); + } + else if(options.get_option("spurious-check") == "complete") + { + summarizer_bw_cex = new summarizer_bw_cex_completet( + options,summary_db,ssa_db, + ssa_unwinder,ssa_inliner,*cex_complete_solver, + entry_function,f_it->first); + } + else if(options.get_option("spurious-check") == "wp") + { + summarizer_bw_cex = new summarizer_bw_cex_wpt( + options,summary_db,ssa_db, + ssa_unwinder,ssa_inliner,*cex_complete_solver, + entry_function,f_it->first); + } + else if(options.get_option("spurious-check") == "all") + { + summarizer_bw_cex = new summarizer_bw_cex_allt( + options,summary_db,ssa_db, + ssa_unwinder,ssa_inliner,*cex_complete_solver, + entry_function,f_it->first); + } + assert(summarizer_bw_cex != NULL); + summarizer_bw_cex->set_message_handler(get_message_handler()); + + cover_goals_extt cover_goals( + solver,loophead_selects,property_map, + f_it->first!=entry_function || !fully_unwound, + all_properties, + *summarizer_bw_cex); + +#if 0 + debug() << "(C) " << from_expr(SSA.ns,"",enabling_expr) << eom; +#endif + + const goto_programt &goto_program=SSA.goto_function.body; + + for(goto_programt::instructionst::const_iterator + i_it=goto_program.instructions.begin(); + i_it!=goto_program.instructions.end(); + i_it++) + { + if(!i_it->is_assert()) + continue; + + const source_locationt &location=i_it->source_location; + std::list assertion_nodes; + SSA.find_nodes(i_it,assertion_nodes); + + irep_idt property_id = location.get_property_id(); + + //do not recheck properties that have already been decided + if(property_map[property_id].result!=UNKNOWN) continue; + + if(property_id=="") //TODO: some properties do not show up in initialize_property_map + continue; + + unsigned property_counter = 0; + for(std::list::const_iterator + n_it=assertion_nodes.begin(); + n_it!=assertion_nodes.end(); + n_it++) + { + for(local_SSAt::nodet::assertionst::const_iterator + a_it=(*n_it)->assertions.begin(); + a_it!=(*n_it)->assertions.end(); + a_it++, property_counter++) + { + exprt property=*a_it; + + if(simplify) + property=::simplify_expr(property, SSA.ns); + +#if 0 + std::cout << "property: " << from_expr(SSA.ns, "", property) << std::endl; +#endif + + property_map[property_id].location = i_it; + cover_goals.goal_map[property_id].conjuncts.push_back(property); + } + } + } + + + for(cover_goals_extt::goal_mapt::const_iterator + it=cover_goals.goal_map.begin(); + it!=cover_goals.goal_map.end(); + it++) + { + // Our goal is to falsify a property. + // The following is TRUE if the conjunction is empty. + //literalt p=!solver.convert(conjunction(it->second.conjuncts)); + //cover_goals.add(p); + cover_goals.add(not_exprt(conjunction(it->second.conjuncts))); + } + + status() << "Running " << solver.solver->decision_procedure_text() << eom; + + cover_goals(); + /* + std::cout << "Output Verbose: " << entry_function << "\n"; + (ssa_db.get(entry_function)).output_verbose(std::cout); + assert(false); + */ + //set all non-covered goals to PASS except if we do not try + // to cover all goals and we have found a FAIL + if(all_properties || cover_goals.number_covered()==0) + { + std::list::const_iterator g_it= + cover_goals.goals.begin(); + for(cover_goals_extt::goal_mapt::const_iterator + it=cover_goals.goal_map.begin(); + it!=cover_goals.goal_map.end(); + it++, g_it++) + { + if(!g_it->covered) property_map[it->first].result=PASS; + } + } + + solver.pop_context(); + + debug() << "** " << cover_goals.number_covered() + << " of " << cover_goals.size() << " failed (" + << cover_goals.iterations() << " iterations)" << eom; + + delete summarizer_bw_cex; + delete cex_complete_solver; +} + +/*******************************************************************\ + +Function: summary_checker_baset::report_statistics() + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +void summary_checker_baset::report_statistics() +{ + for(ssa_dbt::functionst::const_iterator f_it = ssa_db.functions().begin(); + f_it != ssa_db.functions().end(); f_it++) + { + incremental_solvert &solver = ssa_db.get_solver(f_it->first); + unsigned calls = solver.get_number_of_solver_calls(); + if(calls>0) solver_instances++; + solver_calls += calls; + } + statistics() << "** statistics: " << eom; + statistics() << " number of solver instances: " << solver_instances << eom; + statistics() << " number of solver calls: " << solver_calls << eom; + statistics() << " number of summaries used: " + << summaries_used << eom; + statistics() << eom; +} + +/*******************************************************************\ + +Function: summary_checker_baset::do_show_vcc + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +void summary_checker_baset::do_show_vcc( + const local_SSAt &SSA, + const goto_programt::const_targett i_it, + const local_SSAt::nodet::assertionst::const_iterator &a_it) +{ + std::cout << i_it->source_location << "\n"; + std::cout << i_it->source_location.get_comment() << "\n"; + + std::list ssa_constraints; + ssa_constraints << SSA; + + unsigned i=1; + for(std::list::const_iterator c_it=ssa_constraints.begin(); + c_it!=ssa_constraints.end(); + c_it++, i++) + std::cout << "{-" << i << "} " << from_expr(SSA.ns, "", *c_it) << "\n"; + + std::cout << "|--------------------------\n"; + + std::cout << "{1} " << from_expr(SSA.ns, "", *a_it) << "\n"; + + std::cout << "\n"; +} + +/*******************************************************************\ + +Function: summary_checker_baset::get_loop_continues + + Inputs: + + Outputs: + + Purpose: returns the loop continuation guards at the end of the + loops in order to check whether we can unroll further + +\*******************************************************************/ + +exprt::operandst summary_checker_baset::get_loop_continues( + const irep_idt &function_name, + const local_SSAt &SSA, prop_convt &solver) +{ + exprt::operandst loop_continues; + + ssa_unwinder.get(function_name).loop_continuation_conditions(loop_continues); + if(loop_continues.size()==0) + { + //TODO: this should actually be done transparently by the unwinder + for(local_SSAt::nodest::const_iterator n_it = SSA.nodes.begin(); + n_it != SSA.nodes.end(); n_it++) + { + if(n_it->loophead==SSA.nodes.end()) continue; + symbol_exprt guard = SSA.guard_symbol(n_it->location); + symbol_exprt cond = SSA.cond_symbol(n_it->location); + loop_continues.push_back(and_exprt(guard,cond)); + } + } + +#if 0 + std::cout << "loophead_continues: " << from_expr(SSA.ns,"",disjunction(loop_continues)) << std::endl; +#endif + + return loop_continues; +} + +/*******************************************************************\ + +Function: summary_checker_baset::is_fully_unwound + + Inputs: + + Outputs: + + Purpose: checks whether the loops have been fully unwound + +\*******************************************************************/ + +bool summary_checker_baset::is_fully_unwound( + const exprt::operandst &loop_continues, + const exprt::operandst &loophead_selects, + incremental_solvert &solver) +{ + solver.new_context(); + solver << and_exprt(conjunction(loophead_selects), + disjunction(loop_continues)); + + solver_calls++; //statistics + + switch(solver()) + { + case decision_proceduret::D_SATISFIABLE: + solver.pop_context(); + return false; + break; + + case decision_proceduret::D_UNSATISFIABLE: + solver.pop_context(); + solver << conjunction(loophead_selects); + return true; + break; + + case decision_proceduret::D_ERROR: + default: + throw "error from decision procedure"; + } +} + +/*******************************************************************\ + +Function: summary_checker_baset::is_spurious + + Inputs: + + Outputs: + + Purpose: checks whether a countermodel is spurious + +\*******************************************************************/ + +bool summary_checker_baset::is_spurious(const exprt::operandst &loophead_selects, + incremental_solvert &solver) +{ + //check loop head choices in model + bool invariants_involved = false; + for(exprt::operandst::const_iterator l_it = loophead_selects.begin(); + l_it != loophead_selects.end(); l_it++) + { + if(solver.get(l_it->op0()).is_true()) + { + invariants_involved = true; + break; + } + } + if(!invariants_involved) return false; + + // force avoiding paths going through invariants + solver << conjunction(loophead_selects); + + solver_calls++; //statistics + + switch(solver()) + { + case decision_proceduret::D_SATISFIABLE: + return false; + break; + + case decision_proceduret::D_UNSATISFIABLE: + return true; + break; + + case decision_proceduret::D_ERROR: + default: + throw "error from decision procedure"; + } +} + +/*******************************************************************\ + +Function: summary_checker_baset::instrument_and_output + + Inputs: + + Outputs: + + Purpose: instruments the code with the inferred information + and outputs it to a goto-binary + +\*******************************************************************/ + +void summary_checker_baset::instrument_and_output(goto_modelt &goto_model) +{ + instrument_gotot instrument_goto(options,ssa_db,summary_db); + instrument_goto(goto_model); + std::string filename = options.get_option("instrument-output"); + status() << "Writing instrumented goto-binary " << filename << eom; + write_goto_binary(filename, + goto_model.symbol_table, + goto_model.goto_functions, get_message_handler()); +} diff --git a/src/summarizer/summary_checker_base.h b/src/summarizer/summary_checker_base.h new file mode 100644 index 000000000..d2419b7ec --- /dev/null +++ b/src/summarizer/summary_checker_base.h @@ -0,0 +1,102 @@ +/*******************************************************************\ + +Module: Summary Checker Base + +Author: Peter Schrammel + +\*******************************************************************/ + +#ifndef CPROVER_SUMMARY_CHECKER_BASE_H +#define CPROVER_SUMMARY_CHECKER_BASE_H + +#include + +#include +#include + +#include "cover_goals_ext.h" +#include "../ssa/local_ssa.h" +#include "../ssa/ssa_unwinder.h" +#include "../ssa/ssa_inliner.h" +#include "../domains/incremental_solver.h" +#include "ssa_db.h" +#include "summary_db.h" + +class summary_checker_baset:public property_checkert +{ +public: + inline summary_checker_baset(optionst &_options): + show_vcc(false), + simplify(false), + fixed_point(false), + options(_options), + ssa_db(_options),summary_db(), + ssa_unwinder(ssa_db), + ssa_inliner(summary_db), + solver_instances(0), + solver_calls(0), + summaries_used(0) + { + ssa_inliner.set_message_handler(get_message_handler()); + } + + bool show_vcc, simplify, fixed_point; + irep_idt function_to_check; + + virtual resultt operator()(const goto_modelt &) { assert(false); } + + void instrument_and_output(goto_modelt &goto_model); + + // statistics + absolute_timet start_time; + time_periodt sat_time; + +protected: + optionst &options; + + ssa_dbt ssa_db; + summary_dbt summary_db; + ssa_unwindert ssa_unwinder; + ssa_inlinert ssa_inliner; + + irep_idt entry_function; + + unsigned solver_instances; + unsigned solver_calls; + unsigned summaries_used; + void report_statistics(); + + void do_show_vcc( + const local_SSAt &, + const goto_programt::const_targett, + const local_SSAt::nodet::assertionst::const_iterator &); + + void SSA_functions(const goto_modelt &, const namespacet &ns); + + void summarize(const goto_modelt &, + bool forward=true, bool termination=false); + + property_checkert::resultt check_properties(); + property_checkert::resultt check_properties( + irep_idt function_name, + irep_idt entry_function, + std::set seen_function_calls); + void check_properties( + const ssa_dbt::functionst::const_iterator f_it, + irep_idt entry_function=""); + + void error_summary_using_vars(const ssa_dbt::functionst::const_iterator f_it); + + exprt::operandst get_loophead_selects( + const irep_idt &function_name, const local_SSAt &, prop_convt &); + bool is_spurious(const exprt::operandst& loophead_selects, + incremental_solvert&); + exprt::operandst get_loop_continues( + const irep_idt &function_name, const local_SSAt &, prop_convt &); + bool is_fully_unwound( + const exprt::operandst& loop_continues, + const exprt::operandst& loophead_selects, + incremental_solvert&); +}; + +#endif diff --git a/src/summarizer/summary_checker_bmc.cpp b/src/summarizer/summary_checker_bmc.cpp new file mode 100644 index 000000000..c3649d534 --- /dev/null +++ b/src/summarizer/summary_checker_bmc.cpp @@ -0,0 +1,63 @@ +/*******************************************************************\ + +Module: Summarizer Checker for BMC + +Author: Peter Schrammel + +\*******************************************************************/ + +#include "summary_checker_bmc.h" + + +/*******************************************************************\ + +Function: summary_checker_bmct::operator() + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +property_checkert::resultt summary_checker_bmct::operator()( + const goto_modelt &goto_model) +{ + const namespacet ns(goto_model.symbol_table); + irep_idt entry_function = goto_model.goto_functions.entry_point(); + if(options.get_bool_option("unit-check")) + entry_function = ""; + + SSA_functions(goto_model,ns); + + ssa_unwinder.init(false,true); + + property_checkert::resultt result = property_checkert::UNKNOWN; + unsigned max_unwind = options.get_unsigned_int_option("unwind"); + status() << "Max-unwind is " << max_unwind << eom; + ssa_unwinder.init_localunwinders(); + + for(unsigned unwind = 0; unwind<=max_unwind; unwind++) + { + status() << "Unwinding (k=" << unwind << ")" << messaget::eom; + summary_db.mark_recompute_all(); + ssa_unwinder.unwind_all(unwind+1); + std::set seen_function_calls; + result = check_properties(entry_function, entry_function, seen_function_calls); + if(result == property_checkert::PASS) + { + status() << "incremental BMC proof found after " + << unwind << " unwinding(s)" << messaget::eom; + break; + } + else if(result == property_checkert::FAIL) + { + status() << "incremental BMC counterexample found after " + << unwind << " unwinding(s)" << messaget::eom; + break; + } + } + report_statistics(); + return result; +} diff --git a/src/summarizer/summary_checker_bmc.h b/src/summarizer/summary_checker_bmc.h new file mode 100644 index 000000000..8345a41fe --- /dev/null +++ b/src/summarizer/summary_checker_bmc.h @@ -0,0 +1,26 @@ +/*******************************************************************\ + +Module: Summary Checker for BMC + +Author: Peter Schrammel + +\*******************************************************************/ + +#ifndef CPROVER_SUMMARY_CHECKER_BMC_H +#define CPROVER_SUMMARY_CHECKER_BMC_H + +#include "summary_checker_base.h" + +class summary_checker_bmct:public summary_checker_baset +{ +public: + inline summary_checker_bmct(optionst &_options): + summary_checker_baset(_options) + { + } + + virtual resultt operator()(const goto_modelt &); + +}; + +#endif diff --git a/src/summarizer/summary_checker_kind.cpp b/src/summarizer/summary_checker_kind.cpp new file mode 100644 index 000000000..2284d2eb2 --- /dev/null +++ b/src/summarizer/summary_checker_kind.cpp @@ -0,0 +1,76 @@ +/*******************************************************************\ + +Module: Summarizer Checker for k-induction + +Author: Peter Schrammel + +\*******************************************************************/ + +#include "summary_checker_kind.h" + +#define GIVE_UP_INVARIANTS 7 + +/*******************************************************************\ + +Function: summary_checker_kindt::operator() + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +property_checkert::resultt summary_checker_kindt::operator()( + const goto_modelt &goto_model) +{ + const namespacet ns(goto_model.symbol_table); + irep_idt entry_function = goto_model.goto_functions.entry_point(); + if(options.get_bool_option("unit-check")) + entry_function = ""; + + SSA_functions(goto_model,ns); + + ssa_unwinder.init(true,false); + + property_checkert::resultt result = property_checkert::UNKNOWN; + unsigned max_unwind = options.get_unsigned_int_option("unwind"); + status() << "Max-unwind is " << max_unwind << eom; + ssa_unwinder.init_localunwinders(); + + for(unsigned unwind = 0; unwind<=max_unwind; unwind++) + { + status() << "Unwinding (k=" << unwind << ")" << eom; + summary_db.mark_recompute_all(); //TODO: recompute only functions with loops + ssa_unwinder.unwind_all(unwind+1); + + std::set seen_function_calls; + result = check_properties(entry_function, entry_function, seen_function_calls); + if(result == property_checkert::UNKNOWN && + !options.get_bool_option("havoc") && + (unwind seen_function_calls; + result = check_properties(entry_function, entry_function, seen_function_calls); + } + + if(result == property_checkert::PASS) + { + status() << "k-induction proof found after " + << unwind << " unwinding(s)" << eom; + break; + } + else if(result == property_checkert::FAIL) + { + status() << "k-induction counterexample found after " + << unwind << " unwinding(s)" << eom; + break; + } + } + report_statistics(); + return result; +} + diff --git a/src/summarizer/summary_checker_kind.h b/src/summarizer/summary_checker_kind.h new file mode 100644 index 000000000..087ba6fae --- /dev/null +++ b/src/summarizer/summary_checker_kind.h @@ -0,0 +1,26 @@ +/*******************************************************************\ + +Module: Summary Checker for k-induction + +Author: Peter Schrammel + +\*******************************************************************/ + +#ifndef CPROVER_SUMMARY_CHECKER_KIND_H +#define CPROVER_SUMMARY_CHECKER_KIND_H + +#include "summary_checker_base.h" + +class summary_checker_kindt:public summary_checker_baset +{ +public: + inline summary_checker_kindt(optionst &_options): + summary_checker_baset(_options) + { + } + + virtual resultt operator()(const goto_modelt &); + +}; + +#endif From 3182257eb399350b8b3fb7ada7bf297c96ecdc5b Mon Sep 17 00:00:00 2001 From: Peter Schrammel Date: Sat, 23 Apr 2016 16:32:09 +0100 Subject: [PATCH 03/82] all commits of old branch --- src/storefront/Makefile | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 src/storefront/Makefile diff --git a/src/storefront/Makefile b/src/storefront/Makefile new file mode 100644 index 000000000..55c7aa7ce --- /dev/null +++ b/src/storefront/Makefile @@ -0,0 +1,27 @@ +include ../config.inc + +SRC = storefront_main.cpp storefront_parse_options.cpp data.cpp \ + property_view.cpp file_view.cpp trace_view.cpp + +OBJ+= $(CBMC)/src/util/util$(LIBEXT) \ + $(CBMC)/src/xmllang/xmllang$(LIBEXT) \ + ../html/html_escape$(OBJEXT) \ + ../html/syntax_highlighting$(OBJEXT) \ + ../html/logo$(OBJEXT) + +include $(CBMC)/src/config.inc +include $(CBMC)/src/common + +INCLUDES= -I $(CBMC)/src + +LIBS = + +CLEANFILES = storefront$(EXEEXT) + +all: storefront$(EXEEXT) + +############################################################################### + +storefront$(EXEEXT): $(OBJ) + $(LINKBIN) + From 87a561b12102351f90645f374ce1c00e142398b8 Mon Sep 17 00:00:00 2001 From: Peter Schrammel Date: Sat, 23 Apr 2016 17:55:53 +0100 Subject: [PATCH 04/82] fixed compilation errors after merge --- src/2ls/cover_goals_ext.h | 6 +-- src/domains/lexlinrank_solver_enumeration.cpp | 11 ++--- src/domains/lexlinrank_solver_enumeration.h | 2 +- src/domains/ranking_solver_enumeration.cpp | 8 ++-- src/domains/ranking_solver_enumeration.h | 4 +- src/domains/ssa_analyzer.cpp | 6 ++- src/solver/summary.cpp | 12 +++++ src/ssa/local_ssa.cpp | 26 ++++++++--- src/summarizer/summary_checker_ai.cpp | 46 ++++++++++++++++++- src/summarizer/summary_checker_base.cpp | 7 +-- 10 files changed, 99 insertions(+), 29 deletions(-) diff --git a/src/2ls/cover_goals_ext.h b/src/2ls/cover_goals_ext.h index c6d8ea290..119dd0e7a 100644 --- a/src/2ls/cover_goals_ext.h +++ b/src/2ls/cover_goals_ext.h @@ -63,8 +63,8 @@ class cover_goals_extt:public messaget spurious_check(_spurious_check), all_properties(_all_properties), build_error_trace(_build_error_trace), - loophead_selects(_loophead_selects), - summarizer_bw_cex(_summarizer_bw_cex) + summarizer_bw_cex(_summarizer_bw_cex), + loophead_selects(_loophead_selects) { } @@ -129,8 +129,8 @@ class cover_goals_extt:public messaget incremental_solvert &solver; property_checkert::property_mapt &property_map; bool spurious_check, all_properties, build_error_trace; - exprt::operandst loophead_selects; summarizer_bw_cex_baset &summarizer_bw_cex; + exprt::operandst loophead_selects; // this method is called for each satisfying assignment virtual void assignment(); diff --git a/src/domains/lexlinrank_solver_enumeration.cpp b/src/domains/lexlinrank_solver_enumeration.cpp index bd87b6af5..283786ad4 100644 --- a/src/domains/lexlinrank_solver_enumeration.cpp +++ b/src/domains/lexlinrank_solver_enumeration.cpp @@ -32,12 +32,12 @@ Function: lexlinrank_solver_enumerationt::iterate \*******************************************************************/ -bool lexlinrank_solver_enumerationt::iterate(invariantt &_rank) +lexlinrank_solver_enumerationt::progresst lexlinrank_solver_enumerationt::iterate(invariantt &_rank) { lexlinrank_domaint::templ_valuet &rank= static_cast(_rank); - bool improved=false; + progresst progress=CONVERGED; static std::vector number_elements_per_row; number_elements_per_row.resize(rank.size()); @@ -45,7 +45,6 @@ bool lexlinrank_solver_enumerationt::iterate(invariantt &_rank) solver.new_context(); - // choose round to even rounding mode for template computations // not clear what its implications on soundness and // termination of the synthesis are @@ -190,7 +189,7 @@ bool lexlinrank_solver_enumerationt::iterate(invariantt &_rank) } } - improved=true; + progress=CHANGED; // update the current template lexlinrank_domain.set_row_value(row, new_row_values, rank); @@ -254,7 +253,7 @@ bool lexlinrank_solver_enumerationt::iterate(invariantt &_rank) debug() << "Inner solver: " << "the number of inner iterations for row " << row << " was reset to " << number_inner_iterations << eom; - improved=true; + progress=CHANGED; } } } @@ -278,5 +277,5 @@ bool lexlinrank_solver_enumerationt::iterate(invariantt &_rank) } solver.pop_context(); - return improved; + return progress; } diff --git a/src/domains/lexlinrank_solver_enumeration.h b/src/domains/lexlinrank_solver_enumeration.h index b31e87382..204b23e14 100644 --- a/src/domains/lexlinrank_solver_enumeration.h +++ b/src/domains/lexlinrank_solver_enumeration.h @@ -36,7 +36,7 @@ class lexlinrank_solver_enumerationt:public strategy_solver_baset solver_instances++; } - virtual bool iterate(invariantt &inv); + virtual progresst iterate(invariantt &inv); protected: lexlinrank_domaint &lexlinrank_domain; diff --git a/src/domains/ranking_solver_enumeration.cpp b/src/domains/ranking_solver_enumeration.cpp index 9d196369b..908acad1a 100644 --- a/src/domains/ranking_solver_enumeration.cpp +++ b/src/domains/ranking_solver_enumeration.cpp @@ -28,12 +28,12 @@ Function: ranking_solver_enumerationt::iterate \*******************************************************************/ -bool ranking_solver_enumerationt::iterate(invariantt &_rank) +ranking_solver_enumerationt::progresst ranking_solver_enumerationt::iterate(invariantt &_rank) { linrank_domaint::templ_valuet &rank= static_cast(_rank); - bool improved=false; + progresst progress=CONVERGED; // context for "outer" solver solver.new_context(); @@ -151,7 +151,7 @@ bool ranking_solver_enumerationt::iterate(invariantt &_rank) if(linrank_domain.refine()) { debug() << "refining..." << eom; - improved=true; // refinement possible + progress=CHANGED; // refinement possible } else { @@ -174,5 +174,5 @@ bool ranking_solver_enumerationt::iterate(invariantt &_rank) solver.pop_context(); - return improved; + return progress; } diff --git a/src/domains/ranking_solver_enumeration.h b/src/domains/ranking_solver_enumeration.h index f51928b7c..b6e810b35 100644 --- a/src/domains/ranking_solver_enumeration.h +++ b/src/domains/ranking_solver_enumeration.h @@ -24,7 +24,7 @@ class ranking_solver_enumerationt:public strategy_solver_baset incremental_solvert &_solver, const namespacet &_ns, unsigned _max_inner_iterations): - strategy_solver_baset(_solver, _ns), + strategy_solver_baset(_solver, literalt(), _ns), linrank_domain(_linrank_domain), max_inner_iterations(_max_inner_iterations), inner_solver(_ns), @@ -33,7 +33,7 @@ class ranking_solver_enumerationt:public strategy_solver_baset solver_instances++; } - virtual bool iterate(invariantt &inv); + virtual progresst iterate(invariantt &inv); protected: linrank_domaint &linrank_domain; diff --git a/src/domains/ssa_analyzer.cpp b/src/domains/ssa_analyzer.cpp index 3b96fe7f1..ddd5a4664 100644 --- a/src/domains/ssa_analyzer.cpp +++ b/src/domains/ssa_analyzer.cpp @@ -57,7 +57,8 @@ bool ssa_analyzert::operator()( incremental_solvert &solver, local_SSAt &SSA, const exprt &precondition, - template_generator_baset &template_generator) + template_generator_baset &template_generator, + bool check_assertions) { if(SSA.goto_function.body.instructions.empty()) return true; @@ -139,7 +140,8 @@ bool ssa_analyzert::operator()( { result=new predabs_domaint::templ_valuet(); strategy_solver=new strategy_solver_predabst( - *static_cast(domain), solver, SSA.ns); + *static_cast(domain), solver, + assertions_check, SSA.ns); } else if(template_generator.options.get_bool_option("binsearch-solver")) { diff --git a/src/solver/summary.cpp b/src/solver/summary.cpp index 3a74ba628..9766ec416 100644 --- a/src/solver/summary.cpp +++ b/src/solver/summary.cpp @@ -77,6 +77,18 @@ void summaryt::output(std::ostream &out, const namespacet &ns) const #endif out << std::endl; out << "terminates: " << threeval2string(terminates) << std::endl; + for(error_summariest::const_iterator + it = error_summaries.begin(); + it != error_summaries.end(); it++) + { + out << "error summary for "; + if(it->first == entry_call_site) + out << "entry point"; + else + out << "location " << it->first.location_number; + out << ": " << std::endl + << " " << from_expr(ns,"",it->second) << std::endl; + } } /*******************************************************************\ diff --git a/src/ssa/local_ssa.cpp b/src/ssa/local_ssa.cpp index 938b98486..b47c2ac47 100644 --- a/src/ssa/local_ssa.cpp +++ b/src/ssa/local_ssa.cpp @@ -295,10 +295,10 @@ Function: local_SSAt::find_location_by_number local_SSAt::locationt local_SSAt::find_location_by_number(unsigned location_number) const { - local_SSAt::nodest::const_iterator n_it =nodes.begin(); - for(; n_it != nodes.end(); n_it++) + local_SSAt::nodest::const_iterator n_it=nodes.begin(); + for(; n_it!=nodes.end(); n_it++) { - if(n_it->location->location_number == location_number) break; + if(n_it->location->location_number==location_number) break; } return n_it->location; } @@ -571,9 +571,23 @@ void local_SSAt::build_function_call(locationt loc) for(exprt::operandst::iterator it=f.arguments().begin(); it!=f.arguments().end(); ++it, ++i) { - symbol_exprt arg(id2string(fname)+"#"+i2string(loc->location_number)+ - "#arg"+i2string(i), it->type()); - n_it->equalities.push_back(equal_exprt(*it, arg)); + symbol_exprt arg( + id2string(fname)+"#"+i2string(loc->location_number)+ + "#arg"+i2string(i),it->type()); + const typet &argtype=ns.follow(it->type()); + if(argtype.id()==ID_struct) + { + exprt lhs = read_rhs(arg, loc); + for(size_t j=0; jequalities.push_back( + equal_exprt(lhs.operands()[j], it->operands()[j])); + } + } + else + { + n_it->equalities.push_back(equal_exprt(arg,*it)); + } *it=arg; } diff --git a/src/summarizer/summary_checker_ai.cpp b/src/summarizer/summary_checker_ai.cpp index 06d077777..db5ac0bf4 100644 --- a/src/summarizer/summary_checker_ai.cpp +++ b/src/summarizer/summary_checker_ai.cpp @@ -76,15 +76,16 @@ property_checkert::resultt summary_checker_ait::operator()( initialize_property_map(goto_model.goto_functions); bool preconditions = options.get_bool_option("preconditions"); + bool termination = options.get_bool_option("termination"); if(!options.get_bool_option("havoc")) { //forward analysis - summarize(goto_model,true,false); + summarize(goto_model,true,termination); } if(!options.get_bool_option("havoc") && preconditions) { //backward analysis - summarize(goto_model,false,false); + summarize(goto_model,false,termination); } if(preconditions) @@ -94,6 +95,12 @@ property_checkert::resultt summary_checker_ait::operator()( return property_checkert::UNKNOWN; } + if(termination) + { + report_statistics(); + return report_termination(); + } + #ifdef SHOW_CALLINGCONTEXTS if(options.get_bool_option("show-calling-contexts")) return property_checkert::UNKNOWN; @@ -143,3 +150,38 @@ void summary_checker_ait::report_preconditions() from_expr(it->second->ns, "", precondition)) << eom; } } + +/*******************************************************************\ + +Function: summary_checker_ait::report_termination + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +property_checkert::resultt summary_checker_ait::report_termination() +{ + result() << eom; + result() << "** Termination: " << eom; + bool all_terminate = true; + bool one_nonterminate = false; + ssa_dbt::functionst &functions = ssa_db.functions(); + for(ssa_dbt::functionst::iterator it = functions.begin(); + it != functions.end(); it++) + { + threevalt terminates = YES; + bool computed = summary_db.exists(it->first); + if(computed) terminates = summary_db.get(it->first).terminates; + all_terminate = all_terminate && (terminates==YES); + one_nonterminate = one_nonterminate || (terminates==NO); + result() << "[" << it->first << "]: " + << (!computed ? "not computed" : threeval2string(terminates)) << eom; + } + if(all_terminate) return property_checkert::PASS; + if(one_nonterminate) return property_checkert::FAIL; + return property_checkert::UNKNOWN; +} diff --git a/src/summarizer/summary_checker_base.cpp b/src/summarizer/summary_checker_base.cpp index 256227f6c..9676fb2aa 100644 --- a/src/summarizer/summary_checker_base.cpp +++ b/src/summarizer/summary_checker_base.cpp @@ -251,10 +251,11 @@ void summary_checker_baset::check_properties( const ssa_dbt::functionst::const_iterator f_it, irep_idt entry_function) { - local_SSAt &SSA = *f_it->second; + unwindable_local_SSAt &SSA = *f_it->second; if(!SSA.goto_function.body.has_assertion()) return; bool all_properties = options.get_bool_option("all-properties"); + bool build_error_trace = options.get_bool_option("show-trace"); SSA.output(debug()); debug() << eom; @@ -359,9 +360,9 @@ void summary_checker_baset::check_properties( summarizer_bw_cex->set_message_handler(get_message_handler()); cover_goals_extt cover_goals( - solver,loophead_selects,property_map, + SSA,solver,loophead_selects,property_map, f_it->first!=entry_function || !fully_unwound, - all_properties, + all_properties,build_error_trace, *summarizer_bw_cex); #if 0 From 5c3468c48e2190e76c6718703d21c44f84f823fb Mon Sep 17 00:00:00 2001 From: Peter Schrammel Date: Mon, 25 Apr 2016 21:07:53 +0100 Subject: [PATCH 05/82] use cex analyser concrete with --inline --- src/2ls/cover_goals_ext.cpp | 43 +++++++++++++++++++++++-- src/summarizer/summary_checker_base.cpp | 5 +-- 2 files changed, 43 insertions(+), 5 deletions(-) diff --git a/src/2ls/cover_goals_ext.cpp b/src/2ls/cover_goals_ext.cpp index 706410331..e4814856c 100644 --- a/src/2ls/cover_goals_ext.cpp +++ b/src/2ls/cover_goals_ext.cpp @@ -177,11 +177,41 @@ void cover_goals_extt::assignment() std::list::const_iterator g_it=goals.begin(); for(goal_mapt::const_iterator it=goal_map.begin(); it!=goal_map.end(); it++, g_it++) + { + if(property_map[it->first].result==property_checkert::UNKNOWN && + solver.l_get(g_it->condition).is_true()) { - if(property_map[it->first].result==property_checkert::UNKNOWN && - solver.l_get(g_it->condition).is_true()) + if(spurious_check) + { + assert((g_it->cond_expression).id() == ID_not); + exprt conjunct_expr = (g_it->cond_expression).op0(); + + if(conjunct_expr.id() != ID_and) { - if(spurious_check) + solver.pop_context(); //otherwise this would interfere with necessary preconditions + summarizer_bw_cex.summarize(g_it->cond_expression); + property_map[it->first].result = summarizer_bw_cex.check(); + solver.new_context(); + } + else + { + exprt::operandst failed_exprs; + for(exprt::operandst::const_iterator c_it = + conjunct_expr.operands().begin(); + c_it != conjunct_expr.operands().end(); c_it++) + { + literalt conjunct_literal = solver.convert(*c_it); + if(solver.l_get(conjunct_literal).is_false()) + failed_exprs.push_back(*c_it); + } + solver.pop_context(); //otherwise this would interfere with necessary preconditions + for(unsigned i=0; ifirst].result = summarizer_bw_cex.check(); + if(property_map[it->first].result == + property_checkert::FAIL) { assert((g_it->cond_expression).id()==ID_not); exprt conjunct_expr=(g_it->cond_expression).op0(); @@ -220,6 +250,13 @@ void cover_goals_extt::assignment() else property_map[it->first].result=property_checkert::FAIL; } + } + else + property_map[it->first].result = property_checkert::FAIL; + } + if(!all_properties && + property_map[it->first].result == property_checkert::FAIL) + break; } _iterations++; //statistics diff --git a/src/summarizer/summary_checker_base.cpp b/src/summarizer/summary_checker_base.cpp index 9676fb2aa..224f0be4d 100644 --- a/src/summarizer/summary_checker_base.cpp +++ b/src/summarizer/summary_checker_base.cpp @@ -321,14 +321,15 @@ void summary_checker_baset::check_properties( incremental_solvert* cex_complete_solver = incremental_solvert::allocate(SSA.ns, options.get_bool_option("refine")); - if(options.get_option("spurious-check") == "concrete") + if(options.get_bool_option("inline") || + options.get_option("spurious-check") == "concrete") { summarizer_bw_cex = new summarizer_bw_cex_concretet( options,summary_db,ssa_db, ssa_unwinder,ssa_inliner, entry_function,f_it->first); } - if(options.get_option("spurious-check") == "abstract") + else if(options.get_option("spurious-check") == "abstract") { summarizer_bw_cex = new summarizer_bw_cex_ait( options,summary_db,ssa_db, From 4fae501bac3124480ca36667e364df3d2a718328 Mon Sep 17 00:00:00 2001 From: Peter Schrammel Date: Mon, 25 Apr 2016 22:16:22 +0100 Subject: [PATCH 06/82] made sure that the executable is named 2ls --- regression/modular/Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/regression/modular/Makefile b/regression/modular/Makefile index 19c23b682..2a3b5cb15 100644 --- a/regression/modular/Makefile +++ b/regression/modular/Makefile @@ -1,12 +1,12 @@ default: tests.log -FLAGS = --verbosity 10 --spurious-check concrete +FLAGS = --verbosity 10 --spurious-check complete test: - @../test.pl -c "../../../src/summarizer/summarizer $(FLAGS)" + @../test.pl -c "../../../src/summarizer/2ls $(FLAGS)" tests.log: ../test.pl - @../test.pl -c "../../../src/summarizer/summarizer $(FLAGS)" + @../test.pl -c "../../../src/summarizer/2ls $(FLAGS)" show: @for dir in *; do \ From 3926b9e0f286428e2536a81b09decf6207db2f18 Mon Sep 17 00:00:00 2001 From: Kumar Madhukar Date: Tue, 26 Apr 2016 18:25:09 +0530 Subject: [PATCH 07/82] bug fixes for abstract case --- src/domains/disjunctive_analyzer.cpp | 10 +++++++--- src/summarizer/summarizer_bw_cex_ai.cpp | 25 +++++++++++++++---------- 2 files changed, 22 insertions(+), 13 deletions(-) diff --git a/src/domains/disjunctive_analyzer.cpp b/src/domains/disjunctive_analyzer.cpp index b82e3cfa0..9d619c364 100644 --- a/src/domains/disjunctive_analyzer.cpp +++ b/src/domains/disjunctive_analyzer.cpp @@ -178,12 +178,12 @@ bool disjunctive_analyzert::operator()( //std::cout << "unsimplified disjunctive cond: " << from_expr(SSA.ns, "", disjunctive_conditions) << "\n\n"; exprt simple_disjunctive_conditions = simplify_expr(disjunctive_conditions, SSA.ns); //disjunctive_conditions; - //std::cout << "simplified disjunctive cond: " << from_expr(SSA.ns, "", simple_disjunctive_conditions) << "\n\n"; + //std::cout << " simplified disjunctive cond: " << from_expr(SSA.ns, "", simple_disjunctive_conditions) << "\n\n"; //converting simple_disjunctive_conditions into DNF //std::cout << "before conversion: " << from_expr(SSA.ns, "", simple_disjunctive_conditions) << "\n\n\n"; this->convert_to_dnf(simple_disjunctive_conditions); - //std::cout << "after conversion: " << from_expr(SSA.ns, "", simple_disjunctive_conditions) << "\n\n\n"; + //std::cout << " after conversion: " << from_expr(SSA.ns, "", simple_disjunctive_conditions) << "\n\n\n"; if(simple_disjunctive_conditions.id() == ID_or){ @@ -192,11 +192,12 @@ bool disjunctive_analyzert::operator()( exprt::operandst disjuncts=simple_disjunctive_conditions.operands(); for(exprt::operandst::iterator d_it=disjuncts.begin();d_it!=disjuncts.end();d_it++){ if((*d_it).id() == ID_not){ + //std::cout << "processing (not) disjunct: " << from_expr(SSA.ns, "", *d_it) << "\n"; + exprt::operandst ops = (*d_it).operands(); for(exprt::operandst::iterator o_it=ops.begin();o_it!=ops.end();o_it++){ if((*o_it).id() == ID_equal){ exprt::operandst ops_equality = (*o_it).operands(); - equal_exprt equal_expr_in_not = to_equal_expr(*o_it); bool constant_comparison = false; @@ -212,6 +213,9 @@ bool disjunctive_analyzert::operator()( processed_disjuncts.push_back(*d_it); } } + else{ + processed_disjuncts.push_back(*d_it); + } } } else{ diff --git a/src/summarizer/summarizer_bw_cex_ai.cpp b/src/summarizer/summarizer_bw_cex_ai.cpp index fb5ae3183..f39b8d3e7 100644 --- a/src/summarizer/summarizer_bw_cex_ai.cpp +++ b/src/summarizer/summarizer_bw_cex_ai.cpp @@ -265,10 +265,10 @@ void summarizer_bw_cex_ait::do_summary(const function_namet &function_name, c.push_back(conjunction(assert_postcond)); //with negative information would need: not_exprt c.push_back(conjunction(noassert_postcond)); //with negative information would need: not_exprt dis - //std::cout << "unsimplified constraints: " << from_expr(SSA.ns, "", conjunction(c)) << "\n\n\n"; + //std::cout << "unsimplified constraints (if): " << from_expr(SSA.ns, "", conjunction(c)) << "\n\n\n"; exprt cc = simplify_expr(conjunction(c), SSA.ns); //exprt cc = conjunction(c); - //std::cout << "simplified constraints passed: " << from_expr(SSA.ns, "", cc) << "\n\n\n"; + //std::cout << "simplified constraints passed (if): " << from_expr(SSA.ns, "", cc) << "\n\n\n"; /* ssa_analyzert analyzer; @@ -277,13 +277,14 @@ void summarizer_bw_cex_ait::do_summary(const function_namet &function_name, analyzer.get_result(summary.error_summaries[call_site], template_generator.inout_vars()); */ - + /**/ disjunctive_analyzert disjunctive_analyzer; disjunctive_analyzer.set_message_handler(get_message_handler()); disjunctive_analyzer(solver,SSA,cc,template_generator, cc,summary.error_summaries[call_site], template_generator.inout_vars()); - + /**/ + #if 0 std::cout << "SUM: " << from_expr(SSA.ns, "", summary.error_summaries[call_site]) << std::endl; #endif @@ -308,20 +309,24 @@ void summarizer_bw_cex_ait::do_summary(const function_namet &function_name, } else // TODO: yet another workaround for ssa_analyzer not being able to handle empty templates properly { - c.push_back(not_exprt(conjunction(assert_postcond))); - c.push_back(not_exprt(disjunction(noassert_postcond))); + c.push_back(conjunction(assert_postcond)); //with negative information would need: not_exprt + c.push_back(conjunction(noassert_postcond)); //with negative information would need: not_exprt dis + //c.push_back(not_exprt(conjunction(assert_postcond))); + //c.push_back(not_exprt(disjunction(noassert_postcond))); - //std::cout << "unsimplified constraints: " << from_expr(SSA.ns, "", conjunction(c)) << "\n\n\n"; + //std::cout << "unsimplified constraints (else): " << from_expr(SSA.ns, "", conjunction(c)) << "\n\n\n"; exprt cc = simplify_expr(conjunction(c), SSA.ns); //exprt cc = conjunction(c); - //std::cout << "simplified constraints passed: " << from_expr(SSA.ns, "", cc) << "\n\n\n"; + //std::cout << "simplified constraints passed (else): " << from_expr(SSA.ns, "", cc) << "\n\n\n"; + + //std::cout << "enabling expressions (else): " << from_expr(SSA.ns, "", SSA.get_enabling_exprs()) << "\n\n\n"; solver << SSA; solver.new_context(); solver << SSA.get_enabling_exprs(); solver << cc; - exprt result = false_exprt(); - if(solver()!=decision_proceduret::D_SATISFIABLE) result = true_exprt(); + exprt result = true_exprt(); + if(solver()!=decision_proceduret::D_SATISFIABLE) result = false_exprt(); solver.pop_context(); summary.error_summaries[call_site] = result; From cf924bc0890f6fe80f5b66543a2c9a3bb9be75a7 Mon Sep 17 00:00:00 2001 From: Kumar Madhukar Date: Tue, 26 Apr 2016 21:31:45 +0530 Subject: [PATCH 08/82] loop-specific unwinding code, in progress --- src/ssa/ssa_unwinder.cpp | 59 +++++++++++++++++++++++++++ src/ssa/ssa_unwinder.h | 4 +- src/summarizer/summary_checker_ai.cpp | 45 ++++++++++++++++++++ 3 files changed, 107 insertions(+), 1 deletion(-) diff --git a/src/ssa/ssa_unwinder.cpp b/src/ssa/ssa_unwinder.cpp index aecf2166c..bbdb78392 100644 --- a/src/ssa/ssa_unwinder.cpp +++ b/src/ssa/ssa_unwinder.cpp @@ -262,6 +262,45 @@ void ssa_local_unwindert::build_exit_conditions() } } +/***************************************************************************** + * + * Function : ssa_local_unwindert::unwind_loop_at_location() + * + * Input : + * + * Output : + * + * Purpose : unwind the loop at the given location, up to k starting from + * previous unwindings + * + * + *****************************************************************************/ + +void ssa_local_unwindert::unwind_loop_at_location(unsigned loc, unsigned k) +{ + if(SSA.current_unwinding>=(long)k) + return; + + current_enabling_expr= + symbol_exprt("unwind::"+id2string(fname)+"::enable"+i2string(k), + bool_typet()); + SSA.enabling_exprs.push_back(current_enabling_expr); + SSA.current_unwinding=k; //TODO: just for exploratory integration, must go away + //recursively unwind everything + SSA.current_unwindings.clear(); + + loopt &loop=loops[loc]; + + if(loop.is_root){ + unwind(loop,k,false); //recursive + assert(SSA.current_unwindings.empty()); + } + + loop.current_unwinding=k; + + return; +} + /*******************************************************************\ Function: ssa_local_unwindert::unwind @@ -808,6 +847,26 @@ void ssa_local_unwindert::unwinder_rename( #endif } +/*****************************************************************************\ + * + * Function : ssa_unwindert::unwind_loop_alone() + * + * Input : + * + * Output : + * + * Purpose : + * + *****************************************************************************/ + +void ssa_unwindert::unwind_loop_alone(const irep_idt fname, unsigned loc, unsigned int k) +{ + assert(is_initialized); + unwinder_mapt::iterator it = unwinder_map.find(fname); + assert(it != unwinder_map.end()); + it->second.unwind_loop_at_location(loc, k); +} + /*******************************************************************\ diff --git a/src/ssa/ssa_unwinder.h b/src/ssa/ssa_unwinder.h index 62b7a20d7..41451334b 100644 --- a/src/ssa/ssa_unwinder.h +++ b/src/ssa/ssa_unwinder.h @@ -32,6 +32,7 @@ class ssa_local_unwindert void init(); + void unwind_loop_at_location(unsigned loc, unsigned k); void unwind(unsigned k); #if 0 @@ -136,7 +137,8 @@ class ssa_unwindert:public messaget void init(bool is_kinduction, bool is_bmc); void init_localunwinders(); - + + void unwind_loop_alone(const irep_idt fname, unsigned loc, unsigned k); void unwind(const irep_idt fname, unsigned k); void unwind_all(unsigned k); diff --git a/src/summarizer/summary_checker_ai.cpp b/src/summarizer/summary_checker_ai.cpp index db5ac0bf4..bd09d187c 100644 --- a/src/summarizer/summary_checker_ai.cpp +++ b/src/summarizer/summary_checker_ai.cpp @@ -42,6 +42,51 @@ property_checkert::resultt summary_checker_ait::operator()( ssa_unwinder.output(debug()); debug() < 0){ + forall_goto_functions(f_it, goto_model.goto_functions){ + if(!f_it->second.body_available()) continue; + if(has_prefix(id2string(f_it->first),TEMPLATE_DECL)) continue; + local_SSAt &SSA = ssa_db.get(f_it->first); + std::cout << "==>> Output SSA for function: " << f_it->first << "\n"; + SSA.output(std::cout); + } + } + else{ + ssa_unwinder.init_localunwinders(); // possibly required; + + // iterate over the SSA to unwind loops + forall_goto_functions(f_it, goto_model.goto_functions){ + + if(!f_it->second.body_available()) continue; + if(has_prefix(id2string(f_it->first),TEMPLATE_DECL)) continue; + + local_SSAt &SSA = ssa_db.get(f_it->first); + for(local_SSAt::nodest::const_iterator n_it = SSA.nodes.begin(); + n_it != SSA.nodes.end(); n_it++){ + if(n_it->loophead!=SSA.nodes.end()){ + std::cout << "==>> unwinding loop with location number: " + << n_it->loophead->location->location_number << "\n"; + ssa_unwinder.unwind_loop_alone(f_it->first, + n_it->loophead->location->location_number, 1); + } + } + } + + forall_goto_functions(f_it, goto_model.goto_functions){ + if(!f_it->second.body_available()) continue; + if(has_prefix(id2string(f_it->first),TEMPLATE_DECL)) continue; + local_SSAt &SSA = ssa_db.get(f_it->first); + std::cout << "==>> Output SSA for function: " << f_it->first << "\n"; + SSA.output(std::cout); + } + + } + /**/ + /*********************************************************************************/ + irep_idt entry_function = goto_model.goto_functions.entry_point(); if(options.get_bool_option("unit-check")) entry_function = ""; From 78c3f8acc2778d23a302c9e469f8e9468e5feff7 Mon Sep 17 00:00:00 2001 From: Kumar Madhukar Date: Wed, 27 Apr 2016 21:06:40 +0530 Subject: [PATCH 09/82] commented new code to check loop-specific unwinding --- src/summarizer/summary_checker_ai.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/summarizer/summary_checker_ai.cpp b/src/summarizer/summary_checker_ai.cpp index bd09d187c..4ad5ab3b1 100644 --- a/src/summarizer/summary_checker_ai.cpp +++ b/src/summarizer/summary_checker_ai.cpp @@ -44,7 +44,7 @@ property_checkert::resultt summary_checker_ait::operator()( /*********************************************************************************/ /**************** code to test the loop-specific unwind function *****************/ - /**/ + /* if(unwind > 0){ forall_goto_functions(f_it, goto_model.goto_functions){ if(!f_it->second.body_available()) continue; @@ -84,7 +84,7 @@ property_checkert::resultt summary_checker_ait::operator()( } } - /**/ + */ /*********************************************************************************/ irep_idt entry_function = goto_model.goto_functions.entry_point(); From 072f5b9407ae7d98eb8299537f6b0f4882575ec4 Mon Sep 17 00:00:00 2001 From: Kumar Madhukar Date: Wed, 27 Apr 2016 22:28:30 +0530 Subject: [PATCH 10/82] commented debug code --- src/summarizer/summarizer_bw_cex_concrete.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/summarizer/summarizer_bw_cex_concrete.cpp b/src/summarizer/summarizer_bw_cex_concrete.cpp index f06da6367..5e06a3103 100644 --- a/src/summarizer/summarizer_bw_cex_concrete.cpp +++ b/src/summarizer/summarizer_bw_cex_concrete.cpp @@ -342,11 +342,12 @@ void summarizer_bw_cex_concretet::do_summary( summary.has_assertion = assertion_flag; solver.pop_context(); - /**/ + /* // if the summary is true, print the postcondition and the list of loops in this function // this postcondition is modified, possibly twice, from what is returned by compute_calling_context2 // pc = end_guard => original_pc, and // pc = pc && not(assertion), if this is error function + std::cout << "==>>\n"; std::cout << "==>> Summary: true\n"; std::cout << "==>> Postcondition: " << from_expr(SSA.ns, "", postcondition) << "\n"; @@ -359,7 +360,7 @@ void summarizer_bw_cex_concretet::do_summary( } } std::cout << "==>>\n"; - /**/ + */ return; } From e3763bc791865f7a797d56e1591f7221114b0767 Mon Sep 17 00:00:00 2001 From: Peter Schrammel Date: Thu, 28 Apr 2016 14:49:25 +0100 Subject: [PATCH 11/82] put unwinding suffix into ID_suffix attribute --- src/ssa/unwindable_local_ssa.cpp | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/ssa/unwindable_local_ssa.cpp b/src/ssa/unwindable_local_ssa.cpp index 8b49f8e76..c8807ba35 100644 --- a/src/ssa/unwindable_local_ssa.cpp +++ b/src/ssa/unwindable_local_ssa.cpp @@ -279,6 +279,12 @@ Function: unwindable_local_SSAt::rename void unwindable_local_SSAt::rename(exprt &expr, locationt current_loc) { + if (expr.id() == ID_function_application) + { + std::string unwind_suffix = odometer_to_string(current_unwindings, + current_unwindings.size()); + expr.set(ID_suffix,unwind_suffix); + } if(expr.id()==ID_symbol) { symbol_exprt &s=to_symbol_expr(expr); @@ -292,7 +298,7 @@ void unwindable_local_SSAt::rename(exprt &expr, locationt current_loc) std::string unwind_suffix= odometer_to_string(current_unwindings, def_level); s.set_identifier(id2string(id)+unwind_suffix); - + s.set(ID_suffix,unwind_suffix); #if 0 std::cout << "DEF_LOC: " << def_loc->location_number << std::endl; std::cout << "DEF_LEVEL: " << def_level << std::endl; @@ -307,13 +313,9 @@ void unwindable_local_SSAt::rename(exprt &expr, locationt current_loc) { std::string unwind_suffix= odometer_to_string(current_unwindings, current_unwindings.size()); - std::string identifier=id2string(expr.get(ID_identifier)); - std::size_t pos=identifier.find("%"); - if(pos!=std::string::npos) - identifier=identifier.substr(0, pos); - expr.set( - ID_identifier, - identifier+unwind_suffix+suffix); + expr.set(ID_suffix,unwind_suffix); + expr.set(ID_identifier, + id2string(expr.get(ID_identifier))+unwind_suffix+suffix); } Forall_operands(it, expr) rename(*it, current_loc); From bd1b95ec55ea40e350b080c5e4aa037e7b43fa3a Mon Sep 17 00:00:00 2001 From: Peter Schrammel Date: Wed, 11 May 2016 23:14:16 +0100 Subject: [PATCH 12/82] collect nondet vars in local_SSA --- src/ssa/local_ssa.cpp | 50 +++++++++++++++++++++++++++++++++++++++++++ src/ssa/local_ssa.h | 4 ++++ 2 files changed, 54 insertions(+) diff --git a/src/ssa/local_ssa.cpp b/src/ssa/local_ssa.cpp index b47c2ac47..44401b850 100644 --- a/src/ssa/local_ssa.cpp +++ b/src/ssa/local_ssa.cpp @@ -117,8 +117,58 @@ void local_SSAt::get_entry_exit_vars() goto_programt::const_targett last=goto_function.body.instructions.end(); last--; get_globals(last, globals_out, true, true, last->function); + + //get nondeterministic variables + get_nondet_vars(); } +/*******************************************************************\ + +Function: local_SSAt::get_nondet_vars + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +void local_SSAt::get_nondet_vars(const exprt &expr) +{ + if(expr.id()==ID_nondet) + nondets.insert(expr); + else + forall_operands(it, expr) + get_nondet_vars(*it); +} + +void local_SSAt::get_nondet_vars() +{ + for(nodest::iterator n_it=nodes.begin(); + n_it!=nodes.end(); n_it++) + { + for(nodet::equalitiest::const_iterator + e_it=n_it->equalities.begin(); + e_it!=n_it->equalities.end(); + e_it++) + get_nondet_vars(*e_it); + + for(nodet::constraintst::const_iterator + c_it=n_it->constraints.begin(); + c_it!=n_it->constraints.end(); + c_it++) + get_nondet_vars(*c_it); + + for(nodet::assertionst::const_iterator + a_it=n_it->assertions.begin(); + a_it!=n_it->assertions.end(); + a_it++) + get_nondet_vars(*a_it); + } +} + + /*******************************************************************\ Function: local_SSAt::get_globals diff --git a/src/ssa/local_ssa.h b/src/ssa/local_ssa.h index 5f9d54006..3b2950d7c 100644 --- a/src/ssa/local_ssa.h +++ b/src/ssa/local_ssa.h @@ -128,6 +128,7 @@ class local_SSAt typedef std::set var_sett; var_listt params; var_sett globals_in, globals_out; + std::set nondets; bool has_function_calls() const; @@ -222,6 +223,9 @@ class local_SSAt void collect_custom_templates(); replace_mapt template_newvars; exprt template_last_newvar; + + void get_nondet_vars(const exprt &expr); + void get_nondet_vars(); }; std::vector & operator << From 4ae34ef215852be32b73c7b217eb6cbbaec22bac Mon Sep 17 00:00:00 2001 From: Peter Schrammel Date: Wed, 11 May 2016 23:25:21 +0100 Subject: [PATCH 13/82] add nondets as OUT vars to summary template for backwards analysis --- src/domains/template_generator_base.cpp | 23 ++++++++++++++++++++++ src/domains/template_generator_summary.cpp | 7 +++++++ 2 files changed, 30 insertions(+) diff --git a/src/domains/template_generator_base.cpp b/src/domains/template_generator_base.cpp index e62fa1649..8a423b426 100644 --- a/src/domains/template_generator_base.cpp +++ b/src/domains/template_generator_base.cpp @@ -337,6 +337,29 @@ Function: template_generator_baset::add_vars \*******************************************************************/ +void template_generator_baset::add_vars( + const std::set &vars_to_add, + const domaint::guardt &pre_guard, + const domaint::guardt &post_guard, + const domaint::kindt &kind, + domaint::var_specst &var_specs) +{ + for(const auto &v : vars_to_add) + add_var(v, pre_guard, post_guard, kind, var_specs); +} + +/*******************************************************************\ + +Function: template_generator_baset::add_vars + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + void template_generator_baset::add_vars( const local_SSAt::var_listt &vars_to_add, const domaint::guardt &pre_guard, diff --git a/src/domains/template_generator_summary.cpp b/src/domains/template_generator_summary.cpp index becceba5f..e50835e82 100644 --- a/src/domains/template_generator_summary.cpp +++ b/src/domains/template_generator_summary.cpp @@ -103,6 +103,13 @@ void template_generator_summaryt::collect_variables_inout( last_guard, forward ? domaint::OUT : domaint::IN, var_specs); + + // add nondets for backwards analysis + if(!forward) + { + add_vars(SSA.nondets,first_guard,first_guard, + domaint::OUT, var_specs); + } } /*******************************************************************\ From 3642d887708ab8201b653ad0dfadec4389324a68 Mon Sep 17 00:00:00 2001 From: Peter Schrammel Date: Wed, 11 May 2016 23:44:31 +0100 Subject: [PATCH 14/82] fixed various places where nondet_symbols in templates were not expected --- src/domains/util.cpp | 5 +++-- src/solver/summary.h | 3 ++- src/ssa/local_ssa.cpp | 2 +- src/summarizer/summarizer_bw_cex_ai.cpp | 2 ++ src/summarizer/summarizer_bw_cex_concrete.cpp | 10 ++++++++++ 5 files changed, 18 insertions(+), 4 deletions(-) diff --git a/src/domains/util.cpp b/src/domains/util.cpp index e763be350..450c5132c 100644 --- a/src/domains/util.cpp +++ b/src/domains/util.cpp @@ -51,6 +51,7 @@ void extend_expr_types(exprt &expr) } if(expr.id()==ID_constant || expr.id()==ID_symbol || + expr.id()==ID_nondet_symbol || expr.id()==ID_index) return; if(expr.id()==ID_unary_minus) @@ -241,7 +242,7 @@ mp_integer simplify_const_int(const exprt &expr) assert(d!=0); return simplify_const_int(expr.op0())/d; } - if(expr.id()==ID_symbol) + if(expr.id()==ID_symbol || expr.id()==ID_nondet_symbol) { #if 0 std::cerr << "substituting default value for " << expr << std::endl; @@ -332,7 +333,7 @@ ieee_floatt simplify_const_float(const exprt &expr) v1/=v2; return v1; } - if(expr.id()==ID_symbol) // default value if not substituted in expr + if(expr.id()==ID_symbol || expr.id()==ID_nondet_symbol) //default value if not substituted in expr { ieee_floatt v; v.make_zero(); diff --git a/src/solver/summary.h b/src/solver/summary.h index ad991e00a..2d9d11a9e 100644 --- a/src/solver/summary.h +++ b/src/solver/summary.h @@ -24,6 +24,7 @@ class summaryt typedef std::list var_listt; typedef std::set var_sett; + typedef std::set expr_sett; summaryt() : fw_precondition(nil_exprt()), @@ -39,7 +40,7 @@ class summaryt var_listt params; var_sett globals_in, globals_out; - + expr_sett nondets; predicatet fw_precondition; // accumulated calling contexts (over-approx) // predicatet fw_postcondition; // we are not projecting that out currently predicatet fw_transformer; // forward summary (over-approx) diff --git a/src/ssa/local_ssa.cpp b/src/ssa/local_ssa.cpp index 44401b850..86fbe9b4b 100644 --- a/src/ssa/local_ssa.cpp +++ b/src/ssa/local_ssa.cpp @@ -136,7 +136,7 @@ Function: local_SSAt::get_nondet_vars void local_SSAt::get_nondet_vars(const exprt &expr) { - if(expr.id()==ID_nondet) + if(expr.id()==ID_nondet_symbol) nondets.insert(expr); else forall_operands(it, expr) diff --git a/src/summarizer/summarizer_bw_cex_ai.cpp b/src/summarizer/summarizer_bw_cex_ai.cpp index f39b8d3e7..785456a1c 100644 --- a/src/summarizer/summarizer_bw_cex_ai.cpp +++ b/src/summarizer/summarizer_bw_cex_ai.cpp @@ -137,6 +137,7 @@ void summarizer_bw_cex_ait::compute_summary_rec( summary.params = SSA.params; summary.globals_in = SSA.globals_in; summary.globals_out = SSA.globals_out; + summary.nondets = SSA.nondets; } // insert assertion @@ -238,6 +239,7 @@ void summarizer_bw_cex_ait::do_summary(const function_namet &function_name, assert_postcond.push_back(postcondition); //context + //TODO: add nondet variables from callees to summary.nondets // assumptions must hold for(local_SSAt::nodest::const_iterator diff --git a/src/summarizer/summarizer_bw_cex_concrete.cpp b/src/summarizer/summarizer_bw_cex_concrete.cpp index 5e06a3103..4a30ef8d9 100644 --- a/src/summarizer/summarizer_bw_cex_concrete.cpp +++ b/src/summarizer/summarizer_bw_cex_concrete.cpp @@ -130,6 +130,7 @@ void summarizer_bw_cex_concretet::compute_summary_rec( summary.params = SSA.params; summary.globals_in = SSA.globals_in; summary.globals_out = SSA.globals_out; + summary.nondets = SSA.nondets; } // insert assertion @@ -227,6 +228,8 @@ void summarizer_bw_cex_concretet::do_summary( assertion_flag = ssa_inliner.get_summaries(SSA,call_site,false,assert_postcond,noassert_postcond,c); //backward summaries assert_postcond.push_back(postcondition); //context + //TODO: add nondet variables from callees to summary.nondets + //std::cout << "Assert Summary: " << from_expr(SSA.ns, "", conjunction(assert_postcond)) << "\n\n"; //std::cout << "Noassert Summary: " << from_expr(SSA.ns, "", conjunction(noassert_postcond)) << "\n\n"; @@ -388,6 +391,13 @@ void summarizer_bw_cex_concretet::do_summary( var_values.push_back(equal_exprt(*it, summ_value)); } + for(std::set::const_iterator it = summary.nondets.begin(); + it != summary.nondets.end(); it++){ + exprt summ_value = solver.get(*it); + if(!summ_value.is_nil()) + var_values.push_back(equal_exprt(*it, summ_value)); + } + summary.error_summaries[call_site] = not_exprt(conjunction(var_values)); summary.has_assertion = assertion_flag; From f0d46d3a3d114ba692ab09a2b9cc6e43bbeb3c1e Mon Sep 17 00:00:00 2001 From: Kumar Madhukar Date: Fri, 13 May 2016 13:19:56 +0530 Subject: [PATCH 15/82] added a comment for new fields in loopt --- src/ssa/ssa_unwinder.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/ssa/ssa_unwinder.h b/src/ssa/ssa_unwinder.h index 41451334b..6119d821a 100644 --- a/src/ssa/ssa_unwinder.h +++ b/src/ssa/ssa_unwinder.h @@ -75,6 +75,9 @@ class ssa_local_unwindert bool is_dowhile; bool is_root; long current_unwinding; + + // to have an enabling_expr and current_unwindings (odometert) + typedef std::map exit_mapt; exit_mapt exit_map; std::map pre_post_map; @@ -142,12 +145,12 @@ class ssa_unwindert:public messaget void unwind(const irep_idt fname, unsigned k); void unwind_all(unsigned k); - inline ssa_local_unwindert &get(const irep_idt& fname) + ssa_local_unwindert &get(const irep_idt& fname) { return unwinder_map.at(fname); } - inline const ssa_local_unwindert &get(const irep_idt& fname) const + const ssa_local_unwindert &get(const irep_idt& fname) const { return unwinder_map.at(fname); } From ec5e73adc747ff5d116b8454c3929dc79828468b Mon Sep 17 00:00:00 2001 From: Peter Schrammel Date: Fri, 13 May 2016 09:18:18 +0100 Subject: [PATCH 16/82] fixes to replace_globals when inlining --- src/ssa/local_ssa.cpp | 16 +++++++++------- src/ssa/ssa_inliner.cpp | 41 +++++++++-------------------------------- 2 files changed, 18 insertions(+), 39 deletions(-) diff --git a/src/ssa/local_ssa.cpp b/src/ssa/local_ssa.cpp index 86fbe9b4b..70256dabe 100644 --- a/src/ssa/local_ssa.cpp +++ b/src/ssa/local_ssa.cpp @@ -198,22 +198,24 @@ void local_SSAt::get_globals( << from_expr(ns, "", read_lhs(it->get_expr(), loc)) << std::endl; #endif - if(!with_returns && - id2string(it->get_identifier()).find( - "#return_value")!=std::string::npos) - continue; + bool is_return=id2string(it->get_identifier()).find( + "#return_value")!=std::string::npos; + if(!with_returns && is_return) + continue; // filter out return values of other functions if(with_returns && returns_for_function!="" && - id2string(it->get_identifier()).find( - "#return_value")!=std::string::npos && + is_return && id2string(it->get_identifier()).find( id2string(returns_for_function)+"#return_value")==std::string::npos) continue; if(rhs_value) { - const exprt &expr=read_rhs(it->get_expr(), loc); + //workaround for the problem that + // rhs() for a return value is always the "input" return value + const exprt &expr=is_return ? + read_lhs(it->get_expr(),--loc) : read_rhs(it->get_expr(),loc); globals.insert(to_symbol_expr(expr)); } else diff --git a/src/ssa/ssa_inliner.cpp b/src/ssa/ssa_inliner.cpp index 50db93b1e..f127fddeb 100644 --- a/src/ssa/ssa_inliner.cpp +++ b/src/ssa/ssa_inliner.cpp @@ -121,19 +121,11 @@ void ssa_inlinert::get_summary( int counter, bool error_summ) { - // getting globals at call site - local_SSAt::var_sett cs_globals_in, cs_globals_out; - goto_programt::const_targett loc=n_it->location; - if(forward) - { - SSA.get_globals(loc, cs_globals_in); - SSA.get_globals(loc, cs_globals_out, false); - } - else - { - SSA.get_globals(loc, cs_globals_out); - SSA.get_globals(loc, cs_globals_in, false); - } + //getting globals at call site + local_SSAt::var_sett cs_globals_in, cs_globals_out; + goto_programt::const_targett loc = n_it->location; + SSA.get_globals(loc,cs_globals_in); + SSA.get_globals(loc,cs_globals_out,false); #if 0 std::cout << "cs_globals_in: "; @@ -153,16 +145,7 @@ void ssa_inlinert::get_summary( get_replace_params(SSA,summary.params, n_it, *f_it, bindings, counter); //equalities for globals_in - if(forward) - { - //get_replace_globals_in(summary.globals_in, cs_globals_in, bindings, counter); - get_replace_globals_in(summary.globals_in, *f_it, cs_globals_in, bindings, counter); - } - else - { - //get_replace_globals_in(summary.globals_out, cs_globals_out, bindings, counter); - get_replace_globals_in(summary.globals_out, *f_it, cs_globals_out, bindings, counter); - } + get_replace_globals_in(summary.globals_in,*f_it,cs_globals_in,bindings,counter); // constraints for transformer @@ -195,14 +178,7 @@ void ssa_inlinert::get_summary( transformer)); //equalities for globals out (including unmodified globals) - if(forward){ - //get_replace_globals_out(summary.globals_out,cs_globals_in,cs_globals_out,bindings,counter); get_replace_globals_out(summary.globals_out,*f_it,cs_globals_in,cs_globals_out,bindings,counter); - } - else{ - //get_replace_globals_out(summary.globals_in,cs_globals_out,cs_globals_in,bindings,counter); - get_replace_globals_out(summary.globals_in,*f_it,cs_globals_out,cs_globals_in,bindings,counter); - } } /*******************************************************************\ @@ -735,7 +711,7 @@ void ssa_inlinert::get_replace_globals_out( int counter) { std::string suffix = id2string(funapp_expr.get(ID_suffix)); - + //equalities for globals_out for(summaryt::var_sett::const_iterator it = cs_globals_out.begin(); it != cs_globals_out.end(); it++) @@ -747,7 +723,8 @@ void ssa_inlinert::get_replace_globals_out( symbol_exprt rhs; if(find_corresponding_symbol(*it,globals_out,rhs)) rename(rhs,counter); - else{ + else + { bool found = find_corresponding_symbol(*it,cs_globals_in,rhs); assert(found); rhs.set_identifier(id2string(rhs.get_identifier())+suffix); From 94f5e3c611ba563f82051cebd274b3b7c89b5bd1 Mon Sep 17 00:00:00 2001 From: Peter Schrammel Date: Fri, 13 May 2016 09:58:05 +0100 Subject: [PATCH 17/82] nondet locals only once --- regression/modular/cex7/main.c | 2 +- src/summarizer/summarizer_parse_options.cpp | 3 --- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/regression/modular/cex7/main.c b/regression/modular/cex7/main.c index 309c06dd9..cfa5ab827 100644 --- a/regression/modular/cex7/main.c +++ b/regression/modular/cex7/main.c @@ -7,7 +7,7 @@ int main(int argc, char** argv) while(y<30){ y++; - assert(y<5); + assert(y<3); } return 0; diff --git a/src/summarizer/summarizer_parse_options.cpp b/src/summarizer/summarizer_parse_options.cpp index 7dba7d8e1..1e9608b0b 100644 --- a/src/summarizer/summarizer_parse_options.cpp +++ b/src/summarizer/summarizer_parse_options.cpp @@ -997,9 +997,6 @@ bool summarizer_parse_optionst::process_goto_program( status() << "Constant Propagation" << eom; propagate_constants(goto_model); } - - //explicitly initialize all local variables - nondet_locals(goto_model); #if 1 //TODO: find a better place for that From c6087cc453793e5138f63c1a4e430962d7430be6 Mon Sep 17 00:00:00 2001 From: Peter Schrammel Date: Fri, 13 May 2016 20:49:43 +0100 Subject: [PATCH 18/82] fixed filtering of non-violating assertion instances before running spurious checker; various code clean-ups --- regression/modular/cex7/main.c | 2 +- src/2ls/cover_goals_ext.cpp | 59 +++------ src/ssa/ssa_inliner.cpp | 26 +--- src/summarizer/summarizer_bw_cex_concrete.cpp | 121 ++++++++---------- 4 files changed, 81 insertions(+), 127 deletions(-) diff --git a/regression/modular/cex7/main.c b/regression/modular/cex7/main.c index cfa5ab827..8ab3e91f9 100644 --- a/regression/modular/cex7/main.c +++ b/regression/modular/cex7/main.c @@ -7,7 +7,7 @@ int main(int argc, char** argv) while(y<30){ y++; - assert(y<3); + assert(y<4); } return 0; diff --git a/src/2ls/cover_goals_ext.cpp b/src/2ls/cover_goals_ext.cpp index e4814856c..3465724af 100644 --- a/src/2ls/cover_goals_ext.cpp +++ b/src/2ls/cover_goals_ext.cpp @@ -195,58 +195,35 @@ void cover_goals_extt::assignment() } else { + //filter out assertion instances that are not violated exprt::operandst failed_exprs; for(exprt::operandst::const_iterator c_it = conjunct_expr.operands().begin(); - c_it != conjunct_expr.operands().end(); c_it++) + c_it != conjunct_expr.operands().end(); c_it++) { literalt conjunct_literal = solver.convert(*c_it); - if(solver.l_get(conjunct_literal).is_false()) + if(solver.l_get(conjunct_literal).is_true()) + { +#ifdef DEBUG + std::cout << "failed_expr: " + << from_expr(SSA.ns, "", *c_it) << std::endl; +#endif failed_exprs.push_back(*c_it); + } } solver.pop_context(); //otherwise this would interfere with necessary preconditions - for(unsigned i=0; ifirst].result = summarizer_bw_cex.check(); - if(property_map[it->first].result == + summarizer_bw_cex.summarize(not_exprt(conjunction(failed_exprs))); + property_map[it->first].result = summarizer_bw_cex.check(); + if(property_map[it->first].result == property_checkert::FAIL) + { + if(build_error_trace) { - assert((g_it->cond_expression).id()==ID_not); - exprt conjunct_expr=(g_it->cond_expression).op0(); - - if(conjunct_expr.id()!=ID_and) - { - solver.pop_context(); //otherwise this would interfere with necessary preconditions - summarizer_bw_cex.summarize(g_it->cond_expression); - property_map[it->first].result=summarizer_bw_cex.check(); - solver.new_context(); - } - else - { - exprt::operandst failed_exprs; - for(exprt::operandst::const_iterator c_it= - conjunct_expr.operands().begin(); - c_it!=conjunct_expr.operands().end(); c_it++) - { - literalt conjunct_literal=solver.convert(*c_it); - if(solver.l_get(conjunct_literal).is_false()) - failed_exprs.push_back(*c_it); - } - solver.pop_context(); // otherwise this would interfere with necessary preconditions - for(const auto &failed_expr : failed_exprs) - { - summarizer_bw_cex.summarize( - not_exprt(failed_expr)); - property_map[it->first].result=summarizer_bw_cex.check(); - if(property_map[it->first].result== - property_checkert::FAIL) - break; - } - solver.new_context(); - } + ssa_build_goto_tracet build_goto_trace(SSA,solver.get_solver()); + build_goto_trace(property_map[it->first].error_trace); } + solver.new_context(); + break; else property_map[it->first].result=property_checkert::FAIL; } diff --git a/src/ssa/ssa_inliner.cpp b/src/ssa/ssa_inliner.cpp index f127fddeb..7b7b4236d 100644 --- a/src/ssa/ssa_inliner.cpp +++ b/src/ssa/ssa_inliner.cpp @@ -2,7 +2,7 @@ Module: SSA Inliner -Author: Peter Schrammel +Author: Peter Schrammel, Madhukar Kumar \*******************************************************************/ @@ -80,21 +80,14 @@ void ssa_inlinert::get_bindings( std::cout << std::endl; #endif - // equalities for arguments - // bindings_in.push_back(get_replace_params(SSA.params, *f_it)); - get_replace_params(SSA,fSSA.params, n_it, *f_it,bindings_in,counter); - - // equalities for globals_in - // bindings_in.push_back(get_replace_globals_in(SSA.globals_in, cs_globals_in)); - - // get_replace_globals_in(fSSA.globals_in, cs_globals_in, bindings_in, counter); - get_replace_globals_in(fSSA.globals_in, *f_it, cs_globals_in, bindings_in, counter); + //equalities for arguments + get_replace_params(SSA,fSSA.params,n_it,*f_it,bindings_in,counter); - // equalities for globals out (including unmodified globals) - // bindings_out.push_back(get_replace_globals_out(SSA.globals_out, cs_globals_in, cs_globals_out)); + //equalities for globals_in + get_replace_globals_in(fSSA.globals_in,*f_it,cs_globals_in,bindings_in,counter); - // get_replace_globals_out(fSSA.globals_out, cs_globals_in, cs_globals_out, bindings_out, counter); - get_replace_globals_out(fSSA.globals_out, *f_it, cs_globals_in, cs_globals_out, bindings_out, counter); + //equalities for globals out (including unmodified globals) + get_replace_globals_out(fSSA.globals_out,*f_it,cs_globals_in,cs_globals_out,bindings_out,counter); } @@ -613,8 +606,6 @@ void ssa_inlinert::get_replace_params( exprt::operandst &c, int counter) { - //std::string suffix = id2string(funapp_expr.get(ID_suffix)); - //equalities for arguments local_SSAt::var_listt::const_iterator p_it = params.begin(); for(exprt::operandst::const_iterator it = funapp_expr.arguments().begin(); @@ -660,9 +651,6 @@ void ssa_inlinert::get_replace_params( exprt lhs = *p_it; //copy rename(lhs,counter); c.push_back(equal_exprt(lhs,*it)); - //symbol_exprt sexpr = to_symbol_expr(*it); - //sexpr.set_identifier(id2string(sexpr.get_identifier())+suffix); - //c.push_back(equal_exprt(lhs,sexpr)); } } } diff --git a/src/summarizer/summarizer_bw_cex_concrete.cpp b/src/summarizer/summarizer_bw_cex_concrete.cpp index 4a30ef8d9..373a1ec4a 100644 --- a/src/summarizer/summarizer_bw_cex_concrete.cpp +++ b/src/summarizer/summarizer_bw_cex_concrete.cpp @@ -138,7 +138,7 @@ void summarizer_bw_cex_concretet::compute_summary_rec( exprt postcondition = implies_exprt(end_guard,_postcondition); if(function_name == error_function) { - postcondition = and_exprt(postcondition,not_exprt(error_assertion)); + postcondition = not_exprt(error_assertion); //and_exprt(postcondition,not_exprt(error_assertion)); } summary.bw_postcondition = _postcondition; @@ -197,10 +197,11 @@ void summarizer_bw_cex_concretet::do_summary( // solver #ifdef OPT_2 - incremental_solvert* fresh_solver = incremental_solvert::allocate(SSA.ns, options.get_bool_option("refine")); - //incremental_solvert &solver = ssa_db.get_solver(function_name); - + incremental_solvert* fresh_solver = + incremental_solvert::allocate(SSA.ns, options.get_bool_option("refine")); incremental_solvert &solver = (*fresh_solver); + SSA.unmark_nodes(); + exprt::operandst store; #else incremental_solvert &solver = ssa_db.get_solver(function_name); #endif @@ -230,24 +231,32 @@ void summarizer_bw_cex_concretet::do_summary( //TODO: add nondet variables from callees to summary.nondets - //std::cout << "Assert Summary: " << from_expr(SSA.ns, "", conjunction(assert_postcond)) << "\n\n"; - //std::cout << "Noassert Summary: " << from_expr(SSA.ns, "", conjunction(noassert_postcond)) << "\n\n"; +#ifdef DEBUG + std::cout << "Assert Summary: " << from_expr(SSA.ns, "", conjunction(assert_postcond)) << "\n\n"; + std::cout << "Noassert Summary: " << from_expr(SSA.ns, "", conjunction(noassert_postcond)) << "\n\n"; +#endif c.push_back(not_exprt(conjunction(assert_postcond))); c.push_back(not_exprt(disjunction(noassert_postcond))); -#if 0 +#ifdef DEBUG debug() << "Backward summaries: " << - from_expr(SSA.ns, "", conjunction(c)) << eom; + from_expr(SSA.ns, "", simplify_expr(conjunction(c),SSA.ns)) << eom; #endif #ifdef OPT_12 store << SSA; +#else +#ifdef OPT_2 + store << SSA; #else solver << SSA; #endif - +#endif + +#ifndef OPT_2 solver.new_context(); +#endif // assumptions must hold for(local_SSAt::nodest::const_iterator @@ -257,81 +266,76 @@ void summarizer_bw_cex_concretet::do_summary( for(local_SSAt::nodet::assumptionst::const_iterator a_it = n_it->assumptions.begin(); a_it != n_it->assumptions.end(); - ++a_it){ - - /* -#ifdef OPT_11 - solver << simplify_expr(*a_it, SSA.ns); -#elif OPT_12 - store.push_back(*a_it); -#else - solver << *a_it; -#endif - */ + ++a_it) + { #ifdef OPT_11 solver << simplify_expr(*a_it, SSA.ns); #else #ifdef OPT_12 store.push_back(*a_it); +#else +#ifdef OPT_2 + store.push_back(*a_it); #else solver << *a_it; #endif +#endif #endif } #ifdef OPT_12 store.push_back(SSA.get_enabling_exprs()); +#else +#ifdef OPT_2 + store.push_back(SSA.get_enabling_exprs()); #else solver << SSA.get_enabling_exprs(); #endif - - /* -#ifdef OPT_11 - solver << simplify_expr(conjunction(c), SSA.ns); -#elif OPT_12 - store.push_back(conjunction(c)); -#else - solver << conjunction(c); #endif - */ - + #ifdef OPT_11 solver << simplify_expr(conjunction(c), SSA.ns); #else #ifdef OPT_12 store.push_back(conjunction(c)); +#else +#ifdef OPT_2 + store.push_back(conjunction(c)); #else solver << conjunction(c); #endif +#endif #endif exprt::operandst loophead_selects; loophead_selects = this->get_loophead_selects(SSA,ssa_unwinder.get(function_name),*solver.solver); - - /* -#ifdef OPT_11 - solver << simplify_expr(conjunction(loophead_selects), SSA.ns); -#elif OPT_12 - store.push_back(conjunction(loophead_selects)); -#else - solver << conjunction(loophead_selects); -#endif - */ #ifdef OPT_11 solver << simplify_expr(conjunction(loophead_selects), SSA.ns); #else #ifdef OPT_12 store.push_back(conjunction(loophead_selects)); +#else +#ifdef OPT_2 + store.push_back(conjunction(loophead_selects)); #else solver << conjunction(loophead_selects); #endif #endif +#endif #ifdef OPT_12 +#ifdef DEBUG std::cout << "\n\n\n pushing to the solver in do_summary:" << from_expr(SSA.ns, "", simplify_expr(conjunction(store), SSA.ns)) << "\n\n\n"; +#endif + solver << simplify_expr(conjunction(store), SSA.ns); +#endif +#ifdef OPT_2 +#ifdef DEBUG + std::cout << "\n\n\n pushing to the solver in do_summary:" << from_expr(SSA.ns, "", simplify_expr(conjunction(store), SSA.ns)) << "\n\n\n"; +#endif solver << simplify_expr(conjunction(store), SSA.ns); #endif @@ -339,18 +343,19 @@ void summarizer_bw_cex_concretet::do_summary( solver_calls++; //solve - if(solver() != decision_proceduret::D_SATISFIABLE) + if(solver() == decision_proceduret::D_UNSATISFIABLE) { summary.error_summaries[call_site] = true_exprt(); //TODO: this is likely to be incomplete summary.has_assertion = assertion_flag; +#ifndef OPT_2 solver.pop_context(); +#endif - /* // if the summary is true, print the postcondition and the list of loops in this function // this postcondition is modified, possibly twice, from what is returned by compute_calling_context2 // pc = end_guard => original_pc, and // pc = pc && not(assertion), if this is error function - +#ifdef DEBUG std::cout << "==>>\n"; std::cout << "==>> Summary: true\n"; std::cout << "==>> Postcondition: " << from_expr(SSA.ns, "", postcondition) << "\n"; @@ -363,7 +368,7 @@ void summarizer_bw_cex_concretet::do_summary( } } std::cout << "==>>\n"; - */ +#endif return; } @@ -401,7 +406,9 @@ void summarizer_bw_cex_concretet::do_summary( summary.error_summaries[call_site] = not_exprt(conjunction(var_values)); summary.has_assertion = assertion_flag; +#ifndef OPT_2 solver.pop_context(); +#endif #ifdef OPT_2 delete fresh_solver; @@ -481,8 +488,8 @@ exprt summarizer_bw_cex_concretet::compute_calling_context2( // solver #ifdef OPT_2 - incremental_solvert* fresh_solver = incremental_solvert::allocate(SSA.ns, options.get_bool_option("refine")); - //incremental_solvert &solver = ssa_db.get_solver(function_name); + incremental_solvert* fresh_solver = + incremental_solvert::allocate(SSA.ns, options.get_bool_option("refine")); incremental_solvert &solver = (*fresh_solver); #else incremental_solvert &solver = ssa_db.get_solver(function_name); @@ -529,16 +536,6 @@ exprt summarizer_bw_cex_concretet::compute_calling_context2( solver << SSA.get_enabling_exprs(); #endif - /* -#ifdef OPT_11 - solver << simplify_expr(conjunction(c), SSA.ns); -#elif OPT_12 - store.push_back(conjunction(c)); -#else - solver << conjunction(c); -#endif - */ - #ifdef OPT_11 solver << simplify_expr(conjunction(c), SSA.ns); #else @@ -552,16 +549,6 @@ exprt summarizer_bw_cex_concretet::compute_calling_context2( exprt::operandst loophead_selects; loophead_selects = this->get_loophead_selects(SSA,ssa_unwinder.get(function_name),*solver.solver); - /* -#ifdef OPT_11 - solver << simplify_expr(conjunction(loophead_selects), SSA.ns); -#elif OPT_12 - store.push_back(conjunction(loophead_selects)); -#else - solver << conjunction(loophead_selects); -#endif - */ - #ifdef OPT_11 solver << simplify_expr(conjunction(loophead_selects), SSA.ns); #else @@ -573,7 +560,9 @@ exprt summarizer_bw_cex_concretet::compute_calling_context2( #endif #ifdef OPT_12 +#ifdef DEBUG std::cout << "\n\n\n pushing to the solver in compute_calling_context2:" << from_expr(SSA.ns, "", conjunction(store)) << "\n\n\n"; +#endif solver << simplify_expr(conjunction(store), SSA.ns); #endif From 22b5caa981427c3f07de206f0373430cac046153 Mon Sep 17 00:00:00 2001 From: Kumar Madhukar Date: Mon, 16 May 2016 13:23:56 +0530 Subject: [PATCH 19/82] modified loop-specific unwinder to iterate over all loops --- src/ssa/ssa_unwinder.cpp | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/src/ssa/ssa_unwinder.cpp b/src/ssa/ssa_unwinder.cpp index bbdb78392..c09365858 100644 --- a/src/ssa/ssa_unwinder.cpp +++ b/src/ssa/ssa_unwinder.cpp @@ -288,15 +288,25 @@ void ssa_local_unwindert::unwind_loop_at_location(unsigned loc, unsigned k) SSA.current_unwinding=k; //TODO: just for exploratory integration, must go away //recursively unwind everything SSA.current_unwindings.clear(); - - loopt &loop=loops[loc]; - - if(loop.is_root){ - unwind(loop,k,false); //recursive + + for(loop_mapt::iterator it = loops.begin(); it != loops.end(); ++it){ + if(!it->second.is_root) + continue; + + if(it->first == loc) + unwind(it->second,k,false); //recursive + else + unwind(it->second,it->second.current_unwinding,false); //recursive + assert(SSA.current_unwindings.empty()); } - - loop.current_unwinding=k; + + //update current unwinding + for(loop_mapt::iterator it = loops.begin(); it != loops.end(); ++it) + { + if(it->first == loc) + it->second.current_unwinding=k; + } return; } From a16b3500832f20c97b5efa1eaa8dfd62b7d74f7c Mon Sep 17 00:00:00 2001 From: Kumar Madhukar Date: Fri, 20 May 2016 12:18:21 +0530 Subject: [PATCH 20/82] selective unwinding code --- src/ssa/local_ssa.cpp | 4 ++ src/ssa/local_ssa.h | 2 + src/ssa/ssa_unwinder.cpp | 55 +++++++++++++++++++++++---- src/ssa/ssa_unwinder.h | 4 +- src/summarizer/summary_checker_ai.cpp | 4 +- 5 files changed, 58 insertions(+), 11 deletions(-) diff --git a/src/ssa/local_ssa.cpp b/src/ssa/local_ssa.cpp index 70256dabe..539aa06eb 100644 --- a/src/ssa/local_ssa.cpp +++ b/src/ssa/local_ssa.cpp @@ -1836,6 +1836,7 @@ Function: local_SSAt::has_function_calls bool local_SSAt::has_function_calls() const { + /* bool found=false; for(local_SSAt::nodest::const_iterator n_it=nodes.begin(); n_it!=nodes.end(); n_it++) @@ -1847,4 +1848,7 @@ bool local_SSAt::has_function_calls() const } } return found; + */ + + return combined_enabling_expr; } diff --git a/src/ssa/local_ssa.h b/src/ssa/local_ssa.h index 3b2950d7c..4c84699e6 100644 --- a/src/ssa/local_ssa.h +++ b/src/ssa/local_ssa.h @@ -121,6 +121,8 @@ class local_SSAt // for incremental unwinding std::list enabling_exprs; + + exprt combined_enabling_expr; // combined enabling expr for loop-specific unwindings exprt get_enabling_exprs() const; // function entry and exit variables diff --git a/src/ssa/ssa_unwinder.cpp b/src/ssa/ssa_unwinder.cpp index c09365858..690807d8a 100644 --- a/src/ssa/ssa_unwinder.cpp +++ b/src/ssa/ssa_unwinder.cpp @@ -281,10 +281,33 @@ void ssa_local_unwindert::unwind_loop_at_location(unsigned loc, unsigned k) if(SSA.current_unwinding>=(long)k) return; - current_enabling_expr= - symbol_exprt("unwind::"+id2string(fname)+"::enable"+i2string(k), + loopt &loop = loops[loc]; + loop.loop_enabling_expr_current = + symbol_exprt("unwind::"+id2string(fname)+"loc::"+i2string(loc)+"::enable"+i2string(k), bool_typet()); - SSA.enabling_exprs.push_back(current_enabling_expr); + + loop.loop_enabling_exprs.push_back(loop.loop_enabling_expr_current); + exprt::operandst ssa_current_enabling_expr; + for(loop_mapt::iterator it = loops.begin(); it != loops.end(); ++it){ + exprt::operandst result; + for(exprt::operandst::iterator e_it = ((it->second).loop_enabling_exprs).begin(); + e_it != ((it->second).loop_enabling_exprs).end(); e_it++){ + exprt::operandst::iterator lh = e_it; lh++; + if(lh != ((it->second).loop_enabling_exprs).end()) result.push_back(not_exprt(*e_it)); + else result.push_back(*e_it); + } + ssa_current_enabling_expr.push_back(conjunction(result)); + } + + SSA.combined_enabling_expr = conjunction(ssa_current_enabling_expr); + + + //current_enabling_expr = + // symbol_exprt("unwind::"+id2string(fname)+"::enable"+i2string(k), + // bool_typet()); + //SSA.enabling_exprs.push_back(current_enabling_expr); + + SSA.current_unwinding=k; //TODO: just for exploratory integration, must go away //recursively unwind everything SSA.current_unwindings.clear(); @@ -294,9 +317,9 @@ void ssa_local_unwindert::unwind_loop_at_location(unsigned loc, unsigned k) continue; if(it->first == loc) - unwind(it->second,k,false); //recursive + unwind(it->second,k,false,false); //recursive else - unwind(it->second,it->second.current_unwinding,false); //recursive + unwind(it->second,it->second.current_unwinding,false,true,k,loc); //recursive assert(SSA.current_unwindings.empty()); } @@ -342,7 +365,7 @@ void ssa_local_unwindert::unwind(unsigned k) { if(!it->second.is_root) continue; - unwind(it->second, k, false); // recursive +(??) unwind(it->second,k,false); //recursive assert(SSA.current_unwindings.empty()); } // update current unwinding @@ -365,7 +388,8 @@ Function: ssa_local_unwindert::unwind \*******************************************************************/ -void ssa_local_unwindert::unwind(loopt &loop, unsigned k, bool is_new_parent) +void ssa_local_unwindert::unwind(loopt &loop, unsigned k, bool is_new_parent, + bool propagate, unsigned prop_unwind, unsigned prop_loc) { odometert context=SSA.current_unwindings; #ifdef DEBUG @@ -428,7 +452,22 @@ void ssa_local_unwindert::unwind(loopt &loop, unsigned k, bool is_new_parent) #ifdef DEBUG std::cout << i << ">" << loop.current_unwinding << std::endl; #endif - unwind(loops[l], k, i>loop.current_unwinding || is_new_parent); + if(propagate == true){ + // if this child loop is the desired loop then unwind k and do not propagate + // else unwind loop.current_unwinding and propagate + if(*l_it == prop_loc){ + unwind(loops[*l_it],k,i>loop.current_unwinding || + is_new_parent,false); + } + else{ + unwind(loops[*l_it],loops[*l_it].current_unwinding,i>loop.current_unwinding || + is_new_parent,true,prop_unwind,prop_loc); + } + } + else{ + unwind(loops[*l_it],loops[*l_it].current_unwinding, + i>loop.current_unwinding || is_new_parent,false); + } } SSA.increment_unwindings(0); } diff --git a/src/ssa/ssa_unwinder.h b/src/ssa/ssa_unwinder.h index 6119d821a..454f7f2fd 100644 --- a/src/ssa/ssa_unwinder.h +++ b/src/ssa/ssa_unwinder.h @@ -77,6 +77,8 @@ class ssa_local_unwindert long current_unwinding; // to have an enabling_expr and current_unwindings (odometert) + exprt::operandst loop_enabling_exprs; + exprt loop_enabling_expr_current; typedef std::map exit_mapt; exit_mapt exit_map; @@ -110,7 +112,7 @@ class ssa_local_unwindert void build_pre_post_map(); void build_exit_conditions(); - void unwind(loopt &loop, unsigned k, bool is_new_parent); + void unwind(loopt &loop, unsigned k, bool is_new_parent, bool propagate = false, unsigned prop_unwind = 0, unsigned prop_loc = 0); exprt get_continuation_condition(const loopt& loop) const; void loop_continuation_conditions( diff --git a/src/summarizer/summary_checker_ai.cpp b/src/summarizer/summary_checker_ai.cpp index 4ad5ab3b1..bd09d187c 100644 --- a/src/summarizer/summary_checker_ai.cpp +++ b/src/summarizer/summary_checker_ai.cpp @@ -44,7 +44,7 @@ property_checkert::resultt summary_checker_ait::operator()( /*********************************************************************************/ /**************** code to test the loop-specific unwind function *****************/ - /* + /**/ if(unwind > 0){ forall_goto_functions(f_it, goto_model.goto_functions){ if(!f_it->second.body_available()) continue; @@ -84,7 +84,7 @@ property_checkert::resultt summary_checker_ait::operator()( } } - */ + /**/ /*********************************************************************************/ irep_idt entry_function = goto_model.goto_functions.entry_point(); From 1c4fca17a5ff44e214adbd3de1de1892aa03c7bf Mon Sep 17 00:00:00 2001 From: Peter Schrammel Date: Fri, 20 May 2016 14:54:21 +0100 Subject: [PATCH 21/82] output unsat core for spurious cex, uses incremental solver debug facilities at the moment --- regression/modular/Makefile | 2 +- src/summarizer/summarizer_bw_cex_complete.cpp | 15 +++++++++++++++ src/summarizer/summarizer_bw_cex_concrete.cpp | 8 ++++---- src/summarizer/summary_checker_base.cpp | 3 +++ 4 files changed, 23 insertions(+), 5 deletions(-) diff --git a/regression/modular/Makefile b/regression/modular/Makefile index 2a3b5cb15..c26b769b2 100644 --- a/regression/modular/Makefile +++ b/regression/modular/Makefile @@ -1,6 +1,6 @@ default: tests.log -FLAGS = --verbosity 10 --spurious-check complete +FLAGS = --verbosity 10 --spurious-check concrete test: @../test.pl -c "../../../src/summarizer/2ls $(FLAGS)" diff --git a/src/summarizer/summarizer_bw_cex_complete.cpp b/src/summarizer/summarizer_bw_cex_complete.cpp index cad7b61de..a8d2db0dd 100644 --- a/src/summarizer/summarizer_bw_cex_complete.cpp +++ b/src/summarizer/summarizer_bw_cex_complete.cpp @@ -26,6 +26,8 @@ Author: Peter Schrammel #include "summarizer_bw_cex_complete.h" +#define SHOW_UNSAT_CORE + /*******************************************************************\ Function: summarizer_bw_cex_completet::summarize() @@ -494,6 +496,19 @@ property_checkert::resultt summarizer_bw_cex_completet::check() //std::cout << "Solver <-- renamed info ~ SAT\n"; return property_checkert::FAIL; } +#ifdef SHOW_UNSAT_CORE + else + { + for(unsigned i=0; iis_in_conflict(solver.formula[i])) + debug() << "is_in_conflict: " << solver.formula[i] << eom; + else + debug() << "not_in_conflict: " << solver.formula[i] << eom; + } + } +#endif + //std::cout << "Solver <-- renamed info ~ UNSAT\n"; return property_checkert::UNKNOWN; } diff --git a/src/summarizer/summarizer_bw_cex_concrete.cpp b/src/summarizer/summarizer_bw_cex_concrete.cpp index 373a1ec4a..87c27ee72 100644 --- a/src/summarizer/summarizer_bw_cex_concrete.cpp +++ b/src/summarizer/summarizer_bw_cex_concrete.cpp @@ -138,7 +138,7 @@ void summarizer_bw_cex_concretet::compute_summary_rec( exprt postcondition = implies_exprt(end_guard,_postcondition); if(function_name == error_function) { - postcondition = not_exprt(error_assertion); //and_exprt(postcondition,not_exprt(error_assertion)); + postcondition = and_exprt(postcondition,not_exprt(error_assertion)); } summary.bw_postcondition = _postcondition; @@ -327,8 +327,8 @@ void summarizer_bw_cex_concretet::do_summary( #endif #ifdef OPT_12 -#ifdef DEBUG - std::cout << "\n\n\n pushing to the solver in do_summary:" << from_expr(SSA.ns, "", simplify_expr(conjunction(store), SSA.ns)) << "\n\n\n"; +#if 1 + std::cout << "\n\n\n pushing to the solver in do_summary:" << from_expr(SSA.ns, "", conjunction(store)) << "\n\n\n"; #endif solver << simplify_expr(conjunction(store), SSA.ns); #endif @@ -560,7 +560,7 @@ exprt summarizer_bw_cex_concretet::compute_calling_context2( #endif #ifdef OPT_12 -#ifdef DEBUG +#if 1 std::cout << "\n\n\n pushing to the solver in compute_calling_context2:" << from_expr(SSA.ns, "", conjunction(store)) << "\n\n\n"; #endif solver << simplify_expr(conjunction(store), SSA.ns); diff --git a/src/summarizer/summary_checker_base.cpp b/src/summarizer/summary_checker_base.cpp index 224f0be4d..83c6c13ca 100644 --- a/src/summarizer/summary_checker_base.cpp +++ b/src/summarizer/summary_checker_base.cpp @@ -321,6 +321,9 @@ void summary_checker_baset::check_properties( incremental_solvert* cex_complete_solver = incremental_solvert::allocate(SSA.ns, options.get_bool_option("refine")); +#if 1 + cex_complete_solver->set_message_handler(get_message_handler()); +#endif if(options.get_bool_option("inline") || options.get_option("spurious-check") == "concrete") { From a7fecc7e07f794f2f742f321c36d3de8b6826c32 Mon Sep 17 00:00:00 2001 From: Peter Schrammel Date: Mon, 23 May 2016 09:40:01 +0100 Subject: [PATCH 22/82] Srivas' examples --- regression/modular/Makefile | 2 +- regression/modular/kind1/main.c | 22 ++++++++++++++++++++ regression/modular/kind1/test.desc | 6 ++++++ regression/modular/kind2/main.c | 28 +++++++++++++++++++++++++ regression/modular/kind2/test.desc | 6 ++++++ regression/modular/kind3/main.c | 26 +++++++++++++++++++++++ regression/modular/kind3/test.desc | 6 ++++++ regression/modular/kind4/main.c | 33 ++++++++++++++++++++++++++++++ regression/modular/kind4/test.desc | 6 ++++++ 9 files changed, 134 insertions(+), 1 deletion(-) create mode 100644 regression/modular/kind1/main.c create mode 100644 regression/modular/kind1/test.desc create mode 100644 regression/modular/kind2/main.c create mode 100644 regression/modular/kind2/test.desc create mode 100644 regression/modular/kind3/main.c create mode 100644 regression/modular/kind3/test.desc create mode 100644 regression/modular/kind4/main.c create mode 100644 regression/modular/kind4/test.desc diff --git a/regression/modular/Makefile b/regression/modular/Makefile index c26b769b2..2a3b5cb15 100644 --- a/regression/modular/Makefile +++ b/regression/modular/Makefile @@ -1,6 +1,6 @@ default: tests.log -FLAGS = --verbosity 10 --spurious-check concrete +FLAGS = --verbosity 10 --spurious-check complete test: @../test.pl -c "../../../src/summarizer/2ls $(FLAGS)" diff --git a/regression/modular/kind1/main.c b/regression/modular/kind1/main.c new file mode 100644 index 000000000..679c7c8be --- /dev/null +++ b/regression/modular/kind1/main.c @@ -0,0 +1,22 @@ +#include + +//Simple K-Induction safe example for K=4 +//No procedure calls; loop inv required: a != b != c + +int main(int argc, char** argv) +{ + unsigned int limit; + int a,b,c,sc, i = 0; + __CPROVER_assume(a != b && b != c && c != a); + + while (i < limit) + { + assert(a != b); + sc = c; c = b; b = a; a = sc; + //a, b, c = c, a, b; parallel assignment; + i++; + } + + return 0; +} + diff --git a/regression/modular/kind1/test.desc b/regression/modular/kind1/test.desc new file mode 100644 index 000000000..630457914 --- /dev/null +++ b/regression/modular/kind1/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--havoc --k-induction +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ diff --git a/regression/modular/kind2/main.c b/regression/modular/kind2/main.c new file mode 100644 index 000000000..0925661c3 --- /dev/null +++ b/regression/modular/kind2/main.c @@ -0,0 +1,28 @@ +#include + + +int foo(int a, int b, int c) +{ + return a+1; +} + +// This main illustrates K-induction with proc call +// Safety can be shown for K = 4 after using summary TRUE for foo +// Only unwinding loop is required +int main(int argc, char** argv) +{ + unsigned int limit; + int a,b,c,sc, i = 0; + __CPROVER_assume(a != b && b != c && c != a); + + while (i < limit) { + assert(a != b); + sc = c; c = b; b = a; a = sc; + //a, b, c = c, a, b; parallel assignment; + if (b == c) a = foo(a,b,c); + i++; + } + + return 0; +} + diff --git a/regression/modular/kind2/test.desc b/regression/modular/kind2/test.desc new file mode 100644 index 000000000..630457914 --- /dev/null +++ b/regression/modular/kind2/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--havoc --k-induction +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ diff --git a/regression/modular/kind3/main.c b/regression/modular/kind3/main.c new file mode 100644 index 000000000..813307dda --- /dev/null +++ b/regression/modular/kind3/main.c @@ -0,0 +1,26 @@ +#include + + +int bar(int a, int b, int c) +{ + return c; +} + +//This main illustrates need for refinement of bar +//based on spurious CEX +int main(int argc, char** argv) +{ + unsigned int limit; + int a,b,c,sc, i = 0; + __CPROVER_assume(a != b && b != c && c != a); + + while (i < limit) { + assert(a != b); + sc = c; c = b; b = a; a = bar(a,b,sc); + //a, b, c = bar(a,b,c), a, b; parallel assignment; + i++; + } + + return 0; +} + diff --git a/regression/modular/kind3/test.desc b/regression/modular/kind3/test.desc new file mode 100644 index 000000000..630457914 --- /dev/null +++ b/regression/modular/kind3/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--havoc --k-induction +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ diff --git a/regression/modular/kind4/main.c b/regression/modular/kind4/main.c new file mode 100644 index 000000000..f8dca89ae --- /dev/null +++ b/regression/modular/kind4/main.c @@ -0,0 +1,33 @@ +#include + +int foo(int a, int b, int c) +{ + return a+1; +} + +int bar(int a, int b, int c) +{ + return c; +} + +// This main illustrates K-induction with proc call +// Safety can be shown for K = 4 after using summary TRUE for foo +// Only unwinding loop is required +int main(int argc, char** argv) +{ + unsigned int limit; + int a,b,c,sc, i = 0; + __CPROVER_assume(a != b && b != c && c != a); + + while (i < limit) { + assert(a != b); + sc = c; c = b; b = a; a = sc; + //a, b, c = c, a, b; parallel assignment; + if (b == c) a = foo(a,b,c); + else c = bar(a,b,c); + i++; + } + + return 0; +} + diff --git a/regression/modular/kind4/test.desc b/regression/modular/kind4/test.desc new file mode 100644 index 000000000..630457914 --- /dev/null +++ b/regression/modular/kind4/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--havoc --k-induction +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ From f7eac117eecb5566dc3967961aaae470d5d5e006 Mon Sep 17 00:00:00 2001 From: Peter Schrammel Date: Mon, 23 May 2016 10:38:44 +0100 Subject: [PATCH 23/82] moved assertion into bar() --- regression/modular/kind4/main.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/regression/modular/kind4/main.c b/regression/modular/kind4/main.c index f8dca89ae..5b4106e35 100644 --- a/regression/modular/kind4/main.c +++ b/regression/modular/kind4/main.c @@ -1,5 +1,6 @@ #include + int foo(int a, int b, int c) { return a+1; @@ -7,9 +8,11 @@ int foo(int a, int b, int c) int bar(int a, int b, int c) { + assert(a != b); return c; } + // This main illustrates K-induction with proc call // Safety can be shown for K = 4 after using summary TRUE for foo // Only unwinding loop is required @@ -20,11 +23,12 @@ int main(int argc, char** argv) __CPROVER_assume(a != b && b != c && c != a); while (i < limit) { - assert(a != b); +// assert(a != b); sc = c; c = b; b = a; a = sc; //a, b, c = c, a, b; parallel assignment; if (b == c) a = foo(a,b,c); - else c = bar(a,b,c); + //else //TODO: investigate why k-ind doesn't terminate if the call to bar is here + c = bar(a,b,c); i++; } From 6d042016857e4193533cb494417eca98999c7aaf Mon Sep 17 00:00:00 2001 From: Peter Schrammel Date: Mon, 23 May 2016 16:19:47 +0100 Subject: [PATCH 24/82] recompute dependency graphs after unwinding --- src/summarizer/summary_checker_ai.cpp | 27 ++++------------- src/summarizer/summary_checker_base.cpp | 39 +++++++++++++++++++++++++ src/summarizer/summary_checker_base.h | 1 + src/summarizer/summary_checker_bmc.cpp | 11 +++++++ src/summarizer/summary_checker_kind.cpp | 10 +++++++ 5 files changed, 66 insertions(+), 22 deletions(-) diff --git a/src/summarizer/summary_checker_ai.cpp b/src/summarizer/summary_checker_ai.cpp index bd09d187c..f1bf9b8ba 100644 --- a/src/summarizer/summary_checker_ai.cpp +++ b/src/summarizer/summary_checker_ai.cpp @@ -91,29 +91,12 @@ property_checkert::resultt summary_checker_ait::operator()( if(options.get_bool_option("unit-check")) entry_function = ""; - if(!(options.get_bool_option("inline"))){ + if(!(options.get_bool_option("inline"))) + { if((options.get_option("spurious-check") != "concrete") && - (options.get_option("spurious-check") != "abstract")){ - // compute dependency graph for all the functions - forall_goto_functions(f_it, goto_model.goto_functions) - { - if(!f_it->second.body_available()) continue; - if(has_prefix(id2string(f_it->first),TEMPLATE_DECL)) continue; - - status() << "Computing dependency graph of " << f_it->first << messaget::eom; - - //ssa_db.depgraph_create(f_it->first, ns, ssa_inliner); - - if(entry_function == f_it->first) - ssa_db.depgraph_create(f_it->first, ns, ssa_inliner, true); - else - ssa_db.depgraph_create(f_it->first, ns, ssa_inliner, false); // change to true if all functions are to be treated equal - - ssa_dependency_grapht &ssa_depgraph = ssa_db.get_depgraph(f_it->first); - ssa_depgraph.output(debug()); debug() << eom; - std::cout << "output SSA for function: " << f_it->first << "\n"; - ssa_db.get(f_it->first).output_verbose(std::cout); - } + (options.get_option("spurious-check") != "abstract")) + { + SSA_dependency_graphs(goto_model, ns); } } diff --git a/src/summarizer/summary_checker_base.cpp b/src/summarizer/summary_checker_base.cpp index 83c6c13ca..8eb4a924a 100644 --- a/src/summarizer/summary_checker_base.cpp +++ b/src/summarizer/summary_checker_base.cpp @@ -45,6 +45,45 @@ Author: Peter Schrammel #include "summarizer_fw_contexts.h" #endif + +/*******************************************************************\ + +Function: summary_checker_baset::SSA_dependency_graphs + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +void summary_checker_baset::SSA_dependency_graphs( + const goto_modelt &goto_model, + const namespacet &ns) +{ + // compute dependency graph for all the functions + forall_goto_functions(f_it, goto_model.goto_functions) + { + if(!f_it->second.body_available()) continue; + if(has_prefix(id2string(f_it->first),TEMPLATE_DECL)) continue; + + status() << "Computing dependency graph of " << f_it->first << messaget::eom; + + //ssa_db.depgraph_create(f_it->first, ns, ssa_inliner); + + if(entry_function == f_it->first) + ssa_db.depgraph_create(f_it->first, ns, ssa_inliner, true); + else + ssa_db.depgraph_create(f_it->first, ns, ssa_inliner, false); // change to true if all functions are to be treated equal + + ssa_dependency_grapht &ssa_depgraph = ssa_db.get_depgraph(f_it->first); + ssa_depgraph.output(debug()); debug() << eom; + std::cout << "output SSA for function: " << f_it->first << "\n"; + ssa_db.get(f_it->first).output_verbose(std::cout); + } +} + /*******************************************************************\ Function: summary_checker_baset::SSA_functions diff --git a/src/summarizer/summary_checker_base.h b/src/summarizer/summary_checker_base.h index d2419b7ec..1c907891a 100644 --- a/src/summarizer/summary_checker_base.h +++ b/src/summarizer/summary_checker_base.h @@ -72,6 +72,7 @@ class summary_checker_baset:public property_checkert const local_SSAt::nodet::assertionst::const_iterator &); void SSA_functions(const goto_modelt &, const namespacet &ns); + void SSA_dependency_graphs(const goto_modelt &, const namespacet &ns); void summarize(const goto_modelt &, bool forward=true, bool termination=false); diff --git a/src/summarizer/summary_checker_bmc.cpp b/src/summarizer/summary_checker_bmc.cpp index c3649d534..1428f7acc 100644 --- a/src/summarizer/summary_checker_bmc.cpp +++ b/src/summarizer/summary_checker_bmc.cpp @@ -43,6 +43,17 @@ property_checkert::resultt summary_checker_bmct::operator()( status() << "Unwinding (k=" << unwind << ")" << messaget::eom; summary_db.mark_recompute_all(); ssa_unwinder.unwind_all(unwind+1); + + //dependency graphs + if(!(options.get_bool_option("inline"))) + { + if((options.get_option("spurious-check")!="concrete") && + (options.get_option("spurious-check")!="abstract")) + { + SSA_dependency_graphs(goto_model, ns); + } + } + std::set seen_function_calls; result = check_properties(entry_function, entry_function, seen_function_calls); if(result == property_checkert::PASS) diff --git a/src/summarizer/summary_checker_kind.cpp b/src/summarizer/summary_checker_kind.cpp index 2284d2eb2..487b2c415 100644 --- a/src/summarizer/summary_checker_kind.cpp +++ b/src/summarizer/summary_checker_kind.cpp @@ -44,6 +44,16 @@ property_checkert::resultt summary_checker_kindt::operator()( status() << "Unwinding (k=" << unwind << ")" << eom; summary_db.mark_recompute_all(); //TODO: recompute only functions with loops ssa_unwinder.unwind_all(unwind+1); + + //dependency graphs + if(!(options.get_bool_option("inline"))) + { + if((options.get_option("spurious-check")!="concrete") && + (options.get_option("spurious-check")!="abstract")) + { + SSA_dependency_graphs(goto_model, ns); + } + } std::set seen_function_calls; result = check_properties(entry_function, entry_function, seen_function_calls); From 4644a57a2e71701d61fc5a410a411e6e65408d6a Mon Sep 17 00:00:00 2001 From: Peter Schrammel Date: Mon, 23 May 2016 16:49:45 +0100 Subject: [PATCH 25/82] fixed renaming of nondets on inlining --- src/ssa/ssa_inliner.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/ssa/ssa_inliner.cpp b/src/ssa/ssa_inliner.cpp index 7b7b4236d..b2c2da908 100644 --- a/src/ssa/ssa_inliner.cpp +++ b/src/ssa/ssa_inliner.cpp @@ -837,10 +837,9 @@ Function: ssa_inlinert::rename void ssa_inlinert::rename(exprt &expr, int counter) { - if(expr.id()==ID_symbol) + if(expr.id()==ID_symbol || expr.id()==ID_nondet_symbol) { - symbol_exprt &sexpr = to_symbol_expr(expr); - std::string id_str = id2string(sexpr.get_identifier()); + std::string id_str = id2string(expr.get(ID_identifier)); irep_idt id; if(id_str.find('@') != std::string::npos) @@ -848,7 +847,7 @@ void ssa_inlinert::rename(exprt &expr, int counter) else id = id_str+"@"+i2string(counter); - sexpr.set_identifier(id); + expr.set(ID_identifier,id); } for(exprt::operandst::iterator it = expr.operands().begin(); it != expr.operands().end(); it++) From 29857fe798e0273f28c7b64ae88cc4913aa31940 Mon Sep 17 00:00:00 2001 From: Peter Schrammel Date: Mon, 23 May 2016 16:55:27 +0100 Subject: [PATCH 26/82] propagate nondets in error summaries up to entry point --- src/summarizer/summarizer_bw_cex_ai.cpp | 8 +++++++- src/summarizer/summarizer_bw_cex_concrete.cpp | 8 +++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/summarizer/summarizer_bw_cex_ai.cpp b/src/summarizer/summarizer_bw_cex_ai.cpp index 785456a1c..2d7ec6dec 100644 --- a/src/summarizer/summarizer_bw_cex_ai.cpp +++ b/src/summarizer/summarizer_bw_cex_ai.cpp @@ -239,7 +239,13 @@ void summarizer_bw_cex_ait::do_summary(const function_namet &function_name, assert_postcond.push_back(postcondition); //context - //TODO: add nondet variables from callees to summary.nondets + //add nondet variables from callees to summary.nondets + std::set summary_vars; + find_symbols(conjunction(assert_postcond),summary_vars); + for(std::set::const_iterator it = summary_vars.begin(); + it != summary_vars.end(); ++it) + if(it->id()==ID_nondet_symbol) + summary.nondets.insert(*it); // assumptions must hold for(local_SSAt::nodest::const_iterator diff --git a/src/summarizer/summarizer_bw_cex_concrete.cpp b/src/summarizer/summarizer_bw_cex_concrete.cpp index 87c27ee72..19ecbd3b7 100644 --- a/src/summarizer/summarizer_bw_cex_concrete.cpp +++ b/src/summarizer/summarizer_bw_cex_concrete.cpp @@ -229,7 +229,13 @@ void summarizer_bw_cex_concretet::do_summary( assertion_flag = ssa_inliner.get_summaries(SSA,call_site,false,assert_postcond,noassert_postcond,c); //backward summaries assert_postcond.push_back(postcondition); //context - //TODO: add nondet variables from callees to summary.nondets + //add nondet variables from callees to summary.nondets + std::set summary_vars; + find_symbols(conjunction(assert_postcond),summary_vars); + for(std::set::const_iterator it = summary_vars.begin(); + it != summary_vars.end(); ++it) + if(it->id()==ID_nondet_symbol) + summary.nondets.insert(*it); #ifdef DEBUG std::cout << "Assert Summary: " << from_expr(SSA.ns, "", conjunction(assert_postcond)) << "\n\n"; From 1d7192bfb9cbae3356b50a55675eeca579c5ffd9 Mon Sep 17 00:00:00 2001 From: Peter Schrammel Date: Mon, 23 May 2016 17:35:27 +0100 Subject: [PATCH 27/82] fixed use of ssa_expr in trace output --- regression/modular/kind5/main.c | 18 ++++++++++++++++++ regression/modular/kind5/test.desc | 6 ++++++ 2 files changed, 24 insertions(+) create mode 100644 regression/modular/kind5/main.c create mode 100644 regression/modular/kind5/test.desc diff --git a/regression/modular/kind5/main.c b/regression/modular/kind5/main.c new file mode 100644 index 000000000..6f6d29b27 --- /dev/null +++ b/regression/modular/kind5/main.c @@ -0,0 +1,18 @@ +#include + +int main(int argc, char** argv) +{ + unsigned int limit; + int a,b,sc, i = 0; + __CPROVER_assume(a != b); + + while (i < limit) + { + assert(a != b); + sc = b; b = a; a = sc; + i++; + } + + return 0; +} + diff --git a/regression/modular/kind5/test.desc b/regression/modular/kind5/test.desc new file mode 100644 index 000000000..630457914 --- /dev/null +++ b/regression/modular/kind5/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--havoc --k-induction +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ From 23ac3cc3a1aee8c32f87ba4d1cc4f7d87fe0a4c3 Mon Sep 17 00:00:00 2001 From: Kumar Madhukar Date: Tue, 24 May 2016 19:20:34 +0530 Subject: [PATCH 28/82] minor bug fixes --- src/ssa/local_ssa.cpp | 15 +++++++- src/ssa/local_ssa.h | 2 +- src/summarizer/summarizer_bw_cex_concrete.cpp | 38 ++++++++++--------- src/summarizer/summary_checker_base.cpp | 1 - 4 files changed, 34 insertions(+), 22 deletions(-) diff --git a/src/ssa/local_ssa.cpp b/src/ssa/local_ssa.cpp index 539aa06eb..78eea63d7 100644 --- a/src/ssa/local_ssa.cpp +++ b/src/ssa/local_ssa.cpp @@ -19,6 +19,9 @@ Author: Daniel Kroening, kroening@kroening.com #include #include +#include + + #include #include "local_ssa.h" @@ -1849,6 +1852,14 @@ bool local_SSAt::has_function_calls() const } return found; */ - - return combined_enabling_expr; + + + if(combined_enabling_expr.is_not_nil()){ + std::cout << "combined enabling expr:" << from_expr(ns, "", combined_enabling_expr) << "\n"; + return combined_enabling_expr; + } + else{ + std::cout << "combined enabling expr is nil; returning true\n"; + return true_exprt(); + } } diff --git a/src/ssa/local_ssa.h b/src/ssa/local_ssa.h index 4c84699e6..9fd429725 100644 --- a/src/ssa/local_ssa.h +++ b/src/ssa/local_ssa.h @@ -122,7 +122,7 @@ class local_SSAt // for incremental unwinding std::list enabling_exprs; - exprt combined_enabling_expr; // combined enabling expr for loop-specific unwindings + exprt combined_enabling_expr = true_exprt(); // combined enabling expr for loop-specific unwindings exprt get_enabling_exprs() const; // function entry and exit variables diff --git a/src/summarizer/summarizer_bw_cex_concrete.cpp b/src/summarizer/summarizer_bw_cex_concrete.cpp index 19ecbd3b7..6d1099bc0 100644 --- a/src/summarizer/summarizer_bw_cex_concrete.cpp +++ b/src/summarizer/summarizer_bw_cex_concrete.cpp @@ -357,24 +357,26 @@ void summarizer_bw_cex_concretet::do_summary( solver.pop_context(); #endif - // if the summary is true, print the postcondition and the list of loops in this function - // this postcondition is modified, possibly twice, from what is returned by compute_calling_context2 - // pc = end_guard => original_pc, and - // pc = pc && not(assertion), if this is error function -#ifdef DEBUG - std::cout << "==>>\n"; - std::cout << "==>> Summary: true\n"; - std::cout << "==>> Postcondition: " << from_expr(SSA.ns, "", postcondition) << "\n"; - std::cout << "==>> Function: " << function_name << "\n"; - std::cout << "==>> Loophead selects: " << from_expr(SSA.ns, "", conjunction(loophead_selects)) << "\n"; - for(local_SSAt::nodest::const_iterator n_it = SSA.nodes.begin(); - n_it != SSA.nodes.end(); n_it++){ - if(n_it->loophead!=SSA.nodes.end()){ - std::cout << "==>> Loop found: " << n_it->loophead->location->location_number << "\n"; - } - } - std::cout << "==>>\n"; -#endif +(??)#ifdef DEBUG +(??) /* +(??) // if the summary is true, print the postcondition and the list of loops in this function +(??) // this postcondition is modified, possibly twice, from what is returned by compute_calling_context2 +(??) // pc = end_guard => original_pc, and +(??) // pc = pc && not(assertion), if this is error function +(??) std::cout << "==>>\n"; +(??) std::cout << "==>> Summary: true\n"; +(??) std::cout << "==>> Postcondition: " << from_expr(SSA.ns, "", postcondition) << "\n"; +(??) std::cout << "==>> Function: " << function_name << "\n"; +(??) std::cout << "==>> Loophead selects: " << from_expr(SSA.ns, "", conjunction(loophead_selects)) << "\n"; +(??) for(local_SSAt::nodest::const_iterator n_it = SSA.nodes.begin(); +(??) n_it != SSA.nodes.end(); n_it++){ +(??) if(n_it->loophead!=SSA.nodes.end()){ +(??) std::cout << "==>> Loop found: " << n_it->loophead->location->location_number << "\n"; +(??) } +(??) } +(??) std::cout << "==>>\n"; +(??) */ +(??)#endif return; } diff --git a/src/summarizer/summary_checker_base.cpp b/src/summarizer/summary_checker_base.cpp index 8eb4a924a..c463106f1 100644 --- a/src/summarizer/summary_checker_base.cpp +++ b/src/summarizer/summary_checker_base.cpp @@ -339,7 +339,6 @@ void summary_checker_baset::check_properties( solver << summary.fw_precondition; } - //callee summaries solver << ssa_inliner.get_summaries(SSA); From c72065ddcd636f8b61f07fd0f465907ae60cd434 Mon Sep 17 00:00:00 2001 From: Peter Schrammel Date: Wed, 25 May 2016 09:35:33 +0100 Subject: [PATCH 29/82] unsat core output (without using incremental solver debug mode) --- src/summarizer/summarizer_bw_cex_complete.cpp | 51 ++++++++++++++++--- src/summarizer/summarizer_bw_cex_complete.h | 4 ++ 2 files changed, 47 insertions(+), 8 deletions(-) diff --git a/src/summarizer/summarizer_bw_cex_complete.cpp b/src/summarizer/summarizer_bw_cex_complete.cpp index a8d2db0dd..4bcc56376 100644 --- a/src/summarizer/summarizer_bw_cex_complete.cpp +++ b/src/summarizer/summarizer_bw_cex_complete.cpp @@ -2,7 +2,7 @@ Module: Simple Complete Counterexample-based Backward Analysis -Author: Peter Schrammel +Author: Madhukar Kumar, Peter Schrammel \*******************************************************************/ @@ -95,7 +95,11 @@ find_symbols_sett summarizer_bw_cex_completet::inline_summaries int counter) { local_SSAt &SSA = ssa_db.get(function_name); - //solver << SSA.get_enabling_exprs(); +#ifdef SHOW_UNSAT_CORE + add_to_formula(SSA.get_enabling_exprs()); +#else + solver << SSA.get_enabling_exprs(); +#endif exprt::operandst loophead_selects; loophead_selects = this->get_loophead_selects(SSA,ssa_unwinder.get(function_name),*solver.solver); @@ -111,7 +115,11 @@ find_symbols_sett summarizer_bw_cex_completet::inline_summaries << "\t renamed info ~ " << from_expr(ssa_db.get(function_name).ns, "", c) << "\n"; #endif +#ifdef SHOW_UNSAT_CORE + add_to_formula(c); +#else solver << c; +#endif ssa_dependency_grapht &ssa_depgraph = ssa_db.get_depgraph(function_name); @@ -302,7 +310,11 @@ find_symbols_sett summarizer_bw_cex_completet::inline_summaries << worknode.node_index << "\t renamed info ~ " << from_expr((ssa_db.get(function_name)).ns, "", worknode_info) << "\n"; #endif +#ifdef SHOW_UNSAT_CORE + add_to_formula(worknode_info); +#else solver << worknode_info; +#endif } } else{ @@ -318,7 +330,11 @@ find_symbols_sett summarizer_bw_cex_completet::inline_summaries << worknode.node_index << "\t renamed info ~ " << from_expr(ssa_db.get(function_name).ns, "", guard_binding) << "\n"; #endif - solver << guard_binding; +#ifdef SHOW_UNSAT_CORE + add_to_formula(guard_binding); +#else + solver << guard_binding; +#endif } } } @@ -492,6 +508,9 @@ Function: summarizer_bw_cex_completet::check() property_checkert::resultt summarizer_bw_cex_completet::check() { solver_calls++; // for statistics +#ifdef SHOW_UNSAT_CORE + solver.solver->set_assumptions(formula); +#endif if(solver() == decision_proceduret::D_SATISFIABLE){ //std::cout << "Solver <-- renamed info ~ SAT\n"; return property_checkert::FAIL; @@ -499,12 +518,11 @@ property_checkert::resultt summarizer_bw_cex_completet::check() #ifdef SHOW_UNSAT_CORE else { - for(unsigned i=0; iis_in_conflict(solver.formula[i])) - debug() << "is_in_conflict: " << solver.formula[i] << eom; - else - debug() << "not_in_conflict: " << solver.formula[i] << eom; + const local_SSAt &SSA = ssa_db.get(entry_function); + if(solver.solver->is_in_conflict(formula[i])) + debug() << "is_in_conflict: " << from_expr(SSA.ns, "", formula_expr[i]) << eom; } } #endif @@ -538,3 +556,20 @@ void summarizer_bw_cex_completet::debug_print } std::cout << "\n"; } + +void summarizer_bw_cex_completet::add_to_formula(const exprt &expr) +{ + literalt l = solver.solver->convert(expr); + if(l.is_false()) + { + literalt dummy = solver.solver->convert(symbol_exprt("goto_symex::\\dummy", + bool_typet())); + formula.push_back(dummy); + formula.push_back(!dummy); + } + else if(!l.is_true()) + { + formula.push_back(l); + formula_expr.push_back(expr); + } +} diff --git a/src/summarizer/summarizer_bw_cex_complete.h b/src/summarizer/summarizer_bw_cex_complete.h index 243120480..a5cb85f87 100644 --- a/src/summarizer/summarizer_bw_cex_complete.h +++ b/src/summarizer/summarizer_bw_cex_complete.h @@ -44,6 +44,8 @@ class summarizer_bw_cex_completet : public summarizer_bw_cex_baset protected: incremental_solvert &solver; + bvt formula; //for UNSAT core + exprt::operandst formula_expr; //for debugging virtual find_symbols_sett inline_summaries( const function_namet &function_name, @@ -58,6 +60,8 @@ class summarizer_bw_cex_completet : public summarizer_bw_cex_baset const function_namet &function_name, find_symbols_sett &dependency_set); + void add_to_formula(const exprt &expr); + }; From 786e15e97ef900e15f02392c7e1630055866b9a4 Mon Sep 17 00:00:00 2001 From: Peter Schrammel Date: Wed, 25 May 2016 12:34:08 +0100 Subject: [PATCH 30/82] get reason for spuriousness --- src/summarizer/summarizer_bw_cex.h | 10 +++++++++- src/summarizer/summary_checker_base.cpp | 2 ++ src/summarizer/summary_checker_base.h | 3 +++ 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/summarizer/summarizer_bw_cex.h b/src/summarizer/summarizer_bw_cex.h index 5cead1add..83d2c9e44 100644 --- a/src/summarizer/summarizer_bw_cex.h +++ b/src/summarizer/summarizer_bw_cex.h @@ -22,16 +22,24 @@ Author: Kumar Madhukar, Peter Schrammel class summarizer_bw_cex_baset : public summarizer_bwt { public: + struct reasont + { + std::set function_names; + std::set loop_ids; + }; + virtual void summarize(); virtual void summarize(const function_namet &entry_function); virtual void summarize(const exprt &_error_assertion); virtual property_checkert::resultt check(); - + virtual void get_reason(reasont &_reason) { _reason = reason; } + protected: function_namet entry_function; function_namet error_function; exprt error_assertion; + reasont reason; explicit summarizer_bw_cex_baset(optionst &_options, summary_dbt &_summary_db, diff --git a/src/summarizer/summary_checker_base.cpp b/src/summarizer/summary_checker_base.cpp index c463106f1..39b653ee7 100644 --- a/src/summarizer/summary_checker_base.cpp +++ b/src/summarizer/summary_checker_base.cpp @@ -497,6 +497,8 @@ void summary_checker_baset::check_properties( solver.pop_context(); + summarizer_bw_cex->get_reason(reason); + debug() << "** " << cover_goals.number_covered() << " of " << cover_goals.size() << " failed (" << cover_goals.iterations() << " iterations)" << eom; diff --git a/src/summarizer/summary_checker_base.h b/src/summarizer/summary_checker_base.h index 1c907891a..5cf648707 100644 --- a/src/summarizer/summary_checker_base.h +++ b/src/summarizer/summary_checker_base.h @@ -21,6 +21,7 @@ Author: Peter Schrammel #include "../domains/incremental_solver.h" #include "ssa_db.h" #include "summary_db.h" +#include "summarizer_bw_cex.h" class summary_checker_baset:public property_checkert { @@ -61,6 +62,8 @@ class summary_checker_baset:public property_checkert irep_idt entry_function; + summarizer_bw_cex_baset::reasont reason; + unsigned solver_instances; unsigned solver_calls; unsigned summaries_used; From b0cf78b2cf362fdf05db509cee478d4eea432823 Mon Sep 17 00:00:00 2001 From: Peter Schrammel Date: Thu, 26 May 2016 10:01:45 +0100 Subject: [PATCH 31/82] to start with, add all functions and loop ids to reason --- src/summarizer/summarizer_bw_cex.h | 11 +++++++++-- src/summarizer/summarizer_bw_cex_complete.cpp | 19 ++++++++++++++++--- 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/src/summarizer/summarizer_bw_cex.h b/src/summarizer/summarizer_bw_cex.h index 83d2c9e44..e11a6db05 100644 --- a/src/summarizer/summarizer_bw_cex.h +++ b/src/summarizer/summarizer_bw_cex.h @@ -25,7 +25,14 @@ class summarizer_bw_cex_baset : public summarizer_bwt struct reasont { std::set function_names; - std::set loop_ids; + std::set loop_ids; //TODO: location_number should be sufficient + + void merge(const reasont &other) + { + function_names.insert(other.function_names.begin(), + other.function_names.end()); + loop_ids.insert(other.loop_ids.begin(), other.loop_ids.end()); + } }; virtual void summarize(); @@ -33,7 +40,7 @@ class summarizer_bw_cex_baset : public summarizer_bwt virtual void summarize(const exprt &_error_assertion); virtual property_checkert::resultt check(); - virtual void get_reason(reasont &_reason) { _reason = reason; } + virtual void get_reason(reasont &_reason) { _reason.merge(reason); } protected: function_namet entry_function; diff --git a/src/summarizer/summarizer_bw_cex_complete.cpp b/src/summarizer/summarizer_bw_cex_complete.cpp index 4bcc56376..d89cf02be 100644 --- a/src/summarizer/summarizer_bw_cex_complete.cpp +++ b/src/summarizer/summarizer_bw_cex_complete.cpp @@ -95,12 +95,25 @@ find_symbols_sett summarizer_bw_cex_completet::inline_summaries int counter) { local_SSAt &SSA = ssa_db.get(function_name); + + //add enabling expressions + exprt enable_exprs = SSA.get_enabling_exprs(); + ssa_inliner.rename(enable_exprs, counter); + #ifdef SHOW_UNSAT_CORE - add_to_formula(SSA.get_enabling_exprs()); + add_to_formula(enable_exprs); #else - solver << SSA.get_enabling_exprs(); + solver << enable_exprs; #endif - + + //TODO: let's just put everything into the reason + reason.function_names.insert(function_name); + for(local_SSAt::nodest::iterator n_it = SSA.nodes.begin(); + n_it != SSA.nodes.end(); ++n_it) + if (n_it->loophead != SSA.nodes.end()) + reason.loop_ids.insert(n_it->loophead->location); + + //add loop selects exprt::operandst loophead_selects; loophead_selects = this->get_loophead_selects(SSA,ssa_unwinder.get(function_name),*solver.solver); exprt c = conjunction(loophead_selects); From ce14c62fed767e802fc0eed237f42b1b957f8fa8 Mon Sep 17 00:00:00 2001 From: Peter Schrammel Date: Thu, 26 May 2016 10:40:47 +0100 Subject: [PATCH 32/82] reason grouped by functions; identify callee by call site location --- src/summarizer/summarizer_bw_cex.h | 23 ++++++++++++++----- src/summarizer/summarizer_bw_cex_complete.cpp | 9 +++++--- 2 files changed, 23 insertions(+), 9 deletions(-) diff --git a/src/summarizer/summarizer_bw_cex.h b/src/summarizer/summarizer_bw_cex.h index e11a6db05..b76a214fb 100644 --- a/src/summarizer/summarizer_bw_cex.h +++ b/src/summarizer/summarizer_bw_cex.h @@ -22,16 +22,27 @@ Author: Kumar Madhukar, Peter Schrammel class summarizer_bw_cex_baset : public summarizer_bwt { public: - struct reasont + struct reason_infot { - std::set function_names; - std::set loop_ids; //TODO: location_number should be sufficient + typedef local_SSAt::locationt function_infot; //call_site; restriction: we assume that there is a single function call in an SSA node + typedef local_SSAt::locationt loop_infot; + std::set functions; + std::set loops; + }; + class reasont : public std::map + { + public: void merge(const reasont &other) { - function_names.insert(other.function_names.begin(), - other.function_names.end()); - loop_ids.insert(other.loop_ids.begin(), other.loop_ids.end()); + for(reasont::const_iterator it = other.begin(); + it != other.end(); ++it) + { + reason_infot &r = (*this)[it->first]; + r.functions.insert(it->second.functions.begin(), + it->second.functions.end()); + r.loops.insert(it->second.loops.begin(), it->second.loops.end()); + } } }; diff --git a/src/summarizer/summarizer_bw_cex_complete.cpp b/src/summarizer/summarizer_bw_cex_complete.cpp index d89cf02be..78585bbd8 100644 --- a/src/summarizer/summarizer_bw_cex_complete.cpp +++ b/src/summarizer/summarizer_bw_cex_complete.cpp @@ -106,12 +106,11 @@ find_symbols_sett summarizer_bw_cex_completet::inline_summaries solver << enable_exprs; #endif - //TODO: let's just put everything into the reason - reason.function_names.insert(function_name); + //TODO: let's just put all loops into the reason for(local_SSAt::nodest::iterator n_it = SSA.nodes.begin(); n_it != SSA.nodes.end(); ++n_it) if (n_it->loophead != SSA.nodes.end()) - reason.loop_ids.insert(n_it->loophead->location); + reason[function_name].loops.insert(n_it->loophead->location); //add loop selects exprt::operandst loophead_selects; @@ -271,6 +270,10 @@ find_symbols_sett summarizer_bw_cex_completet::inline_summaries */ ///////////////////////////////////////////////////////////////////////////////////// + //TODO: just put all function calls into reason + reason[function_name].functions.insert(ssa_depgraph.depnodes_map[worknode.node_index].location); + + //recurse worknode.dependency_set = compute_summary_rec(fname,worknode.dependency_set, ssa_depgraph.depnodes_map[worknode.node_index].rename_counter); From d0ce3c88ada7270af9c82bf8c2e2f226795cb58d Mon Sep 17 00:00:00 2001 From: Kumar Madhukar Date: Fri, 27 May 2016 13:35:36 +0530 Subject: [PATCH 33/82] selective unwinding and inlining code - in progress --- src/summarizer/summary_checker_kind.cpp | 60 ++++++++++++++++++++++++- 1 file changed, 59 insertions(+), 1 deletion(-) diff --git a/src/summarizer/summary_checker_kind.cpp b/src/summarizer/summary_checker_kind.cpp index 487b2c415..199945741 100644 --- a/src/summarizer/summary_checker_kind.cpp +++ b/src/summarizer/summary_checker_kind.cpp @@ -43,7 +43,65 @@ property_checkert::resultt summary_checker_kindt::operator()( { status() << "Unwinding (k=" << unwind << ")" << eom; summary_db.mark_recompute_all(); //TODO: recompute only functions with loops - ssa_unwinder.unwind_all(unwind+1); + //ssa_unwinder.unwind_all(unwind); + + // unwind loops "selectively" (those that seem to be the "reason") + for(summarizer_bw_cex_baset::reasont::const_iterator it = reason.begin(); it != reason.end(); ++it){ + for(std::set::const_iterator l_it = it->second.loops.begin(); + l_it != it->second.loops.end(); l_it++){ + ssa_unwinder.unwind_loop_alone(it->first, (*l_it)->location_number, unwind); + } + } + + // inline functions "selectively" (those that seem to be the "reason") + for(summarizer_bw_cex_baset::reasont::const_iterator it = reason.begin(); it != reason.end(); ++it){ + for(std::set::const_iterator f_it = it->second.functions.begin(); + f_it != it->second.functions.end(); f_it++){ + local_SSAt &SSA = ssa_db.get(it->first); + + for(local_SSAt::nodest::const_iterator n_it = SSA.nodes.begin(); + n_it != SSA.nodes.end(); n_it++){ + + local_SSAt::nodet &node=*n_it; + if(node.location == *(f_it)){ + + for(local_SSAt::nodet::function_callst::const_iterator fc_it=node.function_calls.begin(); + fc_it!=node.function_calls.end(); fc_it++){ + + irep_idt fname = to_symbol_expr(fc_it->function()).get_identifier(); + if(ssa_db.exists(fname)) + { + const local_SSAt &fSSA = ssa_db.get(fname); + + exprt guard_binding; + exprt::operandst bindings_in, bindings_out; + int counter = ssa_inliner.get_rename_counter(); + + ssa_inliner.get_guard_binding(SSA,fSSA,n_it,guard_binding,counter); + equal_exprt e = to_equal_expr(guard_binding); + node.equalities.push_back(e); + + + ssa_inliner.get_bindings(SSA,fSSA,n_it,fc_it,bindings_in,bindings_out,counter); + // put guard_binding, bindings_in, bindings_out in the caller's SSA (equalities) + + // copy fSSA's each node's items (equalities, assertions, etc.) + // into node's corresponding item (after renaming) + + + + } + + + } + } + } + + + + + } + } //dependency graphs if(!(options.get_bool_option("inline"))) From 76551992f1d82403ad40a7cb800f4324a942037d Mon Sep 17 00:00:00 2001 From: Kumar Madhukar Date: Fri, 27 May 2016 19:06:20 +0530 Subject: [PATCH 34/82] code for unwinding and inlining --- src/summarizer/summary_checker_kind.cpp | 119 +++++++++++++++++++++--- 1 file changed, 105 insertions(+), 14 deletions(-) diff --git a/src/summarizer/summary_checker_kind.cpp b/src/summarizer/summary_checker_kind.cpp index 199945741..a6aeb5dcb 100644 --- a/src/summarizer/summary_checker_kind.cpp +++ b/src/summarizer/summary_checker_kind.cpp @@ -59,46 +59,137 @@ property_checkert::resultt summary_checker_kindt::operator()( f_it != it->second.functions.end(); f_it++){ local_SSAt &SSA = ssa_db.get(it->first); - for(local_SSAt::nodest::const_iterator n_it = SSA.nodes.begin(); + std::list inline_nodes; + std::vector first_node_equalities; + int counter = ssa_inliner.get_rename_counter(); + + for(local_SSAt::nodest::iterator n_it = SSA.nodes.begin(); n_it != SSA.nodes.end(); n_it++){ - + local_SSAt::nodet &node=*n_it; + if(node.location == *(f_it)){ + bool clear_function_call = false; + for(local_SSAt::nodet::function_callst::const_iterator fc_it=node.function_calls.begin(); fc_it!=node.function_calls.end(); fc_it++){ irep_idt fname = to_symbol_expr(fc_it->function()).get_identifier(); if(ssa_db.exists(fname)) { - const local_SSAt &fSSA = ssa_db.get(fname); + clear_function_call = true; + + local_SSAt &fSSA = ssa_db.get(fname); exprt guard_binding; exprt::operandst bindings_in, bindings_out; - int counter = ssa_inliner.get_rename_counter(); - + + // put guard_binding, bindings_in, bindings_out in the caller's SSA (equalities) ssa_inliner.get_guard_binding(SSA,fSSA,n_it,guard_binding,counter); equal_exprt e = to_equal_expr(guard_binding); node.equalities.push_back(e); - ssa_inliner.get_bindings(SSA,fSSA,n_it,fc_it,bindings_in,bindings_out,counter); - // put guard_binding, bindings_in, bindings_out in the caller's SSA (equalities) - // copy fSSA's each node's items (equalities, assertions, etc.) - // into node's corresponding item (after renaming) + for(exprt::operandst::const_iterator b_it=bindings_in.begin(); + b_it!=bindings_in.end(); b_it++){ + equal_exprt e = to_equal_expr(*b_it); + node.equalities.push_back(e); + } + for(exprt::operandst::const_iterator b_it=bindings_out.begin(); + b_it!=bindings_out.end(); b_it++){ + equal_exprt e = to_equal_expr(*b_it); + node.equalities.push_back(e); + } + + for(local_SSAt::nodest::const_iterator fn_it = fSSA.nodes.begin(); + fn_it != fSSA.nodes.end(); fn_it++){ + local_SSAt::nodet fnode=*fn_it; + inline_nodes.push_back(fnode); + } + + if(fname == entry_function){ + // first_node_equalities should contain all the equalities from the first node of fSSA + for(local_SSAt::nodest::iterator fn_it = fSSA.nodes.begin(); + fn_it != fSSA.nodes.end(); fn_it++){ + local_SSAt::nodet &fnode=*fn_it; + for(local_SSAt::nodet::equalitiest::iterator e_it=fnode.equalities.begin(); + e_it!=fnode.equalities.end(); e_it++){ + first_node_equalities.push_back(*e_it); + } + break; + } + } + else{ + // except those (the one) that start with "ssa::guard" and have true in the rhs + for(local_SSAt::nodest::iterator fn_it = fSSA.nodes.begin(); + fn_it != fSSA.nodes.end(); fn_it++){ + local_SSAt::nodet &fnode=*fn_it; + for(local_SSAt::nodet::equalitiest::iterator e_it=fnode.equalities.begin(); + e_it!=fnode.equalities.end(); e_it++){ + // unless lhs starts with "ssa::guard" and rhs is true + + equal_exprt e = to_equal_expr(*e_it); + exprt &lhs = e.lhs(); exprt &rhs = e.rhs(); + std::string var_string = id2string(to_symbol_expr(lhs).get_identifier()); + if(((var_string.substr(0,11)) == "ssa::$guard") && (rhs.is_true())){ + // ignore the equality in this case + } + else{ + first_node_equalities.push_back(*e_it); + } + + } + break; + } + } - - } - - } + + if(clear_function_call == true) + node.function_calls.clear(); + } } - + bool replace_first_node_equalities = true; + if(inline_nodes.size() > 0){ + for(std::list::iterator in_it = inline_nodes.begin(); + in_it != inline_nodes.end(); in_it++){ + local_SSAt::nodet &inline_node = *in_it; + + if(replace_first_node_equalities == true){ + inline_node.equalities.clear(); + for(std::vector::iterator e_it=first_node_equalities.begin(); + e_it!=first_node_equalities.end(); e_it++){ + inline_node.equalities.push_back(*e_it); + } + replace_first_node_equalities = false; + } + + for(local_SSAt::nodet::equalitiest::iterator e_it=inline_node.equalities.begin(); + e_it!=inline_node.equalities.end(); e_it++){ + ssa_inliner.rename(*e_it, counter); + } + + for(local_SSAt::nodet::constraintst::iterator c_it=inline_node.constraints.begin(); + c_it!=inline_node.constraints.end(); c_it++){ + ssa_inliner.rename(*c_it, counter); + } + + for(local_SSAt::nodet::assertionst::iterator a_it=inline_node.assertions.begin(); + a_it!=inline_node.assertions.end(); a_it++){ + ssa_inliner.rename(*a_it, counter); + } + + // push inline_node into SSA + SSA.nodes.push_back(inline_node); + + } + } } } From 972de28893f586a1deaa46f67f02597c6787144e Mon Sep 17 00:00:00 2001 From: Kumar Madhukar Date: Sat, 28 May 2016 09:27:03 +0530 Subject: [PATCH 35/82] minor fix in inlining code --- src/summarizer/summary_checker_kind.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/summarizer/summary_checker_kind.cpp b/src/summarizer/summary_checker_kind.cpp index a6aeb5dcb..c7f50b656 100644 --- a/src/summarizer/summary_checker_kind.cpp +++ b/src/summarizer/summary_checker_kind.cpp @@ -126,6 +126,9 @@ property_checkert::resultt summary_checker_kindt::operator()( for(local_SSAt::nodest::iterator fn_it = fSSA.nodes.begin(); fn_it != fSSA.nodes.end(); fn_it++){ local_SSAt::nodet &fnode=*fn_it; + + bool ignore_equality = true; + for(local_SSAt::nodet::equalitiest::iterator e_it=fnode.equalities.begin(); e_it!=fnode.equalities.end(); e_it++){ // unless lhs starts with "ssa::guard" and rhs is true @@ -133,8 +136,8 @@ property_checkert::resultt summary_checker_kindt::operator()( equal_exprt e = to_equal_expr(*e_it); exprt &lhs = e.lhs(); exprt &rhs = e.rhs(); std::string var_string = id2string(to_symbol_expr(lhs).get_identifier()); - if(((var_string.substr(0,11)) == "ssa::$guard") && (rhs.is_true())){ - // ignore the equality in this case + if(((var_string.substr(0,11)) == "ssa::$guard") && (rhs.is_true()) && (ignore_equality == true)){ + ignore_equality = false; } else{ first_node_equalities.push_back(*e_it); From ac5ce60b8cce1d9d98ec045a93d96fac85be15a6 Mon Sep 17 00:00:00 2001 From: Peter Schrammel Date: Sat, 28 May 2016 14:06:34 +0100 Subject: [PATCH 36/82] more k-induction tests --- regression/kiki/unwind21/test.desc | 2 +- regression/modular/induction1/main.c | 12 +++++ regression/modular/induction1/test.desc | 6 +++ regression/modular/induction2/main.c | 12 +++++ regression/modular/induction2/test.desc | 6 +++ regression/modular/induction3/main.c | 12 +++++ regression/modular/induction3/test.desc | 6 +++ regression/modular/induction4/main.c | 16 +++++++ regression/modular/induction4/test.desc | 6 +++ regression/modular/induction5/main.c | 16 +++++++ regression/modular/induction5/test.desc | 6 +++ regression/modular/induction7/main.c | 23 +++++++++ regression/modular/induction7/test.desc | 6 +++ regression/modular/induction8/main.c | 19 ++++++++ regression/modular/induction8/test.desc | 6 +++ regression/modular/loop25/main.c | 12 +++++ regression/modular/loop25/test.desc | 6 +++ regression/modular/loop27/main.c | 13 +++++ regression/modular/loop27/test.desc | 6 +++ regression/modular/loop28/main.c | 8 ++++ regression/modular/loop28/test.desc | 6 +++ regression/modular/s3_clnt_1/main.c | 64 +++++++++++++++++++++++++ regression/modular/s3_clnt_1/test.desc | 6 +++ regression/modular/scope1/main.c | 11 +++++ regression/modular/scope1/test.desc | 6 +++ 25 files changed, 291 insertions(+), 1 deletion(-) create mode 100644 regression/modular/induction1/main.c create mode 100644 regression/modular/induction1/test.desc create mode 100644 regression/modular/induction2/main.c create mode 100644 regression/modular/induction2/test.desc create mode 100644 regression/modular/induction3/main.c create mode 100644 regression/modular/induction3/test.desc create mode 100644 regression/modular/induction4/main.c create mode 100644 regression/modular/induction4/test.desc create mode 100644 regression/modular/induction5/main.c create mode 100644 regression/modular/induction5/test.desc create mode 100644 regression/modular/induction7/main.c create mode 100644 regression/modular/induction7/test.desc create mode 100644 regression/modular/induction8/main.c create mode 100644 regression/modular/induction8/test.desc create mode 100644 regression/modular/loop25/main.c create mode 100644 regression/modular/loop25/test.desc create mode 100644 regression/modular/loop27/main.c create mode 100644 regression/modular/loop27/test.desc create mode 100644 regression/modular/loop28/main.c create mode 100644 regression/modular/loop28/test.desc create mode 100644 regression/modular/s3_clnt_1/main.c create mode 100644 regression/modular/s3_clnt_1/test.desc create mode 100644 regression/modular/scope1/main.c create mode 100644 regression/modular/scope1/test.desc diff --git a/regression/kiki/unwind21/test.desc b/regression/kiki/unwind21/test.desc index f4c56630b..f2e264817 100644 --- a/regression/kiki/unwind21/test.desc +++ b/regression/kiki/unwind21/test.desc @@ -1,4 +1,4 @@ -KNOWNBUG +CORE main.c --k-induction ^EXIT=10$ diff --git a/regression/modular/induction1/main.c b/regression/modular/induction1/main.c new file mode 100644 index 000000000..23a7e0054 --- /dev/null +++ b/regression/modular/induction1/main.c @@ -0,0 +1,12 @@ +void main() +{ + int x = 1; + + while(1) + { + if(x==2) x=-x; + if(x>0) x++; + if(x==0) assert(0); + if(-10<=x && x<0) x--; + } +} diff --git a/regression/modular/induction1/test.desc b/regression/modular/induction1/test.desc new file mode 100644 index 000000000..34e465e33 --- /dev/null +++ b/regression/modular/induction1/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--k-induction +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ diff --git a/regression/modular/induction2/main.c b/regression/modular/induction2/main.c new file mode 100644 index 000000000..76f88d6eb --- /dev/null +++ b/regression/modular/induction2/main.c @@ -0,0 +1,12 @@ +void main() +{ + int x = 1, y = -1, z = 1; + + while(1) + { + z = y; + y = x; + x = -x; + assert(x==z); + } +} diff --git a/regression/modular/induction2/test.desc b/regression/modular/induction2/test.desc new file mode 100644 index 000000000..3bf2a93f1 --- /dev/null +++ b/regression/modular/induction2/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--k-induction --havoc +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ diff --git a/regression/modular/induction3/main.c b/regression/modular/induction3/main.c new file mode 100644 index 000000000..38ef4b24f --- /dev/null +++ b/regression/modular/induction3/main.c @@ -0,0 +1,12 @@ +void main() +{ + int x = 0, y = 0, z = 0; + + while(1) + { + z = -y; + y = -x; + x++; + assert(x<=z+2); + } +} diff --git a/regression/modular/induction3/test.desc b/regression/modular/induction3/test.desc new file mode 100644 index 000000000..3bf2a93f1 --- /dev/null +++ b/regression/modular/induction3/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--k-induction --havoc +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ diff --git a/regression/modular/induction4/main.c b/regression/modular/induction4/main.c new file mode 100644 index 000000000..c55adf781 --- /dev/null +++ b/regression/modular/induction4/main.c @@ -0,0 +1,16 @@ +#define a 2 + +extern int nondet_int(); + +int main() { + int i=0, n=3; + + int sn0 = nondet_int(); + int sn = sn0; + + while(i=10) { + x = y = z = 0; + } +// if(x>z+2) break; +// assert(x<=z+2); + } + assert(0); //this works with assertion hoisting +} diff --git a/regression/modular/induction8/test.desc b/regression/modular/induction8/test.desc new file mode 100644 index 000000000..34e465e33 --- /dev/null +++ b/regression/modular/induction8/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--k-induction +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ diff --git a/regression/modular/loop25/main.c b/regression/modular/loop25/main.c new file mode 100644 index 000000000..8febd85d7 --- /dev/null +++ b/regression/modular/loop25/main.c @@ -0,0 +1,12 @@ +void main() +{ + int x = 1, y = -1, z = 1; + + while(x==z) + { + z = y; + y = x; + x = -x; + } + assert(0); +} diff --git a/regression/modular/loop25/test.desc b/regression/modular/loop25/test.desc new file mode 100644 index 000000000..6755e58a3 --- /dev/null +++ b/regression/modular/loop25/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--k-induction +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ diff --git a/regression/modular/loop27/main.c b/regression/modular/loop27/main.c new file mode 100644 index 000000000..ca9acda4c --- /dev/null +++ b/regression/modular/loop27/main.c @@ -0,0 +1,13 @@ +void main() +{ + int x = 1, y = -1, z = 1; + + do + { + z = y; + y = x; + x = -x; + } + while(x==z); + assert(0); +} diff --git a/regression/modular/loop27/test.desc b/regression/modular/loop27/test.desc new file mode 100644 index 000000000..34e465e33 --- /dev/null +++ b/regression/modular/loop27/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--k-induction +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ diff --git a/regression/modular/loop28/main.c b/regression/modular/loop28/main.c new file mode 100644 index 000000000..7ae8d5301 --- /dev/null +++ b/regression/modular/loop28/main.c @@ -0,0 +1,8 @@ +void main() { + int b = 3; + unsigned int j=0; + while (j<1 && b!=3) { + j++; + } + assert(j<1); +} diff --git a/regression/modular/loop28/test.desc b/regression/modular/loop28/test.desc new file mode 100644 index 000000000..34e465e33 --- /dev/null +++ b/regression/modular/loop28/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--k-induction +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ diff --git a/regression/modular/s3_clnt_1/main.c b/regression/modular/s3_clnt_1/main.c new file mode 100644 index 000000000..f958efad6 --- /dev/null +++ b/regression/modular/s3_clnt_1/main.c @@ -0,0 +1,64 @@ +#include + +extern int __VERIFIER_nondet_int(); + +int ssl3_connect(void) +{ + int s__state ; + int blastFlag ; + + s__state = 12292; + blastFlag = 0; + + while (1) { + if (s__state == 12292) { + goto switch_1_12292; + } else { + if (s__state == 4368) { + goto switch_1_4368; + } else { + if (s__state == 4384) { + goto switch_1_4384; + } else { + if (s__state == 4400) { + goto switch_1_4400; + } else { + return 0; + if (0) { + switch_1_12292: /* CIL Label */ + s__state = 4368; + continue; + switch_1_4368: /* CIL Label */ ; + blastFlag++; + s__state = 4384; + continue; + switch_1_4384: /* CIL Label */ ; + blastFlag++; + s__state = 4400; + continue; + switch_1_4400: /* CIL Label */ ; + if (blastFlag == 2) { + break; + } + continue; + } + } + } + } + } + } + assert(0); + return -1; +} +int main(void) +{ + ssl3_connect(); + return 0; +} + +/* +We get hoisted assertion: +(C) $guard#ls50%2 && ($cond#22%2 || $cond#36%2 || $cond#49%2) ==> ($guard#51 ==> FALSE) + +But $cond#36%2 is a return and no break condition! +*/ diff --git a/regression/modular/s3_clnt_1/test.desc b/regression/modular/s3_clnt_1/test.desc new file mode 100644 index 000000000..4d84485b2 --- /dev/null +++ b/regression/modular/s3_clnt_1/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--havoc --k-induction +^EXIT=10$ +^SIGNAL=0$ +^.*FAILURE$ diff --git a/regression/modular/scope1/main.c b/regression/modular/scope1/main.c new file mode 100644 index 000000000..ec678aac1 --- /dev/null +++ b/regression/modular/scope1/main.c @@ -0,0 +1,11 @@ +void main() +{ + int y = 5; + int i; + for(i=0; i<10; i+=y) + { + int y = 20; + } + assert(y==5); + assert(i==10); +} diff --git a/regression/modular/scope1/test.desc b/regression/modular/scope1/test.desc new file mode 100644 index 000000000..34e465e33 --- /dev/null +++ b/regression/modular/scope1/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--k-induction +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ From 31fd7847769816e85abc493a12e8e37a5ddbaac7 Mon Sep 17 00:00:00 2001 From: Peter Schrammel Date: Sat, 28 May 2016 16:03:27 +0100 Subject: [PATCH 37/82] spurious check refactoring started --- regression/modular/induction4/main.c | 32 +-- regression/modular/induction5/main.c | 32 +-- regression/modular/induction7/main.c | 46 ++--- regression/modular/induction8/main.c | 38 ++-- src/2ls/cover_goals_ext.cpp | 79 ++++---- src/2ls/cover_goals_ext.h | 10 +- src/summarizer/summarizer_bw_cex_complete.cpp | 10 +- src/summarizer/summarizer_bw_cex_concrete.cpp | 40 +++- src/summarizer/summary_checker_base.cpp | 186 +++++++++--------- 9 files changed, 242 insertions(+), 231 deletions(-) diff --git a/regression/modular/induction4/main.c b/regression/modular/induction4/main.c index c55adf781..241e31944 100644 --- a/regression/modular/induction4/main.c +++ b/regression/modular/induction4/main.c @@ -1,16 +1,16 @@ -#define a 2 - -extern int nondet_int(); - -int main() { - int i=0, n=3; - - int sn0 = nondet_int(); - int sn = sn0; - - while(i=10) { - x = y = z = 0; - } -// if(x>z+2) break; -// assert(x<=z+2); - } - assert(0); //this works with assertion hoisting -} +int main() { + int x,y,z; + __CPROVER_assume(x==y && y==z && -10<=x && x<0); + +// while(1) + while(x<=z+2) + { +// __CPROVER_assume(x<=z+2); + z = -y; + y = -x; + if(nondet()) x = x+1; + if(x>=10) { + x = y = z = 0; + } +// if(x>z+2) break; +// assert(x<=z+2); + } + assert(0); //this works with assertion hoisting +} diff --git a/src/2ls/cover_goals_ext.cpp b/src/2ls/cover_goals_ext.cpp index 3465724af..abb93dc6b 100644 --- a/src/2ls/cover_goals_ext.cpp +++ b/src/2ls/cover_goals_ext.cpp @@ -181,55 +181,41 @@ void cover_goals_extt::assignment() if(property_map[it->first].result==property_checkert::UNKNOWN && solver.l_get(g_it->condition).is_true()) { - if(spurious_check) + assert((g_it->cond_expression).id() == ID_not); + exprt conjunct_expr = (g_it->cond_expression).op0(); + + if(conjunct_expr.id() != ID_and) { - assert((g_it->cond_expression).id() == ID_not); - exprt conjunct_expr = (g_it->cond_expression).op0(); - - if(conjunct_expr.id() != ID_and) - { - solver.pop_context(); //otherwise this would interfere with necessary preconditions - summarizer_bw_cex.summarize(g_it->cond_expression); - property_map[it->first].result = summarizer_bw_cex.check(); - solver.new_context(); - } - else - { - //filter out assertion instances that are not violated - exprt::operandst failed_exprs; - for(exprt::operandst::const_iterator c_it = - conjunct_expr.operands().begin(); - c_it != conjunct_expr.operands().end(); c_it++) - { - literalt conjunct_literal = solver.convert(*c_it); - if(solver.l_get(conjunct_literal).is_true()) - { -#ifdef DEBUG - std::cout << "failed_expr: " - << from_expr(SSA.ns, "", *c_it) << std::endl; -#endif - failed_exprs.push_back(*c_it); - } - } - solver.pop_context(); //otherwise this would interfere with necessary preconditions - summarizer_bw_cex.summarize(not_exprt(conjunction(failed_exprs))); - property_map[it->first].result = summarizer_bw_cex.check(); - if(property_map[it->first].result == - property_checkert::FAIL) - { - if(build_error_trace) - { - ssa_build_goto_tracet build_goto_trace(SSA,solver.get_solver()); - build_goto_trace(property_map[it->first].error_trace); - } - solver.new_context(); - break; - else - property_map[it->first].result=property_checkert::FAIL; - } + solver.pop_context(); //otherwise this would interfere with necessary preconditions + summarizer_bw_cex.summarize(g_it->cond_expression); + property_map[it->first].result = summarizer_bw_cex.check(); + solver.new_context(); } else - property_map[it->first].result = property_checkert::FAIL; + { + //filter out assertion instances that are not violated + exprt::operandst failed_exprs; + for(exprt::operandst::const_iterator c_it = + conjunct_expr.operands().begin(); + c_it != conjunct_expr.operands().end(); c_it++) + { + literalt conjunct_literal = solver.convert(*c_it); + if(solver.l_get(conjunct_literal).is_true()) + failed_exprs.push_back(*c_it); + } + solver.pop_context(); //otherwise this would interfere with necessary preconditions + summarizer_bw_cex.summarize(not_exprt(conjunction(failed_exprs))); + property_map[it->first].result = summarizer_bw_cex.check(); + solver.new_context(); + } + } + if(property_map[it->first].result == property_checkert::FAIL) + { + if(build_error_trace) + { + ssa_build_goto_tracet build_goto_trace(SSA,solver.get_solver()); + build_goto_trace(property_map[it->first].error_trace); + } } if(!all_properties && property_map[it->first].result == property_checkert::FAIL) @@ -238,3 +224,4 @@ void cover_goals_extt::assignment() _iterations++; //statistics } + diff --git a/src/2ls/cover_goals_ext.h b/src/2ls/cover_goals_ext.h index 119dd0e7a..0ac80f61e 100644 --- a/src/2ls/cover_goals_ext.h +++ b/src/2ls/cover_goals_ext.h @@ -52,19 +52,16 @@ class cover_goals_extt:public messaget explicit inline cover_goals_extt( unwindable_local_SSAt &_SSA, incremental_solvert &_solver, - const exprt::operandst& _loophead_selects, property_checkert::property_mapt &_property_map, - bool _spurious_check, bool _all_properties, + bool _all_properties, bool _build_error_trace, summarizer_bw_cex_baset &_summarizer_bw_cex): SSA(_SSA), solver(_solver), property_map(_property_map), - spurious_check(_spurious_check), all_properties(_all_properties), build_error_trace(_build_error_trace), - summarizer_bw_cex(_summarizer_bw_cex), - loophead_selects(_loophead_selects) + summarizer_bw_cex(_summarizer_bw_cex) { } @@ -128,9 +125,8 @@ class cover_goals_extt:public messaget unsigned _number_covered, _iterations; incremental_solvert &solver; property_checkert::property_mapt &property_map; - bool spurious_check, all_properties, build_error_trace; + bool all_properties, build_error_trace; summarizer_bw_cex_baset &summarizer_bw_cex; - exprt::operandst loophead_selects; // this method is called for each satisfying assignment virtual void assignment(); diff --git a/src/summarizer/summarizer_bw_cex_complete.cpp b/src/summarizer/summarizer_bw_cex_complete.cpp index 78585bbd8..9e8c70440 100644 --- a/src/summarizer/summarizer_bw_cex_complete.cpp +++ b/src/summarizer/summarizer_bw_cex_complete.cpp @@ -543,7 +543,15 @@ property_checkert::resultt summarizer_bw_cex_completet::check() } #endif - //std::cout << "Solver <-- renamed info ~ UNSAT\n"; + //check whether loops have been fully unwound + bool fully_unwound = + is_fully_unwound(loop_continues,loophead_selects,solver); + status() << "Loops " << (fully_unwound ? "" : "not ") + << "fully unwound" << eom; + + if(fully_unwound) + return property_heckert::PASS; + return property_checkert::UNKNOWN; } diff --git a/src/summarizer/summarizer_bw_cex_concrete.cpp b/src/summarizer/summarizer_bw_cex_concrete.cpp index 6d1099bc0..8aa770c02 100644 --- a/src/summarizer/summarizer_bw_cex_concrete.cpp +++ b/src/summarizer/summarizer_bw_cex_concrete.cpp @@ -87,19 +87,39 @@ Function: summarizer_bw_cex_concretet::check() property_checkert::resultt summarizer_bw_cex_concretet::check() { - //TODO: store information about why have UNKNOWN - // we have to distinguish the case when we cannot decide about spuriousness - + property_checkert::resultt result = property_checkert::FAIL; if(!summary_db.exists(entry_function)) - return property_checkert::UNKNOWN; + { + result = property_checkert::UNKNOWN; + } + else + { + const summaryt &summary = summary_db.get(entry_function); + if(summary.error_summaries.empty() || + summary.error_summaries.begin()->second.is_nil() || + summary.error_summaries.begin()->second.is_true()) + result = property_checkert::UNKNOWN; + } - const summaryt &summary = summary_db.get(entry_function); - if(summary.error_summaries.empty() || - summary.error_summaries.begin()->second.is_nil() || - summary.error_summaries.begin()->second.is_true()) - return property_checkert::UNKNOWN; + //we are only complete if we are in the entry function + if(result == property_checkert::UNKNOWN && + entry_function == error_function) + { + incremental_solvert &solver = ssa_db.get_solver(entry_function); + //these have not been collected yet + get_loop_continues(entry_function, + ssa_db.get(entry_function), solver, loop_continues); + //check whether loops have been fully unwound + bool fully_unwound = + is_fully_unwound(loop_continues,loophead_selects,solver); + status() << "Loops " << (fully_unwound ? "" : "not ") + << "fully unwound" << eom; + + if(fully_unwound) + result = property_heckert::PASS; + } - return property_checkert::FAIL; + return result; } /*******************************************************************\ diff --git a/src/summarizer/summary_checker_base.cpp b/src/summarizer/summary_checker_base.cpp index 39b653ee7..84fbdff6e 100644 --- a/src/summarizer/summary_checker_base.cpp +++ b/src/summarizer/summary_checker_base.cpp @@ -39,7 +39,9 @@ Author: Peter Schrammel #include "summarizer_bw_cex_all.h" #include "summarizer_fw.h" +#include "summarizer_fw_term.h" #include "summarizer_bw.h" +#include "summarizer_bw_term.h" #ifdef SHOW_CALLING_CONTEXTS #include "summarizer_fw_contexts.h" @@ -154,9 +156,15 @@ void summary_checker_baset::summarize(const goto_modelt &goto_model, if(forward && !termination) summarizer = new summarizer_fwt( options,summary_db,ssa_db,ssa_unwinder,ssa_inliner); + if(forward && termination) + summarizer = new summarizer_fw_termt( + options,summary_db,ssa_db,ssa_unwinder,ssa_inliner); if(!forward && !termination) summarizer = new summarizer_bwt( options,summary_db,ssa_db,ssa_unwinder,ssa_inliner); + if(!forward && termination) + summarizer = new summarizer_bw_termt( + options,summary_db,ssa_db,ssa_unwinder,ssa_inliner); } assert(summarizer != NULL); @@ -344,15 +352,8 @@ void summary_checker_baset::check_properties( //freeze loop head selects exprt::operandst loophead_selects = - summarizer_baset::get_loophead_selects(SSA,ssa_unwinder.get(f_it->first),*solver.solver); - //check whether loops have been fully unwound - exprt::operandst loop_continues = - get_loop_continues(f_it->first,SSA,*solver.solver); - bool fully_unwound = - is_fully_unwound(loop_continues,loophead_selects,solver); - status() << "Loops " << (fully_unwound ? "" : "not ") - << "fully unwound" << eom; - + summarizer_baset::get_loophead_selects(SSA, + ssa_unwinder.get(f_it->first),*solver.solver); //spuriousness checkers summarizer_bw_cex_baset *summarizer_bw_cex = NULL; @@ -402,9 +403,8 @@ void summary_checker_baset::check_properties( summarizer_bw_cex->set_message_handler(get_message_handler()); cover_goals_extt cover_goals( - SSA,solver,loophead_selects,property_map, - f_it->first!=entry_function || !fully_unwound, - all_properties,build_error_trace, + SSA, solver,loophead_selects, property_map, + all_properties, build_error_trace, *summarizer_bw_cex); #if 0 @@ -573,87 +573,87 @@ void summary_checker_baset::do_show_vcc( std::cout << "\n"; } -/*******************************************************************\ - -Function: summary_checker_baset::get_loop_continues - - Inputs: - - Outputs: - - Purpose: returns the loop continuation guards at the end of the - loops in order to check whether we can unroll further - -\*******************************************************************/ - -exprt::operandst summary_checker_baset::get_loop_continues( - const irep_idt &function_name, - const local_SSAt &SSA, prop_convt &solver) -{ - exprt::operandst loop_continues; - - ssa_unwinder.get(function_name).loop_continuation_conditions(loop_continues); - if(loop_continues.size()==0) - { - //TODO: this should actually be done transparently by the unwinder - for(local_SSAt::nodest::const_iterator n_it = SSA.nodes.begin(); - n_it != SSA.nodes.end(); n_it++) - { - if(n_it->loophead==SSA.nodes.end()) continue; - symbol_exprt guard = SSA.guard_symbol(n_it->location); - symbol_exprt cond = SSA.cond_symbol(n_it->location); - loop_continues.push_back(and_exprt(guard,cond)); - } - } - -#if 0 - std::cout << "loophead_continues: " << from_expr(SSA.ns,"",disjunction(loop_continues)) << std::endl; -#endif - - return loop_continues; -} - -/*******************************************************************\ - -Function: summary_checker_baset::is_fully_unwound - - Inputs: - - Outputs: - - Purpose: checks whether the loops have been fully unwound - -\*******************************************************************/ - -bool summary_checker_baset::is_fully_unwound( - const exprt::operandst &loop_continues, - const exprt::operandst &loophead_selects, - incremental_solvert &solver) -{ - solver.new_context(); - solver << and_exprt(conjunction(loophead_selects), - disjunction(loop_continues)); - - solver_calls++; //statistics - - switch(solver()) - { - case decision_proceduret::D_SATISFIABLE: - solver.pop_context(); - return false; - break; - - case decision_proceduret::D_UNSATISFIABLE: - solver.pop_context(); - solver << conjunction(loophead_selects); - return true; - break; - - case decision_proceduret::D_ERROR: - default: - throw "error from decision procedure"; - } -} +(??)/*******************************************************************\ +(??) +(??)Function: summary_checker_baset::get_loop_continues +(??) +(??) Inputs: +(??) +(??) Outputs: +(??) +(??) Purpose: returns the loop continuation guards at the end of the +(??) loops in order to check whether we can unroll further +(??) +(??)\*******************************************************************/ +(??) +(??)exprt::operandst summary_checker_baset::get_loop_continues( +(??) const irep_idt &function_name, +(??) const local_SSAt &SSA, prop_convt &solver) +(??){ +(??) exprt::operandst loop_continues; +(??) +(??) ssa_unwinder.get(function_name).loop_continuation_conditions(loop_continues); +(??) if(loop_continues.size()==0) +(??) { +(??) //TODO: this should actually be done transparently by the unwinder +(??) for(local_SSAt::nodest::const_iterator n_it = SSA.nodes.begin(); +(??) n_it != SSA.nodes.end(); n_it++) +(??) { +(??) if(n_it->loophead==SSA.nodes.end()) continue; +(??) symbol_exprt guard = SSA.guard_symbol(n_it->location); +(??) symbol_exprt cond = SSA.cond_symbol(n_it->location); +(??) loop_continues.push_back(and_exprt(guard,cond)); +(??) } +(??) } +(??) +(??)#if 0 +(??) std::cout << "loophead_continues: " << from_expr(SSA.ns,"",disjunction(loop_continues)) << std::endl; +(??)#endif +(??) +(??) return loop_continues; +(??)} +(??) +(??)/*******************************************************************\ +(??) +(??)Function: summary_checker_baset::is_fully_unwound +(??) +(??) Inputs: +(??) +(??) Outputs: +(??) +(??) Purpose: checks whether the loops have been fully unwound +(??) +(??)\*******************************************************************/ +(??) +(??)bool summary_checker_baset::is_fully_unwound( +(??) const exprt::operandst &loop_continues, +(??) const exprt::operandst &loophead_selects, +(??) incremental_solvert &solver) +(??){ +(??) solver.new_context(); +(??) solver << and_exprt(conjunction(loophead_selects), +(??) disjunction(loop_continues)); +(??) +(??) solver_calls++; //statistics +(??) +(??) switch(solver()) +(??) { +(??) case decision_proceduret::D_SATISFIABLE: +(??) solver.pop_context(); +(??) return false; +(??) break; +(??) +(??) case decision_proceduret::D_UNSATISFIABLE: +(??) solver.pop_context(); +(??) solver << conjunction(loophead_selects); +(??) return true; +(??) break; +(??) +(??) case decision_proceduret::D_ERROR: +(??) default: +(??) throw "error from decision procedure"; +(??) } +(??)} /*******************************************************************\ From fc6a15b8449c86674f9b185862bed4e16276a141 Mon Sep 17 00:00:00 2001 From: Peter Schrammel Date: Sat, 28 May 2016 18:29:51 +0100 Subject: [PATCH 38/82] refactoring done, except loop continuations --- src/ssa/ssa_dependency_graph.cpp | 26 +- src/ssa/ssa_dependency_graph.h | 3 +- src/summarizer/summarizer_bw_cex_ai.cpp | 46 +- src/summarizer/summarizer_bw_cex_complete.cpp | 428 +++++++++--------- src/summarizer/summarizer_bw_cex_complete.h | 2 + src/summarizer/summarizer_bw_cex_concrete.cpp | 18 +- src/summarizer/summarizer_bw_cex_wp.cpp | 2 +- src/summarizer/summary_checker_base.cpp | 8 +- 8 files changed, 301 insertions(+), 232 deletions(-) diff --git a/src/ssa/ssa_dependency_graph.cpp b/src/ssa/ssa_dependency_graph.cpp index 26bf05fba..fc7875824 100644 --- a/src/ssa/ssa_dependency_graph.cpp +++ b/src/ssa/ssa_dependency_graph.cpp @@ -49,7 +49,8 @@ void ssa_dependency_grapht::create(const local_SSAt &SSA, ssa_inlinert &ssa_inli depnodet sink_node; sink_node.is_assertion = false; sink_node.is_function_call = false; - + sink_node.is_loop = false; + // globals_out is the used_symbol of the sink_node for(local_SSAt::var_sett::const_iterator g_it = SSA.globals_out.begin(); g_it != SSA.globals_out.end(); g_it++){ @@ -88,9 +89,26 @@ void ssa_dependency_grapht::create(const local_SSAt &SSA, ssa_inlinert &ssa_inli depnodet temp_node; temp_node.is_assertion = false; temp_node.is_function_call = false; + temp_node.is_loop = false; temp_node.node_info = *e_it; temp_node.location = n_it->location; + //loop-head select + //TODO: this is an ugly hack (this can be changed as soon as unwindable_local_SSA provides smooth renaming with odometers) + //if(n_it->loophead!=SSA.nodes.end()) + if(e_it->op1().id()==ID_if && + e_it->op1().op0().id()==ID_symbol) + { + std::string var_string = id2string(e_it->op1().op0().get(ID_identifier)); + if(((var_string.substr(0,14)) == "ssa::$guard#ls")) + { + temp_node.is_loop = true; +/* symbol_exprt lsguard = SSA.name(SSA.guard_symbol(), + local_SSAt::LOOP_SELECT, n_it->location); + ssa_local_unwinder.unwinder_rename(lsguard,*n_it,true);*/ + temp_node.guard = not_exprt(e_it->op1().op0()); + } + } //temp_node.trivial_guard = true; equal_exprt e = to_equal_expr(*e_it); @@ -130,6 +148,7 @@ void ssa_dependency_grapht::create(const local_SSAt &SSA, ssa_inlinert &ssa_inli depnodet temp_node; temp_node.is_assertion = false; temp_node.is_function_call = false; + temp_node.is_loop = false; temp_node.node_info = *c_it; temp_node.location = n_it->location; find_symbols(*c_it,temp_node.used_symbols); @@ -147,6 +166,7 @@ void ssa_dependency_grapht::create(const local_SSAt &SSA, ssa_inlinert &ssa_inli depnodet temp_node; temp_node.is_assertion = true; temp_node.is_function_call = false; + temp_node.is_loop = false; temp_node.node_info = *a_it; temp_node.location = n_it->location; find_symbols(*a_it,temp_node.used_symbols); @@ -221,6 +241,7 @@ void ssa_dependency_grapht::create(const local_SSAt &SSA, ssa_inlinert &ssa_inli depnodet temp_node; temp_node.is_assertion = false; temp_node.is_function_call = false; + temp_node.is_loop = false; temp_node.node_info = *b_it; temp_node.location = n_it->location; @@ -241,6 +262,7 @@ void ssa_dependency_grapht::create(const local_SSAt &SSA, ssa_inlinert &ssa_inli depnodet temp_node; temp_node.is_assertion = false; temp_node.is_function_call = false; + temp_node.is_loop = false; temp_node.node_info = *b_it; temp_node.location = n_it->location; @@ -259,6 +281,7 @@ void ssa_dependency_grapht::create(const local_SSAt &SSA, ssa_inlinert &ssa_inli temp_node.guard = guard_binding; temp_node.is_assertion = false; temp_node.is_function_call = true; + temp_node.is_loop = false; temp_node.node_info = *f_it; temp_node.rename_counter = counter; temp_node.location = n_it->location; @@ -299,6 +322,7 @@ void ssa_dependency_grapht::create(const local_SSAt &SSA, ssa_inlinert &ssa_inli depnodet source_node; source_node.is_assertion = false; source_node.is_function_call = false; + source_node.is_loop = false; // params and globals_in are the modified_symbols at source_node diff --git a/src/ssa/ssa_dependency_graph.h b/src/ssa/ssa_dependency_graph.h index 7d360f218..1acb50978 100644 --- a/src/ssa/ssa_dependency_graph.h +++ b/src/ssa/ssa_dependency_graph.h @@ -29,9 +29,10 @@ class ssa_dependency_grapht{ struct depnodet{ exprt node_info; - exprt guard; + exprt guard; //guard binding or loop-head select bool is_assertion; bool is_function_call; + bool is_loop; //bool trivial_guard; int rename_counter; find_symbols_sett used_symbols; diff --git a/src/summarizer/summarizer_bw_cex_ai.cpp b/src/summarizer/summarizer_bw_cex_ai.cpp index 2d7ec6dec..27734fb20 100644 --- a/src/summarizer/summarizer_bw_cex_ai.cpp +++ b/src/summarizer/summarizer_bw_cex_ai.cpp @@ -82,19 +82,45 @@ Function: summarizer_bw_cex_ait::check() property_checkert::resultt summarizer_bw_cex_ait::check() { - //TODO: store information about why have UNKNOWN - // we have to distinguish the case when we cannot decide about spuriousness - + property_checkert::resultt result = property_checkert::FAIL; if(!summary_db.exists(entry_function)) - return property_checkert::UNKNOWN; + { + result = property_checkert::UNKNOWN; + } + else + { + const summaryt &summary = summary_db.get(entry_function); + if(summary.error_summaries.empty() || + summary.error_summaries.begin()->second.is_nil() || + summary.error_summaries.begin()->second.is_true()) + result = property_checkert::UNKNOWN; + } - const summaryt &summary = summary_db.get(entry_function); - if(summary.error_summaries.empty() || - summary.error_summaries.begin()->second.is_nil() || - summary.error_summaries.begin()->second.is_true()) - return property_checkert::UNKNOWN; + //we are only complete if we are in the entry function + if(result == property_checkert::UNKNOWN && + entry_function == error_function) + { + incremental_solvert &solver = ssa_db.get_solver(entry_function); + const local_SSAt &ssa = ssa_db.get(entry_function); + const ssa_local_unwindert &ssa_local_unwinder = + ssa_unwinder.get(entry_function); + exprt::operandst loophead_selects; + exprt::operandst loop_continues; + get_loophead_selects(ssa, ssa_local_unwinder, + *solver.solver, loophead_selects); + get_loop_continues(ssa, ssa_local_unwinder, + *solver.solver, loop_continues); + //check whether loops have been fully unwound + bool fully_unwound = + is_fully_unwound(loop_continues,loophead_selects,solver); + status() << "Loops " << (fully_unwound ? "" : "not ") + << "fully unwound" << eom; + + if(fully_unwound) + result = property_checkert::PASS; + } - return property_checkert::FAIL; + return result; } /*******************************************************************\ diff --git a/src/summarizer/summarizer_bw_cex_complete.cpp b/src/summarizer/summarizer_bw_cex_complete.cpp index 9e8c70440..422d22fc9 100644 --- a/src/summarizer/summarizer_bw_cex_complete.cpp +++ b/src/summarizer/summarizer_bw_cex_complete.cpp @@ -42,7 +42,7 @@ Function: summarizer_bw_cex_completet::summarize() void summarizer_bw_cex_completet::summarize ( - const function_namet &entry_function) + const function_namet &entry_function) { // no dependencies to begin with find_symbols_sett dependency_set; @@ -68,9 +68,9 @@ void summarizer_bw_cex_completet::summarize(const exprt &_error_assertion) status() << "\nBackward error analysis (complete)..." << eom; error_assertion = _error_assertion; /* - std::cout << "error assertion: " - << from_expr(ssa_db.get(entry_function).ns, "", error_assertion) - << "\n"; + std::cout << "error assertion: " + << from_expr(ssa_db.get(entry_function).ns, "", error_assertion) + << "\n"; */ summarize(entry_function); } @@ -90,9 +90,9 @@ Function: summarizer_bw_cex_completet::inline_summaries() find_symbols_sett summarizer_bw_cex_completet::inline_summaries ( - const function_namet &function_name, - find_symbols_sett &dependency_set, - int counter) + const function_namet &function_name, + find_symbols_sett &dependency_set, + int counter) { local_SSAt &SSA = ssa_db.get(function_name); @@ -112,26 +112,6 @@ find_symbols_sett summarizer_bw_cex_completet::inline_summaries if (n_it->loophead != SSA.nodes.end()) reason[function_name].loops.insert(n_it->loophead->location); - //add loop selects - exprt::operandst loophead_selects; - loophead_selects = this->get_loophead_selects(SSA,ssa_unwinder.get(function_name),*solver.solver); - exprt c = conjunction(loophead_selects); - - //std::cout << "Solver <-- " << function_name << ": (conjunction of loophead_selects):" - // << "\t original info ~ " << from_expr(ssa_db.get(function_name).ns, "", c) << "\n"; - - ssa_inliner.rename(c, counter); - -#if 0 - std::cout << "Solver <-- " << function_name << ": (conjunction of loophead_selects):" - << "\t renamed info ~ " << from_expr(ssa_db.get(function_name).ns, "", c) << "\n"; -#endif - -#ifdef SHOW_UNSAT_CORE - add_to_formula(c); -#else - solver << c; -#endif ssa_dependency_grapht &ssa_depgraph = ssa_db.get_depgraph(function_name); @@ -153,33 +133,35 @@ find_symbols_sett summarizer_bw_cex_completet::inline_summaries while(!worklist.empty()){ /* - std::cout << "worklist: "; - for(worklistt::const_iterator w_it=worklist.begin(); - w_it != worklist.end(); w_it++){ + std::cout << "worklist: "; + for(worklistt::const_iterator w_it=worklist.begin(); + w_it != worklist.end(); w_it++){ std::cout << w_it->node_index << " "; - } - std::cout << "\n"; + } + std::cout << "\n"; - std::cout << "\t waitlist: "; - for(worklistt::const_iterator w_it=work_waitlist.begin(); - w_it != work_waitlist.end(); w_it++){ + std::cout << "\t waitlist: "; + for(worklistt::const_iterator w_it=work_waitlist.begin(); + w_it != work_waitlist.end(); w_it++){ std::cout << w_it->node_index << " "; - } - std::cout << "\n"; + } + std::cout << "\n"; */ worknodet &worknode = worklist.front(); + const ssa_dependency_grapht::depnodet &depnode = + ssa_depgraph.depnodes_map[worknode.node_index]; //std::cout << "working node: " << function_name << ": " << worknode.node_index << "\n"; ///////////////////////////////////////////////////////////////////////////////////// //std::cout << "\t size of dependency set: " << worknode.dependency_set.size() << "\n"; /* - std::cout << "\t dependency set: "; - for(find_symbols_sett::iterator d_it = worknode.dependency_set.begin(); - d_it != worknode.dependency_set.end(); d_it++){ + std::cout << "\t dependency set: "; + for(find_symbols_sett::iterator d_it = worknode.dependency_set.begin(); + d_it != worknode.dependency_set.end(); d_it++){ std::cout << *d_it; - } - std::cout << "\n\n\n"; + } + std::cout << "\n\n\n"; */ ///////////////////////////////////////////////////////////////////////////////////// @@ -189,24 +171,24 @@ find_symbols_sett summarizer_bw_cex_completet::inline_summaries return worknode.dependency_set; // modify worknode_dependency_set if the node is an assertion - if(ssa_depgraph.depnodes_map[worknode.node_index].is_assertion == true){ + if(depnode.is_assertion == true){ //std::cout << "\t\t an assertion node\n"; - for(find_symbols_sett::const_iterator d_it = ssa_depgraph.depnodes_map[worknode.node_index].used_symbols.begin(); - d_it != ssa_depgraph.depnodes_map[worknode.node_index].used_symbols.end(); d_it++){ - worknode.dependency_set.insert(*d_it); + for(find_symbols_sett::const_iterator d_it = depnode.used_symbols.begin(); + d_it != depnode.used_symbols.end(); d_it++){ + worknode.dependency_set.insert(*d_it); } ///////////////////////////////////////////////////////////////////////////////////// /* - std::cout << "\t size of dependency set: " << worknode.dependency_set.size() << "\n"; + std::cout << "\t size of dependency set: " << worknode.dependency_set.size() << "\n"; - std::cout << "\t dependency set: "; - for(find_symbols_sett::iterator d_it = worknode.dependency_set.begin(); - d_it != worknode.dependency_set.end(); d_it++){ - std::cout << *d_it; - } - std::cout << "\n"; + std::cout << "\t dependency set: "; + for(find_symbols_sett::iterator d_it = worknode.dependency_set.begin(); + d_it != worknode.dependency_set.end(); d_it++){ + std::cout << *d_it; + } + std::cout << "\n"; */ ///////////////////////////////////////////////////////////////////////////////////// @@ -215,90 +197,90 @@ find_symbols_sett summarizer_bw_cex_completet::inline_summaries } // if this is a function call - if(ssa_depgraph.depnodes_map[worknode.node_index].is_function_call == true){ + if(depnode.is_function_call == true){ //std::cout << "fcall: working node: " << function_name << ": " << worknode.node_index << "\n"; irep_idt fname = - to_symbol_expr((to_function_application_expr(ssa_depgraph.depnodes_map[worknode.node_index].node_info)).function()).get_identifier(); + to_symbol_expr((to_function_application_expr(depnode.node_info)).function()).get_identifier(); find_symbols_sett renamed_dependencies; ///////////////////////////////////////////////////////////////////////////////////// /* - std::cout << "\t size of dependency set: " << worknode.dependency_set.size() << "\n"; + std::cout << "\t size of dependency set: " << worknode.dependency_set.size() << "\n"; - std::cout << "\t dependency set: "; - for(find_symbols_sett::iterator d_it = worknode.dependency_set.begin(); - d_it != worknode.dependency_set.end(); d_it++){ - std::cout << *d_it; - } - std::cout << "\n"; + std::cout << "\t dependency set: "; + for(find_symbols_sett::iterator d_it = worknode.dependency_set.begin(); + d_it != worknode.dependency_set.end(); d_it++){ + std::cout << *d_it; + } + std::cout << "\n"; */ ///////////////////////////////////////////////////////////////////////////////////// for(find_symbols_sett::iterator d_it = worknode.dependency_set.begin(); - d_it != worknode.dependency_set.end(); d_it++){ - irep_idt id = *d_it; - // detach the '@' symbol if there - irep_idt renamed_id = ssa_inliner.rename - (id, - ssa_depgraph.depnodes_map[worknode.node_index].rename_counter, false); - renamed_dependencies.insert(renamed_id); + d_it != worknode.dependency_set.end(); d_it++){ + irep_idt id = *d_it; + // detach the '@' symbol if there + irep_idt renamed_id = ssa_inliner.rename + (id, + depnode.rename_counter, false); + renamed_dependencies.insert(renamed_id); } worknode.dependency_set = renamed_dependencies; if(!worknode.dependency_set.empty()){ - find_symbols_sett guard_dependencies; - find_symbols(ssa_depgraph.depnodes_map[worknode.node_index].guard, - guard_dependencies); - for(find_symbols_sett::const_iterator d_it = guard_dependencies.begin(); - d_it != guard_dependencies.end(); d_it++){ - worknode.dependency_set.insert(*d_it); + find_symbols_sett guard_dependencies; + find_symbols(depnode.guard, + guard_dependencies); + for(find_symbols_sett::const_iterator d_it = guard_dependencies.begin(); + d_it != guard_dependencies.end(); d_it++){ + worknode.dependency_set.insert(*d_it); } } ///////////////////////////////////////////////////////////////////////////////////// /* - std::cout << "\t size of dependency set: " << worknode.dependency_set.size() << "\n"; + std::cout << "\t size of dependency set: " << worknode.dependency_set.size() << "\n"; - std::cout << "\t dependency set: "; - for(find_symbols_sett::iterator d_it = worknode.dependency_set.begin(); - d_it != worknode.dependency_set.end(); d_it++){ - std::cout << *d_it; - } - std::cout << "\n"; + std::cout << "\t dependency set: "; + for(find_symbols_sett::iterator d_it = worknode.dependency_set.begin(); + d_it != worknode.dependency_set.end(); d_it++){ + std::cout << *d_it; + } + std::cout << "\n"; */ ///////////////////////////////////////////////////////////////////////////////////// //TODO: just put all function calls into reason - reason[function_name].functions.insert(ssa_depgraph.depnodes_map[worknode.node_index].location); + reason[function_name].functions.insert(depnode.location); //recurse worknode.dependency_set = - compute_summary_rec(fname,worknode.dependency_set, - ssa_depgraph.depnodes_map[worknode.node_index].rename_counter); + compute_summary_rec(fname,worknode.dependency_set, + depnode.rename_counter); renamed_dependencies.clear(); for(find_symbols_sett::iterator d_it = worknode.dependency_set.begin(); - d_it != worknode.dependency_set.end(); d_it++){ - irep_idt id = *d_it; - // attach the '@' symbol if not already there - irep_idt renamed_id = ssa_inliner.rename - (id, - ssa_depgraph.depnodes_map[worknode.node_index].rename_counter, true); - renamed_dependencies.insert(renamed_id); + d_it != worknode.dependency_set.end(); d_it++){ + irep_idt id = *d_it; + // attach the '@' symbol if not already there + irep_idt renamed_id = ssa_inliner.rename + (id, + depnode.rename_counter, true); + renamed_dependencies.insert(renamed_id); } worknode.dependency_set = renamed_dependencies; if(!worknode.dependency_set.empty()){ - find_symbols_sett guard_dependencies; - find_symbols(ssa_depgraph.depnodes_map[worknode.node_index].guard, guard_dependencies); - for(find_symbols_sett::const_iterator d_it = guard_dependencies.begin(); - d_it != guard_dependencies.end(); d_it++){ - worknode.dependency_set.insert(*d_it); + find_symbols_sett guard_dependencies; + find_symbols(depnode.guard, guard_dependencies); + for(find_symbols_sett::const_iterator d_it = guard_dependencies.begin(); + d_it != guard_dependencies.end(); d_it++){ + worknode.dependency_set.insert(*d_it); } } @@ -306,74 +288,94 @@ find_symbols_sett summarizer_bw_cex_completet::inline_summaries // if the dependency set is non-empty if(!worknode.dependency_set.empty()){ - exprt worknode_info = ssa_depgraph.depnodes_map[worknode.node_index].node_info; - if(ssa_depgraph.depnodes_map[worknode.node_index].is_assertion == true) - worknode_info = not_exprt(worknode_info); + exprt worknode_info = depnode.node_info; + if(depnode.is_assertion == true) + worknode_info = not_exprt(worknode_info); if(worknode.node_index != 0){ - if(!(ssa_depgraph.depnodes_map[worknode.node_index].is_function_call)){ - if((ssa_depgraph.depnodes_map[worknode.node_index].is_assertion == false) || - (worknode_info == error_assertion)){ - /* - std::cout << "Solver <-- " << function_name << ": (node) node#:" - << worknode.node_index << "\t original info ~ " - << from_expr((ssa_db.get(function_name)).ns, "", worknode_info) << "\n"; - */ - ssa_inliner.rename(worknode_info, counter); + if(!(depnode.is_function_call)){ + if((depnode.is_assertion == false) || + (worknode_info == error_assertion)){ + /* + std::cout << "Solver <-- " << function_name << ": (node) node#:" + << worknode.node_index << "\t original info ~ " + << from_expr((ssa_db.get(function_name)).ns, "", worknode_info) << "\n"; + */ + ssa_inliner.rename(worknode_info, counter); #if 0 - std::cout << "Solver <-- renamed assertion: " << from_expr((ssa_db.get(function_name)).ns, "", worknode_info) << "\n"; - std::cout << "Solver <-- " << function_name << ": (node) node#:" - << worknode.node_index << "\t renamed info ~ " - << from_expr((ssa_db.get(function_name)).ns, "", worknode_info) << "\n"; + std::cout << "Solver <-- renamed assertion: " << from_expr((ssa_db.get(function_name)).ns, "", worknode_info) << "\n"; + std::cout << "Solver <-- " << function_name << ": (node) node#:" + << worknode.node_index << "\t renamed info ~ " + << from_expr((ssa_db.get(function_name)).ns, "", worknode_info) << "\n"; #endif #ifdef SHOW_UNSAT_CORE - add_to_formula(worknode_info); + add_to_formula(worknode_info); #else - solver << worknode_info; + solver << worknode_info; #endif - } - } - else{ - exprt guard_binding = ssa_depgraph.depnodes_map[worknode.node_index].guard; - /* - std::cout << "Solver <-- " << function_name << ": (bind) node#:" - << worknode.node_index << "\t original info ~ " - << from_expr(ssa_db.get(function_name).ns, "", guard_binding) << "\n"; - */ - ssa_inliner.rename(guard_binding, counter); + + if(depnode.is_loop) + { + //loop head selects + exprt lsguard = depnode.guard; + ssa_inliner.rename(lsguard, counter); + loophead_selects.push_back(lsguard); + solver.solver->set_frozen(solver.convert(lsguard)); + + //loop continuations + exprt::operandst local_loop_continues; +/* ssa_local_unwinder.get_loop_continuations(depnode.location, + local_loop_continues);*/ + for(size_t i=0; inode_index == pred_node_index){ + if(w_it->node_index == pred_node_index){ - dependencies_merged = true; + dependencies_merged = true; - for(find_symbols_sett::const_iterator - a_it=pred_annotation.begin(); a_it!=pred_annotation.end(); a_it++) - { - if(worknode.dependency_set.find(*a_it) != worknode.dependency_set.end()){ - if((w_it->dependency_set).find(*a_it) == (w_it->dependency_set).end()){ - (w_it->dependency_set).insert(*a_it); - } - } - } - break; - } + for(find_symbols_sett::const_iterator + a_it=pred_annotation.begin(); a_it!=pred_annotation.end(); a_it++) + { + if(worknode.dependency_set.find(*a_it) != worknode.dependency_set.end()){ + if((w_it->dependency_set).find(*a_it) == (w_it->dependency_set).end()){ + (w_it->dependency_set).insert(*a_it); + } + } + } + break; + } } if(dependencies_merged == false){ - worknodet new_worknode; - new_worknode.node_index = pred_node_index; + worknodet new_worknode; + new_worknode.node_index = pred_node_index; - for(find_symbols_sett::const_iterator - a_it=pred_annotation.begin(); a_it!=pred_annotation.end(); a_it++) - { - if(worknode.dependency_set.find(*a_it) != worknode.dependency_set.end()) - new_worknode.dependency_set.insert(*a_it); - } + for(find_symbols_sett::const_iterator + a_it=pred_annotation.begin(); a_it!=pred_annotation.end(); a_it++) + { + if(worknode.dependency_set.find(*a_it) != worknode.dependency_set.end()) + new_worknode.dependency_set.insert(*a_it); + } - work_waitlist.push_back(new_worknode); + work_waitlist.push_back(new_worknode); } } #if 0 std::cout << function_name << ": worklist: "; for(worklistt::const_iterator w_it=worklist.begin(); - w_it != worklist.end(); w_it++){ + w_it != worklist.end(); w_it++){ std::cout << w_it->node_index << " "; } std::cout << "\n"; @@ -424,7 +426,7 @@ find_symbols_sett summarizer_bw_cex_completet::inline_summaries std::cout << "\t" << function_name << ": waitlist: "; for(worklistt::const_iterator w_it=work_waitlist.begin(); - w_it != work_waitlist.end(); w_it++){ + w_it != work_waitlist.end(); w_it++){ std::cout << w_it->node_index << " "; } std::cout << "\n"; @@ -450,31 +452,31 @@ find_symbols_sett summarizer_bw_cex_completet::inline_summaries bool uncovered_successor = false; std::vector &waitlisted_worknode_successors = - ssa_depgraph.depnodes_map[waitlisted_worknode.node_index].successors; + ssa_depgraph.depnodes_map[waitlisted_worknode.node_index].successors; for(unsigned i = 0; i < waitlisted_worknode_successors.size(); i++){ - bool check_covered = false; - for(unsigned j = 0; j < covered_nodes.size(); j++){ - if(waitlisted_worknode_successors[i] == covered_nodes[j]){ - check_covered = true; - break; - } - } - if(!check_covered){ + bool check_covered = false; + for(unsigned j = 0; j < covered_nodes.size(); j++){ + if(waitlisted_worknode_successors[i] == covered_nodes[j]){ + check_covered = true; + break; + } + } + if(!check_covered){ #if 0 - std::cout << function_name << ": an uncovered successor of " << waitlisted_worknode.node_index << " : " - << waitlisted_worknode_successors[i] << "\n"; + std::cout << function_name << ": an uncovered successor of " << waitlisted_worknode.node_index << " : " + << waitlisted_worknode_successors[i] << "\n"; #endif - uncovered_successor = true; - break; - } + uncovered_successor = true; + break; + } } if(!uncovered_successor){ - worklist.push_back(waitlisted_worknode); + worklist.push_back(waitlisted_worknode); } else{ - work_waitlist.push_back(waitlisted_worknode); + work_waitlist.push_back(waitlisted_worknode); } } @@ -500,10 +502,10 @@ Function: summarizer_bw_cex_completet::compute_summary_rec() \*******************************************************************/ find_symbols_sett summarizer_bw_cex_completet::compute_summary_rec - ( - const function_namet &function_name, - find_symbols_sett &dependency_set, - int counter) +( + const function_namet &function_name, + find_symbols_sett &dependency_set, + int counter) { // recursively compute summaries for function calls return inline_summaries(function_name,dependency_set,counter); @@ -523,12 +525,20 @@ Function: summarizer_bw_cex_completet::check() property_checkert::resultt summarizer_bw_cex_completet::check() { - solver_calls++; // for statistics +//add loophead selects +#ifdef SHOW_UNSAT_CORE + add_to_formula(conjunction(loophead_selects)); +#else + solver << conjunction(loophead_selects); +#endif + #ifdef SHOW_UNSAT_CORE solver.solver->set_assumptions(formula); #endif - if(solver() == decision_proceduret::D_SATISFIABLE){ - //std::cout << "Solver <-- renamed info ~ SAT\n"; + + solver_calls++; // for statistics + if(solver() == decision_proceduret::D_SATISFIABLE) + { return property_checkert::FAIL; } #ifdef SHOW_UNSAT_CORE @@ -536,10 +546,10 @@ property_checkert::resultt summarizer_bw_cex_completet::check() { for(unsigned i=0; iis_in_conflict(formula[i])) - debug() << "is_in_conflict: " << from_expr(SSA.ns, "", formula_expr[i]) << eom; - } + debug() << "is_in_conflict: " << from_expr(ns, "", formula_expr[i]) << eom; + } } #endif @@ -547,10 +557,10 @@ property_checkert::resultt summarizer_bw_cex_completet::check() bool fully_unwound = is_fully_unwound(loop_continues,loophead_selects,solver); status() << "Loops " << (fully_unwound ? "" : "not ") - << "fully unwound" << eom; + << "fully unwound" << eom; if(fully_unwound) - return property_heckert::PASS; + return property_checkert::PASS; return property_checkert::UNKNOWN; } @@ -568,16 +578,16 @@ Function: summarizer_bw_cex_completet::debug_print() \*******************************************************************/ void summarizer_bw_cex_completet::debug_print -( - const function_namet &function_name, - find_symbols_sett &dependency_set) + ( + const function_namet &function_name, + find_symbols_sett &dependency_set) { std::cout << "DebugInfo: function -> " << function_name - << " ; dependency_set -> "; + << " ; dependency_set -> "; for(find_symbols_sett::iterator d_it = dependency_set.begin(); - d_it != dependency_set.end(); d_it++){ - std::cout << *d_it << ", "; - } + d_it != dependency_set.end(); d_it++){ + std::cout << *d_it << ", "; +} std::cout << "\n"; } @@ -586,14 +596,14 @@ void summarizer_bw_cex_completet::add_to_formula(const exprt &expr) literalt l = solver.solver->convert(expr); if(l.is_false()) { - literalt dummy = solver.solver->convert(symbol_exprt("goto_symex::\\dummy", - bool_typet())); - formula.push_back(dummy); - formula.push_back(!dummy); - } + literalt dummy = solver.solver->convert(symbol_exprt("goto_symex::\\dummy", + bool_typet())); + formula.push_back(dummy); + formula.push_back(!dummy); +} else if(!l.is_true()) { - formula.push_back(l); - formula_expr.push_back(expr); - } + formula.push_back(l); + formula_expr.push_back(expr); +} } diff --git a/src/summarizer/summarizer_bw_cex_complete.h b/src/summarizer/summarizer_bw_cex_complete.h index a5cb85f87..37f80d672 100644 --- a/src/summarizer/summarizer_bw_cex_complete.h +++ b/src/summarizer/summarizer_bw_cex_complete.h @@ -46,6 +46,8 @@ class summarizer_bw_cex_completet : public summarizer_bw_cex_baset incremental_solvert &solver; bvt formula; //for UNSAT core exprt::operandst formula_expr; //for debugging + exprt::operandst loophead_selects; + exprt::operandst loop_continues; virtual find_symbols_sett inline_summaries( const function_namet &function_name, diff --git a/src/summarizer/summarizer_bw_cex_concrete.cpp b/src/summarizer/summarizer_bw_cex_concrete.cpp index 8aa770c02..5dcd08e89 100644 --- a/src/summarizer/summarizer_bw_cex_concrete.cpp +++ b/src/summarizer/summarizer_bw_cex_concrete.cpp @@ -106,9 +106,15 @@ property_checkert::resultt summarizer_bw_cex_concretet::check() entry_function == error_function) { incremental_solvert &solver = ssa_db.get_solver(entry_function); - //these have not been collected yet - get_loop_continues(entry_function, - ssa_db.get(entry_function), solver, loop_continues); + const local_SSAt &ssa = ssa_db.get(entry_function); + const ssa_local_unwindert &ssa_local_unwinder = + ssa_unwinder.get(entry_function); + exprt::operandst loophead_selects; + exprt::operandst loop_continues; + get_loophead_selects(ssa, ssa_local_unwinder, + *solver.solver, loophead_selects); + get_loop_continues(ssa, ssa_local_unwinder, + *solver.solver, loop_continues); //check whether loops have been fully unwound bool fully_unwound = is_fully_unwound(loop_continues,loophead_selects,solver); @@ -116,7 +122,7 @@ property_checkert::resultt summarizer_bw_cex_concretet::check() << "fully unwound" << eom; if(fully_unwound) - result = property_heckert::PASS; + result = property_checkert::PASS; } return result; @@ -336,7 +342,7 @@ void summarizer_bw_cex_concretet::do_summary( #endif exprt::operandst loophead_selects; - loophead_selects = this->get_loophead_selects(SSA,ssa_unwinder.get(function_name),*solver.solver); + get_loophead_selects(SSA,ssa_unwinder.get(function_name),*solver.solver,loophead_selects); #ifdef OPT_11 solver << simplify_expr(conjunction(loophead_selects), SSA.ns); @@ -575,7 +581,7 @@ exprt summarizer_bw_cex_concretet::compute_calling_context2( #endif exprt::operandst loophead_selects; - loophead_selects = this->get_loophead_selects(SSA,ssa_unwinder.get(function_name),*solver.solver); + get_loophead_selects(SSA,ssa_unwinder.get(function_name),*solver.solver,loophead_selects); #ifdef OPT_11 solver << simplify_expr(conjunction(loophead_selects), SSA.ns); diff --git a/src/summarizer/summarizer_bw_cex_wp.cpp b/src/summarizer/summarizer_bw_cex_wp.cpp index 37c629e0a..97d0010cd 100644 --- a/src/summarizer/summarizer_bw_cex_wp.cpp +++ b/src/summarizer/summarizer_bw_cex_wp.cpp @@ -100,7 +100,7 @@ find_symbols_sett summarizer_bw_cex_wpt::inline_summaries //solver << SSA.get_enabling_exprs(); exprt::operandst loophead_selects; - loophead_selects = this->get_loophead_selects(SSA,ssa_unwinder.get(function_name),*solver.solver); + get_loophead_selects(SSA,ssa_unwinder.get(function_name),*solver.solver,loophead_selects); exprt c = conjunction(loophead_selects); //std::cout << "Solver <-- " << function_name << ": (conjunction of loophead_selects):" diff --git a/src/summarizer/summary_checker_base.cpp b/src/summarizer/summary_checker_base.cpp index 84fbdff6e..a96708f22 100644 --- a/src/summarizer/summary_checker_base.cpp +++ b/src/summarizer/summary_checker_base.cpp @@ -351,9 +351,9 @@ void summary_checker_baset::check_properties( solver << ssa_inliner.get_summaries(SSA); //freeze loop head selects - exprt::operandst loophead_selects = - summarizer_baset::get_loophead_selects(SSA, - ssa_unwinder.get(f_it->first),*solver.solver); + exprt::operandst loophead_selects; + summarizer_baset::get_loophead_selects(SSA, + ssa_unwinder.get(f_it->first),*solver.solver, loophead_selects); //spuriousness checkers summarizer_bw_cex_baset *summarizer_bw_cex = NULL; @@ -403,7 +403,7 @@ void summary_checker_baset::check_properties( summarizer_bw_cex->set_message_handler(get_message_handler()); cover_goals_extt cover_goals( - SSA, solver,loophead_selects, property_map, + SSA, solver, property_map, all_properties, build_error_trace, *summarizer_bw_cex); From 04ab15bdca76a05125351a4c53095c6bc6a20436 Mon Sep 17 00:00:00 2001 From: Peter Schrammel Date: Sat, 28 May 2016 21:17:09 +0100 Subject: [PATCH 39/82] loop-specific continuation conditions --- src/ssa/ssa_unwinder.cpp | 53 +++++++++++++++++++ src/ssa/ssa_unwinder.h | 7 ++- src/summarizer/summarizer_bw_cex_ai.cpp | 5 +- src/summarizer/summarizer_bw_cex_complete.cpp | 7 +-- src/summarizer/summarizer_bw_cex_concrete.cpp | 5 +- 5 files changed, 67 insertions(+), 10 deletions(-) diff --git a/src/ssa/ssa_unwinder.cpp b/src/ssa/ssa_unwinder.cpp index 690807d8a..ef792e31f 100644 --- a/src/ssa/ssa_unwinder.cpp +++ b/src/ssa/ssa_unwinder.cpp @@ -779,6 +779,12 @@ Function: ssa_local_unwindert::loop_continuation_conditions void ssa_local_unwindert::loop_continuation_conditions( exprt::operandst& loop_cont) const { + //clear old ones + for(loop_mapt::iterator it = loops.begin(); it != loops.end(); ++it) + { + it->second.current_continuation_conditions.clear(); + } + //compute new SSA.current_unwindings.clear(); for(loop_mapt::const_iterator it=loops.begin(); it!=loops.end(); ++it) { @@ -789,6 +795,53 @@ void ssa_local_unwindert::loop_continuation_conditions( } } +/*****************************************************************************\ + * + * Function : ssa_local_unwindert::loop_continuation_conditions + * + * Input : + * + * Output : + * + * Purpose : return loop continuation conditions for all loops in this function + * + *****************************************************************************/ + +void ssa_local_unwindert::loop_continuation_conditions( + exprt::operandst &loop_cont) const +{ + for(loop_mapt::const_iterator it = loops.begin(); it != loops.end(); ++it) + { + loop_cont.insert(loop_cont.end(), + it->second.current_continuation_conditions.begin(), + it->second.current_continuation_conditions.end()); + } +} + +/*****************************************************************************\ + * + * Function : ssa_local_unwindert::loop_continuation_conditions + * + * Input : + * + * Output : + * + * Purpose : return loop continuation conditions for all instances + * of the given loop in this function + * + *****************************************************************************/ + +void ssa_local_unwindert::loop_continuation_conditions( + const locationt& loop_id, + exprt::operandst &loop_cont) const +{ + const loopt &loop = loops.at(loop_id->location_number); + loop_cont.insert(loop_cont.end(), + loop.current_continuation_conditions.begin(), + loop.current_continuation_conditions.end()); +} + + /*******************************************************************\ Function: ssa_local_unwindert::get_continuation_condition diff --git a/src/ssa/ssa_unwinder.h b/src/ssa/ssa_unwinder.h index 454f7f2fd..54af2f1a7 100644 --- a/src/ssa/ssa_unwinder.h +++ b/src/ssa/ssa_unwinder.h @@ -45,7 +45,10 @@ class ssa_local_unwindert // TODO: this should be loop specific in future, // maybe move to unwindable_local_ssa as it is not really unwinder related - void loop_continuation_conditions(exprt::operandst& loop_cont) const; + void compute_loop_continuation_conditions(); + void loop_continuation_conditions(exprt::operandst &loop_cont) const; + void loop_continuation_conditions(const locationt& loop_id, + exprt::operandst &loop_cont) const; #if 0 // TODO: these two should be possible with unwindable_local_ssa facilities @@ -80,6 +83,8 @@ class ssa_local_unwindert exprt::operandst loop_enabling_exprs; exprt loop_enabling_expr_current; + exprt::operandst current_continuation_conditions; + typedef std::map exit_mapt; exit_mapt exit_map; std::map pre_post_map; diff --git a/src/summarizer/summarizer_bw_cex_ai.cpp b/src/summarizer/summarizer_bw_cex_ai.cpp index 27734fb20..6d676e175 100644 --- a/src/summarizer/summarizer_bw_cex_ai.cpp +++ b/src/summarizer/summarizer_bw_cex_ai.cpp @@ -102,14 +102,13 @@ property_checkert::resultt summarizer_bw_cex_ait::check() { incremental_solvert &solver = ssa_db.get_solver(entry_function); const local_SSAt &ssa = ssa_db.get(entry_function); - const ssa_local_unwindert &ssa_local_unwinder = + ssa_local_unwindert &ssa_local_unwinder = ssa_unwinder.get(entry_function); exprt::operandst loophead_selects; exprt::operandst loop_continues; get_loophead_selects(ssa, ssa_local_unwinder, *solver.solver, loophead_selects); - get_loop_continues(ssa, ssa_local_unwinder, - *solver.solver, loop_continues); + get_loop_continues(ssa, ssa_local_unwinder, loop_continues); //check whether loops have been fully unwound bool fully_unwound = is_fully_unwound(loop_continues,loophead_selects,solver); diff --git a/src/summarizer/summarizer_bw_cex_complete.cpp b/src/summarizer/summarizer_bw_cex_complete.cpp index 422d22fc9..6a6ca30b6 100644 --- a/src/summarizer/summarizer_bw_cex_complete.cpp +++ b/src/summarizer/summarizer_bw_cex_complete.cpp @@ -95,7 +95,8 @@ find_symbols_sett summarizer_bw_cex_completet::inline_summaries int counter) { local_SSAt &SSA = ssa_db.get(function_name); - + ssa_local_unwindert &ssa_local_unwinder = ssa_unwinder.get(function_name); + ssa_local_unwinder.compute_loop_continuation_conditions(); //add enabling expressions exprt enable_exprs = SSA.get_enabling_exprs(); ssa_inliner.rename(enable_exprs, counter); @@ -324,8 +325,8 @@ find_symbols_sett summarizer_bw_cex_completet::inline_summaries //loop continuations exprt::operandst local_loop_continues; -/* ssa_local_unwinder.get_loop_continuations(depnode.location, - local_loop_continues);*/ + get_loop_continues(SSA, ssa_local_unwinder, depnode.location, + local_loop_continues); for(size_t i=0; i Date: Sat, 28 May 2016 21:58:04 +0100 Subject: [PATCH 40/82] update enable_expr after 0th unwinding --- regression/kiki/Makefile | 2 +- src/ssa/ssa_unwinder.cpp | 58 +++-- src/ssa/ssa_unwinder.h | 1 + src/summarizer/summary_checker_kind.cpp | 268 +++++++++++++----------- 4 files changed, 185 insertions(+), 144 deletions(-) diff --git a/regression/kiki/Makefile b/regression/kiki/Makefile index b5f2484a2..569e1b125 100644 --- a/regression/kiki/Makefile +++ b/regression/kiki/Makefile @@ -1,6 +1,6 @@ default: tests.log -FLAGS = --verbosity 10 +FLAGS = --verbosity 10 --inline test: @../test.pl -c "../../../src/2ls/2ls $(FLAGS)" diff --git a/src/ssa/ssa_unwinder.cpp b/src/ssa/ssa_unwinder.cpp index ef792e31f..fa3597e0c 100644 --- a/src/ssa/ssa_unwinder.cpp +++ b/src/ssa/ssa_unwinder.cpp @@ -30,6 +30,7 @@ void ssa_local_unwindert::init() build_pre_post_map(); build_exit_conditions(); unwind(0); + compute_enable_expr(); #ifdef DEBUG SSA.output_verbose(std::cout); #endif @@ -287,20 +288,6 @@ void ssa_local_unwindert::unwind_loop_at_location(unsigned loc, unsigned k) bool_typet()); loop.loop_enabling_exprs.push_back(loop.loop_enabling_expr_current); - exprt::operandst ssa_current_enabling_expr; - for(loop_mapt::iterator it = loops.begin(); it != loops.end(); ++it){ - exprt::operandst result; - for(exprt::operandst::iterator e_it = ((it->second).loop_enabling_exprs).begin(); - e_it != ((it->second).loop_enabling_exprs).end(); e_it++){ - exprt::operandst::iterator lh = e_it; lh++; - if(lh != ((it->second).loop_enabling_exprs).end()) result.push_back(not_exprt(*e_it)); - else result.push_back(*e_it); - } - ssa_current_enabling_expr.push_back(conjunction(result)); - } - - SSA.combined_enabling_expr = conjunction(ssa_current_enabling_expr); - //current_enabling_expr = // symbol_exprt("unwind::"+id2string(fname)+"::enable"+i2string(k), @@ -330,7 +317,8 @@ void ssa_local_unwindert::unwind_loop_at_location(unsigned loc, unsigned k) if(it->first == loc) it->second.current_unwinding=k; } - + + compute_enable_expr(); return; } @@ -354,7 +342,10 @@ void ssa_local_unwindert::unwind(unsigned k) current_enabling_expr= symbol_exprt("unwind::"+id2string(fname)+"::enable"+i2string(k), bool_typet()); - SSA.enabling_exprs.push_back(current_enabling_expr); + for(loop_mapt::iterator it = loops.begin(); it != loops.end(); ++it) + { + it->second.loop_enabling_exprs.push_back(current_enabling_expr); + } // TODO: just for exploratory integration, must go away SSA.current_unwinding=k; @@ -373,6 +364,8 @@ void ssa_local_unwindert::unwind(unsigned k) { it->second.current_unwinding=k; } + + compute_enable_expr(); } /*******************************************************************\ @@ -764,6 +757,39 @@ void ssa_local_unwindert::add_hoisted_assertions(loopt &loop, bool is_last) } } +/*****************************************************************************\ + * + * Function : ssa_local_unwindert::compute_enable_expr + * + * Input : + * + * Output : + * + * Purpose : updates the enable_expr + * + *****************************************************************************/ + +void ssa_local_unwindert::compute_enable_expr() +{ + exprt::operandst ssa_current_enabling_expr; + for(loop_mapt::const_iterator it = loops.begin(); it != loops.end(); ++it) + { + for(exprt::operandst::const_iterator + e_it = ((it->second).loop_enabling_exprs).begin(); + e_it != ((it->second).loop_enabling_exprs).end(); e_it++) + { + exprt::operandst::const_iterator lh = e_it; lh++; + if(lh != ((it->second).loop_enabling_exprs).end()) + ssa_current_enabling_expr.push_back(not_exprt(*e_it)); + else + ssa_current_enabling_expr.push_back(*e_it); + } + } + + SSA.combined_enabling_expr = conjunction(ssa_current_enabling_expr); +} + + /*******************************************************************\ Function: ssa_local_unwindert::loop_continuation_conditions diff --git a/src/ssa/ssa_unwinder.h b/src/ssa/ssa_unwinder.h index 54af2f1a7..a0cc486d2 100644 --- a/src/ssa/ssa_unwinder.h +++ b/src/ssa/ssa_unwinder.h @@ -46,6 +46,7 @@ class ssa_local_unwindert // TODO: this should be loop specific in future, // maybe move to unwindable_local_ssa as it is not really unwinder related void compute_loop_continuation_conditions(); + void compute_enable_expr(); void loop_continuation_conditions(exprt::operandst &loop_cont) const; void loop_continuation_conditions(const locationt& loop_id, exprt::operandst &loop_cont) const; diff --git a/src/summarizer/summary_checker_kind.cpp b/src/summarizer/summary_checker_kind.cpp index c7f50b656..e9b0c7506 100644 --- a/src/summarizer/summary_checker_kind.cpp +++ b/src/summarizer/summary_checker_kind.cpp @@ -9,6 +9,7 @@ Author: Peter Schrammel #include "summary_checker_kind.h" #define GIVE_UP_INVARIANTS 7 +//#define UNWIND_ALL /*******************************************************************\ @@ -28,7 +29,7 @@ property_checkert::resultt summary_checker_kindt::operator()( const namespacet ns(goto_model.symbol_table); irep_idt entry_function = goto_model.goto_functions.entry_point(); if(options.get_bool_option("unit-check")) - entry_function = ""; + entry_function = ""; SSA_functions(goto_model,ns); @@ -43,156 +44,168 @@ property_checkert::resultt summary_checker_kindt::operator()( { status() << "Unwinding (k=" << unwind << ")" << eom; summary_db.mark_recompute_all(); //TODO: recompute only functions with loops - //ssa_unwinder.unwind_all(unwind); - + +#ifdef UNWIND_ALL + ssa_unwinder.unwind_all(unwind); +#else // unwind loops "selectively" (those that seem to be the "reason") - for(summarizer_bw_cex_baset::reasont::const_iterator it = reason.begin(); it != reason.end(); ++it){ + for(summarizer_bw_cex_baset::reasont::const_iterator it = reason.begin(); it != reason.end(); ++it) + { for(std::set::const_iterator l_it = it->second.loops.begin(); - l_it != it->second.loops.end(); l_it++){ - ssa_unwinder.unwind_loop_alone(it->first, (*l_it)->location_number, unwind); + l_it != it->second.loops.end(); l_it++) + { + ssa_unwinder.unwind_loop_alone(it->first, (*l_it)->location_number, unwind); } } // inline functions "selectively" (those that seem to be the "reason") - for(summarizer_bw_cex_baset::reasont::const_iterator it = reason.begin(); it != reason.end(); ++it){ + for(summarizer_bw_cex_baset::reasont::const_iterator it = reason.begin(); it != reason.end(); ++it) + { for(std::set::const_iterator f_it = it->second.functions.begin(); - f_it != it->second.functions.end(); f_it++){ - local_SSAt &SSA = ssa_db.get(it->first); + f_it != it->second.functions.end(); f_it++) + { + local_SSAt &SSA = ssa_db.get(it->first); - std::list inline_nodes; - std::vector first_node_equalities; - int counter = ssa_inliner.get_rename_counter(); + std::list inline_nodes; + std::vector first_node_equalities; + int counter = ssa_inliner.get_rename_counter(); - for(local_SSAt::nodest::iterator n_it = SSA.nodes.begin(); - n_it != SSA.nodes.end(); n_it++){ + for(local_SSAt::nodest::iterator n_it = SSA.nodes.begin(); + n_it != SSA.nodes.end(); n_it++) + { - local_SSAt::nodet &node=*n_it; + local_SSAt::nodet &node=*n_it; - if(node.location == *(f_it)){ + if(node.location == *(f_it)) + { - bool clear_function_call = false; + bool clear_function_call = false; - for(local_SSAt::nodet::function_callst::const_iterator fc_it=node.function_calls.begin(); - fc_it!=node.function_calls.end(); fc_it++){ + for(local_SSAt::nodet::function_callst::const_iterator fc_it=node.function_calls.begin(); + fc_it!=node.function_calls.end(); fc_it++) + { - irep_idt fname = to_symbol_expr(fc_it->function()).get_identifier(); - if(ssa_db.exists(fname)) - { - clear_function_call = true; + irep_idt fname = to_symbol_expr(fc_it->function()).get_identifier(); + if(ssa_db.exists(fname)) + { + clear_function_call = true; - local_SSAt &fSSA = ssa_db.get(fname); + local_SSAt &fSSA = ssa_db.get(fname); - exprt guard_binding; - exprt::operandst bindings_in, bindings_out; + exprt guard_binding; + exprt::operandst bindings_in, bindings_out; - // put guard_binding, bindings_in, bindings_out in the caller's SSA (equalities) - ssa_inliner.get_guard_binding(SSA,fSSA,n_it,guard_binding,counter); - equal_exprt e = to_equal_expr(guard_binding); - node.equalities.push_back(e); + // put guard_binding, bindings_in, bindings_out in the caller's SSA (equalities) + ssa_inliner.get_guard_binding(SSA,fSSA,n_it,guard_binding,counter); + equal_exprt e = to_equal_expr(guard_binding); + node.equalities.push_back(e); - ssa_inliner.get_bindings(SSA,fSSA,n_it,fc_it,bindings_in,bindings_out,counter); - - for(exprt::operandst::const_iterator b_it=bindings_in.begin(); - b_it!=bindings_in.end(); b_it++){ - equal_exprt e = to_equal_expr(*b_it); - node.equalities.push_back(e); - } - for(exprt::operandst::const_iterator b_it=bindings_out.begin(); - b_it!=bindings_out.end(); b_it++){ - equal_exprt e = to_equal_expr(*b_it); - node.equalities.push_back(e); - } - - for(local_SSAt::nodest::const_iterator fn_it = fSSA.nodes.begin(); - fn_it != fSSA.nodes.end(); fn_it++){ - local_SSAt::nodet fnode=*fn_it; - inline_nodes.push_back(fnode); - } - - if(fname == entry_function){ - // first_node_equalities should contain all the equalities from the first node of fSSA - for(local_SSAt::nodest::iterator fn_it = fSSA.nodes.begin(); - fn_it != fSSA.nodes.end(); fn_it++){ - local_SSAt::nodet &fnode=*fn_it; - for(local_SSAt::nodet::equalitiest::iterator e_it=fnode.equalities.begin(); - e_it!=fnode.equalities.end(); e_it++){ - first_node_equalities.push_back(*e_it); - } - break; - } - } - else{ - // except those (the one) that start with "ssa::guard" and have true in the rhs - for(local_SSAt::nodest::iterator fn_it = fSSA.nodes.begin(); - fn_it != fSSA.nodes.end(); fn_it++){ - local_SSAt::nodet &fnode=*fn_it; - - bool ignore_equality = true; + ssa_inliner.get_bindings(SSA,fSSA,n_it,fc_it,bindings_in,bindings_out,counter); + + for(exprt::operandst::const_iterator b_it=bindings_in.begin(); + b_it!=bindings_in.end(); b_it++){ + equal_exprt e = to_equal_expr(*b_it); + node.equalities.push_back(e); + } + for(exprt::operandst::const_iterator b_it=bindings_out.begin(); + b_it!=bindings_out.end(); b_it++){ + equal_exprt e = to_equal_expr(*b_it); + node.equalities.push_back(e); + } + + for(local_SSAt::nodest::const_iterator fn_it = fSSA.nodes.begin(); + fn_it != fSSA.nodes.end(); fn_it++){ + local_SSAt::nodet fnode=*fn_it; + inline_nodes.push_back(fnode); + } + + if(fname == entry_function){ + // first_node_equalities should contain all the equalities from the first node of fSSA + for(local_SSAt::nodest::iterator fn_it = fSSA.nodes.begin(); + fn_it != fSSA.nodes.end(); fn_it++){ + local_SSAt::nodet &fnode=*fn_it; + for(local_SSAt::nodet::equalitiest::iterator e_it=fnode.equalities.begin(); + e_it!=fnode.equalities.end(); e_it++){ + first_node_equalities.push_back(*e_it); + } + break; + } + } + else{ + // except those (the one) that start with "ssa::guard" and have true in the rhs + for(local_SSAt::nodest::iterator fn_it = fSSA.nodes.begin(); + fn_it != fSSA.nodes.end(); fn_it++){ + local_SSAt::nodet &fnode=*fn_it; + + bool ignore_equality = true; - for(local_SSAt::nodet::equalitiest::iterator e_it=fnode.equalities.begin(); - e_it!=fnode.equalities.end(); e_it++){ - // unless lhs starts with "ssa::guard" and rhs is true - - equal_exprt e = to_equal_expr(*e_it); - exprt &lhs = e.lhs(); exprt &rhs = e.rhs(); - std::string var_string = id2string(to_symbol_expr(lhs).get_identifier()); - if(((var_string.substr(0,11)) == "ssa::$guard") && (rhs.is_true()) && (ignore_equality == true)){ - ignore_equality = false; - } - else{ - first_node_equalities.push_back(*e_it); - } + for(local_SSAt::nodet::equalitiest::iterator e_it=fnode.equalities.begin(); + e_it!=fnode.equalities.end(); e_it++){ + // unless lhs starts with "ssa::guard" and rhs is true + + equal_exprt e = to_equal_expr(*e_it); + exprt &lhs = e.lhs(); exprt &rhs = e.rhs(); + std::string var_string = id2string(to_symbol_expr(lhs).get_identifier()); + if(((var_string.substr(0,11)) == "ssa::$guard") && (rhs.is_true()) && (ignore_equality == true)){ + ignore_equality = false; + } + else{ + first_node_equalities.push_back(*e_it); + } - } - break; - } - } + } + break; + } + } - } - } + } + } - if(clear_function_call == true) - node.function_calls.clear(); + if(clear_function_call == true) + node.function_calls.clear(); - } - } + } + } - bool replace_first_node_equalities = true; + bool replace_first_node_equalities = true; - if(inline_nodes.size() > 0){ - for(std::list::iterator in_it = inline_nodes.begin(); - in_it != inline_nodes.end(); in_it++){ - local_SSAt::nodet &inline_node = *in_it; - - if(replace_first_node_equalities == true){ - inline_node.equalities.clear(); - for(std::vector::iterator e_it=first_node_equalities.begin(); - e_it!=first_node_equalities.end(); e_it++){ - inline_node.equalities.push_back(*e_it); - } - replace_first_node_equalities = false; - } + if(inline_nodes.size() > 0) + { + for(std::list::iterator in_it = inline_nodes.begin(); + in_it != inline_nodes.end(); in_it++) + { + local_SSAt::nodet &inline_node = *in_it; + + if(replace_first_node_equalities == true) + { + inline_node.equalities.clear(); + for(std::vector::iterator e_it=first_node_equalities.begin(); + e_it!=first_node_equalities.end(); e_it++){ + inline_node.equalities.push_back(*e_it); + } + replace_first_node_equalities = false; + } - for(local_SSAt::nodet::equalitiest::iterator e_it=inline_node.equalities.begin(); - e_it!=inline_node.equalities.end(); e_it++){ - ssa_inliner.rename(*e_it, counter); - } + for(local_SSAt::nodet::equalitiest::iterator e_it=inline_node.equalities.begin(); + e_it!=inline_node.equalities.end(); e_it++){ + ssa_inliner.rename(*e_it, counter); + } - for(local_SSAt::nodet::constraintst::iterator c_it=inline_node.constraints.begin(); - c_it!=inline_node.constraints.end(); c_it++){ - ssa_inliner.rename(*c_it, counter); - } - - for(local_SSAt::nodet::assertionst::iterator a_it=inline_node.assertions.begin(); - a_it!=inline_node.assertions.end(); a_it++){ - ssa_inliner.rename(*a_it, counter); - } - - // push inline_node into SSA - SSA.nodes.push_back(inline_node); + for(local_SSAt::nodet::constraintst::iterator c_it=inline_node.constraints.begin(); + c_it!=inline_node.constraints.end(); c_it++){ + ssa_inliner.rename(*c_it, counter); + } + + for(local_SSAt::nodet::assertionst::iterator a_it=inline_node.assertions.begin(); + a_it!=inline_node.assertions.end(); a_it++){ + ssa_inliner.rename(*a_it, counter); + } + + // push inline_node into SSA + SSA.nodes.push_back(inline_node); - } - } + } + } } } @@ -203,10 +216,11 @@ property_checkert::resultt summary_checker_kindt::operator()( if((options.get_option("spurious-check")!="concrete") && (options.get_option("spurious-check")!="abstract")) { - SSA_dependency_graphs(goto_model, ns); + SSA_dependency_graphs(goto_model, ns); } } - + +#endif std::set seen_function_calls; result = check_properties(entry_function, entry_function, seen_function_calls); if(result == property_checkert::UNKNOWN && @@ -222,13 +236,13 @@ property_checkert::resultt summary_checker_kindt::operator()( if(result == property_checkert::PASS) { status() << "k-induction proof found after " - << unwind << " unwinding(s)" << eom; + << unwind << " unwinding(s)" << eom; break; } else if(result == property_checkert::FAIL) { status() << "k-induction counterexample found after " - << unwind << " unwinding(s)" << eom; + << unwind << " unwinding(s)" << eom; break; } } From 5e9883c0b9c5fcff9ebb5204492d956980894f01 Mon Sep 17 00:00:00 2001 From: Peter Schrammel Date: Sat, 28 May 2016 22:52:45 +0100 Subject: [PATCH 41/82] concrete only complete with inline --- src/summarizer/summarizer_bw_cex_concrete.cpp | 4 ++-- src/summarizer/summary_checker_base.cpp | 4 +++- src/summarizer/summary_checker_kind.cpp | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/summarizer/summarizer_bw_cex_concrete.cpp b/src/summarizer/summarizer_bw_cex_concrete.cpp index cc6268b08..84f025115 100644 --- a/src/summarizer/summarizer_bw_cex_concrete.cpp +++ b/src/summarizer/summarizer_bw_cex_concrete.cpp @@ -101,9 +101,9 @@ property_checkert::resultt summarizer_bw_cex_concretet::check() result = property_checkert::UNKNOWN; } - //we are only complete if we are in the entry function + //we are only complete if everything was inlined if(result == property_checkert::UNKNOWN && - entry_function == error_function) + options.get_bool_option("inline")) { incremental_solvert &solver = ssa_db.get_solver(entry_function); const local_SSAt &ssa = ssa_db.get(entry_function); diff --git a/src/summarizer/summary_checker_base.cpp b/src/summarizer/summary_checker_base.cpp index a96708f22..f7aac91b6 100644 --- a/src/summarizer/summary_checker_base.cpp +++ b/src/summarizer/summary_checker_base.cpp @@ -78,11 +78,13 @@ void summary_checker_baset::SSA_dependency_graphs( ssa_db.depgraph_create(f_it->first, ns, ssa_inliner, true); else ssa_db.depgraph_create(f_it->first, ns, ssa_inliner, false); // change to true if all functions are to be treated equal - + +#if 0 ssa_dependency_grapht &ssa_depgraph = ssa_db.get_depgraph(f_it->first); ssa_depgraph.output(debug()); debug() << eom; std::cout << "output SSA for function: " << f_it->first << "\n"; ssa_db.get(f_it->first).output_verbose(std::cout); +#endif } } diff --git a/src/summarizer/summary_checker_kind.cpp b/src/summarizer/summary_checker_kind.cpp index e9b0c7506..dff7c3f2b 100644 --- a/src/summarizer/summary_checker_kind.cpp +++ b/src/summarizer/summary_checker_kind.cpp @@ -9,7 +9,7 @@ Author: Peter Schrammel #include "summary_checker_kind.h" #define GIVE_UP_INVARIANTS 7 -//#define UNWIND_ALL +#define UNWIND_ALL /*******************************************************************\ From 034901cbf0edb546499ed103603557806d914a04 Mon Sep 17 00:00:00 2001 From: Peter Schrammel Date: Sun, 29 May 2016 10:33:48 +0100 Subject: [PATCH 42/82] take into account enabling_expr in depgraph construction --- src/ssa/local_ssa.cpp | 12 ------------ src/ssa/local_ssa.h | 4 +--- src/ssa/ssa_dependency_graph.cpp | 24 ++++++++++++++++++++++-- src/ssa/ssa_unwinder.cpp | 8 +++----- 4 files changed, 26 insertions(+), 22 deletions(-) diff --git a/src/ssa/local_ssa.cpp b/src/ssa/local_ssa.cpp index 78eea63d7..5395082f7 100644 --- a/src/ssa/local_ssa.cpp +++ b/src/ssa/local_ssa.cpp @@ -1839,7 +1839,6 @@ Function: local_SSAt::has_function_calls bool local_SSAt::has_function_calls() const { - /* bool found=false; for(local_SSAt::nodest::const_iterator n_it=nodes.begin(); n_it!=nodes.end(); n_it++) @@ -1851,15 +1850,4 @@ bool local_SSAt::has_function_calls() const } } return found; - */ - - - if(combined_enabling_expr.is_not_nil()){ - std::cout << "combined enabling expr:" << from_expr(ns, "", combined_enabling_expr) << "\n"; - return combined_enabling_expr; - } - else{ - std::cout << "combined enabling expr is nil; returning true\n"; - return true_exprt(); - } } diff --git a/src/ssa/local_ssa.h b/src/ssa/local_ssa.h index 9fd429725..f414d0e66 100644 --- a/src/ssa/local_ssa.h +++ b/src/ssa/local_ssa.h @@ -120,9 +120,7 @@ class local_SSAt } // for incremental unwinding - std::list enabling_exprs; - - exprt combined_enabling_expr = true_exprt(); // combined enabling expr for loop-specific unwindings + std::vector enabling_exprs; exprt get_enabling_exprs() const; // function entry and exit variables diff --git a/src/ssa/ssa_dependency_graph.cpp b/src/ssa/ssa_dependency_graph.cpp index fc7875824..3a34a14e1 100644 --- a/src/ssa/ssa_dependency_graph.cpp +++ b/src/ssa/ssa_dependency_graph.cpp @@ -75,10 +75,30 @@ void ssa_dependency_grapht::create(const local_SSAt &SSA, ssa_inlinert &ssa_inli bool ignore_equality_done = false; for(local_SSAt::nodest::const_iterator n_it = SSA.nodes.begin(); - n_it != SSA.nodes.end(); n_it++){ - + n_it != SSA.nodes.end(); n_it++) + { const local_SSAt::nodet &node=*n_it; + // check whether this node is enabled + if(!node.enabling_expr.is_true()) + { + bool enabled=true; + const irep_idt &enable=to_symbol_expr(node.enabling_expr).get_identifier(); + for(size_t i=0; isecond).loop_enabling_exprs).end()) - ssa_current_enabling_expr.push_back(not_exprt(*e_it)); + SSA.enabling_exprs.push_back(not_exprt(*e_it)); else - ssa_current_enabling_expr.push_back(*e_it); + SSA.enabling_exprs.push_back(*e_it); } } - - SSA.combined_enabling_expr = conjunction(ssa_current_enabling_expr); } From 682b15ed7518207553019e495800c838072ca875 Mon Sep 17 00:00:00 2001 From: Peter Schrammel Date: Sun, 29 May 2016 11:30:20 +0100 Subject: [PATCH 43/82] fixed all no-cex regressions for complete --- regression/modular/{nocex7 => kind6}/main.c | 0 .../modular/{nocex7 => kind6}/test.desc | 2 +- regression/modular/nocex6/test.desc | 4 +-- src/ssa/local_ssa.cpp | 35 ++++++++++--------- src/ssa/ssa_unwinder.cpp | 3 ++ src/summarizer/summary_checker_ai.cpp | 2 ++ 6 files changed, 27 insertions(+), 19 deletions(-) rename regression/modular/{nocex7 => kind6}/main.c (100%) rename regression/modular/{nocex7 => kind6}/test.desc (72%) diff --git a/regression/modular/nocex7/main.c b/regression/modular/kind6/main.c similarity index 100% rename from regression/modular/nocex7/main.c rename to regression/modular/kind6/main.c diff --git a/regression/modular/nocex7/test.desc b/regression/modular/kind6/test.desc similarity index 72% rename from regression/modular/nocex7/test.desc rename to regression/modular/kind6/test.desc index dc053e6ab..630457914 100644 --- a/regression/modular/nocex7/test.desc +++ b/regression/modular/kind6/test.desc @@ -1,6 +1,6 @@ CORE main.c ---havoc +--havoc --k-induction ^EXIT=0$ ^SIGNAL=0$ ^VERIFICATION SUCCESSFUL$ diff --git a/regression/modular/nocex6/test.desc b/regression/modular/nocex6/test.desc index 895f3abe9..1f240717a 100644 --- a/regression/modular/nocex6/test.desc +++ b/regression/modular/nocex6/test.desc @@ -1,6 +1,6 @@ CORE main.c --havoc --unwind 2 -^EXIT=10$ +^EXIT=5$ ^SIGNAL=0$ -^VERIFICATION FAILED$ +^VERIFICATION INCONCLUSIVE$ diff --git a/src/ssa/local_ssa.cpp b/src/ssa/local_ssa.cpp index 5395082f7..254ef3920 100644 --- a/src/ssa/local_ssa.cpp +++ b/src/ssa/local_ssa.cpp @@ -152,21 +152,21 @@ void local_SSAt::get_nondet_vars() n_it!=nodes.end(); n_it++) { for(nodet::equalitiest::const_iterator - e_it=n_it->equalities.begin(); - e_it!=n_it->equalities.end(); - e_it++) + e_it=n_it->equalities.begin(); + e_it!=n_it->equalities.end(); + e_it++) get_nondet_vars(*e_it); for(nodet::constraintst::const_iterator - c_it=n_it->constraints.begin(); - c_it!=n_it->constraints.end(); - c_it++) + c_it=n_it->constraints.begin(); + c_it!=n_it->constraints.end(); + c_it++) get_nondet_vars(*c_it); for(nodet::assertionst::const_iterator - a_it=n_it->assertions.begin(); - a_it!=n_it->assertions.end(); - a_it++) + a_it=n_it->assertions.begin(); + a_it!=n_it->assertions.end(); + a_it++) get_nondet_vars(*a_it); } } @@ -204,7 +204,7 @@ void local_SSAt::get_globals( bool is_return=id2string(it->get_identifier()).find( "#return_value")!=std::string::npos; if(!with_returns && is_return) - continue; + continue; // filter out return values of other functions if(with_returns && returns_for_function!="" && @@ -641,7 +641,7 @@ void local_SSAt::build_function_call(locationt loc) } else { - n_it->equalities.push_back(equal_exprt(arg,*it)); + n_it->equalities.push_back(equal_exprt(arg,*it)); } *it=arg; } @@ -1270,7 +1270,10 @@ symbol_exprt local_SSAt::name( unsigned cnt=loc->location_number; irep_idt new_id=id2string(id)+"#"+ - (kind==PHI?"phi":kind==LOOP_BACK?"lb":kind==LOOP_SELECT?"ls":"")+ + (kind==PHI?"phi": + kind==LOOP_BACK?"lb": + kind==LOOP_SELECT?"ls": + "")+ i2string(cnt)+ (kind==LOOP_SELECT?std::string(""):suffix); @@ -1672,7 +1675,7 @@ std::list &operator<<( e_it++) { if(!n_it->enabling_expr.is_true()) - dest.push_back(implies_exprt(n_it->enabling_expr,*e_it)); + dest.push_back(implies_exprt(n_it->enabling_expr,*e_it)); else dest.push_back(*e_it); } @@ -1683,7 +1686,7 @@ std::list &operator<<( c_it++) { if(!n_it->enabling_expr.is_true()) - dest.push_back(implies_exprt(n_it->enabling_expr,*c_it)); + dest.push_back(implies_exprt(n_it->enabling_expr,*c_it)); else dest.push_back(*c_it); } @@ -1718,7 +1721,7 @@ decision_proceduret &operator<<( e_it++) { if(!n_it->enabling_expr.is_true()) - dest.push_back(implies_exprt(n_it->enabling_expr,*e_it)); + dest.push_back(implies_exprt(n_it->enabling_expr,*e_it)); else dest.push_back(*e_it); } @@ -1729,7 +1732,7 @@ decision_proceduret &operator<<( c_it++) { if(!n_it->enabling_expr.is_true()) - dest.push_back(implies_exprt(n_it->enabling_expr,*c_it)); + dest.push_back(implies_exprt(n_it->enabling_expr,*c_it)); else dest.push_back(*c_it); } diff --git a/src/ssa/ssa_unwinder.cpp b/src/ssa/ssa_unwinder.cpp index c81006be0..7381a8d75 100644 --- a/src/ssa/ssa_unwinder.cpp +++ b/src/ssa/ssa_unwinder.cpp @@ -859,6 +859,9 @@ void ssa_local_unwindert::loop_continuation_conditions( const locationt& loop_id, exprt::operandst &loop_cont) const { + if(loops.empty()) //ignore silently, TBD + return; + const loopt &loop = loops.at(loop_id->location_number); loop_cont.insert(loop_cont.end(), loop.current_continuation_conditions.begin(), diff --git a/src/summarizer/summary_checker_ai.cpp b/src/summarizer/summary_checker_ai.cpp index f1bf9b8ba..16008db7f 100644 --- a/src/summarizer/summary_checker_ai.cpp +++ b/src/summarizer/summary_checker_ai.cpp @@ -42,6 +42,7 @@ property_checkert::resultt summary_checker_ait::operator()( ssa_unwinder.output(debug()); debug() < Date: Sun, 29 May 2016 13:30:06 +0100 Subject: [PATCH 44/82] factor out SSA refinements into separate classes --- src/ssa/Makefile | 4 +- src/ssa/ssa_refiner.h | 21 +++ src/ssa/ssa_refiner_monolithic.cpp | 30 ++++ src/ssa/ssa_refiner_monolithic.h | 44 ++++++ src/ssa/ssa_refiner_selective.cpp | 195 +++++++++++++++++++++++ src/ssa/ssa_refiner_selective.h | 74 +++++++++ src/ssa/ssa_unwinder.cpp | 27 ++++ src/ssa/ssa_unwinder.h | 2 + src/summarizer/summarizer_bw_cex.h | 25 +-- src/summarizer/summary_checker_bmc.cpp | 21 ++- src/summarizer/summary_checker_kind.cpp | 200 +++--------------------- 11 files changed, 443 insertions(+), 200 deletions(-) create mode 100644 src/ssa/ssa_refiner.h create mode 100644 src/ssa/ssa_refiner_monolithic.cpp create mode 100644 src/ssa/ssa_refiner_monolithic.h create mode 100644 src/ssa/ssa_refiner_selective.cpp create mode 100644 src/ssa/ssa_refiner_selective.h diff --git a/src/ssa/Makefile b/src/ssa/Makefile index 0c4c0263f..08f82cbb2 100644 --- a/src/ssa/Makefile +++ b/src/ssa/Makefile @@ -3,7 +3,9 @@ SRC = local_ssa.cpp \ guard_map.cpp ssa_object.cpp assignments.cpp ssa_dereference.cpp \ ssa_value_set.cpp address_canonizer.cpp simplify_ssa.cpp \ ssa_build_goto_trace.cpp ssa_inliner.cpp ssa_unwinder.cpp \ - unwindable_local_ssa.cpp ssa_db.cpp + unwindable_local_ssa.cpp split_loopheads.cpp const_propagator.cpp ssa_const_propagator.cpp \ + replace_symbol_ext.cpp ssa_dependency_graph.cpp \ + ssa_refiner_monolithic.cpp ssa_refiner_selective.cpp include ../config.inc include $(CBMC)/src/config.inc diff --git a/src/ssa/ssa_refiner.h b/src/ssa/ssa_refiner.h new file mode 100644 index 000000000..0c933e0da --- /dev/null +++ b/src/ssa/ssa_refiner.h @@ -0,0 +1,21 @@ +/*******************************************************************\ + +Module: SSA Refiner Base Class + +Author: Peter Schrammel + +\*******************************************************************/ + +#ifndef CPROVER_SSA_REFINER_H +#define CPROVER_SSA_REFINER_H + +#include + +class ssa_refinert : public messaget +{ + public: + virtual bool operator()() { assert(false); } + virtual unsigned get_unwind() { assert(false); } +}; + +#endif diff --git a/src/ssa/ssa_refiner_monolithic.cpp b/src/ssa/ssa_refiner_monolithic.cpp new file mode 100644 index 000000000..a7191481c --- /dev/null +++ b/src/ssa/ssa_refiner_monolithic.cpp @@ -0,0 +1,30 @@ +/*******************************************************************\ + +Module: SSA Refiner for Monolithic Analysis + +Author: Peter Schrammel + +\*******************************************************************/ + +#include "ssa_refiner_monolithic.h" + +/*******************************************************************\ + +Function: ssa_refiner_monolithict::operator() + + Inputs: + + Outputs: + + Purpose: refine all + +\*******************************************************************/ + +bool ssa_refiner_monolithict::operator()() +{ + status() << "Unwinding (k=" << unwind << ")" << eom; + summary_db.mark_recompute_all(); //TODO: recompute only functions with loops + ssa_unwinder.unwind_all(unwind); + + return unwind++::const_iterator l_it = + it->second.loops.begin(); + l_it != it->second.loops.end(); l_it++) + { + unsigned new_unwind = ssa_unwinder.unwind_loop_once_more(it->first, + (*l_it)->location_number); + unwind = std::max(unwind, new_unwind); + } + } + +#if 0 + // inline functions "selectively" (those that seem to be the "reason") + for(reasont::const_iterator it = reason.begin(); it != reason.end(); ++it) + { + for(std::set::const_iterator f_it = + it->second.functions.begin(); + f_it != it->second.functions.end(); f_it++) + { + local_SSAt &SSA = ssa_db.get(it->first); + + std::list inline_nodes; + std::vector first_node_equalities; + int counter = ssa_inliner.get_rename_counter(); + + for(local_SSAt::nodest::iterator n_it = SSA.nodes.begin(); + n_it != SSA.nodes.end(); n_it++) + { + + local_SSAt::nodet &node=*n_it; + + if(node.location == *(f_it)) + { + + bool clear_function_call = false; + + for(local_SSAt::nodet::function_callst::const_iterator fc_it = + node.function_calls.begin(); + fc_it!=node.function_calls.end(); fc_it++) + { + + irep_idt fname = to_symbol_expr(fc_it->function()).get_identifier(); + if(ssa_db.exists(fname)) + { + clear_function_call = true; + + local_SSAt &fSSA = ssa_db.get(fname); + + exprt guard_binding; + exprt::operandst bindings_in, bindings_out; + + // put guard_binding, bindings_in, bindings_out in the caller's SSA (equalities) + ssa_inliner.get_guard_binding(SSA,fSSA,n_it,guard_binding,counter); + equal_exprt e = to_equal_expr(guard_binding); + node.equalities.push_back(e); + + ssa_inliner.get_bindings(SSA,fSSA,n_it,fc_it,bindings_in,bindings_out,counter); + + for(exprt::operandst::const_iterator b_it=bindings_in.begin(); + b_it!=bindings_in.end(); b_it++){ + equal_exprt e = to_equal_expr(*b_it); + node.equalities.push_back(e); + } + for(exprt::operandst::const_iterator b_it=bindings_out.begin(); + b_it!=bindings_out.end(); b_it++){ + equal_exprt e = to_equal_expr(*b_it); + node.equalities.push_back(e); + } + + for(local_SSAt::nodest::const_iterator fn_it = fSSA.nodes.begin(); + fn_it != fSSA.nodes.end(); fn_it++){ + local_SSAt::nodet fnode=*fn_it; + inline_nodes.push_back(fnode); + } + + if(fname == entry_function){ + // first_node_equalities should contain all the equalities from the first node of fSSA + for(local_SSAt::nodest::iterator fn_it = fSSA.nodes.begin(); + fn_it != fSSA.nodes.end(); fn_it++){ + local_SSAt::nodet &fnode=*fn_it; + for(local_SSAt::nodet::equalitiest::iterator e_it=fnode.equalities.begin(); + e_it!=fnode.equalities.end(); e_it++){ + first_node_equalities.push_back(*e_it); + } + break; + } + } + else{ + // except those (the one) that start with "ssa::guard" and have true in the rhs + for(local_SSAt::nodest::iterator fn_it = fSSA.nodes.begin(); + fn_it != fSSA.nodes.end(); fn_it++){ + local_SSAt::nodet &fnode=*fn_it; + + bool ignore_equality = true; + + for(local_SSAt::nodet::equalitiest::iterator e_it=fnode.equalities.begin(); + e_it!=fnode.equalities.end(); e_it++){ + // unless lhs starts with "ssa::guard" and rhs is true + + equal_exprt e = to_equal_expr(*e_it); + exprt &lhs = e.lhs(); exprt &rhs = e.rhs(); + std::string var_string = id2string(to_symbol_expr(lhs).get_identifier()); + if(((var_string.substr(0,11)) == "ssa::$guard") && (rhs.is_true()) && (ignore_equality == true)){ + ignore_equality = false; + } + else{ + first_node_equalities.push_back(*e_it); + } + + } + break; + } + } + + } + } + + if(clear_function_call == true) + node.function_calls.clear(); + + } + } + + bool replace_first_node_equalities = true; + + if(inline_nodes.size() > 0) + { + for(std::list::iterator in_it = inline_nodes.begin(); + in_it != inline_nodes.end(); in_it++) + { + local_SSAt::nodet &inline_node = *in_it; + + if(replace_first_node_equalities == true) + { + inline_node.equalities.clear(); + for(std::vector::iterator e_it=first_node_equalities.begin(); + e_it!=first_node_equalities.end(); e_it++){ + inline_node.equalities.push_back(*e_it); + } + replace_first_node_equalities = false; + } + + for(local_SSAt::nodet::equalitiest::iterator e_it=inline_node.equalities.begin(); + e_it!=inline_node.equalities.end(); e_it++){ + ssa_inliner.rename(*e_it, counter); + } + + for(local_SSAt::nodet::constraintst::iterator c_it=inline_node.constraints.begin(); + c_it!=inline_node.constraints.end(); c_it++){ + ssa_inliner.rename(*c_it, counter); + } + + for(local_SSAt::nodet::assertionst::iterator a_it=inline_node.assertions.begin(); + a_it!=inline_node.assertions.end(); a_it++){ + ssa_inliner.rename(*a_it, counter); + } + + // push inline_node into SSA + SSA.nodes.push_back(inline_node); + + } + } + + } + } +#endif + + return unwind functions; + std::set loops; + }; + + class reasont : public std::map + { + public: + void merge(const reasont &other) + { + for(reasont::const_iterator it = other.begin(); + it != other.end(); ++it) + { + reason_infot &r = (*this)[it->first]; + r.functions.insert(it->second.functions.begin(), + it->second.functions.end()); + r.loops.insert(it->second.loops.begin(), it->second.loops.end()); + } + } + }; + + + explicit ssa_refiner_selectivet( + ssa_dbt &_ssa_db, + ssa_unwindert &_ssa_unwinder, + unsigned _max_unwind, + ssa_inlinert &_ssa_inliner, + reasont &_reason + ) : + ssa_db(_ssa_db), + ssa_unwinder(_ssa_unwinder), + max_unwind(_max_unwind), + ssa_inliner(_ssa_inliner), + reason(_reason) + {} + + virtual bool operator()(); + virtual unsigned get_unwind() { return unwind; } + + protected: + ssa_dbt &ssa_db; + ssa_unwindert &ssa_unwinder; + const unsigned max_unwind; + ssa_inlinert &ssa_inliner; + unsigned unwind; + reasont &reason; +}; + +#endif diff --git a/src/ssa/ssa_unwinder.cpp b/src/ssa/ssa_unwinder.cpp index 7381a8d75..dbc5878c0 100644 --- a/src/ssa/ssa_unwinder.cpp +++ b/src/ssa/ssa_unwinder.cpp @@ -277,6 +277,13 @@ void ssa_local_unwindert::build_exit_conditions() * *****************************************************************************/ +unsigned ssa_local_unwindert::unwind_loop_at_location(unsigned loc) +{ + unsigned k = loops.at(loc).current_unwinding+1; + unwind_loop_at_location(loc,k); + return k; +} + void ssa_local_unwindert::unwind_loop_at_location(unsigned loc, unsigned k) { if(SSA.current_unwinding>=(long)k) @@ -996,6 +1003,26 @@ void ssa_unwindert::unwind_loop_alone(const irep_idt fname, unsigned loc, unsign it->second.unwind_loop_at_location(loc, k); } +/*****************************************************************************\ + * + * Function : ssa_unwindert::unwind_loop_once_more() + * + * Input : + * + * Output : + * + * Purpose : + * + *****************************************************************************/ + +unsigned ssa_unwindert::unwind_loop_once_more(const irep_idt fname, unsigned loc) +{ + assert(is_initialized); + unwinder_mapt::iterator it = unwinder_map.find(fname); + assert(it != unwinder_map.end()); + return it->second.unwind_loop_at_location(loc); +} + /*******************************************************************\ diff --git a/src/ssa/ssa_unwinder.h b/src/ssa/ssa_unwinder.h index a0cc486d2..20d376fc6 100644 --- a/src/ssa/ssa_unwinder.h +++ b/src/ssa/ssa_unwinder.h @@ -33,6 +33,7 @@ class ssa_local_unwindert void init(); void unwind_loop_at_location(unsigned loc, unsigned k); + unsigned unwind_loop_at_location(unsigned loc); void unwind(unsigned k); #if 0 @@ -150,6 +151,7 @@ class ssa_unwindert:public messaget void init_localunwinders(); void unwind_loop_alone(const irep_idt fname, unsigned loc, unsigned k); + unsigned unwind_loop_once_more(const irep_idt fname, unsigned loc); void unwind(const irep_idt fname, unsigned k); void unwind_all(unsigned k); diff --git a/src/summarizer/summarizer_bw_cex.h b/src/summarizer/summarizer_bw_cex.h index b76a214fb..8da077347 100644 --- a/src/summarizer/summarizer_bw_cex.h +++ b/src/summarizer/summarizer_bw_cex.h @@ -14,6 +14,7 @@ Author: Kumar Madhukar, Peter Schrammel #include #include "../ssa/ssa_inliner.h" #include "../ssa/ssa_unwinder.h" +#include "../ssa/ssa_refiner_selective.h" #include "../ssa/local_ssa.h" #include "ssa_db.h" @@ -22,29 +23,7 @@ Author: Kumar Madhukar, Peter Schrammel class summarizer_bw_cex_baset : public summarizer_bwt { public: - struct reason_infot - { - typedef local_SSAt::locationt function_infot; //call_site; restriction: we assume that there is a single function call in an SSA node - typedef local_SSAt::locationt loop_infot; - std::set functions; - std::set loops; - }; - - class reasont : public std::map - { - public: - void merge(const reasont &other) - { - for(reasont::const_iterator it = other.begin(); - it != other.end(); ++it) - { - reason_infot &r = (*this)[it->first]; - r.functions.insert(it->second.functions.begin(), - it->second.functions.end()); - r.loops.insert(it->second.loops.begin(), it->second.loops.end()); - } - } - }; + typedef ssa_refiner_selectivet::reasont reasont; virtual void summarize(); virtual void summarize(const function_namet &entry_function); diff --git a/src/summarizer/summary_checker_bmc.cpp b/src/summarizer/summary_checker_bmc.cpp index 1428f7acc..9efbbc98b 100644 --- a/src/summarizer/summary_checker_bmc.cpp +++ b/src/summarizer/summary_checker_bmc.cpp @@ -8,6 +8,10 @@ Author: Peter Schrammel #include "summary_checker_bmc.h" +#include "../ssa/ssa_refiner.h" +#include "../ssa/ssa_refiner_monolithic.h" +#include "../ssa/ssa_refiner_selective.h" + /*******************************************************************\ @@ -38,7 +42,17 @@ property_checkert::resultt summary_checker_bmct::operator()( status() << "Max-unwind is " << max_unwind << eom; ssa_unwinder.init_localunwinders(); - for(unsigned unwind = 0; unwind<=max_unwind; unwind++) + ssa_refinert *ssa_refiner; + if((options.get_bool_option("inline"))) + ssa_refiner = new ssa_refiner_monolithict(summary_db, ssa_unwinder, + max_unwind); + else + ssa_refiner = new ssa_refiner_selectivet(ssa_db, ssa_unwinder, + max_unwind, ssa_inliner, reason); + ssa_refiner->set_message_handler(get_message_handler()); + + //while can refine + while((*ssa_refiner)()) { status() << "Unwinding (k=" << unwind << ")" << messaget::eom; summary_db.mark_recompute_all(); @@ -50,12 +64,15 @@ property_checkert::resultt summary_checker_bmct::operator()( if((options.get_option("spurious-check")!="concrete") && (options.get_option("spurious-check")!="abstract")) { - SSA_dependency_graphs(goto_model, ns); + SSA_dependency_graphs(goto_model, ns); } } + //check std::set seen_function_calls; result = check_properties(entry_function, entry_function, seen_function_calls); + + //result if(result == property_checkert::PASS) { status() << "incremental BMC proof found after " diff --git a/src/summarizer/summary_checker_kind.cpp b/src/summarizer/summary_checker_kind.cpp index dff7c3f2b..c35506d0a 100644 --- a/src/summarizer/summary_checker_kind.cpp +++ b/src/summarizer/summary_checker_kind.cpp @@ -1,15 +1,17 @@ /*******************************************************************\ -Module: Summarizer Checker for k-induction +Module: Summary Checker for k-induction Author: Peter Schrammel \*******************************************************************/ #include "summary_checker_kind.h" +#include "../ssa/ssa_refiner.h" +#include "../ssa/ssa_refiner_monolithic.h" +#include "../ssa/ssa_refiner_selective.h" #define GIVE_UP_INVARIANTS 7 -#define UNWIND_ALL /*******************************************************************\ @@ -40,175 +42,19 @@ property_checkert::resultt summary_checker_kindt::operator()( status() << "Max-unwind is " << max_unwind << eom; ssa_unwinder.init_localunwinders(); - for(unsigned unwind = 0; unwind<=max_unwind; unwind++) + ssa_refinert *ssa_refiner; + if((options.get_bool_option("inline"))) + ssa_refiner = new ssa_refiner_monolithict(summary_db, ssa_unwinder, + max_unwind); + else + ssa_refiner = new ssa_refiner_selectivet(ssa_db, ssa_unwinder, + max_unwind, ssa_inliner, reason); + ssa_refiner->set_message_handler(get_message_handler()); + + //while can refine + while((*ssa_refiner)()) { - status() << "Unwinding (k=" << unwind << ")" << eom; - summary_db.mark_recompute_all(); //TODO: recompute only functions with loops - -#ifdef UNWIND_ALL - ssa_unwinder.unwind_all(unwind); -#else - // unwind loops "selectively" (those that seem to be the "reason") - for(summarizer_bw_cex_baset::reasont::const_iterator it = reason.begin(); it != reason.end(); ++it) - { - for(std::set::const_iterator l_it = it->second.loops.begin(); - l_it != it->second.loops.end(); l_it++) - { - ssa_unwinder.unwind_loop_alone(it->first, (*l_it)->location_number, unwind); - } - } - - // inline functions "selectively" (those that seem to be the "reason") - for(summarizer_bw_cex_baset::reasont::const_iterator it = reason.begin(); it != reason.end(); ++it) - { - for(std::set::const_iterator f_it = it->second.functions.begin(); - f_it != it->second.functions.end(); f_it++) - { - local_SSAt &SSA = ssa_db.get(it->first); - - std::list inline_nodes; - std::vector first_node_equalities; - int counter = ssa_inliner.get_rename_counter(); - - for(local_SSAt::nodest::iterator n_it = SSA.nodes.begin(); - n_it != SSA.nodes.end(); n_it++) - { - - local_SSAt::nodet &node=*n_it; - - if(node.location == *(f_it)) - { - - bool clear_function_call = false; - - for(local_SSAt::nodet::function_callst::const_iterator fc_it=node.function_calls.begin(); - fc_it!=node.function_calls.end(); fc_it++) - { - - irep_idt fname = to_symbol_expr(fc_it->function()).get_identifier(); - if(ssa_db.exists(fname)) - { - clear_function_call = true; - - local_SSAt &fSSA = ssa_db.get(fname); - - exprt guard_binding; - exprt::operandst bindings_in, bindings_out; - - // put guard_binding, bindings_in, bindings_out in the caller's SSA (equalities) - ssa_inliner.get_guard_binding(SSA,fSSA,n_it,guard_binding,counter); - equal_exprt e = to_equal_expr(guard_binding); - node.equalities.push_back(e); - - ssa_inliner.get_bindings(SSA,fSSA,n_it,fc_it,bindings_in,bindings_out,counter); - - for(exprt::operandst::const_iterator b_it=bindings_in.begin(); - b_it!=bindings_in.end(); b_it++){ - equal_exprt e = to_equal_expr(*b_it); - node.equalities.push_back(e); - } - for(exprt::operandst::const_iterator b_it=bindings_out.begin(); - b_it!=bindings_out.end(); b_it++){ - equal_exprt e = to_equal_expr(*b_it); - node.equalities.push_back(e); - } - - for(local_SSAt::nodest::const_iterator fn_it = fSSA.nodes.begin(); - fn_it != fSSA.nodes.end(); fn_it++){ - local_SSAt::nodet fnode=*fn_it; - inline_nodes.push_back(fnode); - } - - if(fname == entry_function){ - // first_node_equalities should contain all the equalities from the first node of fSSA - for(local_SSAt::nodest::iterator fn_it = fSSA.nodes.begin(); - fn_it != fSSA.nodes.end(); fn_it++){ - local_SSAt::nodet &fnode=*fn_it; - for(local_SSAt::nodet::equalitiest::iterator e_it=fnode.equalities.begin(); - e_it!=fnode.equalities.end(); e_it++){ - first_node_equalities.push_back(*e_it); - } - break; - } - } - else{ - // except those (the one) that start with "ssa::guard" and have true in the rhs - for(local_SSAt::nodest::iterator fn_it = fSSA.nodes.begin(); - fn_it != fSSA.nodes.end(); fn_it++){ - local_SSAt::nodet &fnode=*fn_it; - - bool ignore_equality = true; - - for(local_SSAt::nodet::equalitiest::iterator e_it=fnode.equalities.begin(); - e_it!=fnode.equalities.end(); e_it++){ - // unless lhs starts with "ssa::guard" and rhs is true - - equal_exprt e = to_equal_expr(*e_it); - exprt &lhs = e.lhs(); exprt &rhs = e.rhs(); - std::string var_string = id2string(to_symbol_expr(lhs).get_identifier()); - if(((var_string.substr(0,11)) == "ssa::$guard") && (rhs.is_true()) && (ignore_equality == true)){ - ignore_equality = false; - } - else{ - first_node_equalities.push_back(*e_it); - } - - } - break; - } - } - - } - } - - if(clear_function_call == true) - node.function_calls.clear(); - - } - } - - bool replace_first_node_equalities = true; - - if(inline_nodes.size() > 0) - { - for(std::list::iterator in_it = inline_nodes.begin(); - in_it != inline_nodes.end(); in_it++) - { - local_SSAt::nodet &inline_node = *in_it; - - if(replace_first_node_equalities == true) - { - inline_node.equalities.clear(); - for(std::vector::iterator e_it=first_node_equalities.begin(); - e_it!=first_node_equalities.end(); e_it++){ - inline_node.equalities.push_back(*e_it); - } - replace_first_node_equalities = false; - } - - for(local_SSAt::nodet::equalitiest::iterator e_it=inline_node.equalities.begin(); - e_it!=inline_node.equalities.end(); e_it++){ - ssa_inliner.rename(*e_it, counter); - } - - for(local_SSAt::nodet::constraintst::iterator c_it=inline_node.constraints.begin(); - c_it!=inline_node.constraints.end(); c_it++){ - ssa_inliner.rename(*c_it, counter); - } - - for(local_SSAt::nodet::assertionst::iterator a_it=inline_node.assertions.begin(); - a_it!=inline_node.assertions.end(); a_it++){ - ssa_inliner.rename(*a_it, counter); - } - - // push inline_node into SSA - SSA.nodes.push_back(inline_node); - - } - } - - } - } + unsigned unwind = ssa_refiner->get_unwind(); //dependency graphs if(!(options.get_bool_option("inline"))) @@ -219,10 +65,13 @@ property_checkert::resultt summary_checker_kindt::operator()( SSA_dependency_graphs(goto_model, ns); } } - -#endif + + //check std::set seen_function_calls; - result = check_properties(entry_function, entry_function, seen_function_calls); + result = check_properties(entry_function, entry_function, + seen_function_calls); + + //do static analysis and check again if(result == property_checkert::UNKNOWN && !options.get_bool_option("havoc") && (unwind seen_function_calls; - result = check_properties(entry_function, entry_function, seen_function_calls); + result = check_properties(entry_function, entry_function, + seen_function_calls); } + //result if(result == property_checkert::PASS) { status() << "k-induction proof found after " @@ -246,6 +97,7 @@ property_checkert::resultt summary_checker_kindt::operator()( break; } } + delete ssa_refiner; report_statistics(); return result; } From 9dd6ae630ca1af4c2e92a2b3d91c5cb9c75afcc2 Mon Sep 17 00:00:00 2001 From: Peter Schrammel Date: Sun, 29 May 2016 16:16:00 +0100 Subject: [PATCH 45/82] unwind output one-off --- src/ssa/ssa_refiner_monolithic.h | 2 +- src/ssa/ssa_refiner_selective.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ssa/ssa_refiner_monolithic.h b/src/ssa/ssa_refiner_monolithic.h index 5bdc562f0..77a86fde3 100644 --- a/src/ssa/ssa_refiner_monolithic.h +++ b/src/ssa/ssa_refiner_monolithic.h @@ -32,7 +32,7 @@ class ssa_refiner_monolithict : public ssa_refinert {} virtual bool operator()(); - virtual unsigned get_unwind() { return unwind; } + virtual unsigned get_unwind() { return unwind>0 ? unwind-1 : 0; } protected: summary_dbt &summary_db; diff --git a/src/ssa/ssa_refiner_selective.h b/src/ssa/ssa_refiner_selective.h index 72e40af87..f97329f01 100644 --- a/src/ssa/ssa_refiner_selective.h +++ b/src/ssa/ssa_refiner_selective.h @@ -60,7 +60,7 @@ class ssa_refiner_selectivet : public ssa_refinert {} virtual bool operator()(); - virtual unsigned get_unwind() { return unwind; } + virtual unsigned get_unwind() { return unwind>0 ? unwind-1 : 0; } protected: ssa_dbt &ssa_db; From 743a5f56d2943b41438ab36e382d26ab6d664953 Mon Sep 17 00:00:00 2001 From: Peter Schrammel Date: Sun, 29 May 2016 16:59:59 +0100 Subject: [PATCH 46/82] flag functions as inlined and debug output in ssa_refiner about what is being refined --- src/ssa/local_ssa.h | 9 ++++---- src/ssa/ssa_refiner_selective.cpp | 21 +++++++++++++++++++ src/summarizer/summarizer_bw_cex_concrete.cpp | 11 +++++++++- 3 files changed, 36 insertions(+), 5 deletions(-) diff --git a/src/ssa/local_ssa.h b/src/ssa/local_ssa.h index f414d0e66..adbc2862f 100644 --- a/src/ssa/local_ssa.h +++ b/src/ssa/local_ssa.h @@ -57,11 +57,11 @@ class local_SSAt public: inline nodet( locationt _location, - std::list::iterator _loophead) - : + std::list::iterator _loophead): enabling_expr(true_exprt()), - marked(false), - location(_location), + marked(false), + function_calls_inlined(false), + location(_location), loophead(_loophead) { } @@ -80,6 +80,7 @@ class local_SSAt typedef std::vector function_callst; function_callst function_calls; + bool function_calls_inlined; exprt enabling_expr; // for incremental unwinding bool marked; // for incremental unwinding diff --git a/src/ssa/ssa_refiner_selective.cpp b/src/ssa/ssa_refiner_selective.cpp index 4406cbb75..1d77dc29f 100644 --- a/src/ssa/ssa_refiner_selective.cpp +++ b/src/ssa/ssa_refiner_selective.cpp @@ -31,10 +31,31 @@ bool ssa_refiner_selectivet::operator()() { unsigned new_unwind = ssa_unwinder.unwind_loop_once_more(it->first, (*l_it)->location_number); + debug() << "Refining function " << it->first << ": unwinding loop at " + << (*l_it)->location_number << " (k=" << new_unwind << ")" << eom; unwind = std::max(unwind, new_unwind); } } + // inline functions "selectively" (those that seem to be the "reason") + for(reasont::const_iterator it = reason.begin(); it != reason.end(); ++it) + { + for(std::set::const_iterator f_it = + it->second.functions.begin(); + f_it != it->second.functions.end(); f_it++) + { + local_SSAt &SSA = ssa_db.get(it->first); + local_SSAt::nodest::iterator n_it = SSA.find_node(*f_it); + assert(n_it->function_calls.size()==1); + n_it->function_calls_inlined = true; + + irep_idt fname = to_symbol_expr(n_it->function_calls.begin() + ->function()).get_identifier(); + debug() << "Refining function " << it->first << ": inlining call to " + << fname << " at " << (*f_it)->location_number<< eom; + } + } + #if 0 // inline functions "selectively" (those that seem to be the "reason") for(reasont::const_iterator it = reason.begin(); it != reason.end(); ++it) diff --git a/src/summarizer/summarizer_bw_cex_concrete.cpp b/src/summarizer/summarizer_bw_cex_concrete.cpp index 84f025115..1c55814de 100644 --- a/src/summarizer/summarizer_bw_cex_concrete.cpp +++ b/src/summarizer/summarizer_bw_cex_concrete.cpp @@ -146,6 +146,12 @@ void summarizer_bw_cex_concretet::compute_summary_rec( bool context_sensitive) { local_SSAt &SSA = ssa_db.get(function_name); + + //TODO: let's just put all loops into the reason + for(local_SSAt::nodest::iterator n_it = SSA.nodes.begin(); + n_it != SSA.nodes.end(); ++n_it) + if (n_it->loophead != SSA.nodes.end()) + reason[function_name].loops.insert(n_it->loophead->location); summaryt summary; if(summary_db.exists(function_name)) @@ -482,7 +488,10 @@ void summarizer_bw_cex_concretet::inline_summaries( exprt postcondition_call = true_exprt(); postcondition_call = compute_calling_context2( - function_name,SSA,old_summary,n_it,f_it,postcondition,sufficient); + function_name,SSA,old_summary,n_it,f_it,postcondition,sufficient); + + //TODO: just put all function calls into reason + reason[function_name].functions.insert(n_it->location); irep_idt fname = to_symbol_expr(f_it->function()).get_identifier(); status() << "Recursively summarizing function " << fname << eom; From dca2ef77ee151ae429251cca78cc8b02e91e9dce Mon Sep 17 00:00:00 2001 From: Peter Schrammel Date: Sun, 29 May 2016 18:52:04 +0100 Subject: [PATCH 47/82] recursive gathering of summaries and inlined functions --- src/ssa/ssa_inliner.cpp | 570 +++++++++++++++----------- src/ssa/ssa_inliner.h | 1 + src/ssa/ssa_refiner_selective.cpp | 156 ------- src/summarizer/summary_checker_base.h | 2 +- 4 files changed, 330 insertions(+), 399 deletions(-) diff --git a/src/ssa/ssa_inliner.cpp b/src/ssa/ssa_inliner.cpp index b2c2da908..72abe4101 100644 --- a/src/ssa/ssa_inliner.cpp +++ b/src/ssa/ssa_inliner.cpp @@ -24,11 +24,11 @@ Function: ssa_inlinert::get_guard_binding \*******************************************************************/ void ssa_inlinert::get_guard_binding( - const local_SSAt &SSA, - const local_SSAt &fSSA, - local_SSAt::nodest::const_iterator n_it, - exprt &guard_binding, - int counter) + const local_SSAt &SSA, + const local_SSAt &fSSA, + local_SSAt::nodest::const_iterator n_it, + exprt &guard_binding, + int counter) { exprt callee_guard, caller_guard; callee_guard=fSSA.guard_symbol(fSSA.goto_function.body.instructions.begin()); @@ -51,13 +51,13 @@ Function: ssa_inlinert::get_bindings \*******************************************************************/ void ssa_inlinert::get_bindings( - const local_SSAt &SSA, - const local_SSAt &fSSA, - local_SSAt::nodest::const_iterator n_it, - local_SSAt::nodet::function_callst::const_iterator f_it, - exprt::operandst &bindings_in, - exprt::operandst &bindings_out, - int counter) + const local_SSAt &SSA, + const local_SSAt &fSSA, + local_SSAt::nodest::const_iterator n_it, + local_SSAt::nodet::function_callst::const_iterator f_it, + exprt::operandst &bindings_in, + exprt::operandst &bindings_out, + int counter) { //getting globals at call site local_SSAt::var_sett cs_globals_in, cs_globals_out; @@ -91,6 +91,87 @@ void ssa_inlinert::get_bindings( } +/*******************************************************************\ + +Function: ssa_inlinert::get_inlined + + Inputs: + + Outputs: + + Purpose: get inlined function call + + +\*******************************************************************/ + +bool ssa_inlinert::get_inlined( + const local_SSAt &SSA, + local_SSAt::nodest::const_iterator n_it, + local_SSAt::nodet::function_callst::const_iterator f_it, + bool forward, + exprt::operandst &assert_summaries, + exprt::operandst &noassert_summaries, + exprt::operandst &bindings, + int counter, + bool error_summ) +{ + irep_idt fname = to_symbol_expr(f_it->function()).get_identifier(); + const local_SSAt &fSSA = ssa_db.get(fname); + + bool assertion_flag = get_summaries(fSSA, + summaryt::call_sitet(fSSA.goto_function.body.instructions.end()), + forward,assert_summaries,noassert_summaries,bindings,error_summ); + + //bindings + exprt guard_binding; + get_guard_binding(SSA,fSSA,n_it,guard_binding,counter); + bindings.push_back(guard_binding); + get_bindings(SSA,fSSA,n_it,f_it,bindings,bindings,counter); + + bool first_equality = true; + for(local_SSAt::nodest::const_iterator n_it = fSSA.nodes.begin(); + n_it != fSSA.nodes.end(); n_it++) + { + const local_SSAt::nodet &fnode=*n_it; + + for(local_SSAt::nodet::equalitiest::const_iterator e_it = + fnode.equalities.begin(); e_it!=fnode.equalities.end(); e_it++) + { + // unless lhs starts with "ssa::guard" and rhs is true + // because that one is replaced by the guard binding + const equal_exprt &e = to_equal_expr(*e_it); + const exprt &lhs = e.lhs(); const exprt &rhs = e.rhs(); + std::string var_string = id2string(to_symbol_expr(lhs).get_identifier()); + if((var_string.substr(0,11) == "ssa::$guard") && + rhs.is_true() && first_equality) + { + first_equality = false; + } + else + { + noassert_summaries.push_back(*e_it); + rename(noassert_summaries.back(), counter); + } + } + for(local_SSAt::nodet::constraintst::const_iterator c_it = + fnode.constraints.begin(); c_it!=fnode.constraints.end(); c_it++) + { + noassert_summaries.push_back(*c_it); + rename(noassert_summaries.back(), counter); + } + for(local_SSAt::nodet::assertionst::const_iterator a_it = + fnode.assertions.begin(); a_it!=fnode.assertions.end(); a_it++) + { + assert_summaries.push_back(*a_it); + rename(assert_summaries.back(), counter); + assertion_flag = true; + } + } + + return assertion_flag; +} + + /*******************************************************************\ Function: ssa_inlinert::get_summary @@ -99,25 +180,29 @@ Function: ssa_inlinert::get_summary Outputs: - Purpose: get summary for function call + Purpose: get summary for non-inlined function calls \*******************************************************************/ -void ssa_inlinert::get_summary( +bool ssa_inlinert::get_summary( const local_SSAt &SSA, local_SSAt::nodest::const_iterator n_it, local_SSAt::nodet::function_callst::const_iterator f_it, const summaryt &summary, bool forward, - exprt::operandst &summaries, + exprt::operandst &assert_summaries, + exprt::operandst &noassert_summaries, exprt::operandst &bindings, int counter, bool error_summ) { + irep_idt fname = to_symbol_expr(f_it->function()).get_identifier(); + const summaryt &summary = summary_db.get(fname); + //getting globals at call site local_SSAt::var_sett cs_globals_in, cs_globals_out; goto_programt::const_targett loc = n_it->location; - SSA.get_globals(loc,cs_globals_in); + SSA.get_globals(loc,cs_globals_in); SSA.get_globals(loc,cs_globals_out,false); #if 0 @@ -157,21 +242,31 @@ void ssa_inlinert::get_summary( transformer=true_exprt(); } else - { - if(forward) - transformer = summary.fw_transformer.is_nil() ? true_exprt() : - summary.fw_transformer; - else - transformer = summary.bw_transformer.is_nil() ? true_exprt() : - summary.bw_transformer; - } + { + if(forward) + transformer = summary.fw_transformer.is_nil() ? true_exprt() : + summary.fw_transformer; + else + transformer = summary.bw_transformer.is_nil() ? true_exprt() : + summary.bw_transformer; + } rename(transformer,counter); - summaries.push_back(implies_exprt(SSA.guard_symbol(n_it->location), - transformer)); + if(summary.has_assertion) + { + assert_summaries.push_back(implies_exprt(SSA.guard_symbol(n_it->location), + transformer)); + } + else + { + noassert_summaries.push_back(implies_exprt(SSA.guard_symbol(n_it->location), + transformer)); + } //equalities for globals out (including unmodified globals) - get_replace_globals_out(summary.globals_out,*f_it,cs_globals_in,cs_globals_out,bindings,counter); + get_replace_globals_out(summary.globals_out,*f_it,cs_globals_in,cs_globals_out,bindings,counter); + + return summary.has_assertion; } /*******************************************************************\ @@ -199,24 +294,9 @@ void ssa_inlinert::get_summaries( exprt::operandst &summaries, exprt::operandst &bindings) { - for(local_SSAt::nodest::const_iterator n_it=SSA.nodes.begin(); - n_it!=SSA.nodes.end(); n_it++) - { - for(local_SSAt::nodet::function_callst::const_iterator f_it= - n_it->function_calls.begin(); - f_it!=n_it->function_calls.end(); f_it++) - { - assert(f_it->function().id()==ID_symbol); // no function pointers - irep_idt fname=to_symbol_expr(f_it->function()).get_identifier(); - - if(summary_db.exists(fname)) - { - counter++; - get_summary(SSA, n_it, f_it,summary_db.get(fname), - forward, summaries, bindings, counter); - } - } - } + get_summaries(SSA, + summaryt::call_sitet(SSA.goto_function.body.instructions.end()), + forward,summaries,summaries,bindings); } /*******************************************************************\ @@ -244,32 +324,37 @@ bool ssa_inlinert::get_summaries( n_it!=SSA.nodes.end(); n_it++) { for(local_SSAt::nodet::function_callst::const_iterator f_it = - n_it->function_calls.begin(); + n_it->function_calls.begin(); f_it!=n_it->function_calls.end(); f_it++) + { + //do not use summary for current call site + summaryt::call_sitet this_call_site(n_it->location); + if(current_call_site == this_call_site) + continue; + + irep_idt fname = to_symbol_expr(f_it->function()).get_identifier(); + + //get inlined function + if(n_it->function_calls_inlined) { - //do not use summary for current call site - summaryt::call_sitet this_call_site(n_it->location); - if(current_call_site==this_call_site) - continue; - - assert(f_it->function().id()==ID_symbol); //no function pointers - irep_idt fname=to_symbol_expr(f_it->function()).get_identifier(); - - //TODO: we need a get_summary variant that retrieves the summary according the call_site from summary.error_summaries - if(summary_db.exists(fname)) - { - summaryt summary=summary_db.get(fname); - if(summary.has_assertion==true){ - counter++; - get_summary(SSA, n_it, f_it, summary_db.get(fname),forward,assert_summaries,bindings,counter,true); - assertion_flag=true; - } - else{ - counter++; - get_summary(SSA, n_it, f_it, summary_db.get(fname),forward,noassert_summaries,bindings,counter,true); - } - } + counter++; + bool new_assertion_flag = + get_inlined(SSA,n_it,f_it, + forward,assert_summaries,noassert_summaries, + bindings,counter,error_summ); + assertion_flag = assertion_flag || new_assertion_flag; + } + //get summary + else if(summary_db.exists(fname)) + { + counter++; + bool new_assertion_flag = + get_summary(SSA,n_it,f_it, + forward,assert_summaries,noassert_summaries, + bindings,counter,error_summ); + assertion_flag = assertion_flag || new_assertion_flag; } + } } return assertion_flag; } @@ -355,52 +440,52 @@ void ssa_inlinert::replace( { for(local_SSAt::nodest::iterator n_it = SSA.nodes.begin(); n_it != SSA.nodes.end(); n_it++) + { + for(local_SSAt::nodet::function_callst::iterator + f_it = n_it->function_calls.begin(); + f_it != n_it->function_calls.end(); f_it++) { - for(local_SSAt::nodet::function_callst::iterator - f_it = n_it->function_calls.begin(); - f_it != n_it->function_calls.end(); f_it++) - { - assert(f_it->function().id()==ID_symbol); //no function pointers - irep_idt fname = to_symbol_expr(f_it->function()).get_identifier(); + assert(f_it->function().id()==ID_symbol); //no function pointers + irep_idt fname = to_symbol_expr(f_it->function()).get_identifier(); - if(ssa_db.exists(fname)) + if(ssa_db.exists(fname)) { status() << "Inlining function " << fname << eom; local_SSAt fSSA = ssa_db.get(fname); //copy if(rename) - { - //getting globals at call site - local_SSAt::var_sett cs_globals_in, cs_globals_out; - goto_programt::const_targett loc = n_it->location; - SSA.get_globals(loc,cs_globals_in); - SSA.get_globals(loc,cs_globals_out,false); + { + //getting globals at call site + local_SSAt::var_sett cs_globals_in, cs_globals_out; + goto_programt::const_targett loc = n_it->location; + SSA.get_globals(loc,cs_globals_in); + SSA.get_globals(loc,cs_globals_out,false); - if(recursive) - { - replace(fSSA,ssa_db,true,counter); - } - - //replace - replace(SSA.nodes,n_it,f_it,cs_globals_in,cs_globals_out,fSSA,counter); - } + if(recursive) + { + replace(fSSA,ssa_db,true,counter); + } + + //replace + replace(SSA.nodes,n_it,f_it,cs_globals_in,cs_globals_out,fSSA,counter); + } else // just add to nodes - { - for(local_SSAt::nodest::const_iterator fn_it = fSSA.nodes.begin(); - fn_it != fSSA.nodes.end(); fn_it++) - { - debug() << "new node: "; fn_it->output(debug(),fSSA.ns); - debug() << eom; + { + for(local_SSAt::nodest::const_iterator fn_it = fSSA.nodes.begin(); + fn_it != fSSA.nodes.end(); fn_it++) + { + debug() << "new node: "; fn_it->output(debug(),fSSA.ns); + debug() << eom; - new_nodes.push_back(*fn_it); - } - } + new_nodes.push_back(*fn_it); + } + } } - else debug() << "No body available for function " << fname << eom; - commit_node(n_it); - } - commit_nodes(SSA.nodes,n_it); + else debug() << "No body available for function " << fname << eom; + commit_node(n_it); } + commit_nodes(SSA.nodes,n_it); + } } /*******************************************************************\ @@ -503,7 +588,7 @@ void ssa_inlinert::replace( // add function body for(local_SSAt::nodest::const_iterator n_it=function.nodes.begin(); n_it!=function.nodes.end(); n_it++) - { + { local_SSAt::nodet n=*n_it; // copy rename(n,counter); new_nodes.push_back(n); @@ -540,30 +625,30 @@ void ssa_inlinert::get_replace_globals_in( //equalities for globals_in for(summaryt::var_sett::const_iterator it = globals_in.begin(); it != globals_in.end(); it++) + { + symbol_exprt lhs = *it; //copy + rename(lhs,counter); + symbol_exprt rhs; + if(find_corresponding_symbol(*it,globals,rhs)) { - symbol_exprt lhs = *it; //copy - rename(lhs,counter); - symbol_exprt rhs; - if(find_corresponding_symbol(*it,globals,rhs)) - { - rhs.set_identifier(id2string(rhs.get_identifier())+suffix); + rhs.set_identifier(id2string(rhs.get_identifier())+suffix); - debug() << "binding: " << lhs.get_identifier() << " == " - << rhs.get_identifier() << eom; - c.push_back(equal_exprt(lhs,rhs)); - } + debug() << "binding: " << lhs.get_identifier() << " == " + << rhs.get_identifier() << eom; + c.push_back(equal_exprt(lhs,rhs)); + } #if 0 - else - warning() << "'" << it->get_identifier() - << "' not bound in caller" << eom; + else + warning() << "'" << it->get_identifier() + << "' not bound in caller" << eom; #endif - } + } //return conjunction(c); } void ssa_inlinert::replace_globals_in(const local_SSAt::var_sett &globals_in, - const local_SSAt::var_sett &globals, - int counter) + const local_SSAt::var_sett &globals, + int counter) { //equalities for globals_in for(summaryt::var_sett::const_iterator it = globals_in.begin(); @@ -573,11 +658,11 @@ void ssa_inlinert::replace_globals_in(const local_SSAt::var_sett &globals_in, rename(lhs,counter); symbol_exprt rhs; if(find_corresponding_symbol(*it,globals,rhs)) - { - debug() << "binding: " << lhs.get_identifier() << " == " - << rhs.get_identifier() << eom; - new_equs.push_back(equal_exprt(lhs,rhs)); - } + { + debug() << "binding: " << lhs.get_identifier() << " == " + << rhs.get_identifier() << eom; + new_equs.push_back(equal_exprt(lhs,rhs)); + } #if 0 else warning() << "'" << it->get_identifier() @@ -610,72 +695,72 @@ void ssa_inlinert::get_replace_params( local_SSAt::var_listt::const_iterator p_it = params.begin(); for(exprt::operandst::const_iterator it = funapp_expr.arguments().begin(); it != funapp_expr.arguments().end(); it++, p_it++) - { + { #if 0 - std::cout << "replace param " << from_expr(SSA.ns,"",*p_it) - << " == " << from_expr(SSA.ns,"",*it) << std::endl; + std::cout << "replace param " << from_expr(SSA.ns,"",*p_it) + << " == " << from_expr(SSA.ns,"",*it) << std::endl; #endif #if 0 - local_SSAt::var_listt::const_iterator next_p_it = p_it; - if(funapp_expr.arguments().size() != params.size() && - ++next_p_it==params.end()) //TODO: handle ellipsis - { - warning() << "ignoring excess function arguments" << eom; - break; - } + local_SSAt::var_listt::const_iterator next_p_it = p_it; + if(funapp_expr.arguments().size() != params.size() && + ++next_p_it==params.end()) //TODO: handle ellipsis + { + warning() << "ignoring excess function arguments" << eom; + break; + } #endif - if(SSA.ns.follow(it->type()).id()==ID_struct) - { - exprt rhs = SSA.read_rhs(*it, n_it->location); //copy + if(SSA.ns.follow(it->type()).id()==ID_struct) + { + exprt rhs = SSA.read_rhs(*it, n_it->location); //copy #if 0 - std::cout << "split param " << from_expr(SSA.ns,"",*it) - << " into " << from_expr(SSA.ns,"",rhs) << std::endl; + std::cout << "split param " << from_expr(SSA.ns,"",*it) + << " into " << from_expr(SSA.ns,"",rhs) << std::endl; #endif - forall_operands(o_it, rhs) - { - assert(p_it!=params.end()); - exprt lhs = *p_it; //copy - rename(lhs,counter); + forall_operands(o_it, rhs) + { + assert(p_it!=params.end()); + exprt lhs = *p_it; //copy + rename(lhs,counter); #if 0 - std::cout << "split replace param " << from_expr(SSA.ns,"",*p_it) - << " == " << from_expr(SSA.ns,"",*o_it) << std::endl; + std::cout << "split replace param " << from_expr(SSA.ns,"",*p_it) + << " == " << from_expr(SSA.ns,"",*o_it) << std::endl; #endif - c.push_back(equal_exprt(lhs,*o_it)); - ++p_it; - } - } - else - { - exprt lhs = *p_it; //copy - rename(lhs,counter); - c.push_back(equal_exprt(lhs,*it)); + c.push_back(equal_exprt(lhs,*o_it)); + ++p_it; } } + else + { + exprt lhs = *p_it; //copy + rename(lhs,counter); + c.push_back(equal_exprt(lhs,*it)); + } + } } void ssa_inlinert::replace_params(const local_SSAt::var_listt ¶ms, - const function_application_exprt &funapp_expr, - int counter) + const function_application_exprt &funapp_expr, + int counter) { //equalities for arguments local_SSAt::var_listt::const_iterator p_it = params.begin(); for(exprt::operandst::const_iterator it = funapp_expr.arguments().begin(); it != funapp_expr.arguments().end(); it++, p_it++) + { + local_SSAt::var_listt::const_iterator next_p_it = p_it; + if(funapp_expr.arguments().size() != params.size() && + ++next_p_it==params.end()) //TODO: handle ellipsis { - local_SSAt::var_listt::const_iterator next_p_it = p_it; - if(funapp_expr.arguments().size() != params.size() && - ++next_p_it==params.end()) //TODO: handle ellipsis - { - warning() << "ignoring excess function arguments" << eom; - break; - } - - exprt lhs = *p_it; //copy - rename(lhs,counter); - new_equs.push_back(equal_exprt(lhs,*it)); + warning() << "ignoring excess function arguments" << eom; + break; } + + exprt lhs = *p_it; //copy + rename(lhs,counter); + new_equs.push_back(equal_exprt(lhs,*it)); + } } /*******************************************************************\ @@ -703,41 +788,41 @@ void ssa_inlinert::get_replace_globals_out( //equalities for globals_out for(summaryt::var_sett::const_iterator it = cs_globals_out.begin(); it != cs_globals_out.end(); it++) - { - symbol_exprt lhs = *it; //copy + { + symbol_exprt lhs = *it; //copy - lhs.set_identifier(id2string(lhs.get_identifier())+suffix); + lhs.set_identifier(id2string(lhs.get_identifier())+suffix); - symbol_exprt rhs; - if(find_corresponding_symbol(*it,globals_out,rhs)) - rename(rhs,counter); - else - { - bool found = find_corresponding_symbol(*it,cs_globals_in,rhs); - assert(found); - rhs.set_identifier(id2string(rhs.get_identifier())+suffix); - } - c.push_back(equal_exprt(lhs,rhs)); + symbol_exprt rhs; + if(find_corresponding_symbol(*it,globals_out,rhs)) + rename(rhs,counter); + else + { + bool found = find_corresponding_symbol(*it,cs_globals_in,rhs); + assert(found); + rhs.set_identifier(id2string(rhs.get_identifier())+suffix); } + c.push_back(equal_exprt(lhs,rhs)); + } } void ssa_inlinert::replace_globals_out(const local_SSAt::var_sett &globals_out, - const local_SSAt::var_sett &cs_globals_in, - const local_SSAt::var_sett &cs_globals_out, - int counter) + const local_SSAt::var_sett &cs_globals_in, + const local_SSAt::var_sett &cs_globals_out, + int counter) { //equalities for globals_out for(summaryt::var_sett::const_iterator it = cs_globals_out.begin(); it != cs_globals_out.end(); it++) - { - symbol_exprt rhs = *it; //copy - symbol_exprt lhs; - if(find_corresponding_symbol(*it,globals_out,lhs)) - rename(lhs,counter); - else - assert(find_corresponding_symbol(*it,cs_globals_in,lhs)); - new_equs.push_back(equal_exprt(lhs,rhs)); - } + { + symbol_exprt rhs = *it; //copy + symbol_exprt lhs; + if(find_corresponding_symbol(*it,globals_out,lhs)) + rename(lhs,counter); + else + assert(find_corresponding_symbol(*it,cs_globals_in,lhs)); + new_equs.push_back(equal_exprt(lhs,rhs)); + } } /*******************************************************************\ @@ -797,19 +882,19 @@ irep_idt ssa_inlinert::rename(irep_idt &id, int counter, bool attach){ //find first @ where afterwards there are no letters size_t pos = std::string::npos; for(size_t i=0;iarguments().size()); @@ -988,17 +1073,17 @@ void ssa_inlinert::rename_to_callee( /* replace_expr(replace_map,expr); - replace_map.clear(); //arguments might contain globals, - // thus, we have to replace them separately - */ + replace_map.clear(); //arguments might contain globals, + // thus, we have to replace them separately + */ for(summaryt::var_sett::const_iterator it = cs_globals_in.begin(); it != cs_globals_in.end(); it++) + { + symbol_exprt cg; + if(find_corresponding_symbol(*it,globals_in,cg)) + replace_map[*it] = cg; + else { - symbol_exprt cg; - if(find_corresponding_symbol(*it,globals_in,cg)) - replace_map[*it] = cg; - else - { #if 0 warning() << "'" << it->get_identifier() << "' not bound in caller" << eom; @@ -1008,6 +1093,7 @@ void ssa_inlinert::rename_to_callee( id2string(it->get_identifier())+"@"+i2string(++counter), it->type()); } } + } replace_expr(replace_map, expr); } diff --git a/src/ssa/ssa_inliner.h b/src/ssa/ssa_inliner.h index beefe4e35..b7ddfcce6 100644 --- a/src/ssa/ssa_inliner.h +++ b/src/ssa/ssa_inliner.h @@ -152,6 +152,7 @@ class ssa_inlinert:public messaget protected: unsigned counter; summary_dbt &summary_db; + ssa_dbt &ssa_db; local_SSAt::nodest new_nodes; local_SSAt::nodet::equalitiest new_equs; diff --git a/src/ssa/ssa_refiner_selective.cpp b/src/ssa/ssa_refiner_selective.cpp index 1d77dc29f..2b09a3f68 100644 --- a/src/ssa/ssa_refiner_selective.cpp +++ b/src/ssa/ssa_refiner_selective.cpp @@ -56,161 +56,5 @@ bool ssa_refiner_selectivet::operator()() } } -#if 0 - // inline functions "selectively" (those that seem to be the "reason") - for(reasont::const_iterator it = reason.begin(); it != reason.end(); ++it) - { - for(std::set::const_iterator f_it = - it->second.functions.begin(); - f_it != it->second.functions.end(); f_it++) - { - local_SSAt &SSA = ssa_db.get(it->first); - - std::list inline_nodes; - std::vector first_node_equalities; - int counter = ssa_inliner.get_rename_counter(); - - for(local_SSAt::nodest::iterator n_it = SSA.nodes.begin(); - n_it != SSA.nodes.end(); n_it++) - { - - local_SSAt::nodet &node=*n_it; - - if(node.location == *(f_it)) - { - - bool clear_function_call = false; - - for(local_SSAt::nodet::function_callst::const_iterator fc_it = - node.function_calls.begin(); - fc_it!=node.function_calls.end(); fc_it++) - { - - irep_idt fname = to_symbol_expr(fc_it->function()).get_identifier(); - if(ssa_db.exists(fname)) - { - clear_function_call = true; - - local_SSAt &fSSA = ssa_db.get(fname); - - exprt guard_binding; - exprt::operandst bindings_in, bindings_out; - - // put guard_binding, bindings_in, bindings_out in the caller's SSA (equalities) - ssa_inliner.get_guard_binding(SSA,fSSA,n_it,guard_binding,counter); - equal_exprt e = to_equal_expr(guard_binding); - node.equalities.push_back(e); - - ssa_inliner.get_bindings(SSA,fSSA,n_it,fc_it,bindings_in,bindings_out,counter); - - for(exprt::operandst::const_iterator b_it=bindings_in.begin(); - b_it!=bindings_in.end(); b_it++){ - equal_exprt e = to_equal_expr(*b_it); - node.equalities.push_back(e); - } - for(exprt::operandst::const_iterator b_it=bindings_out.begin(); - b_it!=bindings_out.end(); b_it++){ - equal_exprt e = to_equal_expr(*b_it); - node.equalities.push_back(e); - } - - for(local_SSAt::nodest::const_iterator fn_it = fSSA.nodes.begin(); - fn_it != fSSA.nodes.end(); fn_it++){ - local_SSAt::nodet fnode=*fn_it; - inline_nodes.push_back(fnode); - } - - if(fname == entry_function){ - // first_node_equalities should contain all the equalities from the first node of fSSA - for(local_SSAt::nodest::iterator fn_it = fSSA.nodes.begin(); - fn_it != fSSA.nodes.end(); fn_it++){ - local_SSAt::nodet &fnode=*fn_it; - for(local_SSAt::nodet::equalitiest::iterator e_it=fnode.equalities.begin(); - e_it!=fnode.equalities.end(); e_it++){ - first_node_equalities.push_back(*e_it); - } - break; - } - } - else{ - // except those (the one) that start with "ssa::guard" and have true in the rhs - for(local_SSAt::nodest::iterator fn_it = fSSA.nodes.begin(); - fn_it != fSSA.nodes.end(); fn_it++){ - local_SSAt::nodet &fnode=*fn_it; - - bool ignore_equality = true; - - for(local_SSAt::nodet::equalitiest::iterator e_it=fnode.equalities.begin(); - e_it!=fnode.equalities.end(); e_it++){ - // unless lhs starts with "ssa::guard" and rhs is true - - equal_exprt e = to_equal_expr(*e_it); - exprt &lhs = e.lhs(); exprt &rhs = e.rhs(); - std::string var_string = id2string(to_symbol_expr(lhs).get_identifier()); - if(((var_string.substr(0,11)) == "ssa::$guard") && (rhs.is_true()) && (ignore_equality == true)){ - ignore_equality = false; - } - else{ - first_node_equalities.push_back(*e_it); - } - - } - break; - } - } - - } - } - - if(clear_function_call == true) - node.function_calls.clear(); - - } - } - - bool replace_first_node_equalities = true; - - if(inline_nodes.size() > 0) - { - for(std::list::iterator in_it = inline_nodes.begin(); - in_it != inline_nodes.end(); in_it++) - { - local_SSAt::nodet &inline_node = *in_it; - - if(replace_first_node_equalities == true) - { - inline_node.equalities.clear(); - for(std::vector::iterator e_it=first_node_equalities.begin(); - e_it!=first_node_equalities.end(); e_it++){ - inline_node.equalities.push_back(*e_it); - } - replace_first_node_equalities = false; - } - - for(local_SSAt::nodet::equalitiest::iterator e_it=inline_node.equalities.begin(); - e_it!=inline_node.equalities.end(); e_it++){ - ssa_inliner.rename(*e_it, counter); - } - - for(local_SSAt::nodet::constraintst::iterator c_it=inline_node.constraints.begin(); - c_it!=inline_node.constraints.end(); c_it++){ - ssa_inliner.rename(*c_it, counter); - } - - for(local_SSAt::nodet::assertionst::iterator a_it=inline_node.assertions.begin(); - a_it!=inline_node.assertions.end(); a_it++){ - ssa_inliner.rename(*a_it, counter); - } - - // push inline_node into SSA - SSA.nodes.push_back(inline_node); - - } - } - - } - } -#endif - return unwind Date: Sun, 29 May 2016 22:14:18 +0100 Subject: [PATCH 48/82] basic unsat-core based refinement selection --- src/ssa/ssa_refiner_selective.h | 3 +- src/summarizer/summarizer_bw_cex_complete.cpp | 109 ++++++++++++++---- src/summarizer/summarizer_bw_cex_complete.h | 12 ++ 3 files changed, 102 insertions(+), 22 deletions(-) diff --git a/src/ssa/ssa_refiner_selective.h b/src/ssa/ssa_refiner_selective.h index f97329f01..9d2d8f352 100644 --- a/src/ssa/ssa_refiner_selective.h +++ b/src/ssa/ssa_refiner_selective.h @@ -56,11 +56,12 @@ class ssa_refiner_selectivet : public ssa_refinert ssa_unwinder(_ssa_unwinder), max_unwind(_max_unwind), ssa_inliner(_ssa_inliner), + unwind(0), reason(_reason) {} virtual bool operator()(); - virtual unsigned get_unwind() { return unwind>0 ? unwind-1 : 0; } + virtual unsigned get_unwind() { return unwind; } protected: ssa_dbt &ssa_db; diff --git a/src/summarizer/summarizer_bw_cex_complete.cpp b/src/summarizer/summarizer_bw_cex_complete.cpp index 6a6ca30b6..b8d5cecad 100644 --- a/src/summarizer/summarizer_bw_cex_complete.cpp +++ b/src/summarizer/summarizer_bw_cex_complete.cpp @@ -26,7 +26,7 @@ Author: Madhukar Kumar, Peter Schrammel #include "summarizer_bw_cex_complete.h" -#define SHOW_UNSAT_CORE +//#define SHOW_UNSAT_CORE /*******************************************************************\ @@ -107,12 +107,13 @@ find_symbols_sett summarizer_bw_cex_completet::inline_summaries solver << enable_exprs; #endif +#if 0 //TODO: let's just put all loops into the reason for(local_SSAt::nodest::iterator n_it = SSA.nodes.begin(); n_it != SSA.nodes.end(); ++n_it) if (n_it->loophead != SSA.nodes.end()) reason[function_name].loops.insert(n_it->loophead->location); - +#endif ssa_dependency_grapht &ssa_depgraph = ssa_db.get_depgraph(function_name); @@ -253,8 +254,10 @@ find_symbols_sett summarizer_bw_cex_completet::inline_summaries */ ///////////////////////////////////////////////////////////////////////////////////// +#if 0 //TODO: just put all function calls into reason reason[function_name].functions.insert(depnode.location); +#endif //recurse worknode.dependency_set = @@ -321,12 +324,13 @@ find_symbols_sett summarizer_bw_cex_completet::inline_summaries exprt lsguard = depnode.guard; ssa_inliner.rename(lsguard, counter); loophead_selects.push_back(lsguard); - solver.solver->set_frozen(solver.convert(lsguard)); + //solver.solver->set_frozen(solver.convert(lsguard)); + add_reason_to_check(lsguard,function_name,false,depnode.location); //loop continuations exprt::operandst local_loop_continues; get_loop_continues(SSA, ssa_local_unwinder, depnode.location, - local_loop_continues); + local_loop_continues); for(size_t i=0; iset_assumptions(formula); -#endif solver_calls++; // for statistics if(solver() == decision_proceduret::D_SATISFIABLE) @@ -545,11 +549,36 @@ property_checkert::resultt summarizer_bw_cex_completet::check() #ifdef SHOW_UNSAT_CORE else { + const namespacet &ns = ssa_db.get(entry_function).ns; + for(unsigned i=0; iis_in_conflict(formula[i])) + debug() << "is_in_conflict: " << from_expr(ns, "", formula_expr[i]) << eom; + } + } +#else + else + { + const namespacet &ns = ssa_db.get(entry_function).ns; + //get reasons for spuriousness for(unsigned i=0; iis_in_conflict(formula[i])) + { debug() << "is_in_conflict: " << from_expr(ns, "", formula_expr[i]) << eom; + const reason_to_checkt &r = reasons_to_check[i]; + if(r.is_function) + reason[r.function_name].functions.insert(r.info); + else + reason[r.function_name].loops.insert(r.info); + } + } + bvt assumptions; + solver.solver->set_assumptions(assumptions); + for(unsigned i=0; i " << function_name << " ; dependency_set -> "; for(find_symbols_sett::iterator d_it = dependency_set.begin(); - d_it != dependency_set.end(); d_it++){ - std::cout << *d_it << ", "; -} + d_it != dependency_set.end(); d_it++){ + std::cout << *d_it << ", "; + } std::cout << "\n"; } @@ -597,14 +626,52 @@ void summarizer_bw_cex_completet::add_to_formula(const exprt &expr) literalt l = solver.solver->convert(expr); if(l.is_false()) { - literalt dummy = solver.solver->convert(symbol_exprt("goto_symex::\\dummy", - bool_typet())); - formula.push_back(dummy); - formula.push_back(!dummy); -} + literalt dummy = solver.solver->convert(symbol_exprt("goto_symex::\\dummy", + bool_typet())); + formula.push_back(dummy); + formula.push_back(!dummy); + } else if(!l.is_true()) { - formula.push_back(l); - formula_expr.push_back(expr); + formula.push_back(l); + formula_expr.push_back(expr); + } } + +/*******************************************************************\ + +Function: summarizer_bw_cex_completet::add_reason_to_check + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +void summarizer_bw_cex_completet::add_reason_to_check( + const exprt &expr, + const function_namet &function_name, + bool is_function, + const local_SSAt::locationt & info) +{ + literalt l = solver.solver->convert(expr); + if(l.is_false()) + { + literalt dummy = solver.solver->convert(symbol_exprt("goto_symex::\\dummy", + bool_typet())); + formula.push_back(dummy); + formula.push_back(!dummy); + } + else if(!l.is_true()) + { + formula.push_back(l); + formula_expr.push_back(expr); + reasons_to_check.push_back(reason_to_checkt()); + reason_to_checkt &r = reasons_to_check.back(); + r.function_name = function_name; + r.info = info; + r.is_function = is_function; + } } diff --git a/src/summarizer/summarizer_bw_cex_complete.h b/src/summarizer/summarizer_bw_cex_complete.h index 37f80d672..51901fd5a 100644 --- a/src/summarizer/summarizer_bw_cex_complete.h +++ b/src/summarizer/summarizer_bw_cex_complete.h @@ -49,6 +49,18 @@ class summarizer_bw_cex_completet : public summarizer_bw_cex_baset exprt::operandst loophead_selects; exprt::operandst loop_continues; + struct reason_to_checkt { + function_namet function_name; + bool is_function; + local_SSAt::locationt info; + }; + std::vector reasons_to_check; + void add_reason_to_check( + const exprt &expr, + const function_namet &function_name, + bool is_function, + const local_SSAt::locationt & info); + virtual find_symbols_sett inline_summaries( const function_namet &function_name, find_symbols_sett &dependency_set, From 0d6fc1bf3ac7e2118c50b5189a60cb62a01f077b Mon Sep 17 00:00:00 2001 From: Peter Schrammel Date: Mon, 30 May 2016 12:08:21 +0100 Subject: [PATCH 49/82] fully-unwound check fixed as far as possible --- src/domains/incremental_solver.cpp | 1 + src/domains/incremental_solver.h | 16 ++++- src/ssa/ssa_unwinder.cpp | 4 +- src/summarizer/summarizer_bw_cex_complete.cpp | 70 ++++++------------- src/summarizer/summarizer_bw_cex_complete.h | 2 - 5 files changed, 39 insertions(+), 54 deletions(-) diff --git a/src/domains/incremental_solver.cpp b/src/domains/incremental_solver.cpp index f25f23cdf..c4ac59d7d 100644 --- a/src/domains/incremental_solver.cpp +++ b/src/domains/incremental_solver.cpp @@ -176,6 +176,7 @@ void incremental_solvert::debug_add_to_formula(const exprt &expr) debug() << "literal " << l << ": " << from_expr(ns, "", expr) << eom; #endif formula.push_back(l); + formula_expr.push_back(expr); } #endif } diff --git a/src/domains/incremental_solver.h b/src/domains/incremental_solver.h index 08f5b1ae2..51f2332ed 100644 --- a/src/domains/incremental_solver.h +++ b/src/domains/incremental_solver.h @@ -94,8 +94,21 @@ class incremental_solvert:public messaget solver->set_assumptions(whole_formula); #endif #endif - +#if defined(DEBUG_FORMULA) && defined(DEBUG_OUTPUT) + decision_proceduret::resultt result = (*solver)(); + if(result==decision_proceduret::D_UNSATISFIABLE) + { + for(unsigned i=0; iis_in_conflict(formula[i])) + std::cout << "is_in_conflict: " + << from_expr(ns, "", formula_expr[i]) << std::endl; + } + } + return result; +#else return (*solver)(); +#endif } exprt get(const exprt& expr) { return solver->get(expr); } @@ -125,6 +138,7 @@ class incremental_solvert:public messaget // for debugging bvt formula; + exprt::operandst formula_expr; void debug_add_to_formula(const exprt &expr); // context assumption literals diff --git a/src/ssa/ssa_unwinder.cpp b/src/ssa/ssa_unwinder.cpp index dbc5878c0..ab73e8a8c 100644 --- a/src/ssa/ssa_unwinder.cpp +++ b/src/ssa/ssa_unwinder.cpp @@ -291,7 +291,7 @@ void ssa_local_unwindert::unwind_loop_at_location(unsigned loc, unsigned k) loopt &loop = loops[loc]; loop.loop_enabling_expr_current = - symbol_exprt("unwind::"+id2string(fname)+"loc::"+i2string(loc)+"::enable"+i2string(k), + symbol_exprt("unwind$"+id2string(fname)+"$loc"+i2string(loc)+"$enable"+i2string(k), bool_typet()); loop.loop_enabling_exprs.push_back(loop.loop_enabling_expr_current); @@ -347,7 +347,7 @@ void ssa_local_unwindert::unwind(unsigned k) return; current_enabling_expr= - symbol_exprt("unwind::"+id2string(fname)+"::enable"+i2string(k), + symbol_exprt("unwind$"+id2string(fname)+"$enable"+i2string(k), bool_typet()); for(loop_mapt::iterator it = loops.begin(); it != loops.end(); ++it) { diff --git a/src/summarizer/summarizer_bw_cex_complete.cpp b/src/summarizer/summarizer_bw_cex_complete.cpp index b8d5cecad..c281779d3 100644 --- a/src/summarizer/summarizer_bw_cex_complete.cpp +++ b/src/summarizer/summarizer_bw_cex_complete.cpp @@ -26,7 +26,7 @@ Author: Madhukar Kumar, Peter Schrammel #include "summarizer_bw_cex_complete.h" -//#define SHOW_UNSAT_CORE +#define REFINE_ALL /*******************************************************************\ @@ -101,13 +101,9 @@ find_symbols_sett summarizer_bw_cex_completet::inline_summaries exprt enable_exprs = SSA.get_enabling_exprs(); ssa_inliner.rename(enable_exprs, counter); -#ifdef SHOW_UNSAT_CORE - add_to_formula(enable_exprs); -#else solver << enable_exprs; -#endif -#if 0 +#ifdef REFINE_ALL //TODO: let's just put all loops into the reason for(local_SSAt::nodest::iterator n_it = SSA.nodes.begin(); n_it != SSA.nodes.end(); ++n_it) @@ -312,11 +308,11 @@ find_symbols_sett summarizer_bw_cex_completet::inline_summaries << worknode.node_index << "\t renamed info ~ " << from_expr((ssa_db.get(function_name)).ns, "", worknode_info) << "\n"; #endif -#ifdef SHOW_UNSAT_CORE - add_to_formula(worknode_info); -#else - solver << worknode_info; -#endif + + if(depnode.is_assertion) //keep for later + error_assertion = worknode_info; + else + solver << worknode_info; if(depnode.is_loop) { @@ -354,11 +350,10 @@ find_symbols_sett summarizer_bw_cex_completet::inline_summaries << from_expr(ssa_db.get(function_name).ns, "", guard_binding) << "\n"; #endif -#ifdef SHOW_UNSAT_CORE - add_to_formula(guard_binding); +#ifdef REFINE_ALL + solver << guard_binding; #else add_reason_to_check(guard_binding,function_name,true,depnode.location); - //solver << guard_binding; #endif } } @@ -533,35 +528,27 @@ Function: summarizer_bw_cex_completet::check() property_checkert::resultt summarizer_bw_cex_completet::check() { //add loophead selects -#ifdef SHOW_UNSAT_CORE - add_to_formula(conjunction(loophead_selects)); +#ifdef REFINE_ALL + solver.new_context(); + solver << error_assertion; + solver << conjunction(loophead_selects); #else -// solver << conjunction(loophead_selects); -#endif - + formula.push_back(solver.solver->convert(error_assertion)); solver.solver->set_assumptions(formula); +#endif solver_calls++; // for statistics if(solver() == decision_proceduret::D_SATISFIABLE) { + //pop_context() not necessary return property_checkert::FAIL; } -#ifdef SHOW_UNSAT_CORE - else - { - const namespacet &ns = ssa_db.get(entry_function).ns; - for(unsigned i=0; iis_in_conflict(formula[i])) - debug() << "is_in_conflict: " << from_expr(ns, "", formula_expr[i]) << eom; - } - } -#else +#ifndef REFINE_ALL else { const namespacet &ns = ssa_db.get(entry_function).ns; //get reasons for spuriousness - for(unsigned i=0; iis_in_conflict(formula[i])) { @@ -575,12 +562,14 @@ property_checkert::resultt summarizer_bw_cex_completet::check() } bvt assumptions; solver.solver->set_assumptions(assumptions); - for(unsigned i=0; iconvert(expr); - if(l.is_false()) - { - literalt dummy = solver.solver->convert(symbol_exprt("goto_symex::\\dummy", - bool_typet())); - formula.push_back(dummy); - formula.push_back(!dummy); - } - else if(!l.is_true()) - { - formula.push_back(l); - formula_expr.push_back(expr); - } -} - /*******************************************************************\ Function: summarizer_bw_cex_completet::add_reason_to_check diff --git a/src/summarizer/summarizer_bw_cex_complete.h b/src/summarizer/summarizer_bw_cex_complete.h index 51901fd5a..ef1827457 100644 --- a/src/summarizer/summarizer_bw_cex_complete.h +++ b/src/summarizer/summarizer_bw_cex_complete.h @@ -74,8 +74,6 @@ class summarizer_bw_cex_completet : public summarizer_bw_cex_baset const function_namet &function_name, find_symbols_sett &dependency_set); - void add_to_formula(const exprt &expr); - }; From c328faa7a2e22c3c09d74660cbc930e5b56dd22d Mon Sep 17 00:00:00 2001 From: Kumar Madhukar Date: Mon, 30 May 2016 17:22:25 +0530 Subject: [PATCH 50/82] unwind value propagation bug fixed (#5) --- src/ssa/ssa_unwinder.cpp | 41 +++++++++++++++++++++++++--------------- src/ssa/ssa_unwinder.h | 6 ++++-- 2 files changed, 30 insertions(+), 17 deletions(-) diff --git a/src/ssa/ssa_unwinder.cpp b/src/ssa/ssa_unwinder.cpp index ab73e8a8c..aa9e3de0f 100644 --- a/src/ssa/ssa_unwinder.cpp +++ b/src/ssa/ssa_unwinder.cpp @@ -345,7 +345,7 @@ void ssa_local_unwindert::unwind(unsigned k) { if(SSA.current_unwinding>=(long)k) return; - + current_enabling_expr= symbol_exprt("unwind$"+id2string(fname)+"$enable"+i2string(k), bool_typet()); @@ -363,7 +363,8 @@ void ssa_local_unwindert::unwind(unsigned k) { if(!it->second.is_root) continue; -(??) unwind(it->second,k,false); //recursive + //unwind(it->second,k,false,false); //recursive + unwind(it->second, k, false, true, k, 0, true); //recursive assert(SSA.current_unwindings.empty()); } // update current unwinding @@ -389,7 +390,8 @@ Function: ssa_local_unwindert::unwind \*******************************************************************/ void ssa_local_unwindert::unwind(loopt &loop, unsigned k, bool is_new_parent, - bool propagate, unsigned prop_unwind, unsigned prop_loc) + bool propagate, unsigned prop_unwind, + unsigned prop_loc, bool propagate_all) { odometert context=SSA.current_unwindings; #ifdef DEBUG @@ -452,26 +454,35 @@ void ssa_local_unwindert::unwind(loopt &loop, unsigned k, bool is_new_parent, #ifdef DEBUG std::cout << i << ">" << loop.current_unwinding << std::endl; #endif - if(propagate == true){ - // if this child loop is the desired loop then unwind k and do not propagate - // else unwind loop.current_unwinding and propagate - if(*l_it == prop_loc){ - unwind(loops[*l_it],k,i>loop.current_unwinding || - is_new_parent,false); + if(propagate_all == true){ + unwind(loops[*l_it],k,i>loop.current_unwinding || + is_new_parent,false); + } + else{ + if(propagate == true){ + // if this child loop is the desired loop then unwind k and do not propagate + // else unwind loop.current_unwinding and propagate + if(*l_it == prop_loc){ + unwind(loops[*l_it],k,i>loop.current_unwinding || + is_new_parent,false); + } + else{ + unwind(loops[*l_it],loops[*l_it].current_unwinding,i>loop.current_unwinding || + is_new_parent,true,prop_unwind,prop_loc); + } } else{ - unwind(loops[*l_it],loops[*l_it].current_unwinding,i>loop.current_unwinding || - is_new_parent,true,prop_unwind,prop_loc); + unwind(loops[*l_it],loops[*l_it].current_unwinding, + i>loop.current_unwinding || is_new_parent,false); } } - else{ - unwind(loops[*l_it],loops[*l_it].current_unwinding, - i>loop.current_unwinding || is_new_parent,false); - } } SSA.increment_unwindings(0); } SSA.increment_unwindings(-1); +#if 0 + std::cout << "calling add_exit_merge with k = " << k << "\n"; +#endif add_exit_merges(loop, k); } diff --git a/src/ssa/ssa_unwinder.h b/src/ssa/ssa_unwinder.h index 20d376fc6..6dc845dbd 100644 --- a/src/ssa/ssa_unwinder.h +++ b/src/ssa/ssa_unwinder.h @@ -119,8 +119,10 @@ class ssa_local_unwindert void build_pre_post_map(); void build_exit_conditions(); - void unwind(loopt &loop, unsigned k, bool is_new_parent, bool propagate = false, unsigned prop_unwind = 0, unsigned prop_loc = 0); - + void unwind(loopt &loop, unsigned k, bool is_new_parent, + bool propagate = false, unsigned prop_unwind = 0, + unsigned prop_loc = 0, bool propagate_all = false); + exprt get_continuation_condition(const loopt& loop) const; void loop_continuation_conditions( const loopt& loop, exprt::operandst &loop_cont) const; From 90e408ae8d3a44ae5d0edb2edfdd5a4bbc77058e Mon Sep 17 00:00:00 2001 From: Peter Schrammel Date: Mon, 30 May 2016 13:23:56 +0100 Subject: [PATCH 51/82] check whether function has assertion was too semantic, we needed to set the property map correctly --- src/summarizer/summary_checker_base.cpp | 147 +++++++++++++----------- 1 file changed, 83 insertions(+), 64 deletions(-) diff --git a/src/summarizer/summary_checker_base.cpp b/src/summarizer/summary_checker_base.cpp index f7aac91b6..22f6f78a7 100644 --- a/src/summarizer/summary_checker_base.cpp +++ b/src/summarizer/summary_checker_base.cpp @@ -102,7 +102,7 @@ Function: summary_checker_baset::SSA_functions void summary_checker_baset::SSA_functions(const goto_modelt &goto_model, const namespacet &ns) { - entry_function = goto_model.goto_functions.entry_point(); + entry_function = goto_model.goto_functions.entry_point(); // compute SSA for all the functions forall_goto_functions(f_it, goto_model.goto_functions) @@ -143,8 +143,8 @@ Function: summary_checker_baset::summarize \*******************************************************************/ void summary_checker_baset::summarize(const goto_modelt &goto_model, - bool forward, - bool termination) + bool forward, + bool termination) { summarizer_baset *summarizer = NULL; @@ -155,18 +155,18 @@ void summary_checker_baset::summarize(const goto_modelt &goto_model, else #endif { - if(forward && !termination) - summarizer = new summarizer_fwt( - options,summary_db,ssa_db,ssa_unwinder,ssa_inliner); - if(forward && termination) - summarizer = new summarizer_fw_termt( - options,summary_db,ssa_db,ssa_unwinder,ssa_inliner); - if(!forward && !termination) - summarizer = new summarizer_bwt( - options,summary_db,ssa_db,ssa_unwinder,ssa_inliner); - if(!forward && termination) - summarizer = new summarizer_bw_termt( - options,summary_db,ssa_db,ssa_unwinder,ssa_inliner); + if(forward && !termination) + summarizer = new summarizer_fwt( + options,summary_db,ssa_db,ssa_unwinder,ssa_inliner); + if(forward && termination) + summarizer = new summarizer_fw_termt( + options,summary_db,ssa_db,ssa_unwinder,ssa_inliner); + if(!forward && !termination) + summarizer = new summarizer_bwt( + options,summary_db,ssa_db,ssa_unwinder,ssa_inliner); + if(!forward && termination) + summarizer = new summarizer_bw_termt( + options,summary_db,ssa_db,ssa_unwinder,ssa_inliner); } assert(summarizer != NULL); @@ -216,27 +216,27 @@ summary_checker_baset::resultt summary_checker_baset::check_properties( // call recursively for all function calls first for(local_SSAt::nodest::const_iterator n_it = SSA.nodes.begin(); - n_it != SSA.nodes.end(); ++n_it) + n_it != SSA.nodes.end(); ++n_it) { for(local_SSAt::nodet::function_callst::const_iterator ff_it = - n_it->function_calls.begin(); - ff_it != n_it->function_calls.end(); ff_it++) + n_it->function_calls.begin(); + ff_it != n_it->function_calls.end(); ff_it++) { - assert(ff_it->function().id()==ID_symbol); //no function pointers - irep_idt fname = to_symbol_expr(ff_it->function()).get_identifier(); + assert(ff_it->function().id()==ID_symbol); //no function pointers + irep_idt fname = to_symbol_expr(ff_it->function()).get_identifier(); //ENHANCE?: can the return value be exploited? - if(!summary_db.exists(fname) || - summary_db.get(fname).bw_transformer.is_nil()) - { + if(!summary_db.exists(fname) || + summary_db.get(fname).bw_transformer.is_nil()) + { #if 0 debug() << "Checking call " << fname << messaget::eom; #endif if(seen_function_calls.find(fname) == seen_function_calls.end()){ - seen_function_calls.insert(fname); - check_properties(fname, entry_function, seen_function_calls); - } - } + seen_function_calls.insert(fname); + check_properties(fname, entry_function, seen_function_calls); + } + } } } @@ -247,7 +247,7 @@ summary_checker_baset::resultt summary_checker_baset::check_properties( else // check all the functions { for(ssa_dbt::functionst::const_iterator f_it = ssa_db.functions().begin(); - f_it != ssa_db.functions().end(); f_it++) + f_it != ssa_db.functions().end(); f_it++) { status() << "Checking properties of " << f_it->first << messaget::eom; @@ -260,9 +260,9 @@ summary_checker_baset::resultt summary_checker_baset::check_properties( if(options.get_bool_option("show-invariants")) { - if(!summary_db.exists(f_it->first)) continue; - show_invariants(*(f_it->second),summary_db.get(f_it->first),result()); - result() << eom; + if(!summary_db.exists(f_it->first)) continue; + show_invariants(*(f_it->second),summary_db.get(f_it->first),result()); + result() << eom; } } } @@ -272,12 +272,12 @@ summary_checker_baset::resultt summary_checker_baset::check_properties( { // determine overall status for(property_mapt::const_iterator - p_it=property_map.begin(); p_it!=property_map.end(); p_it++) + p_it=property_map.begin(); p_it!=property_map.end(); p_it++) { if(p_it->second.result==FAIL) - return property_checkert::FAIL; + return property_checkert::FAIL; if(p_it->second.result==UNKNOWN) - result = property_checkert::UNKNOWN; + result = property_checkert::UNKNOWN; } } @@ -301,7 +301,27 @@ void summary_checker_baset::check_properties( irep_idt entry_function) { unwindable_local_SSAt &SSA = *f_it->second; - if(!SSA.goto_function.body.has_assertion()) return; + + //check whether function has assertions + // SSA.goto_function.body.has_assertion() has become too semantic + bool has_assertion = false; + for(goto_programt::instructionst::const_iterator + i_it=SSA.goto_function.body.instructions.begin(); + i_it!=SSA.goto_function.body.instructions.end(); + i_it++) + { + if(!i_it->is_assert()) + continue; + + irep_idt property_id = i_it->source_location.get_property_id(); + + if(i_it->guard.is_true()) + property_map[property_id].result=PASS; + else + has_assertion=true; + } + if(!has_assertion) + return; bool all_properties = options.get_bool_option("all-properties"); bool build_error_trace = options.get_bool_option("show-trace"); @@ -314,7 +334,7 @@ void summary_checker_baset::check_properties( incremental_solvert &solver = ssa_db.get_solver(f_it->first); solver.set_message_handler(get_message_handler()); -#if 1 +#if 0 // TEST ssa_const_propagation if(options.get_bool_option("ssa-propagation")) { @@ -324,7 +344,7 @@ void summary_checker_baset::check_properties( solver << c; debug() << "SSA const propagation: " << eom; for(std::list::iterator it = c.begin(); - it!=c.end(); it++) + it!=c.end(); it++) debug() << " " << from_expr(SSA.ns,"",*it) << eom; } #endif @@ -333,7 +353,6 @@ void summary_checker_baset::check_properties( solver << SSA; SSA.mark_nodes(); - solver.new_context(); exprt enabling_expr = SSA.get_enabling_exprs(); @@ -361,7 +380,7 @@ void summary_checker_baset::check_properties( summarizer_bw_cex_baset *summarizer_bw_cex = NULL; incremental_solvert* cex_complete_solver = incremental_solvert::allocate(SSA.ns, - options.get_bool_option("refine")); + options.get_bool_option("refine")); #if 1 cex_complete_solver->set_message_handler(get_message_handler()); #endif @@ -416,7 +435,7 @@ void summary_checker_baset::check_properties( const goto_programt &goto_program=SSA.goto_function.body; for(goto_programt::instructionst::const_iterator - i_it=goto_program.instructions.begin(); + i_it=goto_program.instructions.begin(); i_it!=goto_program.instructions.end(); i_it++) { @@ -437,33 +456,33 @@ void summary_checker_baset::check_properties( unsigned property_counter = 0; for(std::list::const_iterator - n_it=assertion_nodes.begin(); + n_it=assertion_nodes.begin(); n_it!=assertion_nodes.end(); n_it++) { for(local_SSAt::nodet::assertionst::const_iterator - a_it=(*n_it)->assertions.begin(); - a_it!=(*n_it)->assertions.end(); - a_it++, property_counter++) + a_it=(*n_it)->assertions.begin(); + a_it!=(*n_it)->assertions.end(); + a_it++, property_counter++) { - exprt property=*a_it; + exprt property=*a_it; - if(simplify) - property=::simplify_expr(property, SSA.ns); + if(simplify) + property=::simplify_expr(property, SSA.ns); #if 0 - std::cout << "property: " << from_expr(SSA.ns, "", property) << std::endl; + std::cout << "property: " << from_expr(SSA.ns, "", property) << std::endl; #endif - property_map[property_id].location = i_it; - cover_goals.goal_map[property_id].conjuncts.push_back(property); + property_map[property_id].location = i_it; + cover_goals.goal_map[property_id].conjuncts.push_back(property); } } } for(cover_goals_extt::goal_mapt::const_iterator - it=cover_goals.goal_map.begin(); + it=cover_goals.goal_map.begin(); it!=cover_goals.goal_map.end(); it++) { @@ -478,9 +497,9 @@ void summary_checker_baset::check_properties( cover_goals(); /* - std::cout << "Output Verbose: " << entry_function << "\n"; - (ssa_db.get(entry_function)).output_verbose(std::cout); - assert(false); + std::cout << "Output Verbose: " << entry_function << "\n"; + (ssa_db.get(entry_function)).output_verbose(std::cout); + assert(false); */ //set all non-covered goals to PASS except if we do not try // to cover all goals and we have found a FAIL @@ -489,9 +508,9 @@ void summary_checker_baset::check_properties( std::list::const_iterator g_it= cover_goals.goals.begin(); for(cover_goals_extt::goal_mapt::const_iterator - it=cover_goals.goal_map.begin(); - it!=cover_goals.goal_map.end(); - it++, g_it++) + it=cover_goals.goal_map.begin(); + it!=cover_goals.goal_map.end(); + it++, g_it++) { if(!g_it->covered) property_map[it->first].result=PASS; } @@ -502,8 +521,8 @@ void summary_checker_baset::check_properties( summarizer_bw_cex->get_reason(reason); debug() << "** " << cover_goals.number_covered() - << " of " << cover_goals.size() << " failed (" - << cover_goals.iterations() << " iterations)" << eom; + << " of " << cover_goals.size() << " failed (" + << cover_goals.iterations() << " iterations)" << eom; delete summarizer_bw_cex; delete cex_complete_solver; @@ -524,7 +543,7 @@ Function: summary_checker_baset::report_statistics() void summary_checker_baset::report_statistics() { for(ssa_dbt::functionst::const_iterator f_it = ssa_db.functions().begin(); - f_it != ssa_db.functions().end(); f_it++) + f_it != ssa_db.functions().end(); f_it++) { incremental_solvert &solver = ssa_db.get_solver(f_it->first); unsigned calls = solver.get_number_of_solver_calls(); @@ -670,12 +689,12 @@ Function: summary_checker_baset::is_spurious \*******************************************************************/ bool summary_checker_baset::is_spurious(const exprt::operandst &loophead_selects, - incremental_solvert &solver) + incremental_solvert &solver) { //check loop head choices in model bool invariants_involved = false; for(exprt::operandst::const_iterator l_it = loophead_selects.begin(); - l_it != loophead_selects.end(); l_it++) + l_it != loophead_selects.end(); l_it++) { if(solver.get(l_it->op0()).is_true()) { @@ -726,6 +745,6 @@ void summary_checker_baset::instrument_and_output(goto_modelt &goto_model) std::string filename = options.get_option("instrument-output"); status() << "Writing instrumented goto-binary " << filename << eom; write_goto_binary(filename, - goto_model.symbol_table, - goto_model.goto_functions, get_message_handler()); + goto_model.symbol_table, + goto_model.goto_functions, get_message_handler()); } From acc5de069ac9061b2a7f6453796dc936fa41f9fb Mon Sep 17 00:00:00 2001 From: Peter Schrammel Date: Mon, 30 May 2016 13:50:53 +0100 Subject: [PATCH 52/82] loop enabling expr fixed --- src/ssa/ssa_unwinder.cpp | 6 +----- src/ssa/ssa_unwinder.h | 2 +- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/src/ssa/ssa_unwinder.cpp b/src/ssa/ssa_unwinder.cpp index aa9e3de0f..1dd62a9a9 100644 --- a/src/ssa/ssa_unwinder.cpp +++ b/src/ssa/ssa_unwinder.cpp @@ -290,11 +290,7 @@ void ssa_local_unwindert::unwind_loop_at_location(unsigned loc, unsigned k) return; loopt &loop = loops[loc]; - loop.loop_enabling_expr_current = - symbol_exprt("unwind$"+id2string(fname)+"$loc"+i2string(loc)+"$enable"+i2string(k), - bool_typet()); - - loop.loop_enabling_exprs.push_back(loop.loop_enabling_expr_current); + loop.loop_enabling_exprs.push_back(symbol_exprt("unwind$"+id2string(fname)+"$loc"+i2string(loc)+"$enable"+i2string(k),bool_typet())); //current_enabling_expr = // symbol_exprt("unwind::"+id2string(fname)+"::enable"+i2string(k), diff --git a/src/ssa/ssa_unwinder.h b/src/ssa/ssa_unwinder.h index 6dc845dbd..73a9d6f07 100644 --- a/src/ssa/ssa_unwinder.h +++ b/src/ssa/ssa_unwinder.h @@ -83,7 +83,7 @@ class ssa_local_unwindert // to have an enabling_expr and current_unwindings (odometert) exprt::operandst loop_enabling_exprs; - exprt loop_enabling_expr_current; + //exprt loop_enabling_expr_current; //seems superfluous exprt::operandst current_continuation_conditions; From eaa73f35efdebbcc6b465cb9a08077edb0445ede Mon Sep 17 00:00:00 2001 From: Peter Schrammel Date: Mon, 30 May 2016 13:57:23 +0100 Subject: [PATCH 53/82] loop enabling expr fixed, removed superfluous variables --- src/ssa/ssa_unwinder.cpp | 4 ++-- src/ssa/ssa_unwinder.h | 11 +++++++---- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/ssa/ssa_unwinder.cpp b/src/ssa/ssa_unwinder.cpp index 1dd62a9a9..1dece3d90 100644 --- a/src/ssa/ssa_unwinder.cpp +++ b/src/ssa/ssa_unwinder.cpp @@ -347,7 +347,7 @@ void ssa_local_unwindert::unwind(unsigned k) bool_typet()); for(loop_mapt::iterator it = loops.begin(); it != loops.end(); ++it) { - it->second.loop_enabling_exprs.push_back(current_enabling_expr); + it->second.loop_enabling_exprs.push_back(symbol_exprt("unwind$"+id2string(fname)+"$loc"+i2string(it->first)+"$enable"+i2string(k),bool_typet())); } // TODO: just for exploratory integration, must go away @@ -689,7 +689,7 @@ void ssa_local_unwindert::add_exit_merges(loopt &loop, unsigned k) SSA.nodes.push_back(local_SSAt::nodet(loop.body_nodes.begin()->location, SSA.nodes.end())); // add new node local_SSAt::nodet &node=SSA.nodes.back(); - node.enabling_expr=current_enabling_expr; +(??) node.enabling_expr = current_enabling_expr; for(loopt::exit_mapt::const_iterator x_it=loop.exit_map.begin(); x_it!=loop.exit_map.end(); x_it++) diff --git a/src/ssa/ssa_unwinder.h b/src/ssa/ssa_unwinder.h index 73a9d6f07..c20dbc280 100644 --- a/src/ssa/ssa_unwinder.h +++ b/src/ssa/ssa_unwinder.h @@ -59,9 +59,13 @@ class ssa_local_unwindert symbol_exprt &var, const local_SSAt::nodet &node, bool pre) const; #endif - // TODO: this must go away, should use SSA.rename instead - void unwinder_rename( - symbol_exprt &var, const local_SSAt::nodet &node, bool pre) const; + //TODO: this must go away, should use SSA.rename instead + void unwinder_rename(symbol_exprt &var, + const local_SSAt::nodet &node, bool pre) const; +protected: + const irep_idt fname; + unwindable_local_SSAt& SSA; + bool is_kinduction,is_bmc; class loopt // loop tree { @@ -83,7 +87,6 @@ class ssa_local_unwindert // to have an enabling_expr and current_unwindings (odometert) exprt::operandst loop_enabling_exprs; - //exprt loop_enabling_expr_current; //seems superfluous exprt::operandst current_continuation_conditions; From 4fe616c278d4409bb33f60d4ff6a23247201f2f0 Mon Sep 17 00:00:00 2001 From: Peter Schrammel Date: Mon, 30 May 2016 15:10:01 +0100 Subject: [PATCH 54/82] missing regressions --- regression/modular/nested11/main.c | 19 +++++++++++++++++++ regression/modular/nested11/test.desc | 6 ++++++ regression/modular/nested12/main.c | 18 ++++++++++++++++++ regression/modular/nested12/test.desc | 6 ++++++ 4 files changed, 49 insertions(+) create mode 100644 regression/modular/nested11/main.c create mode 100644 regression/modular/nested11/test.desc create mode 100644 regression/modular/nested12/main.c create mode 100644 regression/modular/nested12/test.desc diff --git a/regression/modular/nested11/main.c b/regression/modular/nested11/main.c new file mode 100644 index 000000000..790b6c4b3 --- /dev/null +++ b/regression/modular/nested11/main.c @@ -0,0 +1,19 @@ +void main() +{ + int x,y; + for(x=0;x<10;) + { + for(y=0;y Date: Mon, 30 May 2016 16:43:20 +0100 Subject: [PATCH 55/82] simplified example that exposes problem with monolithic --k-induction --havoc --- regression/kiki/induction7a/main.c | 12 ++++++++++++ regression/kiki/induction7a/test.desc | 6 ++++++ src/summarizer/summarizer_bw_cex_concrete.cpp | 2 ++ 3 files changed, 20 insertions(+) create mode 100644 regression/kiki/induction7a/main.c create mode 100644 regression/kiki/induction7a/test.desc diff --git a/regression/kiki/induction7a/main.c b/regression/kiki/induction7a/main.c new file mode 100644 index 000000000..5a9e3cf63 --- /dev/null +++ b/regression/kiki/induction7a/main.c @@ -0,0 +1,12 @@ +void main() +{ + int s=0; + int x=0; + while(1) + { + s += 2; + if(x==1) s++; + x++; + assert(s == 2*x); + } +} diff --git a/regression/kiki/induction7a/test.desc b/regression/kiki/induction7a/test.desc new file mode 100644 index 000000000..b3256a114 --- /dev/null +++ b/regression/kiki/induction7a/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--k-induction --havoc +^EXIT=10$ +^SIGNAL=0$ +^.*FAILURE$ diff --git a/src/summarizer/summarizer_bw_cex_concrete.cpp b/src/summarizer/summarizer_bw_cex_concrete.cpp index 1c55814de..db09fda7c 100644 --- a/src/summarizer/summarizer_bw_cex_concrete.cpp +++ b/src/summarizer/summarizer_bw_cex_concrete.cpp @@ -14,6 +14,8 @@ Author: Kumar Madhukar, Peter Schrammel //TODO: a bug in the fresh solver case; does not compute //calling contexts (see struct tests in regression) +#define DEBUG + #include #include From f3eac2150cf76bb1643583051d3a484188dab7ec Mon Sep 17 00:00:00 2001 From: Peter Schrammel Date: Mon, 30 May 2016 17:52:00 +0100 Subject: [PATCH 56/82] wrong assertions feeded into cex checker; output assignments in incremental_solver debug mode --- regression/modular/nested12/main.c | 36 +++++++++---------- src/2ls/cover_goals_ext.cpp | 12 ++++++- src/domains/incremental_solver.h | 13 +++++++ src/ssa/ssa_refiner_monolithic.cpp | 2 +- src/ssa/ssa_refiner_selective.cpp | 2 +- src/summarizer/summarizer_bw_cex_concrete.cpp | 9 +++-- 6 files changed, 48 insertions(+), 26 deletions(-) diff --git a/regression/modular/nested12/main.c b/regression/modular/nested12/main.c index 3b136bbd9..c36a9507a 100644 --- a/regression/modular/nested12/main.c +++ b/regression/modular/nested12/main.c @@ -1,18 +1,18 @@ -#define a 2 - -extern int nondet_int(); - -int main() { - int i=0, n=3,sn=0,x,y; - - for(x=0;x<5;x++) - { - sn = nondet_int(); - - while(icond_expression).id() == ID_not); exprt conjunct_expr = (g_it->cond_expression).op0(); +#if 0 + std::cout << "FAILED EXPR: " + << from_expr(SSA.ns, "", conjunct_expr) << std::endl; +#endif if(conjunct_expr.id() != ID_and) { @@ -200,8 +204,14 @@ void cover_goals_extt::assignment() c_it != conjunct_expr.operands().end(); c_it++) { literalt conjunct_literal = solver.convert(*c_it); - if(solver.l_get(conjunct_literal).is_true()) + if(solver.l_get(conjunct_literal).is_false()) + { failed_exprs.push_back(*c_it); +#if 0 + std::cout << "failed_expr: " + << from_expr(SSA.ns, "", *c_it) << std::endl; +#endif + } } solver.pop_context(); //otherwise this would interfere with necessary preconditions summarizer_bw_cex.summarize(not_exprt(conjunction(failed_exprs))); diff --git a/src/domains/incremental_solver.h b/src/domains/incremental_solver.h index 51f2332ed..f16ed53f3 100644 --- a/src/domains/incremental_solver.h +++ b/src/domains/incremental_solver.h @@ -15,6 +15,7 @@ Author: Peter Schrammel #include #include #include +#include #include "domain.h" #include "util.h" @@ -105,6 +106,18 @@ class incremental_solvert:public messaget << from_expr(ns, "", formula_expr[i]) << std::endl; } } + if(result==decision_proceduret::D_SATISFIABLE) + { + std::set vars; + for(unsigned i=0; i::const_iterator it = vars.begin(); + it != vars.end(); ++it) + { + std::cout << "assignment: " << from_expr(ns, "", *it) << " = " + << from_expr(ns, "", solver->get(*it)) << std::endl; + } + } return result; #else return (*solver)(); diff --git a/src/ssa/ssa_refiner_monolithic.cpp b/src/ssa/ssa_refiner_monolithic.cpp index a7191481c..ceb26639e 100644 --- a/src/ssa/ssa_refiner_monolithic.cpp +++ b/src/ssa/ssa_refiner_monolithic.cpp @@ -26,5 +26,5 @@ bool ssa_refiner_monolithict::operator()() summary_db.mark_recompute_all(); //TODO: recompute only functions with loops ssa_unwinder.unwind_all(unwind); - return unwind++ @@ -177,8 +177,7 @@ void summarizer_bw_cex_concretet::compute_summary_rec( summary.bw_postcondition = _postcondition; #if 0 - debug() << "Postcondition: " << - from_expr(SSA.ns, "", postcondition) << eom; + debug() << "Postcondition: " << from_expr(SSA.ns, "", postcondition) << eom; #endif // recursively compute summaries for function calls @@ -366,7 +365,7 @@ void summarizer_bw_cex_concretet::do_summary( #endif #ifdef OPT_12 -#if 1 +#ifdef DEBUG std::cout << "\n\n\n pushing to the solver in do_summary:" << from_expr(SSA.ns, "", conjunction(store)) << "\n\n\n"; #endif solver << simplify_expr(conjunction(store), SSA.ns); @@ -604,7 +603,7 @@ exprt summarizer_bw_cex_concretet::compute_calling_context2( #endif #ifdef OPT_12 -#if 1 +#ifdef DEBUG std::cout << "\n\n\n pushing to the solver in compute_calling_context2:" << from_expr(SSA.ns, "", conjunction(store)) << "\n\n\n"; #endif solver << simplify_expr(conjunction(store), SSA.ns); From ffae69d2c4bec7e14f3ac18bbc28bef413b14a6a Mon Sep 17 00:00:00 2001 From: Peter Schrammel Date: Mon, 30 May 2016 18:37:57 +0100 Subject: [PATCH 57/82] collecting renamed error assertions - still some of them are missed --- src/summarizer/summarizer_bw_cex_complete.cpp | 27 ++++++++++++++----- src/summarizer/summarizer_bw_cex_complete.h | 1 + 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/src/summarizer/summarizer_bw_cex_complete.cpp b/src/summarizer/summarizer_bw_cex_complete.cpp index c281779d3..f4ddc9cce 100644 --- a/src/summarizer/summarizer_bw_cex_complete.cpp +++ b/src/summarizer/summarizer_bw_cex_complete.cpp @@ -289,13 +289,23 @@ find_symbols_sett summarizer_bw_cex_completet::inline_summaries // if the dependency set is non-empty if(!worknode.dependency_set.empty()){ exprt worknode_info = depnode.node_info; - if(depnode.is_assertion == true) - worknode_info = not_exprt(worknode_info); + + bool is_error_assertion = false; + assert(error_assertion.id()==ID_not); + if(error_assertion.op0().id()!=ID_and) + is_error_assertion = (worknode_info == error_assertion.op0()); + else + forall_operands(a_it, error_assertion.op0()) + if(worknode_info == *a_it) + { + is_error_assertion = true; + break; + } if(worknode.node_index != 0){ if(!(depnode.is_function_call)){ - if((depnode.is_assertion == false) || - (worknode_info == error_assertion)){ + if(!depnode.is_assertion || is_error_assertion) + { /* std::cout << "Solver <-- " << function_name << ": (node) node#:" << worknode.node_index << "\t original info ~ " @@ -310,7 +320,7 @@ find_symbols_sett summarizer_bw_cex_completet::inline_summaries #endif if(depnode.is_assertion) //keep for later - error_assertion = worknode_info; + renamed_error_assertion.push_back(worknode_info); else solver << worknode_info; @@ -527,13 +537,16 @@ Function: summarizer_bw_cex_completet::check() property_checkert::resultt summarizer_bw_cex_completet::check() { + assert(!renamed_error_assertion.empty()); //otherwise the error assertion was not renamed + //add loophead selects #ifdef REFINE_ALL solver.new_context(); - solver << error_assertion; + solver << not_exprt(conjunction(renamed_error_assertion)); solver << conjunction(loophead_selects); #else - formula.push_back(solver.solver->convert(error_assertion)); + formula.push_back(solver.solver->convert( + not_exprt(conjunction(renamed_error_assertion)))); solver.solver->set_assumptions(formula); #endif diff --git a/src/summarizer/summarizer_bw_cex_complete.h b/src/summarizer/summarizer_bw_cex_complete.h index ef1827457..8646c409d 100644 --- a/src/summarizer/summarizer_bw_cex_complete.h +++ b/src/summarizer/summarizer_bw_cex_complete.h @@ -48,6 +48,7 @@ class summarizer_bw_cex_completet : public summarizer_bw_cex_baset exprt::operandst formula_expr; //for debugging exprt::operandst loophead_selects; exprt::operandst loop_continues; + exprt::operandst renamed_error_assertion; struct reason_to_checkt { function_namet function_name; From badd85e799ffb8aa37b7c7d8b0844603b3c47de7 Mon Sep 17 00:00:00 2001 From: Peter Schrammel Date: Mon, 30 May 2016 20:52:08 +0100 Subject: [PATCH 58/82] assertion renaming in cex_complete fixed --- src/2ls/cover_goals_ext.cpp | 8 +++++ src/domains/incremental_solver.h | 10 +++++-- src/summarizer/summarizer_bw_cex_complete.cpp | 30 ++++++++++++------- 3 files changed, 35 insertions(+), 13 deletions(-) diff --git a/src/2ls/cover_goals_ext.cpp b/src/2ls/cover_goals_ext.cpp index 906ac1497..219012e0e 100644 --- a/src/2ls/cover_goals_ext.cpp +++ b/src/2ls/cover_goals_ext.cpp @@ -181,6 +181,13 @@ void cover_goals_extt::assignment() if(property_map[it->first].result==property_checkert::UNKNOWN && solver.l_get(g_it->condition).is_true()) { +#if 1 + solver.pop_context(); //otherwise this would interfere with necessary preconditions + summarizer_bw_cex.summarize(g_it->cond_expression); + property_map[it->first].result = summarizer_bw_cex.check(); + solver.new_context(); +#else // THE ASSERTIONS THAT FAIL COULD BE RATHER ARBITRARY SINCE THE FORMULA + // IS NOT "ROOTED" IN AN INITIAL STATE. assert((g_it->cond_expression).id() == ID_not); exprt conjunct_expr = (g_it->cond_expression).op0(); #if 0 @@ -218,6 +225,7 @@ void cover_goals_extt::assignment() property_map[it->first].result = summarizer_bw_cex.check(); solver.new_context(); } +#endif } if(property_map[it->first].result == property_checkert::FAIL) { diff --git a/src/domains/incremental_solver.h b/src/domains/incremental_solver.h index f16ed53f3..c5f16cfc6 100644 --- a/src/domains/incremental_solver.h +++ b/src/domains/incremental_solver.h @@ -95,8 +95,10 @@ class incremental_solvert:public messaget solver->set_assumptions(whole_formula); #endif #endif -#if defined(DEBUG_FORMULA) && defined(DEBUG_OUTPUT) +#if defined(DEBUG_FORMULA) || defined(DISPLAY_FORMULA) decision_proceduret::resultt result = (*solver)(); +#endif +#if defined(DEBUG_FORMULA) && defined(DEBUG_OUTPUT) if(result==decision_proceduret::D_UNSATISFIABLE) { for(unsigned i=0; i vars; @@ -119,7 +123,8 @@ class incremental_solvert:public messaget } } return result; -#else +#endif +#if !defined(DEBUG_FORMULA) && !defined(DISPLAY_FORMULA) return (*solver)(); #endif } @@ -217,6 +222,7 @@ static inline incremental_solvert &operator<<( else std::cerr << "add_to_solver: " << from_expr(dest.ns, "", src) << std::endl; + dest.formula_expr.push_back(src); #endif #ifdef NON_INCREMENTAL diff --git a/src/summarizer/summarizer_bw_cex_complete.cpp b/src/summarizer/summarizer_bw_cex_complete.cpp index f4ddc9cce..b90f912d4 100644 --- a/src/summarizer/summarizer_bw_cex_complete.cpp +++ b/src/summarizer/summarizer_bw_cex_complete.cpp @@ -287,20 +287,28 @@ find_symbols_sett summarizer_bw_cex_completet::inline_summaries } // if the dependency set is non-empty - if(!worknode.dependency_set.empty()){ + if(!worknode.dependency_set.empty()) + { exprt worknode_info = depnode.node_info; bool is_error_assertion = false; - assert(error_assertion.id()==ID_not); - if(error_assertion.op0().id()!=ID_and) - is_error_assertion = (worknode_info == error_assertion.op0()); - else - forall_operands(a_it, error_assertion.op0()) - if(worknode_info == *a_it) - { - is_error_assertion = true; - break; - } + if(depnode.is_assertion) + { +#if 0 + std::cout << "assertion: " << from_expr(SSA.ns, "", error_assertion) << std::endl; + std::cout << "to check: " << from_expr(SSA.ns, "", worknode_info) << std::endl; +#endif + assert(error_assertion.id()==ID_not); + if(error_assertion.op0().id()!=ID_and) + is_error_assertion = (worknode_info == error_assertion.op0()); + else + forall_operands(a_it, error_assertion.op0()) + if(worknode_info == *a_it) + { + is_error_assertion = true; + break; + } + } if(worknode.node_index != 0){ if(!(depnode.is_function_call)){ From d1d8bf8306ea594a3b0993a5db16dbc6885e0d46 Mon Sep 17 00:00:00 2001 From: Peter Schrammel Date: Mon, 30 May 2016 21:22:22 +0100 Subject: [PATCH 59/82] be more robust w.r.t. functions that are not in the SSA db --- src/summarizer/summary_checker_base.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/summarizer/summary_checker_base.cpp b/src/summarizer/summary_checker_base.cpp index 22f6f78a7..3bf06e9a6 100644 --- a/src/summarizer/summary_checker_base.cpp +++ b/src/summarizer/summary_checker_base.cpp @@ -212,6 +212,7 @@ summary_checker_baset::resultt summary_checker_baset::check_properties( { ssa_dbt::functionst::const_iterator f_it = ssa_db.functions().find(function_name); + assert(f_it != ssa_db.functions().end()); local_SSAt &SSA = *f_it->second; // call recursively for all function calls first @@ -224,10 +225,11 @@ summary_checker_baset::resultt summary_checker_baset::check_properties( { assert(ff_it->function().id()==ID_symbol); //no function pointers irep_idt fname = to_symbol_expr(ff_it->function()).get_identifier(); + //ENHANCE?: can the return value be exploited? - - if(!summary_db.exists(fname) || - summary_db.get(fname).bw_transformer.is_nil()) + if(ssa_db.functions().find(fname)!=ssa_db.functions().end() && + (!summary_db.exists(fname) || + summary_db.get(fname).bw_transformer.is_nil())) { #if 0 debug() << "Checking call " << fname << messaget::eom; From 54980f3eb07fe9adc90125738a87490c5b266f01 Mon Sep 17 00:00:00 2001 From: Peter Schrammel Date: Mon, 30 May 2016 21:46:59 +0100 Subject: [PATCH 60/82] assumptions must hold in backwards analysis --- src/summarizer/summarizer_bw_cex_complete.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/summarizer/summarizer_bw_cex_complete.cpp b/src/summarizer/summarizer_bw_cex_complete.cpp index b90f912d4..a11851038 100644 --- a/src/summarizer/summarizer_bw_cex_complete.cpp +++ b/src/summarizer/summarizer_bw_cex_complete.cpp @@ -103,6 +103,17 @@ find_symbols_sett summarizer_bw_cex_completet::inline_summaries solver << enable_exprs; + // assumptions must hold + for(local_SSAt::nodest::const_iterator + n_it = SSA.nodes.begin(); n_it != SSA.nodes.end(); ++n_it) + for(local_SSAt::nodet::assumptionst::const_iterator + a_it = n_it->assumptions.begin(); a_it != n_it->assumptions.end(); ++a_it) + { + exprt assumption = *a_it; + ssa_inliner.rename(assumption, counter); + solver << assumption; + } + #ifdef REFINE_ALL //TODO: let's just put all loops into the reason for(local_SSAt::nodest::iterator n_it = SSA.nodes.begin(); From b7c42d56a4f6e0a80f02d6be848b08f6386b8452 Mon Sep 17 00:00:00 2001 From: Peter Schrammel Date: Mon, 30 May 2016 22:10:48 +0100 Subject: [PATCH 61/82] clean up summary_checker_base --- src/summarizer/summarizer_bw_cex_complete.cpp | 2 +- src/summarizer/summary_checker_ai.cpp | 2 +- src/summarizer/summary_checker_base.cpp | 144 +++++------------- src/summarizer/summary_checker_base.h | 16 +- src/summarizer/summary_checker_bmc.cpp | 3 +- src/summarizer/summary_checker_kind.cpp | 4 +- 6 files changed, 47 insertions(+), 124 deletions(-) diff --git a/src/summarizer/summarizer_bw_cex_complete.cpp b/src/summarizer/summarizer_bw_cex_complete.cpp index a11851038..8c2a7ef1e 100644 --- a/src/summarizer/summarizer_bw_cex_complete.cpp +++ b/src/summarizer/summarizer_bw_cex_complete.cpp @@ -261,7 +261,7 @@ find_symbols_sett summarizer_bw_cex_completet::inline_summaries */ ///////////////////////////////////////////////////////////////////////////////////// -#if 0 +#ifdef REFINE_ALL //TODO: just put all function calls into reason reason[function_name].functions.insert(depnode.location); #endif diff --git a/src/summarizer/summary_checker_ai.cpp b/src/summarizer/summary_checker_ai.cpp index 16008db7f..51c2411d2 100644 --- a/src/summarizer/summary_checker_ai.cpp +++ b/src/summarizer/summary_checker_ai.cpp @@ -143,7 +143,7 @@ property_checkert::resultt summary_checker_ait::operator()( */ std::set seen_function_calls; - property_checkert::resultt result = check_properties(entry_function, entry_function, seen_function_calls); + property_checkert::resultt result = check_properties(entry_function, entry_function, seen_function_calls, false); report_statistics(); return result; } diff --git a/src/summarizer/summary_checker_base.cpp b/src/summarizer/summary_checker_base.cpp index 3bf06e9a6..a02857af5 100644 --- a/src/summarizer/summary_checker_base.cpp +++ b/src/summarizer/summary_checker_base.cpp @@ -202,11 +202,14 @@ Function: summary_checker_baset::check_properties summary_checker_baset::resultt summary_checker_baset::check_properties() { std::set seen_function_calls; - return check_properties("", "", seen_function_calls); + return check_properties("", "", seen_function_calls, false); } summary_checker_baset::resultt summary_checker_baset::check_properties( - irep_idt function_name, irep_idt entry_function, std::set seen_function_calls) + irep_idt function_name, + irep_idt entry_function, + std::set seen_function_calls, + bool is_inlined) { if(function_name!="") { @@ -236,15 +239,19 @@ summary_checker_baset::resultt summary_checker_baset::check_properties( #endif if(seen_function_calls.find(fname) == seen_function_calls.end()){ seen_function_calls.insert(fname); - check_properties(fname, entry_function, seen_function_calls); + check_properties(fname, entry_function, seen_function_calls, + n_it->function_calls_inlined); } } } } - //now check function itself - status() << "Checking properties of " << f_it->first << messaget::eom; - check_properties(f_it, entry_function); + if(!is_inlined) + { + //now check function itself + status() << "Checking properties of " << f_it->first << messaget::eom; + check_properties(f_it, entry_function); + } } else // check all the functions { @@ -373,10 +380,12 @@ void summary_checker_baset::check_properties( //callee summaries solver << ssa_inliner.get_summaries(SSA); +#if 0 //freeze loop head selects exprt::operandst loophead_selects; summarizer_baset::get_loophead_selects(SSA, ssa_unwinder.get(f_it->first),*solver.solver, loophead_selects); +#endif //spuriousness checkers summarizer_bw_cex_baset *summarizer_bw_cex = NULL; @@ -449,6 +458,12 @@ void summary_checker_baset::check_properties( SSA.find_nodes(i_it,assertion_nodes); irep_idt property_id = location.get_property_id(); + + if(i_it->guard.is_true()) + { + property_map[property_id].result=PASS; + continue; + } //do not recheck properties that have already been decided if(property_map[property_id].result!=UNKNOWN) continue; @@ -594,81 +609,49 @@ void summary_checker_baset::do_show_vcc( std::cout << "{1} " << from_expr(SSA.ns, "", *a_it) << "\n"; std::cout << "\n"; -} - +(??)} +(??) +(??) (??)/*******************************************************************\ (??) -(??)Function: summary_checker_baset::get_loop_continues +(??)Function: summary_checker_baset::is_spurious (??) (??) Inputs: (??) (??) Outputs: (??) -(??) Purpose: returns the loop continuation guards at the end of the -(??) loops in order to check whether we can unroll further +(??) Purpose: checks whether a countermodel is spurious (??) (??)\*******************************************************************/ (??) -(??)exprt::operandst summary_checker_baset::get_loop_continues( -(??) const irep_idt &function_name, -(??) const local_SSAt &SSA, prop_convt &solver) +(??)bool summary_checker_baset::is_spurious(const exprt::operandst &loophead_selects, +(??) incremental_solvert &solver) (??){ -(??) exprt::operandst loop_continues; -(??) -(??) ssa_unwinder.get(function_name).loop_continuation_conditions(loop_continues); -(??) if(loop_continues.size()==0) +(??) //check loop head choices in model +(??) bool invariants_involved = false; +(??) for(exprt::operandst::const_iterator l_it = loophead_selects.begin(); +(??) l_it != loophead_selects.end(); l_it++) (??) { -(??) //TODO: this should actually be done transparently by the unwinder -(??) for(local_SSAt::nodest::const_iterator n_it = SSA.nodes.begin(); -(??) n_it != SSA.nodes.end(); n_it++) +(??) if(solver.get(l_it->op0()).is_true()) (??) { -(??) if(n_it->loophead==SSA.nodes.end()) continue; -(??) symbol_exprt guard = SSA.guard_symbol(n_it->location); -(??) symbol_exprt cond = SSA.cond_symbol(n_it->location); -(??) loop_continues.push_back(and_exprt(guard,cond)); +(??) invariants_involved = true; +(??) break; (??) } (??) } -(??) -(??)#if 0 -(??) std::cout << "loophead_continues: " << from_expr(SSA.ns,"",disjunction(loop_continues)) << std::endl; -(??)#endif -(??) -(??) return loop_continues; -(??)} -(??) -(??)/*******************************************************************\ -(??) -(??)Function: summary_checker_baset::is_fully_unwound -(??) -(??) Inputs: -(??) -(??) Outputs: -(??) -(??) Purpose: checks whether the loops have been fully unwound -(??) -(??)\*******************************************************************/ -(??) -(??)bool summary_checker_baset::is_fully_unwound( -(??) const exprt::operandst &loop_continues, -(??) const exprt::operandst &loophead_selects, -(??) incremental_solvert &solver) -(??){ -(??) solver.new_context(); -(??) solver << and_exprt(conjunction(loophead_selects), -(??) disjunction(loop_continues)); +(??) if(!invariants_involved) return false; +(??) +(??) // force avoiding paths going through invariants +(??) solver << conjunction(loophead_selects); (??) (??) solver_calls++; //statistics (??) (??) switch(solver()) (??) { (??) case decision_proceduret::D_SATISFIABLE: -(??) solver.pop_context(); (??) return false; (??) break; (??) (??) case decision_proceduret::D_UNSATISFIABLE: -(??) solver.pop_context(); -(??) solver << conjunction(loophead_selects); (??) return true; (??) break; (??) @@ -676,55 +659,6 @@ void summary_checker_baset::do_show_vcc( (??) default: (??) throw "error from decision procedure"; (??) } -(??)} - -/*******************************************************************\ - -Function: summary_checker_baset::is_spurious - - Inputs: - - Outputs: - - Purpose: checks whether a countermodel is spurious - -\*******************************************************************/ - -bool summary_checker_baset::is_spurious(const exprt::operandst &loophead_selects, - incremental_solvert &solver) -{ - //check loop head choices in model - bool invariants_involved = false; - for(exprt::operandst::const_iterator l_it = loophead_selects.begin(); - l_it != loophead_selects.end(); l_it++) - { - if(solver.get(l_it->op0()).is_true()) - { - invariants_involved = true; - break; - } - } - if(!invariants_involved) return false; - - // force avoiding paths going through invariants - solver << conjunction(loophead_selects); - - solver_calls++; //statistics - - switch(solver()) - { - case decision_proceduret::D_SATISFIABLE: - return false; - break; - - case decision_proceduret::D_UNSATISFIABLE: - return true; - break; - - case decision_proceduret::D_ERROR: - default: - throw "error from decision procedure"; - } } /*******************************************************************\ diff --git a/src/summarizer/summary_checker_base.h b/src/summarizer/summary_checker_base.h index b1e7e3eb8..024db61d0 100644 --- a/src/summarizer/summary_checker_base.h +++ b/src/summarizer/summary_checker_base.h @@ -84,23 +84,11 @@ class summary_checker_baset:public property_checkert property_checkert::resultt check_properties( irep_idt function_name, irep_idt entry_function, - std::set seen_function_calls); + std::set seen_function_calls, + bool is_inlined); void check_properties( const ssa_dbt::functionst::const_iterator f_it, irep_idt entry_function=""); - - void error_summary_using_vars(const ssa_dbt::functionst::const_iterator f_it); - - exprt::operandst get_loophead_selects( - const irep_idt &function_name, const local_SSAt &, prop_convt &); - bool is_spurious(const exprt::operandst& loophead_selects, - incremental_solvert&); - exprt::operandst get_loop_continues( - const irep_idt &function_name, const local_SSAt &, prop_convt &); - bool is_fully_unwound( - const exprt::operandst& loop_continues, - const exprt::operandst& loophead_selects, - incremental_solvert&); }; #endif diff --git a/src/summarizer/summary_checker_bmc.cpp b/src/summarizer/summary_checker_bmc.cpp index 9efbbc98b..9ce39f96f 100644 --- a/src/summarizer/summary_checker_bmc.cpp +++ b/src/summarizer/summary_checker_bmc.cpp @@ -70,7 +70,8 @@ property_checkert::resultt summary_checker_bmct::operator()( //check std::set seen_function_calls; - result = check_properties(entry_function, entry_function, seen_function_calls); + result = check_properties(entry_function, entry_function, + seen_function_calls, false); //result if(result == property_checkert::PASS) diff --git a/src/summarizer/summary_checker_kind.cpp b/src/summarizer/summary_checker_kind.cpp index c35506d0a..7a4fed218 100644 --- a/src/summarizer/summary_checker_kind.cpp +++ b/src/summarizer/summary_checker_kind.cpp @@ -69,7 +69,7 @@ property_checkert::resultt summary_checker_kindt::operator()( //check std::set seen_function_calls; result = check_properties(entry_function, entry_function, - seen_function_calls); + seen_function_calls, false); //do static analysis and check again if(result == property_checkert::UNKNOWN && @@ -80,7 +80,7 @@ property_checkert::resultt summary_checker_kindt::operator()( summarize(goto_model); std::set seen_function_calls; result = check_properties(entry_function, entry_function, - seen_function_calls); + seen_function_calls, false); } //result From 06849a2f380d3282d9921ba3f7c1bb9e6aa2e7ad Mon Sep 17 00:00:00 2001 From: Peter Schrammel Date: Mon, 30 May 2016 22:44:41 +0100 Subject: [PATCH 62/82] check for inlined functions whether they have assertions --- src/ssa/ssa_inliner.cpp | 2 + src/summarizer/summary_checker_base.cpp | 69 ++++++++++++++++++------- src/summarizer/summary_checker_base.h | 3 ++ 3 files changed, 56 insertions(+), 18 deletions(-) diff --git a/src/ssa/ssa_inliner.cpp b/src/ssa/ssa_inliner.cpp index 72abe4101..e7818d59a 100644 --- a/src/ssa/ssa_inliner.cpp +++ b/src/ssa/ssa_inliner.cpp @@ -1225,3 +1225,5 @@ irep_idt ssa_inlinert::get_original_identifier(const symbol_exprt &s) return id; } + + diff --git a/src/summarizer/summary_checker_base.cpp b/src/summarizer/summary_checker_base.cpp index a02857af5..e2a8ad0f0 100644 --- a/src/summarizer/summary_checker_base.cpp +++ b/src/summarizer/summary_checker_base.cpp @@ -312,24 +312,7 @@ void summary_checker_baset::check_properties( unwindable_local_SSAt &SSA = *f_it->second; //check whether function has assertions - // SSA.goto_function.body.has_assertion() has become too semantic - bool has_assertion = false; - for(goto_programt::instructionst::const_iterator - i_it=SSA.goto_function.body.instructions.begin(); - i_it!=SSA.goto_function.body.instructions.end(); - i_it++) - { - if(!i_it->is_assert()) - continue; - - irep_idt property_id = i_it->source_location.get_property_id(); - - if(i_it->guard.is_true()) - property_map[property_id].result=PASS; - else - has_assertion=true; - } - if(!has_assertion) + if(!has_assertion(f_it->first)) return; bool all_properties = options.get_bool_option("all-properties"); @@ -684,3 +667,53 @@ void summary_checker_baset::instrument_and_output(goto_modelt &goto_model) goto_model.symbol_table, goto_model.goto_functions, get_message_handler()); } + +/*******************************************************************\ + +Function: summary_checker_baset::has_assertion + + Inputs: + + Outputs: + + Purpose: searches recursively for assertions in inlined functions + +\*******************************************************************/ + +bool summary_checker_baset::has_assertion(irep_idt function_name) +{ + // SSA.goto_function.body.has_assertion() has become too semantic + bool _has_assertion = false; + const local_SSAt &SSA = ssa_db.get(function_name); + + for(local_SSAt::nodest::const_iterator + n_it = SSA.nodes.begin(); n_it != SSA.nodes.end(); ++n_it) + { + for(local_SSAt::nodet::assertionst::const_iterator + a_it = n_it->assertions.begin(); a_it != n_it->assertions.end(); ++a_it) + { + irep_idt property_id = n_it->location->source_location.get_property_id(); + + if(n_it->location->guard.is_true()) + property_map[property_id].result=PASS; + else + _has_assertion=true; + } + if(!n_it->function_calls_inlined) + continue; + + for(local_SSAt::nodet::function_callst::const_iterator + f_it = n_it->function_calls.begin(); + f_it != n_it->function_calls.end(); ++f_it) + { + irep_idt fname = to_symbol_expr(f_it->function()).get_identifier(); + if(ssa_db.functions().find(fname)==ssa_db.functions().end()) + continue; + + bool new_has_assertion = has_assertion(fname); //recurse + _has_assertion = _has_assertion || new_has_assertion; + } + } + + return _has_assertion; +} diff --git a/src/summarizer/summary_checker_base.h b/src/summarizer/summary_checker_base.h index 024db61d0..bbcd9bd6b 100644 --- a/src/summarizer/summary_checker_base.h +++ b/src/summarizer/summary_checker_base.h @@ -89,6 +89,9 @@ class summary_checker_baset:public property_checkert void check_properties( const ssa_dbt::functionst::const_iterator f_it, irep_idt entry_function=""); + + bool has_assertion(irep_idt function_name); + }; #endif From a9babc3b154981cb348d9644357ad5e1d6395dc4 Mon Sep 17 00:00:00 2001 From: Peter Schrammel Date: Mon, 30 May 2016 23:36:29 +0100 Subject: [PATCH 63/82] recursively collect assertions from inlined functions through inliner --- src/ssa/ssa_inliner.cpp | 63 +++++++++++-- src/ssa/ssa_inliner.h | 116 ++++++++++++++---------- src/summarizer/summary_checker_base.cpp | 75 +++++---------- 3 files changed, 146 insertions(+), 108 deletions(-) diff --git a/src/ssa/ssa_inliner.cpp b/src/ssa/ssa_inliner.cpp index e7818d59a..ecec65331 100644 --- a/src/ssa/ssa_inliner.cpp +++ b/src/ssa/ssa_inliner.cpp @@ -112,6 +112,7 @@ bool ssa_inlinert::get_inlined( exprt::operandst &assert_summaries, exprt::operandst &noassert_summaries, exprt::operandst &bindings, + assertion_mapt &assertion_map, int counter, bool error_summ) { @@ -120,7 +121,8 @@ bool ssa_inlinert::get_inlined( bool assertion_flag = get_summaries(fSSA, summaryt::call_sitet(fSSA.goto_function.body.instructions.end()), - forward,assert_summaries,noassert_summaries,bindings,error_summ); + forward,assert_summaries,noassert_summaries, + bindings,assertion_map,error_summ); //bindings exprt guard_binding; @@ -288,15 +290,35 @@ exprt ssa_inlinert::get_summaries(const local_SSAt &SSA) return and_exprt(conjunction(bindings), conjunction(summaries)); } +exprt ssa_inlinert::get_summaries(const local_SSAt &SSA, + assertion_mapt &assertion_map) +{ + exprt::operandst summaries,bindings; + get_summaries(SSA,true,summaries,bindings,assertion_map); + return and_exprt(conjunction(bindings),conjunction(summaries)); +} + void ssa_inlinert::get_summaries( const local_SSAt &SSA, bool forward, exprt::operandst &summaries, exprt::operandst &bindings) { + assertion_mapt assertion_map; get_summaries(SSA, summaryt::call_sitet(SSA.goto_function.body.instructions.end()), - forward,summaries,summaries,bindings); + forward,summaries,summaries,bindings,assertion_map); +} + +void ssa_inlinert::get_summaries(const local_SSAt &SSA, + bool forward, + exprt::operandst &summaries, + exprt::operandst &bindings, + assertion_mapt &assertion_map) +{ + get_summaries(SSA, + summaryt::call_sitet(SSA.goto_function.body.instructions.end()), + forward,summaries,summaries,bindings,assertion_map); } /*******************************************************************\ @@ -318,11 +340,33 @@ bool ssa_inlinert::get_summaries( exprt::operandst &assert_summaries, exprt::operandst &noassert_summaries, exprt::operandst &bindings) +{ + assertion_mapt assertion_map; + return get_summaries(SSA, + summaryt::call_sitet(SSA.goto_function.body.instructions.end()), + forward,assert_summaries,noassert_summaries,bindings,assertion_map); +} + +bool ssa_inlinert::get_summaries(const local_SSAt &SSA, + const summaryt::call_sitet ¤t_call_site, + bool forward, + exprt::operandst &assert_summaries, + exprt::operandst &noassert_summaries, + exprt::operandst &bindings, + assertion_mapt &assertion_map, + bool error_summ) { bool assertion_flag = false; for(local_SSAt::nodest::const_iterator n_it=SSA.nodes.begin(); n_it!=SSA.nodes.end(); n_it++) { + for(local_SSAt::nodet::assertionst::const_iterator a_it = + n_it->assertions.begin(); + a_it != n_it->assertions.end(); a_it++) + { + assertion_map[n_it->location].push_back(*a_it); + rename(assertion_map[n_it->location].back(), counter); + } for(local_SSAt::nodet::function_callst::const_iterator f_it = n_it->function_calls.begin(); f_it!=n_it->function_calls.end(); f_it++) @@ -341,7 +385,7 @@ bool ssa_inlinert::get_summaries( bool new_assertion_flag = get_inlined(SSA,n_it,f_it, forward,assert_summaries,noassert_summaries, - bindings,counter,error_summ); + bindings,assertion_map,counter,error_summ); assertion_flag = assertion_flag || new_assertion_flag; } //get summary @@ -859,6 +903,8 @@ Function: ssa_inlinert::rename irep_idt ssa_inlinert::rename(irep_idt &id, int counter) { + if(counter<0) + return id; return id2string(id)+"@"+i2string(counter); } @@ -924,13 +970,10 @@ void ssa_inlinert::rename(exprt &expr, int counter) { if(expr.id()==ID_symbol || expr.id()==ID_nondet_symbol) { - std::string id_str = id2string(expr.get(ID_identifier)); - irep_idt id; - - if(id_str.find('@') != std::string::npos) - id = id_str; - else - id = id_str+"@"+i2string(counter); + irep_idt id = expr.get(ID_identifier); + std::string id_str = id2string(id); + if(id_str.find('@') == std::string::npos) + rename(id, counter); expr.set(ID_identifier,id); } diff --git a/src/ssa/ssa_inliner.h b/src/ssa/ssa_inliner.h index b7ddfcce6..672e28cda 100644 --- a/src/ssa/ssa_inliner.h +++ b/src/ssa/ssa_inliner.h @@ -19,55 +19,79 @@ Author: Peter Schrammel class ssa_inlinert:public messaget { -public: - explicit ssa_inlinert(summary_dbt &_summary_db): - counter(0), - summary_db(_summary_db) - { - } - - void get_guard_binding( - const local_SSAt &SSA, - const local_SSAt &fSSA, - local_SSAt::nodest::const_iterator n_it, - exprt &guard_binding, - int counter); - - void get_bindings( - const local_SSAt &SSA, - const local_SSAt &fSSA, - local_SSAt::nodest::const_iterator n_it, - local_SSAt::nodet::function_callst::const_iterator f_it, - exprt::operandst &bindings_in, - exprt::operandst &bindings_out, - int counter); - - void get_summary( - const local_SSAt &SSA, - local_SSAt::nodest::const_iterator n_it, - local_SSAt::nodet::function_callst::const_iterator f_it, - const summaryt &summary, - bool forward, - exprt::operandst &summaries, - exprt::operandst &bindings, - int counter, - bool error_summ=false); - + public: + explicit ssa_inlinert(summary_dbt &_summary_db, + ssa_dbt &_ssa_db) : + counter(-1), + summary_db(_summary_db), + ssa_db(_ssa_db) + {} + + typedef std::map assertion_mapt; + + void get_guard_binding(const local_SSAt &SSA, + const local_SSAt &fSSA, + local_SSAt::nodest::const_iterator n_it, + exprt &guard_binding, + int counter); + void get_bindings(const local_SSAt &SSA, + const local_SSAt &fSSA, + local_SSAt::nodest::const_iterator n_it, + local_SSAt::nodet::function_callst::const_iterator f_it, + exprt::operandst &bindings_in, + exprt::operandst &bindings_out, + int counter); + bool get_summary(const local_SSAt &SSA, + local_SSAt::nodest::const_iterator n_it, + local_SSAt::nodet::function_callst::const_iterator f_it, + bool forward, + exprt::operandst &assert_summaries, + exprt::operandst &noassert_summaries, + exprt::operandst &bindings, + int counter, + bool error_summ = false); + bool get_inlined(const local_SSAt &SSA, + local_SSAt::nodest::const_iterator n_it, + local_SSAt::nodet::function_callst::const_iterator f_it, + bool forward, + exprt::operandst &assert_summaries, + exprt::operandst &noassert_summaries, + exprt::operandst &bindings, + assertion_mapt &assertion_map, + int counter, + bool error_summ); void get_summaries( - const local_SSAt &SSA, - bool forward, - exprt::operandst &summaries, - exprt::operandst &bindings); //TODO: need to explicitly pass the correct counter - + const local_SSAt &SSA, + bool forward, + exprt::operandst &summaries, + exprt::operandst &bindings, + assertion_mapt &assertion_map); //TODO: need to explicitly pass the correct counter + void get_summaries( + const local_SSAt &SSA, + bool forward, + exprt::operandst &summaries, + exprt::operandst &bindings); //TODO: need to explicitly pass the correct counter bool get_summaries( - const local_SSAt &SSA, - const summaryt::call_sitet ¤t_call_site, - bool forward, - exprt::operandst &assert_summaries, - exprt::operandst &noassert_summaries, - exprt::operandst &bindings); //TODO: need to explicitly pass the correct counter + const local_SSAt &SSA, + const summaryt::call_sitet ¤t_call_site, + bool forward, + exprt::operandst &assert_summaries, + exprt::operandst &noassert_summaries, + exprt::operandst &bindings, + bool error_summ=false); //TODO: need to explicitly pass the correct counter + bool get_summaries( + const local_SSAt &SSA, + const summaryt::call_sitet ¤t_call_site, + bool forward, + exprt::operandst &assert_summaries, + exprt::operandst &noassert_summaries, + exprt::operandst &bindings, + assertion_mapt &assertion_map, + bool error_summ=false); //TODO: need to explicitly pass the correct counter exprt get_summaries(const local_SSAt &SSA); //TODO: need to explicitly pass the correct counter + exprt get_summaries(const local_SSAt &SSA, + assertion_mapt &assertion_map); //TODO: need to explicitly pass the correct counter void replace( local_SSAt &SSA, @@ -150,7 +174,7 @@ class ssa_inlinert:public messaget void rename(exprt &expr, int counter); protected: - unsigned counter; + int counter; summary_dbt &summary_db; ssa_dbt &ssa_db; diff --git a/src/summarizer/summary_checker_base.cpp b/src/summarizer/summary_checker_base.cpp index e2a8ad0f0..37a6d89ab 100644 --- a/src/summarizer/summary_checker_base.cpp +++ b/src/summarizer/summary_checker_base.cpp @@ -360,15 +360,9 @@ void summary_checker_baset::check_properties( solver << summary.fw_precondition; } - //callee summaries - solver << ssa_inliner.get_summaries(SSA); - -#if 0 - //freeze loop head selects - exprt::operandst loophead_selects; - summarizer_baset::get_loophead_selects(SSA, - ssa_unwinder.get(f_it->first),*solver.solver, loophead_selects); -#endif + //callee summaries and inlined functions + ssa_inlinert::assertion_mapt assertion_map; + solver << ssa_inliner.get_summaries(SSA, assertion_map); //spuriousness checkers summarizer_bw_cex_baset *summarizer_bw_cex = NULL; @@ -422,61 +416,38 @@ void summary_checker_baset::check_properties( all_properties, build_error_trace, *summarizer_bw_cex); -#if 0 - debug() << "(C) " << from_expr(SSA.ns,"",enabling_expr) << eom; -#endif - - const goto_programt &goto_program=SSA.goto_function.body; - - for(goto_programt::instructionst::const_iterator - i_it=goto_program.instructions.begin(); - i_it!=goto_program.instructions.end(); - i_it++) + for(ssa_inlinert::assertion_mapt::const_iterator + aa_it=assertion_map.begin(); + aa_it!=assertion_map.end(); + aa_it++) { - if(!i_it->is_assert()) - continue; - - const source_locationt &location=i_it->source_location; - std::list assertion_nodes; - SSA.find_nodes(i_it,assertion_nodes); - - irep_idt property_id = location.get_property_id(); - - if(i_it->guard.is_true()) - { - property_map[property_id].result=PASS; - continue; - } + irep_idt property_id = aa_it->first->source_location.get_property_id(); //do not recheck properties that have already been decided - if(property_map[property_id].result!=UNKNOWN) continue; + if(property_map[property_id].result!=UNKNOWN) + continue; +#if 0 if(property_id=="") //TODO: some properties do not show up in initialize_property_map continue; +#endif - unsigned property_counter = 0; - for(std::list::const_iterator - n_it=assertion_nodes.begin(); - n_it!=assertion_nodes.end(); - n_it++) + for(exprt::operandst::const_iterator + a_it=aa_it->second.begin(); + a_it!=aa_it->second.end(); + a_it++) { - for(local_SSAt::nodet::assertionst::const_iterator - a_it=(*n_it)->assertions.begin(); - a_it!=(*n_it)->assertions.end(); - a_it++, property_counter++) - { - exprt property=*a_it; + exprt property=*a_it; - if(simplify) - property=::simplify_expr(property, SSA.ns); + if(simplify) + property=::simplify_expr(property, SSA.ns); -#if 0 - std::cout << "property: " << from_expr(SSA.ns, "", property) << std::endl; +#if 1 + std::cout << "property: " << from_expr(SSA.ns, "", property) << std::endl; #endif - property_map[property_id].location = i_it; - cover_goals.goal_map[property_id].conjuncts.push_back(property); - } + property_map[property_id].location = aa_it->first; + cover_goals.goal_map[property_id].conjuncts.push_back(property); } } From 6fb2966b877310c2f444539896698b416cdf739c Mon Sep 17 00:00:00 2001 From: Peter Schrammel Date: Tue, 31 May 2016 00:19:40 +0100 Subject: [PATCH 64/82] sync --- src/summarizer/summary_checker_base.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/summarizer/summary_checker_base.cpp b/src/summarizer/summary_checker_base.cpp index 37a6d89ab..526338971 100644 --- a/src/summarizer/summary_checker_base.cpp +++ b/src/summarizer/summary_checker_base.cpp @@ -79,7 +79,7 @@ void summary_checker_baset::SSA_dependency_graphs( else ssa_db.depgraph_create(f_it->first, ns, ssa_inliner, false); // change to true if all functions are to be treated equal -#if 0 +#if 1 ssa_dependency_grapht &ssa_depgraph = ssa_db.get_depgraph(f_it->first); ssa_depgraph.output(debug()); debug() << eom; std::cout << "output SSA for function: " << f_it->first << "\n"; From 8fe63167488cd1baac3b0596d2560d565e4c5f40 Mon Sep 17 00:00:00 2001 From: Peter Schrammel Date: Tue, 31 May 2016 09:17:40 +0100 Subject: [PATCH 65/82] depgraph renaming problem fixed --- src/ssa/ssa_dependency_graph.cpp | 18 ++++---- src/ssa/ssa_inliner.cpp | 45 +++++-------------- src/ssa/ssa_inliner.h | 12 ++--- src/summarizer/summarizer_bw_cex_complete.cpp | 13 +++--- src/summarizer/summarizer_bw_cex_wp.cpp | 22 +++++---- 5 files changed, 39 insertions(+), 71 deletions(-) diff --git a/src/ssa/ssa_dependency_graph.cpp b/src/ssa/ssa_dependency_graph.cpp index 3a34a14e1..651563082 100644 --- a/src/ssa/ssa_dependency_graph.cpp +++ b/src/ssa/ssa_dependency_graph.cpp @@ -311,25 +311,25 @@ void ssa_dependency_grapht::create(const local_SSAt &SSA, ssa_inlinert &ssa_inli for(local_SSAt::var_listt::const_iterator p_it = fSSA.params.begin(); p_it != fSSA.params.end(); p_it++){ irep_idt id = (*p_it).get(ID_identifier); - irep_idt sym = ssa_inliner.rename(id, counter); - all_ssa_symbols.insert(sym); - temp_node.used_symbols.insert(sym); + ssa_inliner.rename(id, counter); + all_ssa_symbols.insert(id); + temp_node.used_symbols.insert(id); } for(local_SSAt::var_sett::const_iterator g_it = fSSA.globals_in.begin(); g_it != fSSA.globals_in.end(); g_it++){ irep_idt id = (*g_it).get(ID_identifier); - irep_idt sym = ssa_inliner.rename(id, counter); - all_ssa_symbols.insert(sym); - temp_node.used_symbols.insert(sym); + ssa_inliner.rename(id, counter); + all_ssa_symbols.insert(id); + temp_node.used_symbols.insert(id); } for(local_SSAt::var_sett::const_iterator g_it = fSSA.globals_out.begin(); g_it != fSSA.globals_out.end(); g_it++){ irep_idt id = (*g_it).get(ID_identifier); - irep_idt sym = ssa_inliner.rename(id, counter); - all_ssa_symbols.insert(sym); - temp_node.modified_symbols.insert(sym); + ssa_inliner.rename(id, counter); + all_ssa_symbols.insert(id); + temp_node.modified_symbols.insert(id); } depnodes_map.push_back(temp_node); diff --git a/src/ssa/ssa_inliner.cpp b/src/ssa/ssa_inliner.cpp index ecec65331..fadd31fdb 100644 --- a/src/ssa/ssa_inliner.cpp +++ b/src/ssa/ssa_inliner.cpp @@ -901,30 +901,12 @@ Function: ssa_inlinert::rename \*******************************************************************/ -irep_idt ssa_inlinert::rename(irep_idt &id, int counter) -{ - if(counter<0) - return id; - return id2string(id)+"@"+i2string(counter); -} - -/*******************************************************************\ - -Function: ssa_inlinert::rename - - Inputs: - - Outputs: - - Purpose: - -\*******************************************************************/ - -irep_idt ssa_inlinert::rename(irep_idt &id, int counter, bool attach){ +void ssa_inlinert::rename(irep_idt &id, int counter, bool attach){ std::string id_str = id2string(id); - if(attach == false){ + if(!attach) + { //find first @ where afterwards there are no letters size_t pos = std::string::npos; for(size_t i=0;i=0) + id = id_str+"@"+i2string(counter); } } @@ -966,21 +945,19 @@ Function: ssa_inlinert::rename \*******************************************************************/ -void ssa_inlinert::rename(exprt &expr, int counter) +void ssa_inlinert::rename(exprt &expr, int counter, bool attach) { if(expr.id()==ID_symbol || expr.id()==ID_nondet_symbol) { irep_idt id = expr.get(ID_identifier); - std::string id_str = id2string(id); - if(id_str.find('@') == std::string::npos) - rename(id, counter); + rename(id, counter, attach); expr.set(ID_identifier,id); } for(exprt::operandst::iterator it = expr.operands().begin(); it != expr.operands().end(); it++) { - rename(*it,counter); + rename(*it, counter, attach); } } diff --git a/src/ssa/ssa_inliner.h b/src/ssa/ssa_inliner.h index 672e28cda..0fe7581ab 100644 --- a/src/ssa/ssa_inliner.h +++ b/src/ssa/ssa_inliner.h @@ -160,18 +160,12 @@ class ssa_inlinert:public messaget static irep_idt get_original_identifier(const symbol_exprt &s); - irep_idt rename(irep_idt &id, int counter); + void rename(irep_idt &id, int counter, bool attach=true); - irep_idt rename(irep_idt &id, int counter, bool attach); - - int get_rename_counter() - { - counter++; - return counter; - } + int get_rename_counter() { return ++counter; } // moved from protected to public, for use in summarizer_bw_cex_complete - void rename(exprt &expr, int counter); + void rename(exprt &expr, int counter, bool attach=true); protected: int counter; diff --git a/src/summarizer/summarizer_bw_cex_complete.cpp b/src/summarizer/summarizer_bw_cex_complete.cpp index 8c2a7ef1e..bb03256bc 100644 --- a/src/summarizer/summarizer_bw_cex_complete.cpp +++ b/src/summarizer/summarizer_bw_cex_complete.cpp @@ -67,6 +67,7 @@ void summarizer_bw_cex_completet::summarize(const exprt &_error_assertion) { status() << "\nBackward error analysis (complete)..." << eom; error_assertion = _error_assertion; + ssa_inliner.rename(error_assertion,-1,false); /* std::cout << "error assertion: " << from_expr(ssa_db.get(entry_function).ns, "", error_assertion) @@ -228,10 +229,9 @@ find_symbols_sett summarizer_bw_cex_completet::inline_summaries for(find_symbols_sett::iterator d_it = worknode.dependency_set.begin(); d_it != worknode.dependency_set.end(); d_it++){ - irep_idt id = *d_it; + irep_idt renamed_id = *d_it; // detach the '@' symbol if there - irep_idt renamed_id = ssa_inliner.rename - (id, + ssa_inliner.rename(renamed_id, depnode.rename_counter, false); renamed_dependencies.insert(renamed_id); } @@ -276,10 +276,9 @@ find_symbols_sett summarizer_bw_cex_completet::inline_summaries for(find_symbols_sett::iterator d_it = worknode.dependency_set.begin(); d_it != worknode.dependency_set.end(); d_it++){ - irep_idt id = *d_it; + irep_idt renamed_id = *d_it; // attach the '@' symbol if not already there - irep_idt renamed_id = ssa_inliner.rename - (id, + ssa_inliner.rename(renamed_id, depnode.rename_counter, true); renamed_dependencies.insert(renamed_id); } @@ -305,7 +304,7 @@ find_symbols_sett summarizer_bw_cex_completet::inline_summaries bool is_error_assertion = false; if(depnode.is_assertion) { -#if 0 +#if 1 std::cout << "assertion: " << from_expr(SSA.ns, "", error_assertion) << std::endl; std::cout << "to check: " << from_expr(SSA.ns, "", worknode_info) << std::endl; #endif diff --git a/src/summarizer/summarizer_bw_cex_wp.cpp b/src/summarizer/summarizer_bw_cex_wp.cpp index 97d0010cd..86b0b6e54 100644 --- a/src/summarizer/summarizer_bw_cex_wp.cpp +++ b/src/summarizer/summarizer_bw_cex_wp.cpp @@ -225,12 +225,11 @@ find_symbols_sett summarizer_bw_cex_wpt::inline_summaries for(find_symbols_sett::iterator d_it = worknode.dependency_set.begin(); d_it != worknode.dependency_set.end(); d_it++){ - irep_idt id = *d_it; - // detach the '@' symbol if there - irep_idt renamed_id = ssa_inliner.rename - (id, - ssa_depgraph.depnodes_map[worknode.node_index].rename_counter, false); - renamed_dependencies.insert(renamed_id); + irep_idt renamed_id = *d_it; + // detach the '@' symbol if there + ssa_inliner.rename(renamed_id, + ssa_depgraph.depnodes_map[worknode.node_index].rename_counter, false); + renamed_dependencies.insert(renamed_id); } worknode.dependency_set = renamed_dependencies; @@ -267,12 +266,11 @@ find_symbols_sett summarizer_bw_cex_wpt::inline_summaries for(find_symbols_sett::iterator d_it = worknode.dependency_set.begin(); d_it != worknode.dependency_set.end(); d_it++){ - irep_idt id = *d_it; - // attach the '@' symbol if not already there - irep_idt renamed_id = ssa_inliner.rename - (id, - ssa_depgraph.depnodes_map[worknode.node_index].rename_counter, true); - renamed_dependencies.insert(renamed_id); + irep_idt renamed_id = *d_it; + // detach the '@' symbol if there + ssa_inliner.rename(renamed_id, + ssa_depgraph.depnodes_map[worknode.node_index].rename_counter, false); + renamed_dependencies.insert(renamed_id); } worknode.dependency_set = renamed_dependencies; From 83809366cfc394dc652cd5b299fe2e2fe307050b Mon Sep 17 00:00:00 2001 From: Peter Schrammel Date: Tue, 31 May 2016 10:45:19 +0100 Subject: [PATCH 66/82] inlined functions must not contain negated assertions; assertions are added separately --- src/domains/incremental_solver.cpp | 42 ++++++++++++------- src/domains/incremental_solver.h | 3 +- src/ssa/ssa_inliner.cpp | 2 + src/summarizer/summarizer_bw_cex_complete.cpp | 2 +- src/summarizer/summary_checker_base.cpp | 4 +- 5 files changed, 34 insertions(+), 19 deletions(-) diff --git a/src/domains/incremental_solver.cpp b/src/domains/incremental_solver.cpp index c4ac59d7d..044f48a40 100644 --- a/src/domains/incremental_solver.cpp +++ b/src/domains/incremental_solver.cpp @@ -152,31 +152,45 @@ Function: incremental_solvert::debug_add_to_formula void incremental_solvert::debug_add_to_formula(const exprt &expr) { + if(_expr.id()!=ID_and) + { #ifdef NON_INCREMENTAL - // no debug mode for non-incremental yet + // no debug mode for non-incremental yet + assert(0); #else - literalt l=solver->convert(expr); - if(l.is_false()) - { + exprt expr; + if(activation.is_nil()) + expr=_expr; + else + expr=or_exprt(_expr, activation); + literalt l = solver->convert(expr); + if(l.is_false()) + { #ifdef DEBUG_OUTPUT - debug() << "literal " << l << ": false=" << from_expr(ns, "", expr) <convert(symbol_exprt("goto_symex::\\dummy", bool_typet())); formula.push_back(dummy); formula.push_back(!dummy); #ifdef DEBUG_OUTPUT - debug() << "literal " << dummy << ", " << !dummy << ": " - << from_expr(ns, "", expr) << eom; + debug() << "literal " << dummy << ", " << !dummy << ": " + << from_expr(ns, "", expr) << eom; #endif - } - else if(!l.is_true()) - { + } + else if(!l.is_true()) + { #ifdef DEBUG_OUTPUT - debug() << "literal " << l << ": " << from_expr(ns, "", expr) << eom; + debug() << "literal " << l << ": " << from_expr(ns,"",expr) << eom; #endif - formula.push_back(l); - formula_expr.push_back(expr); - } + formula.push_back(l); + formula_expr.push_back(expr); + } #endif + } + else + { + forall_operands(it, _expr) + debug_add_to_formula(*it, activation); + } } diff --git a/src/domains/incremental_solver.h b/src/domains/incremental_solver.h index c5f16cfc6..ca4369be2 100644 --- a/src/domains/incremental_solver.h +++ b/src/domains/incremental_solver.h @@ -20,7 +20,6 @@ Author: Peter Schrammel #include "domain.h" #include "util.h" -// #define DISPLAY_FORMULA // #define NO_ARITH_REFINEMENT // #define NON_INCREMENTAL // (experimental) @@ -157,7 +156,7 @@ class incremental_solvert:public messaget // for debugging bvt formula; exprt::operandst formula_expr; - void debug_add_to_formula(const exprt &expr); + void debug_add_to_formula(const exprt &expr, exprt activation=nil_exprt()); // context assumption literals bvt activation_literals; diff --git a/src/ssa/ssa_inliner.cpp b/src/ssa/ssa_inliner.cpp index fadd31fdb..1fa429cd5 100644 --- a/src/ssa/ssa_inliner.cpp +++ b/src/ssa/ssa_inliner.cpp @@ -164,8 +164,10 @@ bool ssa_inlinert::get_inlined( for(local_SSAt::nodet::assertionst::const_iterator a_it = fnode.assertions.begin(); a_it!=fnode.assertions.end(); a_it++) { +#if 0 assert_summaries.push_back(*a_it); rename(assert_summaries.back(), counter); +#endif assertion_flag = true; } } diff --git a/src/summarizer/summarizer_bw_cex_complete.cpp b/src/summarizer/summarizer_bw_cex_complete.cpp index bb03256bc..9ba0d6ecb 100644 --- a/src/summarizer/summarizer_bw_cex_complete.cpp +++ b/src/summarizer/summarizer_bw_cex_complete.cpp @@ -304,7 +304,7 @@ find_symbols_sett summarizer_bw_cex_completet::inline_summaries bool is_error_assertion = false; if(depnode.is_assertion) { -#if 1 +#if 0 std::cout << "assertion: " << from_expr(SSA.ns, "", error_assertion) << std::endl; std::cout << "to check: " << from_expr(SSA.ns, "", worknode_info) << std::endl; #endif diff --git a/src/summarizer/summary_checker_base.cpp b/src/summarizer/summary_checker_base.cpp index 526338971..0879ea8bf 100644 --- a/src/summarizer/summary_checker_base.cpp +++ b/src/summarizer/summary_checker_base.cpp @@ -79,7 +79,7 @@ void summary_checker_baset::SSA_dependency_graphs( else ssa_db.depgraph_create(f_it->first, ns, ssa_inliner, false); // change to true if all functions are to be treated equal -#if 1 +#if 0 ssa_dependency_grapht &ssa_depgraph = ssa_db.get_depgraph(f_it->first); ssa_depgraph.output(debug()); debug() << eom; std::cout << "output SSA for function: " << f_it->first << "\n"; @@ -443,7 +443,7 @@ void summary_checker_baset::check_properties( property=::simplify_expr(property, SSA.ns); #if 1 - std::cout << "property: " << from_expr(SSA.ns, "", property) << std::endl; + debug() << "property: " << from_expr(SSA.ns, "", property) << eom; #endif property_map[property_id].location = aa_it->first; From 6b19c3082429e4d2094ec5b796c7b3534209fbc9 Mon Sep 17 00:00:00 2001 From: Peter Schrammel Date: Tue, 31 May 2016 12:43:37 +0100 Subject: [PATCH 67/82] regression tests refactored --- regression/kiki-modular/Makefile | 20 ++ .../cex-struct1/main.c | 0 regression/kiki-modular/cex-struct1/test.desc | 6 + .../cex-struct2/main.c | 0 regression/kiki-modular/cex-struct2/test.desc | 6 + .../cex-struct3/main.c | 0 regression/kiki-modular/cex-struct3/test.desc | 6 + .../{modular => kiki-modular}/cex1/main.c | 0 regression/kiki-modular/cex1/test.desc | 6 + .../{modular => kiki-modular}/cex10/main.c | 0 regression/kiki-modular/cex10/test.desc | 6 + .../{modular => kiki-modular}/cex13/main.c | 0 regression/kiki-modular/cex13/test.desc | 6 + .../{modular => kiki-modular}/cex2/main.c | 0 regression/kiki-modular/cex2/test.desc | 6 + .../{modular => kiki-modular}/cex3/main.c | 0 regression/kiki-modular/cex3/test.desc | 6 + .../{modular => kiki-modular}/cex4/main.c | 0 regression/kiki-modular/cex4/test.desc | 6 + .../{modular => kiki-modular}/cex5/main.c | 0 regression/kiki-modular/cex5/test.desc | 6 + .../{modular => kiki-modular}/cex6/main.c | 0 regression/kiki-modular/cex6/test.desc | 6 + .../{modular => kiki-modular}/cex7/main.c | 0 regression/kiki-modular/cex7/test.desc | 6 + .../{modular => kiki-modular}/cex8/main.c | 0 regression/kiki-modular/cex8/test.desc | 6 + .../{modular => kiki-modular}/cex9/main.c | 0 regression/kiki-modular/cex9/test.desc | 6 + .../induction1/main.c | 0 .../induction1}/test.desc | 2 +- .../induction2/main.c | 0 regression/kiki-modular/induction2/test.desc | 6 + .../induction3/main.c | 0 regression/kiki-modular/induction3/test.desc | 6 + .../induction4/main.c | 0 .../induction4}/test.desc | 2 +- .../induction5/main.c | 0 .../induction5/test.desc | 2 +- .../induction7/main.c | 0 .../induction7/test.desc | 2 +- .../induction8/main.c | 0 regression/kiki-modular/induction8/test.desc | 6 + regression/kiki-modular/inline-refine1/main.c | 17 ++ .../kiki-modular/inline-refine1/test.desc | 6 + .../inline-refine2}/main.c | 0 .../kiki-modular/inline-refine2/test.desc | 6 + .../inline-refine3}/main.c | 0 .../kiki-modular/inline-refine3/test.desc | 6 + .../inline-refine4}/main.c | 0 .../kiki-modular/inline-refine4/test.desc | 6 + .../inline-refine5}/main.c | 0 .../kiki-modular/inline-refine5/test.desc | 6 + .../inline-refine6}/main.c | 0 .../kiki-modular/inline-refine6/test.desc | 6 + .../inline-refine7}/main.c | 0 .../kiki-modular/inline-refine7/test.desc | 6 + .../inline-refine8}/main.c | 0 .../kiki-modular/inline-refine8/test.desc | 6 + regression/kiki-modular/inline-refine9/main.c | 11 ++ .../kiki-modular/inline-refine9/test.desc | 6 + .../{modular => kiki-modular}/kind1/main.c | 0 regression/kiki-modular/kind1/test.desc | 6 + .../{modular => kiki-modular}/kind2/main.c | 0 regression/kiki-modular/kind2/test.desc | 6 + .../{modular => kiki-modular}/kind3/main.c | 0 regression/kiki-modular/kind3/test.desc | 6 + .../{modular => kiki-modular}/kind4/main.c | 0 regression/kiki-modular/kind4/test.desc | 6 + .../{modular => kiki-modular}/kind5/main.c | 0 regression/kiki-modular/kind5/test.desc | 6 + .../{modular => kiki-modular}/kind6/main.c | 0 regression/kiki-modular/kind6/test.desc | 6 + .../cex11 => kiki-modular/kind7}/main.c | 0 regression/kiki-modular/kind7/test.desc | 6 + .../cex12 => kiki-modular/kind8}/main.c | 0 regression/kiki-modular/kind8/test.desc | 6 + .../{modular => kiki-modular}/loop25/main.c | 0 regression/kiki-modular/loop25/test.desc | 6 + .../{modular => kiki-modular}/loop27/main.c | 0 regression/kiki-modular/loop27/test.desc | 6 + .../{modular => kiki-modular}/loop28/main.c | 0 regression/kiki-modular/loop28/test.desc | 6 + .../{modular => kiki-modular}/nested11/main.c | 0 regression/kiki-modular/nested11/test.desc | 6 + .../{modular => kiki-modular}/nested12/main.c | 0 .../nested12/test.desc | 2 +- regression/kiki-modular/nocex1/main.c | 15 ++ regression/kiki-modular/nocex1/test.desc | 6 + regression/kiki-modular/nocex2/main.c | 16 ++ regression/kiki-modular/nocex2/test.desc | 6 + regression/kiki-modular/nocex3/main.c | 18 ++ regression/kiki-modular/nocex3/test.desc | 6 + regression/kiki-modular/nocex4/main.c | 20 ++ regression/kiki-modular/nocex4/test.desc | 6 + regression/kiki-modular/nocex5/main.c | 30 +++ regression/kiki-modular/nocex5/test.desc | 6 + regression/kiki-modular/nocex6/main.c | 15 ++ regression/kiki-modular/nocex6/test.desc | 6 + regression/kiki-modular/nocex8/main.c | 16 ++ regression/kiki-modular/nocex8/test.desc | 6 + regression/kiki-modular/nocex9/main.c | 11 ++ regression/kiki-modular/nocex9/test.desc | 6 + .../s3_clnt_1/main.c | 0 regression/kiki-modular/s3_clnt_1/test.desc | 6 + .../{modular => kiki-modular}/scope1/main.c | 0 regression/kiki-modular/scope1/test.desc | 6 + regression/kiki-modular/unwind-refine1/main.c | 15 ++ .../kiki-modular/unwind-refine1/test.desc | 6 + regression/modular/kind1/test.desc | 6 - regression/modular/kind2/test.desc | 6 - regression/modular/kind3/test.desc | 6 - regression/modular/kind4/test.desc | 6 - regression/modular/kind5/test.desc | 6 - regression/modular/kind6/test.desc | 6 - regression/modular/loop25/test.desc | 6 - regression/modular/loop28/test.desc | 6 - regression/modular/nested11/test.desc | 6 - regression/modular/s3_clnt_1/test.desc | 6 - regression/modular/scope1/test.desc | 6 - regression/spurious-check-abstract/Makefile | 20 ++ .../cex-struct1/main.c | 180 ++++++++++++++++++ .../cex-struct1/test.desc | 0 .../cex-struct2/main.c | 22 +++ .../cex-struct2/test.desc | 0 .../cex-struct3/main.c | 23 +++ .../cex-struct3/test.desc | 0 .../spurious-check-abstract/cex1/main.c | 15 ++ .../cex1/test.desc | 0 .../spurious-check-abstract/cex10/main.c | 21 ++ .../cex10/test.desc | 0 .../spurious-check-abstract/cex13/main.c | 16 ++ .../cex13/test.desc | 0 .../cex2/main.c} | 0 .../cex2/test.desc | 0 .../spurious-check-abstract/cex3/main.c | 16 ++ .../cex3/test.desc | 0 .../spurious-check-abstract/cex4/main.c | 11 ++ .../cex4/test.desc | 0 .../spurious-check-abstract/cex5/main.c | 15 ++ .../cex5/test.desc | 0 .../spurious-check-abstract/cex6/main.c | 20 ++ .../cex6/test.desc | 0 .../spurious-check-abstract/cex7/main.c | 15 ++ .../cex7/test.desc | 0 .../spurious-check-abstract/cex8/main.c | 20 ++ .../cex8/test.desc | 0 .../spurious-check-abstract/cex9/main.c | 24 +++ .../cex9/test.desc | 0 .../spurious-check-abstract/nocex1/main.c | 15 ++ .../nocex1/test.desc | 0 .../spurious-check-abstract/nocex10/main.c | 11 ++ .../spurious-check-abstract/nocex10/test.desc | 6 + .../spurious-check-abstract/nocex2/main.c | 16 ++ .../nocex2/test.desc | 0 .../spurious-check-abstract/nocex3/main.c | 18 ++ .../nocex3/test.desc | 0 .../spurious-check-abstract/nocex4/main.c | 20 ++ .../nocex4/test.desc | 0 .../spurious-check-abstract/nocex5/main.c | 30 +++ .../nocex5/test.desc | 0 .../spurious-check-abstract/nocex6/main.c | 15 ++ .../nocex6/test.desc | 0 .../spurious-check-abstract/nocex8/main.c | 16 ++ .../nocex8/test.desc | 0 .../spurious-check-abstract/nocex9/main.c | 11 ++ .../spurious-check-abstract/nocex9/test.desc | 6 + .../Makefile | 0 .../cex-struct1/main.c | 180 ++++++++++++++++++ .../cex-struct1/test.desc | 6 + .../cex-struct2/main.c | 22 +++ .../cex-struct2/test.desc | 6 + .../cex-struct3/main.c | 23 +++ .../cex-struct3/test.desc | 6 + .../spurious-check-complete/cex1/main.c | 15 ++ .../spurious-check-complete/cex1/test.desc | 6 + .../spurious-check-complete/cex10/main.c | 21 ++ .../spurious-check-complete/cex10/test.desc | 6 + .../spurious-check-complete/cex13/main.c | 16 ++ .../spurious-check-complete/cex13/test.desc | 6 + .../spurious-check-complete/cex2/main.c | 16 ++ .../spurious-check-complete/cex2/test.desc | 6 + .../spurious-check-complete/cex3/main.c | 16 ++ .../spurious-check-complete/cex3/test.desc | 6 + .../spurious-check-complete/cex4/main.c | 11 ++ .../spurious-check-complete/cex4/test.desc | 6 + .../spurious-check-complete/cex5/main.c | 15 ++ .../spurious-check-complete/cex5/test.desc | 6 + .../spurious-check-complete/cex6/main.c | 20 ++ .../spurious-check-complete/cex6/test.desc | 6 + .../spurious-check-complete/cex7/main.c | 15 ++ .../spurious-check-complete/cex7/test.desc | 6 + .../spurious-check-complete/cex8/main.c | 20 ++ .../spurious-check-complete/cex8/test.desc | 6 + .../spurious-check-complete/cex9/main.c | 24 +++ .../spurious-check-complete/cex9/test.desc | 6 + .../spurious-check-complete/nocex1/main.c | 15 ++ .../nocex1}/test.desc | 2 +- .../spurious-check-complete/nocex10/main.c | 11 ++ .../spurious-check-complete/nocex10/test.desc | 6 + .../spurious-check-complete/nocex2/main.c | 16 ++ .../nocex2}/test.desc | 2 +- .../spurious-check-complete/nocex3/main.c | 18 ++ .../nocex3}/test.desc | 2 +- .../spurious-check-complete/nocex4/main.c | 20 ++ .../nocex4}/test.desc | 2 +- .../spurious-check-complete/nocex5/main.c | 30 +++ .../spurious-check-complete/nocex5/test.desc | 6 + .../spurious-check-complete/nocex6/main.c | 15 ++ .../spurious-check-complete/nocex6/test.desc | 6 + .../spurious-check-complete/nocex8/main.c | 16 ++ .../spurious-check-complete/nocex8/test.desc | 6 + .../spurious-check-complete/nocex9/main.c | 11 ++ .../spurious-check-complete/nocex9/test.desc | 6 + regression/spurious-check-concrete/Makefile | 20 ++ .../cex-struct1/main.c | 180 ++++++++++++++++++ .../cex-struct1/test.desc | 6 + .../cex-struct2/main.c | 22 +++ .../cex-struct2/test.desc | 6 + .../cex-struct3/main.c | 23 +++ .../cex-struct3/test.desc | 6 + .../spurious-check-concrete/cex1/main.c | 15 ++ .../spurious-check-concrete/cex1/test.desc | 6 + .../spurious-check-concrete/cex10/main.c | 21 ++ .../spurious-check-concrete/cex10/test.desc | 6 + .../spurious-check-concrete/cex13/main.c | 16 ++ .../spurious-check-concrete/cex13/test.desc | 6 + .../spurious-check-concrete/cex2/main.c | 16 ++ .../spurious-check-concrete/cex2/test.desc | 6 + .../spurious-check-concrete/cex3/main.c | 16 ++ .../spurious-check-concrete/cex3/test.desc | 6 + .../spurious-check-concrete/cex4/main.c | 11 ++ .../spurious-check-concrete/cex4/test.desc | 6 + .../spurious-check-concrete/cex5/main.c | 15 ++ .../spurious-check-concrete/cex5/test.desc | 6 + .../spurious-check-concrete/cex6/main.c | 20 ++ .../spurious-check-concrete/cex6/test.desc | 6 + .../spurious-check-concrete/cex7/main.c | 15 ++ .../spurious-check-concrete/cex7/test.desc | 6 + .../spurious-check-concrete/cex8/main.c | 20 ++ .../spurious-check-concrete/cex8/test.desc | 6 + .../spurious-check-concrete/cex9/main.c | 24 +++ .../spurious-check-concrete/cex9/test.desc | 6 + .../spurious-check-concrete/nocex1/main.c | 15 ++ .../spurious-check-concrete/nocex1/test.desc | 6 + .../spurious-check-concrete/nocex10/main.c | 11 ++ .../spurious-check-concrete/nocex10/test.desc | 6 + .../spurious-check-concrete/nocex2/main.c | 16 ++ .../spurious-check-concrete/nocex2/test.desc | 6 + .../spurious-check-concrete/nocex3/main.c | 18 ++ .../spurious-check-concrete/nocex3/test.desc | 6 + .../spurious-check-concrete/nocex4/main.c | 20 ++ .../spurious-check-concrete/nocex4/test.desc | 6 + .../spurious-check-concrete/nocex5/main.c | 30 +++ .../spurious-check-concrete/nocex5/test.desc | 6 + .../spurious-check-concrete/nocex6/main.c | 15 ++ .../spurious-check-concrete/nocex6/test.desc | 6 + .../spurious-check-concrete/nocex8/main.c | 16 ++ .../spurious-check-concrete/nocex8/test.desc | 6 + .../spurious-check-concrete/nocex9/main.c | 11 ++ .../spurious-check-concrete/nocex9/test.desc | 6 + src/summarizer/summary_checker_kind.cpp | 1 + 262 files changed, 2494 insertions(+), 75 deletions(-) create mode 100644 regression/kiki-modular/Makefile rename regression/{modular => kiki-modular}/cex-struct1/main.c (100%) create mode 100644 regression/kiki-modular/cex-struct1/test.desc rename regression/{modular => kiki-modular}/cex-struct2/main.c (100%) create mode 100644 regression/kiki-modular/cex-struct2/test.desc rename regression/{modular => kiki-modular}/cex-struct3/main.c (100%) create mode 100644 regression/kiki-modular/cex-struct3/test.desc rename regression/{modular => kiki-modular}/cex1/main.c (100%) create mode 100644 regression/kiki-modular/cex1/test.desc rename regression/{modular => kiki-modular}/cex10/main.c (100%) create mode 100644 regression/kiki-modular/cex10/test.desc rename regression/{modular => kiki-modular}/cex13/main.c (100%) create mode 100644 regression/kiki-modular/cex13/test.desc rename regression/{modular => kiki-modular}/cex2/main.c (100%) create mode 100644 regression/kiki-modular/cex2/test.desc rename regression/{modular => kiki-modular}/cex3/main.c (100%) create mode 100644 regression/kiki-modular/cex3/test.desc rename regression/{modular => kiki-modular}/cex4/main.c (100%) create mode 100644 regression/kiki-modular/cex4/test.desc rename regression/{modular => kiki-modular}/cex5/main.c (100%) create mode 100644 regression/kiki-modular/cex5/test.desc rename regression/{modular => kiki-modular}/cex6/main.c (100%) create mode 100644 regression/kiki-modular/cex6/test.desc rename regression/{modular => kiki-modular}/cex7/main.c (100%) create mode 100644 regression/kiki-modular/cex7/test.desc rename regression/{modular => kiki-modular}/cex8/main.c (100%) create mode 100644 regression/kiki-modular/cex8/test.desc rename regression/{modular => kiki-modular}/cex9/main.c (100%) create mode 100644 regression/kiki-modular/cex9/test.desc rename regression/{modular => kiki-modular}/induction1/main.c (100%) rename regression/{modular/induction2 => kiki-modular/induction1}/test.desc (59%) rename regression/{modular => kiki-modular}/induction2/main.c (100%) create mode 100644 regression/kiki-modular/induction2/test.desc rename regression/{modular => kiki-modular}/induction3/main.c (100%) create mode 100644 regression/kiki-modular/induction3/test.desc rename regression/{modular => kiki-modular}/induction4/main.c (100%) rename regression/{modular/induction3 => kiki-modular/induction4}/test.desc (59%) rename regression/{modular => kiki-modular}/induction5/main.c (100%) rename regression/{modular => kiki-modular}/induction5/test.desc (52%) rename regression/{modular => kiki-modular}/induction7/main.c (100%) rename regression/{modular => kiki-modular}/induction7/test.desc (52%) rename regression/{modular => kiki-modular}/induction8/main.c (100%) create mode 100644 regression/kiki-modular/induction8/test.desc create mode 100644 regression/kiki-modular/inline-refine1/main.c create mode 100644 regression/kiki-modular/inline-refine1/test.desc rename regression/{modular/nocex2 => kiki-modular/inline-refine2}/main.c (100%) create mode 100644 regression/kiki-modular/inline-refine2/test.desc rename regression/{modular/nocex3 => kiki-modular/inline-refine3}/main.c (100%) create mode 100644 regression/kiki-modular/inline-refine3/test.desc rename regression/{modular/nocex4 => kiki-modular/inline-refine4}/main.c (100%) create mode 100644 regression/kiki-modular/inline-refine4/test.desc rename regression/{modular/nocex5 => kiki-modular/inline-refine5}/main.c (100%) create mode 100644 regression/kiki-modular/inline-refine5/test.desc rename regression/{modular/nocex6 => kiki-modular/inline-refine6}/main.c (100%) create mode 100644 regression/kiki-modular/inline-refine6/test.desc rename regression/{modular/nocex1 => kiki-modular/inline-refine7}/main.c (100%) create mode 100644 regression/kiki-modular/inline-refine7/test.desc rename regression/{modular/nocex8 => kiki-modular/inline-refine8}/main.c (100%) create mode 100644 regression/kiki-modular/inline-refine8/test.desc create mode 100644 regression/kiki-modular/inline-refine9/main.c create mode 100644 regression/kiki-modular/inline-refine9/test.desc rename regression/{modular => kiki-modular}/kind1/main.c (100%) create mode 100644 regression/kiki-modular/kind1/test.desc rename regression/{modular => kiki-modular}/kind2/main.c (100%) create mode 100644 regression/kiki-modular/kind2/test.desc rename regression/{modular => kiki-modular}/kind3/main.c (100%) create mode 100644 regression/kiki-modular/kind3/test.desc rename regression/{modular => kiki-modular}/kind4/main.c (100%) create mode 100644 regression/kiki-modular/kind4/test.desc rename regression/{modular => kiki-modular}/kind5/main.c (100%) create mode 100644 regression/kiki-modular/kind5/test.desc rename regression/{modular => kiki-modular}/kind6/main.c (100%) create mode 100644 regression/kiki-modular/kind6/test.desc rename regression/{modular/cex11 => kiki-modular/kind7}/main.c (100%) create mode 100644 regression/kiki-modular/kind7/test.desc rename regression/{modular/cex12 => kiki-modular/kind8}/main.c (100%) create mode 100644 regression/kiki-modular/kind8/test.desc rename regression/{modular => kiki-modular}/loop25/main.c (100%) create mode 100644 regression/kiki-modular/loop25/test.desc rename regression/{modular => kiki-modular}/loop27/main.c (100%) create mode 100644 regression/kiki-modular/loop27/test.desc rename regression/{modular => kiki-modular}/loop28/main.c (100%) create mode 100644 regression/kiki-modular/loop28/test.desc rename regression/{modular => kiki-modular}/nested11/main.c (100%) create mode 100644 regression/kiki-modular/nested11/test.desc rename regression/{modular => kiki-modular}/nested12/main.c (100%) rename regression/{modular => kiki-modular}/nested12/test.desc (52%) create mode 100644 regression/kiki-modular/nocex1/main.c create mode 100644 regression/kiki-modular/nocex1/test.desc create mode 100644 regression/kiki-modular/nocex2/main.c create mode 100644 regression/kiki-modular/nocex2/test.desc create mode 100644 regression/kiki-modular/nocex3/main.c create mode 100644 regression/kiki-modular/nocex3/test.desc create mode 100644 regression/kiki-modular/nocex4/main.c create mode 100644 regression/kiki-modular/nocex4/test.desc create mode 100644 regression/kiki-modular/nocex5/main.c create mode 100644 regression/kiki-modular/nocex5/test.desc create mode 100644 regression/kiki-modular/nocex6/main.c create mode 100644 regression/kiki-modular/nocex6/test.desc create mode 100644 regression/kiki-modular/nocex8/main.c create mode 100644 regression/kiki-modular/nocex8/test.desc create mode 100644 regression/kiki-modular/nocex9/main.c create mode 100644 regression/kiki-modular/nocex9/test.desc rename regression/{modular => kiki-modular}/s3_clnt_1/main.c (100%) create mode 100644 regression/kiki-modular/s3_clnt_1/test.desc rename regression/{modular => kiki-modular}/scope1/main.c (100%) create mode 100644 regression/kiki-modular/scope1/test.desc create mode 100644 regression/kiki-modular/unwind-refine1/main.c create mode 100644 regression/kiki-modular/unwind-refine1/test.desc delete mode 100644 regression/modular/kind1/test.desc delete mode 100644 regression/modular/kind2/test.desc delete mode 100644 regression/modular/kind3/test.desc delete mode 100644 regression/modular/kind4/test.desc delete mode 100644 regression/modular/kind5/test.desc delete mode 100644 regression/modular/kind6/test.desc delete mode 100644 regression/modular/loop25/test.desc delete mode 100644 regression/modular/loop28/test.desc delete mode 100644 regression/modular/nested11/test.desc delete mode 100644 regression/modular/s3_clnt_1/test.desc delete mode 100644 regression/modular/scope1/test.desc create mode 100644 regression/spurious-check-abstract/Makefile create mode 100644 regression/spurious-check-abstract/cex-struct1/main.c rename regression/{modular => spurious-check-abstract}/cex-struct1/test.desc (100%) create mode 100644 regression/spurious-check-abstract/cex-struct2/main.c rename regression/{modular => spurious-check-abstract}/cex-struct2/test.desc (100%) create mode 100644 regression/spurious-check-abstract/cex-struct3/main.c rename regression/{modular => spurious-check-abstract}/cex-struct3/test.desc (100%) create mode 100644 regression/spurious-check-abstract/cex1/main.c rename regression/{modular => spurious-check-abstract}/cex1/test.desc (100%) create mode 100644 regression/spurious-check-abstract/cex10/main.c rename regression/{modular => spurious-check-abstract}/cex10/test.desc (100%) create mode 100644 regression/spurious-check-abstract/cex13/main.c rename regression/{modular => spurious-check-abstract}/cex13/test.desc (100%) rename regression/{modular/cex13/main.c~ => spurious-check-abstract/cex2/main.c} (100%) rename regression/{modular => spurious-check-abstract}/cex2/test.desc (100%) create mode 100644 regression/spurious-check-abstract/cex3/main.c rename regression/{modular => spurious-check-abstract}/cex3/test.desc (100%) create mode 100644 regression/spurious-check-abstract/cex4/main.c rename regression/{modular => spurious-check-abstract}/cex4/test.desc (100%) create mode 100644 regression/spurious-check-abstract/cex5/main.c rename regression/{modular => spurious-check-abstract}/cex5/test.desc (100%) create mode 100644 regression/spurious-check-abstract/cex6/main.c rename regression/{modular => spurious-check-abstract}/cex6/test.desc (100%) create mode 100644 regression/spurious-check-abstract/cex7/main.c rename regression/{modular => spurious-check-abstract}/cex7/test.desc (100%) create mode 100644 regression/spurious-check-abstract/cex8/main.c rename regression/{modular => spurious-check-abstract}/cex8/test.desc (100%) create mode 100644 regression/spurious-check-abstract/cex9/main.c rename regression/{modular => spurious-check-abstract}/cex9/test.desc (100%) create mode 100644 regression/spurious-check-abstract/nocex1/main.c rename regression/{modular => spurious-check-abstract}/nocex1/test.desc (100%) create mode 100644 regression/spurious-check-abstract/nocex10/main.c create mode 100644 regression/spurious-check-abstract/nocex10/test.desc create mode 100644 regression/spurious-check-abstract/nocex2/main.c rename regression/{modular => spurious-check-abstract}/nocex2/test.desc (100%) create mode 100644 regression/spurious-check-abstract/nocex3/main.c rename regression/{modular => spurious-check-abstract}/nocex3/test.desc (100%) create mode 100644 regression/spurious-check-abstract/nocex4/main.c rename regression/{modular => spurious-check-abstract}/nocex4/test.desc (100%) create mode 100644 regression/spurious-check-abstract/nocex5/main.c rename regression/{modular => spurious-check-abstract}/nocex5/test.desc (100%) create mode 100644 regression/spurious-check-abstract/nocex6/main.c rename regression/{modular => spurious-check-abstract}/nocex6/test.desc (100%) create mode 100644 regression/spurious-check-abstract/nocex8/main.c rename regression/{modular => spurious-check-abstract}/nocex8/test.desc (100%) create mode 100644 regression/spurious-check-abstract/nocex9/main.c create mode 100644 regression/spurious-check-abstract/nocex9/test.desc rename regression/{modular => spurious-check-complete}/Makefile (100%) create mode 100644 regression/spurious-check-complete/cex-struct1/main.c create mode 100644 regression/spurious-check-complete/cex-struct1/test.desc create mode 100644 regression/spurious-check-complete/cex-struct2/main.c create mode 100644 regression/spurious-check-complete/cex-struct2/test.desc create mode 100644 regression/spurious-check-complete/cex-struct3/main.c create mode 100644 regression/spurious-check-complete/cex-struct3/test.desc create mode 100644 regression/spurious-check-complete/cex1/main.c create mode 100644 regression/spurious-check-complete/cex1/test.desc create mode 100644 regression/spurious-check-complete/cex10/main.c create mode 100644 regression/spurious-check-complete/cex10/test.desc create mode 100644 regression/spurious-check-complete/cex13/main.c create mode 100644 regression/spurious-check-complete/cex13/test.desc create mode 100644 regression/spurious-check-complete/cex2/main.c create mode 100644 regression/spurious-check-complete/cex2/test.desc create mode 100644 regression/spurious-check-complete/cex3/main.c create mode 100644 regression/spurious-check-complete/cex3/test.desc create mode 100644 regression/spurious-check-complete/cex4/main.c create mode 100644 regression/spurious-check-complete/cex4/test.desc create mode 100644 regression/spurious-check-complete/cex5/main.c create mode 100644 regression/spurious-check-complete/cex5/test.desc create mode 100644 regression/spurious-check-complete/cex6/main.c create mode 100644 regression/spurious-check-complete/cex6/test.desc create mode 100644 regression/spurious-check-complete/cex7/main.c create mode 100644 regression/spurious-check-complete/cex7/test.desc create mode 100644 regression/spurious-check-complete/cex8/main.c create mode 100644 regression/spurious-check-complete/cex8/test.desc create mode 100644 regression/spurious-check-complete/cex9/main.c create mode 100644 regression/spurious-check-complete/cex9/test.desc create mode 100644 regression/spurious-check-complete/nocex1/main.c rename regression/{modular/induction1 => spurious-check-complete/nocex1}/test.desc (80%) create mode 100644 regression/spurious-check-complete/nocex10/main.c create mode 100644 regression/spurious-check-complete/nocex10/test.desc create mode 100644 regression/spurious-check-complete/nocex2/main.c rename regression/{modular/induction8 => spurious-check-complete/nocex2}/test.desc (80%) create mode 100644 regression/spurious-check-complete/nocex3/main.c rename regression/{modular/loop27 => spurious-check-complete/nocex3}/test.desc (80%) create mode 100644 regression/spurious-check-complete/nocex4/main.c rename regression/{modular/induction4 => spurious-check-complete/nocex4}/test.desc (80%) create mode 100644 regression/spurious-check-complete/nocex5/main.c create mode 100644 regression/spurious-check-complete/nocex5/test.desc create mode 100644 regression/spurious-check-complete/nocex6/main.c create mode 100644 regression/spurious-check-complete/nocex6/test.desc create mode 100644 regression/spurious-check-complete/nocex8/main.c create mode 100644 regression/spurious-check-complete/nocex8/test.desc create mode 100644 regression/spurious-check-complete/nocex9/main.c create mode 100644 regression/spurious-check-complete/nocex9/test.desc create mode 100644 regression/spurious-check-concrete/Makefile create mode 100644 regression/spurious-check-concrete/cex-struct1/main.c create mode 100644 regression/spurious-check-concrete/cex-struct1/test.desc create mode 100644 regression/spurious-check-concrete/cex-struct2/main.c create mode 100644 regression/spurious-check-concrete/cex-struct2/test.desc create mode 100644 regression/spurious-check-concrete/cex-struct3/main.c create mode 100644 regression/spurious-check-concrete/cex-struct3/test.desc create mode 100644 regression/spurious-check-concrete/cex1/main.c create mode 100644 regression/spurious-check-concrete/cex1/test.desc create mode 100644 regression/spurious-check-concrete/cex10/main.c create mode 100644 regression/spurious-check-concrete/cex10/test.desc create mode 100644 regression/spurious-check-concrete/cex13/main.c create mode 100644 regression/spurious-check-concrete/cex13/test.desc create mode 100644 regression/spurious-check-concrete/cex2/main.c create mode 100644 regression/spurious-check-concrete/cex2/test.desc create mode 100644 regression/spurious-check-concrete/cex3/main.c create mode 100644 regression/spurious-check-concrete/cex3/test.desc create mode 100644 regression/spurious-check-concrete/cex4/main.c create mode 100644 regression/spurious-check-concrete/cex4/test.desc create mode 100644 regression/spurious-check-concrete/cex5/main.c create mode 100644 regression/spurious-check-concrete/cex5/test.desc create mode 100644 regression/spurious-check-concrete/cex6/main.c create mode 100644 regression/spurious-check-concrete/cex6/test.desc create mode 100644 regression/spurious-check-concrete/cex7/main.c create mode 100644 regression/spurious-check-concrete/cex7/test.desc create mode 100644 regression/spurious-check-concrete/cex8/main.c create mode 100644 regression/spurious-check-concrete/cex8/test.desc create mode 100644 regression/spurious-check-concrete/cex9/main.c create mode 100644 regression/spurious-check-concrete/cex9/test.desc create mode 100644 regression/spurious-check-concrete/nocex1/main.c create mode 100644 regression/spurious-check-concrete/nocex1/test.desc create mode 100644 regression/spurious-check-concrete/nocex10/main.c create mode 100644 regression/spurious-check-concrete/nocex10/test.desc create mode 100644 regression/spurious-check-concrete/nocex2/main.c create mode 100644 regression/spurious-check-concrete/nocex2/test.desc create mode 100644 regression/spurious-check-concrete/nocex3/main.c create mode 100644 regression/spurious-check-concrete/nocex3/test.desc create mode 100644 regression/spurious-check-concrete/nocex4/main.c create mode 100644 regression/spurious-check-concrete/nocex4/test.desc create mode 100644 regression/spurious-check-concrete/nocex5/main.c create mode 100644 regression/spurious-check-concrete/nocex5/test.desc create mode 100644 regression/spurious-check-concrete/nocex6/main.c create mode 100644 regression/spurious-check-concrete/nocex6/test.desc create mode 100644 regression/spurious-check-concrete/nocex8/main.c create mode 100644 regression/spurious-check-concrete/nocex8/test.desc create mode 100644 regression/spurious-check-concrete/nocex9/main.c create mode 100644 regression/spurious-check-concrete/nocex9/test.desc diff --git a/regression/kiki-modular/Makefile b/regression/kiki-modular/Makefile new file mode 100644 index 000000000..d2ff74910 --- /dev/null +++ b/regression/kiki-modular/Makefile @@ -0,0 +1,20 @@ +default: tests.log + +FLAGS = --verbosity 10 + +test: + @../test.pl -c "../../../src/summarizer/2ls $(FLAGS)" + +tests.log: ../test.pl + @../test.pl -c "../../../src/summarizer/2ls $(FLAGS)" + +show: + @for dir in *; do \ + if [ -d "$$dir" ]; then \ + vim -o "$$dir/*.c" "$$dir/*.out"; \ + fi; \ + done; + +clean: + @rm -f *.log + @for dir in *; do rm -f $$dir/*.out; done; diff --git a/regression/modular/cex-struct1/main.c b/regression/kiki-modular/cex-struct1/main.c similarity index 100% rename from regression/modular/cex-struct1/main.c rename to regression/kiki-modular/cex-struct1/main.c diff --git a/regression/kiki-modular/cex-struct1/test.desc b/regression/kiki-modular/cex-struct1/test.desc new file mode 100644 index 000000000..b5b4ee326 --- /dev/null +++ b/regression/kiki-modular/cex-struct1/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--havoc --k-induction --spurious-check complete +^EXIT=10$ +^SIGNAL=0$ +^VERIFICATION FAILED$ diff --git a/regression/modular/cex-struct2/main.c b/regression/kiki-modular/cex-struct2/main.c similarity index 100% rename from regression/modular/cex-struct2/main.c rename to regression/kiki-modular/cex-struct2/main.c diff --git a/regression/kiki-modular/cex-struct2/test.desc b/regression/kiki-modular/cex-struct2/test.desc new file mode 100644 index 000000000..b5b4ee326 --- /dev/null +++ b/regression/kiki-modular/cex-struct2/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--havoc --k-induction --spurious-check complete +^EXIT=10$ +^SIGNAL=0$ +^VERIFICATION FAILED$ diff --git a/regression/modular/cex-struct3/main.c b/regression/kiki-modular/cex-struct3/main.c similarity index 100% rename from regression/modular/cex-struct3/main.c rename to regression/kiki-modular/cex-struct3/main.c diff --git a/regression/kiki-modular/cex-struct3/test.desc b/regression/kiki-modular/cex-struct3/test.desc new file mode 100644 index 000000000..b5b4ee326 --- /dev/null +++ b/regression/kiki-modular/cex-struct3/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--havoc --k-induction --spurious-check complete +^EXIT=10$ +^SIGNAL=0$ +^VERIFICATION FAILED$ diff --git a/regression/modular/cex1/main.c b/regression/kiki-modular/cex1/main.c similarity index 100% rename from regression/modular/cex1/main.c rename to regression/kiki-modular/cex1/main.c diff --git a/regression/kiki-modular/cex1/test.desc b/regression/kiki-modular/cex1/test.desc new file mode 100644 index 000000000..b5b4ee326 --- /dev/null +++ b/regression/kiki-modular/cex1/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--havoc --k-induction --spurious-check complete +^EXIT=10$ +^SIGNAL=0$ +^VERIFICATION FAILED$ diff --git a/regression/modular/cex10/main.c b/regression/kiki-modular/cex10/main.c similarity index 100% rename from regression/modular/cex10/main.c rename to regression/kiki-modular/cex10/main.c diff --git a/regression/kiki-modular/cex10/test.desc b/regression/kiki-modular/cex10/test.desc new file mode 100644 index 000000000..b5b4ee326 --- /dev/null +++ b/regression/kiki-modular/cex10/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--havoc --k-induction --spurious-check complete +^EXIT=10$ +^SIGNAL=0$ +^VERIFICATION FAILED$ diff --git a/regression/modular/cex13/main.c b/regression/kiki-modular/cex13/main.c similarity index 100% rename from regression/modular/cex13/main.c rename to regression/kiki-modular/cex13/main.c diff --git a/regression/kiki-modular/cex13/test.desc b/regression/kiki-modular/cex13/test.desc new file mode 100644 index 000000000..b5b4ee326 --- /dev/null +++ b/regression/kiki-modular/cex13/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--havoc --k-induction --spurious-check complete +^EXIT=10$ +^SIGNAL=0$ +^VERIFICATION FAILED$ diff --git a/regression/modular/cex2/main.c b/regression/kiki-modular/cex2/main.c similarity index 100% rename from regression/modular/cex2/main.c rename to regression/kiki-modular/cex2/main.c diff --git a/regression/kiki-modular/cex2/test.desc b/regression/kiki-modular/cex2/test.desc new file mode 100644 index 000000000..b5b4ee326 --- /dev/null +++ b/regression/kiki-modular/cex2/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--havoc --k-induction --spurious-check complete +^EXIT=10$ +^SIGNAL=0$ +^VERIFICATION FAILED$ diff --git a/regression/modular/cex3/main.c b/regression/kiki-modular/cex3/main.c similarity index 100% rename from regression/modular/cex3/main.c rename to regression/kiki-modular/cex3/main.c diff --git a/regression/kiki-modular/cex3/test.desc b/regression/kiki-modular/cex3/test.desc new file mode 100644 index 000000000..b5b4ee326 --- /dev/null +++ b/regression/kiki-modular/cex3/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--havoc --k-induction --spurious-check complete +^EXIT=10$ +^SIGNAL=0$ +^VERIFICATION FAILED$ diff --git a/regression/modular/cex4/main.c b/regression/kiki-modular/cex4/main.c similarity index 100% rename from regression/modular/cex4/main.c rename to regression/kiki-modular/cex4/main.c diff --git a/regression/kiki-modular/cex4/test.desc b/regression/kiki-modular/cex4/test.desc new file mode 100644 index 000000000..b5b4ee326 --- /dev/null +++ b/regression/kiki-modular/cex4/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--havoc --k-induction --spurious-check complete +^EXIT=10$ +^SIGNAL=0$ +^VERIFICATION FAILED$ diff --git a/regression/modular/cex5/main.c b/regression/kiki-modular/cex5/main.c similarity index 100% rename from regression/modular/cex5/main.c rename to regression/kiki-modular/cex5/main.c diff --git a/regression/kiki-modular/cex5/test.desc b/regression/kiki-modular/cex5/test.desc new file mode 100644 index 000000000..b5b4ee326 --- /dev/null +++ b/regression/kiki-modular/cex5/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--havoc --k-induction --spurious-check complete +^EXIT=10$ +^SIGNAL=0$ +^VERIFICATION FAILED$ diff --git a/regression/modular/cex6/main.c b/regression/kiki-modular/cex6/main.c similarity index 100% rename from regression/modular/cex6/main.c rename to regression/kiki-modular/cex6/main.c diff --git a/regression/kiki-modular/cex6/test.desc b/regression/kiki-modular/cex6/test.desc new file mode 100644 index 000000000..b5b4ee326 --- /dev/null +++ b/regression/kiki-modular/cex6/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--havoc --k-induction --spurious-check complete +^EXIT=10$ +^SIGNAL=0$ +^VERIFICATION FAILED$ diff --git a/regression/modular/cex7/main.c b/regression/kiki-modular/cex7/main.c similarity index 100% rename from regression/modular/cex7/main.c rename to regression/kiki-modular/cex7/main.c diff --git a/regression/kiki-modular/cex7/test.desc b/regression/kiki-modular/cex7/test.desc new file mode 100644 index 000000000..b5b4ee326 --- /dev/null +++ b/regression/kiki-modular/cex7/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--havoc --k-induction --spurious-check complete +^EXIT=10$ +^SIGNAL=0$ +^VERIFICATION FAILED$ diff --git a/regression/modular/cex8/main.c b/regression/kiki-modular/cex8/main.c similarity index 100% rename from regression/modular/cex8/main.c rename to regression/kiki-modular/cex8/main.c diff --git a/regression/kiki-modular/cex8/test.desc b/regression/kiki-modular/cex8/test.desc new file mode 100644 index 000000000..b5b4ee326 --- /dev/null +++ b/regression/kiki-modular/cex8/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--havoc --k-induction --spurious-check complete +^EXIT=10$ +^SIGNAL=0$ +^VERIFICATION FAILED$ diff --git a/regression/modular/cex9/main.c b/regression/kiki-modular/cex9/main.c similarity index 100% rename from regression/modular/cex9/main.c rename to regression/kiki-modular/cex9/main.c diff --git a/regression/kiki-modular/cex9/test.desc b/regression/kiki-modular/cex9/test.desc new file mode 100644 index 000000000..b5b4ee326 --- /dev/null +++ b/regression/kiki-modular/cex9/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--havoc --k-induction --spurious-check complete +^EXIT=10$ +^SIGNAL=0$ +^VERIFICATION FAILED$ diff --git a/regression/modular/induction1/main.c b/regression/kiki-modular/induction1/main.c similarity index 100% rename from regression/modular/induction1/main.c rename to regression/kiki-modular/induction1/main.c diff --git a/regression/modular/induction2/test.desc b/regression/kiki-modular/induction1/test.desc similarity index 59% rename from regression/modular/induction2/test.desc rename to regression/kiki-modular/induction1/test.desc index 3bf2a93f1..e35a0daa7 100644 --- a/regression/modular/induction2/test.desc +++ b/regression/kiki-modular/induction1/test.desc @@ -1,6 +1,6 @@ CORE main.c ---k-induction --havoc +--k-induction --spurious-check complete ^EXIT=0$ ^SIGNAL=0$ ^VERIFICATION SUCCESSFUL$ diff --git a/regression/modular/induction2/main.c b/regression/kiki-modular/induction2/main.c similarity index 100% rename from regression/modular/induction2/main.c rename to regression/kiki-modular/induction2/main.c diff --git a/regression/kiki-modular/induction2/test.desc b/regression/kiki-modular/induction2/test.desc new file mode 100644 index 000000000..0544a23e5 --- /dev/null +++ b/regression/kiki-modular/induction2/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--havoc --k-induction --spurious-check complete +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ diff --git a/regression/modular/induction3/main.c b/regression/kiki-modular/induction3/main.c similarity index 100% rename from regression/modular/induction3/main.c rename to regression/kiki-modular/induction3/main.c diff --git a/regression/kiki-modular/induction3/test.desc b/regression/kiki-modular/induction3/test.desc new file mode 100644 index 000000000..0544a23e5 --- /dev/null +++ b/regression/kiki-modular/induction3/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--havoc --k-induction --spurious-check complete +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ diff --git a/regression/modular/induction4/main.c b/regression/kiki-modular/induction4/main.c similarity index 100% rename from regression/modular/induction4/main.c rename to regression/kiki-modular/induction4/main.c diff --git a/regression/modular/induction3/test.desc b/regression/kiki-modular/induction4/test.desc similarity index 59% rename from regression/modular/induction3/test.desc rename to regression/kiki-modular/induction4/test.desc index 3bf2a93f1..e35a0daa7 100644 --- a/regression/modular/induction3/test.desc +++ b/regression/kiki-modular/induction4/test.desc @@ -1,6 +1,6 @@ CORE main.c ---k-induction --havoc +--k-induction --spurious-check complete ^EXIT=0$ ^SIGNAL=0$ ^VERIFICATION SUCCESSFUL$ diff --git a/regression/modular/induction5/main.c b/regression/kiki-modular/induction5/main.c similarity index 100% rename from regression/modular/induction5/main.c rename to regression/kiki-modular/induction5/main.c diff --git a/regression/modular/induction5/test.desc b/regression/kiki-modular/induction5/test.desc similarity index 52% rename from regression/modular/induction5/test.desc rename to regression/kiki-modular/induction5/test.desc index 9a09cc686..4fb3efe5e 100644 --- a/regression/modular/induction5/test.desc +++ b/regression/kiki-modular/induction5/test.desc @@ -1,6 +1,6 @@ CORE main.c ---k-induction +--k-induction --spurious-check complete ^EXIT=10$ ^SIGNAL=0$ ^.*FAILURE$ diff --git a/regression/modular/induction7/main.c b/regression/kiki-modular/induction7/main.c similarity index 100% rename from regression/modular/induction7/main.c rename to regression/kiki-modular/induction7/main.c diff --git a/regression/modular/induction7/test.desc b/regression/kiki-modular/induction7/test.desc similarity index 52% rename from regression/modular/induction7/test.desc rename to regression/kiki-modular/induction7/test.desc index 9a09cc686..4fb3efe5e 100644 --- a/regression/modular/induction7/test.desc +++ b/regression/kiki-modular/induction7/test.desc @@ -1,6 +1,6 @@ CORE main.c ---k-induction +--k-induction --spurious-check complete ^EXIT=10$ ^SIGNAL=0$ ^.*FAILURE$ diff --git a/regression/modular/induction8/main.c b/regression/kiki-modular/induction8/main.c similarity index 100% rename from regression/modular/induction8/main.c rename to regression/kiki-modular/induction8/main.c diff --git a/regression/kiki-modular/induction8/test.desc b/regression/kiki-modular/induction8/test.desc new file mode 100644 index 000000000..e35a0daa7 --- /dev/null +++ b/regression/kiki-modular/induction8/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--k-induction --spurious-check complete +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ diff --git a/regression/kiki-modular/inline-refine1/main.c b/regression/kiki-modular/inline-refine1/main.c new file mode 100644 index 000000000..5662b4933 --- /dev/null +++ b/regression/kiki-modular/inline-refine1/main.c @@ -0,0 +1,17 @@ +#include + +int inc(int x) +{ + return x+1; +} + +void main() +{ + int x = 0; + int y = 0; + + x = inc(x); + y = inc(y); + + assert(x==1); +} diff --git a/regression/kiki-modular/inline-refine1/test.desc b/regression/kiki-modular/inline-refine1/test.desc new file mode 100644 index 000000000..af2fdc37b --- /dev/null +++ b/regression/kiki-modular/inline-refine1/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--havoc --k-induction --no-propagation --spurious-check concrete +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ diff --git a/regression/modular/nocex2/main.c b/regression/kiki-modular/inline-refine2/main.c similarity index 100% rename from regression/modular/nocex2/main.c rename to regression/kiki-modular/inline-refine2/main.c diff --git a/regression/kiki-modular/inline-refine2/test.desc b/regression/kiki-modular/inline-refine2/test.desc new file mode 100644 index 000000000..75b577755 --- /dev/null +++ b/regression/kiki-modular/inline-refine2/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--havoc --k-induction --spurious-check concrete +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ diff --git a/regression/modular/nocex3/main.c b/regression/kiki-modular/inline-refine3/main.c similarity index 100% rename from regression/modular/nocex3/main.c rename to regression/kiki-modular/inline-refine3/main.c diff --git a/regression/kiki-modular/inline-refine3/test.desc b/regression/kiki-modular/inline-refine3/test.desc new file mode 100644 index 000000000..75b577755 --- /dev/null +++ b/regression/kiki-modular/inline-refine3/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--havoc --k-induction --spurious-check concrete +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ diff --git a/regression/modular/nocex4/main.c b/regression/kiki-modular/inline-refine4/main.c similarity index 100% rename from regression/modular/nocex4/main.c rename to regression/kiki-modular/inline-refine4/main.c diff --git a/regression/kiki-modular/inline-refine4/test.desc b/regression/kiki-modular/inline-refine4/test.desc new file mode 100644 index 000000000..75b577755 --- /dev/null +++ b/regression/kiki-modular/inline-refine4/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--havoc --k-induction --spurious-check concrete +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ diff --git a/regression/modular/nocex5/main.c b/regression/kiki-modular/inline-refine5/main.c similarity index 100% rename from regression/modular/nocex5/main.c rename to regression/kiki-modular/inline-refine5/main.c diff --git a/regression/kiki-modular/inline-refine5/test.desc b/regression/kiki-modular/inline-refine5/test.desc new file mode 100644 index 000000000..75b577755 --- /dev/null +++ b/regression/kiki-modular/inline-refine5/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--havoc --k-induction --spurious-check concrete +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ diff --git a/regression/modular/nocex6/main.c b/regression/kiki-modular/inline-refine6/main.c similarity index 100% rename from regression/modular/nocex6/main.c rename to regression/kiki-modular/inline-refine6/main.c diff --git a/regression/kiki-modular/inline-refine6/test.desc b/regression/kiki-modular/inline-refine6/test.desc new file mode 100644 index 000000000..dbc94b93b --- /dev/null +++ b/regression/kiki-modular/inline-refine6/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--havoc --unwind 2 --k-induction --spurious-check concrete +^EXIT=5$ +^SIGNAL=0$ +^VERIFICATION INCONCLUSIVE$ diff --git a/regression/modular/nocex1/main.c b/regression/kiki-modular/inline-refine7/main.c similarity index 100% rename from regression/modular/nocex1/main.c rename to regression/kiki-modular/inline-refine7/main.c diff --git a/regression/kiki-modular/inline-refine7/test.desc b/regression/kiki-modular/inline-refine7/test.desc new file mode 100644 index 000000000..75b577755 --- /dev/null +++ b/regression/kiki-modular/inline-refine7/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--havoc --k-induction --spurious-check concrete +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ diff --git a/regression/modular/nocex8/main.c b/regression/kiki-modular/inline-refine8/main.c similarity index 100% rename from regression/modular/nocex8/main.c rename to regression/kiki-modular/inline-refine8/main.c diff --git a/regression/kiki-modular/inline-refine8/test.desc b/regression/kiki-modular/inline-refine8/test.desc new file mode 100644 index 000000000..75b577755 --- /dev/null +++ b/regression/kiki-modular/inline-refine8/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--havoc --k-induction --spurious-check concrete +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ diff --git a/regression/kiki-modular/inline-refine9/main.c b/regression/kiki-modular/inline-refine9/main.c new file mode 100644 index 000000000..47067bc2f --- /dev/null +++ b/regression/kiki-modular/inline-refine9/main.c @@ -0,0 +1,11 @@ +#include + +void main() +{ + int x = 0; + int y = 0; + + while(y<10) { x++; } + + assert(x==11); +} diff --git a/regression/kiki-modular/inline-refine9/test.desc b/regression/kiki-modular/inline-refine9/test.desc new file mode 100644 index 000000000..842d3328d --- /dev/null +++ b/regression/kiki-modular/inline-refine9/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--havoc --k-induction --spurious-check concrete --no-propagation +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ diff --git a/regression/modular/kind1/main.c b/regression/kiki-modular/kind1/main.c similarity index 100% rename from regression/modular/kind1/main.c rename to regression/kiki-modular/kind1/main.c diff --git a/regression/kiki-modular/kind1/test.desc b/regression/kiki-modular/kind1/test.desc new file mode 100644 index 000000000..0544a23e5 --- /dev/null +++ b/regression/kiki-modular/kind1/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--havoc --k-induction --spurious-check complete +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ diff --git a/regression/modular/kind2/main.c b/regression/kiki-modular/kind2/main.c similarity index 100% rename from regression/modular/kind2/main.c rename to regression/kiki-modular/kind2/main.c diff --git a/regression/kiki-modular/kind2/test.desc b/regression/kiki-modular/kind2/test.desc new file mode 100644 index 000000000..0544a23e5 --- /dev/null +++ b/regression/kiki-modular/kind2/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--havoc --k-induction --spurious-check complete +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ diff --git a/regression/modular/kind3/main.c b/regression/kiki-modular/kind3/main.c similarity index 100% rename from regression/modular/kind3/main.c rename to regression/kiki-modular/kind3/main.c diff --git a/regression/kiki-modular/kind3/test.desc b/regression/kiki-modular/kind3/test.desc new file mode 100644 index 000000000..0544a23e5 --- /dev/null +++ b/regression/kiki-modular/kind3/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--havoc --k-induction --spurious-check complete +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ diff --git a/regression/modular/kind4/main.c b/regression/kiki-modular/kind4/main.c similarity index 100% rename from regression/modular/kind4/main.c rename to regression/kiki-modular/kind4/main.c diff --git a/regression/kiki-modular/kind4/test.desc b/regression/kiki-modular/kind4/test.desc new file mode 100644 index 000000000..0544a23e5 --- /dev/null +++ b/regression/kiki-modular/kind4/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--havoc --k-induction --spurious-check complete +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ diff --git a/regression/modular/kind5/main.c b/regression/kiki-modular/kind5/main.c similarity index 100% rename from regression/modular/kind5/main.c rename to regression/kiki-modular/kind5/main.c diff --git a/regression/kiki-modular/kind5/test.desc b/regression/kiki-modular/kind5/test.desc new file mode 100644 index 000000000..0544a23e5 --- /dev/null +++ b/regression/kiki-modular/kind5/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--havoc --k-induction --spurious-check complete +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ diff --git a/regression/modular/kind6/main.c b/regression/kiki-modular/kind6/main.c similarity index 100% rename from regression/modular/kind6/main.c rename to regression/kiki-modular/kind6/main.c diff --git a/regression/kiki-modular/kind6/test.desc b/regression/kiki-modular/kind6/test.desc new file mode 100644 index 000000000..0544a23e5 --- /dev/null +++ b/regression/kiki-modular/kind6/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--havoc --k-induction --spurious-check complete +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ diff --git a/regression/modular/cex11/main.c b/regression/kiki-modular/kind7/main.c similarity index 100% rename from regression/modular/cex11/main.c rename to regression/kiki-modular/kind7/main.c diff --git a/regression/kiki-modular/kind7/test.desc b/regression/kiki-modular/kind7/test.desc new file mode 100644 index 000000000..0544a23e5 --- /dev/null +++ b/regression/kiki-modular/kind7/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--havoc --k-induction --spurious-check complete +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ diff --git a/regression/modular/cex12/main.c b/regression/kiki-modular/kind8/main.c similarity index 100% rename from regression/modular/cex12/main.c rename to regression/kiki-modular/kind8/main.c diff --git a/regression/kiki-modular/kind8/test.desc b/regression/kiki-modular/kind8/test.desc new file mode 100644 index 000000000..0544a23e5 --- /dev/null +++ b/regression/kiki-modular/kind8/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--havoc --k-induction --spurious-check complete +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ diff --git a/regression/modular/loop25/main.c b/regression/kiki-modular/loop25/main.c similarity index 100% rename from regression/modular/loop25/main.c rename to regression/kiki-modular/loop25/main.c diff --git a/regression/kiki-modular/loop25/test.desc b/regression/kiki-modular/loop25/test.desc new file mode 100644 index 000000000..0544a23e5 --- /dev/null +++ b/regression/kiki-modular/loop25/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--havoc --k-induction --spurious-check complete +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ diff --git a/regression/modular/loop27/main.c b/regression/kiki-modular/loop27/main.c similarity index 100% rename from regression/modular/loop27/main.c rename to regression/kiki-modular/loop27/main.c diff --git a/regression/kiki-modular/loop27/test.desc b/regression/kiki-modular/loop27/test.desc new file mode 100644 index 000000000..0544a23e5 --- /dev/null +++ b/regression/kiki-modular/loop27/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--havoc --k-induction --spurious-check complete +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ diff --git a/regression/modular/loop28/main.c b/regression/kiki-modular/loop28/main.c similarity index 100% rename from regression/modular/loop28/main.c rename to regression/kiki-modular/loop28/main.c diff --git a/regression/kiki-modular/loop28/test.desc b/regression/kiki-modular/loop28/test.desc new file mode 100644 index 000000000..e35a0daa7 --- /dev/null +++ b/regression/kiki-modular/loop28/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--k-induction --spurious-check complete +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ diff --git a/regression/modular/nested11/main.c b/regression/kiki-modular/nested11/main.c similarity index 100% rename from regression/modular/nested11/main.c rename to regression/kiki-modular/nested11/main.c diff --git a/regression/kiki-modular/nested11/test.desc b/regression/kiki-modular/nested11/test.desc new file mode 100644 index 000000000..e35a0daa7 --- /dev/null +++ b/regression/kiki-modular/nested11/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--k-induction --spurious-check complete +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ diff --git a/regression/modular/nested12/main.c b/regression/kiki-modular/nested12/main.c similarity index 100% rename from regression/modular/nested12/main.c rename to regression/kiki-modular/nested12/main.c diff --git a/regression/modular/nested12/test.desc b/regression/kiki-modular/nested12/test.desc similarity index 52% rename from regression/modular/nested12/test.desc rename to regression/kiki-modular/nested12/test.desc index 9a09cc686..4fb3efe5e 100644 --- a/regression/modular/nested12/test.desc +++ b/regression/kiki-modular/nested12/test.desc @@ -1,6 +1,6 @@ CORE main.c ---k-induction +--k-induction --spurious-check complete ^EXIT=10$ ^SIGNAL=0$ ^.*FAILURE$ diff --git a/regression/kiki-modular/nocex1/main.c b/regression/kiki-modular/nocex1/main.c new file mode 100644 index 000000000..6faa3e65d --- /dev/null +++ b/regression/kiki-modular/nocex1/main.c @@ -0,0 +1,15 @@ +#include + +int foo(int x) +{ + assert(x>5); +} + +int main(int argc, char** argv) +{ + int y; + if(y>10) foo(y); + + return 0; +} + diff --git a/regression/kiki-modular/nocex1/test.desc b/regression/kiki-modular/nocex1/test.desc new file mode 100644 index 000000000..0544a23e5 --- /dev/null +++ b/regression/kiki-modular/nocex1/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--havoc --k-induction --spurious-check complete +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ diff --git a/regression/kiki-modular/nocex2/main.c b/regression/kiki-modular/nocex2/main.c new file mode 100644 index 000000000..100ddaec6 --- /dev/null +++ b/regression/kiki-modular/nocex2/main.c @@ -0,0 +1,16 @@ + +#include + +void foo(int x) +{ + assert(x==5); +} + +int main(int argc, char** argv) +{ + int y = 5; + foo(y); + + return 0; +} + diff --git a/regression/kiki-modular/nocex2/test.desc b/regression/kiki-modular/nocex2/test.desc new file mode 100644 index 000000000..0544a23e5 --- /dev/null +++ b/regression/kiki-modular/nocex2/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--havoc --k-induction --spurious-check complete +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ diff --git a/regression/kiki-modular/nocex3/main.c b/regression/kiki-modular/nocex3/main.c new file mode 100644 index 000000000..257e8fc7a --- /dev/null +++ b/regression/kiki-modular/nocex3/main.c @@ -0,0 +1,18 @@ + +#include + +int bar(){ + return 1; +} + +void foo(int x) { + assert(x != 5); +} + +int main() { + int y = bar(); + foo(y); + return 0; +} + + diff --git a/regression/kiki-modular/nocex3/test.desc b/regression/kiki-modular/nocex3/test.desc new file mode 100644 index 000000000..0544a23e5 --- /dev/null +++ b/regression/kiki-modular/nocex3/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--havoc --k-induction --spurious-check complete +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ diff --git a/regression/kiki-modular/nocex4/main.c b/regression/kiki-modular/nocex4/main.c new file mode 100644 index 000000000..4e96e8e89 --- /dev/null +++ b/regression/kiki-modular/nocex4/main.c @@ -0,0 +1,20 @@ + +#include + +int bar(int k){ + return (k+1); +} + +void foo(int x) { + x = bar(x); + assert(x>5); +} + +int main() { + int y; + __CPROVER_assume(y<100000); + if(y > 10) foo(y); + return 0; +} + + diff --git a/regression/kiki-modular/nocex4/test.desc b/regression/kiki-modular/nocex4/test.desc new file mode 100644 index 000000000..0544a23e5 --- /dev/null +++ b/regression/kiki-modular/nocex4/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--havoc --k-induction --spurious-check complete +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ diff --git a/regression/kiki-modular/nocex5/main.c b/regression/kiki-modular/nocex5/main.c new file mode 100644 index 000000000..b225c7ce8 --- /dev/null +++ b/regression/kiki-modular/nocex5/main.c @@ -0,0 +1,30 @@ + +#include + +int foobar(int a){ + int i; + if(i < a) + return i+a; + else + return i-a; +} + +int bar(int k){ + return (k+1); +} + +void foo(int x, int s) { + int m; + s = foobar(m); + x = bar(x); + assert(x>5); +} + +int main() { + int y,k; + __CPROVER_assume(y<100000); + if(y > 10) foo(y,k); + return 0; +} + + diff --git a/regression/kiki-modular/nocex5/test.desc b/regression/kiki-modular/nocex5/test.desc new file mode 100644 index 000000000..0544a23e5 --- /dev/null +++ b/regression/kiki-modular/nocex5/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--havoc --k-induction --spurious-check complete +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ diff --git a/regression/kiki-modular/nocex6/main.c b/regression/kiki-modular/nocex6/main.c new file mode 100644 index 000000000..309c06dd9 --- /dev/null +++ b/regression/kiki-modular/nocex6/main.c @@ -0,0 +1,15 @@ + +#include + +int main(int argc, char** argv) +{ + int y = 1; + + while(y<30){ + y++; + assert(y<5); + } + + return 0; +} + diff --git a/regression/kiki-modular/nocex6/test.desc b/regression/kiki-modular/nocex6/test.desc new file mode 100644 index 000000000..f0edbd788 --- /dev/null +++ b/regression/kiki-modular/nocex6/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--havoc --unwind 2 --k-induction --spurious-check complete +^EXIT=5$ +^SIGNAL=0$ +^VERIFICATION INCONCLUSIVE$ diff --git a/regression/kiki-modular/nocex8/main.c b/regression/kiki-modular/nocex8/main.c new file mode 100644 index 000000000..d9ee4be0c --- /dev/null +++ b/regression/kiki-modular/nocex8/main.c @@ -0,0 +1,16 @@ + +#include + +void fail(void) +{ + assert(0); +} + +int main(void) +{ + int tmp = 0; + if(tmp) + fail(); + return 0; +} + diff --git a/regression/kiki-modular/nocex8/test.desc b/regression/kiki-modular/nocex8/test.desc new file mode 100644 index 000000000..0544a23e5 --- /dev/null +++ b/regression/kiki-modular/nocex8/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--havoc --k-induction --spurious-check complete +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ diff --git a/regression/kiki-modular/nocex9/main.c b/regression/kiki-modular/nocex9/main.c new file mode 100644 index 000000000..47067bc2f --- /dev/null +++ b/regression/kiki-modular/nocex9/main.c @@ -0,0 +1,11 @@ +#include + +void main() +{ + int x = 0; + int y = 0; + + while(y<10) { x++; } + + assert(x==11); +} diff --git a/regression/kiki-modular/nocex9/test.desc b/regression/kiki-modular/nocex9/test.desc new file mode 100644 index 000000000..312f3d84e --- /dev/null +++ b/regression/kiki-modular/nocex9/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--havoc --k-induction --spurious-check complete --no-propagation +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ diff --git a/regression/modular/s3_clnt_1/main.c b/regression/kiki-modular/s3_clnt_1/main.c similarity index 100% rename from regression/modular/s3_clnt_1/main.c rename to regression/kiki-modular/s3_clnt_1/main.c diff --git a/regression/kiki-modular/s3_clnt_1/test.desc b/regression/kiki-modular/s3_clnt_1/test.desc new file mode 100644 index 000000000..62a74380a --- /dev/null +++ b/regression/kiki-modular/s3_clnt_1/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--havoc --k-induction --spurious-check complete +^EXIT=10$ +^SIGNAL=0$ +^.*FAILURE$ diff --git a/regression/modular/scope1/main.c b/regression/kiki-modular/scope1/main.c similarity index 100% rename from regression/modular/scope1/main.c rename to regression/kiki-modular/scope1/main.c diff --git a/regression/kiki-modular/scope1/test.desc b/regression/kiki-modular/scope1/test.desc new file mode 100644 index 000000000..e35a0daa7 --- /dev/null +++ b/regression/kiki-modular/scope1/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--k-induction --spurious-check complete +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ diff --git a/regression/kiki-modular/unwind-refine1/main.c b/regression/kiki-modular/unwind-refine1/main.c new file mode 100644 index 000000000..6852ba883 --- /dev/null +++ b/regression/kiki-modular/unwind-refine1/main.c @@ -0,0 +1,15 @@ +#include + +void main() +{ + int x = 0; + int y = 0; + int c; + + while(x<10) ++x; + + int c; + while(c) ++y; + + assert(x==10); +} diff --git a/regression/kiki-modular/unwind-refine1/test.desc b/regression/kiki-modular/unwind-refine1/test.desc new file mode 100644 index 000000000..80195020a --- /dev/null +++ b/regression/kiki-modular/unwind-refine1/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--havoc --k-induction --no-propagation --spurious-check complete +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ diff --git a/regression/modular/kind1/test.desc b/regression/modular/kind1/test.desc deleted file mode 100644 index 630457914..000000000 --- a/regression/modular/kind1/test.desc +++ /dev/null @@ -1,6 +0,0 @@ -CORE -main.c ---havoc --k-induction -^EXIT=0$ -^SIGNAL=0$ -^VERIFICATION SUCCESSFUL$ diff --git a/regression/modular/kind2/test.desc b/regression/modular/kind2/test.desc deleted file mode 100644 index 630457914..000000000 --- a/regression/modular/kind2/test.desc +++ /dev/null @@ -1,6 +0,0 @@ -CORE -main.c ---havoc --k-induction -^EXIT=0$ -^SIGNAL=0$ -^VERIFICATION SUCCESSFUL$ diff --git a/regression/modular/kind3/test.desc b/regression/modular/kind3/test.desc deleted file mode 100644 index 630457914..000000000 --- a/regression/modular/kind3/test.desc +++ /dev/null @@ -1,6 +0,0 @@ -CORE -main.c ---havoc --k-induction -^EXIT=0$ -^SIGNAL=0$ -^VERIFICATION SUCCESSFUL$ diff --git a/regression/modular/kind4/test.desc b/regression/modular/kind4/test.desc deleted file mode 100644 index 630457914..000000000 --- a/regression/modular/kind4/test.desc +++ /dev/null @@ -1,6 +0,0 @@ -CORE -main.c ---havoc --k-induction -^EXIT=0$ -^SIGNAL=0$ -^VERIFICATION SUCCESSFUL$ diff --git a/regression/modular/kind5/test.desc b/regression/modular/kind5/test.desc deleted file mode 100644 index 630457914..000000000 --- a/regression/modular/kind5/test.desc +++ /dev/null @@ -1,6 +0,0 @@ -CORE -main.c ---havoc --k-induction -^EXIT=0$ -^SIGNAL=0$ -^VERIFICATION SUCCESSFUL$ diff --git a/regression/modular/kind6/test.desc b/regression/modular/kind6/test.desc deleted file mode 100644 index 630457914..000000000 --- a/regression/modular/kind6/test.desc +++ /dev/null @@ -1,6 +0,0 @@ -CORE -main.c ---havoc --k-induction -^EXIT=0$ -^SIGNAL=0$ -^VERIFICATION SUCCESSFUL$ diff --git a/regression/modular/loop25/test.desc b/regression/modular/loop25/test.desc deleted file mode 100644 index 6755e58a3..000000000 --- a/regression/modular/loop25/test.desc +++ /dev/null @@ -1,6 +0,0 @@ -CORE -main.c ---k-induction -^EXIT=0$ -^SIGNAL=0$ -^VERIFICATION SUCCESSFUL$ diff --git a/regression/modular/loop28/test.desc b/regression/modular/loop28/test.desc deleted file mode 100644 index 34e465e33..000000000 --- a/regression/modular/loop28/test.desc +++ /dev/null @@ -1,6 +0,0 @@ -CORE -main.c ---k-induction -^EXIT=0$ -^SIGNAL=0$ -^VERIFICATION SUCCESSFUL$ diff --git a/regression/modular/nested11/test.desc b/regression/modular/nested11/test.desc deleted file mode 100644 index 34e465e33..000000000 --- a/regression/modular/nested11/test.desc +++ /dev/null @@ -1,6 +0,0 @@ -CORE -main.c ---k-induction -^EXIT=0$ -^SIGNAL=0$ -^VERIFICATION SUCCESSFUL$ diff --git a/regression/modular/s3_clnt_1/test.desc b/regression/modular/s3_clnt_1/test.desc deleted file mode 100644 index 4d84485b2..000000000 --- a/regression/modular/s3_clnt_1/test.desc +++ /dev/null @@ -1,6 +0,0 @@ -CORE -main.c ---havoc --k-induction -^EXIT=10$ -^SIGNAL=0$ -^.*FAILURE$ diff --git a/regression/modular/scope1/test.desc b/regression/modular/scope1/test.desc deleted file mode 100644 index 34e465e33..000000000 --- a/regression/modular/scope1/test.desc +++ /dev/null @@ -1,6 +0,0 @@ -CORE -main.c ---k-induction -^EXIT=0$ -^SIGNAL=0$ -^VERIFICATION SUCCESSFUL$ diff --git a/regression/spurious-check-abstract/Makefile b/regression/spurious-check-abstract/Makefile new file mode 100644 index 000000000..3a92d5017 --- /dev/null +++ b/regression/spurious-check-abstract/Makefile @@ -0,0 +1,20 @@ +default: tests.log + +FLAGS = --verbosity 10 --spurious-check abstract + +test: + @../test.pl -c "../../../src/summarizer/2ls $(FLAGS)" + +tests.log: ../test.pl + @../test.pl -c "../../../src/summarizer/2ls $(FLAGS)" + +show: + @for dir in *; do \ + if [ -d "$$dir" ]; then \ + vim -o "$$dir/*.c" "$$dir/*.out"; \ + fi; \ + done; + +clean: + @rm -f *.log + @for dir in *; do rm -f $$dir/*.out; done; diff --git a/regression/spurious-check-abstract/cex-struct1/main.c b/regression/spurious-check-abstract/cex-struct1/main.c new file mode 100644 index 000000000..a9a9139fa --- /dev/null +++ b/regression/spurious-check-abstract/cex-struct1/main.c @@ -0,0 +1,180 @@ + +#include +#include + +typedef struct{ int x; int y; int z; int w; int p; int q; int a; } foo; + +foo func_1(foo f); +foo func_2(foo f); +foo func_3(foo f); +foo func_4(foo f); +foo func_5(foo f); +foo func_6(foo f); +foo func_7(foo f); +foo func_8(foo f); + +foo func_1(foo f) +{ + f.x = 23 + 12; + f.x = 4 - 1; + if(f.w > f.x) {f.q = 21 * f.z;} else {f.q = 4 / f.p;} + f.a = f.a + 1; + f.z = f.y * f.x; + f.x = 11 - f.p; + f.y = 1 - 19; + f.y = f.w - 14; + return f; +} + +/**********************************************************************/ + +foo func_2(foo f) +{ + if(f.y < f.q) {f.x = f.w / 24;} else {f.w = 18 / 3;} + f.w = f.p * f.q; + if(f.q < 6) {f.y = 25 - f.x;} else {f.q = f.y / f.w;} + f.a = f.a + 1; + if(f.x <= f.x) {f.z = 9 + f.x;} else {f.y = 1 + f.x;} + f.x = f.q / 25; + f.w = f.x - f.y; + f.x = 9 + f.y; + f.y = 24 - 2; + f.w = 10 + f.z; + return f; +} + +/**********************************************************************/ + +foo func_3(foo f) +{ + if(f.p == 12) {f.w = 22 + 7;} else {f.p = f.x + f.q;} + f.y = f.p + f.x; + f.w = 6 * f.y; + if(f.z <= 20) {f.q = 21 / 24;} else {f.w = f.q * f.w;} + f.w = f.y - 10; + f.q = 2 - 20; + f.x = f.x / 10; + f.p = 16 * 23; + f.w = 18 - 13; + f.w = f.p - 2; + f.z = 7 + f.w; + f.a = f.a + 1; + f.x = 16 / f.x; + return f; +} + +/**********************************************************************/ + +foo func_4(foo f) +{ + f.w = f.y + f.y; + f.q = 18 * 13; + f.y = f.z * f.y; + f.x = 1 * 25; + f.y = 4 / f.q; + f.x = f.p / 9; + f.a = f.a + 1; + if(f.x >= 7) {f.q = f.q / 8;} else {if(f.x < 9) {f.z = 16 + f.p;} else {f.x = f.w - 18;}} + f.y = 2 * 4; + f.q = 16 + f.x; + f.q = 16 * f.w; + if(f.w > 14) {f.q = 20 + 20;} else {f.x = 25 + 9;} + return f; +} + +/**********************************************************************/ + +foo func_5(foo f) +{ + f.a = f.a + 1; + if(f.x == 13) {f.p = 13 * f.x;} else {f.w = f.q / f.w;} + f.y = 21 * f.x; + f.p = 4 * 25; + if(f.p >= 24) {f.x = 11 * 6;} else {f.p = 9 * f.p;} + f.x = 3 + f.z; + f.x = f.x + 22; + f.z = 8 / 8; + f.q = 18 + f.x; + f.x = 5 * f.z; + f.y = f.w + f.w; + return f; +} + +/**********************************************************************/ + +foo func_6(foo f) +{ + f.y = f.w / f.q; + f.p = f.x + 8; + f.a = f.a + 1; + f.z = f.w * 20; + if(f.x < f.p) {f.x = f.z + 2;} else {f.y = f.y * f.x;} + if(f.y <= f.y) {f.q = f.y * f.w;} else {f.q = f.w - 13;} + f.p = 9 + f.y; + f.q = f.y / 14; + f.p = 18 / f.z; + if(f.w < f.p) {f.w = 17 * f.p;} else {f.p = f.y - 10;} + f.p = 3 / 14; + f.q = 10 - f.w; + if(f.y > 12) {f.z = f.q - 24;} else {f.x = f.z / 17;} + return f; +} + +/**********************************************************************/ + +foo func_7(foo f) +{ + f.q = f.q * 23; + f.w = 25 - f.w; + if(f.q < f.y) {f.w = 21 + f.z;} else {f.p = 16 - 1;} + f.y = f.z * f.z; + f.x = 5 * 16; + f.x = 11 + f.x; + f.z = f.y - f.y; + f.q = 11 - f.z; + f.a = f.a + 1; + return f; +} + +/**********************************************************************/ + +foo func_8(foo f) +{ + f.w = f.y - 15; + f.q = f.x + f.z; + f.y = 5 / 1; + if(f.q < 3) {f.p = 6 * f.x; } else {f.w = 8 + 21;} + f.p = 19 / f.p; + f.z = 4 / f.z; + if(f.x < 12) {f.p = f.y - 4; } else {f.x = 15 + 2;} + f.q = 19 / f.w; + if(f.p > 24) {f.z = 5 / 9;} else {f.w = f.x + f.z;} + f.z = f.z + 1; + f.a = f.a + 1; + if(f.z > f.y) {f.y = f.y + f.x;} else {f.y = 13 - 18;} + return f; +} + + +/**********************************************************************/ + +int main() +{ + foo f0, f1, f2, f3, f4, f5, f6, f7, f8; + +// __CPROVER_assume((f0.a >= 0) && (f0.a <= 9)); + f0.a = 0; + + f1 = func_1(f0); +/* f2 = func_2(f1); + f3 = func_3(f2); + f4 = func_4(f3); + f5 = func_5(f4); + f6 = func_6(f5); + f7 = func_7(f6); + f8 = func_8(f7);*/ + + assert(/*(f8.x + f8.y + f8.z + f8.w + f8.p + f8.q > 0) &&*/ (f1.a != 1)); // unsafe assertion + + return 0; +} diff --git a/regression/modular/cex-struct1/test.desc b/regression/spurious-check-abstract/cex-struct1/test.desc similarity index 100% rename from regression/modular/cex-struct1/test.desc rename to regression/spurious-check-abstract/cex-struct1/test.desc diff --git a/regression/spurious-check-abstract/cex-struct2/main.c b/regression/spurious-check-abstract/cex-struct2/main.c new file mode 100644 index 000000000..a5d7032f4 --- /dev/null +++ b/regression/spurious-check-abstract/cex-struct2/main.c @@ -0,0 +1,22 @@ + +#include +#include + +typedef struct{ int a; } foo; + +foo func_1(foo f) +{ + f.a = f.a + 1; + return f; +} + +int main() +{ + foo f0, f1; + f0.a = 0; + + f1 = func_1(f0); + + assert((f1.a) != 1); + return 0; +} diff --git a/regression/modular/cex-struct2/test.desc b/regression/spurious-check-abstract/cex-struct2/test.desc similarity index 100% rename from regression/modular/cex-struct2/test.desc rename to regression/spurious-check-abstract/cex-struct2/test.desc diff --git a/regression/spurious-check-abstract/cex-struct3/main.c b/regression/spurious-check-abstract/cex-struct3/main.c new file mode 100644 index 000000000..1715861bf --- /dev/null +++ b/regression/spurious-check-abstract/cex-struct3/main.c @@ -0,0 +1,23 @@ + +#include +#include + +typedef struct{ int x; int a; } foo; + +foo func_1(foo f) +{ + f.a = f.a + 1; + f.x = f.a; + return f; +} + +int main() +{ + foo f0, f1; + f0.a = 0; + + f1 = func_1(f0); + assert(f1.a != 1); // unsafe assertion + + return 0; +} diff --git a/regression/modular/cex-struct3/test.desc b/regression/spurious-check-abstract/cex-struct3/test.desc similarity index 100% rename from regression/modular/cex-struct3/test.desc rename to regression/spurious-check-abstract/cex-struct3/test.desc diff --git a/regression/spurious-check-abstract/cex1/main.c b/regression/spurious-check-abstract/cex1/main.c new file mode 100644 index 000000000..53451cf50 --- /dev/null +++ b/regression/spurious-check-abstract/cex1/main.c @@ -0,0 +1,15 @@ +#include + +int foo(int x) +{ + assert(x>5); +} + +int main(int argc, char** argv) +{ + int y; + if(y<=0) foo(y); + + return 0; +} + diff --git a/regression/modular/cex1/test.desc b/regression/spurious-check-abstract/cex1/test.desc similarity index 100% rename from regression/modular/cex1/test.desc rename to regression/spurious-check-abstract/cex1/test.desc diff --git a/regression/spurious-check-abstract/cex10/main.c b/regression/spurious-check-abstract/cex10/main.c new file mode 100644 index 000000000..5908a46cc --- /dev/null +++ b/regression/spurious-check-abstract/cex10/main.c @@ -0,0 +1,21 @@ +#include + +int error(int k){ + assert(k != 3); +} + +int inc(int x){ + return (x+1); +}; + +int main(){ + int num = 0; + num = inc(num); + num = inc(num); + num = inc(num); + error(num); + return 0; +} + + + diff --git a/regression/modular/cex10/test.desc b/regression/spurious-check-abstract/cex10/test.desc similarity index 100% rename from regression/modular/cex10/test.desc rename to regression/spurious-check-abstract/cex10/test.desc diff --git a/regression/spurious-check-abstract/cex13/main.c b/regression/spurious-check-abstract/cex13/main.c new file mode 100644 index 000000000..242217d45 --- /dev/null +++ b/regression/spurious-check-abstract/cex13/main.c @@ -0,0 +1,16 @@ + +#include + +void foo(int x) +{ + assert(x==5); +} + +int main(int argc, char** argv) +{ + int y = 4; + foo(y); + + return 0; +} + diff --git a/regression/modular/cex13/test.desc b/regression/spurious-check-abstract/cex13/test.desc similarity index 100% rename from regression/modular/cex13/test.desc rename to regression/spurious-check-abstract/cex13/test.desc diff --git a/regression/modular/cex13/main.c~ b/regression/spurious-check-abstract/cex2/main.c similarity index 100% rename from regression/modular/cex13/main.c~ rename to regression/spurious-check-abstract/cex2/main.c diff --git a/regression/modular/cex2/test.desc b/regression/spurious-check-abstract/cex2/test.desc similarity index 100% rename from regression/modular/cex2/test.desc rename to regression/spurious-check-abstract/cex2/test.desc diff --git a/regression/spurious-check-abstract/cex3/main.c b/regression/spurious-check-abstract/cex3/main.c new file mode 100644 index 000000000..952a3137b --- /dev/null +++ b/regression/spurious-check-abstract/cex3/main.c @@ -0,0 +1,16 @@ + +#include + +int foo(int x) +{ + assert(x!=5); +} + +int main(int argc, char** argv) +{ + int y; + if(y > 0) foo(y); + + return 0; +} + diff --git a/regression/modular/cex3/test.desc b/regression/spurious-check-abstract/cex3/test.desc similarity index 100% rename from regression/modular/cex3/test.desc rename to regression/spurious-check-abstract/cex3/test.desc diff --git a/regression/spurious-check-abstract/cex4/main.c b/regression/spurious-check-abstract/cex4/main.c new file mode 100644 index 000000000..8463fe610 --- /dev/null +++ b/regression/spurious-check-abstract/cex4/main.c @@ -0,0 +1,11 @@ + +#include + +int main(int argc, char** argv) +{ + int y = 5; + assert(y != 5); + + return 0; +} + diff --git a/regression/modular/cex4/test.desc b/regression/spurious-check-abstract/cex4/test.desc similarity index 100% rename from regression/modular/cex4/test.desc rename to regression/spurious-check-abstract/cex4/test.desc diff --git a/regression/spurious-check-abstract/cex5/main.c b/regression/spurious-check-abstract/cex5/main.c new file mode 100644 index 000000000..0eabc5796 --- /dev/null +++ b/regression/spurious-check-abstract/cex5/main.c @@ -0,0 +1,15 @@ +#include + +int foo(int x) +{ + assert(x>5); +} + +int main(int argc, char** argv) +{ + int y; + if(y>0) foo(y); + + return 0; +} + diff --git a/regression/modular/cex5/test.desc b/regression/spurious-check-abstract/cex5/test.desc similarity index 100% rename from regression/modular/cex5/test.desc rename to regression/spurious-check-abstract/cex5/test.desc diff --git a/regression/spurious-check-abstract/cex6/main.c b/regression/spurious-check-abstract/cex6/main.c new file mode 100644 index 000000000..80de0138d --- /dev/null +++ b/regression/spurious-check-abstract/cex6/main.c @@ -0,0 +1,20 @@ + +#include + +void foo(int x) +{ + assert(x<1); +} + +int main() +{ + int y; + + while(y < 2){ + y++; + foo(y); + } + + return 0; +} + diff --git a/regression/modular/cex6/test.desc b/regression/spurious-check-abstract/cex6/test.desc similarity index 100% rename from regression/modular/cex6/test.desc rename to regression/spurious-check-abstract/cex6/test.desc diff --git a/regression/spurious-check-abstract/cex7/main.c b/regression/spurious-check-abstract/cex7/main.c new file mode 100644 index 000000000..8ab3e91f9 --- /dev/null +++ b/regression/spurious-check-abstract/cex7/main.c @@ -0,0 +1,15 @@ + +#include + +int main(int argc, char** argv) +{ + int y = 1; + + while(y<30){ + y++; + assert(y<4); + } + + return 0; +} + diff --git a/regression/modular/cex7/test.desc b/regression/spurious-check-abstract/cex7/test.desc similarity index 100% rename from regression/modular/cex7/test.desc rename to regression/spurious-check-abstract/cex7/test.desc diff --git a/regression/spurious-check-abstract/cex8/main.c b/regression/spurious-check-abstract/cex8/main.c new file mode 100644 index 000000000..3bb7e471c --- /dev/null +++ b/regression/spurious-check-abstract/cex8/main.c @@ -0,0 +1,20 @@ +#include + +int error(int k){ + assert(k != 2); +} + +int inc(int x){ + return (x+1); +}; + +int main(){ + int num = 0; + num = inc(num); + num = inc(num); + error(num); + return 0; +} + + + diff --git a/regression/modular/cex8/test.desc b/regression/spurious-check-abstract/cex8/test.desc similarity index 100% rename from regression/modular/cex8/test.desc rename to regression/spurious-check-abstract/cex8/test.desc diff --git a/regression/spurious-check-abstract/cex9/main.c b/regression/spurious-check-abstract/cex9/main.c new file mode 100644 index 000000000..675f72f26 --- /dev/null +++ b/regression/spurious-check-abstract/cex9/main.c @@ -0,0 +1,24 @@ +#include + +int error(int k){ + assert(k != 2); +} + +int inc(int x){ + return (x+1); +}; + +int inc_copy(int x){ + return (x+1); +}; + +int main(){ + int num = 0; + num = inc_copy(num); + num = inc(num); + error(num); + return 0; +} + + + diff --git a/regression/modular/cex9/test.desc b/regression/spurious-check-abstract/cex9/test.desc similarity index 100% rename from regression/modular/cex9/test.desc rename to regression/spurious-check-abstract/cex9/test.desc diff --git a/regression/spurious-check-abstract/nocex1/main.c b/regression/spurious-check-abstract/nocex1/main.c new file mode 100644 index 000000000..6faa3e65d --- /dev/null +++ b/regression/spurious-check-abstract/nocex1/main.c @@ -0,0 +1,15 @@ +#include + +int foo(int x) +{ + assert(x>5); +} + +int main(int argc, char** argv) +{ + int y; + if(y>10) foo(y); + + return 0; +} + diff --git a/regression/modular/nocex1/test.desc b/regression/spurious-check-abstract/nocex1/test.desc similarity index 100% rename from regression/modular/nocex1/test.desc rename to regression/spurious-check-abstract/nocex1/test.desc diff --git a/regression/spurious-check-abstract/nocex10/main.c b/regression/spurious-check-abstract/nocex10/main.c new file mode 100644 index 000000000..5e3d522a4 --- /dev/null +++ b/regression/spurious-check-abstract/nocex10/main.c @@ -0,0 +1,11 @@ +#include + +void main() +{ + int x = 0; + int y = 0; + + while(y<10); + + assert(x==11); +} diff --git a/regression/spurious-check-abstract/nocex10/test.desc b/regression/spurious-check-abstract/nocex10/test.desc new file mode 100644 index 000000000..329fdf02a --- /dev/null +++ b/regression/spurious-check-abstract/nocex10/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--havoc --no-propagation +^EXIT=5$ +^SIGNAL=0$ +^VERIFICATION INCONCLUSIVE$ diff --git a/regression/spurious-check-abstract/nocex2/main.c b/regression/spurious-check-abstract/nocex2/main.c new file mode 100644 index 000000000..100ddaec6 --- /dev/null +++ b/regression/spurious-check-abstract/nocex2/main.c @@ -0,0 +1,16 @@ + +#include + +void foo(int x) +{ + assert(x==5); +} + +int main(int argc, char** argv) +{ + int y = 5; + foo(y); + + return 0; +} + diff --git a/regression/modular/nocex2/test.desc b/regression/spurious-check-abstract/nocex2/test.desc similarity index 100% rename from regression/modular/nocex2/test.desc rename to regression/spurious-check-abstract/nocex2/test.desc diff --git a/regression/spurious-check-abstract/nocex3/main.c b/regression/spurious-check-abstract/nocex3/main.c new file mode 100644 index 000000000..257e8fc7a --- /dev/null +++ b/regression/spurious-check-abstract/nocex3/main.c @@ -0,0 +1,18 @@ + +#include + +int bar(){ + return 1; +} + +void foo(int x) { + assert(x != 5); +} + +int main() { + int y = bar(); + foo(y); + return 0; +} + + diff --git a/regression/modular/nocex3/test.desc b/regression/spurious-check-abstract/nocex3/test.desc similarity index 100% rename from regression/modular/nocex3/test.desc rename to regression/spurious-check-abstract/nocex3/test.desc diff --git a/regression/spurious-check-abstract/nocex4/main.c b/regression/spurious-check-abstract/nocex4/main.c new file mode 100644 index 000000000..4e96e8e89 --- /dev/null +++ b/regression/spurious-check-abstract/nocex4/main.c @@ -0,0 +1,20 @@ + +#include + +int bar(int k){ + return (k+1); +} + +void foo(int x) { + x = bar(x); + assert(x>5); +} + +int main() { + int y; + __CPROVER_assume(y<100000); + if(y > 10) foo(y); + return 0; +} + + diff --git a/regression/modular/nocex4/test.desc b/regression/spurious-check-abstract/nocex4/test.desc similarity index 100% rename from regression/modular/nocex4/test.desc rename to regression/spurious-check-abstract/nocex4/test.desc diff --git a/regression/spurious-check-abstract/nocex5/main.c b/regression/spurious-check-abstract/nocex5/main.c new file mode 100644 index 000000000..b225c7ce8 --- /dev/null +++ b/regression/spurious-check-abstract/nocex5/main.c @@ -0,0 +1,30 @@ + +#include + +int foobar(int a){ + int i; + if(i < a) + return i+a; + else + return i-a; +} + +int bar(int k){ + return (k+1); +} + +void foo(int x, int s) { + int m; + s = foobar(m); + x = bar(x); + assert(x>5); +} + +int main() { + int y,k; + __CPROVER_assume(y<100000); + if(y > 10) foo(y,k); + return 0; +} + + diff --git a/regression/modular/nocex5/test.desc b/regression/spurious-check-abstract/nocex5/test.desc similarity index 100% rename from regression/modular/nocex5/test.desc rename to regression/spurious-check-abstract/nocex5/test.desc diff --git a/regression/spurious-check-abstract/nocex6/main.c b/regression/spurious-check-abstract/nocex6/main.c new file mode 100644 index 000000000..309c06dd9 --- /dev/null +++ b/regression/spurious-check-abstract/nocex6/main.c @@ -0,0 +1,15 @@ + +#include + +int main(int argc, char** argv) +{ + int y = 1; + + while(y<30){ + y++; + assert(y<5); + } + + return 0; +} + diff --git a/regression/modular/nocex6/test.desc b/regression/spurious-check-abstract/nocex6/test.desc similarity index 100% rename from regression/modular/nocex6/test.desc rename to regression/spurious-check-abstract/nocex6/test.desc diff --git a/regression/spurious-check-abstract/nocex8/main.c b/regression/spurious-check-abstract/nocex8/main.c new file mode 100644 index 000000000..d9ee4be0c --- /dev/null +++ b/regression/spurious-check-abstract/nocex8/main.c @@ -0,0 +1,16 @@ + +#include + +void fail(void) +{ + assert(0); +} + +int main(void) +{ + int tmp = 0; + if(tmp) + fail(); + return 0; +} + diff --git a/regression/modular/nocex8/test.desc b/regression/spurious-check-abstract/nocex8/test.desc similarity index 100% rename from regression/modular/nocex8/test.desc rename to regression/spurious-check-abstract/nocex8/test.desc diff --git a/regression/spurious-check-abstract/nocex9/main.c b/regression/spurious-check-abstract/nocex9/main.c new file mode 100644 index 000000000..47067bc2f --- /dev/null +++ b/regression/spurious-check-abstract/nocex9/main.c @@ -0,0 +1,11 @@ +#include + +void main() +{ + int x = 0; + int y = 0; + + while(y<10) { x++; } + + assert(x==11); +} diff --git a/regression/spurious-check-abstract/nocex9/test.desc b/regression/spurious-check-abstract/nocex9/test.desc new file mode 100644 index 000000000..329fdf02a --- /dev/null +++ b/regression/spurious-check-abstract/nocex9/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--havoc --no-propagation +^EXIT=5$ +^SIGNAL=0$ +^VERIFICATION INCONCLUSIVE$ diff --git a/regression/modular/Makefile b/regression/spurious-check-complete/Makefile similarity index 100% rename from regression/modular/Makefile rename to regression/spurious-check-complete/Makefile diff --git a/regression/spurious-check-complete/cex-struct1/main.c b/regression/spurious-check-complete/cex-struct1/main.c new file mode 100644 index 000000000..a9a9139fa --- /dev/null +++ b/regression/spurious-check-complete/cex-struct1/main.c @@ -0,0 +1,180 @@ + +#include +#include + +typedef struct{ int x; int y; int z; int w; int p; int q; int a; } foo; + +foo func_1(foo f); +foo func_2(foo f); +foo func_3(foo f); +foo func_4(foo f); +foo func_5(foo f); +foo func_6(foo f); +foo func_7(foo f); +foo func_8(foo f); + +foo func_1(foo f) +{ + f.x = 23 + 12; + f.x = 4 - 1; + if(f.w > f.x) {f.q = 21 * f.z;} else {f.q = 4 / f.p;} + f.a = f.a + 1; + f.z = f.y * f.x; + f.x = 11 - f.p; + f.y = 1 - 19; + f.y = f.w - 14; + return f; +} + +/**********************************************************************/ + +foo func_2(foo f) +{ + if(f.y < f.q) {f.x = f.w / 24;} else {f.w = 18 / 3;} + f.w = f.p * f.q; + if(f.q < 6) {f.y = 25 - f.x;} else {f.q = f.y / f.w;} + f.a = f.a + 1; + if(f.x <= f.x) {f.z = 9 + f.x;} else {f.y = 1 + f.x;} + f.x = f.q / 25; + f.w = f.x - f.y; + f.x = 9 + f.y; + f.y = 24 - 2; + f.w = 10 + f.z; + return f; +} + +/**********************************************************************/ + +foo func_3(foo f) +{ + if(f.p == 12) {f.w = 22 + 7;} else {f.p = f.x + f.q;} + f.y = f.p + f.x; + f.w = 6 * f.y; + if(f.z <= 20) {f.q = 21 / 24;} else {f.w = f.q * f.w;} + f.w = f.y - 10; + f.q = 2 - 20; + f.x = f.x / 10; + f.p = 16 * 23; + f.w = 18 - 13; + f.w = f.p - 2; + f.z = 7 + f.w; + f.a = f.a + 1; + f.x = 16 / f.x; + return f; +} + +/**********************************************************************/ + +foo func_4(foo f) +{ + f.w = f.y + f.y; + f.q = 18 * 13; + f.y = f.z * f.y; + f.x = 1 * 25; + f.y = 4 / f.q; + f.x = f.p / 9; + f.a = f.a + 1; + if(f.x >= 7) {f.q = f.q / 8;} else {if(f.x < 9) {f.z = 16 + f.p;} else {f.x = f.w - 18;}} + f.y = 2 * 4; + f.q = 16 + f.x; + f.q = 16 * f.w; + if(f.w > 14) {f.q = 20 + 20;} else {f.x = 25 + 9;} + return f; +} + +/**********************************************************************/ + +foo func_5(foo f) +{ + f.a = f.a + 1; + if(f.x == 13) {f.p = 13 * f.x;} else {f.w = f.q / f.w;} + f.y = 21 * f.x; + f.p = 4 * 25; + if(f.p >= 24) {f.x = 11 * 6;} else {f.p = 9 * f.p;} + f.x = 3 + f.z; + f.x = f.x + 22; + f.z = 8 / 8; + f.q = 18 + f.x; + f.x = 5 * f.z; + f.y = f.w + f.w; + return f; +} + +/**********************************************************************/ + +foo func_6(foo f) +{ + f.y = f.w / f.q; + f.p = f.x + 8; + f.a = f.a + 1; + f.z = f.w * 20; + if(f.x < f.p) {f.x = f.z + 2;} else {f.y = f.y * f.x;} + if(f.y <= f.y) {f.q = f.y * f.w;} else {f.q = f.w - 13;} + f.p = 9 + f.y; + f.q = f.y / 14; + f.p = 18 / f.z; + if(f.w < f.p) {f.w = 17 * f.p;} else {f.p = f.y - 10;} + f.p = 3 / 14; + f.q = 10 - f.w; + if(f.y > 12) {f.z = f.q - 24;} else {f.x = f.z / 17;} + return f; +} + +/**********************************************************************/ + +foo func_7(foo f) +{ + f.q = f.q * 23; + f.w = 25 - f.w; + if(f.q < f.y) {f.w = 21 + f.z;} else {f.p = 16 - 1;} + f.y = f.z * f.z; + f.x = 5 * 16; + f.x = 11 + f.x; + f.z = f.y - f.y; + f.q = 11 - f.z; + f.a = f.a + 1; + return f; +} + +/**********************************************************************/ + +foo func_8(foo f) +{ + f.w = f.y - 15; + f.q = f.x + f.z; + f.y = 5 / 1; + if(f.q < 3) {f.p = 6 * f.x; } else {f.w = 8 + 21;} + f.p = 19 / f.p; + f.z = 4 / f.z; + if(f.x < 12) {f.p = f.y - 4; } else {f.x = 15 + 2;} + f.q = 19 / f.w; + if(f.p > 24) {f.z = 5 / 9;} else {f.w = f.x + f.z;} + f.z = f.z + 1; + f.a = f.a + 1; + if(f.z > f.y) {f.y = f.y + f.x;} else {f.y = 13 - 18;} + return f; +} + + +/**********************************************************************/ + +int main() +{ + foo f0, f1, f2, f3, f4, f5, f6, f7, f8; + +// __CPROVER_assume((f0.a >= 0) && (f0.a <= 9)); + f0.a = 0; + + f1 = func_1(f0); +/* f2 = func_2(f1); + f3 = func_3(f2); + f4 = func_4(f3); + f5 = func_5(f4); + f6 = func_6(f5); + f7 = func_7(f6); + f8 = func_8(f7);*/ + + assert(/*(f8.x + f8.y + f8.z + f8.w + f8.p + f8.q > 0) &&*/ (f1.a != 1)); // unsafe assertion + + return 0; +} diff --git a/regression/spurious-check-complete/cex-struct1/test.desc b/regression/spurious-check-complete/cex-struct1/test.desc new file mode 100644 index 000000000..429367b44 --- /dev/null +++ b/regression/spurious-check-complete/cex-struct1/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--havoc +^EXIT=10$ +^SIGNAL=0$ +^VERIFICATION FAILED$ diff --git a/regression/spurious-check-complete/cex-struct2/main.c b/regression/spurious-check-complete/cex-struct2/main.c new file mode 100644 index 000000000..a5d7032f4 --- /dev/null +++ b/regression/spurious-check-complete/cex-struct2/main.c @@ -0,0 +1,22 @@ + +#include +#include + +typedef struct{ int a; } foo; + +foo func_1(foo f) +{ + f.a = f.a + 1; + return f; +} + +int main() +{ + foo f0, f1; + f0.a = 0; + + f1 = func_1(f0); + + assert((f1.a) != 1); + return 0; +} diff --git a/regression/spurious-check-complete/cex-struct2/test.desc b/regression/spurious-check-complete/cex-struct2/test.desc new file mode 100644 index 000000000..429367b44 --- /dev/null +++ b/regression/spurious-check-complete/cex-struct2/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--havoc +^EXIT=10$ +^SIGNAL=0$ +^VERIFICATION FAILED$ diff --git a/regression/spurious-check-complete/cex-struct3/main.c b/regression/spurious-check-complete/cex-struct3/main.c new file mode 100644 index 000000000..1715861bf --- /dev/null +++ b/regression/spurious-check-complete/cex-struct3/main.c @@ -0,0 +1,23 @@ + +#include +#include + +typedef struct{ int x; int a; } foo; + +foo func_1(foo f) +{ + f.a = f.a + 1; + f.x = f.a; + return f; +} + +int main() +{ + foo f0, f1; + f0.a = 0; + + f1 = func_1(f0); + assert(f1.a != 1); // unsafe assertion + + return 0; +} diff --git a/regression/spurious-check-complete/cex-struct3/test.desc b/regression/spurious-check-complete/cex-struct3/test.desc new file mode 100644 index 000000000..429367b44 --- /dev/null +++ b/regression/spurious-check-complete/cex-struct3/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--havoc +^EXIT=10$ +^SIGNAL=0$ +^VERIFICATION FAILED$ diff --git a/regression/spurious-check-complete/cex1/main.c b/regression/spurious-check-complete/cex1/main.c new file mode 100644 index 000000000..53451cf50 --- /dev/null +++ b/regression/spurious-check-complete/cex1/main.c @@ -0,0 +1,15 @@ +#include + +int foo(int x) +{ + assert(x>5); +} + +int main(int argc, char** argv) +{ + int y; + if(y<=0) foo(y); + + return 0; +} + diff --git a/regression/spurious-check-complete/cex1/test.desc b/regression/spurious-check-complete/cex1/test.desc new file mode 100644 index 000000000..429367b44 --- /dev/null +++ b/regression/spurious-check-complete/cex1/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--havoc +^EXIT=10$ +^SIGNAL=0$ +^VERIFICATION FAILED$ diff --git a/regression/spurious-check-complete/cex10/main.c b/regression/spurious-check-complete/cex10/main.c new file mode 100644 index 000000000..5908a46cc --- /dev/null +++ b/regression/spurious-check-complete/cex10/main.c @@ -0,0 +1,21 @@ +#include + +int error(int k){ + assert(k != 3); +} + +int inc(int x){ + return (x+1); +}; + +int main(){ + int num = 0; + num = inc(num); + num = inc(num); + num = inc(num); + error(num); + return 0; +} + + + diff --git a/regression/spurious-check-complete/cex10/test.desc b/regression/spurious-check-complete/cex10/test.desc new file mode 100644 index 000000000..429367b44 --- /dev/null +++ b/regression/spurious-check-complete/cex10/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--havoc +^EXIT=10$ +^SIGNAL=0$ +^VERIFICATION FAILED$ diff --git a/regression/spurious-check-complete/cex13/main.c b/regression/spurious-check-complete/cex13/main.c new file mode 100644 index 000000000..242217d45 --- /dev/null +++ b/regression/spurious-check-complete/cex13/main.c @@ -0,0 +1,16 @@ + +#include + +void foo(int x) +{ + assert(x==5); +} + +int main(int argc, char** argv) +{ + int y = 4; + foo(y); + + return 0; +} + diff --git a/regression/spurious-check-complete/cex13/test.desc b/regression/spurious-check-complete/cex13/test.desc new file mode 100644 index 000000000..429367b44 --- /dev/null +++ b/regression/spurious-check-complete/cex13/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--havoc +^EXIT=10$ +^SIGNAL=0$ +^VERIFICATION FAILED$ diff --git a/regression/spurious-check-complete/cex2/main.c b/regression/spurious-check-complete/cex2/main.c new file mode 100644 index 000000000..cd18d78fc --- /dev/null +++ b/regression/spurious-check-complete/cex2/main.c @@ -0,0 +1,16 @@ + +#include + +void foo(int x) +{ + assert(x!=5); +} + +int main(int argc, char** argv) +{ + int y = 5; + foo(y); + + return 0; +} + diff --git a/regression/spurious-check-complete/cex2/test.desc b/regression/spurious-check-complete/cex2/test.desc new file mode 100644 index 000000000..429367b44 --- /dev/null +++ b/regression/spurious-check-complete/cex2/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--havoc +^EXIT=10$ +^SIGNAL=0$ +^VERIFICATION FAILED$ diff --git a/regression/spurious-check-complete/cex3/main.c b/regression/spurious-check-complete/cex3/main.c new file mode 100644 index 000000000..952a3137b --- /dev/null +++ b/regression/spurious-check-complete/cex3/main.c @@ -0,0 +1,16 @@ + +#include + +int foo(int x) +{ + assert(x!=5); +} + +int main(int argc, char** argv) +{ + int y; + if(y > 0) foo(y); + + return 0; +} + diff --git a/regression/spurious-check-complete/cex3/test.desc b/regression/spurious-check-complete/cex3/test.desc new file mode 100644 index 000000000..429367b44 --- /dev/null +++ b/regression/spurious-check-complete/cex3/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--havoc +^EXIT=10$ +^SIGNAL=0$ +^VERIFICATION FAILED$ diff --git a/regression/spurious-check-complete/cex4/main.c b/regression/spurious-check-complete/cex4/main.c new file mode 100644 index 000000000..8463fe610 --- /dev/null +++ b/regression/spurious-check-complete/cex4/main.c @@ -0,0 +1,11 @@ + +#include + +int main(int argc, char** argv) +{ + int y = 5; + assert(y != 5); + + return 0; +} + diff --git a/regression/spurious-check-complete/cex4/test.desc b/regression/spurious-check-complete/cex4/test.desc new file mode 100644 index 000000000..429367b44 --- /dev/null +++ b/regression/spurious-check-complete/cex4/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--havoc +^EXIT=10$ +^SIGNAL=0$ +^VERIFICATION FAILED$ diff --git a/regression/spurious-check-complete/cex5/main.c b/regression/spurious-check-complete/cex5/main.c new file mode 100644 index 000000000..0eabc5796 --- /dev/null +++ b/regression/spurious-check-complete/cex5/main.c @@ -0,0 +1,15 @@ +#include + +int foo(int x) +{ + assert(x>5); +} + +int main(int argc, char** argv) +{ + int y; + if(y>0) foo(y); + + return 0; +} + diff --git a/regression/spurious-check-complete/cex5/test.desc b/regression/spurious-check-complete/cex5/test.desc new file mode 100644 index 000000000..429367b44 --- /dev/null +++ b/regression/spurious-check-complete/cex5/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--havoc +^EXIT=10$ +^SIGNAL=0$ +^VERIFICATION FAILED$ diff --git a/regression/spurious-check-complete/cex6/main.c b/regression/spurious-check-complete/cex6/main.c new file mode 100644 index 000000000..80de0138d --- /dev/null +++ b/regression/spurious-check-complete/cex6/main.c @@ -0,0 +1,20 @@ + +#include + +void foo(int x) +{ + assert(x<1); +} + +int main() +{ + int y; + + while(y < 2){ + y++; + foo(y); + } + + return 0; +} + diff --git a/regression/spurious-check-complete/cex6/test.desc b/regression/spurious-check-complete/cex6/test.desc new file mode 100644 index 000000000..429367b44 --- /dev/null +++ b/regression/spurious-check-complete/cex6/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--havoc +^EXIT=10$ +^SIGNAL=0$ +^VERIFICATION FAILED$ diff --git a/regression/spurious-check-complete/cex7/main.c b/regression/spurious-check-complete/cex7/main.c new file mode 100644 index 000000000..8ab3e91f9 --- /dev/null +++ b/regression/spurious-check-complete/cex7/main.c @@ -0,0 +1,15 @@ + +#include + +int main(int argc, char** argv) +{ + int y = 1; + + while(y<30){ + y++; + assert(y<4); + } + + return 0; +} + diff --git a/regression/spurious-check-complete/cex7/test.desc b/regression/spurious-check-complete/cex7/test.desc new file mode 100644 index 000000000..696fce3b5 --- /dev/null +++ b/regression/spurious-check-complete/cex7/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--havoc --unwind 3 +^EXIT=10$ +^SIGNAL=0$ +^VERIFICATION FAILED$ diff --git a/regression/spurious-check-complete/cex8/main.c b/regression/spurious-check-complete/cex8/main.c new file mode 100644 index 000000000..3bb7e471c --- /dev/null +++ b/regression/spurious-check-complete/cex8/main.c @@ -0,0 +1,20 @@ +#include + +int error(int k){ + assert(k != 2); +} + +int inc(int x){ + return (x+1); +}; + +int main(){ + int num = 0; + num = inc(num); + num = inc(num); + error(num); + return 0; +} + + + diff --git a/regression/spurious-check-complete/cex8/test.desc b/regression/spurious-check-complete/cex8/test.desc new file mode 100644 index 000000000..429367b44 --- /dev/null +++ b/regression/spurious-check-complete/cex8/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--havoc +^EXIT=10$ +^SIGNAL=0$ +^VERIFICATION FAILED$ diff --git a/regression/spurious-check-complete/cex9/main.c b/regression/spurious-check-complete/cex9/main.c new file mode 100644 index 000000000..675f72f26 --- /dev/null +++ b/regression/spurious-check-complete/cex9/main.c @@ -0,0 +1,24 @@ +#include + +int error(int k){ + assert(k != 2); +} + +int inc(int x){ + return (x+1); +}; + +int inc_copy(int x){ + return (x+1); +}; + +int main(){ + int num = 0; + num = inc_copy(num); + num = inc(num); + error(num); + return 0; +} + + + diff --git a/regression/spurious-check-complete/cex9/test.desc b/regression/spurious-check-complete/cex9/test.desc new file mode 100644 index 000000000..429367b44 --- /dev/null +++ b/regression/spurious-check-complete/cex9/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--havoc +^EXIT=10$ +^SIGNAL=0$ +^VERIFICATION FAILED$ diff --git a/regression/spurious-check-complete/nocex1/main.c b/regression/spurious-check-complete/nocex1/main.c new file mode 100644 index 000000000..6faa3e65d --- /dev/null +++ b/regression/spurious-check-complete/nocex1/main.c @@ -0,0 +1,15 @@ +#include + +int foo(int x) +{ + assert(x>5); +} + +int main(int argc, char** argv) +{ + int y; + if(y>10) foo(y); + + return 0; +} + diff --git a/regression/modular/induction1/test.desc b/regression/spurious-check-complete/nocex1/test.desc similarity index 80% rename from regression/modular/induction1/test.desc rename to regression/spurious-check-complete/nocex1/test.desc index 34e465e33..dc053e6ab 100644 --- a/regression/modular/induction1/test.desc +++ b/regression/spurious-check-complete/nocex1/test.desc @@ -1,6 +1,6 @@ CORE main.c ---k-induction +--havoc ^EXIT=0$ ^SIGNAL=0$ ^VERIFICATION SUCCESSFUL$ diff --git a/regression/spurious-check-complete/nocex10/main.c b/regression/spurious-check-complete/nocex10/main.c new file mode 100644 index 000000000..5e3d522a4 --- /dev/null +++ b/regression/spurious-check-complete/nocex10/main.c @@ -0,0 +1,11 @@ +#include + +void main() +{ + int x = 0; + int y = 0; + + while(y<10); + + assert(x==11); +} diff --git a/regression/spurious-check-complete/nocex10/test.desc b/regression/spurious-check-complete/nocex10/test.desc new file mode 100644 index 000000000..329fdf02a --- /dev/null +++ b/regression/spurious-check-complete/nocex10/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--havoc --no-propagation +^EXIT=5$ +^SIGNAL=0$ +^VERIFICATION INCONCLUSIVE$ diff --git a/regression/spurious-check-complete/nocex2/main.c b/regression/spurious-check-complete/nocex2/main.c new file mode 100644 index 000000000..100ddaec6 --- /dev/null +++ b/regression/spurious-check-complete/nocex2/main.c @@ -0,0 +1,16 @@ + +#include + +void foo(int x) +{ + assert(x==5); +} + +int main(int argc, char** argv) +{ + int y = 5; + foo(y); + + return 0; +} + diff --git a/regression/modular/induction8/test.desc b/regression/spurious-check-complete/nocex2/test.desc similarity index 80% rename from regression/modular/induction8/test.desc rename to regression/spurious-check-complete/nocex2/test.desc index 34e465e33..dc053e6ab 100644 --- a/regression/modular/induction8/test.desc +++ b/regression/spurious-check-complete/nocex2/test.desc @@ -1,6 +1,6 @@ CORE main.c ---k-induction +--havoc ^EXIT=0$ ^SIGNAL=0$ ^VERIFICATION SUCCESSFUL$ diff --git a/regression/spurious-check-complete/nocex3/main.c b/regression/spurious-check-complete/nocex3/main.c new file mode 100644 index 000000000..257e8fc7a --- /dev/null +++ b/regression/spurious-check-complete/nocex3/main.c @@ -0,0 +1,18 @@ + +#include + +int bar(){ + return 1; +} + +void foo(int x) { + assert(x != 5); +} + +int main() { + int y = bar(); + foo(y); + return 0; +} + + diff --git a/regression/modular/loop27/test.desc b/regression/spurious-check-complete/nocex3/test.desc similarity index 80% rename from regression/modular/loop27/test.desc rename to regression/spurious-check-complete/nocex3/test.desc index 34e465e33..dc053e6ab 100644 --- a/regression/modular/loop27/test.desc +++ b/regression/spurious-check-complete/nocex3/test.desc @@ -1,6 +1,6 @@ CORE main.c ---k-induction +--havoc ^EXIT=0$ ^SIGNAL=0$ ^VERIFICATION SUCCESSFUL$ diff --git a/regression/spurious-check-complete/nocex4/main.c b/regression/spurious-check-complete/nocex4/main.c new file mode 100644 index 000000000..4e96e8e89 --- /dev/null +++ b/regression/spurious-check-complete/nocex4/main.c @@ -0,0 +1,20 @@ + +#include + +int bar(int k){ + return (k+1); +} + +void foo(int x) { + x = bar(x); + assert(x>5); +} + +int main() { + int y; + __CPROVER_assume(y<100000); + if(y > 10) foo(y); + return 0; +} + + diff --git a/regression/modular/induction4/test.desc b/regression/spurious-check-complete/nocex4/test.desc similarity index 80% rename from regression/modular/induction4/test.desc rename to regression/spurious-check-complete/nocex4/test.desc index 34e465e33..dc053e6ab 100644 --- a/regression/modular/induction4/test.desc +++ b/regression/spurious-check-complete/nocex4/test.desc @@ -1,6 +1,6 @@ CORE main.c ---k-induction +--havoc ^EXIT=0$ ^SIGNAL=0$ ^VERIFICATION SUCCESSFUL$ diff --git a/regression/spurious-check-complete/nocex5/main.c b/regression/spurious-check-complete/nocex5/main.c new file mode 100644 index 000000000..b225c7ce8 --- /dev/null +++ b/regression/spurious-check-complete/nocex5/main.c @@ -0,0 +1,30 @@ + +#include + +int foobar(int a){ + int i; + if(i < a) + return i+a; + else + return i-a; +} + +int bar(int k){ + return (k+1); +} + +void foo(int x, int s) { + int m; + s = foobar(m); + x = bar(x); + assert(x>5); +} + +int main() { + int y,k; + __CPROVER_assume(y<100000); + if(y > 10) foo(y,k); + return 0; +} + + diff --git a/regression/spurious-check-complete/nocex5/test.desc b/regression/spurious-check-complete/nocex5/test.desc new file mode 100644 index 000000000..dc053e6ab --- /dev/null +++ b/regression/spurious-check-complete/nocex5/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--havoc +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ diff --git a/regression/spurious-check-complete/nocex6/main.c b/regression/spurious-check-complete/nocex6/main.c new file mode 100644 index 000000000..309c06dd9 --- /dev/null +++ b/regression/spurious-check-complete/nocex6/main.c @@ -0,0 +1,15 @@ + +#include + +int main(int argc, char** argv) +{ + int y = 1; + + while(y<30){ + y++; + assert(y<5); + } + + return 0; +} + diff --git a/regression/spurious-check-complete/nocex6/test.desc b/regression/spurious-check-complete/nocex6/test.desc new file mode 100644 index 000000000..1f240717a --- /dev/null +++ b/regression/spurious-check-complete/nocex6/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--havoc --unwind 2 +^EXIT=5$ +^SIGNAL=0$ +^VERIFICATION INCONCLUSIVE$ diff --git a/regression/spurious-check-complete/nocex8/main.c b/regression/spurious-check-complete/nocex8/main.c new file mode 100644 index 000000000..d9ee4be0c --- /dev/null +++ b/regression/spurious-check-complete/nocex8/main.c @@ -0,0 +1,16 @@ + +#include + +void fail(void) +{ + assert(0); +} + +int main(void) +{ + int tmp = 0; + if(tmp) + fail(); + return 0; +} + diff --git a/regression/spurious-check-complete/nocex8/test.desc b/regression/spurious-check-complete/nocex8/test.desc new file mode 100644 index 000000000..dc053e6ab --- /dev/null +++ b/regression/spurious-check-complete/nocex8/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--havoc +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ diff --git a/regression/spurious-check-complete/nocex9/main.c b/regression/spurious-check-complete/nocex9/main.c new file mode 100644 index 000000000..47067bc2f --- /dev/null +++ b/regression/spurious-check-complete/nocex9/main.c @@ -0,0 +1,11 @@ +#include + +void main() +{ + int x = 0; + int y = 0; + + while(y<10) { x++; } + + assert(x==11); +} diff --git a/regression/spurious-check-complete/nocex9/test.desc b/regression/spurious-check-complete/nocex9/test.desc new file mode 100644 index 000000000..329fdf02a --- /dev/null +++ b/regression/spurious-check-complete/nocex9/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--havoc --no-propagation +^EXIT=5$ +^SIGNAL=0$ +^VERIFICATION INCONCLUSIVE$ diff --git a/regression/spurious-check-concrete/Makefile b/regression/spurious-check-concrete/Makefile new file mode 100644 index 000000000..c26b769b2 --- /dev/null +++ b/regression/spurious-check-concrete/Makefile @@ -0,0 +1,20 @@ +default: tests.log + +FLAGS = --verbosity 10 --spurious-check concrete + +test: + @../test.pl -c "../../../src/summarizer/2ls $(FLAGS)" + +tests.log: ../test.pl + @../test.pl -c "../../../src/summarizer/2ls $(FLAGS)" + +show: + @for dir in *; do \ + if [ -d "$$dir" ]; then \ + vim -o "$$dir/*.c" "$$dir/*.out"; \ + fi; \ + done; + +clean: + @rm -f *.log + @for dir in *; do rm -f $$dir/*.out; done; diff --git a/regression/spurious-check-concrete/cex-struct1/main.c b/regression/spurious-check-concrete/cex-struct1/main.c new file mode 100644 index 000000000..a9a9139fa --- /dev/null +++ b/regression/spurious-check-concrete/cex-struct1/main.c @@ -0,0 +1,180 @@ + +#include +#include + +typedef struct{ int x; int y; int z; int w; int p; int q; int a; } foo; + +foo func_1(foo f); +foo func_2(foo f); +foo func_3(foo f); +foo func_4(foo f); +foo func_5(foo f); +foo func_6(foo f); +foo func_7(foo f); +foo func_8(foo f); + +foo func_1(foo f) +{ + f.x = 23 + 12; + f.x = 4 - 1; + if(f.w > f.x) {f.q = 21 * f.z;} else {f.q = 4 / f.p;} + f.a = f.a + 1; + f.z = f.y * f.x; + f.x = 11 - f.p; + f.y = 1 - 19; + f.y = f.w - 14; + return f; +} + +/**********************************************************************/ + +foo func_2(foo f) +{ + if(f.y < f.q) {f.x = f.w / 24;} else {f.w = 18 / 3;} + f.w = f.p * f.q; + if(f.q < 6) {f.y = 25 - f.x;} else {f.q = f.y / f.w;} + f.a = f.a + 1; + if(f.x <= f.x) {f.z = 9 + f.x;} else {f.y = 1 + f.x;} + f.x = f.q / 25; + f.w = f.x - f.y; + f.x = 9 + f.y; + f.y = 24 - 2; + f.w = 10 + f.z; + return f; +} + +/**********************************************************************/ + +foo func_3(foo f) +{ + if(f.p == 12) {f.w = 22 + 7;} else {f.p = f.x + f.q;} + f.y = f.p + f.x; + f.w = 6 * f.y; + if(f.z <= 20) {f.q = 21 / 24;} else {f.w = f.q * f.w;} + f.w = f.y - 10; + f.q = 2 - 20; + f.x = f.x / 10; + f.p = 16 * 23; + f.w = 18 - 13; + f.w = f.p - 2; + f.z = 7 + f.w; + f.a = f.a + 1; + f.x = 16 / f.x; + return f; +} + +/**********************************************************************/ + +foo func_4(foo f) +{ + f.w = f.y + f.y; + f.q = 18 * 13; + f.y = f.z * f.y; + f.x = 1 * 25; + f.y = 4 / f.q; + f.x = f.p / 9; + f.a = f.a + 1; + if(f.x >= 7) {f.q = f.q / 8;} else {if(f.x < 9) {f.z = 16 + f.p;} else {f.x = f.w - 18;}} + f.y = 2 * 4; + f.q = 16 + f.x; + f.q = 16 * f.w; + if(f.w > 14) {f.q = 20 + 20;} else {f.x = 25 + 9;} + return f; +} + +/**********************************************************************/ + +foo func_5(foo f) +{ + f.a = f.a + 1; + if(f.x == 13) {f.p = 13 * f.x;} else {f.w = f.q / f.w;} + f.y = 21 * f.x; + f.p = 4 * 25; + if(f.p >= 24) {f.x = 11 * 6;} else {f.p = 9 * f.p;} + f.x = 3 + f.z; + f.x = f.x + 22; + f.z = 8 / 8; + f.q = 18 + f.x; + f.x = 5 * f.z; + f.y = f.w + f.w; + return f; +} + +/**********************************************************************/ + +foo func_6(foo f) +{ + f.y = f.w / f.q; + f.p = f.x + 8; + f.a = f.a + 1; + f.z = f.w * 20; + if(f.x < f.p) {f.x = f.z + 2;} else {f.y = f.y * f.x;} + if(f.y <= f.y) {f.q = f.y * f.w;} else {f.q = f.w - 13;} + f.p = 9 + f.y; + f.q = f.y / 14; + f.p = 18 / f.z; + if(f.w < f.p) {f.w = 17 * f.p;} else {f.p = f.y - 10;} + f.p = 3 / 14; + f.q = 10 - f.w; + if(f.y > 12) {f.z = f.q - 24;} else {f.x = f.z / 17;} + return f; +} + +/**********************************************************************/ + +foo func_7(foo f) +{ + f.q = f.q * 23; + f.w = 25 - f.w; + if(f.q < f.y) {f.w = 21 + f.z;} else {f.p = 16 - 1;} + f.y = f.z * f.z; + f.x = 5 * 16; + f.x = 11 + f.x; + f.z = f.y - f.y; + f.q = 11 - f.z; + f.a = f.a + 1; + return f; +} + +/**********************************************************************/ + +foo func_8(foo f) +{ + f.w = f.y - 15; + f.q = f.x + f.z; + f.y = 5 / 1; + if(f.q < 3) {f.p = 6 * f.x; } else {f.w = 8 + 21;} + f.p = 19 / f.p; + f.z = 4 / f.z; + if(f.x < 12) {f.p = f.y - 4; } else {f.x = 15 + 2;} + f.q = 19 / f.w; + if(f.p > 24) {f.z = 5 / 9;} else {f.w = f.x + f.z;} + f.z = f.z + 1; + f.a = f.a + 1; + if(f.z > f.y) {f.y = f.y + f.x;} else {f.y = 13 - 18;} + return f; +} + + +/**********************************************************************/ + +int main() +{ + foo f0, f1, f2, f3, f4, f5, f6, f7, f8; + +// __CPROVER_assume((f0.a >= 0) && (f0.a <= 9)); + f0.a = 0; + + f1 = func_1(f0); +/* f2 = func_2(f1); + f3 = func_3(f2); + f4 = func_4(f3); + f5 = func_5(f4); + f6 = func_6(f5); + f7 = func_7(f6); + f8 = func_8(f7);*/ + + assert(/*(f8.x + f8.y + f8.z + f8.w + f8.p + f8.q > 0) &&*/ (f1.a != 1)); // unsafe assertion + + return 0; +} diff --git a/regression/spurious-check-concrete/cex-struct1/test.desc b/regression/spurious-check-concrete/cex-struct1/test.desc new file mode 100644 index 000000000..429367b44 --- /dev/null +++ b/regression/spurious-check-concrete/cex-struct1/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--havoc +^EXIT=10$ +^SIGNAL=0$ +^VERIFICATION FAILED$ diff --git a/regression/spurious-check-concrete/cex-struct2/main.c b/regression/spurious-check-concrete/cex-struct2/main.c new file mode 100644 index 000000000..a5d7032f4 --- /dev/null +++ b/regression/spurious-check-concrete/cex-struct2/main.c @@ -0,0 +1,22 @@ + +#include +#include + +typedef struct{ int a; } foo; + +foo func_1(foo f) +{ + f.a = f.a + 1; + return f; +} + +int main() +{ + foo f0, f1; + f0.a = 0; + + f1 = func_1(f0); + + assert((f1.a) != 1); + return 0; +} diff --git a/regression/spurious-check-concrete/cex-struct2/test.desc b/regression/spurious-check-concrete/cex-struct2/test.desc new file mode 100644 index 000000000..429367b44 --- /dev/null +++ b/regression/spurious-check-concrete/cex-struct2/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--havoc +^EXIT=10$ +^SIGNAL=0$ +^VERIFICATION FAILED$ diff --git a/regression/spurious-check-concrete/cex-struct3/main.c b/regression/spurious-check-concrete/cex-struct3/main.c new file mode 100644 index 000000000..1715861bf --- /dev/null +++ b/regression/spurious-check-concrete/cex-struct3/main.c @@ -0,0 +1,23 @@ + +#include +#include + +typedef struct{ int x; int a; } foo; + +foo func_1(foo f) +{ + f.a = f.a + 1; + f.x = f.a; + return f; +} + +int main() +{ + foo f0, f1; + f0.a = 0; + + f1 = func_1(f0); + assert(f1.a != 1); // unsafe assertion + + return 0; +} diff --git a/regression/spurious-check-concrete/cex-struct3/test.desc b/regression/spurious-check-concrete/cex-struct3/test.desc new file mode 100644 index 000000000..429367b44 --- /dev/null +++ b/regression/spurious-check-concrete/cex-struct3/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--havoc +^EXIT=10$ +^SIGNAL=0$ +^VERIFICATION FAILED$ diff --git a/regression/spurious-check-concrete/cex1/main.c b/regression/spurious-check-concrete/cex1/main.c new file mode 100644 index 000000000..53451cf50 --- /dev/null +++ b/regression/spurious-check-concrete/cex1/main.c @@ -0,0 +1,15 @@ +#include + +int foo(int x) +{ + assert(x>5); +} + +int main(int argc, char** argv) +{ + int y; + if(y<=0) foo(y); + + return 0; +} + diff --git a/regression/spurious-check-concrete/cex1/test.desc b/regression/spurious-check-concrete/cex1/test.desc new file mode 100644 index 000000000..429367b44 --- /dev/null +++ b/regression/spurious-check-concrete/cex1/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--havoc +^EXIT=10$ +^SIGNAL=0$ +^VERIFICATION FAILED$ diff --git a/regression/spurious-check-concrete/cex10/main.c b/regression/spurious-check-concrete/cex10/main.c new file mode 100644 index 000000000..5908a46cc --- /dev/null +++ b/regression/spurious-check-concrete/cex10/main.c @@ -0,0 +1,21 @@ +#include + +int error(int k){ + assert(k != 3); +} + +int inc(int x){ + return (x+1); +}; + +int main(){ + int num = 0; + num = inc(num); + num = inc(num); + num = inc(num); + error(num); + return 0; +} + + + diff --git a/regression/spurious-check-concrete/cex10/test.desc b/regression/spurious-check-concrete/cex10/test.desc new file mode 100644 index 000000000..429367b44 --- /dev/null +++ b/regression/spurious-check-concrete/cex10/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--havoc +^EXIT=10$ +^SIGNAL=0$ +^VERIFICATION FAILED$ diff --git a/regression/spurious-check-concrete/cex13/main.c b/regression/spurious-check-concrete/cex13/main.c new file mode 100644 index 000000000..242217d45 --- /dev/null +++ b/regression/spurious-check-concrete/cex13/main.c @@ -0,0 +1,16 @@ + +#include + +void foo(int x) +{ + assert(x==5); +} + +int main(int argc, char** argv) +{ + int y = 4; + foo(y); + + return 0; +} + diff --git a/regression/spurious-check-concrete/cex13/test.desc b/regression/spurious-check-concrete/cex13/test.desc new file mode 100644 index 000000000..429367b44 --- /dev/null +++ b/regression/spurious-check-concrete/cex13/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--havoc +^EXIT=10$ +^SIGNAL=0$ +^VERIFICATION FAILED$ diff --git a/regression/spurious-check-concrete/cex2/main.c b/regression/spurious-check-concrete/cex2/main.c new file mode 100644 index 000000000..cd18d78fc --- /dev/null +++ b/regression/spurious-check-concrete/cex2/main.c @@ -0,0 +1,16 @@ + +#include + +void foo(int x) +{ + assert(x!=5); +} + +int main(int argc, char** argv) +{ + int y = 5; + foo(y); + + return 0; +} + diff --git a/regression/spurious-check-concrete/cex2/test.desc b/regression/spurious-check-concrete/cex2/test.desc new file mode 100644 index 000000000..429367b44 --- /dev/null +++ b/regression/spurious-check-concrete/cex2/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--havoc +^EXIT=10$ +^SIGNAL=0$ +^VERIFICATION FAILED$ diff --git a/regression/spurious-check-concrete/cex3/main.c b/regression/spurious-check-concrete/cex3/main.c new file mode 100644 index 000000000..952a3137b --- /dev/null +++ b/regression/spurious-check-concrete/cex3/main.c @@ -0,0 +1,16 @@ + +#include + +int foo(int x) +{ + assert(x!=5); +} + +int main(int argc, char** argv) +{ + int y; + if(y > 0) foo(y); + + return 0; +} + diff --git a/regression/spurious-check-concrete/cex3/test.desc b/regression/spurious-check-concrete/cex3/test.desc new file mode 100644 index 000000000..429367b44 --- /dev/null +++ b/regression/spurious-check-concrete/cex3/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--havoc +^EXIT=10$ +^SIGNAL=0$ +^VERIFICATION FAILED$ diff --git a/regression/spurious-check-concrete/cex4/main.c b/regression/spurious-check-concrete/cex4/main.c new file mode 100644 index 000000000..8463fe610 --- /dev/null +++ b/regression/spurious-check-concrete/cex4/main.c @@ -0,0 +1,11 @@ + +#include + +int main(int argc, char** argv) +{ + int y = 5; + assert(y != 5); + + return 0; +} + diff --git a/regression/spurious-check-concrete/cex4/test.desc b/regression/spurious-check-concrete/cex4/test.desc new file mode 100644 index 000000000..429367b44 --- /dev/null +++ b/regression/spurious-check-concrete/cex4/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--havoc +^EXIT=10$ +^SIGNAL=0$ +^VERIFICATION FAILED$ diff --git a/regression/spurious-check-concrete/cex5/main.c b/regression/spurious-check-concrete/cex5/main.c new file mode 100644 index 000000000..0eabc5796 --- /dev/null +++ b/regression/spurious-check-concrete/cex5/main.c @@ -0,0 +1,15 @@ +#include + +int foo(int x) +{ + assert(x>5); +} + +int main(int argc, char** argv) +{ + int y; + if(y>0) foo(y); + + return 0; +} + diff --git a/regression/spurious-check-concrete/cex5/test.desc b/regression/spurious-check-concrete/cex5/test.desc new file mode 100644 index 000000000..429367b44 --- /dev/null +++ b/regression/spurious-check-concrete/cex5/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--havoc +^EXIT=10$ +^SIGNAL=0$ +^VERIFICATION FAILED$ diff --git a/regression/spurious-check-concrete/cex6/main.c b/regression/spurious-check-concrete/cex6/main.c new file mode 100644 index 000000000..80de0138d --- /dev/null +++ b/regression/spurious-check-concrete/cex6/main.c @@ -0,0 +1,20 @@ + +#include + +void foo(int x) +{ + assert(x<1); +} + +int main() +{ + int y; + + while(y < 2){ + y++; + foo(y); + } + + return 0; +} + diff --git a/regression/spurious-check-concrete/cex6/test.desc b/regression/spurious-check-concrete/cex6/test.desc new file mode 100644 index 000000000..429367b44 --- /dev/null +++ b/regression/spurious-check-concrete/cex6/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--havoc +^EXIT=10$ +^SIGNAL=0$ +^VERIFICATION FAILED$ diff --git a/regression/spurious-check-concrete/cex7/main.c b/regression/spurious-check-concrete/cex7/main.c new file mode 100644 index 000000000..8ab3e91f9 --- /dev/null +++ b/regression/spurious-check-concrete/cex7/main.c @@ -0,0 +1,15 @@ + +#include + +int main(int argc, char** argv) +{ + int y = 1; + + while(y<30){ + y++; + assert(y<4); + } + + return 0; +} + diff --git a/regression/spurious-check-concrete/cex7/test.desc b/regression/spurious-check-concrete/cex7/test.desc new file mode 100644 index 000000000..696fce3b5 --- /dev/null +++ b/regression/spurious-check-concrete/cex7/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--havoc --unwind 3 +^EXIT=10$ +^SIGNAL=0$ +^VERIFICATION FAILED$ diff --git a/regression/spurious-check-concrete/cex8/main.c b/regression/spurious-check-concrete/cex8/main.c new file mode 100644 index 000000000..3bb7e471c --- /dev/null +++ b/regression/spurious-check-concrete/cex8/main.c @@ -0,0 +1,20 @@ +#include + +int error(int k){ + assert(k != 2); +} + +int inc(int x){ + return (x+1); +}; + +int main(){ + int num = 0; + num = inc(num); + num = inc(num); + error(num); + return 0; +} + + + diff --git a/regression/spurious-check-concrete/cex8/test.desc b/regression/spurious-check-concrete/cex8/test.desc new file mode 100644 index 000000000..429367b44 --- /dev/null +++ b/regression/spurious-check-concrete/cex8/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--havoc +^EXIT=10$ +^SIGNAL=0$ +^VERIFICATION FAILED$ diff --git a/regression/spurious-check-concrete/cex9/main.c b/regression/spurious-check-concrete/cex9/main.c new file mode 100644 index 000000000..675f72f26 --- /dev/null +++ b/regression/spurious-check-concrete/cex9/main.c @@ -0,0 +1,24 @@ +#include + +int error(int k){ + assert(k != 2); +} + +int inc(int x){ + return (x+1); +}; + +int inc_copy(int x){ + return (x+1); +}; + +int main(){ + int num = 0; + num = inc_copy(num); + num = inc(num); + error(num); + return 0; +} + + + diff --git a/regression/spurious-check-concrete/cex9/test.desc b/regression/spurious-check-concrete/cex9/test.desc new file mode 100644 index 000000000..429367b44 --- /dev/null +++ b/regression/spurious-check-concrete/cex9/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--havoc +^EXIT=10$ +^SIGNAL=0$ +^VERIFICATION FAILED$ diff --git a/regression/spurious-check-concrete/nocex1/main.c b/regression/spurious-check-concrete/nocex1/main.c new file mode 100644 index 000000000..6faa3e65d --- /dev/null +++ b/regression/spurious-check-concrete/nocex1/main.c @@ -0,0 +1,15 @@ +#include + +int foo(int x) +{ + assert(x>5); +} + +int main(int argc, char** argv) +{ + int y; + if(y>10) foo(y); + + return 0; +} + diff --git a/regression/spurious-check-concrete/nocex1/test.desc b/regression/spurious-check-concrete/nocex1/test.desc new file mode 100644 index 000000000..dc053e6ab --- /dev/null +++ b/regression/spurious-check-concrete/nocex1/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--havoc +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ diff --git a/regression/spurious-check-concrete/nocex10/main.c b/regression/spurious-check-concrete/nocex10/main.c new file mode 100644 index 000000000..5e3d522a4 --- /dev/null +++ b/regression/spurious-check-concrete/nocex10/main.c @@ -0,0 +1,11 @@ +#include + +void main() +{ + int x = 0; + int y = 0; + + while(y<10); + + assert(x==11); +} diff --git a/regression/spurious-check-concrete/nocex10/test.desc b/regression/spurious-check-concrete/nocex10/test.desc new file mode 100644 index 000000000..329fdf02a --- /dev/null +++ b/regression/spurious-check-concrete/nocex10/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--havoc --no-propagation +^EXIT=5$ +^SIGNAL=0$ +^VERIFICATION INCONCLUSIVE$ diff --git a/regression/spurious-check-concrete/nocex2/main.c b/regression/spurious-check-concrete/nocex2/main.c new file mode 100644 index 000000000..100ddaec6 --- /dev/null +++ b/regression/spurious-check-concrete/nocex2/main.c @@ -0,0 +1,16 @@ + +#include + +void foo(int x) +{ + assert(x==5); +} + +int main(int argc, char** argv) +{ + int y = 5; + foo(y); + + return 0; +} + diff --git a/regression/spurious-check-concrete/nocex2/test.desc b/regression/spurious-check-concrete/nocex2/test.desc new file mode 100644 index 000000000..dc053e6ab --- /dev/null +++ b/regression/spurious-check-concrete/nocex2/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--havoc +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ diff --git a/regression/spurious-check-concrete/nocex3/main.c b/regression/spurious-check-concrete/nocex3/main.c new file mode 100644 index 000000000..257e8fc7a --- /dev/null +++ b/regression/spurious-check-concrete/nocex3/main.c @@ -0,0 +1,18 @@ + +#include + +int bar(){ + return 1; +} + +void foo(int x) { + assert(x != 5); +} + +int main() { + int y = bar(); + foo(y); + return 0; +} + + diff --git a/regression/spurious-check-concrete/nocex3/test.desc b/regression/spurious-check-concrete/nocex3/test.desc new file mode 100644 index 000000000..dc053e6ab --- /dev/null +++ b/regression/spurious-check-concrete/nocex3/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--havoc +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ diff --git a/regression/spurious-check-concrete/nocex4/main.c b/regression/spurious-check-concrete/nocex4/main.c new file mode 100644 index 000000000..4e96e8e89 --- /dev/null +++ b/regression/spurious-check-concrete/nocex4/main.c @@ -0,0 +1,20 @@ + +#include + +int bar(int k){ + return (k+1); +} + +void foo(int x) { + x = bar(x); + assert(x>5); +} + +int main() { + int y; + __CPROVER_assume(y<100000); + if(y > 10) foo(y); + return 0; +} + + diff --git a/regression/spurious-check-concrete/nocex4/test.desc b/regression/spurious-check-concrete/nocex4/test.desc new file mode 100644 index 000000000..dc053e6ab --- /dev/null +++ b/regression/spurious-check-concrete/nocex4/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--havoc +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ diff --git a/regression/spurious-check-concrete/nocex5/main.c b/regression/spurious-check-concrete/nocex5/main.c new file mode 100644 index 000000000..b225c7ce8 --- /dev/null +++ b/regression/spurious-check-concrete/nocex5/main.c @@ -0,0 +1,30 @@ + +#include + +int foobar(int a){ + int i; + if(i < a) + return i+a; + else + return i-a; +} + +int bar(int k){ + return (k+1); +} + +void foo(int x, int s) { + int m; + s = foobar(m); + x = bar(x); + assert(x>5); +} + +int main() { + int y,k; + __CPROVER_assume(y<100000); + if(y > 10) foo(y,k); + return 0; +} + + diff --git a/regression/spurious-check-concrete/nocex5/test.desc b/regression/spurious-check-concrete/nocex5/test.desc new file mode 100644 index 000000000..dc053e6ab --- /dev/null +++ b/regression/spurious-check-concrete/nocex5/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--havoc +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ diff --git a/regression/spurious-check-concrete/nocex6/main.c b/regression/spurious-check-concrete/nocex6/main.c new file mode 100644 index 000000000..309c06dd9 --- /dev/null +++ b/regression/spurious-check-concrete/nocex6/main.c @@ -0,0 +1,15 @@ + +#include + +int main(int argc, char** argv) +{ + int y = 1; + + while(y<30){ + y++; + assert(y<5); + } + + return 0; +} + diff --git a/regression/spurious-check-concrete/nocex6/test.desc b/regression/spurious-check-concrete/nocex6/test.desc new file mode 100644 index 000000000..1f240717a --- /dev/null +++ b/regression/spurious-check-concrete/nocex6/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--havoc --unwind 2 +^EXIT=5$ +^SIGNAL=0$ +^VERIFICATION INCONCLUSIVE$ diff --git a/regression/spurious-check-concrete/nocex8/main.c b/regression/spurious-check-concrete/nocex8/main.c new file mode 100644 index 000000000..d9ee4be0c --- /dev/null +++ b/regression/spurious-check-concrete/nocex8/main.c @@ -0,0 +1,16 @@ + +#include + +void fail(void) +{ + assert(0); +} + +int main(void) +{ + int tmp = 0; + if(tmp) + fail(); + return 0; +} + diff --git a/regression/spurious-check-concrete/nocex8/test.desc b/regression/spurious-check-concrete/nocex8/test.desc new file mode 100644 index 000000000..dc053e6ab --- /dev/null +++ b/regression/spurious-check-concrete/nocex8/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--havoc +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ diff --git a/regression/spurious-check-concrete/nocex9/main.c b/regression/spurious-check-concrete/nocex9/main.c new file mode 100644 index 000000000..47067bc2f --- /dev/null +++ b/regression/spurious-check-concrete/nocex9/main.c @@ -0,0 +1,11 @@ +#include + +void main() +{ + int x = 0; + int y = 0; + + while(y<10) { x++; } + + assert(x==11); +} diff --git a/regression/spurious-check-concrete/nocex9/test.desc b/regression/spurious-check-concrete/nocex9/test.desc new file mode 100644 index 000000000..329fdf02a --- /dev/null +++ b/regression/spurious-check-concrete/nocex9/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--havoc --no-propagation +^EXIT=5$ +^SIGNAL=0$ +^VERIFICATION INCONCLUSIVE$ diff --git a/src/summarizer/summary_checker_kind.cpp b/src/summarizer/summary_checker_kind.cpp index 7a4fed218..895b1a49d 100644 --- a/src/summarizer/summary_checker_kind.cpp +++ b/src/summarizer/summary_checker_kind.cpp @@ -62,6 +62,7 @@ property_checkert::resultt summary_checker_kindt::operator()( if((options.get_option("spurious-check")!="concrete") && (options.get_option("spurious-check")!="abstract")) { + //TODO: update only those that were refined by unwinding SSA_dependency_graphs(goto_model, ns); } } From 7beec891de429bc01b4f210e8f069b9e42d9654f Mon Sep 17 00:00:00 2001 From: Peter Schrammel Date: Sat, 17 Sep 2016 17:29:59 +0100 Subject: [PATCH 68/82] partial upgrade to new cbmc version --- src/summarizer/preprocessing_util.cpp | 254 ++++++------ src/summarizer/summarizer_parse_options.cpp | 407 +++++++++++++++----- src/summarizer/summarizer_parse_options.h | 5 +- 3 files changed, 449 insertions(+), 217 deletions(-) diff --git a/src/summarizer/preprocessing_util.cpp b/src/summarizer/preprocessing_util.cpp index a6b125135..59f7a825e 100644 --- a/src/summarizer/preprocessing_util.cpp +++ b/src/summarizer/preprocessing_util.cpp @@ -1,12 +1,13 @@ #include #include #include -#include -#include "../ssa/const_propagator.h" +#include +#include #include "summarizer_parse_options.h" + /*******************************************************************\ Function: summarizer_parse_optionst::inline_main @@ -95,13 +96,13 @@ void summarizer_parse_optionst::nondet_locals(goto_modelt &goto_model) { if(i_it->is_decl()) { - const code_declt& decl = to_code_decl(i_it->code); + const code_declt& decl = to_code_decl(i_it->code); side_effect_expr_nondett nondet(decl.symbol().type()); - goto_programt::targett t = f_it->second.body.insert_after(i_it); - t->make_assignment(); - code_assignt c(decl.symbol(),nondet); - t->code.swap(c); - t->source_location = i_it->source_location; + goto_programt::targett t = f_it->second.body.insert_after(i_it); + t->make_assignment(); + code_assignt c(decl.symbol(),nondet); + t->code.swap(c); + t->source_location = i_it->source_location; } } } @@ -120,61 +121,64 @@ Function: goto_unwind \*******************************************************************/ -void summarizer_parse_optionst::goto_unwind(goto_modelt &goto_model, unsigned k) +void summarizer_parse_optionst::unwind(goto_modelt &goto_model, unsigned k) { - - typedef std::vector > loopst; +goto_unwind(goto_model.goto_functions, k); - Forall_goto_functions(f_it, goto_model.goto_functions) - { - goto_programt &body=f_it->second.body; +#if 0 +typedef std::vector > loopst; + +Forall_goto_functions(f_it, goto_model.goto_functions) +{ +goto_programt &body=f_it->second.body; - loopst loops; - Forall_goto_program_instructions(i_it, body) - { - if(i_it->is_backwards_goto()) - { - goto_programt::targett loop_head = i_it->get_target(); - goto_programt::targett loop_exit = i_it; - bool has_goto_into_loop = false; +loopst loops; +Forall_goto_program_instructions(i_it, body) +{ +if(i_it->is_backwards_goto()) +{ +goto_programt::targett loop_head = i_it->get_target(); +goto_programt::targett loop_exit = i_it; +bool has_goto_into_loop = false; - goto_programt::targett it = loop_head; - if(it!=loop_exit) it++; - for(; it!=loop_exit; it++) - { - for( std::set::iterator - s_it = it->incoming_edges.begin(); - s_it!=it->incoming_edges.end(); ++s_it) - { - if((*s_it)->is_goto() && - (*s_it)->location_number < loop_head->location_number) - { - has_goto_into_loop = true; - break; - } - } - if(has_goto_into_loop) break; - } - if(has_goto_into_loop) - { - status() << "Unwinding jump into loop" << eom; - loops.push_back(loopst::value_type(++loop_exit,loop_head)); - } - } - } +goto_programt::targett it = loop_head; +if(it!=loop_exit) it++; +for(; it!=loop_exit; it++) +{ +for( std::set::iterator +s_it = it->incoming_edges.begin(); +s_it!=it->incoming_edges.end(); ++s_it) +{ +if((*s_it)->is_goto() && +(*s_it)->location_number < loop_head->location_number) +{ +has_goto_into_loop = true; +break; +} +} +if(has_goto_into_loop) break; +} +if(has_goto_into_loop) +{ +status() << "Unwinding jump into loop" << eom; +loops.push_back(loopst::value_type(++loop_exit,loop_head)); +} +} +} - for(loopst::iterator l_it = loops.begin(); l_it != loops.end(); ++l_it) - { - std::vector iteration_points; - unwind(body,l_it->second,l_it->first,k,iteration_points); - assert(iteration_points.size()==2); - goto_programt::targett t=body.insert_before(l_it->first); - t->make_goto(); - t->targets.push_back(iteration_points.front()); - } - } - goto_model.goto_functions.update(); - goto_model.goto_functions.compute_loop_numbers(); +for(loopst::iterator l_it = loops.begin(); l_it != loops.end(); ++l_it) +{ +std::vector iteration_points; +unwind(body,l_it->second,l_it->first,k,iteration_points); +assert(iteration_points.size()==2); +goto_programt::targett t=body.insert_before(l_it->first); +t->make_goto(); +t->targets.push_back(iteration_points.front()); +} +} +goto_model.goto_functions.update(); +goto_model.goto_functions.compute_loop_numbers(); +#endif } /*******************************************************************\ @@ -191,75 +195,75 @@ Function: remove_multiple_dereferences void summarizer_parse_optionst::remove_multiple_dereferences(goto_modelt &goto_model, goto_programt &body, goto_programt::targett t, exprt &expr, unsigned &var_counter, bool deref_seen) { - if(expr.id()==ID_member) - { - member_exprt &member_expr = to_member_expr(expr); - if(member_expr.compound().id()==ID_dereference) - { - dereference_exprt &deref_expr = to_dereference_expr(member_expr.compound()); - remove_multiple_dereferences(goto_model,body,t,deref_expr.pointer(),var_counter,true); - if(deref_seen) - { - symbolt new_symbol; - new_symbol.type=member_expr.type(); - new_symbol.name="$deref"+i2string(var_counter++); - new_symbol.base_name=new_symbol.name; - new_symbol.pretty_name=new_symbol.name; - goto_model.symbol_table.add(new_symbol); - goto_programt::targett t_new = body.insert_before(t); - t_new->make_assignment(); - t_new->code = code_assignt(new_symbol.symbol_expr(),member_expr); - expr = new_symbol.symbol_expr(); - for(std::set::iterator t_it = - t->incoming_edges.begin(); - t_it != t->incoming_edges.end(); ++t_it) - { - (*t_it)->targets.clear(); - (*t_it)->targets.push_back(t_new); - } - body.compute_location_numbers(); - body.compute_target_numbers(); - body.compute_incoming_edges(); - } - } - else - Forall_operands(o_it,expr) - remove_multiple_dereferences(goto_model,body,t,*o_it,var_counter,deref_seen); - } - else - Forall_operands(o_it,expr) - remove_multiple_dereferences(goto_model,body,t,*o_it,var_counter,deref_seen); +if(expr.id()==ID_member) +{ +member_exprt &member_expr = to_member_expr(expr); +if(member_expr.compound().id()==ID_dereference) +{ +dereference_exprt &deref_expr = to_dereference_expr(member_expr.compound()); +remove_multiple_dereferences(goto_model,body,t,deref_expr.pointer(),var_counter,true); +if(deref_seen) +{ +symbolt new_symbol; +new_symbol.type=member_expr.type(); +new_symbol.name="$deref"+i2string(var_counter++); +new_symbol.base_name=new_symbol.name; +new_symbol.pretty_name=new_symbol.name; +goto_model.symbol_table.add(new_symbol); +goto_programt::targett t_new = body.insert_before(t); +t_new->make_assignment(); +t_new->code = code_assignt(new_symbol.symbol_expr(),member_expr); +expr = new_symbol.symbol_expr(); +for(std::set::iterator t_it = + t->incoming_edges.begin(); +t_it != t->incoming_edges.end(); ++t_it) +{ +(*t_it)->targets.clear(); +(*t_it)->targets.push_back(t_new); +} +body.compute_location_numbers(); +body.compute_target_numbers(); +body.compute_incoming_edges(); +} +} +else + Forall_operands(o_it,expr) + remove_multiple_dereferences(goto_model,body,t,*o_it,var_counter,deref_seen); +} +else + Forall_operands(o_it,expr) + remove_multiple_dereferences(goto_model,body,t,*o_it,var_counter,deref_seen); } void summarizer_parse_optionst::remove_multiple_dereferences(goto_modelt &goto_model) { - unsigned var_counter = 0; - namespacet ns(goto_model.symbol_table); - Forall_goto_functions(f_it, goto_model.goto_functions) - { - Forall_goto_program_instructions(i_it, f_it->second.body) - { - if(i_it->is_goto()) - { - remove_multiple_dereferences(goto_model, - f_it->second.body, - i_it, - i_it->guard, - var_counter, false); - } - else if(i_it->is_assign()) - { - remove_multiple_dereferences(goto_model, - f_it->second.body, - i_it, - to_code_assign(i_it->code).lhs(), - var_counter, false); - remove_multiple_dereferences(goto_model, - f_it->second.body, - i_it, - to_code_assign(i_it->code).rhs(), - var_counter, false); - } - } - } +unsigned var_counter = 0; +namespacet ns(goto_model.symbol_table); +Forall_goto_functions(f_it, goto_model.goto_functions) +{ +Forall_goto_program_instructions(i_it, f_it->second.body) +{ +if(i_it->is_goto()) +{ +remove_multiple_dereferences(goto_model, + f_it->second.body, + i_it, + i_it->guard, + var_counter, false); +} +else if(i_it->is_assign()) +{ +remove_multiple_dereferences(goto_model, + f_it->second.body, + i_it, + to_code_assign(i_it->code).lhs(), + var_counter, false); +remove_multiple_dereferences(goto_model, + f_it->second.body, + i_it, + to_code_assign(i_it->code).rhs(), + var_counter, false); +} +} +} } diff --git a/src/summarizer/summarizer_parse_options.cpp b/src/summarizer/summarizer_parse_options.cpp index 1e9608b0b..9a5b0e7da 100644 --- a/src/summarizer/summarizer_parse_options.cpp +++ b/src/summarizer/summarizer_parse_options.cpp @@ -30,7 +30,10 @@ Author: Daniel Kroening, kroening@kroening.com #include #include #include +#include +#include #include +#include #include "array_abstraction.h" #include @@ -49,6 +52,7 @@ Author: Daniel Kroening, kroening@kroening.com #include "summary_checker_kind.h" #include "../ssa/split_loopheads.h" #include "show.h" +#include "horn_encoding.h" #define UNWIND_GOTO_INTO_LOOP 1 #define REMOVE_MULTIPLE_DEREFERENCES 1 @@ -66,8 +70,9 @@ Function: summarizer_parse_optionst::summarizer_parse_optionst \*******************************************************************/ summarizer_parse_optionst::summarizer_parse_optionst(int argc, const char **argv): - parse_options_baset(SUMMARIZER_OPTIONS, argc, argv), - language_uit("Summarizer " CBMC_VERSION, cmdline) +parse_options_baset(SUMMARIZER_OPTIONS, argc, argv), + language_uit(cmdline, ui_message_handler), + ui_message_handler(cmdline, "2LS " SUMMARIZER_VERSION) { } @@ -273,7 +278,35 @@ void summarizer_parse_optionst::get_command_line_options(optionst &options) if(cmdline.isset("sufficient")) options.set_option("sufficient", true); - // do k-induction refinement + // compute ranking functions + if(cmdline.isset("termination")) + { + options.set_option("termination", true); + options.set_option("sufficient", true); + options.set_option("std-invariants", true); + } + + if(cmdline.isset("monolithic-ranking-function")) + { + options.set_option("monolithic-ranking-function", true); + } + else options.set_option("monolithic-ranking-function", false); + + if(cmdline.isset("lexicographic-ranking-function")) + { + options.set_option("lexicographic-ranking-function", + cmdline.get_value("lexicographic-ranking-function")); + } + else options.set_option("lexicographic-ranking-function",3); + + if(cmdline.isset("max-inner-ranking-iterations")) + { + options.set_option("max-inner-ranking-iterations", + cmdline.get_value("max-inner-ranking-iterations")); + } + else options.set_option("max-inner-ranking-iterations",20); + + // do k-induction refinement if(cmdline.isset("k-induction")) { options.set_option("std-invariants", true); @@ -283,7 +316,7 @@ void summarizer_parse_optionst::get_command_line_options(optionst &options) options.set_option("unwind",UINT_MAX); } - // do incremental bmc + // do incremental bmc if(cmdline.isset("incremental-bmc")) { options.set_option("incremental-bmc", true); @@ -293,12 +326,24 @@ void summarizer_parse_optionst::get_command_line_options(optionst &options) options.set_option("unwind",UINT_MAX); } + // check for spuriousness of assertion failures + if(cmdline.isset("no-spurious-check")) + options.set_option("spurious-check", false); + else + options.set_option("spurious-check", true); + // all properties (default) if(cmdline.isset("no-all-properties")) options.set_option("all-properties", false); else options.set_option("all-properties", true); + // no all functions (default) + if(cmdline.isset("all-functions")) + options.set_option("all-functions", true); + else + options.set_option("all-functions", false); + // competition mode if(cmdline.isset("competition-mode")) { @@ -309,7 +354,7 @@ void summarizer_parse_optionst::get_command_line_options(optionst &options) // instrumentation / output if(cmdline.isset("instrument-output")) options.set_option("instrument-output", - cmdline.get_value("instrument-output")); + cmdline.get_value("instrument-output")); #ifdef SHOW_CALLING_CONTEXTS @@ -319,9 +364,16 @@ void summarizer_parse_optionst::get_command_line_options(optionst &options) throw "--show-calling-contexts only possible with --intervals"; options.set_option("show-calling-contexts", true); options.set_option("do-not-analyze-functions", - cmdline.get_value("show-calling-contexts")); + cmdline.get_value("show-calling-contexts")); } #endif + + if(cmdline.isset("show-trace")) + options.set_option("show-trace", true); + if(cmdline.isset("graphml-cex")) + options.set_option("graphml-cex", cmdline.get_value("graphml-cex")); + if(cmdline.isset("json-cex")) + options.set_option("json-cex", cmdline.get_value("json-cex")); } /*******************************************************************\ @@ -358,11 +410,10 @@ int summarizer_parse_optionst::doit() // status() << "SUMMARIZER version " SUMMARIZER_VERSION " (based on CBMC " CBMC_VERSION ")" << eom; - register_language(new_ansi_c_language); - register_language(new_cpp_language); - goto_modelt goto_model; + register_languages(); + if(get_goto_program(options, goto_model)) return 6; @@ -463,13 +514,13 @@ int summarizer_parse_optionst::doit() summary_checker_baset *summary_checker = NULL; if(!options.get_bool_option("k-induction") && !options.get_bool_option("incremental-bmc")) - summary_checker = new summary_checker_ait(options); + summary_checker = new summary_checker_ait(options); if(options.get_bool_option("k-induction") && !options.get_bool_option("incremental-bmc")) - summary_checker = new summary_checker_kindt(options); + summary_checker = new summary_checker_kindt(options); if(!options.get_bool_option("k-induction") && options.get_bool_option("incremental-bmc")) - summary_checker = new summary_checker_bmct(options); + summary_checker = new summary_checker_bmct(options); summary_checker->set_message_handler(get_message_handler()); summary_checker->simplify=!cmdline.isset("no-simplify"); @@ -481,26 +532,67 @@ int summarizer_parse_optionst::doit() std::cout << "VERIFICATION CONDITIONS:\n\n"; summary_checker->show_vcc=true; (*summary_checker)(goto_model); - retval = 0; - goto clean_up; + delete summary_checker; + return 0; + } + + if(cmdline.isset("horn-encoding")) + { + status() << "Horn-clause encoding" << eom; + namespacet ns(symbol_table); + + std::string out_file=cmdline.get_value("horn-encoding"); + + if(out_file=="-") + { + horn_encoding(goto_model, std::cout); + } + else + { +#ifdef _MSC_VER + std::ofstream out(widen(out_file).c_str()); +#else + std::ofstream out(out_file.c_str()); +#endif + + if(!out) + { + error() << "Failed to open output file " + << out_file << eom; + delete summary_checker; + return 1; + } + + horn_encoding(goto_model, out); + } + + delete summary_checker; + return 0; } + bool report_assertions = + !options.get_bool_option("preconditions") && + !options.get_bool_option("termination"); // do actual analysis switch((*summary_checker)(goto_model)) { case property_checkert::PASS: - report_properties(goto_model, summary_checker->property_map); + if(report_assertions) + report_properties(options,goto_model, summary_checker->property_map); report_success(); retval = 0; break; case property_checkert::FAIL: - report_properties(goto_model, summary_checker->property_map); + if(report_assertions) + report_properties(options,goto_model, summary_checker->property_map); report_failure(); retval = 10; break; case property_checkert::UNKNOWN: + if(report_assertions) + report_properties(options,goto_model, summary_checker->property_map); retval = 5; if(options.get_bool_option("preconditions")) goto clean_up; @@ -534,20 +626,20 @@ int summarizer_parse_optionst::doit() return 8; } - #if 0 +#if 0 // let's log some more statistics debug() << "Memory consumption:" << messaget::endl; memory_info(debug()); debug() << eom; - #endif +#endif } void summarizer_parse_optionst::type_stats_rec( - const typet &type, - expr_statst &stats, - const namespacet &ns) + const typet &type, + expr_statst &stats, + const namespacet &ns) { if(type.id()==ID_symbol) @@ -590,8 +682,8 @@ Function: summarizer_parse_optionst::expr_stats_rec void summarizer_parse_optionst::expr_stats_rec( - const exprt &expr, - expr_statst &stats) + const exprt &expr, + expr_statst &stats) { if(expr.id()==ID_side_effect) @@ -637,7 +729,7 @@ Function: summarizer_parse_optionst::show_stats \*******************************************************************/ void summarizer_parse_optionst::show_stats(const goto_modelt &goto_model, - std::ostream &out) + std::ostream &out) { const namespacet ns(goto_model.symbol_table); @@ -663,9 +755,9 @@ void summarizer_parse_optionst::show_stats(const goto_modelt &goto_model, #endif for(goto_programt::instructionst::const_iterator - i_it=goto_program.instructions.begin(); - i_it!=goto_program.instructions.end(); - i_it++) + i_it=goto_program.instructions.begin(); + i_it!=goto_program.instructions.end(); + i_it++) { nr_instructions++; const goto_programt::instructiont &instruction=*i_it; @@ -674,32 +766,32 @@ void summarizer_parse_optionst::show_stats(const goto_modelt &goto_model, switch(instruction.type) { - case ASSIGN: - { - const code_assignt &assign=to_code_assign(instruction.code); - expr_stats_rec(assign.lhs(), stats); - expr_stats_rec(assign.rhs(), stats); - } - break; - case ASSUME: - expr_stats_rec(instruction.guard, stats); - break; - case ASSERT: - expr_stats_rec(instruction.guard, stats); - break; - case GOTO: - expr_stats_rec(instruction.guard, stats); - break; + case ASSIGN: + { + const code_assignt &assign=to_code_assign(instruction.code); + expr_stats_rec(assign.lhs(), stats); + expr_stats_rec(assign.rhs(), stats); + } + break; + case ASSUME: + expr_stats_rec(instruction.guard, stats); + break; + case ASSERT: + expr_stats_rec(instruction.guard, stats); + break; + case GOTO: + expr_stats_rec(instruction.guard, stats); + break; - case DECL: - // someone declaring an array - type_stats_rec(to_code_decl(instruction.code).symbol().type(), stats, ns); + case DECL: + // someone declaring an array + type_stats_rec(to_code_decl(instruction.code).symbol().type(), stats, ns); - break; + break; - default: - // skip - break; + default: + // skip + break; } // switch } // forall instructions } // forall functions @@ -756,6 +848,27 @@ bool summarizer_parse_optionst::set_properties(goto_modelt &goto_model) /*******************************************************************\ +Function: summarizer_parse_optionst::require_entry + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +void summarizer_parse_optionst::require_entry( + const goto_modelt &goto_model) +{ + irep_idt entry_point=goto_model.goto_functions.entry_point(); + + if(goto_model.symbol_table.symbols.find(entry_point)==symbol_table.symbols.end()) + throw "The program has no entry point; please complete linking"; +} + +/*******************************************************************\ + Function: summarizer_parse_optionst::get_goto_program Inputs: @@ -784,7 +897,7 @@ bool summarizer_parse_optionst::get_goto_program( status() << "Reading GOTO program from file" << eom; if(read_goto_binary(cmdline.args[0], - goto_model, get_message_handler())) + goto_model, get_message_handler())) return true; config.set_from_symbol_table(goto_model.symbol_table); @@ -813,11 +926,11 @@ bool summarizer_parse_optionst::get_goto_program( std::string filename=cmdline.args[0]; - #ifdef _MSC_VER +#ifdef _MSC_VER std::ifstream infile(widen(filename).c_str()); - #else +#else std::ifstream infile(filename.c_str()); - #endif +#endif if(!infile) { @@ -862,6 +975,7 @@ bool summarizer_parse_optionst::get_goto_program( return true; } +#if 0 irep_idt entry_point=goto_model.goto_functions.entry_point(); if(symbol_table.symbols.find(entry_point)==symbol_table.symbols.end()) @@ -869,6 +983,7 @@ bool summarizer_parse_optionst::get_goto_program( error() << "No entry point; please provide a main function" << eom; return true; } +#endif status() << "Generating GOTO Program" << eom; @@ -939,9 +1054,9 @@ bool summarizer_parse_optionst::process_goto_program( Forall_goto_functions(f_it, goto_model.goto_functions) if(f_it->first!=ID__start && f_it->second.body.instructions.size()<=2*(limit/2)) - { + { f_it->second.body.clear(); - } + } } // add generic checks @@ -976,16 +1091,41 @@ bool summarizer_parse_optionst::process_goto_program( } #if UNWIND_GOTO_INTO_LOOP - goto_unwind(goto_model,2); + unwind(goto_model,2); #endif // now do full inlining, if requested if(options.get_bool_option("inline")) { status() << "Performing full inlining" << eom; - goto_inline(goto_model, ui_message_handler); + if(goto_inline(goto_model, ui_message_handler)) + { + report_unknown(); + return 5; + } } + //preprocessing to improve the structure of the SSA for the unwinder + split_loopheads(goto_model); + + //explicitly initialize all local variables + nondet_locals(goto_model); + +#if 1 + //TODO: find a better place for that + replace_malloc(goto_model,""); +#endif + +#if REMOVE_MULTIPLE_DEREFERENCES + remove_multiple_dereferences(goto_model); +#endif + + // recalculate numbers, etc. + goto_model.goto_functions.update(); + + // add loop ids + goto_model.goto_functions.compute_loop_numbers(); + //inline __CPROVER_initialize and main if(cmdline.isset("inline-main")) { @@ -1078,7 +1218,7 @@ void summarizer_parse_optionst::report_properties( const property_checkert::property_mapt &property_map) { for(property_checkert::property_mapt::const_iterator - it=property_map.begin(); + it=property_map.begin(); it!=property_map.end(); it++) { @@ -1104,6 +1244,14 @@ void summarizer_parse_optionst::report_properties( if(cmdline.isset("show-trace") && it->second.result==property_checkert::FAIL) show_counterexample(goto_model, it->second.error_trace); + if(cmdline.isset("graphml-cex") && + it->second.result==property_checkert::FAIL) + output_graphml_cex(options,goto_model, it->second.error_trace); + if(cmdline.isset("json-cex") && + it->second.result==property_checkert::FAIL) + output_json_cex(options, + goto_model, it->second.error_trace, + id2string(it->first)); } if(!cmdline.isset("property")) @@ -1114,7 +1262,7 @@ void summarizer_parse_optionst::report_properties( unsigned unknown=0; for(property_checkert::property_mapt::const_iterator - it=property_map.begin(); + it=property_map.begin(); it!=property_map.end(); it++) { @@ -1155,13 +1303,13 @@ void summarizer_parse_optionst::report_success() break; case ui_message_handlert::XML_UI: - { - xmlt xml("cprover-status"); - xml.data="SUCCESS"; - std::cout << xml; - std::cout << std::endl; - } - break; + { + xmlt xml("cprover-status"); + xml.data="SUCCESS"; + std::cout << xml; + std::cout << std::endl; + } + break; default: assert(false); @@ -1194,12 +1342,12 @@ void summarizer_parse_optionst::show_counterexample( break; case ui_message_handlert::XML_UI: - { - xmlt xml; - convert(ns, error_trace, xml); - std::cout << xml << std::endl; - } - break; + { + xmlt xml; + convert(ns, error_trace, xml); + std::cout << xml << std::endl; + } + break; default: assert(false); @@ -1208,6 +1356,76 @@ void summarizer_parse_optionst::show_counterexample( /*******************************************************************\ +Function: summarizer_parse_optionst::output_graphml_cex + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +void summarizer_parse_optionst::output_graphml_cex( + const optionst &options, + const goto_modelt &goto_model, + const goto_tracet &error_trace) +{ + const namespacet ns(goto_model.symbol_table); + const std::string graphml=options.get_option("graphml-cex"); + if(!graphml.empty()) + { + graphmlt cex_graph; + convert(ns, error_trace, cex_graph); + + if(graphml=="-") + write_graphml(cex_graph, std::cout); + else + { + std::ofstream out(graphml.c_str()); + write_graphml(cex_graph, out); + } + } +} + +/*******************************************************************\ + +Function: summarizer_parse_optionst::output_json_cex + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +void summarizer_parse_optionst::output_json_cex( + const optionst &options, + const goto_modelt &goto_model, + const goto_tracet &error_trace, + const std::string &property_id) +{ + if(options.get_option("json-cex")!="") + { + const namespacet ns(goto_model.symbol_table); + jsont json_trace; + convert(ns, error_trace, json_trace); + + if(options.get_option("json-cex")=="-") + { + std::cout << json_trace; + } + else + { + std::ofstream out((options.get_option("json-cex")+"-"+property_id+".json").c_str()); + out << json_trace << '\n'; + } + } +} + +/*******************************************************************\ + Function: summarizer_parse_optionst::report_failure Inputs: @@ -1228,13 +1446,13 @@ void summarizer_parse_optionst::report_failure() break; case ui_message_handlert::XML_UI: - { - xmlt xml("cprover-status"); - xml.data="FAILURE"; - std::cout << xml; - std::cout << std::endl; - } - break; + { + xmlt xml("cprover-status"); + xml.data="FAILURE"; + std::cout << xml; + std::cout << std::endl; + } + break; default: assert(false); @@ -1263,13 +1481,13 @@ void summarizer_parse_optionst::report_unknown() break; case ui_message_handlert::XML_UI: - { - xmlt xml("cprover-status"); - xml.data="UNKNOWN"; - std::cout << xml; - std::cout << std::endl; - } - break; + { + xmlt xml("cprover-status"); + xml.data="UNKNOWN"; + std::cout << xml; + std::cout << std::endl; + } + break; default: assert(false); @@ -1324,12 +1542,12 @@ void summarizer_parse_optionst::help() " --show-symbol-table show symbol table\n" " --show-goto-functions show goto program\n" " --arch set architecture (default: " - << configt::this_architecture() << ")\n" + << configt::this_architecture() << ")\n" " --os set operating system (default: " - << configt::this_operating_system() << ")\n" - #ifdef _WIN32 + << configt::this_operating_system() << ")\n" +#ifdef _WIN32 " --gcc use GCC as preprocessor\n" - #endif +#endif " --no-arch don't set up an architecture\n" " --no-library disable built-in abstract C library\n" " --round-to-nearest IEEE floating point rounding mode (default)\n" @@ -1355,6 +1573,10 @@ void summarizer_parse_optionst::help() " --instrument-output f output inferred information in goto-binary f\n" "\n" "Backend options:\n" + " --all-functions check each function as entry point\n" + " --no-all-properties stop on first failing assertion\n" + " --context-sensitive context-sensitive analysis from entry point\n" + " --termination compute ranking functions to prove termination\n" " --k-induction use k-induction\n" " --unit-check check each function (similar to a unit test)\n" " --incremental-bmc use incremental-bmc\n" @@ -1369,6 +1591,9 @@ void summarizer_parse_optionst::help() " --enum-solver use solver based on model enumeration\n" " --binsearch-solver use solver based on binary search\n" " --arrays do not ignore array contents\n" + " --lexicographic-ranking-function n (default n=3)\n" + " --monolithic-ranking-function\n" + " --max-inner-ranking-iterations n (default n=20)\n" "\n" "Other options:\n" " --version show version and exit\n" diff --git a/src/summarizer/summarizer_parse_options.h b/src/summarizer/summarizer_parse_options.h index 542817efa..9e612e340 100644 --- a/src/summarizer/summarizer_parse_options.h +++ b/src/summarizer/summarizer_parse_options.h @@ -74,6 +74,9 @@ class summarizer_parse_optionst: const std::string &extra_options); protected: + ui_message_handlert ui_message_handler; + virtual void register_languages(); + void get_command_line_options(optionst &options); bool get_goto_program( @@ -131,7 +134,7 @@ class summarizer_parse_optionst: void inline_main(goto_modelt &goto_model); void propagate_constants(goto_modelt &goto_model); void nondet_locals(goto_modelt &goto_model); - void goto_unwind(goto_modelt &goto_model, unsigned k); + void unwind(goto_modelt &goto_model, unsigned k); void replace_types_rec(const replace_symbolt &replace_const, exprt &expr); exprt evaluate_casts_in_constants(const exprt &expr, const typet& parent_type, bool &valid); From f94dfc3cd98a7901e09433c1532f1d1c7c986af7 Mon Sep 17 00:00:00 2001 From: Peter Schrammel Date: Sun, 18 Sep 2016 15:56:07 +0100 Subject: [PATCH 69/82] bounds simplification --- src/domains/Makefile | 3 +- src/domains/simplify_bounds.cpp | 454 ++++++++++++++++++++ src/domains/simplify_bounds.h | 32 ++ src/domains/simplify_bounds_class.h | 66 +++ src/domains/simplify_transformer.cpp | 254 +++++++++++ src/domains/simplify_transformer.h | 35 ++ src/domains/simplify_transformer_class.h | 59 +++ src/domains/tpolyhedra_domain.cpp | 3 + src/summarizer/summarizer_parse_options.cpp | 2 +- 9 files changed, 906 insertions(+), 2 deletions(-) create mode 100644 src/domains/simplify_bounds.cpp create mode 100644 src/domains/simplify_bounds.h create mode 100644 src/domains/simplify_bounds_class.h create mode 100644 src/domains/simplify_transformer.cpp create mode 100644 src/domains/simplify_transformer.h create mode 100644 src/domains/simplify_transformer_class.h diff --git a/src/domains/Makefile b/src/domains/Makefile index 82b6a23b8..f5f1c7082 100644 --- a/src/domains/Makefile +++ b/src/domains/Makefile @@ -7,7 +7,8 @@ SRC = tpolyhedra_domain.cpp equality_domain.cpp domain.cpp predabs_domain.cpp\ template_generator_base.cpp template_generator_summary.cpp \ template_generator_callingcontext.cpp template_generator_ranking.cpp \ strategy_solver_binsearch2.cpp strategy_solver_binsearch3.cpp \ - strategy_solver_predabs.cpp + strategy_solver_predabs.cpp \ + simplify_transformer.cpp simplify_bounds.cpp #solver_enumeration.cpp include ../config.inc diff --git a/src/domains/simplify_bounds.cpp b/src/domains/simplify_bounds.cpp new file mode 100644 index 000000000..cfa64de81 --- /dev/null +++ b/src/domains/simplify_bounds.cpp @@ -0,0 +1,454 @@ +/*******************************************************************\ + +Module: Bounds simplification + +Author: Peter Schrammel + +\*******************************************************************/ + +#include + +#include "simplify_bounds.h" +#include "simplify_bounds_class.h" +#include + +#define DEBUGX + +#ifdef DEBUGX +#include +#include +#endif + +/*******************************************************************\ + +Function: simplify_boundst::get_min_bound + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +bool simplify_boundst::get_min_bound(const exprt &expr, mp_integer &value) +{ +#ifdef DEBUGX + std::cout << "get_min_bound: " << from_expr(ns, "", expr) + << "\n"; +#endif + + if(!is_bitvector_type(expr.type())) + return false; + + if(expr.id()==ID_symbol) + { + value=get_smallest(expr.type()); + return true; + } + else if(expr.id()==ID_typecast) + { + return get_min_bound(to_typecast_expr(expr).op(), value); + } + else if(expr.id()==ID_unary_minus) + { + bool result=get_max_bound(to_unary_minus_expr(expr).op(), value); + value=-value; + return result; + } + else if(expr.id()==ID_plus) + { + mp_integer vr, vl; + bool rr=get_min_bound(expr.op0(), vr); + bool rl=get_min_bound(expr.op1(), vl); + if(rr && rl) + { + value=vr+vl; + return true; + } + } + else if(expr.id()==ID_minus) + { + mp_integer vr, vl; + bool rr=get_min_bound(expr.op0(), vr); + bool rl=get_max_bound(expr.op1(), vl); + if(rr && rl) + { + value=vr-vl; + return true; + } + } + + return false; +} + +/*******************************************************************\ + +Function: simplify_boundst::get_max_bound + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +bool simplify_boundst::get_max_bound(const exprt &expr, mp_integer &value) +{ +#ifdef DEBUGX + std::cout << "get_max_bound: " << from_expr(ns, "", expr) + << "\n"; +#endif + + if(!is_bitvector_type(expr.type())) + return false; + + if(expr.id()==ID_symbol) + { + value=get_largest(expr.type()); + return true; + } + else if(expr.id()==ID_typecast) + { + return get_max_bound(to_typecast_expr(expr).op(), value); + } + else if(expr.id()==ID_unary_minus) + { + bool result=get_min_bound(to_unary_minus_expr(expr).op(), value); + value=-value; + return result; + } + else if(expr.id()==ID_plus) + { + mp_integer vr, vl; + bool rr=get_max_bound(expr.op0(), vr); + bool rl=get_max_bound(expr.op1(), vl); + if(rr && rl) + { + value=vr+vl; + return true; + } + } + else if(expr.id()==ID_minus) + { + mp_integer vr, vl; + bool rr=get_max_bound(expr.op0(), vr); + bool rl=get_min_bound(expr.op1(), vl); + if(rr && rl) + { + value=vr-vl; + return true; + } + } + + return false; +} + +/*******************************************************************\ + +Function: simplify_boundst::simplify_rec + + Inputs: + + Outputs: returns true if expression unchanged; + returns false if changed + + Purpose: + +\*******************************************************************/ + +bool simplify_boundst::simplify_rec(exprt &expr) +{ +#ifdef DEBUGX + exprt old(expr); +#endif + + bool result=true; + if(expr.id()==ID_le) + { + binary_relation_exprt &e = to_binary_relation_expr(expr); + if(is_bitvector_type(e.rhs().type()) && e.rhs().id()==ID_constant && + e.lhs().id()!=ID_symbol) + { + mp_integer rhs_value, lhs_max, lhs_min; + to_integer(e.rhs(), rhs_value); + if(get_max_bound(e.lhs(), lhs_max)) + { + if(lhs_max<=rhs_value) + { + expr=true_exprt(); + result=false; + } + else + result=clean_up_typecast(expr,rhs_value); + } + else if(get_min_bound(e.lhs(), lhs_min)) + { + if(lhs_min>rhs_value) + { + expr=false_exprt(); + result=false; + } + } + } + } + else if(expr.id()==ID_ge) + { + binary_relation_exprt &e = to_binary_relation_expr(expr); + if(is_bitvector_type(e.rhs().type()) && e.rhs().id()==ID_constant && + e.lhs().id()!=ID_symbol) + { + mp_integer rhs_value, lhs_max, lhs_min; + to_integer(e.rhs(), rhs_value); + if(get_max_bound(e.lhs(), lhs_max)) + { + if(lhs_max=rhs_value) + { + expr=true_exprt(); + result=false; + } + } + } + } + else if(expr.id()==ID_lt) + { + binary_relation_exprt &e = to_binary_relation_expr(expr); + if(is_bitvector_type(e.rhs().type()) && e.rhs().id()==ID_constant && + e.lhs().id()!=ID_symbol) + { + mp_integer rhs_value, lhs_max, lhs_min; + to_integer(e.rhs(), rhs_value); + if(get_max_bound(e.lhs(), lhs_max)) + { + if(lhs_max=rhs_value) + { + expr=false_exprt(); + result=false; + } + } + } + } + else if(expr.id()==ID_gt) + { + binary_relation_exprt &e = to_binary_relation_expr(expr); + if(is_bitvector_type(e.rhs().type()) && e.rhs().id()==ID_constant && + e.lhs().id()!=ID_symbol) + { + mp_integer rhs_value, lhs_max, lhs_min; + to_integer(e.rhs(), rhs_value); + if(get_max_bound(e.lhs(), lhs_max)) + { + if(lhs_max<=rhs_value) + { + expr=false_exprt(); + result=false; + } + } + else if(get_min_bound(e.lhs(), lhs_min)) + { + if(lhs_min>rhs_value) + { + expr=true_exprt(); + result=false; + } + } + } + } + else + { + Forall_operands(it, expr) + if(!simplify_rec(*it)) + result=false; + } +#ifdef DEBUGX + std::cout << "===== " << from_expr(ns, "", old) + << "\n ---> " << from_expr(ns, "", expr) + << "\n"; +#endif + + return result; +} + +/*******************************************************************\ + +Function: simplify_boundst::clean_up_typecast + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +bool simplify_boundst::clean_up_typecast(exprt &expr, + const mp_integer &rhs_value) +{ + if(expr.id()==ID_le && expr.op0().id()==ID_unary_minus && + expr.op0().op0().id()==ID_typecast) + { + const typet &inner_type=expr.op0().op0().op0().type(); + if(-rhs_value>get_smallest(inner_type)) + { + expr=binary_relation_exprt(expr.op0().op0().op0(), ID_ge, + from_integer(-rhs_value,inner_type)); + return true; + } + } + return false; +} + +/*******************************************************************\ + +Function: simplify_boundst::clean_up_implications + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +bool simplify_boundst::clean_up_implications(exprt &expr) +{ + bool result=true; + if(expr.id()==ID_and) + { + Forall_operands(it, expr) + if(!clean_up_implications(*it)) + result=false; + exprt::operandst::iterator it=expr.operands().begin(); + while(it!=expr.operands().end()) + { + if(it->is_true()) + it=expr.operands().erase(it); + else + ++it; + } + if(expr.operands().empty()) + expr=true_exprt(); + else if(expr.operands().size()==1) + expr=expr.op0(); + } + else if(expr.id()==ID_implies) + { + if(expr.op1().is_true()) + { + expr=true_exprt(); + result=false; + } + } + return result; +} + +/*******************************************************************\ + +Function: simplify_boundst::clean_up_implications + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +bool simplify_boundst::regroup_implications(exprt &expr) +{ + std::map implication_map; + exprt::operandst r; + if(expr.id()==ID_and) + { + Forall_operands(it, expr) + if(it->id()==ID_implies) + implication_map[it->op0()].push_back(it->op1()); + else + r.push_back(*it); + } + else + return true; + for(auto &i : implication_map) + r.push_back(implies_exprt(i.first, conjunction(i.second))); + expr=conjunction(r); + return false; +} + +/*******************************************************************\ + +Function: simplify_boundst::operator() + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +bool simplify_boundst::operator()(exprt &expr) +{ + bool result=simplify_rec(expr); + if(!clean_up_implications(expr)) + result=false; + if(!regroup_implications(expr)) + result=false; + return result; +} + +/*******************************************************************\ + +Function: simplify + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +bool simplify_bounds(exprt &expr, + const namespacet &ns) +{ + return simplify_boundst(ns)(expr); +} + +/*******************************************************************\ + +Function: simplify_bounds + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +exprt simplify_bounds(const exprt &src, + const namespacet &ns) +{ + exprt tmp=src; + simplify_boundst simplify_bounds(ns); + simplify_bounds(tmp); + return tmp; +} + diff --git a/src/domains/simplify_bounds.h b/src/domains/simplify_bounds.h new file mode 100644 index 000000000..6799b76a2 --- /dev/null +++ b/src/domains/simplify_bounds.h @@ -0,0 +1,32 @@ +/*******************************************************************\ + +Module: Bounds simplification + +Author: Peter Schrammel + +\*******************************************************************/ + +#ifndef CPROVER_SIMPLIFY_BOUNDS_H +#define CPROVER_SIMPLIFY_BOUNDS_H + +#include + +class exprt; +class namespacet; + +// +// simplify bounds +// +// true: did nothing +// false: simplified something +// + +bool simplify_bounds( + exprt &expr, + const namespacet &ns); + +exprt simplify_bounds( + const exprt &src, + const namespacet &ns); + +#endif diff --git a/src/domains/simplify_bounds_class.h b/src/domains/simplify_bounds_class.h new file mode 100644 index 000000000..3510f42ed --- /dev/null +++ b/src/domains/simplify_bounds_class.h @@ -0,0 +1,66 @@ +/*******************************************************************\ + +Module: Bounds Simplification + +Author: Peter Schrammel + +\*******************************************************************/ + +#ifndef CPROVER_SIMPLIFY_BOUNDS_CLASS_H +#define CPROVER_SIMPLIFY_BOUNDS_CLASS_H + +#include +#include + +class exprt; +class namespacet; + +class simplify_boundst +{ +public: + explicit simplify_boundst(const namespacet &_ns): + ns(_ns) + { + } + + virtual ~simplify_boundst() + { + } + + // These below all return 'true' if the simplification wasn't applicable. + // If false is returned, the expression has changed. + + virtual bool operator()(exprt &expr); + + inline static bool is_bitvector_type(const typet &type) + { + return type.id()==ID_unsignedbv || + type.id()==ID_signedbv; + } + inline static mp_integer get_largest(const typet &type) + { + if(type.id()==ID_signedbv) return to_signedbv_type(type).largest(); + else if(type.id()==ID_unsignedbv) return to_unsignedbv_type(type).largest(); + assert(false); + } + inline static mp_integer get_smallest(const typet &type) + { + if(type.id()==ID_signedbv) return to_signedbv_type(type).smallest(); + else if(type.id()==ID_unsignedbv) return to_unsignedbv_type(type).smallest(); + assert(false); + } + +protected: + const namespacet &ns; + + bool simplify_rec(exprt &expr); + bool get_min_bound(const exprt &expr, mp_integer &value); + bool get_max_bound(const exprt &expr, mp_integer &value); + + bool clean_up_implications(exprt &expr); + bool regroup_implications(exprt &expr); + bool clean_up_typecast(exprt &expr, const mp_integer &value); + +}; + +#endif diff --git a/src/domains/simplify_transformer.cpp b/src/domains/simplify_transformer.cpp new file mode 100644 index 000000000..87f43673d --- /dev/null +++ b/src/domains/simplify_transformer.cpp @@ -0,0 +1,254 @@ +/*******************************************************************\ + +Module: Transformer simplification + +Author: Peter Schrammel + +\*******************************************************************/ + +#include + +#include "simplify_transformer.h" +#include "simplify_transformer_class.h" +#include + +#define DEBUGX + +#ifdef DEBUGX +#include +#include +#endif + +/*******************************************************************\ + +Function: simplify_transformert::collect_node + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +void simplify_transformert::collect_node(const exprt &expr, + replace_mapt &substitutions, + bool frozen_only, + bool make_copy) +{ + if(expr.id()==ID_equal) + { + const equal_exprt &e = to_equal_expr(expr); + + bool rhs_is_constant=e.rhs().id()==ID_constant; + bool rhs_is_symbol=e.rhs().id()==ID_symbol || + e.rhs().id()==ID_nondet_symbol; + bool rhs_is_frozen=rhs_is_symbol && + frozen_symbols.find(e.rhs().get(ID_identifier))!=frozen_symbols.end(); + bool lhs_is_constant=e.lhs().id()==ID_constant; + bool lhs_is_symbol=e.lhs().id()==ID_symbol || + e.lhs().id()==ID_nondet_symbol; + bool lhs_is_frozen=lhs_is_symbol && + frozen_symbols.find(e.lhs().get(ID_identifier))!=frozen_symbols.end(); + + exprt lhs, rhs; + lhs.make_nil(); + rhs.make_nil(); + //stupid matching + if((rhs_is_frozen || rhs_is_constant || !frozen_only) && + lhs_is_symbol && !lhs_is_frozen) + { + lhs=e.lhs(); + rhs=e.rhs(); + } + if((lhs_is_frozen || lhs_is_constant || !frozen_only) && + rhs_is_symbol && !rhs_is_frozen) + { + rhs=e.lhs(); + lhs=e.rhs(); + } + if(rhs.is_not_nil() && lhs.is_not_nil()) + { + if(make_copy) //make lazy copy + { + replace_mapt _subst = substitutions; + substitutions = _subst; + } + substitutions[lhs]=rhs; + } + } + +#ifdef DEBUGX + std::cout << "COLLECT: " << from_expr(ns, "", expr) << std::endl; + for(const auto &it : substitutions) + std::cout << from_expr(ns, "", it.first) + << "---> " << from_expr(ns, "", it.second) + << "\n"; +#endif +} + +/*******************************************************************\ + +Function: simplify_transformert::simplify_node + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +bool simplify_transformert::simplify_node(exprt &expr, + const replace_mapt &substitutions) +{ + return replace_expr(substitutions, expr); +} + +/*******************************************************************\ + +Function: simplify_transformert::simplify_rec + + Inputs: + + Outputs: returns true if expression unchanged; + returns false if changed + + Purpose: + +\*******************************************************************/ + +bool simplify_transformert::simplify_rec(exprt &expr, + replace_mapt &substitutions) +{ +#ifdef DEBUGX + exprt old(expr); +#endif + + bool result=true; + if(expr.id()==ID_and) + { + //first propagate from frozen symbols + bool res=false; + do + { + Forall_operands(it, expr) + collect_node(*it, substitutions, true, false); + + Forall_operands(it, expr) + if(!simplify_rec(*it, substitutions)) + result=false; + + res=simplify_node(expr, substitutions); + if(!res) result=false; + } + while(!res); + + //simplify remaining equalities + Forall_operands(it, expr) + collect_node(*it, substitutions, false, false); + + res=false; + do + { + res=simplify_node(expr, substitutions); + if(!res) result=false; + } + while(!res); + } + +#if 0 //for later extension to disjunctions + //TODO: handle negation, too + else if(expr.id()==ID_or || expr.id()==ID_implies) + { + Forall_operands(it, expr) + { + collect_node(*it, substitutions, true); + if(!simplify_rec(*it, substitutions)) + result=false; + + bool res=false; + do + { + res=simplify_node(*it, substitutions); + if(!res) result=false; + } + while(!res); + } + } +#endif + +#ifdef DEBUGX + std::cout << "===== " << from_expr(ns, "", old) + << "\n ---> " << from_expr(ns, "", expr) + << "\n"; +#endif + + return result; +} + +/*******************************************************************\ + +Function: simplify_transformert::operator() + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +bool simplify_transformert::operator()(exprt &expr) +{ + replace_mapt substitutions; + return simplify_rec(expr, substitutions); +} + +/*******************************************************************\ + +Function: simplify + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +bool simplify(exprt &expr, + const std::set &frozen_vars, + const namespacet &ns) +{ + return simplify_transformert(ns, frozen_vars)(expr); +} + +/*******************************************************************\ + +Function: simplify_transformer + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +exprt simplify_transformer(const exprt &src, + const std::set &frozen_vars, + const namespacet &ns) +{ +#ifdef DEBUGX + std::cout << "FROZEN:"; + for(const auto &it : frozen_vars) + std::cout << " " << it; + std::cout << "\n"; +#endif + + exprt tmp=src; + simplify_transformert(ns, frozen_vars)(tmp); + return tmp; +} + diff --git a/src/domains/simplify_transformer.h b/src/domains/simplify_transformer.h new file mode 100644 index 000000000..32a815c8c --- /dev/null +++ b/src/domains/simplify_transformer.h @@ -0,0 +1,35 @@ +/*******************************************************************\ + +Module: Transformer simplification + +Author: Peter Schrammel + +\*******************************************************************/ + +#ifndef CPROVER_SIMPLIFY_TRANSFORMER_H +#define CPROVER_SIMPLIFY_TRANSFORMER_H + +#include +#include + +class exprt; +class namespacet; + +// +// simplify transformers by best-effort intermediate variable elimination +// +// true: did nothing +// false: simplified something +// + +bool simplify( + exprt &expr, + const std::set &frozen_vars, //do not eliminate these + const namespacet &ns); + +exprt simplify_transformer( + const exprt &src, + const std::set &frozen_vars, //do not eliminate these + const namespacet &ns); + +#endif diff --git a/src/domains/simplify_transformer_class.h b/src/domains/simplify_transformer_class.h new file mode 100644 index 000000000..ccae118b4 --- /dev/null +++ b/src/domains/simplify_transformer_class.h @@ -0,0 +1,59 @@ +/*******************************************************************\ + +Module: Transformer Simplification + +Author: Peter Schrammel + +\*******************************************************************/ + +#ifndef CPROVER_SIMPLIFY_TRANSFORMER_CLASS_H +#define CPROVER_SIMPLIFY_TRANSFORMER_CLASS_H + +#include +#include + +class exprt; +class namespacet; + +class simplify_transformert +{ +public: + explicit simplify_transformert(const namespacet &_ns, + const std::set &_frozen_symbols): + ns(_ns), + frozen_symbols(_frozen_symbols) + { + } + + virtual ~simplify_transformert() + { + } + + // These below all return 'true' if the simplification wasn't applicable. + // If false is returned, the expression has changed. + + // main recursion + bool simplify_rec(exprt &expr, replace_mapt &substitutions); + + virtual bool operator()(exprt &expr); + + inline static bool is_bitvector_type(const typet &type) + { + return type.id()==ID_unsignedbv || + type.id()==ID_signedbv || + type.id()==ID_bv; + } + +protected: + const namespacet &ns; + const std::set &frozen_symbols; + + void collect_node( + const exprt &expr, replace_mapt &substitutions, + bool frozen_only, + bool make_copy); + bool simplify_node(exprt &expr, const replace_mapt &substitutions); + +}; + +#endif diff --git a/src/domains/tpolyhedra_domain.cpp b/src/domains/tpolyhedra_domain.cpp index a7c4de1c3..e79d76229 100644 --- a/src/domains/tpolyhedra_domain.cpp +++ b/src/domains/tpolyhedra_domain.cpp @@ -18,6 +18,8 @@ Author: Peter Schrammel #include "tpolyhedra_domain.h" #include "util.h" +#include "simplify_bounds.h" + #define SYMB_BOUND_VAR "symb_bound#" #define ENABLE_HEURISTICS @@ -696,6 +698,7 @@ void tpolyhedra_domaint::project_on_vars( } } result=conjunction(c); + simplify_bounds(result, ns); } /*******************************************************************\ diff --git a/src/summarizer/summarizer_parse_options.cpp b/src/summarizer/summarizer_parse_options.cpp index 9a5b0e7da..bbc2a002c 100644 --- a/src/summarizer/summarizer_parse_options.cpp +++ b/src/summarizer/summarizer_parse_options.cpp @@ -54,7 +54,7 @@ Author: Daniel Kroening, kroening@kroening.com #include "show.h" #include "horn_encoding.h" -#define UNWIND_GOTO_INTO_LOOP 1 +#define UNWIND_GOTO_INTO_LOOP 0 #define REMOVE_MULTIPLE_DEREFERENCES 1 /*******************************************************************\ From d796c56fd7897f77095336256203599688b21e80 Mon Sep 17 00:00:00 2001 From: Peter Schrammel Date: Sat, 17 Sep 2016 20:40:41 +0100 Subject: [PATCH 70/82] merge --- src/summarizer/preprocessing_util.cpp | 250 ++++++++++---------- src/summarizer/summarizer_parse_options.cpp | 2 +- src/summarizer/summarizer_parse_options.h | 2 +- 3 files changed, 125 insertions(+), 129 deletions(-) diff --git a/src/summarizer/preprocessing_util.cpp b/src/summarizer/preprocessing_util.cpp index 59f7a825e..ccc335388 100644 --- a/src/summarizer/preprocessing_util.cpp +++ b/src/summarizer/preprocessing_util.cpp @@ -69,7 +69,7 @@ void summarizer_parse_optionst::propagate_constants(goto_modelt &goto_model) namespacet ns(goto_model.symbol_table); Forall_goto_functions(f_it, goto_model.goto_functions) { - const_propagator_ait(f_it->second,ns); + constant_propagator_ait(f_it->second,ns); } } @@ -96,13 +96,13 @@ void summarizer_parse_optionst::nondet_locals(goto_modelt &goto_model) { if(i_it->is_decl()) { - const code_declt& decl = to_code_decl(i_it->code); + const code_declt& decl = to_code_decl(i_it->code); side_effect_expr_nondett nondet(decl.symbol().type()); - goto_programt::targett t = f_it->second.body.insert_after(i_it); - t->make_assignment(); - code_assignt c(decl.symbol(),nondet); - t->code.swap(c); - t->source_location = i_it->source_location; + goto_programt::targett t = f_it->second.body.insert_after(i_it); + t->make_assignment(); + code_assignt c(decl.symbol(),nondet); + t->code.swap(c); + t->source_location = i_it->source_location; } } } @@ -121,64 +121,60 @@ Function: goto_unwind \*******************************************************************/ -void summarizer_parse_optionst::unwind(goto_modelt &goto_model, unsigned k) +void summarizer_parse_optionst::unwind_goto_into_loop(goto_modelt &goto_model, unsigned k) { -goto_unwind(goto_model.goto_functions, k); + typedef std::vector > loopst; -#if 0 -typedef std::vector > loopst; - -Forall_goto_functions(f_it, goto_model.goto_functions) -{ -goto_programt &body=f_it->second.body; + Forall_goto_functions(f_it, goto_model.goto_functions) + { + goto_programt &body=f_it->second.body; -loopst loops; -Forall_goto_program_instructions(i_it, body) -{ -if(i_it->is_backwards_goto()) -{ -goto_programt::targett loop_head = i_it->get_target(); -goto_programt::targett loop_exit = i_it; -bool has_goto_into_loop = false; + loopst loops; + Forall_goto_program_instructions(i_it, body) + { + if(i_it->is_backwards_goto()) + { + goto_programt::targett loop_head = i_it->get_target(); + goto_programt::targett loop_exit = i_it; + bool has_goto_into_loop = false; -goto_programt::targett it = loop_head; -if(it!=loop_exit) it++; -for(; it!=loop_exit; it++) -{ -for( std::set::iterator -s_it = it->incoming_edges.begin(); -s_it!=it->incoming_edges.end(); ++s_it) -{ -if((*s_it)->is_goto() && -(*s_it)->location_number < loop_head->location_number) -{ -has_goto_into_loop = true; -break; -} -} -if(has_goto_into_loop) break; -} -if(has_goto_into_loop) -{ -status() << "Unwinding jump into loop" << eom; -loops.push_back(loopst::value_type(++loop_exit,loop_head)); -} -} -} + goto_programt::targett it = loop_head; + if(it!=loop_exit) it++; + for(; it!=loop_exit; it++) + { + for( std::set::iterator + s_it = it->incoming_edges.begin(); + s_it!=it->incoming_edges.end(); ++s_it) + { + if((*s_it)->is_goto() && + (*s_it)->location_number < loop_head->location_number) + { + has_goto_into_loop = true; + break; + } + } + if(has_goto_into_loop) break; + } + if(has_goto_into_loop) + { + status() << "Unwinding jump into loop" << eom; + loops.push_back(loopst::value_type(++loop_exit,loop_head)); + } + } + } -for(loopst::iterator l_it = loops.begin(); l_it != loops.end(); ++l_it) -{ -std::vector iteration_points; -unwind(body,l_it->second,l_it->first,k,iteration_points); -assert(iteration_points.size()==2); -goto_programt::targett t=body.insert_before(l_it->first); -t->make_goto(); -t->targets.push_back(iteration_points.front()); -} -} -goto_model.goto_functions.update(); -goto_model.goto_functions.compute_loop_numbers(); -#endif + for(loopst::iterator l_it = loops.begin(); l_it != loops.end(); ++l_it) + { + std::vector iteration_points; + unwind(body,l_it->second,l_it->first,k,iteration_points); + assert(iteration_points.size()==2); + goto_programt::targett t=body.insert_before(l_it->first); + t->make_goto(); + t->targets.push_back(iteration_points.front()); + } + } + goto_model.goto_functions.update(); + goto_model.goto_functions.compute_loop_numbers(); } /*******************************************************************\ @@ -195,75 +191,75 @@ Function: remove_multiple_dereferences void summarizer_parse_optionst::remove_multiple_dereferences(goto_modelt &goto_model, goto_programt &body, goto_programt::targett t, exprt &expr, unsigned &var_counter, bool deref_seen) { -if(expr.id()==ID_member) -{ -member_exprt &member_expr = to_member_expr(expr); -if(member_expr.compound().id()==ID_dereference) -{ -dereference_exprt &deref_expr = to_dereference_expr(member_expr.compound()); -remove_multiple_dereferences(goto_model,body,t,deref_expr.pointer(),var_counter,true); -if(deref_seen) -{ -symbolt new_symbol; -new_symbol.type=member_expr.type(); -new_symbol.name="$deref"+i2string(var_counter++); -new_symbol.base_name=new_symbol.name; -new_symbol.pretty_name=new_symbol.name; -goto_model.symbol_table.add(new_symbol); -goto_programt::targett t_new = body.insert_before(t); -t_new->make_assignment(); -t_new->code = code_assignt(new_symbol.symbol_expr(),member_expr); -expr = new_symbol.symbol_expr(); -for(std::set::iterator t_it = - t->incoming_edges.begin(); -t_it != t->incoming_edges.end(); ++t_it) -{ -(*t_it)->targets.clear(); -(*t_it)->targets.push_back(t_new); -} -body.compute_location_numbers(); -body.compute_target_numbers(); -body.compute_incoming_edges(); -} -} -else - Forall_operands(o_it,expr) - remove_multiple_dereferences(goto_model,body,t,*o_it,var_counter,deref_seen); -} -else - Forall_operands(o_it,expr) - remove_multiple_dereferences(goto_model,body,t,*o_it,var_counter,deref_seen); + if(expr.id()==ID_member) + { + member_exprt &member_expr = to_member_expr(expr); + if(member_expr.compound().id()==ID_dereference) + { + dereference_exprt &deref_expr = to_dereference_expr(member_expr.compound()); + remove_multiple_dereferences(goto_model,body,t,deref_expr.pointer(),var_counter,true); + if(deref_seen) + { + symbolt new_symbol; + new_symbol.type=member_expr.type(); + new_symbol.name="$deref"+i2string(var_counter++); + new_symbol.base_name=new_symbol.name; + new_symbol.pretty_name=new_symbol.name; + goto_model.symbol_table.add(new_symbol); + goto_programt::targett t_new = body.insert_before(t); + t_new->make_assignment(); + t_new->code = code_assignt(new_symbol.symbol_expr(),member_expr); + expr = new_symbol.symbol_expr(); + for(std::set::iterator t_it = + t->incoming_edges.begin(); + t_it != t->incoming_edges.end(); ++t_it) + { + (*t_it)->targets.clear(); + (*t_it)->targets.push_back(t_new); + } + body.compute_location_numbers(); + body.compute_target_numbers(); + body.compute_incoming_edges(); + } + } + else + Forall_operands(o_it,expr) + remove_multiple_dereferences(goto_model,body,t,*o_it,var_counter,deref_seen); + } + else + Forall_operands(o_it,expr) + remove_multiple_dereferences(goto_model,body,t,*o_it,var_counter,deref_seen); } void summarizer_parse_optionst::remove_multiple_dereferences(goto_modelt &goto_model) { -unsigned var_counter = 0; -namespacet ns(goto_model.symbol_table); -Forall_goto_functions(f_it, goto_model.goto_functions) -{ -Forall_goto_program_instructions(i_it, f_it->second.body) -{ -if(i_it->is_goto()) -{ -remove_multiple_dereferences(goto_model, - f_it->second.body, - i_it, - i_it->guard, - var_counter, false); -} -else if(i_it->is_assign()) -{ -remove_multiple_dereferences(goto_model, - f_it->second.body, - i_it, - to_code_assign(i_it->code).lhs(), - var_counter, false); -remove_multiple_dereferences(goto_model, - f_it->second.body, - i_it, - to_code_assign(i_it->code).rhs(), - var_counter, false); -} -} -} + unsigned var_counter = 0; + namespacet ns(goto_model.symbol_table); + Forall_goto_functions(f_it, goto_model.goto_functions) + { + Forall_goto_program_instructions(i_it, f_it->second.body) + { + if(i_it->is_goto()) + { + remove_multiple_dereferences(goto_model, + f_it->second.body, + i_it, + i_it->guard, + var_counter, false); + } + else if(i_it->is_assign()) + { + remove_multiple_dereferences(goto_model, + f_it->second.body, + i_it, + to_code_assign(i_it->code).lhs(), + var_counter, false); + remove_multiple_dereferences(goto_model, + f_it->second.body, + i_it, + to_code_assign(i_it->code).rhs(), + var_counter, false); + } + } + } } diff --git a/src/summarizer/summarizer_parse_options.cpp b/src/summarizer/summarizer_parse_options.cpp index bbc2a002c..9a5b0e7da 100644 --- a/src/summarizer/summarizer_parse_options.cpp +++ b/src/summarizer/summarizer_parse_options.cpp @@ -54,7 +54,7 @@ Author: Daniel Kroening, kroening@kroening.com #include "show.h" #include "horn_encoding.h" -#define UNWIND_GOTO_INTO_LOOP 0 +#define UNWIND_GOTO_INTO_LOOP 1 #define REMOVE_MULTIPLE_DEREFERENCES 1 /*******************************************************************\ diff --git a/src/summarizer/summarizer_parse_options.h b/src/summarizer/summarizer_parse_options.h index 9e612e340..738eb579f 100644 --- a/src/summarizer/summarizer_parse_options.h +++ b/src/summarizer/summarizer_parse_options.h @@ -134,7 +134,7 @@ class summarizer_parse_optionst: void inline_main(goto_modelt &goto_model); void propagate_constants(goto_modelt &goto_model); void nondet_locals(goto_modelt &goto_model); - void unwind(goto_modelt &goto_model, unsigned k); + void unwind_goto_into_loop(goto_modelt &goto_model, unsigned k); void replace_types_rec(const replace_symbolt &replace_const, exprt &expr); exprt evaluate_casts_in_constants(const exprt &expr, const typet& parent_type, bool &valid); From 6a82e7677f78144d05937914d62938b07d2f9bfd Mon Sep 17 00:00:00 2001 From: Peter Schrammel Date: Sat, 17 Sep 2016 17:29:59 +0100 Subject: [PATCH 71/82] merge --- src/summarizer/preprocessing_util.cpp | 12 ++--- src/summarizer/summarizer_parse_options.cpp | 53 +++++++++------------ 2 files changed, 28 insertions(+), 37 deletions(-) diff --git a/src/summarizer/preprocessing_util.cpp b/src/summarizer/preprocessing_util.cpp index ccc335388..0be64ff76 100644 --- a/src/summarizer/preprocessing_util.cpp +++ b/src/summarizer/preprocessing_util.cpp @@ -96,13 +96,13 @@ void summarizer_parse_optionst::nondet_locals(goto_modelt &goto_model) { if(i_it->is_decl()) { - const code_declt& decl = to_code_decl(i_it->code); + const code_declt& decl = to_code_decl(i_it->code); side_effect_expr_nondett nondet(decl.symbol().type()); - goto_programt::targett t = f_it->second.body.insert_after(i_it); - t->make_assignment(); - code_assignt c(decl.symbol(),nondet); - t->code.swap(c); - t->source_location = i_it->source_location; + goto_programt::targett t = f_it->second.body.insert_after(i_it); + t->make_assignment(); + code_assignt c(decl.symbol(),nondet); + t->code.swap(c); + t->source_location = i_it->source_location; } } } diff --git a/src/summarizer/summarizer_parse_options.cpp b/src/summarizer/summarizer_parse_options.cpp index 9a5b0e7da..30863d1dd 100644 --- a/src/summarizer/summarizer_parse_options.cpp +++ b/src/summarizer/summarizer_parse_options.cpp @@ -408,8 +408,11 @@ int summarizer_parse_optionst::doit() // // Print a banner // - status() << "SUMMARIZER version " SUMMARIZER_VERSION " (based on CBMC " CBMC_VERSION ")" << eom; - +(??) status() << "2LS version " SUMMARIZER_VERSION " (based on CBMC " CBMC_VERSION ")" << eom; +(??) +(??) register_language(new_ansi_c_language); +(??) register_language(new_cpp_language); +(??) goto_modelt goto_model; register_languages(); @@ -1069,31 +1072,15 @@ bool summarizer_parse_optionst::process_goto_program( // remove returns (must be done after function pointer removal) remove_returns(goto_model); - - split_loopheads(goto_model); - - // recalculate numbers, etc. - goto_model.goto_functions.update(); - - // add loop ids - goto_model.goto_functions.compute_loop_numbers(); - - // if we aim to cover, replace - // all assertions by false to prevent simplification - if(cmdline.isset("cover-assertions")) - make_assertions_false(goto_model); - - // show it? - if(cmdline.isset("show-loops")) - { - show_loop_ids(get_ui(), goto_model); - return true; - } - + + #if UNWIND_GOTO_INTO_LOOP - unwind(goto_model,2); + unwind_goto_into_loop(goto_model,2); #endif + remove_skip(goto_model.goto_functions); + goto_model.goto_functions.update(); + // now do full inlining, if requested if(options.get_bool_option("inline")) { @@ -1138,14 +1125,17 @@ bool summarizer_parse_optionst::process_goto_program( propagate_constants(goto_model); } -#if 1 - //TODO: find a better place for that - replace_malloc(goto_model,""); -#endif + // if we aim to cover, replace + // all assertions by false to prevent simplification + if(cmdline.isset("cover-assertions")) + make_assertions_false(goto_model); -#if REMOVE_MULTIPLE_DEREFERENCES - remove_multiple_dereferences(goto_model); -#endif + // show it? + if(cmdline.isset("show-loops")) + { + show_loop_ids(get_ui(), goto_model); + return true; + } // do array abstraction if(cmdline.isset("array-abstraction")) @@ -1214,6 +1204,7 @@ Function: summarizer_parse_optionst::report_properties \*******************************************************************/ void summarizer_parse_optionst::report_properties( + const optionst &options, const goto_modelt &goto_model, const property_checkert::property_mapt &property_map) { From 85a7af1df1838af04df0203b429a1fd1a0cc7fa3 Mon Sep 17 00:00:00 2001 From: Peter Schrammel Date: Sun, 18 Sep 2016 15:56:07 +0100 Subject: [PATCH 72/82] bounds simplification --- src/domains/tpolyhedra_domain.cpp | 3 +++ src/summarizer/summarizer_parse_options.cpp | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/domains/tpolyhedra_domain.cpp b/src/domains/tpolyhedra_domain.cpp index e79d76229..25997d740 100644 --- a/src/domains/tpolyhedra_domain.cpp +++ b/src/domains/tpolyhedra_domain.cpp @@ -20,6 +20,8 @@ Author: Peter Schrammel #include "simplify_bounds.h" +#include "simplify_bounds.h" + #define SYMB_BOUND_VAR "symb_bound#" #define ENABLE_HEURISTICS @@ -699,6 +701,7 @@ void tpolyhedra_domaint::project_on_vars( } result=conjunction(c); simplify_bounds(result, ns); + simplify_bounds(result, ns); } /*******************************************************************\ diff --git a/src/summarizer/summarizer_parse_options.cpp b/src/summarizer/summarizer_parse_options.cpp index 30863d1dd..15be22a06 100644 --- a/src/summarizer/summarizer_parse_options.cpp +++ b/src/summarizer/summarizer_parse_options.cpp @@ -54,7 +54,7 @@ Author: Daniel Kroening, kroening@kroening.com #include "show.h" #include "horn_encoding.h" -#define UNWIND_GOTO_INTO_LOOP 1 +#define UNWIND_GOTO_INTO_LOOP 0 #define REMOVE_MULTIPLE_DEREFERENCES 1 /*******************************************************************\ From b8ee5c9c1017ff92e9af3ff57b8899b5caf0d616 Mon Sep 17 00:00:00 2001 From: Peter Schrammel Date: Tue, 9 May 2017 18:30:54 +0200 Subject: [PATCH 73/82] Rebase bw cex --- src/2ls/Makefile | 1 + src/2ls/cover_goals_ext.cpp | 50 +- src/2ls/cover_goals_ext.h | 13 +- src/2ls/summary_checker_base.cpp | 400 +++++----- src/2ls/summary_checker_base.h | 24 +- src/deltacheck/deltacheck_parse_options.cpp | 44 +- src/deltacheck/deltacheck_parse_options.h | 2 +- src/deltagit/deltagit_parse_options.cpp | 12 +- src/domains/Makefile | 2 +- src/domains/disjunctive_analyzer.cpp | 276 +++---- src/domains/disjunctive_analyzer.h | 45 +- src/domains/domain.h | 2 +- src/domains/domain_refinement.h | 8 +- src/domains/domain_refinement_variables.cpp | 12 +- src/domains/incremental_solver.cpp | 13 +- src/domains/incremental_solver.h | 14 +- src/domains/lexlinrank_solver_enumeration.cpp | 6 +- src/domains/lexlinrank_solver_enumeration.h | 4 +- src/domains/ranking_solver_enumeration.cpp | 2 +- src/domains/simplify_bounds.cpp | 38 +- src/domains/simplify_bounds_class.h | 2 +- src/domains/simplify_transformer.cpp | 46 +- src/domains/simplify_transformer.h | 4 +- src/domains/simplify_transformer_class.h | 8 +- src/domains/ssa_analyzer.cpp | 61 +- src/domains/ssa_analyzer.h | 10 +- src/domains/strategy_solver_base.h | 2 +- src/domains/strategy_solver_binsearch.cpp | 2 +- src/domains/strategy_solver_binsearch2.cpp | 3 +- src/domains/strategy_solver_binsearch2.h | 3 +- src/domains/strategy_solver_binsearch3.cpp | 9 +- src/domains/strategy_solver_binsearch3.h | 3 +- src/domains/strategy_solver_enumeration.cpp | 8 +- src/domains/strategy_solver_enumeration.h | 6 +- src/domains/strategy_solver_equality.cpp | 4 +- src/domains/strategy_solver_predabs.cpp | 7 +- src/domains/strategy_solver_predabs.h | 5 +- src/domains/template_generator_base.h | 6 + src/domains/template_generator_summary.cpp | 2 +- src/domains/tpolyhedra_domain.cpp | 32 +- src/domains/tpolyhedra_domain.h | 6 +- src/domains/util.cpp | 4 +- src/html/syntax_highlighting.cpp | 48 +- src/html/syntax_highlighting.h | 6 +- src/solver/Makefile | 19 +- src/solver/summarizer_bw_cex.cpp | 271 +++++++ src/solver/summarizer_bw_cex.h | 80 ++ src/solver/summarizer_bw_cex_ai.cpp | 535 ++++++++++++++ .../summarizer_bw_cex_ai.h | 62 +- .../summarizer_bw_cex_all.cpp | 16 +- .../summarizer_bw_cex_all.h | 52 +- .../summarizer_bw_cex_complete.cpp | 346 ++++----- .../summarizer_bw_cex_complete.h | 62 +- .../summarizer_bw_cex_concrete.cpp | 342 ++++----- src/solver/summarizer_bw_cex_concrete.h | 80 ++ src/solver/summarizer_bw_cex_wp.cpp | 643 +++++++++++++++++ .../summarizer_bw_cex_wp.h | 60 +- src/solver/summary.cpp | 12 +- src/solver/summary.h | 14 +- src/solver/summary_db.h | 4 +- src/ssa/Makefile | 2 +- src/ssa/const_propagator.cpp | 150 ++-- src/ssa/const_propagator.h | 26 +- src/ssa/local_ssa.cpp | 115 ++- src/ssa/local_ssa.h | 21 +- src/ssa/replace_symbol_ext.cpp | 6 +- src/ssa/ssa_const_propagator.cpp | 278 +++---- src/ssa/ssa_const_propagator.h | 24 +- src/ssa/ssa_db.cpp | 6 +- src/ssa/ssa_db.h | 38 +- src/ssa/ssa_dependency_graph.cpp | 683 +++++++++--------- src/ssa/ssa_dependency_graph.h | 50 +- src/ssa/ssa_domain.cpp | 2 +- src/ssa/ssa_inliner.cpp | 494 ++++++------- src/ssa/ssa_inliner.h | 105 +-- src/ssa/ssa_refiner_monolithic.cpp | 2 +- src/ssa/ssa_refiner_monolithic.h | 8 +- src/ssa/ssa_refiner_selective.cpp | 28 +- src/ssa/ssa_refiner_selective.h | 20 +- src/ssa/ssa_slicer.cpp | 194 ++--- src/ssa/ssa_slicer.h | 10 +- src/ssa/ssa_unwinder.cpp | 236 +++--- src/ssa/ssa_unwinder.h | 20 +- src/ssa/ssa_value_set.cpp | 3 +- src/ssa/unwindable_local_ssa.cpp | 16 +- src/storefront/data.cpp | 4 +- src/storefront/data.h | 4 +- src/storefront/file_view.cpp | 38 +- src/storefront/storefront_main.cpp | 2 +- src/storefront/storefront_parse_options.cpp | 14 +- src/summarizer/function_signature.cpp | 2 +- src/summarizer/instrument_goto.cpp | 60 +- src/summarizer/instrument_goto.h | 8 +- src/summarizer/preprocessing_util.cpp | 80 +- src/summarizer/summarizer.cpp | 16 +- src/summarizer/summarizer.h | 2 +- src/summarizer/summarizer_bw_cex.cpp | 100 --- src/summarizer/summarizer_bw_cex.h | 56 -- src/summarizer/summarizer_bw_cex_ai.cpp | 549 -------------- src/summarizer/summarizer_bw_cex_concrete.h | 77 -- src/summarizer/summarizer_bw_cex_wp.cpp | 643 ----------------- src/summarizer/summarizer_fw_contexts.cpp | 176 ++--- src/summarizer/summarizer_fw_contexts.h | 24 +- src/summarizer/summarizer_parse_options.cpp | 302 ++++---- src/summarizer/summarizer_parse_options.h | 28 +- src/summarizer/summary_checker_ai.cpp | 112 +-- src/summarizer/summary_checker_ai.h | 2 +- src/summarizer/summary_checker_base.cpp | 326 ++++----- src/summarizer/summary_checker_base.h | 8 +- src/summarizer/summary_checker_bmc.cpp | 42 +- src/summarizer/summary_checker_bmc.h | 2 +- src/summarizer/summary_checker_kind.cpp | 58 +- src/summarizer/summary_checker_kind.h | 2 +- 113 files changed, 4693 insertions(+), 4434 deletions(-) create mode 100644 src/solver/summarizer_bw_cex.cpp create mode 100644 src/solver/summarizer_bw_cex.h create mode 100644 src/solver/summarizer_bw_cex_ai.cpp rename src/{summarizer => solver}/summarizer_bw_cex_ai.h (50%) rename src/{summarizer => solver}/summarizer_bw_cex_all.cpp (82%) rename src/{summarizer => solver}/summarizer_bw_cex_all.h (54%) rename src/{summarizer => solver}/summarizer_bw_cex_complete.cpp (62%) rename src/{summarizer => solver}/summarizer_bw_cex_complete.h (51%) rename src/{summarizer => solver}/summarizer_bw_cex_concrete.cpp (54%) create mode 100644 src/solver/summarizer_bw_cex_concrete.h create mode 100644 src/solver/summarizer_bw_cex_wp.cpp rename src/{summarizer => solver}/summarizer_bw_cex_wp.h (51%) delete mode 100644 src/summarizer/summarizer_bw_cex.cpp delete mode 100644 src/summarizer/summarizer_bw_cex.h delete mode 100644 src/summarizer/summarizer_bw_cex_ai.cpp delete mode 100644 src/summarizer/summarizer_bw_cex_concrete.h delete mode 100644 src/summarizer/summarizer_bw_cex_wp.cpp diff --git a/src/2ls/Makefile b/src/2ls/Makefile index 06b9d4486..b3a785bfd 100644 --- a/src/2ls/Makefile +++ b/src/2ls/Makefile @@ -29,6 +29,7 @@ OBJ+= $(CBMC)/src/ansi-c/ansi-c$(LIBEXT) \ ../domains/domains$(LIBEXT) \ ../ssa/ssa$(LIBEXT) \ ../solver/solver$(LIBEXT) \ + # empty last line CP_CXXFLAGS+= $(TWOLSFLAGS) diff --git a/src/2ls/cover_goals_ext.cpp b/src/2ls/cover_goals_ext.cpp index 219012e0e..b3167f479 100644 --- a/src/2ls/cover_goals_ext.cpp +++ b/src/2ls/cover_goals_ext.cpp @@ -182,64 +182,64 @@ void cover_goals_extt::assignment() solver.l_get(g_it->condition).is_true()) { #if 1 - solver.pop_context(); //otherwise this would interfere with necessary preconditions + solver.pop_context(); // otherwise this would interfere with necessary preconditions summarizer_bw_cex.summarize(g_it->cond_expression); - property_map[it->first].result = summarizer_bw_cex.check(); + property_map[it->first].result=summarizer_bw_cex.check(); solver.new_context(); -#else // THE ASSERTIONS THAT FAIL COULD BE RATHER ARBITRARY SINCE THE FORMULA - // IS NOT "ROOTED" IN AN INITIAL STATE. - assert((g_it->cond_expression).id() == ID_not); - exprt conjunct_expr = (g_it->cond_expression).op0(); +#else // THE ASSERTIONS THAT FAIL COULD BE RATHER ARBITRARY SINCE THE FORMULA + // IS NOT "ROOTED" IN AN INITIAL STATE. + assert((g_it->cond_expression).id()==ID_not); + exprt conjunct_expr=(g_it->cond_expression).op0(); #if 0 - std::cout << "FAILED EXPR: " + std::cout << "FAILED EXPR: " << from_expr(SSA.ns, "", conjunct_expr) << std::endl; #endif - - if(conjunct_expr.id() != ID_and) + + if(conjunct_expr.id()!=ID_and) { - solver.pop_context(); //otherwise this would interfere with necessary preconditions + solver.pop_context(); // otherwise this would interfere with necessary preconditions summarizer_bw_cex.summarize(g_it->cond_expression); - property_map[it->first].result = summarizer_bw_cex.check(); + property_map[it->first].result=summarizer_bw_cex.check(); solver.new_context(); } else { - //filter out assertion instances that are not violated + // filter out assertion instances that are not violated exprt::operandst failed_exprs; - for(exprt::operandst::const_iterator c_it = + for(exprt::operandst::const_iterator c_it= conjunct_expr.operands().begin(); - c_it != conjunct_expr.operands().end(); c_it++) + c_it!=conjunct_expr.operands().end(); c_it++) { - literalt conjunct_literal = solver.convert(*c_it); + literalt conjunct_literal=solver.convert(*c_it); if(solver.l_get(conjunct_literal).is_false()) { failed_exprs.push_back(*c_it); #if 0 - std::cout << "failed_expr: " + std::cout << "failed_expr: " << from_expr(SSA.ns, "", *c_it) << std::endl; #endif } } - solver.pop_context(); //otherwise this would interfere with necessary preconditions + solver.pop_context(); // otherwise this would interfere with necessary preconditions summarizer_bw_cex.summarize(not_exprt(conjunction(failed_exprs))); - property_map[it->first].result = summarizer_bw_cex.check(); + property_map[it->first].result=summarizer_bw_cex.check(); solver.new_context(); } #endif } - if(property_map[it->first].result == property_checkert::FAIL) + if(property_map[it->first].result==property_checkert::FAIL) { if(build_error_trace) { - ssa_build_goto_tracet build_goto_trace(SSA,solver.get_solver()); - build_goto_trace(property_map[it->first].error_trace); + ssa_build_goto_tracet build_goto_trace(SSA, solver.get_solver()); + build_goto_trace(property_map[it->first].error_trace); } } if(!all_properties && - property_map[it->first].result == property_checkert::FAIL) + property_map[it->first].result==property_checkert::FAIL) break; } - - _iterations++; //statistics + + _iterations++; // statistics } - + diff --git a/src/2ls/cover_goals_ext.h b/src/2ls/cover_goals_ext.h index 0ac80f61e..7cd3f9360 100644 --- a/src/2ls/cover_goals_ext.h +++ b/src/2ls/cover_goals_ext.h @@ -12,11 +12,10 @@ Author: Daniel Kroening, kroening@kroening.com #include #include -#include "../ssa/local_ssa.h" -#include "../ssa/unwindable_local_ssa.h" -#include "../domains/incremental_solver.h" -#include "summarizer_bw_cex.h" -#include "summarizer_bw_cex_complete.h" +#include +#include +#include +#include /*******************************************************************\ @@ -49,7 +48,7 @@ struct goalt class cover_goals_extt:public messaget { public: - explicit inline cover_goals_extt( + cover_goals_extt( unwindable_local_SSAt &_SSA, incremental_solvert &_solver, property_checkert::property_mapt &_property_map, @@ -75,7 +74,7 @@ class cover_goals_extt:public messaget { literalt condition; bool covered; - exprt cond_expression; + exprt cond_expression; cover_goalt():covered(false) { diff --git a/src/2ls/summary_checker_base.cpp b/src/2ls/summary_checker_base.cpp index c910b184c..2c34120b6 100644 --- a/src/2ls/summary_checker_base.cpp +++ b/src/2ls/summary_checker_base.cpp @@ -29,6 +29,12 @@ Author: Peter Schrammel #include #include #include +#include +#include +#include +#include +#include +#include #ifdef SHOW_CALLING_CONTEXTS #include @@ -138,11 +144,15 @@ void summary_checker_baset::summarize( delete summarizer; } + /*******************************************************************\ Function: summary_checker_baset::check_properties - Inputs: + Inputs: function_name!=nil + checks all functions in the call graph from the entry point + else + checks all functions Outputs: @@ -152,36 +162,93 @@ Function: summary_checker_baset::check_properties summary_checker_baset::resultt summary_checker_baset::check_properties() { - // analyze all the functions - for(ssa_dbt::functionst::const_iterator f_it=ssa_db.functions().begin(); - f_it!=ssa_db.functions().end(); f_it++) + std::set seen_function_calls; + return check_properties("", "", seen_function_calls, false); +} + +summary_checker_baset::resultt summary_checker_baset::check_properties( + irep_idt function_name, + irep_idt entry_function, + std::set seen_function_calls, + bool is_inlined) +{ + if(function_name!="") { - status() << "Checking properties of " << f_it->first << messaget::eom; + ssa_dbt::functionst::const_iterator f_it= + ssa_db.functions().find(function_name); + assert(f_it!=ssa_db.functions().end()); + local_SSAt &SSA=*f_it->second; + // call recursively for all function calls first + for(local_SSAt::nodest::const_iterator n_it=SSA.nodes.begin(); + n_it!=SSA.nodes.end(); ++n_it) + { + for(local_SSAt::nodet::function_callst::const_iterator ff_it= + n_it->function_calls.begin(); + ff_it!=n_it->function_calls.end(); ff_it++) + { + assert(ff_it->function().id()==ID_symbol); // no function pointers + irep_idt fname=to_symbol_expr(ff_it->function()).get_identifier(); + + // ENHANCE?: can the return value be exploited? + if(ssa_db.functions().find(fname)!=ssa_db.functions().end() && + (!summary_db.exists(fname) || + summary_db.get(fname).bw_transformer.is_nil())) + { #if 0 - // for debugging - show_ssa_symbols(*f_it->second, std::cerr); + debug() << "Checking call " << fname << messaget::eom; #endif + if(seen_function_calls.find(fname)==seen_function_calls.end()){ + seen_function_calls.insert(fname); + check_properties(fname, entry_function, seen_function_calls, + n_it->function_calls_inlined); + } + } + } + } - check_properties(f_it); - - if(options.get_bool_option("show-invariants")) + if(!is_inlined) { - if(!summary_db.exists(f_it->first)) - continue; - show_invariants(*(f_it->second), summary_db.get(f_it->first), result()); - result() << eom; + // now check function itself + status() << "Checking properties of " << f_it->first << messaget::eom; + check_properties(f_it, entry_function); + } + } + else // check all the functions + { + for(ssa_dbt::functionst::const_iterator f_it=ssa_db.functions().begin(); + f_it!=ssa_db.functions().end(); f_it++) + { + status() << "Checking properties of " << f_it->first << messaget::eom; + +#if 0 + // for debugging + show_ssa_symbols(*f_it->second, std::cerr); +#endif + + check_properties(f_it); + + if(options.get_bool_option("show-invariants")) + { + if(!summary_db.exists(f_it->first)) continue; + show_invariants(*(f_it->second), summary_db.get(f_it->first), result()); + result() << eom; + } } } summary_checker_baset::resultt result=property_checkert::PASS; - for(property_mapt::const_iterator - p_it=property_map.begin(); p_it!=property_map.end(); p_it++) + if(function_name=="" || function_name==entry_function) { - if(p_it->second.result==FAIL) - return property_checkert::FAIL; - if(p_it->second.result==UNKNOWN) - result=property_checkert::UNKNOWN; + // determine overall status + for(property_mapt::const_iterator + p_it=property_map.begin(); p_it!=property_map.end(); p_it++) + { + if(p_it->second.result==FAIL) + return property_checkert::FAIL; + if(p_it->second.result==UNKNOWN) + result=property_checkert::UNKNOWN; + } } return result; @@ -200,11 +267,20 @@ Function: summary_checker_baset::check_properties \*******************************************************************/ void summary_checker_baset::check_properties( - const ssa_dbt::functionst::const_iterator f_it) + const ssa_dbt::functionst::const_iterator f_it, + irep_idt entry_function) { unwindable_local_SSAt &SSA=*f_it->second; + // check whether function has assertions + if(!has_assertion(f_it->first)) + return; + bool all_properties=options.get_bool_option("all-properties"); + bool build_error_trace= + options.get_bool_option("show-trace") || + options.get_option("graphml-witness")!="" || + options.get_option("json-cex")!=""; SSA.output_verbose(debug()); debug() << eom; @@ -233,24 +309,63 @@ void summary_checker_baset::check_properties( // callee summaries solver << ssa_inliner.get_summaries(SSA); - // freeze loop head selects - exprt::operandst loophead_selects= - get_loophead_selects(f_it->first, SSA, *solver.solver); - // check whether loops have been fully unwound - exprt::operandst loop_continues= - get_loop_continues(f_it->first, SSA, *solver.solver); - bool fully_unwound= - is_fully_unwound(loop_continues, loophead_selects, solver); - status() << "Loops " << (fully_unwound ? "" : "not ") - << "fully unwound" << eom; + // spuriousness checkers + summarizer_bw_cex_baset *summarizer_bw_cex=NULL; + incremental_solvert* cex_complete_solver= + incremental_solvert::allocate(SSA.ns, + options.get_bool_option("refine")); +#if 1 + cex_complete_solver->set_message_handler(get_message_handler()); +#endif + if(options.get_option("spurious-check")=="abstract") + { + summarizer_bw_cex=new summarizer_bw_cex_ait( + options, summary_db, ssa_db, + ssa_unwinder, ssa_inliner, + entry_function, f_it->first); + } + else if(options.get_option("spurious-check")=="complete") + { + summarizer_bw_cex=new summarizer_bw_cex_completet( + options, summary_db, ssa_db, + ssa_unwinder, ssa_inliner, *cex_complete_solver, + entry_function, f_it->first); + } + else if(options.get_option("spurious-check")=="wp") + { + summarizer_bw_cex=new summarizer_bw_cex_wpt( + options, summary_db, ssa_db, + ssa_unwinder, ssa_inliner, *cex_complete_solver, + entry_function, f_it->first); + } + else if(options.get_option("spurious-check")=="all") + { + summarizer_bw_cex=new summarizer_bw_cex_allt( + options, summary_db, ssa_db, + ssa_unwinder, ssa_inliner, *cex_complete_solver, + entry_function, f_it->first); + } + else +#if 0 + if(options.get_bool_option("inline") || + options.get_option("spurious-check")=="concrete") +#endif + { + summarizer_bw_cex=new summarizer_bw_cex_concretet( + options, summary_db, ssa_db, + ssa_unwinder, ssa_inliner, + entry_function, f_it->first); + } + assert(summarizer_bw_cex!=NULL); + summarizer_bw_cex->set_message_handler(get_message_handler()); cover_goals_extt cover_goals( - SSA, solver, loophead_selects, property_map, - !fully_unwound && options.get_bool_option("spurious-check"), + SSA, + solver, + property_map, all_properties, - options.get_bool_option("show-trace") || - options.get_option("graphml-witness")!="" || - options.get_option("json-cex")!=""); + build_error_trace, + *summarizer_bw_cex); #if 0 debug() << "(C) " << from_expr(SSA.ns, "", enabling_expr) << eom; @@ -422,206 +537,77 @@ void summary_checker_baset::do_show_vcc( /*******************************************************************\ -Function: summary_checker_baset::get_loophead_selects +Function: summary_checker_baset::instrument_and_output Inputs: Outputs: - Purpose: returns the select guards at the loop heads - in order to check whether a countermodel is spurious + Purpose: instruments the code with the inferred information + and outputs it to a goto-binary \*******************************************************************/ -exprt::operandst summary_checker_baset::get_loophead_selects( - const irep_idt &function_name, - const local_SSAt &SSA, prop_convt &solver) +void summary_checker_baset::instrument_and_output(goto_modelt &goto_model) { - // TODO: this should be provided by unwindable_local_SSA - exprt::operandst loophead_selects; - for(local_SSAt::nodest::const_iterator n_it=SSA.nodes.begin(); - n_it!=SSA.nodes.end(); n_it++) - { - if(n_it->loophead==SSA.nodes.end()) - continue; - symbol_exprt lsguard= - SSA.name(SSA.guard_symbol(), local_SSAt::LOOP_SELECT, n_it->location); - ssa_unwinder.get(function_name).unwinder_rename(lsguard, *n_it, true); - loophead_selects.push_back(not_exprt(lsguard)); - solver.set_frozen(solver.convert(lsguard)); - } - literalt loophead_selects_literal= - solver.convert(conjunction(loophead_selects)); - if(!loophead_selects_literal.is_constant()) - solver.set_frozen(loophead_selects_literal); - -#if 0 - std::cout << "loophead_selects: " - << from_expr(SSA.ns, "", conjunction(loophead_selects)) - << std::endl; -#endif - - return loophead_selects; + instrument_gotot instrument_goto(options, ssa_db, summary_db); + instrument_goto(goto_model); + std::string filename=options.get_option("instrument-output"); + status() << "Writing instrumented goto-binary " << filename << eom; + write_goto_binary( + filename, + goto_model.symbol_table, + goto_model.goto_functions, + get_message_handler()); } -/*******************************************************************\ - -Function: summary_checker_baset::get_loop_continues - - Inputs: - - Outputs: - - Purpose: returns the loop continuation guards at the end of the - loops in order to check whether we can unroll further - -\*******************************************************************/ - -exprt::operandst summary_checker_baset::get_loop_continues( - const irep_idt &function_name, - const local_SSAt &SSA, prop_convt &solver) -{ - // TODO: this should be provided by unwindable_local_SSA - exprt::operandst loop_continues; - - ssa_unwinder.get(function_name).loop_continuation_conditions(loop_continues); - if(loop_continues.size()==0) - { - // TODO: this should actually be done transparently by the unwinder - for(local_SSAt::nodest::const_iterator n_it=SSA.nodes.begin(); - n_it!=SSA.nodes.end(); n_it++) - { - if(n_it->loophead==SSA.nodes.end()) - continue; - symbol_exprt guard=SSA.guard_symbol(n_it->location); - symbol_exprt cond=SSA.cond_symbol(n_it->location); - loop_continues.push_back(and_exprt(guard, cond)); - } - } - -#if 0 - std::cout << "loophead_continues: " - << from_expr(SSA.ns, "", disjunction(loop_continues)) << std::endl; -#endif - - return loop_continues; -} /*******************************************************************\ -Function: summary_checker_baset::is_fully_unwound +Function: summary_checker_baset::has_assertion Inputs: Outputs: - Purpose: checks whether the loops have been fully unwound + Purpose: searches recursively for assertions in inlined functions \*******************************************************************/ -bool summary_checker_baset::is_fully_unwound( - const exprt::operandst &loop_continues, - const exprt::operandst &loophead_selects, - incremental_solvert &solver) +bool summary_checker_baset::has_assertion(irep_idt function_name) { - solver.new_context(); - solver << - and_exprt(conjunction(loophead_selects), disjunction(loop_continues)); - - solver_calls++; // statistics - - switch(solver()) - { - case decision_proceduret::D_SATISFIABLE: - solver.pop_context(); - return false; - break; - - case decision_proceduret::D_UNSATISFIABLE: - solver.pop_context(); - solver << conjunction(loophead_selects); - return true; - break; - - case decision_proceduret::D_ERROR: - default: - throw "error from decision procedure"; - } -} - -/*******************************************************************\ - -Function: summary_checker_baset::is_spurious + // SSA.goto_function.body.has_assertion() has become too semantic + bool _has_assertion=false; + const local_SSAt &SSA=ssa_db.get(function_name); - Inputs: - - Outputs: - - Purpose: checks whether a countermodel is spurious - -\*******************************************************************/ - -bool summary_checker_baset::is_spurious( - const exprt::operandst &loophead_selects, - incremental_solvert &solver) -{ - // check loop head choices in model - bool invariants_involved=false; - for(exprt::operandst::const_iterator l_it=loophead_selects.begin(); - l_it!=loophead_selects.end(); l_it++) + for(local_SSAt::nodest::const_iterator + n_it=SSA.nodes.begin(); n_it!=SSA.nodes.end(); ++n_it) { - if(solver.get(l_it->op0()).is_true()) + for(local_SSAt::nodet::assertionst::const_iterator + a_it=n_it->assertions.begin(); a_it!=n_it->assertions.end(); ++a_it) { - invariants_involved=true; - break; - } - } - if(!invariants_involved) - return false; - - // force avoiding paths going through invariants - solver << conjunction(loophead_selects); + irep_idt property_id=n_it->location->source_location.get_property_id(); - solver_calls++; // statistics - - switch(solver()) - { - case decision_proceduret::D_SATISFIABLE: - return false; - break; + if(n_it->location->guard.is_true()) + property_map[property_id].result=PASS; + else + _has_assertion=true; + } + if(!n_it->function_calls_inlined) + continue; - case decision_proceduret::D_UNSATISFIABLE: - return true; - break; + for(local_SSAt::nodet::function_callst::const_iterator + f_it=n_it->function_calls.begin(); + f_it!=n_it->function_calls.end(); ++f_it) + { + irep_idt fname=to_symbol_expr(f_it->function()).get_identifier(); + if(ssa_db.functions().find(fname)==ssa_db.functions().end()) + continue; - case decision_proceduret::D_ERROR: - default: - throw "error from decision procedure"; + bool new_has_assertion=has_assertion(fname); // recurse + _has_assertion=_has_assertion || new_has_assertion; + } } -} -/*******************************************************************\ - -Function: summary_checker_baset::instrument_and_output - - Inputs: - - Outputs: - - Purpose: instruments the code with the inferred information - and outputs it to a goto-binary - -\*******************************************************************/ - -void summary_checker_baset::instrument_and_output(goto_modelt &goto_model) -{ - instrument_gotot instrument_goto(options, ssa_db, summary_db); - instrument_goto(goto_model); - std::string filename=options.get_option("instrument-output"); - status() << "Writing instrumented goto-binary " << filename << eom; - write_goto_binary( - filename, - goto_model.symbol_table, - goto_model.goto_functions, - get_message_handler()); + return _has_assertion; } diff --git a/src/2ls/summary_checker_base.h b/src/2ls/summary_checker_base.h index d4b1ad0e5..616705696 100644 --- a/src/2ls/summary_checker_base.h +++ b/src/2ls/summary_checker_base.h @@ -34,7 +34,7 @@ class summary_checker_baset:public property_checkert options(_options), ssa_db(_options), summary_db(), ssa_unwinder(ssa_db), - ssa_inliner(summary_db), + ssa_inliner(summary_db, ssa_db), solver_instances(0), solver_calls(0), summaries_used(0), @@ -81,20 +81,16 @@ class summary_checker_baset:public property_checkert bool termination=false); property_checkert::resultt check_properties(); + property_checkert::resultt check_properties( + irep_idt function_name, + irep_idt entry_function, + std::set seen_function_calls, + bool is_inlined); void check_properties( - const ssa_dbt::functionst::const_iterator f_it); - - exprt::operandst get_loophead_selects( - const irep_idt &function_name, const local_SSAt &, prop_convt &); - bool is_spurious( - const exprt::operandst& loophead_selects, - incremental_solvert&); - exprt::operandst get_loop_continues( - const irep_idt &function_name, const local_SSAt &, prop_convt &); - bool is_fully_unwound( - const exprt::operandst& loop_continues, - const exprt::operandst& loophead_selects, - incremental_solvert&); + const ssa_dbt::functionst::const_iterator f_it, + irep_idt entry_function=""); + + bool has_assertion(irep_idt function_name); friend graphml_witness_extt; }; diff --git a/src/deltacheck/deltacheck_parse_options.cpp b/src/deltacheck/deltacheck_parse_options.cpp index 4938e4300..7a5b44378 100644 --- a/src/deltacheck/deltacheck_parse_options.cpp +++ b/src/deltacheck/deltacheck_parse_options.cpp @@ -48,7 +48,7 @@ deltacheck_parse_optionst::deltacheck_parse_optionst( "DeltaCheck " DELTACHECK_VERSION) { } - + /*******************************************************************\ Function: deltacheck_parse_optionst::eval_verbosity @@ -65,7 +65,7 @@ void deltacheck_parse_optionst::eval_verbosity() { // our default verbosity int v=messaget::M_STATISTICS; - + if(cmdline.isset("verbosity")) { v=unsafe_string2int(cmdline.get_value("verbosity")); @@ -74,7 +74,7 @@ void deltacheck_parse_optionst::eval_verbosity() else if(v>10) v=10; } - + ui_message_handler.set_verbosity(v); } @@ -158,7 +158,7 @@ Function: deltacheck_parse_optionst::register_langauges Outputs: - Purpose: + Purpose: \*******************************************************************/ @@ -202,10 +202,10 @@ int deltacheck_parse_optionst::doit() options.set_option("simplify", true); options.set_option("assertions", true); options.set_option("assumptions", true); - + if(cmdline.isset("function")) options.set_option("function", cmdline.get_value("function")); - + if(cmdline.args.size()!=2) { usage_error(); @@ -216,33 +216,33 @@ int deltacheck_parse_optionst::doit() options.set_option("description-old", cmdline.get_value("description-old")); else options.set_option("description-old", cmdline.args[0]); - + if(cmdline.isset("description-new")) options.set_option("description-new", cmdline.get_value("description-new")); else options.set_option("description-new", cmdline.args[1]); - + status() << "Reading first GOTO program from file" << eom; - + goto_modelt goto_model1; if(read_goto_binary(cmdline.args[0], goto_model1, get_message_handler())) return 10; - + status() << "Reading second GOTO program from file" << eom; - + goto_modelt goto_model2; if(read_goto_binary(cmdline.args[1], goto_model2, get_message_handler())) return 10; - + if(cmdline.isset("show-diff")) { change_impactt change_impact; change_impact.set_message_handler(get_message_handler()); - + change_impact.diff(goto_model1, goto_model2); change_impact.output_diff(std::cout); } @@ -250,7 +250,7 @@ int deltacheck_parse_optionst::doit() { change_impactt change_impact; change_impact.set_message_handler(get_message_handler()); - + status() << "Computing syntactic difference" << eom; change_impact.diff(goto_model1, goto_model2); @@ -263,13 +263,13 @@ int deltacheck_parse_optionst::doit() { std::string path1=get_directory(cmdline.args[0]); std::string path2=get_directory(cmdline.args[1]); - + deltacheck_analyzer( path1, goto_model1, path2, goto_model2, options, get_message_handler()); } - + return 0; } @@ -284,18 +284,18 @@ int deltacheck_parse_optionst::doit() error() << e << eom; return 13; } - + catch(int) { return 13; } - + catch(std::bad_alloc) { error() << "Out of memory" << eom; return 14; } - + return 0; } @@ -315,7 +315,7 @@ void deltacheck_parse_optionst::help() { std::cout << "\n" - "* * DELTACHECK " DELTACHECK_VERSION " - Copyright (C) 2011-2015 * *\n" + "* * DELTACHECK " DELTACHECK_VERSION "-Copyright (C) 2011-2015 * *\n" "* * based on CBMC " CBMC_VERSION " * *\n" "* * Daniel Kroening * *\n" "* * Oxford University, Computer Science Department * *\n" @@ -337,8 +337,8 @@ void deltacheck_parse_optionst::help() " --pointer-check add pointer checks\n" " --signed-overflow-check add arithmetic over- and underflow checks\n" " --unsigned-overflow-check add arithmetic over- and underflow checks\n" - " --nan-check add floating-point NaN checks\n" - "\n" + " --nan-check add floating-point NaN checks\n" + "\n" "Other options:\n" " --version show version and exit\n" " --xml-ui use XML-formatted output\n" diff --git a/src/deltacheck/deltacheck_parse_options.h b/src/deltacheck/deltacheck_parse_options.h index dbeb2fa6d..bb3241d33 100644 --- a/src/deltacheck/deltacheck_parse_options.h +++ b/src/deltacheck/deltacheck_parse_options.h @@ -45,7 +45,7 @@ class deltacheck_parse_optionst: virtual void get_command_line_options(optionst &options); void eval_verbosity(); - + ui_message_handlert ui_message_handler; }; diff --git a/src/deltagit/deltagit_parse_options.cpp b/src/deltagit/deltagit_parse_options.cpp index bbd8f4e1d..3868415b1 100644 --- a/src/deltagit/deltagit_parse_options.cpp +++ b/src/deltagit/deltagit_parse_options.cpp @@ -39,7 +39,7 @@ deltagit_parse_optionst::deltagit_parse_optionst( parse_options_baset(DELTACHECK_OPTIONS, argc, argv) { } - + /*******************************************************************\ Function: deltagit_parse_optionst::doit @@ -69,7 +69,7 @@ int deltagit_parse_optionst::doit() } const std::string command=cmdline.args[0]; - + if(command=="jobs") { show_jobs(std::cout); @@ -153,13 +153,13 @@ int deltagit_parse_optionst::doit() std::cerr << e << std::endl; return 13; } - + catch(std::bad_alloc) { std::cerr << "Out of memory" << std::endl; return 14; } - + return 0; } @@ -179,7 +179,7 @@ void deltagit_parse_optionst::help() { std::cout << "\n" - "* * DELTAGIT " DELTACHECK_VERSION " - Copyright (C) 2012-2013 * *\n" + "* * DELTAGIT " DELTACHECK_VERSION "-Copyright (C) 2012-2013 * *\n" "* * Daniel Kroening * *\n" "* * Oxford University, Computer Science Department * *\n" "* * kroening@kroening.com * *\n" @@ -198,7 +198,7 @@ void deltagit_parse_optionst::help() "Reporting options:\n" " --partial-html generate a partial HTML file \"include.html\"\n" " --max-revs report on the last revisions\n" - "\n" + "\n" "Other options:\n" " --version show version and exit\n" " --xml-ui use XML-formatted output\n" diff --git a/src/domains/Makefile b/src/domains/Makefile index f5f1c7082..86018b186 100644 --- a/src/domains/Makefile +++ b/src/domains/Makefile @@ -7,7 +7,7 @@ SRC = tpolyhedra_domain.cpp equality_domain.cpp domain.cpp predabs_domain.cpp\ template_generator_base.cpp template_generator_summary.cpp \ template_generator_callingcontext.cpp template_generator_ranking.cpp \ strategy_solver_binsearch2.cpp strategy_solver_binsearch3.cpp \ - strategy_solver_predabs.cpp \ + strategy_solver_predabs.cpp disjunctive_analyzer.cpp \ simplify_transformer.cpp simplify_bounds.cpp #solver_enumeration.cpp diff --git a/src/domains/disjunctive_analyzer.cpp b/src/domains/disjunctive_analyzer.cpp index 9d619c364..9424d1945 100644 --- a/src/domains/disjunctive_analyzer.cpp +++ b/src/domains/disjunctive_analyzer.cpp @@ -27,12 +27,12 @@ Function: disjunctive_analyzert::eliminate_implication() void disjunctive_analyzert::eliminate_implication(exprt &formula) { - if(formula.id() == ID_implies) - formula = or_exprt(not_exprt(formula.op0()), formula.op1()); - + if(formula.id()==ID_implies) + formula=or_exprt(not_exprt(formula.op0()), formula.op1()); + Forall_operands(it, formula) eliminate_implication(*it); - + return; } @@ -50,29 +50,29 @@ Function: disjunctive_analyzert::push_negation_to_atoms() void disjunctive_analyzert::push_negation_to_atoms(exprt &formula) { - if(formula.id() == ID_not){ - if((formula.op0()).id() == ID_not){ - formula = (formula.op0()).op0(); + if(formula.id()==ID_not){ + if((formula.op0()).id()==ID_not){ + formula=(formula.op0()).op0(); } else{ exprt::operandst operands; Forall_operands(it, formula.op0()) - operands.push_back(not_exprt(*it)); - - if((formula.op0()).id() == ID_and){ - formula = disjunction(operands); + operands.push_back(not_exprt(*it)); + + if((formula.op0()).id()==ID_and){ + formula=disjunction(operands); } else{ - if((formula.op0()).id() == ID_or){ - formula = conjunction(operands); - } + if((formula.op0()).id()==ID_or){ + formula=conjunction(operands); + } } } } Forall_operands(it, formula) push_negation_to_atoms(*it); - + return; } @@ -111,43 +111,43 @@ Function: disjunctive_analyzert::convert_to_dnf_rec() void disjunctive_analyzert::convert_to_dnf_rec(exprt &formula) { - if(formula.id() == ID_or){ + if(formula.id()==ID_or){ Forall_operands(it, formula) convert_to_dnf_rec(*it); } else{ - if(formula.id() == ID_and){ + if(formula.id()==ID_and){ Forall_operands(it, formula) - convert_to_dnf_rec(*it); - + convert_to_dnf_rec(*it); + while((formula.operands()).size() > 1){ - exprt::operandst first_operands, second_operands, combination; - - if(((formula.operands()).back()).id() == ID_or) - first_operands = ((formula.operands()).back()).operands(); - else - first_operands.push_back((formula.operands()).back()); - formula.operands().pop_back(); - - if(((formula.operands()).back()).id() == ID_or) - second_operands = ((formula.operands()).back()).operands(); - else - second_operands.push_back((formula.operands()).back()); - formula.operands().pop_back(); - - for(exprt::operandst::iterator f_it=first_operands.begin();f_it!=first_operands.end();f_it++){ - for(exprt::operandst::iterator s_it=second_operands.begin();s_it!=second_operands.end();s_it++){ - combination.push_back(and_exprt(*f_it,*s_it)); - } - } - - (formula.operands()).push_back(disjunction(combination)); + exprt::operandst first_operands, second_operands, combination; + + if(((formula.operands()).back()).id()==ID_or) + first_operands=((formula.operands()).back()).operands(); + else + first_operands.push_back((formula.operands()).back()); + formula.operands().pop_back(); + + if(((formula.operands()).back()).id()==ID_or) + second_operands=((formula.operands()).back()).operands(); + else + second_operands.push_back((formula.operands()).back()); + formula.operands().pop_back(); + + for(exprt::operandst::iterator f_it=first_operands.begin();f_it!=first_operands.end();f_it++){ + for(exprt::operandst::iterator s_it=second_operands.begin();s_it!=second_operands.end();s_it++){ + combination.push_back(and_exprt(*f_it, *s_it)); + } + } + + (formula.operands()).push_back(disjunction(combination)); } - formula = formula.op0(); + formula=formula.op0(); } } - + return; } @@ -164,143 +164,143 @@ Function: disjunctive_analyzert::operator() \*******************************************************************/ bool disjunctive_analyzert::operator()( - incremental_solvert &solver, - local_SSAt &SSA, - const exprt &side_conditions, - template_generator_baset &template_generator, - const exprt &disjunctive_conditions, - exprt &result_expr, - const domaint::var_sett &vars - ) + incremental_solvert &solver, + local_SSAt &SSA, + const exprt &side_conditions, + template_generator_baset &template_generator, + const exprt &disjunctive_conditions, + exprt &result_expr, + const domaint::var_sett &vars + ) { - bool response = true; + bool response=true; exprt::operandst result; - //std::cout << "unsimplified disjunctive cond: " << from_expr(SSA.ns, "", disjunctive_conditions) << "\n\n"; - exprt simple_disjunctive_conditions = simplify_expr(disjunctive_conditions, SSA.ns); //disjunctive_conditions; - //std::cout << " simplified disjunctive cond: " << from_expr(SSA.ns, "", simple_disjunctive_conditions) << "\n\n"; + // std::cout << "unsimplified disjunctive cond: " << from_expr(SSA.ns, "", disjunctive_conditions) << "\n\n"; + exprt simple_disjunctive_conditions=simplify_expr(disjunctive_conditions, SSA.ns); // disjunctive_conditions; + // std::cout << " simplified disjunctive cond: " << from_expr(SSA.ns, "", simple_disjunctive_conditions) << "\n\n"; - //converting simple_disjunctive_conditions into DNF - //std::cout << "before conversion: " << from_expr(SSA.ns, "", simple_disjunctive_conditions) << "\n\n\n"; + // converting simple_disjunctive_conditions into DNF + // std::cout << "before conversion: " << from_expr(SSA.ns, "", simple_disjunctive_conditions) << "\n\n\n"; this->convert_to_dnf(simple_disjunctive_conditions); - //std::cout << " after conversion: " << from_expr(SSA.ns, "", simple_disjunctive_conditions) << "\n\n\n"; - - if(simple_disjunctive_conditions.id() == ID_or){ + // std::cout << " after conversion: " << from_expr(SSA.ns, "", simple_disjunctive_conditions) << "\n\n\n"; + + if(simple_disjunctive_conditions.id()==ID_or){ exprt::operandst processed_disjuncts; - + exprt::operandst disjuncts=simple_disjunctive_conditions.operands(); for(exprt::operandst::iterator d_it=disjuncts.begin();d_it!=disjuncts.end();d_it++){ - if((*d_it).id() == ID_not){ - //std::cout << "processing (not) disjunct: " << from_expr(SSA.ns, "", *d_it) << "\n"; - - exprt::operandst ops = (*d_it).operands(); - for(exprt::operandst::iterator o_it=ops.begin();o_it!=ops.end();o_it++){ - if((*o_it).id() == ID_equal){ - exprt::operandst ops_equality = (*o_it).operands(); - equal_exprt equal_expr_in_not = to_equal_expr(*o_it); - - bool constant_comparison = false; - for(exprt::operandst::iterator oe_it=ops_equality.begin();oe_it!=ops_equality.end();oe_it++){ - if((*oe_it).id() == ID_constant) - constant_comparison = true; - } - if(constant_comparison){ - processed_disjuncts.push_back(binary_relation_exprt(equal_expr_in_not.rhs(),ID_gt,equal_expr_in_not.lhs())); - processed_disjuncts.push_back(binary_relation_exprt(equal_expr_in_not.rhs(),ID_lt,equal_expr_in_not.lhs())); - } - else{ - processed_disjuncts.push_back(*d_it); - } - } - else{ - processed_disjuncts.push_back(*d_it); - } - } + if((*d_it).id()==ID_not){ + // std::cout << "processing (not) disjunct: " << from_expr(SSA.ns, "", *d_it) << "\n"; + + exprt::operandst ops=(*d_it).operands(); + for(exprt::operandst::iterator o_it=ops.begin();o_it!=ops.end();o_it++){ + if((*o_it).id()==ID_equal){ + exprt::operandst ops_equality=(*o_it).operands(); + equal_exprt equal_expr_in_not=to_equal_expr(*o_it); + + bool constant_comparison=false; + for(exprt::operandst::iterator oe_it=ops_equality.begin();oe_it!=ops_equality.end();oe_it++){ + if((*oe_it).id()==ID_constant) + constant_comparison=true; + } + if(constant_comparison){ + processed_disjuncts.push_back(binary_relation_exprt(equal_expr_in_not.rhs(), ID_gt, equal_expr_in_not.lhs())); + processed_disjuncts.push_back(binary_relation_exprt(equal_expr_in_not.rhs(), ID_lt, equal_expr_in_not.lhs())); + } + else{ + processed_disjuncts.push_back(*d_it); + } + } + else{ + processed_disjuncts.push_back(*d_it); + } + } } else{ - processed_disjuncts.push_back(*d_it); + processed_disjuncts.push_back(*d_it); } } - + for(exprt::operandst::iterator it=processed_disjuncts.begin();it!=processed_disjuncts.end();it++){ - //std::cout << "disjunct: " << from_expr(SSA.ns, "", *it) << "\n"; - + // std::cout << "disjunct: " << from_expr(SSA.ns, "", *it) << "\n"; + std::set disjunct_symbols; - find_symbols(*it,disjunct_symbols); + find_symbols(*it, disjunct_symbols); - //TODO: decompose into convex regions for all variables - //assert(disjunct_symbols.size() == 1); + // TODO: decompose into convex regions for all variables + // assert(disjunct_symbols.size()==1); symbol_exprt var; for(std::set::const_iterator ds_it=disjunct_symbols.begin(); - ds_it!=disjunct_symbols.end(); ds_it++){ - var = *ds_it; + ds_it!=disjunct_symbols.end(); ds_it++){ + var=*ds_it; } - //std::cout << "symbol expr in disjunct: " << var << "\n\n"; + // std::cout << "symbol expr in disjunct: " << var << "\n\n"; exprt::operandst split_disjuncts; - - if((var.type().id() == ID_signedbv) || (var.type().id() == ID_unsignedbv)){ - - exprt smallest; - if(var.type().id()==ID_signedbv) - smallest = to_signedbv_type(var.type()).smallest_expr(); - if(var.type().id()==ID_unsignedbv) - smallest = to_unsignedbv_type(var.type()).smallest_expr(); - - split_disjuncts.push_back - (and_exprt(*it,binary_relation_exprt(var,ID_ge,plus_exprt(smallest,from_integer(mp_integer(1),var.type()))))); - - split_disjuncts.push_back(and_exprt(*it,binary_relation_exprt(var,ID_equal,smallest))); + + if((var.type().id()==ID_signedbv) || (var.type().id()==ID_unsignedbv)){ + + exprt smallest; + if(var.type().id()==ID_signedbv) + smallest=to_signedbv_type(var.type()).smallest_expr(); + if(var.type().id()==ID_unsignedbv) + smallest=to_unsignedbv_type(var.type()).smallest_expr(); + + split_disjuncts.push_back + (and_exprt(*it, binary_relation_exprt(var, ID_ge, plus_exprt(smallest, from_integer(mp_integer(1), var.type()))))); + + split_disjuncts.push_back(and_exprt(*it, binary_relation_exprt(var, ID_equal, smallest))); } else{ - split_disjuncts.push_back(*it); + split_disjuncts.push_back(*it); } for(exprt::operandst::iterator s_it=split_disjuncts.begin();s_it!=split_disjuncts.end();s_it++){ - ssa_analyzert analyzer; - analyzer.set_message_handler(get_message_handler()); - exprt cc = simplify_expr((and_exprt(side_conditions, *s_it)), SSA.ns); - response = response && (analyzer(solver,SSA,cc,template_generator)); - - exprt res; - analyzer.get_result(res, vars); - result.push_back(res); - - //std::cout << "disjunct passed: " << from_expr(SSA.ns, "", cc) << "\n"; - //std::cout << "disjunct's result: " << from_expr(SSA.ns, "", res) << "\n"; - - //statistics - solver_instances += analyzer.get_number_of_solver_instances(); - solver_calls += analyzer.get_number_of_solver_calls(); + ssa_analyzert analyzer; + analyzer.set_message_handler(get_message_handler()); + exprt cc=simplify_expr((and_exprt(side_conditions, *s_it)), SSA.ns); + response=response && (analyzer(solver, SSA, cc, template_generator)); + + exprt res; + analyzer.get_result(res, vars); + result.push_back(res); + + // std::cout << "disjunct passed: " << from_expr(SSA.ns, "", cc) << "\n"; + // std::cout << "disjunct's result: " << from_expr(SSA.ns, "", res) << "\n"; + + // statistics + solver_instances+=analyzer.get_number_of_solver_instances(); + solver_calls+=analyzer.get_number_of_solver_calls(); } } } else{ - //for the complete disjunctive_conditions at once - //std::cout << "disjunction not at top-level" << "\n"; - + // for the complete disjunctive_conditions at once + // std::cout << "disjunction not at top-level" << "\n"; + ssa_analyzert analyzer; analyzer.set_message_handler(get_message_handler()); - exprt cc = simplify_expr((and_exprt(side_conditions, simple_disjunctive_conditions)), SSA.ns); + exprt cc=simplify_expr((and_exprt(side_conditions, simple_disjunctive_conditions)), SSA.ns); + + response=analyzer(solver, SSA, cc, template_generator); - response = analyzer(solver,SSA,cc,template_generator); - exprt res; analyzer.get_result(res, vars); result.push_back(res); - //std::cout << "disjunct passed: " << from_expr(SSA.ns, "", cc) << "\n"; - //std::cout << "disjunct's result: " << from_expr(SSA.ns, "", res) << "\n"; + // std::cout << "disjunct passed: " << from_expr(SSA.ns, "", cc) << "\n"; + // std::cout << "disjunct's result: " << from_expr(SSA.ns, "", res) << "\n"; - //statistics - solver_instances += analyzer.get_number_of_solver_instances(); - solver_calls += analyzer.get_number_of_solver_calls(); + // statistics + solver_instances+=analyzer.get_number_of_solver_instances(); + solver_calls+=analyzer.get_number_of_solver_calls(); } - - result_expr = disjunction(result); + + result_expr=disjunction(result); return response; } diff --git a/src/domains/disjunctive_analyzer.h b/src/domains/disjunctive_analyzer.h index 322d4a0a6..7a1cafbca 100644 --- a/src/domains/disjunctive_analyzer.h +++ b/src/domains/disjunctive_analyzer.h @@ -6,46 +6,45 @@ Author: Peter Schrammel, Kumar Madhukar \*******************************************************************/ -#ifndef DELTACHECK_DISJUNCTIVE_ANALYZER_H -#define DELTACHECK_DISJUNCTIVE_ANALYZER_H +#ifndef CPROVER_2LS_DOMAINS_DISJUNCTIVE_ANALYZER_H +#define CPROVER_2LS_DOMAINS_DISJUNCTIVE_ANALYZER_H class disjunctive_analyzert : public messaget { public: - explicit disjunctive_analyzert() - : - solver_instances(0), + explicit disjunctive_analyzert(): + solver_instances(0), solver_calls(0) - { - } - - ~disjunctive_analyzert() - { - } + { + } + + ~disjunctive_analyzert() + { + } void eliminate_implication(exprt &formula); void push_negation_to_atoms(exprt &formula); void convert_to_dnf(exprt &formula); void convert_to_dnf_rec(exprt &formula); - - bool operator()(incremental_solvert &solver, - local_SSAt &SSA, - const exprt &side_conditions, - template_generator_baset &template_generator, - const exprt &disjunctive_conditions, - exprt &result_expr, - const domaint::var_sett &vars - ); + + bool operator()( + incremental_solvert &solver, + local_SSAt &SSA, + const exprt &side_conditions, + template_generator_baset &template_generator, + const exprt &disjunctive_conditions, + exprt &result_expr, + const domaint::var_sett &vars); unsigned get_number_of_solver_instances() { return solver_instances; } unsigned get_number_of_solver_calls() { return solver_calls; } - + protected: - //statistics + // statistics unsigned solver_instances; unsigned solver_calls; }; #endif - + diff --git a/src/domains/domain.h b/src/domains/domain.h index 82d54a43e..59487f28a 100644 --- a/src/domains/domain.h +++ b/src/domains/domain.h @@ -110,7 +110,7 @@ class domaint } virtual bool is_spec_empty() const { assert(false); } - + static kindt merge_kinds(kindt k1, kindt k2); static void output_var_specs( diff --git a/src/domains/domain_refinement.h b/src/domains/domain_refinement.h index 58d53cf9b..b265b0ea0 100644 --- a/src/domains/domain_refinement.h +++ b/src/domains/domain_refinement.h @@ -17,17 +17,17 @@ class domain_refinementt { public: explicit domain_refinementt( - const local_SSAt &_SSA, - incremental_solvert &_solver) + const local_SSAt &_SSA, + incremental_solvert &_solver) : SSA(_SSA), solver(_solver) {} - //refine, returns true if there are no more refinements + // refine, returns true if there are no more refinements virtual bool operator()() { return true; } - //template generators associated with this SSA and solver + // template generators associated with this SSA and solver typedef std::map template_generatorst; template_generatorst template_generators; diff --git a/src/domains/domain_refinement_variables.cpp b/src/domains/domain_refinement_variables.cpp index f8e313ea4..cb906d8d1 100644 --- a/src/domains/domain_refinement_variables.cpp +++ b/src/domains/domain_refinement_variables.cpp @@ -8,13 +8,13 @@ Author: Peter Schrammel bool domain_refinementt::operator()() { - //TODO: analyze counterexample - for(template_generatorst::iterator it = template_generators.begin(); - it != template_generators.end(); ++it) + // TODO: analyze counterexample + for(template_generatorst::iterator it=template_generators.begin(); + it!=template_generators.end(); ++it) { - //TODO: select refinement to be performed + // TODO: select refinement to be performed - //TODO: update template and domain - //it->add_template(); + // TODO: update template and domain + // it->add_template(); } } diff --git a/src/domains/incremental_solver.cpp b/src/domains/incremental_solver.cpp index 044f48a40..750073850 100644 --- a/src/domains/incremental_solver.cpp +++ b/src/domains/incremental_solver.cpp @@ -150,7 +150,8 @@ Function: incremental_solvert::debug_add_to_formula \*******************************************************************/ -void incremental_solvert::debug_add_to_formula(const exprt &expr) +void incremental_solvert::debug_add_to_formula( + const exprt &_expr, exprt activation) { if(_expr.id()!=ID_and) { @@ -163,25 +164,25 @@ void incremental_solvert::debug_add_to_formula(const exprt &expr) expr=_expr; else expr=or_exprt(_expr, activation); - literalt l = solver->convert(expr); + literalt l=solver->convert(expr); if(l.is_false()) { #ifdef DEBUG_OUTPUT - debug() << "literal " << l << ": false = " << from_expr(ns, "", expr) <convert(symbol_exprt("goto_symex::\\dummy", bool_typet())); formula.push_back(dummy); formula.push_back(!dummy); #ifdef DEBUG_OUTPUT - debug() << "literal " << dummy << ", " << !dummy << ": " + debug() << "literal " << dummy << ", " << !dummy << ": " << from_expr(ns, "", expr) << eom; #endif } - else if(!l.is_true()) + else if(!l.is_true()) { #ifdef DEBUG_OUTPUT - debug() << "literal " << l << ": " << from_expr(ns,"",expr) << eom; + debug() << "literal " << l << ": " << from_expr(ns, "", expr) << eom; #endif formula.push_back(l); formula_expr.push_back(expr); diff --git a/src/domains/incremental_solver.h b/src/domains/incremental_solver.h index ca4369be2..f25f2ef57 100644 --- a/src/domains/incremental_solver.h +++ b/src/domains/incremental_solver.h @@ -95,15 +95,15 @@ class incremental_solvert:public messaget #endif #endif #if defined(DEBUG_FORMULA) || defined(DISPLAY_FORMULA) - decision_proceduret::resultt result = (*solver)(); + decision_proceduret::resultt result=(*solver)(); #endif #if defined(DEBUG_FORMULA) && defined(DEBUG_OUTPUT) if(result==decision_proceduret::D_UNSATISFIABLE) { - for(unsigned i=0; iis_in_conflict(formula[i])) - std::cout << "is_in_conflict: " + std::cout << "is_in_conflict: " << from_expr(ns, "", formula_expr[i]) << std::endl; } } @@ -112,12 +112,12 @@ class incremental_solvert:public messaget if(result==decision_proceduret::D_SATISFIABLE) { std::set vars; - for(unsigned i=0; i::const_iterator it = vars.begin(); - it != vars.end(); ++it) + for(std::set::const_iterator it=vars.begin(); + it!=vars.end(); ++it) { - std::cout << "assignment: " << from_expr(ns, "", *it) << " = " + std::cout << "assignment: " << from_expr(ns, "", *it) << "=" << from_expr(ns, "", solver->get(*it)) << std::endl; } } diff --git a/src/domains/lexlinrank_solver_enumeration.cpp b/src/domains/lexlinrank_solver_enumeration.cpp index 283786ad4..223ad8b8d 100644 --- a/src/domains/lexlinrank_solver_enumeration.cpp +++ b/src/domains/lexlinrank_solver_enumeration.cpp @@ -1,6 +1,6 @@ /*******************************************************************\ -Module: Enumeration-based solver for lexicographic linear ranking +Module: Enumeration-based solver for lexicographic linear ranking functions Author: Peter Schrammel @@ -189,7 +189,7 @@ lexlinrank_solver_enumerationt::progresst lexlinrank_solver_enumerationt::iterat } } - progress=CHANGED; + progress=CHANGED; // update the current template lexlinrank_domain.set_row_value(row, new_row_values, rank); @@ -220,7 +220,7 @@ lexlinrank_solver_enumerationt::progresst lexlinrank_solver_enumerationt::iterat if(lexlinrank_domain.refine()) { debug() << "refining..." << eom; - improved=true; // refinement possible + progress=CHANGED; // refinement possible if(!refinement_constraint.is_true()) inner_solver->pop_context(); diff --git a/src/domains/lexlinrank_solver_enumeration.h b/src/domains/lexlinrank_solver_enumeration.h index 204b23e14..257be310f 100644 --- a/src/domains/lexlinrank_solver_enumeration.h +++ b/src/domains/lexlinrank_solver_enumeration.h @@ -1,6 +1,6 @@ /*******************************************************************\ -Module: Enumeration-based solver for lexicographic linear ranking +Module: Enumeration-based solver for lexicographic linear ranking functions Author: Peter Schrammel @@ -26,7 +26,7 @@ class lexlinrank_solver_enumerationt:public strategy_solver_baset const namespacet &_ns, unsigned _max_elements, // lexicographic components unsigned _max_inner_iterations): - strategy_solver_baset(_solver, _ns), + strategy_solver_baset(_solver, const_literal(true), _ns), lexlinrank_domain(_lexlinrank_domain), max_elements(_max_elements), max_inner_iterations(_max_inner_iterations), diff --git a/src/domains/ranking_solver_enumeration.cpp b/src/domains/ranking_solver_enumeration.cpp index 908acad1a..2d35335be 100644 --- a/src/domains/ranking_solver_enumeration.cpp +++ b/src/domains/ranking_solver_enumeration.cpp @@ -142,7 +142,7 @@ ranking_solver_enumerationt::progresst ranking_solver_enumerationt::iterate(inva // update the current template linrank_domain.set_row_value(row, new_row_values, rank); - improved=true; + progress=CHANGED; } else { diff --git a/src/domains/simplify_bounds.cpp b/src/domains/simplify_bounds.cpp index cfa64de81..8c63fa646 100644 --- a/src/domains/simplify_bounds.cpp +++ b/src/domains/simplify_bounds.cpp @@ -25,7 +25,7 @@ Function: simplify_boundst::get_min_bound Inputs: - Outputs: + Outputs: Purpose: @@ -88,7 +88,7 @@ Function: simplify_boundst::get_max_bound Inputs: - Outputs: + Outputs: Purpose: @@ -167,7 +167,7 @@ bool simplify_boundst::simplify_rec(exprt &expr) bool result=true; if(expr.id()==ID_le) { - binary_relation_exprt &e = to_binary_relation_expr(expr); + binary_relation_exprt &e=to_binary_relation_expr(expr); if(is_bitvector_type(e.rhs().type()) && e.rhs().id()==ID_constant && e.lhs().id()!=ID_symbol) { @@ -181,7 +181,7 @@ bool simplify_boundst::simplify_rec(exprt &expr) result=false; } else - result=clean_up_typecast(expr,rhs_value); + result=clean_up_typecast(expr, rhs_value); } else if(get_min_bound(e.lhs(), lhs_min)) { @@ -195,7 +195,7 @@ bool simplify_boundst::simplify_rec(exprt &expr) } else if(expr.id()==ID_ge) { - binary_relation_exprt &e = to_binary_relation_expr(expr); + binary_relation_exprt &e=to_binary_relation_expr(expr); if(is_bitvector_type(e.rhs().type()) && e.rhs().id()==ID_constant && e.lhs().id()!=ID_symbol) { @@ -221,7 +221,7 @@ bool simplify_boundst::simplify_rec(exprt &expr) } else if(expr.id()==ID_lt) { - binary_relation_exprt &e = to_binary_relation_expr(expr); + binary_relation_exprt &e=to_binary_relation_expr(expr); if(is_bitvector_type(e.rhs().type()) && e.rhs().id()==ID_constant && e.lhs().id()!=ID_symbol) { @@ -247,7 +247,7 @@ bool simplify_boundst::simplify_rec(exprt &expr) } else if(expr.id()==ID_gt) { - binary_relation_exprt &e = to_binary_relation_expr(expr); + binary_relation_exprt &e=to_binary_relation_expr(expr); if(is_bitvector_type(e.rhs().type()) && e.rhs().id()==ID_constant && e.lhs().id()!=ID_symbol) { @@ -271,7 +271,7 @@ bool simplify_boundst::simplify_rec(exprt &expr) } } } - else + else { Forall_operands(it, expr) if(!simplify_rec(*it)) @@ -282,7 +282,7 @@ bool simplify_boundst::simplify_rec(exprt &expr) << "\n ---> " << from_expr(ns, "", expr) << "\n"; #endif - + return result; } @@ -292,13 +292,13 @@ Function: simplify_boundst::clean_up_typecast Inputs: - Outputs: + Outputs: Purpose: \*******************************************************************/ -bool simplify_boundst::clean_up_typecast(exprt &expr, +bool simplify_boundst::clean_up_typecast(exprt &expr, const mp_integer &rhs_value) { if(expr.id()==ID_le && expr.op0().id()==ID_unary_minus && @@ -308,7 +308,7 @@ bool simplify_boundst::clean_up_typecast(exprt &expr, if(-rhs_value>get_smallest(inner_type)) { expr=binary_relation_exprt(expr.op0().op0().op0(), ID_ge, - from_integer(-rhs_value,inner_type)); + from_integer(-rhs_value, inner_type)); return true; } } @@ -321,7 +321,7 @@ Function: simplify_boundst::clean_up_implications Inputs: - Outputs: + Outputs: Purpose: @@ -340,14 +340,14 @@ bool simplify_boundst::clean_up_implications(exprt &expr) { if(it->is_true()) it=expr.operands().erase(it); - else + else ++it; } if(expr.operands().empty()) expr=true_exprt(); else if(expr.operands().size()==1) expr=expr.op0(); - } + } else if(expr.id()==ID_implies) { if(expr.op1().is_true()) @@ -365,7 +365,7 @@ Function: simplify_boundst::clean_up_implications Inputs: - Outputs: + Outputs: Purpose: @@ -380,7 +380,7 @@ bool simplify_boundst::regroup_implications(exprt &expr) Forall_operands(it, expr) if(it->id()==ID_implies) implication_map[it->op0()].push_back(it->op1()); - else + else r.push_back(*it); } else @@ -425,7 +425,7 @@ Function: simplify \*******************************************************************/ -bool simplify_bounds(exprt &expr, +bool simplify_bounds(exprt &expr, const namespacet &ns) { return simplify_boundst(ns)(expr); @@ -443,7 +443,7 @@ Function: simplify_bounds \*******************************************************************/ -exprt simplify_bounds(const exprt &src, +exprt simplify_bounds(const exprt &src, const namespacet &ns) { exprt tmp=src; diff --git a/src/domains/simplify_bounds_class.h b/src/domains/simplify_bounds_class.h index 3510f42ed..941320572 100644 --- a/src/domains/simplify_bounds_class.h +++ b/src/domains/simplify_bounds_class.h @@ -31,7 +31,7 @@ class simplify_boundst // If false is returned, the expression has changed. virtual bool operator()(exprt &expr); - + inline static bool is_bitvector_type(const typet &type) { return type.id()==ID_unsignedbv || diff --git a/src/domains/simplify_transformer.cpp b/src/domains/simplify_transformer.cpp index 87f43673d..4a8db3274 100644 --- a/src/domains/simplify_transformer.cpp +++ b/src/domains/simplify_transformer.cpp @@ -38,30 +38,30 @@ void simplify_transformert::collect_node(const exprt &expr, { if(expr.id()==ID_equal) { - const equal_exprt &e = to_equal_expr(expr); - + const equal_exprt &e=to_equal_expr(expr); + bool rhs_is_constant=e.rhs().id()==ID_constant; - bool rhs_is_symbol=e.rhs().id()==ID_symbol || + bool rhs_is_symbol=e.rhs().id()==ID_symbol || e.rhs().id()==ID_nondet_symbol; bool rhs_is_frozen=rhs_is_symbol && frozen_symbols.find(e.rhs().get(ID_identifier))!=frozen_symbols.end(); bool lhs_is_constant=e.lhs().id()==ID_constant; - bool lhs_is_symbol=e.lhs().id()==ID_symbol || + bool lhs_is_symbol=e.lhs().id()==ID_symbol || e.lhs().id()==ID_nondet_symbol; bool lhs_is_frozen=lhs_is_symbol && frozen_symbols.find(e.lhs().get(ID_identifier))!=frozen_symbols.end(); exprt lhs, rhs; - lhs.make_nil(); + lhs.make_nil(); rhs.make_nil(); - //stupid matching - if((rhs_is_frozen || rhs_is_constant || !frozen_only) && + // stupid matching + if((rhs_is_frozen || rhs_is_constant || !frozen_only) && lhs_is_symbol && !lhs_is_frozen) { lhs=e.lhs(); rhs=e.rhs(); } - if((lhs_is_frozen || lhs_is_constant || !frozen_only) && + if((lhs_is_frozen || lhs_is_constant || !frozen_only) && rhs_is_symbol && !rhs_is_frozen) { rhs=e.lhs(); @@ -69,10 +69,10 @@ void simplify_transformert::collect_node(const exprt &expr, } if(rhs.is_not_nil() && lhs.is_not_nil()) { - if(make_copy) //make lazy copy + if(make_copy) // make lazy copy { - replace_mapt _subst = substitutions; - substitutions = _subst; + replace_mapt _subst=substitutions; + substitutions=_subst; } substitutions[lhs]=rhs; } @@ -128,7 +128,7 @@ bool simplify_transformert::simplify_rec(exprt &expr, bool result=true; if(expr.id()==ID_and) { - //first propagate from frozen symbols + // first propagate from frozen symbols bool res=false; do { @@ -138,13 +138,13 @@ bool simplify_transformert::simplify_rec(exprt &expr, Forall_operands(it, expr) if(!simplify_rec(*it, substitutions)) result=false; - + res=simplify_node(expr, substitutions); if(!res) result=false; } while(!res); - //simplify remaining equalities + // simplify remaining equalities Forall_operands(it, expr) collect_node(*it, substitutions, false, false); @@ -155,10 +155,10 @@ bool simplify_transformert::simplify_rec(exprt &expr, if(!res) result=false; } while(!res); - } + } -#if 0 //for later extension to disjunctions - //TODO: handle negation, too +#if 0 // for later extension to disjunctions + // TODO: handle negation, too else if(expr.id()==ID_or || expr.id()==ID_implies) { Forall_operands(it, expr) @@ -166,7 +166,7 @@ bool simplify_transformert::simplify_rec(exprt &expr, collect_node(*it, substitutions, true); if(!simplify_rec(*it, substitutions)) result=false; - + bool res=false; do { @@ -177,13 +177,13 @@ bool simplify_transformert::simplify_rec(exprt &expr, } } #endif - + #ifdef DEBUGX std::cout << "===== " << from_expr(ns, "", old) << "\n ---> " << from_expr(ns, "", expr) << "\n"; #endif - + return result; } @@ -217,8 +217,8 @@ Function: simplify \*******************************************************************/ -bool simplify(exprt &expr, - const std::set &frozen_vars, +bool simplify(exprt &expr, + const std::set &frozen_vars, const namespacet &ns) { return simplify_transformert(ns, frozen_vars)(expr); @@ -236,7 +236,7 @@ Function: simplify_transformer \*******************************************************************/ -exprt simplify_transformer(const exprt &src, +exprt simplify_transformer(const exprt &src, const std::set &frozen_vars, const namespacet &ns) { diff --git a/src/domains/simplify_transformer.h b/src/domains/simplify_transformer.h index 32a815c8c..19d6b7c99 100644 --- a/src/domains/simplify_transformer.h +++ b/src/domains/simplify_transformer.h @@ -24,12 +24,12 @@ class namespacet; bool simplify( exprt &expr, - const std::set &frozen_vars, //do not eliminate these + const std::set &frozen_vars, // do not eliminate these const namespacet &ns); exprt simplify_transformer( const exprt &src, - const std::set &frozen_vars, //do not eliminate these + const std::set &frozen_vars, // do not eliminate these const namespacet &ns); #endif diff --git a/src/domains/simplify_transformer_class.h b/src/domains/simplify_transformer_class.h index ccae118b4..2129c44f6 100644 --- a/src/domains/simplify_transformer_class.h +++ b/src/domains/simplify_transformer_class.h @@ -19,7 +19,7 @@ class simplify_transformert { public: explicit simplify_transformert(const namespacet &_ns, - const std::set &_frozen_symbols): + const std::set &_frozen_symbols): ns(_ns), frozen_symbols(_frozen_symbols) { @@ -34,16 +34,16 @@ class simplify_transformert // main recursion bool simplify_rec(exprt &expr, replace_mapt &substitutions); - + virtual bool operator()(exprt &expr); - + inline static bool is_bitvector_type(const typet &type) { return type.id()==ID_unsignedbv || type.id()==ID_signedbv || type.id()==ID_bv; } - + protected: const namespacet &ns; const std::set &frozen_symbols; diff --git a/src/domains/ssa_analyzer.cpp b/src/domains/ssa_analyzer.cpp index ddd5a4664..c01a1917e 100644 --- a/src/domains/ssa_analyzer.cpp +++ b/src/domains/ssa_analyzer.cpp @@ -32,13 +32,16 @@ Author: Peter Schrammel #include "strategy_solver_predabs.h" #include "ssa_analyzer.h" -#define BINSEARCH_SOLVER strategy_solver_binsearcht(\ - *static_cast(domain), solver, SSA.ns) +#define BINSEARCH_SOLVER strategy_solver_binsearcht( \ + *static_cast(domain), \ + solver, assertions_check, SSA.ns) #if 0 -#define BINSEARCH_SOLVER strategy_solver_binsearch2t(\ - *static_cast(domain), solver, SSA.ns) -#define BINSEARCH_SOLVER strategy_solver_binsearch3t(\ - *static_cast(domain), solver, SSA, SSA.ns) +#define BINSEARCH_SOLVER strategy_solver_binsearch2t( \ + *static_cast(domain), solver, \ + assertions_check, SSA.ns) +#define BINSEARCH_SOLVER strategy_solver_binsearch3t( \ + *static_cast(domain), solver, \ + assertions_check, SSA, SSA.ns) #endif /*******************************************************************\ @@ -47,7 +50,7 @@ Function: ssa_analyzert::operator() Inputs: - Outputs: true if the computation was not aborted due to + Outputs: true if the computation was not aborted due to assertion_checks that did not pass Purpose: @@ -78,24 +81,24 @@ bool ssa_analyzert::operator()( literalt assertions_check=const_literal(false); bvt assertion_literals; if(check_assertions) - { + { exprt::operandst ll; for(local_SSAt::nodest::iterator n_it=SSA.nodes.begin(); - n_it!=SSA.nodes.end(); n_it++) + n_it!=SSA.nodes.end(); n_it++) { assert(n_it->assertions.size()<=1); for(local_SSAt::nodet::assertionst::const_iterator - a_it=n_it->assertions.begin(); - a_it!=n_it->assertions.end(); - a_it++) + a_it=n_it->assertions.begin(); + a_it!=n_it->assertions.end(); + a_it++) { - literalt l=solver.solver->convert(*a_it); - assertion_literals.push_back(!l); - ll.push_back(literal_exprt(!l)); - nonpassed_assertions.push_back(n_it); + literalt l=solver.solver->convert(*a_it); + assertion_literals.push_back(!l); + ll.push_back(literal_exprt(!l)); + nonpassed_assertions.push_back(n_it); } } - assertions_check = solver.solver->convert(disjunction(ll)); + assertions_check=solver.solver->convert(disjunction(ll)); } // get strategy solver from options @@ -125,7 +128,8 @@ bool ssa_analyzert::operator()( else if(template_generator.options.get_bool_option("equalities")) { strategy_solver=new strategy_solver_equalityt( - *static_cast(domain), solver, SSA.ns); + *static_cast(domain), + solver, assertions_check, SSA.ns); result=new equality_domaint::equ_valuet(); } else @@ -134,14 +138,15 @@ bool ssa_analyzert::operator()( { result=new tpolyhedra_domaint::templ_valuet(); strategy_solver=new strategy_solver_enumerationt( - *static_cast(domain), solver, SSA.ns); + *static_cast(domain), + solver, assertions_check, SSA.ns); } else if(template_generator.options.get_bool_option("predabs-solver")) { result=new predabs_domaint::templ_valuet(); strategy_solver=new strategy_solver_predabst( - *static_cast(domain), solver, - assertions_check, SSA.ns); + *static_cast(domain), + solver, assertions_check, SSA.ns); } else if(template_generator.options.get_bool_option("binsearch-solver")) { @@ -165,21 +170,15 @@ bool ssa_analyzert::operator()( } while(status==strategy_solver_baset::CHANGED); -#ifdef DEBUG - std::cout << "Fixed-point after " << iteration_number - << " iteration(s)\n"; - domain->output_value(std::cout,*result,SSA.ns); -#endif - - //get status of assertions - if(!assertions_check.is_false() && + // get status of assertions + if(!assertions_check.is_false() && status==strategy_solver_baset::FAILED) { nonpassed_assertionst::iterator it=nonpassed_assertions.begin(); for(unsigned i=0;il_get(assertion_literals[i]).is_true()) - nonpassed_assertions.erase(it++); + nonpassed_assertions.erase(it++); else ++it; } } @@ -187,7 +186,7 @@ bool ssa_analyzert::operator()( solver.pop_context(); - //statistics + // statistics solver_calls+=strategy_solver->get_number_of_solver_calls(); solver_instances+=strategy_solver->get_number_of_solver_instances(); diff --git a/src/domains/ssa_analyzer.h b/src/domains/ssa_analyzer.h index 35fd52edd..35cc63626 100644 --- a/src/domains/ssa_analyzer.h +++ b/src/domains/ssa_analyzer.h @@ -35,20 +35,20 @@ class ssa_analyzert:public messaget delete result; } - void operator()( + bool operator()( incremental_solvert &solver, local_SSAt &SSA, const exprt &precondition, template_generator_baset &template_generator, bool check_assertions=false); - //retrieve the result if operator() returned true + // retrieve the result if operator() returned true void get_result(exprt &result, const domaint::var_sett &vars); - //retrieve the non-passed assertions if operator() returned false - typedef std::list + // retrieve the non-passed assertions if operator() returned false + typedef std::list nonpassed_assertionst; - nonpassed_assertionst get_nonpassed_assertions() + nonpassed_assertionst get_nonpassed_assertions() { return nonpassed_assertions; } inline unsigned get_number_of_solver_instances() { return solver_instances; } diff --git a/src/domains/strategy_solver_base.h b/src/domains/strategy_solver_base.h index 7ef72b19c..1244a7bdc 100644 --- a/src/domains/strategy_solver_base.h +++ b/src/domains/strategy_solver_base.h @@ -32,7 +32,7 @@ class strategy_solver_baset:public messaget solver_calls(0) {} - virtual bool iterate(invariantt &inv) { assert(false); } + virtual progresst iterate(invariantt &inv) { assert(false); } unsigned get_number_of_solver_calls() { return solver_calls; } unsigned get_number_of_solver_instances() { return solver_instances; } diff --git a/src/domains/strategy_solver_binsearch.cpp b/src/domains/strategy_solver_binsearch.cpp index 5a354d3d1..6731ef713 100644 --- a/src/domains/strategy_solver_binsearch.cpp +++ b/src/domains/strategy_solver_binsearch.cpp @@ -66,7 +66,7 @@ strategy_solver_baset::progresst strategy_solver_binsearcht::iterate(invariantt #endif solver << or_exprt(disjunction(strategy_cond_exprs), - literal_exprt(assertion_check)); + literal_exprt(assertion_check)); #if 0 debug() << "solve(): "; diff --git a/src/domains/strategy_solver_binsearch2.cpp b/src/domains/strategy_solver_binsearch2.cpp index 6fdb00a1e..d97bb40a8 100644 --- a/src/domains/strategy_solver_binsearch2.cpp +++ b/src/domains/strategy_solver_binsearch2.cpp @@ -32,7 +32,8 @@ Function: strategy_solver_binsearch2t::iterate \*******************************************************************/ -bool strategy_solver_binsearch2t::iterate(invariantt &_inv) +strategy_solver_binsearch2t::progresst +strategy_solver_binsearch2t::iterate(invariantt &_inv) { tpolyhedra_domaint::templ_valuet &inv= static_cast(_inv); diff --git a/src/domains/strategy_solver_binsearch2.h b/src/domains/strategy_solver_binsearch2.h index 586116e52..0692418a6 100644 --- a/src/domains/strategy_solver_binsearch2.h +++ b/src/domains/strategy_solver_binsearch2.h @@ -19,8 +19,9 @@ class strategy_solver_binsearch2t:public strategy_solver_baset strategy_solver_binsearch2t( tpolyhedra_domaint &_tpolyhedra_domain, incremental_solvert &_solver, + literalt _assertion_check, const namespacet &_ns): - strategy_solver_baset(_solver, _ns), + strategy_solver_baset(_solver, _assertion_check, _ns), tpolyhedra_domain(_tpolyhedra_domain), sum_bound_counter(0) { diff --git a/src/domains/strategy_solver_binsearch3.cpp b/src/domains/strategy_solver_binsearch3.cpp index f7d795115..8be4c7136 100644 --- a/src/domains/strategy_solver_binsearch3.cpp +++ b/src/domains/strategy_solver_binsearch3.cpp @@ -31,12 +31,13 @@ Function: strategy_solver_binsearch3t::iterate \*******************************************************************/ -strategy_solver_baset::progresst strategy_solver_binsearch3t::iterate(invariantt &_inv) +strategy_solver_baset::progresst +strategy_solver_binsearch3t::iterate(invariantt &_inv) { tpolyhedra_domaint::templ_valuet &inv= static_cast(_inv); - progresst progress = CONVERGED; + progresst progress=CONVERGED; solver.new_context(); // for improvement check @@ -109,7 +110,7 @@ strategy_solver_baset::progresst strategy_solver_binsearch3t::iterate(invariantt } solver.pop_context(); // improvement check - if(progress!=CHANGED) //done + if(progress!=CHANGED) // done { #if 0 debug() << "UNSAT" << eom; @@ -151,7 +152,7 @@ strategy_solver_baset::progresst strategy_solver_binsearch3t::iterate(invariantt // do not solve system if we have just reached a new loop // (the system will be very large!) if(improved_from_neginf) - return improved; + return progress; solver.new_context(); // symbolic value system solver << pre_inv_expr; diff --git a/src/domains/strategy_solver_binsearch3.h b/src/domains/strategy_solver_binsearch3.h index fa7afd53e..a7af92f94 100644 --- a/src/domains/strategy_solver_binsearch3.h +++ b/src/domains/strategy_solver_binsearch3.h @@ -21,8 +21,9 @@ class strategy_solver_binsearch3t:public strategy_solver_baset tpolyhedra_domaint &_tpolyhedra_domain, incremental_solvert &_solver, local_SSAt& _SSA, + literalt _assertion_check, const namespacet &_ns): - strategy_solver_baset(_solver, _ns), + strategy_solver_baset(_solver, _assertion_check, _ns), SSA(_SSA), tpolyhedra_domain(_tpolyhedra_domain), sum_bound_counter(0) {} diff --git a/src/domains/strategy_solver_enumeration.cpp b/src/domains/strategy_solver_enumeration.cpp index b7b089907..6da344a50 100644 --- a/src/domains/strategy_solver_enumeration.cpp +++ b/src/domains/strategy_solver_enumeration.cpp @@ -68,8 +68,8 @@ strategy_solver_baset::progresst strategy_solver_enumerationt::iterate(invariant debug() << eom; #endif - solver << or_exprt(disjunction(strategy_cond_exprs), - literal_exprt(assertion_check)); + solver << or_exprt(disjunction(strategy_cond_exprs), + literal_exprt(assertion_check)); #ifdef DEBUG_OUTPUT debug() << "solve(): "; @@ -148,11 +148,11 @@ strategy_solver_baset::progresst strategy_solver_enumerationt::iterate(invariant progress=CHANGED; } } - if(!progress==CHANGED) //only possible if assertion check fails + if(!progress==CHANGED) // only possible if assertion check fails { solver.pop_context(); return FAILED; - } + } } else { diff --git a/src/domains/strategy_solver_enumeration.h b/src/domains/strategy_solver_enumeration.h index ff7420833..4383e4d0e 100644 --- a/src/domains/strategy_solver_enumeration.h +++ b/src/domains/strategy_solver_enumeration.h @@ -17,11 +17,11 @@ class strategy_solver_enumerationt:public strategy_solver_baset public: strategy_solver_enumerationt( tpolyhedra_domaint &_tpolyhedra_domain, - incremental_solvert &_solver, + incremental_solvert &_solver, literalt _assertion_check, - const namespacet &_ns): + const namespacet &_ns): strategy_solver_baset(_solver, _assertion_check, _ns), - tpolyhedra_domain(_tpolyhedra_domain) + tpolyhedra_domain(_tpolyhedra_domain) { } diff --git a/src/domains/strategy_solver_equality.cpp b/src/domains/strategy_solver_equality.cpp index ff7acca05..43602e881 100644 --- a/src/domains/strategy_solver_equality.cpp +++ b/src/domains/strategy_solver_equality.cpp @@ -21,7 +21,7 @@ Function: strategy_solver_equalityt::iterate Outputs: - Purpose: Comment: assertion check is not possible + Purpose: Comment: assertion check is not possible because this is a gfp solver \*******************************************************************/ @@ -84,7 +84,7 @@ strategy_solver_baset::progresst strategy_solver_equalityt::iterate(invariantt & { e_it=todo_disequs.begin(); if(e_it==todo_disequs.end()) - return false; // done + return CONVERGED; // done solver.new_context(); diff --git a/src/domains/strategy_solver_predabs.cpp b/src/domains/strategy_solver_predabs.cpp index c3f5fe2ca..353c0ea4f 100644 --- a/src/domains/strategy_solver_predabs.cpp +++ b/src/domains/strategy_solver_predabs.cpp @@ -26,7 +26,8 @@ Function: strategy_solver_predabst::iterate \*******************************************************************/ -bool strategy_solver_predabst::iterate(invariantt &_inv) +strategy_solver_predabst::progresst +strategy_solver_predabst::iterate(invariantt &_inv) { predabs_domaint::templ_valuet &inv= static_cast(_inv); @@ -96,8 +97,8 @@ bool strategy_solver_predabst::iterate(invariantt &_inv) todo_preds.erase(e_it); - return true; + return CHANGED; } - return false; + return CONVERGED; } diff --git a/src/domains/strategy_solver_predabs.h b/src/domains/strategy_solver_predabs.h index 1654e9729..b7ec0695d 100644 --- a/src/domains/strategy_solver_predabs.h +++ b/src/domains/strategy_solver_predabs.h @@ -18,14 +18,15 @@ class strategy_solver_predabst:public strategy_solver_baset explicit strategy_solver_predabst( predabs_domaint &_predabs_domain, incremental_solvert &_solver, + literalt _assertion_check, const namespacet &_ns): - strategy_solver_baset(_solver, _ns), + strategy_solver_baset(_solver, _assertion_check, _ns), predabs_domain(_predabs_domain) { predabs_domain.get_row_set(todo_preds); } - virtual bool iterate(invariantt &inv); + virtual progresst iterate(invariantt &inv); protected: predabs_domaint &predabs_domain; diff --git a/src/domains/template_generator_base.h b/src/domains/template_generator_base.h index 231154986..8b9b802dc 100644 --- a/src/domains/template_generator_base.h +++ b/src/domains/template_generator_base.h @@ -80,6 +80,12 @@ class template_generator_baset:public messaget domaint::guardt post_guard, const domaint::kindt &kind, domaint::var_specst &var_specs); + void add_vars( + const std::set &vars_to_add, + const domaint::guardt &pre_guard, + const domaint::guardt &post_guard, + const domaint::kindt &kind, + domaint::var_specst &var_specs); void add_vars( const var_listt &vars_to_add, const domaint::guardt &pre_guard, diff --git a/src/domains/template_generator_summary.cpp b/src/domains/template_generator_summary.cpp index e50835e82..3fbddd77f 100644 --- a/src/domains/template_generator_summary.cpp +++ b/src/domains/template_generator_summary.cpp @@ -107,7 +107,7 @@ void template_generator_summaryt::collect_variables_inout( // add nondets for backwards analysis if(!forward) { - add_vars(SSA.nondets,first_guard,first_guard, + add_vars(SSA.nondets, first_guard, first_guard, domaint::OUT, var_specs); } } diff --git a/src/domains/tpolyhedra_domain.cpp b/src/domains/tpolyhedra_domain.cpp index 25997d740..917d45830 100644 --- a/src/domains/tpolyhedra_domain.cpp +++ b/src/domains/tpolyhedra_domain.cpp @@ -55,7 +55,7 @@ void tpolyhedra_domaint::initialize(valuet &value) v[row]=false_exprt(); // marker for -oo } - refine(); //initialise refinements + refine(); // initialise refinements } /*******************************************************************\ @@ -980,11 +980,11 @@ bool tpolyhedra_domaint::is_row_value_inf( to_integer(row_value, rvalue); const typet &inner_type=row_expr.op0().op0().type(); mp_integer smallest; - if(inner_type.id()==ID_unsignedbv) + if(inner_type.id()==ID_unsignedbv) smallest=to_unsignedbv_type(inner_type).smallest(); - else if(inner_type.id()==ID_signedbv) + else if(inner_type.id()==ID_signedbv) smallest=to_signedbv_type(inner_type).smallest(); - else + else return false; if(smallest==rvalue) return true; @@ -1250,40 +1250,40 @@ Function: tpolyhedra_domaint::refine void tpolyhedra_domaint::replace_comparison(exprt &expr, bool greater) { - //TODO + // TODO } bool tpolyhedra_domaint::refine() { return false; - //TODO - if(current_refinement==0) //initialise + // TODO + if(current_refinement==0) // initialise { if(refinement_exprs.size()==0) { - max_refinements = 0; + max_refinements=0; return false; } - max_refinements = 3; - current_refinement = 1; + max_refinements=3; + current_refinement=1; exprt::operandst c; - //TODO - current_refinement_expr = conjunction(c); + // TODO + current_refinement_expr=conjunction(c); return true; } - if(current_refinement>max_refinements) + if(current_refinement>max_refinements) return false; if(current_refinement==1) { exprt::operandst c; - //TODO - current_refinement_expr = conjunction(c); + // TODO + current_refinement_expr=conjunction(c); } else if(current_refinement==2) - current_refinement_expr = true_exprt(); + current_refinement_expr=true_exprt(); current_refinement++; return true; diff --git a/src/domains/tpolyhedra_domain.h b/src/domains/tpolyhedra_domain.h index 8aa852ece..5b55dcd21 100644 --- a/src/domains/tpolyhedra_domain.h +++ b/src/domains/tpolyhedra_domain.h @@ -50,8 +50,8 @@ class tpolyhedra_domaint:public domaint // initialize value virtual void initialize(valuet &value); - virtual void reset_refinements() { current_refinement = 0; } - virtual bool refine(); //non-monotone condition refinement + virtual void reset_refinements() { current_refinement=0; } + virtual bool refine(); // non-monotone condition refinement std::vector &refinement_expressions() { return refinement_exprs; } virtual void join(valuet &value1, const valuet &value2); @@ -141,7 +141,7 @@ class tpolyhedra_domaint:public domaint templatet templ; - //non-monotone condition refinement + // non-monotone condition refinement std::vector refinement_exprs; unsigned current_refinement, max_refinements; exprt current_refinement_expr; diff --git a/src/domains/util.cpp b/src/domains/util.cpp index 450c5132c..6a726f796 100644 --- a/src/domains/util.cpp +++ b/src/domains/util.cpp @@ -242,7 +242,7 @@ mp_integer simplify_const_int(const exprt &expr) assert(d!=0); return simplify_const_int(expr.op0())/d; } - if(expr.id()==ID_symbol || expr.id()==ID_nondet_symbol) + if(expr.id()==ID_symbol || expr.id()==ID_nondet_symbol) { #if 0 std::cerr << "substituting default value for " << expr << std::endl; @@ -333,7 +333,7 @@ ieee_floatt simplify_const_float(const exprt &expr) v1/=v2; return v1; } - if(expr.id()==ID_symbol || expr.id()==ID_nondet_symbol) //default value if not substituted in expr + if(expr.id()==ID_symbol || expr.id()==ID_nondet_symbol) // default value if not substituted in expr { ieee_floatt v; v.make_zero(); diff --git a/src/html/syntax_highlighting.cpp b/src/html/syntax_highlighting.cpp index 5c6e078d0..bc3cb230c 100644 --- a/src/html/syntax_highlighting.cpp +++ b/src/html/syntax_highlighting.cpp @@ -6,7 +6,7 @@ Author: Daniel Kroening, kroening@kroening.com \*******************************************************************/ -// may wish to try http://www.gnu.org/software/src-highlite/ +// may wish to try http:// www.gnu.org/software/src-highlite/ #include #include @@ -29,7 +29,7 @@ Function: is_keyword \*******************************************************************/ const char *keywords[]= -{ +{ "auto", "_Bool", "break", "case", "char", "_Complex", "const", "continue", "default", "do", "double", "else", "enum", "extern", "float", "for", "goto", "if", "inline", "int", "long", "register", "restrict", "return", @@ -51,10 +51,10 @@ bool is_keyword(const std::string &token) if(strcmp(keywords[i], token.c_str())==0) return true; } - + return false; } - + /*******************************************************************\ Class: tokenizert @@ -65,16 +65,16 @@ bool is_keyword(const std::string &token) const char *tokens[]= { "++", "+=", "--", "-=", "&&", "&=", "||", "|=", "/*", - "*/", "//", "%=", "/=", "<<", ">>", "<<=", ">>=", "==", + "*/", "// ", "%=", "/=", "<<", ">>", "<<=", ">>=", "==", "!=", "<=", ">=", "::", "->", "##", ".*", "->*", NULL }; - + class tokenizert { public: explicit tokenizert(const std::string &_buf):buf(_buf) { } - + std::string get(); std::string peek(); std::string buf; @@ -87,7 +87,7 @@ class tokenizert buf.erase(0, 1); return result; } - + static inline bool is_identifier_char(char ch) { return isalnum(ch) || ch=='_'; @@ -111,9 +111,9 @@ std::string tokenizert::peek() if(buf.empty()) return buf; char first=buf[0]; - + unsigned pos=1; - + if(is_identifier_char(first)) { // identifier or keyword or number @@ -137,7 +137,7 @@ std::string tokenizert::peek() for(pos=1; pos"; - + if(comment) out << ""; - std::string token; - + std::string token; + std::map var_count; while(!tokenizer.eol()) @@ -216,7 +216,7 @@ void syntax_highlightingt::operator()(const std::string &line) { std::string buf; bool end_of_comment=false; - + while(!end_of_comment) { char ch=tokenizer.get_char(); @@ -225,7 +225,7 @@ void syntax_highlightingt::operator()(const std::string &line) if(buf.size()>=2 && buf[buf.size()-2]=='*' && buf[buf.size()-1]=='/') end_of_comment=true; } - + out << html_escape(buf); if(end_of_comment) @@ -251,13 +251,13 @@ void syntax_highlightingt::operator()(const std::string &line) { if(identifier_tooltip) out << ""; else out << ""; - + out << html_escape(token); out << ""; @@ -268,7 +268,7 @@ void syntax_highlightingt::operator()(const std::string &line) comment=true; out << "" << token; } - else if(token=="//") + else if(token=="// ") { out << "" << token; while(!(token=tokenizer.get()).empty()) @@ -297,10 +297,10 @@ void syntax_highlightingt::operator()(const std::string &line) } } - // close tags + // close tags if(comment) out << ""; if(!strong_class.empty()) out << ""; - + out << "\n"; } diff --git a/src/html/syntax_highlighting.h b/src/html/syntax_highlighting.h index 159abcc28..412a8434b 100644 --- a/src/html/syntax_highlighting.h +++ b/src/html/syntax_highlighting.h @@ -19,12 +19,12 @@ class syntax_highlightingt line_no(0), identifier_tooltip(false), out(_out), comment(false) { } - std::string strong_class; + std::string strong_class; unsigned line_no; std::string id_suffix; - + bool identifier_tooltip; - + void operator()(const std::string &line); protected: diff --git a/src/solver/Makefile b/src/solver/Makefile index fee456366..e473705db 100644 --- a/src/solver/Makefile +++ b/src/solver/Makefile @@ -1,7 +1,18 @@ -SRC = summarizer_base.cpp summarizer_bw.cpp \ - summarizer_bw_term.cpp summarizer_fw_contexts.cpp \ - summarizer_fw.cpp summarizer_fw_term.cpp \ - summary.cpp summary_db.cpp +SRC = summarizer_base.cpp \ + summarizer_bw.cpp \ + summarizer_bw_term.cpp \ + summarizer_bw_cex.cpp \ + summarizer_bw_cex_ai.cpp \ + summarizer_bw_cex_complete.cpp \ + summarizer_bw_cex_concrete.cpp \ + summarizer_bw_cex_all.cpp \ + summarizer_bw_cex_wp.cpp \ + summarizer_fw_contexts.cpp \ + summarizer_fw.cpp \ + summarizer_fw_term.cpp \ + summary.cpp \ + summary_db.cpp \ + # empty last line include ../config.inc include $(CBMC)/src/config.inc diff --git a/src/solver/summarizer_bw_cex.cpp b/src/solver/summarizer_bw_cex.cpp new file mode 100644 index 000000000..7307697bf --- /dev/null +++ b/src/solver/summarizer_bw_cex.cpp @@ -0,0 +1,271 @@ +/*******************************************************************\ + +Module: Counterexample-based Backward Analysis + +Author: Kumar Madhukar, Peter Schrammel + +\*******************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include "summarizer_bw_cex.h" +#include "summary_db.h" + +#include +#include +#include + +#include +#include + + +/*******************************************************************\ + +Function: summarizer_bw_cex_baset::summarize() + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +void summarizer_bw_cex_baset::summarize() +{ + assert(false); // unused +} + +/*******************************************************************\ + +Function: summarizer_bw_cex_baset::summarize() + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +void summarizer_bw_cex_baset::summarize(const function_namet &function_name) +{ + exprt postcondition=true_exprt(); // initial calling context + + status() << "\nSummarizing function " << function_name << eom; + compute_summary_rec(function_name, postcondition, true); +} + +/*******************************************************************\ + +Function: summarizer_bw_cex_baset::summarize() + + Inputs: + + Outputs: + + Purpose: summarize backwards from given assertion + +\*******************************************************************/ + +void summarizer_bw_cex_baset::summarize(const exprt &_error_assertion) +{ + status() << "\nBackward error analysis..." << eom; + error_assertion=_error_assertion; + + summarize(entry_function); +} + +/*******************************************************************\ + +Function: summarizer_bw_cex_baset::check() + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +property_checkert::resultt summarizer_bw_cex_baset::check() +{ + assert(false); +} + +/*******************************************************************\ + +Function: summarizer_bw_cex_baset::get_loophead_selects + + Inputs: + + Outputs: + + Purpose: returns the select guards at the loop heads + in order to check whether a countermodel is spurious + +\*******************************************************************/ + +void summarizer_bw_cex_baset::get_loophead_selects( + const irep_idt &function_name, + const local_SSAt &SSA, + prop_convt &solver, + exprt::operandst &loophead_selects) +{ + // TODO: this should be provided by unwindable_local_SSA + for(local_SSAt::nodest::const_iterator n_it=SSA.nodes.begin(); + n_it!=SSA.nodes.end(); n_it++) + { + if(n_it->loophead==SSA.nodes.end()) + continue; + symbol_exprt lsguard= + SSA.name(SSA.guard_symbol(), local_SSAt::LOOP_SELECT, n_it->location); + ssa_unwinder.get(function_name).unwinder_rename(lsguard, *n_it, true); + loophead_selects.push_back(not_exprt(lsguard)); + solver.set_frozen(solver.convert(lsguard)); + } + literalt loophead_selects_literal= + solver.convert(conjunction(loophead_selects)); + if(!loophead_selects_literal.is_constant()) + solver.set_frozen(loophead_selects_literal); + +#if 0 + std::cout << "loophead_selects: " + << from_expr(SSA.ns, "", conjunction(loophead_selects)) + << std::endl; +#endif +} + +/*******************************************************************\ + +Function: summarizer_bw_cex_baset::get_loop_continues + + Inputs: + + Outputs: + + Purpose: returns the loop continuation guards at the end of the + loops in order to check whether we can unroll further + +\*******************************************************************/ + +void summarizer_bw_cex_baset::get_loop_continues( + const irep_idt &function_name, + const local_SSAt &SSA, + prop_convt &solver, + exprt::operandst &loop_continues) +{ + // TODO: this should be provided by unwindable_local_SSA + ssa_unwinder.get(function_name).loop_continuation_conditions(loop_continues); + if(loop_continues.size()==0) + { + // TODO: this should actually be done transparently by the unwinder + for(local_SSAt::nodest::const_iterator n_it=SSA.nodes.begin(); + n_it!=SSA.nodes.end(); n_it++) + { + if(n_it->loophead==SSA.nodes.end()) + continue; + symbol_exprt guard=SSA.guard_symbol(n_it->location); + symbol_exprt cond=SSA.cond_symbol(n_it->location); + loop_continues.push_back(and_exprt(guard, cond)); + } + } + +#if 0 + std::cout << "loophead_continues: " + << from_expr(SSA.ns, "", disjunction(loop_continues)) << std::endl; +#endif +} + +/*******************************************************************\ + +Function: summarizer_bw_cex_baset::get_loop_continues + + Inputs: + + Outputs: + + Purpose: returns the loop continuation guards at the end of the + given loop in order to check whether we can unroll further + +\*******************************************************************/ + +void summarizer_bw_cex_baset::get_loop_continues( + const irep_idt &function_name, + const local_SSAt &SSA, + const local_SSAt::locationt &loop_id, + exprt::operandst &loop_continues) +{ + // TODO: need to ask ssa_inliner regarding inlined functions + + // TODO: this should be provided by unwindable_local_SSA + + ssa_unwinder.get(function_name) + .loop_continuation_conditions(loop_id, loop_continues); + if(loop_continues.empty()) + { + // TODO: this should actually be done transparently by the unwinder + for(local_SSAt::nodest::const_iterator n_it=SSA.nodes.begin(); + n_it!=SSA.nodes.end(); n_it++) + { + if(n_it->loophead==SSA.nodes.end()) continue; + if(n_it->loophead->location!=loop_id) continue; + symbol_exprt guard=SSA.guard_symbol(n_it->location); + symbol_exprt cond=SSA.cond_symbol(n_it->location); + loop_continues.push_back(and_exprt(guard, cond)); + break; + } + } + +#if 0 + std::cout << "loophead_continues: " << from_expr(SSA.ns, "", disjunction(loop_continues)) << std::endl; +#endif +} + +/*******************************************************************\ + +Function: summarizer_bw_cex_baset::is_fully_unwound + + Inputs: + + Outputs: + + Purpose: checks whether the loops have been fully unwound + +\*******************************************************************/ + +bool summarizer_bw_cex_baset::is_fully_unwound( + const exprt::operandst &loop_continues, + const exprt::operandst &loophead_selects, + incremental_solvert &solver) +{ + solver.new_context(); + solver << + and_exprt(conjunction(loophead_selects), disjunction(loop_continues)); + + solver_calls++; // statistics + + switch(solver()) + { + case decision_proceduret::D_SATISFIABLE: + solver.pop_context(); + return false; + break; + + case decision_proceduret::D_UNSATISFIABLE: + solver.pop_context(); + solver << conjunction(loophead_selects); + return true; + break; + + case decision_proceduret::D_ERROR: + default: + throw "error from decision procedure"; + } +} diff --git a/src/solver/summarizer_bw_cex.h b/src/solver/summarizer_bw_cex.h new file mode 100644 index 000000000..117a47416 --- /dev/null +++ b/src/solver/summarizer_bw_cex.h @@ -0,0 +1,80 @@ +/*******************************************************************\ + +Module: Counterexample-based Backward Analysis Base + +Author: Kumar Madhukar, Peter Schrammel + +\*******************************************************************/ + +#ifndef CPROVER_2LS_SOLVER_SUMMARIZER_BW_CEX_H +#define CPROVER_2LS_SOLVER_SUMMARIZER_BW_CEX_H + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "summarizer_bw.h" + +class summarizer_bw_cex_baset : public summarizer_bwt +{ +public: + typedef ssa_refiner_selectivet::reasont reasont; + + virtual void summarize(); + virtual void summarize(const function_namet &entry_function); + virtual void summarize(const exprt &_error_assertion); + + virtual property_checkert::resultt check(); + virtual void get_reason(reasont &_reason) { _reason.merge(reason); } + +protected: + function_namet entry_function; + function_namet error_function; + exprt error_assertion; + reasont reason; + + summarizer_bw_cex_baset( + optionst &_options, + summary_dbt &_summary_db, + ssa_dbt &_ssa_db, + ssa_unwindert &_ssa_unwinder, + ssa_inlinert &_ssa_inliner, + function_namet _entry_function, + function_namet _error_function): + summarizer_bwt(_options, _summary_db, _ssa_db, _ssa_unwinder, _ssa_inliner), + entry_function(_entry_function), + error_function(_error_function) + { + } + + void get_loophead_selects( + const irep_idt &function_name, + const local_SSAt &, + prop_convt &, + exprt::operandst &loophead_selects); + + void get_loop_continues( + const irep_idt &function_name, + const local_SSAt &, + prop_convt &, + exprt::operandst &loop_continues); + + void get_loop_continues( + const irep_idt &function_name, + const local_SSAt &SSA, + const local_SSAt::locationt &loop_id, + exprt::operandst &loop_continues); + + bool is_fully_unwound( + const exprt::operandst& loop_continues, + const exprt::operandst& loophead_selects, + incremental_solvert&); +}; + +#endif diff --git a/src/solver/summarizer_bw_cex_ai.cpp b/src/solver/summarizer_bw_cex_ai.cpp new file mode 100644 index 000000000..f796c3cad --- /dev/null +++ b/src/solver/summarizer_bw_cex_ai.cpp @@ -0,0 +1,535 @@ +/*******************************************************************\ + +Module: Summarizer for Backward Analysis + +Author: Peter Schrammel + +\*******************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include "summarizer_bw_cex_ai.h" +#include "summary_db.h" + +#include "../domains/ssa_analyzer.h" +#include "../domains/template_generator_summary.h" +#include "../domains/template_generator_callingcontext.h" + +#include "../domains/disjunctive_analyzer.h" + +#include "../ssa/local_ssa.h" +#include "../ssa/simplify_ssa.h" + + +/*******************************************************************\ + +Function: summarizer_bw_cex_ait::summarize() + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +void summarizer_bw_cex_ait::summarize(const function_namet &function_name) +{ + exprt postcondition=true_exprt(); // initial calling context + + status() << "\nSummarizing function " << function_name << eom; + compute_summary_rec(function_name, summaryt::entry_call_site, + postcondition, true); +} + +/*******************************************************************\ + +Function: summarizer_bw_cex_ait::summarize() + + Inputs: + + Outputs: + + Purpose: summarize backwards from given assertion + +\*******************************************************************/ + +void summarizer_bw_cex_ait::summarize(const exprt &_error_assertion) +{ + status() << "\nBackward error analysis (abstract)..." << eom; + error_assertion=_error_assertion; + + summarize(entry_function); +} + +/*******************************************************************\ + +Function: summarizer_bw_cex_ait::check() + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +property_checkert::resultt summarizer_bw_cex_ait::check() +{ + property_checkert::resultt result=property_checkert::FAIL; + if(!summary_db.exists(entry_function)) + { + result=property_checkert::UNKNOWN; + } + else + { + const summaryt &summary=summary_db.get(entry_function); + if(summary.error_summaries.empty() || + summary.error_summaries.begin()->second.is_nil() || + summary.error_summaries.begin()->second.is_true()) + result=property_checkert::UNKNOWN; + } + + // we are only complete if we are in the entry function + if(result==property_checkert::UNKNOWN && + entry_function==error_function) + { + incremental_solvert &solver=ssa_db.get_solver(entry_function); + const local_SSAt &ssa=ssa_db.get(entry_function); + exprt::operandst loophead_selects; + exprt::operandst loop_continues; + get_loophead_selects( + entry_function, ssa, *solver.solver, loophead_selects); + get_loop_continues(entry_function, ssa, *solver.solver, loop_continues); + // check whether loops have been fully unwound + bool fully_unwound= + is_fully_unwound(loop_continues, loophead_selects, solver); + status() << "Loops " << (fully_unwound ? "" : "not ") + << "fully unwound" << eom; + + if(fully_unwound) + result=property_checkert::PASS; + } + + return result; +} + +/*******************************************************************\ + +Function: summarizer_bw_cex_ait::compute_summary_rec() + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +void summarizer_bw_cex_ait::compute_summary_rec( + const function_namet &function_name, + const summaryt::call_sitet &call_site, + const exprt &_postcondition, + bool context_sensitive) +{ + local_SSAt &SSA=ssa_db.get(function_name); + + summaryt summary; + if(summary_db.exists(function_name)) + summary=summary_db.get(function_name); + else + { + summary.params=SSA.params; + summary.globals_in=SSA.globals_in; + summary.globals_out=SSA.globals_out; + summary.nondets=SSA.nondets; + } + + // insert assertion + exprt end_guard=SSA.guard_symbol(--SSA.goto_function.body.instructions.end()); + exprt postcondition=implies_exprt(end_guard, _postcondition); + if(function_name==error_function) + { + postcondition=and_exprt(postcondition, not_exprt(error_assertion)); + } + + summary.bw_postcondition=_postcondition; + +#if 0 + debug() << "Postcondition: " << + from_expr(SSA.ns, "", postcondition) << eom; +#endif + + if(_postcondition.is_false()){ + + summary.error_summaries[call_site]=false_exprt(); + + } + else{ + + // recursively compute summaries for function calls + inline_summaries(function_name, SSA, summary, + postcondition, context_sensitive, + true); + + status() << "Analyzing function " << function_name << eom; + + do_summary(function_name, call_site, SSA, summary, summary, postcondition, context_sensitive); + + if(function_name==error_function) + summary.has_assertion=true; + + } + + summary_db.set(function_name, summary); + + { + std::ostringstream out; + out << std::endl << "Summary for function " << function_name << std::endl; + summary_db.get(function_name).output(out, SSA.ns); + debug() << out.str() << eom; + } + +} + +/*******************************************************************\ + +Function: summarizer_bw_cex_ait::do_summary() + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +void summarizer_bw_cex_ait::do_summary(const function_namet &function_name, + const summaryt::call_sitet &call_site, + local_SSAt &SSA, + const summaryt &old_summary, + summaryt &summary, + const exprt &postcondition, + bool context_sensitive) +{ + status() << "Computing error summary" << eom; + + // solver + incremental_solvert &solver=ssa_db.get_solver(function_name); + solver.set_message_handler(get_message_handler()); + + // TODO: maybe allow setting this separately on the command line + optionst _options=options; + _options.set_option("intervals", true); + _options.set_option("binsearch-solver", true); + + // TODO: use a template generator without invariants + template_generator_summaryt template_generator( + _options, ssa_db, ssa_unwinder.get(function_name)); + template_generator.set_message_handler(get_message_handler()); + template_generator(solver.next_domain_number(), SSA, false); + + exprt::operandst c; + // add forward information if available + if(!old_summary.fw_precondition.is_nil()) + c.push_back(old_summary.fw_precondition); + if(!old_summary.fw_invariant.is_nil()) + c.push_back(old_summary.fw_invariant); + c.push_back(ssa_inliner.get_summaries(SSA)); // forward summaries + exprt::operandst assert_postcond, noassert_postcond; + // add error summaries for function calls + bool assertion_flag; + assertion_flag=ssa_inliner.get_summaries(SSA, call_site, false, + assert_postcond, noassert_postcond, c); // backward summaries + + assert_postcond.push_back(postcondition); // context + + // add nondet variables from callees to summary.nondets + std::set summary_vars; + find_symbols(conjunction(assert_postcond), summary_vars); + for(std::set::const_iterator it=summary_vars.begin(); + it!=summary_vars.end(); ++it) + if(it->id()==ID_nondet_symbol) + summary.nondets.insert(*it); + + // assumptions must hold + for(local_SSAt::nodest::const_iterator + n_it=SSA.nodes.begin(); + n_it!=SSA.nodes.end(); + ++n_it) + for(local_SSAt::nodet::assumptionst::const_iterator + a_it=n_it->assumptions.begin(); + a_it!=n_it->assumptions.end(); + ++a_it) + c.push_back(*a_it); + + + + +#if 0 + std::cout << from_expr(SSA.ns, "", cc) << std::endl; +#endif + + // TODO: pushing loophead_selects into the solver + + summary.error_summaries[call_site]; + if(!template_generator.empty()) + { + c.push_back(conjunction(assert_postcond)); // with negative information would need: not_exprt + c.push_back(conjunction(noassert_postcond)); // with negative information would need: not_exprt dis + + // std::cout << "unsimplified constraints (if): " << from_expr(SSA.ns, "", conjunction(c)) << "\n\n\n"; + exprt cc=simplify_expr(conjunction(c), SSA.ns); + // exprt cc=conjunction(c); + // std::cout << "simplified constraints passed (if): " << from_expr(SSA.ns, "", cc) << "\n\n\n"; + + /* + ssa_analyzert analyzer; + analyzer.set_message_handler(get_message_handler()); + analyzer(solver, SSA, cc, template_generator); + analyzer.get_result(summary.error_summaries[call_site], + template_generator.inout_vars()); + */ + /**/ + disjunctive_analyzert disjunctive_analyzer; + disjunctive_analyzer.set_message_handler(get_message_handler()); + disjunctive_analyzer(solver, SSA, cc, template_generator, + cc, summary.error_summaries[call_site], + template_generator.inout_vars()); + /**/ + +#if 0 + std::cout << "SUM: " << from_expr(SSA.ns, "", summary.error_summaries[call_site]) << std::endl; +#endif + + + summary.error_summaries[call_site]= + simplify_expr(summary.error_summaries[call_site], SSA.ns); + + +#if 0 + std::cout << "SUM (post simplification): " << from_expr(SSA.ns, "", summary.error_summaries[call_site]) << std::endl; +#endif + + // statistics + /* + solver_instances+=analyzer.get_number_of_solver_instances(); + solver_calls+=analyzer.get_number_of_solver_calls(); + */ + solver_instances+=disjunctive_analyzer.get_number_of_solver_instances(); + solver_calls+=disjunctive_analyzer.get_number_of_solver_calls(); + + } + else // TODO: yet another workaround for ssa_analyzer not being able to handle empty templates properly + { + c.push_back(conjunction(assert_postcond)); // with negative information would need: not_exprt + c.push_back(conjunction(noassert_postcond)); // with negative information would need: not_exprt dis + // c.push_back(not_exprt(conjunction(assert_postcond))); + // c.push_back(not_exprt(disjunction(noassert_postcond))); + + // std::cout << "unsimplified constraints (else): " << from_expr(SSA.ns, "", conjunction(c)) << "\n\n\n"; + exprt cc=simplify_expr(conjunction(c), SSA.ns); + // exprt cc=conjunction(c); + // std::cout << "simplified constraints passed (else): " << from_expr(SSA.ns, "", cc) << "\n\n\n"; + + // std::cout << "enabling expressions (else): " << from_expr(SSA.ns, "", SSA.get_enabling_exprs()) << "\n\n\n"; + + solver << SSA; + solver.new_context(); + solver << SSA.get_enabling_exprs(); + solver << cc; + exprt result=true_exprt(); + if(solver()!=decision_proceduret::D_SATISFIABLE) result=false_exprt(); + solver.pop_context(); + summary.error_summaries[call_site]=result; + +#if 0 + std::cout << "SUM: " << from_expr(SSA.ns, "", summary.error_summaries[call_site]) << std::endl; +#endif + } + + summary.error_summaries[call_site]= + simplify_expr((summary.error_summaries[call_site]), SSA.ns); // not_exprt + + summary.has_assertion=assertion_flag; +} + +/*******************************************************************\ + +Function: summarizer_bw_cex_ait::inline_summaries() + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +void summarizer_bw_cex_ait::inline_summaries(const function_namet &function_name, + local_SSAt &SSA, + const summaryt &old_summary, + const exprt &postcondition, + bool context_sensitive, + bool sufficient) +{ + for(local_SSAt::nodest::const_iterator n_it=SSA.nodes.end(); + n_it!=SSA.nodes.begin(); ) + { + n_it--; + + for(local_SSAt::nodet::function_callst::const_iterator f_it= + n_it->function_calls.begin(); + f_it!=n_it->function_calls.end(); f_it++) + { + assert(f_it->function().id()==ID_symbol); // no function pointers + + exprt postcondition_call= true_exprt(); + postcondition_call=compute_calling_context2( + function_name, SSA, old_summary, n_it, f_it, postcondition, sufficient); + + irep_idt fname=to_symbol_expr(f_it->function()).get_identifier(); + status() << "Recursively summarizing function " << fname << eom; + compute_summary_rec(fname, summaryt::call_sitet(n_it->location), + postcondition_call, context_sensitive); + } + } +} + +/*******************************************************************\ + +Function: summarizer_bw_cex_ait::compute_calling_context2() + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +exprt summarizer_bw_cex_ait::compute_calling_context2( + const function_namet &function_name, + local_SSAt &SSA, + summaryt old_summary, + local_SSAt::nodest::const_iterator n_it, + local_SSAt::nodet::function_callst::const_iterator f_it, + const exprt &postcondition, + bool sufficient) +{ + assert(f_it->function().id()==ID_symbol); // no function pointers + irep_idt fname=to_symbol_expr(f_it->function()).get_identifier(); + + status() << "Computing calling context for function " << fname << eom; + + // solver + incremental_solvert &solver=ssa_db.get_solver(function_name); + solver.set_message_handler(get_message_handler()); + + // analyze + /* + ssa_analyzert analyzer; + analyzer.set_message_handler(get_message_handler()); + */ + + disjunctive_analyzert disjunctive_analyzer; + disjunctive_analyzer.set_message_handler(get_message_handler()); + + // TODO: maybe allow setting this separately on the command line + optionst _options=options; + _options.set_option("intervals", true); + _options.set_option("binsearch-solver", true); + + // TODO: use a template generator without invariants + template_generator_callingcontextt template_generator( + _options, ssa_db, ssa_unwinder.get(function_name)); + template_generator.set_message_handler(get_message_handler()); + template_generator(solver.next_domain_number(), SSA, n_it, f_it, false); + + // collect globals at call site + std::map + cs_globals_out; + SSA.get_globals(n_it->location, cs_globals_out[f_it], false); + + exprt::operandst c; + + // add forward information if available + if(!old_summary.fw_precondition.is_nil()) + c.push_back(old_summary.fw_precondition); + if(!old_summary.fw_invariant.is_nil()) + c.push_back(old_summary.fw_invariant); + c.push_back(ssa_inliner.get_summaries(SSA)); // forward summaries + + exprt::operandst assert_postcond, noassert_postcond; + // add error summaries for function calls + ssa_inliner.get_summaries(SSA, summaryt::call_sitet(n_it->location), false, + assert_postcond, noassert_postcond, c); // backward summaries + assert_postcond.push_back(postcondition); // context + + + // TODO: pushing loophead_selects into the solver + + // set preconditions + local_SSAt &fSSA=ssa_db.get(fname); + + exprt postcondition_call; + + if(!template_generator.empty()){ + + c.push_back(conjunction(assert_postcond)); // with negative information would need: not_exprt + c.push_back(conjunction(noassert_postcond)); // with negative information would need: not_exprt dis + + /* + analyzer(solver, SSA, conjunction(c), template_generator); + analyzer.get_result(postcondition_call, + template_generator.callingcontext_vars()); + */ + + disjunctive_analyzer(solver, SSA, conjunction(c), template_generator, + conjunction(c), postcondition_call, + template_generator.callingcontext_vars()); + + ssa_inliner.rename_to_callee(f_it, fSSA.params, + cs_globals_out[f_it], fSSA.globals_out, + postcondition_call); + + } + else{ // TODO: yet another workaround for ssa_analyzer not being able to handle empty templates properly + + c.push_back(not_exprt(conjunction(assert_postcond))); + c.push_back(not_exprt(disjunction(noassert_postcond))); + + solver << SSA; + solver.new_context(); + solver << SSA.get_enabling_exprs(); + solver << conjunction(c); + + // std::cout << "passed to solver, else branch, calling context: " << from_expr(SSA.ns, "", conjunction(c)) << "\n\n"; + + postcondition_call=false_exprt(); + if(solver()!=decision_proceduret::D_SATISFIABLE) postcondition_call=true_exprt(); + solver.pop_context(); + } + + debug() << "Backward calling context for " << + from_expr(SSA.ns, "", *f_it) << ": " + << from_expr(SSA.ns, "", postcondition_call) << eom; + + // statistics + /* + solver_instances+=analyzer.get_number_of_solver_instances(); + solver_calls+=analyzer.get_number_of_solver_calls(); + */ + solver_instances+=disjunctive_analyzer.get_number_of_solver_instances(); + solver_calls+=disjunctive_analyzer.get_number_of_solver_calls(); + + return postcondition_call; +} + + diff --git a/src/summarizer/summarizer_bw_cex_ai.h b/src/solver/summarizer_bw_cex_ai.h similarity index 50% rename from src/summarizer/summarizer_bw_cex_ai.h rename to src/solver/summarizer_bw_cex_ai.h index a41b9c122..3448a1422 100644 --- a/src/summarizer/summarizer_bw_cex_ai.h +++ b/src/solver/summarizer_bw_cex_ai.h @@ -2,19 +2,19 @@ Module: Summarizer for Backwards Error Analysis -Author: Peter Schrammel +Author: Kumar Madhukar, Peter Schrammel \*******************************************************************/ -#ifndef CPROVER_SUMMARIZER_BW_CEX_AI_H -#define CPROVER_SUMMARIZER_BW_CEX_AI_H +#ifndef CPROVER_2LS_SOLVER_SUMMARIZER_BW_CEX_AI_H +#define CPROVER_2LS_SOLVER_SUMMARIZER_BW_CEX_AI_H #include #include -#include "../ssa/ssa_inliner.h" -#include "../ssa/ssa_unwinder.h" -#include "../ssa/local_ssa.h" -#include "ssa_db.h" +#include +#include +#include +#include #include @@ -23,16 +23,16 @@ Author: Peter Schrammel class summarizer_bw_cex_ait : public summarizer_bw_cex_baset { public: - explicit summarizer_bw_cex_ait(optionst &_options, - summary_dbt &_summary_db, + explicit summarizer_bw_cex_ait(optionst &_options, + summary_dbt &_summary_db, ssa_dbt &_ssa_db, - ssa_unwindert &_ssa_unwinder, - ssa_inlinert &_ssa_inliner, - function_namet _entry_function, - function_namet _error_function): - summarizer_bw_cex_baset(_options,_summary_db,_ssa_db, - _ssa_unwinder,_ssa_inliner, - _entry_function,_error_function) + ssa_unwindert &_ssa_unwinder, + ssa_inlinert &_ssa_inliner, + function_namet _entry_function, + function_namet _error_function): + summarizer_bw_cex_baset(_options, _summary_db, _ssa_db, + _ssa_unwinder, _ssa_inliner, + _entry_function, _error_function) {} virtual void summarize(const function_namet &entry_function); @@ -44,28 +44,28 @@ class summarizer_bw_cex_ait : public summarizer_bw_cex_baset virtual void compute_summary_rec(const function_namet &function_name, const summaryt::call_sitet &call_site, - const exprt &postcondition, + const exprt &postcondition, bool context_sensitive); - virtual void inline_summaries(const function_namet &function_name, - local_SSAt &SSA, - const summaryt &old_summary, - const exprt &postcondition, + virtual void inline_summaries(const function_namet &function_name, + local_SSAt &SSA, + const summaryt &old_summary, + const exprt &postcondition, bool context_sensitive, - bool sufficient); + bool sufficient); - virtual void do_summary(const function_namet &function_name, - const summaryt::call_sitet &call_site, - local_SSAt &SSA, - const summaryt &old_summary, - summaryt &summary, - const exprt &postcondition, - bool context_sensitive); + virtual void do_summary(const function_namet &function_name, + const summaryt::call_sitet &call_site, + local_SSAt &SSA, + const summaryt &old_summary, + summaryt &summary, + const exprt &postcondition, + bool context_sensitive); - virtual exprt compute_calling_context2(const function_namet &function_name, + virtual exprt compute_calling_context2(const function_namet &function_name, local_SSAt &SSA, summaryt old_summary, - local_SSAt::nodest::const_iterator n_it, + local_SSAt::nodest::const_iterator n_it, local_SSAt::nodet::function_callst::const_iterator f_it, const exprt &postcondition, bool sufficient); diff --git a/src/summarizer/summarizer_bw_cex_all.cpp b/src/solver/summarizer_bw_cex_all.cpp similarity index 82% rename from src/summarizer/summarizer_bw_cex_all.cpp rename to src/solver/summarizer_bw_cex_all.cpp index cefdd8757..4b1052fcc 100644 --- a/src/summarizer/summarizer_bw_cex_all.cpp +++ b/src/solver/summarizer_bw_cex_all.cpp @@ -1,6 +1,6 @@ /*******************************************************************\ -Module: Counterexample-based Backward Analysis +Module: Counterexample-based Backward Analysis Author: Kumar Madhukar, Peter Schrammel @@ -39,20 +39,20 @@ Function: summarizer_bw_cex_allt::summarize() void summarizer_bw_cex_allt::summarize(const exprt &_error_assertion) { status() << "\nBackward error analysis (all)..." << eom; - error_assertion = _error_assertion; + error_assertion=_error_assertion; summarizer_bw_cex_concrete.summarize(error_assertion); - result = summarizer_bw_cex_concrete.check(); + result=summarizer_bw_cex_concrete.check(); - if(result == property_checkert::UNKNOWN) + if(result==property_checkert::UNKNOWN) { summarizer_bw_cex_ai.summarize(error_assertion); - result = summarizer_bw_cex_ai.check(); + result=summarizer_bw_cex_ai.check(); - if(result == property_checkert::UNKNOWN) + if(result==property_checkert::UNKNOWN) { summarizer_bw_cex_complete.summarize(error_assertion); - result = summarizer_bw_cex_complete.check(); + result=summarizer_bw_cex_complete.check(); } } } @@ -65,7 +65,7 @@ Function: summarizer_bw_cex_allt::check() Outputs: - Purpose: + Purpose: \*******************************************************************/ diff --git a/src/summarizer/summarizer_bw_cex_all.h b/src/solver/summarizer_bw_cex_all.h similarity index 54% rename from src/summarizer/summarizer_bw_cex_all.h rename to src/solver/summarizer_bw_cex_all.h index b04dae0fb..f29326931 100644 --- a/src/summarizer/summarizer_bw_cex_all.h +++ b/src/solver/summarizer_bw_cex_all.h @@ -6,16 +6,16 @@ Author: Kumar Madhukar, Peter Schrammel \*******************************************************************/ -#ifndef CPROVER_SUMMARIZER_BW_CEX_ALL_H -#define CPROVER_SUMMARIZER_BW_CEX_ALL_H +#ifndef CPROVER_2LS_SOLVER_SUMMARIZER_BW_CEX_ALL_H +#define CPROVER_2LS_SOLVER_SUMMARIZER_BW_CEX_ALL_H #include #include #include -#include "../ssa/ssa_inliner.h" -#include "../ssa/ssa_unwinder.h" -#include "../ssa/local_ssa.h" -#include "ssa_db.h" +#include +#include +#include +#include #include "summarizer_bw_cex.h" #include "summarizer_bw_cex_concrete.h" @@ -26,25 +26,25 @@ class summarizer_bw_cex_allt : public summarizer_bw_cex_baset { public: explicit summarizer_bw_cex_allt(optionst &_options, - summary_dbt &_summary_db, - ssa_dbt &_ssa_db, - ssa_unwindert &_ssa_unwinder, - ssa_inlinert &_ssa_inliner, - incremental_solvert &_solver, - function_namet _entry_function, - function_namet _error_function): - summarizer_bw_cex_baset(_options,_summary_db,_ssa_db, - _ssa_unwinder,_ssa_inliner, - _entry_function,_error_function), - summarizer_bw_cex_concrete(_options,_summary_db,_ssa_db, - _ssa_unwinder,_ssa_inliner, - _entry_function,_error_function), - summarizer_bw_cex_ai(_options,_summary_db,_ssa_db, - _ssa_unwinder,_ssa_inliner, - _entry_function,_error_function), - summarizer_bw_cex_complete(_options,_summary_db,_ssa_db, - _ssa_unwinder,_ssa_inliner, - _solver,_entry_function,_error_function), + summary_dbt &_summary_db, + ssa_dbt &_ssa_db, + ssa_unwindert &_ssa_unwinder, + ssa_inlinert &_ssa_inliner, + incremental_solvert &_solver, + function_namet _entry_function, + function_namet _error_function): + summarizer_bw_cex_baset(_options, _summary_db, _ssa_db, + _ssa_unwinder, _ssa_inliner, + _entry_function, _error_function), + summarizer_bw_cex_concrete(_options, _summary_db, _ssa_db, + _ssa_unwinder, _ssa_inliner, + _entry_function, _error_function), + summarizer_bw_cex_ai(_options, _summary_db, _ssa_db, + _ssa_unwinder, _ssa_inliner, + _entry_function, _error_function), + summarizer_bw_cex_complete(_options, _summary_db, _ssa_db, + _ssa_unwinder, _ssa_inliner, + _solver, _entry_function, _error_function), result(property_checkert::UNKNOWN) {} @@ -60,7 +60,7 @@ class summarizer_bw_cex_allt : public summarizer_bw_cex_baset virtual property_checkert::resultt check(); - + protected: summarizer_bw_cex_concretet summarizer_bw_cex_concrete; summarizer_bw_cex_ait summarizer_bw_cex_ai; diff --git a/src/summarizer/summarizer_bw_cex_complete.cpp b/src/solver/summarizer_bw_cex_complete.cpp similarity index 62% rename from src/summarizer/summarizer_bw_cex_complete.cpp rename to src/solver/summarizer_bw_cex_complete.cpp index 9ba0d6ecb..c658c91eb 100644 --- a/src/summarizer/summarizer_bw_cex_complete.cpp +++ b/src/solver/summarizer_bw_cex_complete.cpp @@ -1,6 +1,6 @@ /*******************************************************************\ -Module: Simple Complete Counterexample-based Backward Analysis +Module: Simple Complete Counterexample-based Backward Analysis Author: Madhukar Kumar, Peter Schrammel @@ -36,7 +36,7 @@ Function: summarizer_bw_cex_completet::summarize() Outputs: - Purpose: + Purpose: \*******************************************************************/ @@ -48,7 +48,7 @@ void summarizer_bw_cex_completet::summarize find_symbols_sett dependency_set; status() << "\nSummarizing function " << entry_function << eom; - compute_summary_rec(entry_function,dependency_set,-1); + compute_summary_rec(entry_function, dependency_set, -1); } /*******************************************************************\ @@ -66,8 +66,8 @@ Function: summarizer_bw_cex_completet::summarize() void summarizer_bw_cex_completet::summarize(const exprt &_error_assertion) { status() << "\nBackward error analysis (complete)..." << eom; - error_assertion = _error_assertion; - ssa_inliner.rename(error_assertion,-1,false); + error_assertion=_error_assertion; + ssa_inliner.rename(error_assertion, -1, false); /* std::cout << "error assertion: " << from_expr(ssa_db.get(entry_function).ns, "", error_assertion) @@ -95,201 +95,203 @@ find_symbols_sett summarizer_bw_cex_completet::inline_summaries find_symbols_sett &dependency_set, int counter) { - local_SSAt &SSA = ssa_db.get(function_name); - ssa_local_unwindert &ssa_local_unwinder = ssa_unwinder.get(function_name); + local_SSAt &SSA=ssa_db.get(function_name); +#if 0 + ssa_local_unwindert &ssa_local_unwinder=ssa_unwinder.get(function_name); ssa_local_unwinder.compute_loop_continuation_conditions(); - //add enabling expressions - exprt enable_exprs = SSA.get_enabling_exprs(); +#endif + // add enabling expressions + exprt enable_exprs=SSA.get_enabling_exprs(); ssa_inliner.rename(enable_exprs, counter); solver << enable_exprs; // assumptions must hold - for(local_SSAt::nodest::const_iterator - n_it = SSA.nodes.begin(); n_it != SSA.nodes.end(); ++n_it) - for(local_SSAt::nodet::assumptionst::const_iterator - a_it = n_it->assumptions.begin(); a_it != n_it->assumptions.end(); ++a_it) + for(local_SSAt::nodest::const_iterator + n_it=SSA.nodes.begin(); n_it!=SSA.nodes.end(); ++n_it) + for(local_SSAt::nodet::assumptionst::const_iterator + a_it=n_it->assumptions.begin(); a_it!=n_it->assumptions.end(); ++a_it) { - exprt assumption = *a_it; + exprt assumption=*a_it; ssa_inliner.rename(assumption, counter); solver << assumption; } #ifdef REFINE_ALL - //TODO: let's just put all loops into the reason - for(local_SSAt::nodest::iterator n_it = SSA.nodes.begin(); - n_it != SSA.nodes.end(); ++n_it) - if (n_it->loophead != SSA.nodes.end()) + // TODO: let's just put all loops into the reason + for(local_SSAt::nodest::iterator n_it=SSA.nodes.begin(); + n_it!=SSA.nodes.end(); ++n_it) + if (n_it->loophead!=SSA.nodes.end()) reason[function_name].loops.insert(n_it->loophead->location); #endif - ssa_dependency_grapht &ssa_depgraph = ssa_db.get_depgraph(function_name); - + ssa_dependency_grapht &ssa_depgraph=ssa_db.get_depgraph(function_name); + struct worknodet{ int node_index; find_symbols_sett dependency_set; }; - + worknodet start_node; - start_node.node_index = 0; - start_node.dependency_set = dependency_set; + start_node.node_index=0; + start_node.dependency_set=dependency_set; typedef std::list worklistt; worklistt worklist, work_waitlist; std::vector covered_nodes; - + worklist.push_back(start_node); - + while(!worklist.empty()){ - + /* std::cout << "worklist: "; for(worklistt::const_iterator w_it=worklist.begin(); - w_it != worklist.end(); w_it++){ + w_it!=worklist.end(); w_it++){ std::cout << w_it->node_index << " "; } std::cout << "\n"; - + std::cout << "\t waitlist: "; for(worklistt::const_iterator w_it=work_waitlist.begin(); - w_it != work_waitlist.end(); w_it++){ + w_it!=work_waitlist.end(); w_it++){ std::cout << w_it->node_index << " "; } std::cout << "\n"; */ - worknodet &worknode = worklist.front(); - const ssa_dependency_grapht::depnodet &depnode = + worknodet &worknode=worklist.front(); + const ssa_dependency_grapht::depnodet &depnode= ssa_depgraph.depnodes_map[worknode.node_index]; - - //std::cout << "working node: " << function_name << ": " << worknode.node_index << "\n"; - ///////////////////////////////////////////////////////////////////////////////////// - //std::cout << "\t size of dependency set: " << worknode.dependency_set.size() << "\n"; + + // std::cout << "working node: " << function_name << ": " << worknode.node_index << "\n"; + // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // / + // std::cout << "\t size of dependency set: " << worknode.dependency_set.size() << "\n"; /* std::cout << "\t dependency set: "; - for(find_symbols_sett::iterator d_it = worknode.dependency_set.begin(); - d_it != worknode.dependency_set.end(); d_it++){ + for(find_symbols_sett::iterator d_it=worknode.dependency_set.begin(); + d_it!=worknode.dependency_set.end(); d_it++){ std::cout << *d_it; } std::cout << "\n\n\n"; */ - ///////////////////////////////////////////////////////////////////////////////////// + // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // / // return if the top most node is reached - if(worknode.node_index == ssa_depgraph.top_node_index) + if(worknode.node_index==ssa_depgraph.top_node_index) return worknode.dependency_set; - + // modify worknode_dependency_set if the node is an assertion - if(depnode.is_assertion == true){ + if(depnode.is_assertion==true){ - //std::cout << "\t\t an assertion node\n"; - for(find_symbols_sett::const_iterator d_it = depnode.used_symbols.begin(); - d_it != depnode.used_symbols.end(); d_it++){ + // std::cout << "\t\t an assertion node\n"; + for(find_symbols_sett::const_iterator d_it=depnode.used_symbols.begin(); + d_it!=depnode.used_symbols.end(); d_it++){ worknode.dependency_set.insert(*d_it); } - ///////////////////////////////////////////////////////////////////////////////////// + // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // / /* std::cout << "\t size of dependency set: " << worknode.dependency_set.size() << "\n"; std::cout << "\t dependency set: "; - for(find_symbols_sett::iterator d_it = worknode.dependency_set.begin(); - d_it != worknode.dependency_set.end(); d_it++){ + for(find_symbols_sett::iterator d_it=worknode.dependency_set.begin(); + d_it!=worknode.dependency_set.end(); d_it++){ std::cout << *d_it; } std::cout << "\n"; */ - ///////////////////////////////////////////////////////////////////////////////////// + // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // / + - } // if this is a function call - if(depnode.is_function_call == true){ - //std::cout << "fcall: working node: " << function_name << ": " << worknode.node_index << "\n"; - irep_idt fname = + if(depnode.is_function_call==true){ + // std::cout << "fcall: working node: " << function_name << ": " << worknode.node_index << "\n"; + irep_idt fname= to_symbol_expr((to_function_application_expr(depnode.node_info)).function()).get_identifier(); - + find_symbols_sett renamed_dependencies; - ///////////////////////////////////////////////////////////////////////////////////// + // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // / /* std::cout << "\t size of dependency set: " << worknode.dependency_set.size() << "\n"; std::cout << "\t dependency set: "; - for(find_symbols_sett::iterator d_it = worknode.dependency_set.begin(); - d_it != worknode.dependency_set.end(); d_it++){ + for(find_symbols_sett::iterator d_it=worknode.dependency_set.begin(); + d_it!=worknode.dependency_set.end(); d_it++){ std::cout << *d_it; } std::cout << "\n"; */ - ///////////////////////////////////////////////////////////////////////////////////// + // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // / - for(find_symbols_sett::iterator d_it = worknode.dependency_set.begin(); - d_it != worknode.dependency_set.end(); d_it++){ - irep_idt renamed_id = *d_it; + for(find_symbols_sett::iterator d_it=worknode.dependency_set.begin(); + d_it!=worknode.dependency_set.end(); d_it++){ + irep_idt renamed_id=*d_it; // detach the '@' symbol if there ssa_inliner.rename(renamed_id, depnode.rename_counter, false); renamed_dependencies.insert(renamed_id); } - worknode.dependency_set = renamed_dependencies; + worknode.dependency_set=renamed_dependencies; if(!worknode.dependency_set.empty()){ find_symbols_sett guard_dependencies; find_symbols(depnode.guard, guard_dependencies); - for(find_symbols_sett::const_iterator d_it = guard_dependencies.begin(); - d_it != guard_dependencies.end(); d_it++){ + for(find_symbols_sett::const_iterator d_it=guard_dependencies.begin(); + d_it!=guard_dependencies.end(); d_it++){ worknode.dependency_set.insert(*d_it); } } - ///////////////////////////////////////////////////////////////////////////////////// + // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // / /* std::cout << "\t size of dependency set: " << worknode.dependency_set.size() << "\n"; std::cout << "\t dependency set: "; - for(find_symbols_sett::iterator d_it = worknode.dependency_set.begin(); - d_it != worknode.dependency_set.end(); d_it++){ + for(find_symbols_sett::iterator d_it=worknode.dependency_set.begin(); + d_it!=worknode.dependency_set.end(); d_it++){ std::cout << *d_it; } std::cout << "\n"; */ - ///////////////////////////////////////////////////////////////////////////////////// + // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // / #ifdef REFINE_ALL - //TODO: just put all function calls into reason + // TODO: just put all function calls into reason reason[function_name].functions.insert(depnode.location); #endif - //recurse - worknode.dependency_set = - compute_summary_rec(fname,worknode.dependency_set, + // recurse + worknode.dependency_set= + compute_summary_rec(fname, worknode.dependency_set, depnode.rename_counter); renamed_dependencies.clear(); - for(find_symbols_sett::iterator d_it = worknode.dependency_set.begin(); - d_it != worknode.dependency_set.end(); d_it++){ - irep_idt renamed_id = *d_it; + for(find_symbols_sett::iterator d_it=worknode.dependency_set.begin(); + d_it!=worknode.dependency_set.end(); d_it++){ + irep_idt renamed_id=*d_it; // attach the '@' symbol if not already there ssa_inliner.rename(renamed_id, depnode.rename_counter, true); renamed_dependencies.insert(renamed_id); } - worknode.dependency_set = renamed_dependencies; + worknode.dependency_set=renamed_dependencies; if(!worknode.dependency_set.empty()){ find_symbols_sett guard_dependencies; find_symbols(depnode.guard, guard_dependencies); - for(find_symbols_sett::const_iterator d_it = guard_dependencies.begin(); - d_it != guard_dependencies.end(); d_it++){ + for(find_symbols_sett::const_iterator d_it=guard_dependencies.begin(); + d_it!=guard_dependencies.end(); d_it++){ worknode.dependency_set.insert(*d_it); } } @@ -299,9 +301,9 @@ find_symbols_sett summarizer_bw_cex_completet::inline_summaries // if the dependency set is non-empty if(!worknode.dependency_set.empty()) { - exprt worknode_info = depnode.node_info; + exprt worknode_info=depnode.node_info; - bool is_error_assertion = false; + bool is_error_assertion=false; if(depnode.is_assertion) { #if 0 @@ -310,19 +312,19 @@ find_symbols_sett summarizer_bw_cex_completet::inline_summaries #endif assert(error_assertion.id()==ID_not); if(error_assertion.op0().id()!=ID_and) - is_error_assertion = (worknode_info == error_assertion.op0()); + is_error_assertion=(worknode_info==error_assertion.op0()); else forall_operands(a_it, error_assertion.op0()) - if(worknode_info == *a_it) + if(worknode_info==*a_it) { - is_error_assertion = true; + is_error_assertion=true; break; } } - - if(worknode.node_index != 0){ + + if(worknode.node_index!=0){ if(!(depnode.is_function_call)){ - if(!depnode.is_assertion || is_error_assertion) + if(!depnode.is_assertion || is_error_assertion) { /* std::cout << "Solver <-- " << function_name << ": (node) node#:" @@ -337,23 +339,23 @@ find_symbols_sett summarizer_bw_cex_completet::inline_summaries << from_expr((ssa_db.get(function_name)).ns, "", worknode_info) << "\n"; #endif - if(depnode.is_assertion) //keep for later + if(depnode.is_assertion) // keep for later renamed_error_assertion.push_back(worknode_info); else solver << worknode_info; if(depnode.is_loop) { - //loop head selects - exprt lsguard = depnode.guard; + // loop head selects + exprt lsguard=depnode.guard; ssa_inliner.rename(lsguard, counter); loophead_selects.push_back(lsguard); - //solver.solver->set_frozen(solver.convert(lsguard)); - add_reason_to_check(lsguard,function_name,false,depnode.location); + // solver.solver->set_frozen(solver.convert(lsguard)); + add_reason_to_check(lsguard, function_name, false, depnode.location); - //loop continuations + // loop continuations exprt::operandst local_loop_continues; - get_loop_continues(SSA, ssa_local_unwinder, depnode.location, + get_loop_continues(function_name, SSA, depnode.location, local_loop_continues); for(size_t i=0; inode_index == pred_node_index){ - - dependencies_merged = true; - + + ssa_dependency_grapht::annotated_predecessort pred=*p_it; + int pred_node_index=pred.predecessor_node_index; + find_symbols_sett pred_annotation=pred.annotation; + + bool dependencies_merged=false; + for(worklistt::iterator w_it=work_waitlist.begin(); w_it!=work_waitlist.end(); w_it++){ + if(w_it->node_index==pred_node_index){ + + dependencies_merged=true; + for(find_symbols_sett::const_iterator a_it=pred_annotation.begin(); a_it!=pred_annotation.end(); a_it++) { - if(worknode.dependency_set.find(*a_it) != worknode.dependency_set.end()){ - if((w_it->dependency_set).find(*a_it) == (w_it->dependency_set).end()){ + if(worknode.dependency_set.find(*a_it)!=worknode.dependency_set.end()){ + if((w_it->dependency_set).find(*a_it)==(w_it->dependency_set).end()){ (w_it->dependency_set).insert(*a_it); } } @@ -429,18 +431,18 @@ find_symbols_sett summarizer_bw_cex_completet::inline_summaries break; } } - - if(dependencies_merged == false){ + + if(dependencies_merged==false){ worknodet new_worknode; - new_worknode.node_index = pred_node_index; - + new_worknode.node_index=pred_node_index; + for(find_symbols_sett::const_iterator a_it=pred_annotation.begin(); a_it!=pred_annotation.end(); a_it++) { - if(worknode.dependency_set.find(*a_it) != worknode.dependency_set.end()) + if(worknode.dependency_set.find(*a_it)!=worknode.dependency_set.end()) new_worknode.dependency_set.insert(*a_it); } - + work_waitlist.push_back(new_worknode); } } @@ -448,7 +450,7 @@ find_symbols_sett summarizer_bw_cex_completet::inline_summaries #if 0 std::cout << function_name << ": worklist: "; for(worklistt::const_iterator w_it=worklist.begin(); - w_it != worklist.end(); w_it++){ + w_it!=worklist.end(); w_it++){ std::cout << w_it->node_index << " "; } std::cout << "\n"; @@ -456,7 +458,7 @@ find_symbols_sett summarizer_bw_cex_completet::inline_summaries std::cout << "\t" << function_name << ": waitlist: "; for(worklistt::const_iterator w_it=work_waitlist.begin(); - w_it != work_waitlist.end(); w_it++){ + w_it!=work_waitlist.end(); w_it++){ std::cout << w_it->node_index << " "; } std::cout << "\n"; @@ -467,28 +469,28 @@ find_symbols_sett summarizer_bw_cex_completet::inline_summaries #if 0 std::cout << function_name << ": covered : "; - for(int l = 0; l < covered_nodes.size(); l++){ + for(int l=0; l &waitlisted_worknode_successors = + for(worklistt::const_iterator w_it=iterate_work_waitlist.begin(); w_it!=iterate_work_waitlist.end(); w_it++){ + worknodet waitlisted_worknode=*w_it; + + bool uncovered_successor=false; + + std::vector &waitlisted_worknode_successors= ssa_depgraph.depnodes_map[waitlisted_worknode.node_index].successors; - - for(unsigned i = 0; i < waitlisted_worknode_successors.size(); i++){ - bool check_covered = false; - for(unsigned j = 0; j < covered_nodes.size(); j++){ - if(waitlisted_worknode_successors[i] == covered_nodes[j]){ - check_covered = true; + + for(unsigned i=0; iis_in_conflict(formula[i])) { debug() << "is_in_conflict: " << from_expr(ns, "", formula_expr[i]) << eom; - const reason_to_checkt &r = reasons_to_check[i]; + const reason_to_checkt &r=reasons_to_check[i]; if(r.is_function) reason[r.function_name].functions.insert(r.info); else @@ -593,7 +595,7 @@ property_checkert::resultt summarizer_bw_cex_completet::check() } bvt assumptions; solver.solver->set_assumptions(assumptions); - for(unsigned i=0; i " << function_name << " ; dependency_set -> "; - for(find_symbols_sett::iterator d_it = dependency_set.begin(); - d_it != dependency_set.end(); d_it++){ + for(find_symbols_sett::iterator d_it=dependency_set.begin(); + d_it!=dependency_set.end(); d_it++){ std::cout << *d_it << ", "; } std::cout << "\n"; @@ -649,32 +651,32 @@ Function: summarizer_bw_cex_completet::add_reason_to_check Outputs: - Purpose: + Purpose: \*******************************************************************/ void summarizer_bw_cex_completet::add_reason_to_check( const exprt &expr, const function_namet &function_name, - bool is_function, - const local_SSAt::locationt & info) + bool is_function, + const local_SSAt::locationt & info) { - literalt l = solver.solver->convert(expr); + literalt l=solver.solver->convert(expr); if(l.is_false()) { - literalt dummy = solver.solver->convert(symbol_exprt("goto_symex::\\dummy", + literalt dummy=solver.solver->convert(symbol_exprt("goto_symex::\\dummy", bool_typet())); formula.push_back(dummy); formula.push_back(!dummy); } - else if(!l.is_true()) + else if(!l.is_true()) { formula.push_back(l); formula_expr.push_back(expr); reasons_to_check.push_back(reason_to_checkt()); - reason_to_checkt &r = reasons_to_check.back(); - r.function_name = function_name; - r.info = info; - r.is_function = is_function; + reason_to_checkt &r=reasons_to_check.back(); + r.function_name=function_name; + r.info=info; + r.is_function=is_function; } } diff --git a/src/summarizer/summarizer_bw_cex_complete.h b/src/solver/summarizer_bw_cex_complete.h similarity index 51% rename from src/summarizer/summarizer_bw_cex_complete.h rename to src/solver/summarizer_bw_cex_complete.h index 8646c409d..df4ca0094 100644 --- a/src/summarizer/summarizer_bw_cex_complete.h +++ b/src/solver/summarizer_bw_cex_complete.h @@ -2,20 +2,20 @@ Module: Simple Complete Counterexample-based Backward Analysis -Author: Peter Schrammel +Author: Madhukar Kumar, Peter Schrammel \*******************************************************************/ -#ifndef CPROVER_SUMMARIZER_BW_CEX_COMPLETE_H -#define CPROVER_SUMMARIZER_BW_CEX_COMPLETE_H +#ifndef CPROVER_2LS_SOLVER_SUMMARIZER_BW_CEX_COMPLETE_H +#define CPROVER_2LS_SOLVER_SUMMARIZER_BW_CEX_COMPLETE_H #include #include #include -#include "../ssa/ssa_inliner.h" -#include "../ssa/ssa_unwinder.h" -#include "../ssa/local_ssa.h" -#include "ssa_db.h" +#include +#include +#include +#include #include @@ -25,27 +25,27 @@ class summarizer_bw_cex_completet : public summarizer_bw_cex_baset { public: explicit summarizer_bw_cex_completet(optionst &_options, - summary_dbt &_summary_db, - ssa_dbt &_ssa_db, - ssa_unwindert &_ssa_unwinder, - ssa_inlinert &_ssa_inliner, - incremental_solvert &_solver, - function_namet _entry_function, - function_namet _error_function): - summarizer_bw_cex_baset(_options,_summary_db,_ssa_db,_ssa_unwinder,_ssa_inliner, - _entry_function,_error_function), + summary_dbt &_summary_db, + ssa_dbt &_ssa_db, + ssa_unwindert &_ssa_unwinder, + ssa_inlinert &_ssa_inliner, + incremental_solvert &_solver, + function_namet _entry_function, + function_namet _error_function): + summarizer_bw_cex_baset(_options, _summary_db, _ssa_db, _ssa_unwinder, _ssa_inliner, + _entry_function, _error_function), solver(_solver) {} - + virtual void summarize(const function_namet &entry_function); virtual void summarize(const exprt &_error_assertion); virtual property_checkert::resultt check(); - + protected: incremental_solvert &solver; - bvt formula; //for UNSAT core - exprt::operandst formula_expr; //for debugging + bvt formula; // for UNSAT core + exprt::operandst formula_expr; // for debugging exprt::operandst loophead_selects; exprt::operandst loop_continues; exprt::operandst renamed_error_assertion; @@ -58,22 +58,22 @@ class summarizer_bw_cex_completet : public summarizer_bw_cex_baset std::vector reasons_to_check; void add_reason_to_check( const exprt &expr, - const function_namet &function_name, - bool is_function, + const function_namet &function_name, + bool is_function, const local_SSAt::locationt & info); virtual find_symbols_sett inline_summaries( - const function_namet &function_name, - find_symbols_sett &dependency_set, - int counter); - + const function_namet &function_name, + find_symbols_sett &dependency_set, + int counter); + virtual find_symbols_sett compute_summary_rec( - const function_namet &function_name, - find_symbols_sett &dependency_set, - int counter); + const function_namet &function_name, + find_symbols_sett &dependency_set, + int counter); virtual void debug_print( - const function_namet &function_name, - find_symbols_sett &dependency_set); + const function_namet &function_name, + find_symbols_sett &dependency_set); }; diff --git a/src/summarizer/summarizer_bw_cex_concrete.cpp b/src/solver/summarizer_bw_cex_concrete.cpp similarity index 54% rename from src/summarizer/summarizer_bw_cex_concrete.cpp rename to src/solver/summarizer_bw_cex_concrete.cpp index 3406d337e..9678ebc15 100644 --- a/src/summarizer/summarizer_bw_cex_concrete.cpp +++ b/src/solver/summarizer_bw_cex_concrete.cpp @@ -1,20 +1,20 @@ /*******************************************************************\ -Module: Simple Counterexample-based Backward Analysis +Module: Simple Counterexample-based Backward Analysis Author: Kumar Madhukar, Peter Schrammel \*******************************************************************/ -//#define OPT_11 // simplify before pushing to solver +// #define OPT_11 // simplify before pushing to solver #define OPT_12 // collect, conjunct, simplify and then push to the solver -//#define OPT_2 // a fresh solver each time +// #define OPT_2 // a fresh solver each time -//TODO: a bug in the fresh solver case; does not compute -//calling contexts (see struct tests in regression) +// TODO: a bug in the fresh solver case; does not compute +// calling contexts (see struct tests in regression) -//#define DEBUG +// #define DEBUG #include @@ -42,17 +42,17 @@ Function: summarizer_bw_cex_concretet::summarize() Outputs: - Purpose: + Purpose: \*******************************************************************/ void summarizer_bw_cex_concretet::summarize(const function_namet &function_name) { - exprt postcondition = true_exprt(); //initial calling context + exprt postcondition=true_exprt(); // initial calling context status() << "\nSummarizing function " << function_name << eom; - compute_summary_rec(function_name,summaryt::entry_call_site, - postcondition,true); + compute_summary_rec(function_name, summaryt::entry_call_site, + postcondition, true); } /*******************************************************************\ @@ -70,7 +70,7 @@ Function: summarizer_bw_cex_concretet::summarize() void summarizer_bw_cex_concretet::summarize(const exprt &_error_assertion) { status() << "\nBackward error analysis (concrete)..." << eom; - error_assertion = _error_assertion; + error_assertion=_error_assertion; summarize(entry_function); } @@ -83,47 +83,45 @@ Function: summarizer_bw_cex_concretet::check() Outputs: - Purpose: + Purpose: \*******************************************************************/ property_checkert::resultt summarizer_bw_cex_concretet::check() { - property_checkert::resultt result = property_checkert::FAIL; + property_checkert::resultt result=property_checkert::FAIL; if(!summary_db.exists(entry_function)) { - result = property_checkert::UNKNOWN; + result=property_checkert::UNKNOWN; } else { - const summaryt &summary = summary_db.get(entry_function); + const summaryt &summary=summary_db.get(entry_function); if(summary.error_summaries.empty() || summary.error_summaries.begin()->second.is_nil() || summary.error_summaries.begin()->second.is_true()) - result = property_checkert::UNKNOWN; + result=property_checkert::UNKNOWN; } - //we are only complete if everything was inlined - if(result == property_checkert::UNKNOWN && + // we are only complete if everything was inlined + if(result==property_checkert::UNKNOWN && options.get_bool_option("inline")) { - incremental_solvert &solver = ssa_db.get_solver(entry_function); - const local_SSAt &ssa = ssa_db.get(entry_function); - ssa_local_unwindert &ssa_local_unwinder = - ssa_unwinder.get(entry_function); + incremental_solvert &solver=ssa_db.get_solver(entry_function); + const local_SSAt &ssa=ssa_db.get(entry_function); exprt::operandst loophead_selects; exprt::operandst loop_continues; - get_loophead_selects(ssa, ssa_local_unwinder, + get_loophead_selects(entry_function, ssa, *solver.solver, loophead_selects); - get_loop_continues(ssa, ssa_local_unwinder, loop_continues); - //check whether loops have been fully unwound - bool fully_unwound = - is_fully_unwound(loop_continues,loophead_selects,solver); - status() << "Loops " << (fully_unwound ? "" : "not ") + get_loop_continues(entry_function, ssa, *solver.solver, loop_continues); + // check whether loops have been fully unwound + bool fully_unwound= + is_fully_unwound(loop_continues, loophead_selects, solver); + status() << "Loops " << (fully_unwound ? "" : "not ") << "fully unwound" << eom; if(fully_unwound) - result = property_checkert::PASS; + result=property_checkert::PASS; } return result; @@ -147,57 +145,57 @@ void summarizer_bw_cex_concretet::compute_summary_rec( const exprt &_postcondition, bool context_sensitive) { - local_SSAt &SSA = ssa_db.get(function_name); + local_SSAt &SSA=ssa_db.get(function_name); - //TODO: let's just put all loops into the reason - for(local_SSAt::nodest::iterator n_it = SSA.nodes.begin(); - n_it != SSA.nodes.end(); ++n_it) - if (n_it->loophead != SSA.nodes.end()) + // TODO: let's just put all loops into the reason + for(local_SSAt::nodest::iterator n_it=SSA.nodes.begin(); + n_it!=SSA.nodes.end(); ++n_it) + if (n_it->loophead!=SSA.nodes.end()) reason[function_name].loops.insert(n_it->loophead->location); - + summaryt summary; if(summary_db.exists(function_name)) - summary = summary_db.get(function_name); + summary=summary_db.get(function_name); else { - summary.params = SSA.params; - summary.globals_in = SSA.globals_in; - summary.globals_out = SSA.globals_out; - summary.nondets = SSA.nondets; + summary.params=SSA.params; + summary.globals_in=SSA.globals_in; + summary.globals_out=SSA.globals_out; + summary.nondets=SSA.nondets; } // insert assertion - exprt end_guard = SSA.guard_symbol(--SSA.goto_function.body.instructions.end()); - exprt postcondition = implies_exprt(end_guard,_postcondition); - if(function_name == error_function) + exprt end_guard=SSA.guard_symbol(--SSA.goto_function.body.instructions.end()); + exprt postcondition=implies_exprt(end_guard, _postcondition); + if(function_name==error_function) { - postcondition = and_exprt(postcondition,not_exprt(error_assertion)); + postcondition=and_exprt(postcondition, not_exprt(error_assertion)); } - - summary.bw_postcondition = _postcondition; + + summary.bw_postcondition=_postcondition; #if 0 debug() << "Postcondition: " << from_expr(SSA.ns, "", postcondition) << eom; #endif - + // recursively compute summaries for function calls - inline_summaries(function_name,SSA,summary, - postcondition,context_sensitive, - true); + inline_summaries(function_name, SSA, summary, + postcondition, context_sensitive, + true); status() << "Analyzing function " << function_name << eom; - do_summary(function_name,call_site,SSA,summary,summary,postcondition,context_sensitive); + do_summary(function_name, call_site, SSA, summary, summary, postcondition, context_sensitive); - if(function_name == error_function) - summary.has_assertion = true; + if(function_name==error_function) + summary.has_assertion=true; - summary_db.set(function_name,summary); + summary_db.set(function_name, summary); { std::ostringstream out; out << std::endl << "Summary for function " << function_name << std::endl; - summary_db.get(function_name).output(out,SSA.ns); + summary_db.get(function_name).output(out, SSA.ns); debug() << out.str() << eom; } @@ -216,7 +214,7 @@ Function: summarizer_bw_cex_concretet::do_summary() \*******************************************************************/ void summarizer_bw_cex_concretet::do_summary( - const function_namet &function_name, + const function_namet &function_name, const summaryt::call_sitet &call_site, local_SSAt &SSA, const summaryt &old_summary, @@ -229,18 +227,18 @@ void summarizer_bw_cex_concretet::do_summary( // solver #ifdef OPT_2 - incremental_solvert* fresh_solver = + incremental_solvert* fresh_solver= incremental_solvert::allocate(SSA.ns, options.get_bool_option("refine")); - incremental_solvert &solver = (*fresh_solver); + incremental_solvert &solver=(*fresh_solver); SSA.unmark_nodes(); exprt::operandst store; #else - incremental_solvert &solver = ssa_db.get_solver(function_name); + incremental_solvert &solver=ssa_db.get_solver(function_name); #endif - + solver.set_message_handler(get_message_handler()); - //ENHANCE: we could reuse the solver state, but it's difficult + // ENHANCE: we could reuse the solver state, but it's difficult // (the function maybe called several times) exprt::operandst c; @@ -248,24 +246,24 @@ void summarizer_bw_cex_concretet::do_summary( exprt::operandst store; #endif - //add forward information if available + // add forward information if available if(!old_summary.fw_precondition.is_nil()) c.push_back(old_summary.fw_precondition); if(!old_summary.fw_invariant.is_nil()) c.push_back(old_summary.fw_invariant); - c.push_back(ssa_inliner.get_summaries(SSA)); //forward summaries + c.push_back(ssa_inliner.get_summaries(SSA)); // forward summaries exprt::operandst assert_postcond, noassert_postcond; // add error summaries for function calls bool assertion_flag; - assertion_flag = ssa_inliner.get_summaries(SSA,call_site,false,assert_postcond,noassert_postcond,c); //backward summaries - assert_postcond.push_back(postcondition); //context + assertion_flag=ssa_inliner.get_summaries(SSA, call_site, false, assert_postcond, noassert_postcond, c); // backward summaries + assert_postcond.push_back(postcondition); // context - //add nondet variables from callees to summary.nondets + // add nondet variables from callees to summary.nondets std::set summary_vars; - find_symbols(conjunction(assert_postcond),summary_vars); - for(std::set::const_iterator it = summary_vars.begin(); - it != summary_vars.end(); ++it) + find_symbols(conjunction(assert_postcond), summary_vars); + for(std::set::const_iterator it=summary_vars.begin(); + it!=summary_vars.end(); ++it) if(it->id()==ID_nondet_symbol) summary.nondets.insert(*it); @@ -274,12 +272,12 @@ void summarizer_bw_cex_concretet::do_summary( std::cout << "Noassert Summary: " << from_expr(SSA.ns, "", conjunction(noassert_postcond)) << "\n\n"; #endif - c.push_back(not_exprt(conjunction(assert_postcond))); - c.push_back(not_exprt(disjunction(noassert_postcond))); + c.push_back(not_exprt(conjunction(assert_postcond))); + c.push_back(not_exprt(disjunction(noassert_postcond))); #ifdef DEBUG - debug() << "Backward summaries: " << - from_expr(SSA.ns, "", simplify_expr(conjunction(c),SSA.ns)) << eom; + debug() << "Backward summaries: " << + from_expr(SSA.ns, "", simplify_expr(conjunction(c), SSA.ns)) << eom; #endif #ifdef OPT_12 @@ -292,19 +290,19 @@ void summarizer_bw_cex_concretet::do_summary( #endif #endif -#ifndef OPT_2 +#ifndef OPT_2 solver.new_context(); #endif // assumptions must hold - for(local_SSAt::nodest::const_iterator - n_it = SSA.nodes.begin(); - n_it != SSA.nodes.end(); + for(local_SSAt::nodest::const_iterator + n_it=SSA.nodes.begin(); + n_it!=SSA.nodes.end(); ++n_it) - for(local_SSAt::nodet::assumptionst::const_iterator - a_it = n_it->assumptions.begin(); - a_it != n_it->assumptions.end(); - ++a_it) + for(local_SSAt::nodet::assumptionst::const_iterator + a_it=n_it->assumptions.begin(); + a_it!=n_it->assumptions.end(); + ++a_it) { #ifdef OPT_11 @@ -346,10 +344,10 @@ void summarizer_bw_cex_concretet::do_summary( #endif #endif #endif - + exprt::operandst loophead_selects; - get_loophead_selects(SSA,ssa_unwinder.get(function_name),*solver.solver,loophead_selects); - + get_loophead_selects(function_name, SSA, *solver.solver, loophead_selects); + #ifdef OPT_11 solver << simplify_expr(conjunction(loophead_selects), SSA.ns); #else @@ -377,76 +375,56 @@ void summarizer_bw_cex_concretet::do_summary( solver << simplify_expr(conjunction(store), SSA.ns); #endif - //statistics + // statistics solver_calls++; - //solve - if(solver() == decision_proceduret::D_UNSATISFIABLE) + // solve + if(solver()==decision_proceduret::D_UNSATISFIABLE) { - summary.error_summaries[call_site] = true_exprt(); //TODO: this is likely to be incomplete - summary.has_assertion = assertion_flag; -#ifndef OPT_2 + summary.error_summaries[call_site]=true_exprt(); // TODO: this is likely to be incomplete + summary.has_assertion=assertion_flag; +#ifndef OPT_2 solver.pop_context(); #endif -(??)#ifdef DEBUG -(??) /* -(??) // if the summary is true, print the postcondition and the list of loops in this function -(??) // this postcondition is modified, possibly twice, from what is returned by compute_calling_context2 -(??) // pc = end_guard => original_pc, and -(??) // pc = pc && not(assertion), if this is error function -(??) std::cout << "==>>\n"; -(??) std::cout << "==>> Summary: true\n"; -(??) std::cout << "==>> Postcondition: " << from_expr(SSA.ns, "", postcondition) << "\n"; -(??) std::cout << "==>> Function: " << function_name << "\n"; -(??) std::cout << "==>> Loophead selects: " << from_expr(SSA.ns, "", conjunction(loophead_selects)) << "\n"; -(??) for(local_SSAt::nodest::const_iterator n_it = SSA.nodes.begin(); -(??) n_it != SSA.nodes.end(); n_it++){ -(??) if(n_it->loophead!=SSA.nodes.end()){ -(??) std::cout << "==>> Loop found: " << n_it->loophead->location->location_number << "\n"; -(??) } -(??) } -(??) std::cout << "==>>\n"; -(??) */ -(??)#endif return; } - - //build error summary and add to summary + + // build error summary and add to summary exprt::operandst var_values; - for(local_SSAt::var_listt::const_iterator it = SSA.params.begin(); - it != SSA.params.end(); it++){ - exprt summ_value = solver.get(*it); + for(local_SSAt::var_listt::const_iterator it=SSA.params.begin(); + it!=SSA.params.end(); it++){ + exprt summ_value=solver.get(*it); if(!summ_value.is_nil()) var_values.push_back(equal_exprt(*it, summ_value)); } - for(local_SSAt::var_sett::const_iterator it = SSA.globals_in.begin(); - it != SSA.globals_in.end(); it++){ - exprt summ_value = solver.get(*it); + for(local_SSAt::var_sett::const_iterator it=SSA.globals_in.begin(); + it!=SSA.globals_in.end(); it++){ + exprt summ_value=solver.get(*it); if(!summ_value.is_nil()) var_values.push_back(equal_exprt(*it, summ_value)); } - for(local_SSAt::var_sett::const_iterator it = SSA.globals_out.begin(); - it != SSA.globals_out.end(); it++){ - exprt summ_value = solver.get(*it); + for(local_SSAt::var_sett::const_iterator it=SSA.globals_out.begin(); + it!=SSA.globals_out.end(); it++){ + exprt summ_value=solver.get(*it); if(!summ_value.is_nil()) var_values.push_back(equal_exprt(*it, summ_value)); } - for(std::set::const_iterator it = summary.nondets.begin(); - it != summary.nondets.end(); it++){ - exprt summ_value = solver.get(*it); + for(std::set::const_iterator it=summary.nondets.begin(); + it!=summary.nondets.end(); it++){ + exprt summ_value=solver.get(*it); if(!summ_value.is_nil()) var_values.push_back(equal_exprt(*it, summ_value)); } - summary.error_summaries[call_site] = not_exprt(conjunction(var_values)); - summary.has_assertion = assertion_flag; + summary.error_summaries[call_site]=not_exprt(conjunction(var_values)); + summary.has_assertion=assertion_flag; -#ifndef OPT_2 +#ifndef OPT_2 solver.pop_context(); #endif @@ -469,35 +447,35 @@ Function: summarizer_bw_cex_concretet::inline_summaries() \*******************************************************************/ void summarizer_bw_cex_concretet::inline_summaries( - const function_namet &function_name, - local_SSAt &SSA, + const function_namet &function_name, + local_SSAt &SSA, const summaryt &old_summary, const exprt &postcondition, bool context_sensitive, bool sufficient) { - for(local_SSAt::nodest::const_iterator n_it = SSA.nodes.end(); - n_it != SSA.nodes.begin(); ) + for(local_SSAt::nodest::const_iterator n_it=SSA.nodes.end(); + n_it!=SSA.nodes.begin(); ) { n_it--; - for(local_SSAt::nodet::function_callst::const_iterator f_it = - n_it->function_calls.begin(); - f_it != n_it->function_calls.end(); f_it++) + for(local_SSAt::nodet::function_callst::const_iterator f_it= + n_it->function_calls.begin(); + f_it!=n_it->function_calls.end(); f_it++) { - assert(f_it->function().id()==ID_symbol); //no function pointers - - exprt postcondition_call = true_exprt(); - postcondition_call = compute_calling_context2( - function_name,SSA,old_summary,n_it,f_it,postcondition,sufficient); + assert(f_it->function().id()==ID_symbol); // no function pointers + + exprt postcondition_call= true_exprt(); + postcondition_call=compute_calling_context2( + function_name, SSA, old_summary, n_it, f_it, postcondition, sufficient); - //TODO: just put all function calls into reason + // TODO: just put all function calls into reason reason[function_name].functions.insert(n_it->location); - irep_idt fname = to_symbol_expr(f_it->function()).get_identifier(); + irep_idt fname=to_symbol_expr(f_it->function()).get_identifier(); status() << "Recursively summarizing function " << fname << eom; - compute_summary_rec(fname,summaryt::call_sitet(n_it->location), - postcondition_call,context_sensitive); + compute_summary_rec(fname, summaryt::call_sitet(n_it->location), + postcondition_call, context_sensitive); } } } @@ -514,28 +492,28 @@ Function: summarizer_bw_cex_concretet::compute_calling_context2() \*******************************************************************/ -exprt summarizer_bw_cex_concretet::compute_calling_context2( - const function_namet &function_name, +exprt summarizer_bw_cex_concretet::compute_calling_context2( + const function_namet &function_name, local_SSAt &SSA, summaryt old_summary, - local_SSAt::nodest::const_iterator n_it, + local_SSAt::nodest::const_iterator n_it, local_SSAt::nodet::function_callst::const_iterator f_it, const exprt &postcondition, bool sufficient) { - assert(f_it->function().id()==ID_symbol); //no function pointers - irep_idt fname = to_symbol_expr(f_it->function()).get_identifier(); + assert(f_it->function().id()==ID_symbol); // no function pointers + irep_idt fname=to_symbol_expr(f_it->function()).get_identifier(); status() << "Computing calling context for function " << fname << eom; // solver #ifdef OPT_2 - incremental_solvert* fresh_solver = + incremental_solvert* fresh_solver= incremental_solvert::allocate(SSA.ns, options.get_bool_option("refine")); - incremental_solvert &solver = (*fresh_solver); + incremental_solvert &solver=(*fresh_solver); #else - incremental_solvert &solver = ssa_db.get_solver(function_name); + incremental_solvert &solver=ssa_db.get_solver(function_name); #endif solver.set_message_handler(get_message_handler()); @@ -543,34 +521,34 @@ exprt summarizer_bw_cex_concretet::compute_calling_context2( // collect globals at call site std::map cs_globals_out; - SSA.get_globals(n_it->location,cs_globals_out[f_it],false); + SSA.get_globals(n_it->location, cs_globals_out[f_it], false); exprt::operandst c; #ifdef OPT_12 exprt::operandst store; #endif - + // add forward information if available if(!old_summary.fw_precondition.is_nil()) c.push_back(old_summary.fw_precondition); if(!old_summary.fw_invariant.is_nil()) c.push_back(old_summary.fw_invariant); - c.push_back(ssa_inliner.get_summaries(SSA)); //forward summaries + c.push_back(ssa_inliner.get_summaries(SSA)); // forward summaries exprt::operandst assert_postcond, noassert_postcond; // add error summaries for function calls - ssa_inliner.get_summaries(SSA,summaryt::call_sitet(n_it->location),false,assert_postcond,noassert_postcond,c); //backward summaries - assert_postcond.push_back(postcondition); //context - c.push_back(not_exprt(conjunction(assert_postcond))); - c.push_back(not_exprt(disjunction(noassert_postcond))); + ssa_inliner.get_summaries(SSA, summaryt::call_sitet(n_it->location), false, assert_postcond, noassert_postcond, c); // backward summaries + assert_postcond.push_back(postcondition); // context + c.push_back(not_exprt(conjunction(assert_postcond))); + c.push_back(not_exprt(disjunction(noassert_postcond))); #ifdef OPT_12 store << SSA; #else solver << SSA; #endif - + solver.new_context(); #ifdef OPT_12 @@ -588,9 +566,9 @@ exprt summarizer_bw_cex_concretet::compute_calling_context2( solver << conjunction(c); #endif #endif - + exprt::operandst loophead_selects; - get_loophead_selects(SSA,ssa_unwinder.get(function_name),*solver.solver,loophead_selects); + get_loophead_selects(function_name, SSA, *solver.solver, loophead_selects); #ifdef OPT_11 solver << simplify_expr(conjunction(loophead_selects), SSA.ns); @@ -601,50 +579,50 @@ exprt summarizer_bw_cex_concretet::compute_calling_context2( solver << conjunction(loophead_selects); #endif #endif - + #ifdef OPT_12 #ifdef DEBUG std::cout << "\n\n\n pushing to the solver in compute_calling_context2:" << from_expr(SSA.ns, "", conjunction(store)) << "\n\n\n"; #endif solver << simplify_expr(conjunction(store), SSA.ns); #endif - - + + // build postcondition exprt postcondition_call; - - if(solver() != decision_proceduret::D_SATISFIABLE) + + if(solver()!=decision_proceduret::D_SATISFIABLE) { - postcondition_call = true_exprt(); //TODO: this is likely to be incomplete + postcondition_call=true_exprt(); // TODO: this is likely to be incomplete solver.pop_context(); return postcondition_call; } - bool result = solver()==decision_proceduret::D_SATISFIABLE; + bool result=solver()==decision_proceduret::D_SATISFIABLE; assert(result); - - exprt::operandst postcond_values; - for(local_SSAt::var_sett::const_iterator it = cs_globals_out[f_it].begin(); - it != cs_globals_out[f_it].end(); it++) + + exprt::operandst postcond_values; + for(local_SSAt::var_sett::const_iterator it=cs_globals_out[f_it].begin(); + it!=cs_globals_out[f_it].end(); it++) { - exprt postc_value = solver.get(*it); + exprt postc_value=solver.get(*it); postcond_values.push_back(equal_exprt(*it, postc_value)); } - postcondition_call = conjunction(postcond_values); + postcondition_call=conjunction(postcond_values); solver.pop_context(); // get callee SSA and rename - local_SSAt &fSSA = ssa_db.get(fname); + local_SSAt &fSSA=ssa_db.get(fname); ssa_inliner.rename_to_callee(f_it, fSSA.params, - cs_globals_out[f_it],fSSA.globals_out, - postcondition_call); + cs_globals_out[f_it], fSSA.globals_out, + postcondition_call); - debug() << "Backward calling context for " << - from_expr(SSA.ns, "", *f_it) << ": " - << from_expr(SSA.ns, "", postcondition_call) << eom; + debug() << "Backward calling context for " << + from_expr(SSA.ns, "", *f_it) << ": " + << from_expr(SSA.ns, "", postcondition_call) << eom; - //statistics + // statistics solver_calls++; #ifdef OPT_2 @@ -653,5 +631,5 @@ exprt summarizer_bw_cex_concretet::compute_calling_context2( return not_exprt(postcondition_call); } - + diff --git a/src/solver/summarizer_bw_cex_concrete.h b/src/solver/summarizer_bw_cex_concrete.h new file mode 100644 index 000000000..ec517ccdc --- /dev/null +++ b/src/solver/summarizer_bw_cex_concrete.h @@ -0,0 +1,80 @@ +/*******************************************************************\ + +Module: Simple Counterexample-based Backward Analysis + +Author: Kumar Madhukar, Peter Schrammel + +\*******************************************************************/ + +#ifndef CPROVER_2LS_SOLVER_SUMMARIZER_BW_CEX_CONCRETE_H +#define CPROVER_2LS_SOLVER_SUMMARIZER_BW_CEX_CONCRETE_H + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "summarizer_bw_cex.h" + +class summarizer_bw_cex_concretet : public summarizer_bw_cex_baset +{ +public: +summarizer_bw_cex_concretet( + optionst &_options, + summary_dbt &_summary_db, + ssa_dbt &_ssa_db, + ssa_unwindert &_ssa_unwinder, + ssa_inlinert &_ssa_inliner, + function_namet _entry_function, + function_namet _error_function): + summarizer_bw_cex_baset(_options, _summary_db, _ssa_db, + _ssa_unwinder, _ssa_inliner, + _entry_function, _error_function) + {} + + virtual void summarize(const function_namet &entry_function); + virtual void summarize(const exprt &_error_assertion); + + virtual property_checkert::resultt check(); + +protected: + virtual void compute_summary_rec( + const function_namet &function_name, + const summaryt::call_sitet &call_site, + const exprt &postcondition, + bool context_sensitive); + + virtual void inline_summaries( + const function_namet &function_name, + local_SSAt &SSA, + const summaryt &old_summary, + const exprt &postcondition, + bool context_sensitive, + bool sufficient); + + virtual void do_summary( + const function_namet &function_name, + const summaryt::call_sitet &call_site, + local_SSAt &SSA, + const summaryt &old_summary, + summaryt &summary, + const exprt &postcondition, + bool context_sensitive); + + virtual exprt compute_calling_context2( + const function_namet &function_name, + local_SSAt &SSA, + summaryt old_summary, + local_SSAt::nodest::const_iterator n_it, + local_SSAt::nodet::function_callst::const_iterator f_it, + const exprt &postcondition, + bool sufficient); + +}; + +#endif diff --git a/src/solver/summarizer_bw_cex_wp.cpp b/src/solver/summarizer_bw_cex_wp.cpp new file mode 100644 index 000000000..f7535f6dd --- /dev/null +++ b/src/solver/summarizer_bw_cex_wp.cpp @@ -0,0 +1,643 @@ +/*******************************************************************\ + +Module: Slicing-based WP Counterexample-based Backward Analysis + +Author: Madhukar Kumar, Peter Schrammel + +\*******************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include "summary_db.h" + +#include "../domains/ssa_analyzer.h" +#include "../domains/template_generator_summary.h" +#include "../domains/template_generator_callingcontext.h" + +#include "../ssa/local_ssa.h" +#include "../ssa/simplify_ssa.h" +#include "../ssa/ssa_dependency_graph.h" + +#include "summarizer_bw_cex_wp.h" + +/*******************************************************************\ + +Function: summarizer_bw_cex_wpt::summarize() + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +void summarizer_bw_cex_wpt::summarize +( + const function_namet &entry_function) +{ + // no dependencies to begin with + find_symbols_sett dependency_set; + + status() << "\nSummarizing function " << entry_function << eom; + compute_summary_rec(entry_function, dependency_set, -1, + summaryt::entry_call_site); +} + +/*******************************************************************\ + +Function: summarizer_bw_cex_wpt::summarize() + + Inputs: + + Outputs: + + Purpose: summarize backwards from given assertion + +\*******************************************************************/ + +void summarizer_bw_cex_wpt::summarize(const exprt &_error_assertion) +{ + status() << "\nBackward error analysis (WP)..." << eom; + error_assertion=_error_assertion; + /* + std::cout << "error assertion: " + << from_expr(ssa_db.get(entry_function).ns, "", error_assertion) + << "\n"; + */ + summarize(entry_function); +} + + +/*******************************************************************\ + +Function: summarizer_bw_cex_wpt::inline_summaries() + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +find_symbols_sett summarizer_bw_cex_wpt::inline_summaries +( + const function_namet &function_name, + const find_symbols_sett &dependency_set, + int counter, + exprt &error_summary) +{ + exprt::operandst slice; + + local_SSAt &SSA=ssa_db.get(function_name); + // solver << SSA.get_enabling_exprs(); + + exprt::operandst loophead_selects; + get_loophead_selects(function_name, SSA, *solver.solver, loophead_selects); + exprt c=conjunction(loophead_selects); + + // std::cout << "Solver <-- " << function_name << ": (conjunction of loophead_selects):" + // << "\t original info ~ " << from_expr(ssa_db.get(function_name).ns, "", c) << "\n"; + + slice.push_back(c); + ssa_inliner.rename(c, counter); + +#if 0 + std::cout << "Solver <-- " << function_name << ": (conjunction of loophead_selects):" + << "\t renamed info ~ " << from_expr(ssa_db.get(function_name).ns, "", c) << "\n"; +#endif + + solver << c; + + ssa_dependency_grapht &ssa_depgraph=ssa_db.get_depgraph(function_name); + + struct worknodet{ + int node_index; + find_symbols_sett dependency_set; + }; + + worknodet start_node; + start_node.node_index=0; + start_node.dependency_set=dependency_set; + + typedef std::list worklistt; + worklistt worklist, work_waitlist; + std::vector covered_nodes; + + worklist.push_back(start_node); + + while(!worklist.empty()){ + + /* + std::cout << "worklist: "; + for(worklistt::const_iterator w_it=worklist.begin(); + w_it!=worklist.end(); w_it++){ + std::cout << w_it->node_index << " "; + } + std::cout << "\n"; + + std::cout << "\t waitlist: "; + for(worklistt::const_iterator w_it=work_waitlist.begin(); + w_it!=work_waitlist.end(); w_it++){ + std::cout << w_it->node_index << " "; + } + std::cout << "\n"; + */ + + worknodet &worknode=worklist.front(); + + // std::cout << "working node: " << function_name << ": " << worknode.node_index << "\n"; + // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // / + // std::cout << "\t size of dependency set: " << worknode.dependency_set.size() << "\n"; + /* + std::cout << "\t dependency set: "; + for(find_symbols_sett::iterator d_it=worknode.dependency_set.begin(); + d_it!=worknode.dependency_set.end(); d_it++){ + std::cout << *d_it; + } + std::cout << "\n\n\n"; + */ + // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // / + + + // return if the top most node is reached + if(worknode.node_index==ssa_depgraph.top_node_index) + { + find_symbols_sett vars=worknode.dependency_set; + vars.insert(dependency_set.begin(), dependency_set.end()); + error_summary=simplify_summary(SSA.ns, conjunction(slice), vars); + return worknode.dependency_set; + } + + // modify worknode_dependency_set if the node is an assertion + if(ssa_depgraph.depnodes_map[worknode.node_index].is_assertion==true){ + + // std::cout << "\t\t an assertion node\n"; + for(find_symbols_sett::const_iterator d_it=ssa_depgraph.depnodes_map[worknode.node_index].used_symbols.begin(); + d_it!=ssa_depgraph.depnodes_map[worknode.node_index].used_symbols.end(); d_it++){ + worknode.dependency_set.insert(*d_it); + } + + // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // / + /* + std::cout << "\t size of dependency set: " << worknode.dependency_set.size() << "\n"; + + std::cout << "\t dependency set: "; + for(find_symbols_sett::iterator d_it=worknode.dependency_set.begin(); + d_it!=worknode.dependency_set.end(); d_it++){ + std::cout << *d_it; + } + std::cout << "\n"; + */ + // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // / + + + + } + + // if this is a function call + if(ssa_depgraph.depnodes_map[worknode.node_index].is_function_call==true){ + // std::cout << "fcall: working node: " << function_name << ": " << worknode.node_index << "\n"; + irep_idt fname= + to_symbol_expr((to_function_application_expr(ssa_depgraph.depnodes_map[worknode.node_index].node_info)).function()).get_identifier(); + + find_symbols_sett renamed_dependencies; + + // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // / + /* + std::cout << "\t size of dependency set: " << worknode.dependency_set.size() << "\n"; + + std::cout << "\t dependency set: "; + for(find_symbols_sett::iterator d_it=worknode.dependency_set.begin(); + d_it!=worknode.dependency_set.end(); d_it++){ + std::cout << *d_it; + } + std::cout << "\n"; + */ + // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // / + + for(find_symbols_sett::iterator d_it=worknode.dependency_set.begin(); + d_it!=worknode.dependency_set.end(); d_it++){ + irep_idt renamed_id=*d_it; + // detach the '@' symbol if there + ssa_inliner.rename(renamed_id, + ssa_depgraph.depnodes_map[worknode.node_index].rename_counter, false); + renamed_dependencies.insert(renamed_id); + } + + worknode.dependency_set=renamed_dependencies; + + if(!worknode.dependency_set.empty()){ + find_symbols_sett guard_dependencies; + find_symbols(ssa_depgraph.depnodes_map[worknode.node_index].guard, + guard_dependencies); + for(find_symbols_sett::const_iterator d_it=guard_dependencies.begin(); + d_it!=guard_dependencies.end(); d_it++){ + worknode.dependency_set.insert(*d_it); + } + } + + // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // / + /* + std::cout << "\t size of dependency set: " << worknode.dependency_set.size() << "\n"; + + std::cout << "\t dependency set: "; + for(find_symbols_sett::iterator d_it=worknode.dependency_set.begin(); + d_it!=worknode.dependency_set.end(); d_it++){ + std::cout << *d_it; + } + std::cout << "\n"; + */ + // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // / + + worknode.dependency_set= + compute_summary_rec(fname, worknode.dependency_set, + ssa_depgraph.depnodes_map[worknode.node_index].rename_counter, summaryt::call_sitet(ssa_depgraph.depnodes_map[worknode.node_index].location)); + slice.push_back(ssa_depgraph.depnodes_map[worknode.node_index].node_info); + + renamed_dependencies.clear(); + + for(find_symbols_sett::iterator d_it=worknode.dependency_set.begin(); + d_it!=worknode.dependency_set.end(); d_it++){ + irep_idt renamed_id=*d_it; + // detach the '@' symbol if there + ssa_inliner.rename(renamed_id, + ssa_depgraph.depnodes_map[worknode.node_index].rename_counter, false); + renamed_dependencies.insert(renamed_id); + } + + worknode.dependency_set=renamed_dependencies; + + if(!worknode.dependency_set.empty()){ + find_symbols_sett guard_dependencies; + find_symbols(ssa_depgraph.depnodes_map[worknode.node_index].guard, guard_dependencies); + for(find_symbols_sett::const_iterator d_it=guard_dependencies.begin(); + d_it!=guard_dependencies.end(); d_it++){ + worknode.dependency_set.insert(*d_it); + } + } + + } + + // if the dependency set is non-empty + if(!worknode.dependency_set.empty()){ + exprt worknode_info=ssa_depgraph.depnodes_map[worknode.node_index].node_info; + if(ssa_depgraph.depnodes_map[worknode.node_index].is_assertion==true) + worknode_info=not_exprt(worknode_info); + + if(worknode.node_index!=0){ + if(!(ssa_depgraph.depnodes_map[worknode.node_index].is_function_call)){ + if((ssa_depgraph.depnodes_map[worknode.node_index].is_assertion==false) || + (worknode_info==error_assertion)){ + /* + std::cout << "Solver <-- " << function_name << ": (node) node#:" + << worknode.node_index << "\t original info ~ " + << from_expr((ssa_db.get(function_name)).ns, "", worknode_info) << "\n"; + */ + slice.push_back(worknode_info); + ssa_inliner.rename(worknode_info, counter); +#if 0 + std::cout << "Solver <-- renamed assertion: " << from_expr((ssa_db.get(function_name)).ns, "", worknode_info) << "\n"; + std::cout << "Solver <-- " << function_name << ": (node) node#:" + << worknode.node_index << "\t renamed info ~ " + << from_expr((ssa_db.get(function_name)).ns, "", worknode_info) << "\n"; +#endif + solver << worknode_info; + } + } + else{ + exprt guard_binding=ssa_depgraph.depnodes_map[worknode.node_index].guard; + /* + std::cout << "Solver <-- " << function_name << ": (bind) node#:" + << worknode.node_index << "\t original info ~ " + << from_expr(ssa_db.get(function_name).ns, "", guard_binding) << "\n"; + */ + ssa_inliner.rename(guard_binding, counter); +#if 0 + std::cout << "Solver <-- " << function_name << ": (bind) node#:" + << worknode.node_index << "\t renamed info ~ " + << from_expr(ssa_db.get(function_name).ns, "", guard_binding) << "\n"; +#endif + solver << guard_binding; + slice.push_back(guard_binding); + } + } + } + + // if not a function call and the dependency set is non-empty + if((ssa_depgraph.depnodes_map[worknode.node_index].is_function_call==false) && + (!worknode.dependency_set.empty())){ + + exprt worknode_info=ssa_depgraph.depnodes_map[worknode.node_index].node_info; + if(ssa_depgraph.depnodes_map[worknode.node_index].is_assertion==true) + worknode_info=not_exprt(worknode_info); + + if((ssa_depgraph.depnodes_map[worknode.node_index].is_assertion==false) || + (worknode_info==error_assertion)){ + worknode.dependency_set= + ssa_depgraph.depnodes_map[worknode.node_index].used_symbols; + } + } + + for(ssa_dependency_grapht::annotated_predecessorst::const_iterator + p_it=ssa_depgraph.depnodes_map[worknode.node_index].predecessors.begin(); + p_it!=ssa_depgraph.depnodes_map[worknode.node_index].predecessors.end(); + p_it++){ + + ssa_dependency_grapht::annotated_predecessort pred=*p_it; + int pred_node_index=pred.predecessor_node_index; + find_symbols_sett pred_annotation=pred.annotation; + + bool dependencies_merged=false; + for(worklistt::iterator w_it=work_waitlist.begin(); w_it!=work_waitlist.end(); w_it++){ + if(w_it->node_index==pred_node_index){ + + dependencies_merged=true; + + for(find_symbols_sett::const_iterator + a_it=pred_annotation.begin(); a_it!=pred_annotation.end(); a_it++) + { + if(worknode.dependency_set.find(*a_it)!=worknode.dependency_set.end()){ + if((w_it->dependency_set).find(*a_it)==(w_it->dependency_set).end()){ + (w_it->dependency_set).insert(*a_it); + } + } + } + break; + } + } + + if(dependencies_merged==false){ + worknodet new_worknode; + new_worknode.node_index=pred_node_index; + + for(find_symbols_sett::const_iterator + a_it=pred_annotation.begin(); a_it!=pred_annotation.end(); a_it++) + { + if(worknode.dependency_set.find(*a_it)!=worknode.dependency_set.end()) + new_worknode.dependency_set.insert(*a_it); + } + + work_waitlist.push_back(new_worknode); + } + } + +#if 0 + std::cout << function_name << ": worklist: "; + for(worklistt::const_iterator w_it=worklist.begin(); + w_it!=worklist.end(); w_it++){ + std::cout << w_it->node_index << " "; + } + std::cout << "\n"; + + + std::cout << "\t" << function_name << ": waitlist: "; + for(worklistt::const_iterator w_it=work_waitlist.begin(); + w_it!=work_waitlist.end(); w_it++){ + std::cout << w_it->node_index << " "; + } + std::cout << "\n"; +#endif + + covered_nodes.push_back(worknode.node_index); + worklist.pop_front(); + +#if 0 + std::cout << function_name << ": covered : "; + for(int l=0; l &waitlisted_worknode_successors= + ssa_depgraph.depnodes_map[waitlisted_worknode.node_index].successors; + + for(unsigned i=0; i " << function_name + << " ; dependency_set -> "; + for(find_symbols_sett::iterator d_it=dependency_set.begin(); + d_it!=dependency_set.end(); d_it++){ + std::cout << *d_it << ", "; + } + std::cout << "\n"; +} + +/*******************************************************************\ + +Function: summarizer_bw_cex_wpt::simplify_summary() + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ +void summarizer_bw_cex_wpt::simplify_summary_build_map( + replace_mapt &replace_map, const exprt &expr) +{ + if(expr.id()==ID_equal) + { + replace_map[expr.op0()]=expr.op1(); + return; + } + forall_operands(it, expr) + simplify_summary_build_map(replace_map, *it); +} +bool summarizer_bw_cex_wpt::simplify_summary_replace( + const replace_mapt &replace_map, exprt &expr) +{ + if(expr.id()==ID_function_application) + { + bool result=true; + exprt::operandst &args=to_function_application_expr(expr).arguments(); + for(size_t i=0;i #include #include -#include "../ssa/ssa_inliner.h" -#include "../ssa/ssa_unwinder.h" -#include "../ssa/local_ssa.h" -#include "ssa_db.h" +#include +#include +#include +#include #include @@ -25,44 +25,44 @@ class summarizer_bw_cex_wpt : public summarizer_bw_cex_baset { public: explicit summarizer_bw_cex_wpt(optionst &_options, - summary_dbt &_summary_db, - ssa_dbt &_ssa_db, - ssa_unwindert &_ssa_unwinder, - ssa_inlinert &_ssa_inliner, - incremental_solvert &_solver, - function_namet _entry_function, - function_namet _error_function): - summarizer_bw_cex_baset(_options,_summary_db,_ssa_db,_ssa_unwinder,_ssa_inliner, - _entry_function,_error_function), + summary_dbt &_summary_db, + ssa_dbt &_ssa_db, + ssa_unwindert &_ssa_unwinder, + ssa_inlinert &_ssa_inliner, + incremental_solvert &_solver, + function_namet _entry_function, + function_namet _error_function): + summarizer_bw_cex_baset(_options, _summary_db, _ssa_db, _ssa_unwinder, _ssa_inliner, + _entry_function, _error_function), solver(_solver) {} - + virtual void summarize(const function_namet &entry_function); virtual void summarize(const exprt &_error_assertion); virtual property_checkert::resultt check(); - + protected: incremental_solvert &solver; virtual find_symbols_sett inline_summaries( - const function_namet &function_name, - const find_symbols_sett &dependency_set, - int counter, + const function_namet &function_name, + const find_symbols_sett &dependency_set, + int counter, exprt &error_summary); - + virtual find_symbols_sett compute_summary_rec( - const function_namet &function_name, - const find_symbols_sett &dependency_set, - int counter, - const summaryt::call_sitet &call_site); + const function_namet &function_name, + const find_symbols_sett &dependency_set, + int counter, + const summaryt::call_sitet &call_site); virtual void debug_print( - const function_namet &function_name, - find_symbols_sett &dependency_set); + const function_namet &function_name, + find_symbols_sett &dependency_set); - exprt simplify_summary(const namespacet &ns, - exprt summary, - const find_symbols_sett &vars); + exprt simplify_summary(const namespacet &ns, + exprt summary, + const find_symbols_sett &vars); void simplify_summary_build_map( replace_mapt &replace_map, const exprt &expr); bool simplify_summary_replace( diff --git a/src/solver/summary.cpp b/src/solver/summary.cpp index 9766ec416..547002037 100644 --- a/src/solver/summary.cpp +++ b/src/solver/summary.cpp @@ -16,6 +16,8 @@ Author: Peter Schrammel // #define PRETTY_PRINT +const summaryt::call_sitet summaryt::entry_call_site; + /*******************************************************************\ Function: summaryt::output @@ -77,17 +79,17 @@ void summaryt::output(std::ostream &out, const namespacet &ns) const #endif out << std::endl; out << "terminates: " << threeval2string(terminates) << std::endl; - for(error_summariest::const_iterator - it = error_summaries.begin(); - it != error_summaries.end(); it++) + for(error_summariest::const_iterator + it=error_summaries.begin(); + it!=error_summaries.end(); it++) { out << "error summary for "; - if(it->first == entry_call_site) + if(it->first==entry_call_site) out << "entry point"; else out << "location " << it->first.location_number; out << ": " << std::endl - << " " << from_expr(ns,"",it->second) << std::endl; + << " " << from_expr(ns, "", it->second) << std::endl; } } diff --git a/src/solver/summary.h b/src/solver/summary.h index 2d9d11a9e..13ce763bf 100644 --- a/src/solver/summary.h +++ b/src/solver/summary.h @@ -15,6 +15,8 @@ Author: Daniel Kroening, kroening@kroening.com #include +#include + typedef enum {YES, NO, UNKNOWN} threevalt; class summaryt @@ -53,17 +55,17 @@ class summaryt predicatet termination_argument; threevalt terminates; - //-------------- + // -------------- // the following is for generating interprocedural counterexample - bool has_assertion; + bool has_assertion; std::list nonpassed_assertions; - struct call_sitet { //TODO: we also need unwinding information here - call_sitet() + struct call_sitet { // TODO: we also need unwinding information here + call_sitet() : location_number(UINT_MAX) {} - explicit call_sitet(local_SSAt::locationt loc) + explicit call_sitet(local_SSAt::locationt loc) : location_number(loc->location_number) {} unsigned location_number; @@ -76,7 +78,7 @@ class summaryt const static call_sitet entry_call_site; typedef std::map error_summariest; error_summariest error_summaries; - //-------------- + // -------------- bool mark_recompute; // to force recomputation of the summary // (used for invariant reuse in k-induction) diff --git a/src/solver/summary_db.h b/src/solver/summary_db.h index 34c761335..04145d8a5 100644 --- a/src/solver/summary_db.h +++ b/src/solver/summary_db.h @@ -25,8 +25,8 @@ class summary_dbt:public messaget summaryt get(const function_namet &function_name) const { return store.at(function_name); } - void set(const function_namet &function_name, const summaryt &summary) - { store[function_name] = summary; } + void set(const function_namet &function_name, const summaryt &summary) + { store[function_name]=summary; } bool exists(const function_namet &function_name) const { return store.find(function_name)!=store.end(); } void put(const function_namet &function_name, const summaryt &summary); diff --git a/src/ssa/Makefile b/src/ssa/Makefile index 08f82cbb2..54979d27f 100644 --- a/src/ssa/Makefile +++ b/src/ssa/Makefile @@ -3,7 +3,7 @@ SRC = local_ssa.cpp \ guard_map.cpp ssa_object.cpp assignments.cpp ssa_dereference.cpp \ ssa_value_set.cpp address_canonizer.cpp simplify_ssa.cpp \ ssa_build_goto_trace.cpp ssa_inliner.cpp ssa_unwinder.cpp \ - unwindable_local_ssa.cpp split_loopheads.cpp const_propagator.cpp ssa_const_propagator.cpp \ + unwindable_local_ssa.cpp ssa_const_propagator.cpp \ replace_symbol_ext.cpp ssa_dependency_graph.cpp \ ssa_refiner_monolithic.cpp ssa_refiner_selective.cpp diff --git a/src/ssa/const_propagator.cpp b/src/ssa/const_propagator.cpp index 747f2af93..e418be0a9 100644 --- a/src/ssa/const_propagator.cpp +++ b/src/ssa/const_propagator.cpp @@ -6,7 +6,7 @@ Author: Peter Schrammel \*******************************************************************/ -//#define DEBUG +// #define DEBUG #include @@ -30,11 +30,11 @@ Function: const_propagator_domaint::assign_rec void const_propagator_domaint::assign_rec(const exprt &lhs, const exprt &rhs, const namespacet &ns) { - const typet & rhs_type = ns.follow(rhs.type()); + const typet & rhs_type=ns.follow(rhs.type()); #ifdef DEBUG std::cout << "assign: " << from_expr(ns, "", lhs) - << " := " << from_type(ns, "", rhs_type) << std::endl; + << " := " << from_type(ns, "", rhs_type) << std::endl; #endif if(lhs.id()==ID_symbol && rhs_type.id()!=ID_array @@ -42,12 +42,12 @@ void const_propagator_domaint::assign_rec(const exprt &lhs, const exprt &rhs, && rhs_type.id()!=ID_union) { if(!values.maps_to_top(rhs)) - assign(values,lhs,rhs,ns); + assign(values, lhs, rhs, ns); else values.set_to_top(lhs); } #if 0 - else //TODO: could make field or array element-sensitive + else // TODO: could make field or array element-sensitive { } #endif @@ -73,9 +73,9 @@ void const_propagator_domaint::transform( { #ifdef DEBUG std::cout << from->location_number << " --> " - << to->location_number << std::endl; + << to->location_number << std::endl; #endif - + if(from->is_decl()) { values.set_to_top(to_code_decl(from->code).symbol()); @@ -83,19 +83,19 @@ void const_propagator_domaint::transform( else if(from->is_assign()) { const code_assignt &assignment=to_code_assign(from->code); - const exprt &lhs = assignment.lhs(); - const exprt &rhs = assignment.rhs(); - assign_rec(lhs,rhs,ns); + const exprt &lhs=assignment.lhs(); + const exprt &rhs=assignment.rhs(); + assign_rec(lhs, rhs, ns); } else if(from->is_goto()) { if(from->guard.id()==ID_equal && from->get_target()==to) { - const exprt &lhs = from->guard.op0(); - const exprt &rhs = from->guard.op1(); + const exprt &lhs=from->guard.op0(); + const exprt &rhs=from->guard.op1(); - assign_rec(lhs,rhs,ns); - assign_rec(rhs,lhs,ns); + assign_rec(lhs, rhs, ns); + assign_rec(rhs, lhs, ns); } } else if(from->is_dead()) @@ -109,7 +109,7 @@ void const_propagator_domaint::transform( } #ifdef DEBUG - output(std::cout,ai,ns); + output(std::cout, ai, ns); #endif } @@ -133,16 +133,16 @@ void const_propagator_domaint::assign( { #ifdef DEBUG std::cout << "assign: " << from_expr(ns, "", lhs) - << " := " << from_expr(ns, "", rhs) << std::endl; + << " := " << from_expr(ns, "", rhs) << std::endl; #endif values.replace_const(rhs); - //this is to remove casts in constants propagated into the size of array types - bool valid = true; - exprt rhs_val = evaluate_casts_in_constants(rhs,lhs.type(),valid); + // this is to remove casts in constants propagated into the size of array types + bool valid=true; + exprt rhs_val=evaluate_casts_in_constants(rhs, lhs.type(), valid); if(valid) - dest.set_to(lhs,rhs_val); + dest.set_to(lhs, rhs_val); } /*******************************************************************\ @@ -159,14 +159,14 @@ Function: const_propagator_domaint::valuest::maps_to_top bool const_propagator_domaint::valuest::maps_to_top(const exprt &expr) const { - if(expr.id()==ID_side_effect && - to_side_effect_expr(expr).get_statement()==ID_nondet) + if(expr.id()==ID_side_effect && + to_side_effect_expr(expr).get_statement()==ID_nondet) return true; if(expr.id()==ID_symbol) if(replace_const.expr_map.find(expr.get(ID_identifier)) - == replace_const.expr_map.end()) + ==replace_const.expr_map.end()) return true; - forall_operands(it,expr) + forall_operands(it, expr) { if(maps_to_top(*it)) return true; @@ -188,18 +188,18 @@ Function: const_propagator_domaint::valuest::set_to_top bool const_propagator_domaint::valuest::set_to_top(const irep_idt &id) { - bool result = false; - replace_symbolt::expr_mapt::iterator r_it = + bool result=false; + replace_symbolt::expr_mapt::iterator r_it= replace_const.expr_map.find(id); - if(r_it != replace_const.expr_map.end()) + if(r_it!=replace_const.expr_map.end()) { replace_const.expr_map.erase(r_it); - result = true; + result=true; } if(top_ids.find(id)==top_ids.end()) { top_ids.insert(id); - result = true; + result=true; } return result; } @@ -211,9 +211,9 @@ bool const_propagator_domaint::valuest::set_to_top(const exprt &expr) void const_propagator_domaint::valuest::set_all_to_top() { - for(replace_symbolt::expr_mapt::iterator it = + for(replace_symbolt::expr_mapt::iterator it= replace_const.expr_map.begin(); - it != replace_const.expr_map.end(); ++it) + it!=replace_const.expr_map.end(); ++it) top_ids.insert(it->first); replace_const.expr_map.clear(); } @@ -232,18 +232,18 @@ Function: const_propagator_domaint::valuest::add \*******************************************************************/ void const_propagator_domaint::valuest::set_to(const irep_idt &lhs_id, - const exprt &rhs_val) + const exprt &rhs_val) { - replace_const.expr_map[lhs_id] = rhs_val; - std::set::iterator it = top_ids.find(lhs_id); + replace_const.expr_map[lhs_id]=rhs_val; + std::set::iterator it=top_ids.find(lhs_id); if(it!=top_ids.end()) top_ids.erase(it); } void const_propagator_domaint::valuest::set_to(const exprt &lhs, - const exprt &rhs_val) + const exprt &rhs_val) { - const irep_idt &lhs_id = to_symbol_expr(lhs).get_identifier(); - set_to(lhs_id,rhs_val); + const irep_idt &lhs_id=to_symbol_expr(lhs).get_identifier(); + set_to(lhs_id, rhs_val); } /*******************************************************************\ @@ -263,15 +263,15 @@ void const_propagator_domaint::valuest::output( const namespacet &ns) const { out << "const map: " << std::endl; - for(replace_symbolt::expr_mapt::const_iterator - it=replace_const.expr_map.begin(); + for(replace_symbolt::expr_mapt::const_iterator + it=replace_const.expr_map.begin(); it!=replace_const.expr_map.end(); ++it) out << ' ' << it->first << "=" << from_expr(ns, "", it->second) << std::endl; out << "top ids: " << std::endl; - for(std::set::const_iterator - it=top_ids.begin(); + for(std::set::const_iterator + it=top_ids.begin(); it!=top_ids.end(); ++it) out << ' ' << *it << std::endl; @@ -294,7 +294,7 @@ void const_propagator_domaint::output( const ai_baset &ai, const namespacet &ns) const { - values.output(out,ns); + values.output(out, ns); } /*******************************************************************\ @@ -311,32 +311,32 @@ Function: const_propagator_domaint::valuest::merge bool const_propagator_domaint::valuest::merge(const valuest &src) { - bool changed = false; - for(replace_symbolt::expr_mapt::const_iterator - it=src.replace_const.expr_map.begin(); + bool changed=false; + for(replace_symbolt::expr_mapt::const_iterator + it=src.replace_const.expr_map.begin(); it!=src.replace_const.expr_map.end(); ++it) { - replace_symbolt::expr_mapt::iterator - c_it = replace_const.expr_map.find(it->first); - if(c_it != replace_const.expr_map.end()) + replace_symbolt::expr_mapt::iterator + c_it=replace_const.expr_map.find(it->first); + if(c_it!=replace_const.expr_map.end()) { - if(c_it->second != it->second) + if(c_it->second!=it->second) { set_to_top(it->first); - changed = true; + changed=true; } } else if(top_ids.find(it->first)==top_ids.end()) { - set_to(it->first,it->second); - changed = true; + set_to(it->first, it->second); + changed=true; } } for(std::set::const_iterator it=src.top_ids.begin(); it!=src.top_ids.end(); ++it) { - bool c = set_to_top(*it); - changed = changed || c; + bool c=set_to_top(*it); + changed=changed || c; } return changed; @@ -368,37 +368,37 @@ Function: const_propagator_domaint::evaluate_casts_in_constants Inputs: - Outputs: + Outputs: - Purpose: + Purpose: \*******************************************************************/ -exprt const_propagator_domaint::evaluate_casts_in_constants(exprt expr, - const typet& parent_type, bool &valid) const +exprt const_propagator_domaint::evaluate_casts_in_constants(exprt expr, + const typet& parent_type, bool &valid) const { if(expr.id()==ID_side_effect) { - valid = false; + valid=false; return expr; } if(expr.type().id()!=ID_signedbv && expr.type().id()!=ID_unsignedbv) return expr; if(expr.id()==ID_typecast) - expr = evaluate_casts_in_constants(expr.op0(),expr.type(),valid); + expr=evaluate_casts_in_constants(expr.op0(), expr.type(), valid); if(expr.id()!=ID_constant) { if(expr.type()!=parent_type) - return typecast_exprt(expr,parent_type); + return typecast_exprt(expr, parent_type); else return expr; } - //TODO: could be improved to resolve float casts as well... + // TODO: could be improved to resolve float casts as well... if(expr.type().id()!=ID_signedbv && expr.type().id()!=ID_unsignedbv) return expr; mp_integer v; to_integer(to_constant_expr(expr), v); - return from_integer(v,parent_type); + return from_integer(v, parent_type); } /*******************************************************************\ @@ -407,7 +407,7 @@ Function: const_propagator_ait::replace Inputs: - Outputs: + Outputs: Purpose: @@ -419,8 +419,8 @@ void const_propagator_ait::replace( { Forall_goto_program_instructions(it, goto_function.body) { - state_mapt::iterator s_it = state_map.find(it); - if(s_it == state_map.end()) + state_mapt::iterator s_it=state_map.find(it); + if(s_it==state_map.end()) continue; replace_types_rec(s_it->second.values.replace_const, it->code); replace_types_rec(s_it->second.values.replace_const, it->guard); @@ -430,15 +430,15 @@ void const_propagator_ait::replace( } else if(it->is_assign()) { - exprt &rhs = to_code_assign(it->code).rhs(); + exprt &rhs=to_code_assign(it->code).rhs(); s_it->second.values.replace_const(rhs); } else if(it->is_function_call()) { - exprt::operandst &args = - to_code_function_call(it->code).arguments(); - for(exprt::operandst::iterator o_it = args.begin(); - o_it != args.end(); ++o_it) + exprt::operandst &args= + to_code_function_call(it->code).arguments(); + for(exprt::operandst::iterator o_it=args.begin(); + o_it!=args.end(); ++o_it) s_it->second.values.replace_const(*o_it); } } @@ -450,18 +450,18 @@ Function: const_propagator_ait::replace_types_rec Inputs: - Outputs: + Outputs: Purpose: \*******************************************************************/ void const_propagator_ait::replace_types_rec( - const replace_symbolt &replace_const, + const replace_symbolt &replace_const, exprt &expr) { replace_const(expr.type()); - Forall_operands(it,expr) - replace_types_rec(replace_const,*it); + Forall_operands(it, expr) + replace_types_rec(replace_const, *it); } diff --git a/src/ssa/const_propagator.h b/src/ssa/const_propagator.h index 6d017f8b9..a1e373e52 100644 --- a/src/ssa/const_propagator.h +++ b/src/ssa/const_propagator.h @@ -27,28 +27,28 @@ class const_propagator_domaint:public ai_domain_baset // maps variables to constants replace_symbol_extt replace_const; std::set top_ids; - + void output(std::ostream &, const namespacet &) const; - + bool merge(const valuest &src); - + inline void clear() { replace_const.expr_map.clear(); replace_const.type_map.clear(); top_ids.clear(); } - + bool empty() const { - return replace_const.expr_map.empty() && - replace_const.type_map.empty() && - top_ids.empty(); + return replace_const.expr_map.empty() && + replace_const.type_map.empty() && + top_ids.empty(); } void set_to(const exprt &lhs, const exprt &rhs_val); void set_to(const irep_idt &lhs_id, const exprt &rhs_val); - + bool maps_to_top(const exprt &expr) const; bool set_to_top(const exprt &expr); bool set_to_top(const irep_idt &id); @@ -56,7 +56,7 @@ class const_propagator_domaint:public ai_domain_baset }; valuest values; - + protected: void assign( valuest &dest, @@ -68,8 +68,8 @@ class const_propagator_domaint:public ai_domain_baset const namespacet &ns); exprt evaluate_casts_in_constants( - exprt expr, - const typet& parent_type, + exprt expr, + const typet& parent_type, bool &valid) const; }; @@ -82,7 +82,7 @@ class const_propagator_ait:public ait const namespacet &ns) { operator()(goto_function, ns); -// output(ns,goto_function.body,"",std::cout); +// output(ns, goto_function.body, "", std::cout); replace(goto_function, ns); } @@ -94,7 +94,7 @@ void replace( const namespacet &ns); void replace_types_rec( - const replace_symbolt &replace_const, + const replace_symbolt &replace_const, exprt &expr); }; diff --git a/src/ssa/local_ssa.cpp b/src/ssa/local_ssa.cpp index 254ef3920..84da5f932 100644 --- a/src/ssa/local_ssa.cpp +++ b/src/ssa/local_ssa.cpp @@ -85,6 +85,8 @@ Function: local_SSAt::get_entry_exit_vars void local_SSAt::get_entry_exit_vars() { + goto_programt::const_targett first=goto_function.body.instructions.begin(); + // get parameters const code_typet::parameterst ¶meter_types= goto_function.type.parameters(); @@ -102,7 +104,7 @@ void local_SSAt::get_entry_exit_vars() { exprt param=read_rhs(symbol->symbol_expr(), first); #if 0 - std::cout << "param: " + std::cout << "param: " << from_expr(ns, "", param) << std::endl; #endif forall_operands(it, param) @@ -113,7 +115,6 @@ void local_SSAt::get_entry_exit_vars() } // get globals in - goto_programt::const_targett first=goto_function.body.instructions.begin(); get_globals(first, globals_in, true, false); // filters out #return_value // get globals out (includes return value) @@ -121,7 +122,7 @@ void local_SSAt::get_entry_exit_vars() last=goto_function.body.instructions.end(); last--; get_globals(last, globals_out, true, true, last->function); - //get nondeterministic variables + // get nondeterministic variables get_nondet_vars(); } @@ -148,7 +149,7 @@ void local_SSAt::get_nondet_vars(const exprt &expr) void local_SSAt::get_nondet_vars() { - for(nodest::iterator n_it=nodes.begin(); + for(nodest::iterator n_it=nodes.begin(); n_it!=nodes.end(); n_it++) { for(nodet::equalitiest::const_iterator @@ -202,8 +203,8 @@ void local_SSAt::get_globals( << std::endl; #endif bool is_return=id2string(it->get_identifier()).find( - "#return_value")!=std::string::npos; - if(!with_returns && is_return) + "#return_value")!=std::string::npos; + if(!with_returns && is_return) continue; // filter out return values of other functions @@ -215,10 +216,10 @@ void local_SSAt::get_globals( if(rhs_value) { - //workaround for the problem that + // workaround for the problem that // rhs() for a return value is always the "input" return value - const exprt &expr=is_return ? - read_lhs(it->get_expr(),--loc) : read_rhs(it->get_expr(),loc); + const exprt &expr=is_return ? + read_lhs(it->get_expr(), --loc) : read_rhs(it->get_expr(), loc); globals.insert(to_symbol_expr(expr)); } else @@ -628,20 +629,20 @@ void local_SSAt::build_function_call(locationt loc) { symbol_exprt arg( id2string(fname)+"#"+i2string(loc->location_number)+ - "#arg"+i2string(i),it->type()); + "#arg"+i2string(i), it->type()); const typet &argtype=ns.follow(it->type()); if(argtype.id()==ID_struct) { - exprt lhs = read_rhs(arg, loc); - for(size_t j=0; jequalities.push_back( + n_it->equalities.push_back( equal_exprt(lhs.operands()[j], it->operands()[j])); } } else { - n_it->equalities.push_back(equal_exprt(arg,*it)); + n_it->equalities.push_back(equal_exprt(arg, *it)); } *it=arg; } @@ -1569,7 +1570,7 @@ void local_SSAt::nodet::output( std::ostream &out, const namespacet &ns) const { - if(!enabling_expr.is_true()) + if(!enabling_expr.is_true()) out << "(enable) " << from_expr(ns, "", enabling_expr) << "\n"; #if 0 if(!marked) @@ -1660,6 +1661,52 @@ Function: local_SSAt::operator << \*******************************************************************/ +std::vector &operator<<( + std::vector &dest, + const local_SSAt &src) +{ + for(local_SSAt::nodest::const_iterator n_it=src.nodes.begin(); + n_it!=src.nodes.end(); n_it++) + { + if(n_it->marked) + continue; + for(local_SSAt::nodet::equalitiest::const_iterator + e_it=n_it->equalities.begin(); + e_it!=n_it->equalities.end(); + e_it++) + { + if(!n_it->enabling_expr.is_true()) + dest.push_back(implies_exprt(n_it->enabling_expr, *e_it)); + else + dest.push_back(*e_it); + } + + for(local_SSAt::nodet::constraintst::const_iterator + c_it=n_it->constraints.begin(); + c_it!=n_it->constraints.end(); + c_it++) + { + if(!n_it->enabling_expr.is_true()) + dest.push_back(implies_exprt(n_it->enabling_expr, *c_it)); + else + dest.push_back(*c_it); + } + } + return dest; +} + +/*******************************************************************\ + +Function: local_SSAt::operator << + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + std::list &operator<<( std::list &dest, const local_SSAt &src) @@ -1674,8 +1721,8 @@ std::list &operator<<( e_it!=n_it->equalities.end(); e_it++) { - if(!n_it->enabling_expr.is_true()) - dest.push_back(implies_exprt(n_it->enabling_expr,*e_it)); + if(!n_it->enabling_expr.is_true()) + dest.push_back(implies_exprt(n_it->enabling_expr, *e_it)); else dest.push_back(*e_it); } @@ -1685,8 +1732,8 @@ std::list &operator<<( c_it!=n_it->constraints.end(); c_it++) { - if(!n_it->enabling_expr.is_true()) - dest.push_back(implies_exprt(n_it->enabling_expr,*c_it)); + if(!n_it->enabling_expr.is_true()) + dest.push_back(implies_exprt(n_it->enabling_expr, *c_it)); else dest.push_back(*c_it); } @@ -1720,10 +1767,24 @@ decision_proceduret &operator<<( e_it!=n_it->equalities.end(); e_it++) { - if(!n_it->enabling_expr.is_true()) - dest.push_back(implies_exprt(n_it->enabling_expr,*e_it)); + if(!n_it->enabling_expr.is_true()) + dest << implies_exprt(n_it->enabling_expr, *e_it); else - dest.push_back(*e_it); + dest << *e_it; + +#if 0 + // freeze cond variables + if(e_it->op0().id()==ID_symbol && + e_it->op0().type().id()==ID_bool) + { + const symbol_exprt &symbol=to_symbol_expr(e_it->op0()); + if(id2string(symbol.get_identifier()).find("ssa::$cond")!= + std::string::npos) + { + dest.solver->set_frozen(dest.solver->convert(symbol)); + } + } +#endif } for(local_SSAt::nodet::constraintst::const_iterator @@ -1731,10 +1792,10 @@ decision_proceduret &operator<<( c_it!=n_it->constraints.end(); c_it++) { - if(!n_it->enabling_expr.is_true()) - dest.push_back(implies_exprt(n_it->enabling_expr,*c_it)); + if(!n_it->enabling_expr.is_true()) + dest << implies_exprt(n_it->enabling_expr, *c_it); else - dest.push_back(*c_it); + dest << *c_it; } } return dest; @@ -1816,10 +1877,10 @@ exprt local_SSAt::get_enabling_exprs() const { exprt::operandst result; result.reserve(enabling_exprs.size()); - for(std::list::const_iterator it=enabling_exprs.begin(); + for(std::vector::const_iterator it=enabling_exprs.begin(); it!=enabling_exprs.end(); ++it) { - std::list::const_iterator lh=it; ++lh; + std::vector::const_iterator lh=it; ++lh; if(lh!=enabling_exprs.end()) result.push_back(not_exprt(*it)); else diff --git a/src/ssa/local_ssa.h b/src/ssa/local_ssa.h index adbc2862f..7e70a5e97 100644 --- a/src/ssa/local_ssa.h +++ b/src/ssa/local_ssa.h @@ -13,7 +13,8 @@ Author: Daniel Kroening, kroening@kroening.com #include -#include "../domains/incremental_solver.h" +#include + #include "ssa_domain.h" #include "guard_map.h" #include "ssa_object.h" @@ -58,10 +59,10 @@ class local_SSAt inline nodet( locationt _location, std::list::iterator _loophead): + function_calls_inlined(false), enabling_expr(true_exprt()), marked(false), - function_calls_inlined(false), - location(_location), + location(_location), loophead(_loophead) { } @@ -111,13 +112,13 @@ class local_SSAt void mark_nodes() { - for(auto &n : nodes) - marked=true; + for(auto &n : nodes) + n.marked=true; } void unmark_nodes() { - for(auto &n : nodes) - marked=false; + for(auto &n : nodes) + n.marked=false; } // for incremental unwinding @@ -129,7 +130,7 @@ class local_SSAt typedef std::set var_sett; var_listt params; var_sett globals_in, globals_out; - std::set nondets; + std::set nondets; bool has_function_calls() const; @@ -204,7 +205,7 @@ class local_SSAt return it->second; } locationt find_location_by_number(unsigned location_number) const; - + protected: typedef std::map location_mapt; location_mapt location_map; @@ -219,7 +220,7 @@ class local_SSAt void build_function_call(locationt loc); void build_assertions(locationt loc); void build_assumptions(locationt loc); - + // custom templates void collect_custom_templates(); replace_mapt template_newvars; diff --git a/src/ssa/replace_symbol_ext.cpp b/src/ssa/replace_symbol_ext.cpp index 7d77633aa..d978d2f99 100644 --- a/src/ssa/replace_symbol_ext.cpp +++ b/src/ssa/replace_symbol_ext.cpp @@ -32,7 +32,7 @@ bool replace_symbol_extt::replace(exprt &dest) const if(have_to_replace(dest.type())) if(!replace_symbolt::replace(dest.type())) result=false; - + // now do expression itself if(!have_to_replace(dest)) @@ -40,14 +40,14 @@ bool replace_symbol_extt::replace(exprt &dest) const if(dest.id()==ID_address_of) { - const exprt &object = to_address_of_expr(dest).object(); + const exprt &object=to_address_of_expr(dest).object(); if(object.id()==ID_symbol) { expr_mapt::const_iterator it= expr_map.find(object.get(ID_identifier)); if(it!=expr_map.end()) - return false; + return false; } } else if(dest.id()==ID_symbol) diff --git a/src/ssa/ssa_const_propagator.cpp b/src/ssa/ssa_const_propagator.cpp index 4ca296238..1c16c1da3 100644 --- a/src/ssa/ssa_const_propagator.cpp +++ b/src/ssa/ssa_const_propagator.cpp @@ -6,7 +6,7 @@ Author: Kumar Madhukar, Peter Schrammel \*******************************************************************/ -//#define DEBUG +// #define DEBUG #ifdef DEBUG #include @@ -20,7 +20,7 @@ Author: Kumar Madhukar, Peter Schrammel #include "ssa_const_propagator.h" -//bool iterate = true; +// bool iterate=true; /*******************************************************************\ @@ -36,168 +36,168 @@ Function: ssa_const_propagatort::operator() \*******************************************************************/ void ssa_const_propagatort::operator()(std::list &dest, - const local_SSAt &src) + const local_SSAt &src) { - values.iterate = true; + values.iterate=true; while(values.iterate){ - values.iterate = false; - for(local_SSAt::nodest::const_iterator n_it = src.nodes.begin(); - n_it != src.nodes.end(); n_it++) + values.iterate=false; + for(local_SSAt::nodest::const_iterator n_it=src.nodes.begin(); + n_it!=src.nodes.end(); n_it++) { - const local_SSAt::nodet &node=*n_it; - - // check if node is active; 'continue' if not active - if(!node.enabling_expr.is_true()) - continue; - - // if src.enabling_exprs does not have a true in the end, then also continue - if(src.enabling_exprs.size() > 0) - if((src.enabling_exprs.back()).is_true()) - continue; - - for(local_SSAt::nodet::equalitiest::const_iterator e_it=node.equalities.begin(); - e_it!=node.equalities.end(); e_it++) - { - equal_exprt e = to_equal_expr(*e_it); - const exprt &lhs = e.lhs(); - exprt &temprhs = e.rhs(); - - // resolving conditional expressions - while(temprhs.id() == ID_if){ - exprt simp_guard; + const local_SSAt::nodet &node=*n_it; + + // check if node is active; 'continue' if not active + if(!node.enabling_expr.is_true()) + continue; + + // if src.enabling_exprs does not have a true in the end, then also continue + if(src.enabling_exprs.size() > 0) + if((src.enabling_exprs.back()).is_true()) + continue; + + for(local_SSAt::nodet::equalitiest::const_iterator e_it=node.equalities.begin(); + e_it!=node.equalities.end(); e_it++) + { + equal_exprt e=to_equal_expr(*e_it); + const exprt &lhs=e.lhs(); + exprt &temprhs=e.rhs(); + + // resolving conditional expressions + while(temprhs.id()==ID_if){ + exprt simp_guard; #ifdef DEBUG - std::cout << "guard: " << from_expr(src.ns, "", temprhs.op0()) << std::endl; + std::cout << "guard: " << from_expr(src.ns, "", temprhs.op0()) << std::endl; #endif - simp_guard = simplify_expr(temprhs.op0(), src.ns); + simp_guard=simplify_expr(temprhs.op0(), src.ns); #ifdef DEBUG - std::cout << "simplified: " << from_expr(src.ns, "", simp_guard) << std::endl; + std::cout << "simplified: " << from_expr(src.ns, "", simp_guard) << std::endl; #endif - if(simp_guard.is_true()) - temprhs = temprhs.op1(); - else if(simp_guard.is_false()) - temprhs = temprhs.op2(); - else - break; - } - - const exprt &rhs = temprhs; - valuest copy_values = values; - - if(!copy_values.maps_to_top(rhs)) - assign(copy_values,lhs,rhs,src.ns); - else - copy_values.set_to_top(lhs); - + if(simp_guard.is_true()) + temprhs=temprhs.op1(); + else if(simp_guard.is_false()) + temprhs=temprhs.op2(); + else + break; + } + + const exprt &rhs=temprhs; + valuest copy_values=values; + + if(!copy_values.maps_to_top(rhs)) + assign(copy_values, lhs, rhs, src.ns); + else + copy_values.set_to_top(lhs); + #ifdef DEBUG - copy_values.output(std::cout,src.ns); + copy_values.output(std::cout, src.ns); #endif - - if(rhs.id() == ID_symbol){ - if(!values.maps_to_top(lhs)) - assign(values,rhs,lhs,src.ns); - else - values.set_to_top(rhs); - } - + + if(rhs.id()==ID_symbol){ + if(!values.maps_to_top(lhs)) + assign(values, rhs, lhs, src.ns); + else + values.set_to_top(rhs); + } + #ifdef DEBUG - values.output(std::cout,src.ns); + values.output(std::cout, src.ns); #endif - - values.merge(copy_values); - + + values.merge(copy_values); + #ifdef DEBUG - values.output(std::cout,src.ns); + values.output(std::cout, src.ns); #endif - } - - for(local_SSAt::nodet::constraintst::const_iterator c_it=n_it->constraints.begin(); - c_it!=n_it->constraints.end(); c_it++) - { - if(c_it->id()!=ID_equal) - continue; - - const equal_exprt e = to_equal_expr(*c_it); - const exprt &lhs = e.lhs(); - const exprt &rhs = e.rhs(); - - // if lhs is a variable and rhs is a constant expression - - valuest copy_values = values; + } + + for(local_SSAt::nodet::constraintst::const_iterator c_it=n_it->constraints.begin(); + c_it!=n_it->constraints.end(); c_it++) + { + if(c_it->id()!=ID_equal) + continue; + + const equal_exprt e=to_equal_expr(*c_it); + const exprt &lhs=e.lhs(); + const exprt &rhs=e.rhs(); + + // if lhs is a variable and rhs is a constant expression + + valuest copy_values=values; if(!copy_values.maps_to_top(rhs)) - assign(copy_values,lhs,rhs,src.ns); + assign(copy_values, lhs, rhs, src.ns); else copy_values.set_to_top(lhs); #ifdef DEBUG - copy_values.output(std::cout,src.ns); + copy_values.output(std::cout, src.ns); #endif - - // if rhs is a variable and lhs is a constant expression - - if(!values.maps_to_top(lhs)) - assign(values,rhs,lhs,src.ns); - else - values.set_to_top(rhs); - + + // if rhs is a variable and lhs is a constant expression + + if(!values.maps_to_top(lhs)) + assign(values, rhs, lhs, src.ns); + else + values.set_to_top(rhs); + #ifdef DEBUG - values.output(std::cout,src.ns); + values.output(std::cout, src.ns); #endif values.merge(copy_values); #ifdef DEBUG - values.output(std::cout,src.ns); + values.output(std::cout, src.ns); #endif - - } + + } } } - + #ifdef DEBUG - values.output(std::cout,src.ns); + values.output(std::cout, src.ns); #endif - + // iterate over values and get all equalities for(replace_symbolt::expr_mapt::const_iterator it=values.replace_const.expr_map.begin(); it!=values.replace_const.expr_map.end(); ++it){ - - //std::cout << ' ' << it->first << " = " << + + // std::cout << ' ' << it->first << "=" << // from_expr(src.ns, "", it->second) << std::endl; - dest.push_back(equal_exprt(symbol_exprt(it->first,it->second.type()),it->second)); - + dest.push_back(equal_exprt(symbol_exprt(it->first, it->second.type()), it->second)); + } } bool ssa_const_propagatort::valuest::maps_to_top(const exprt &expr) const { find_symbols_sett symbols; - find_symbols(expr,symbols); - for(find_symbols_sett::const_iterator it = symbols.begin(); - it != symbols.end(); ++it) + find_symbols(expr, symbols); + for(find_symbols_sett::const_iterator it=symbols.begin(); + it!=symbols.end(); ++it) { if(replace_const.expr_map.find(*it) - == replace_const.expr_map.end()) - return true; +==replace_const.expr_map.end()) + return true; } return false; } void ssa_const_propagatort::assign( - valuest &dest, - const exprt &lhs, - exprt rhs, - const namespacet &ns) const + valuest &dest, + const exprt &lhs, + exprt rhs, + const namespacet &ns) const { #ifdef DEBUG std::cout << "assign: " << from_expr(ns, "", lhs) << " := " << from_expr(ns, "", rhs) << std::endl; #endif - + values.replace_const(rhs); #ifdef DEBUG @@ -205,30 +205,30 @@ void ssa_const_propagatort::assign( << " := " << from_expr(ns, "", rhs) << std::endl; #endif - rhs = simplify_expr(rhs,ns); + rhs=simplify_expr(rhs, ns); #ifdef DEBUG std::cout << "simplified: " << from_expr(ns, "", lhs) << " := " << from_expr(ns, "", rhs) << std::endl; #endif - dest.set_to(lhs,rhs); + dest.set_to(lhs, rhs); } bool ssa_const_propagatort::valuest::set_to_top(const irep_idt &id) { - bool result = false; - replace_symbolt::expr_mapt::iterator r_it = + bool result=false; + replace_symbolt::expr_mapt::iterator r_it= replace_const.expr_map.find(id); - if(r_it != replace_const.expr_map.end()) + if(r_it!=replace_const.expr_map.end()) { replace_const.expr_map.erase(r_it); - result = true; + result=true; } if(top_ids.find(id)==top_ids.end()) { top_ids.insert(id); - result = true; + result=true; } return result; } @@ -239,27 +239,27 @@ bool ssa_const_propagatort::valuest::set_to_top(const exprt &expr) } void ssa_const_propagatort::valuest::set_to(const irep_idt &lhs_id, - const exprt &rhs_val) + const exprt &rhs_val) { - - if(replace_const.expr_map[lhs_id] != rhs_val){ - replace_const.expr_map[lhs_id] = rhs_val; - iterate = true; + + if(replace_const.expr_map[lhs_id]!=rhs_val){ + replace_const.expr_map[lhs_id]=rhs_val; + iterate=true; } - std::set::iterator it = top_ids.find(lhs_id); + std::set::iterator it=top_ids.find(lhs_id); if(it!=top_ids.end()) top_ids.erase(it); } void ssa_const_propagatort::valuest::set_to(const exprt &lhs, - const exprt &rhs_val) + const exprt &rhs_val) { - const irep_idt &lhs_id = to_symbol_expr(lhs).get_identifier(); - set_to(lhs_id,rhs_val); + const irep_idt &lhs_id=to_symbol_expr(lhs).get_identifier(); + set_to(lhs_id, rhs_val); } void ssa_const_propagatort::valuest::output( - std::ostream &out, - const namespacet &ns) const + std::ostream &out, + const namespacet &ns) const { out << "const map: " << std::endl; for(replace_symbolt::expr_mapt::const_iterator @@ -278,26 +278,26 @@ void ssa_const_propagatort::valuest::output( bool ssa_const_propagatort::valuest::merge(const valuest &src) { - bool changed = false; + bool changed=false; for(replace_symbolt::expr_mapt::const_iterator it=src.replace_const.expr_map.begin(); it!=src.replace_const.expr_map.end(); ++it) { replace_symbolt::expr_mapt::iterator - c_it = replace_const.expr_map.find(it->first); - if(c_it != replace_const.expr_map.end()) - { - if(c_it->second != it->second) - { - set_to_top(it->first); - changed = true; - } - } + c_it=replace_const.expr_map.find(it->first); + if(c_it!=replace_const.expr_map.end()) + { + if(c_it->second!=it->second) + { + set_to_top(it->first); + changed=true; + } + } else if(top_ids.find(it->first)==top_ids.end()) - { - set_to(it->first,it->second); - changed = true; - } + { + set_to(it->first, it->second); + changed=true; + } } return changed; diff --git a/src/ssa/ssa_const_propagator.h b/src/ssa/ssa_const_propagator.h index ee89071db..5620ce57b 100644 --- a/src/ssa/ssa_const_propagator.h +++ b/src/ssa/ssa_const_propagator.h @@ -19,7 +19,7 @@ class ssa_const_propagatort : public messaget public: void operator()(std::list &dest, - const local_SSAt &src); + const local_SSAt &src); struct valuest { @@ -53,7 +53,7 @@ class ssa_const_propagatort : public messaget bool maps_to_top(const exprt &expr) const; bool set_to_top(const exprt &expr); bool set_to_top(const irep_idt &id); - + bool iterate; }; @@ -63,18 +63,18 @@ class ssa_const_propagatort : public messaget protected: void assign( - valuest &dest, - const exprt &lhs, - exprt rhs, - const namespacet &ns) const; + valuest &dest, + const exprt &lhs, + exprt rhs, + const namespacet &ns) const; exprt evaluate_casts_in_constants( - exprt expr, - const typet& parent_type, - bool &valid) const; - - - + exprt expr, + const typet& parent_type, + bool &valid) const; + + + }; #endif diff --git a/src/ssa/ssa_db.cpp b/src/ssa/ssa_db.cpp index fbbb80ef3..3eae31ea4 100644 --- a/src/ssa/ssa_db.cpp +++ b/src/ssa/ssa_db.cpp @@ -8,11 +8,11 @@ Author: Peter Schrammel #include "ssa_db.h" -//void ssa_dbt::depgraph_create(const function_namet &function_name, const namespacet &ns, ssa_inlinert &ssa_inliner) +// void ssa_dbt::depgraph_create(const function_namet &function_name, const namespacet &ns, ssa_inlinert &ssa_inliner) void ssa_dbt::depgraph_create(const function_namet &function_name, const namespacet &ns, ssa_inlinert &ssa_inliner, bool entry) { - depgraph_store[function_name] = new ssa_dependency_grapht(*this,ns); - const local_SSAt &SSA=this->get(function_name); + depgraph_store[function_name]=new ssa_dependency_grapht(*this, ns); + const local_SSAt &SSA=this->get(function_name); depgraph_store[function_name]->create(SSA, ssa_inliner, entry); } diff --git a/src/ssa/ssa_db.h b/src/ssa/ssa_db.h index c7c92ed91..c3c332074 100644 --- a/src/ssa/ssa_db.h +++ b/src/ssa/ssa_db.h @@ -12,14 +12,19 @@ Author: Peter Schrammel #include #include +#include #include #include +class ssa_inlinert; +class ssa_dependency_grapht; + class ssa_dbt { public: typedef irep_idt function_namet; typedef std::map functionst; + typedef std::map depgrapht; typedef std::map solverst; explicit ssa_dbt(const optionst &_options): @@ -33,14 +38,22 @@ class ssa_dbt delete item.second; for(auto &item : the_solvers) delete item.second; + for(auto &item : depgraph_store) + delete item.second; } - inline local_SSAt &get(const function_namet &function_name) const + local_SSAt &get(const function_namet &function_name) const { return *store.at(function_name); } - inline incremental_solvert &get_solver(const function_namet &function_name) + ssa_dependency_grapht &get_depgraph( + const function_namet &function_name) const + { + return *depgraph_store.at(function_name); + } + + incremental_solvert &get_solver(const function_namet &function_name) { solverst::iterator it=the_solvers.find(function_name); if(it!=the_solvers.end()) @@ -53,15 +66,15 @@ class ssa_dbt return *the_solvers.at(function_name); } - inline functionst &functions() { return store; } - inline solverst &solvers() { return the_solvers; } + functionst &functions() { return store; } + solverst &solvers() { return the_solvers; } - inline bool exists(const function_namet &function_name) const + bool exists(const function_namet &function_name) const { return store.find(function_name)!=store.end(); } - inline void create( + void create( const function_namet &function_name, const goto_functionst::goto_functiont &goto_function, const namespacet &ns) @@ -69,9 +82,22 @@ class ssa_dbt store[function_name]=new unwindable_local_SSAt(goto_function, ns); } + void depgraph_create( + const function_namet &function_name, + const namespacet &ns, + ssa_inlinert &ssa_inliner, + bool entry) + { + depgraph_store[function_name]=new ssa_dependency_grapht(*this, ns); + const local_SSAt &SSA=this->get(function_name); + depgraph_store[function_name]->create(SSA, ssa_inliner, entry); + } + + protected: const optionst &options; functionst store; + depgrapht depgraph_store; solverst the_solvers; }; diff --git a/src/ssa/ssa_dependency_graph.cpp b/src/ssa/ssa_dependency_graph.cpp index 651563082..f419fbac7 100644 --- a/src/ssa/ssa_dependency_graph.cpp +++ b/src/ssa/ssa_dependency_graph.cpp @@ -1,81 +1,90 @@ +/*******************************************************************\ + +Module: SSA Dependency Graph + +Author: Madhukar Kumar + +\*******************************************************************/ #include #include #include +#include + #include "ssa_dependency_graph.h" void ssa_dependency_grapht::output(std::ostream &out) const { - for(unsigned index = 0; index < depnodes_map.size(); index++) - { - out << "Node#" << index << "; info: " << from_expr(ns, "", depnodes_map[index].node_info) << "\n"; - out << "Node#" << index << "; -> Used Symbols: "; - for(find_symbols_sett::const_iterator u_it=depnodes_map[index].used_symbols.begin(); - u_it!=depnodes_map[index].used_symbols.end(); u_it++){ - out << *u_it << " "; - } - out << "\n"; + for(unsigned index=0; index Used Symbols: "; + for(find_symbols_sett::const_iterator u_it=depnodes_map[index].used_symbols.begin(); + u_it!=depnodes_map[index].used_symbols.end(); u_it++){ + out << *u_it << " "; + } + out << "\n"; - out << "Node#" << index << "; -> Modified Symbols: "; - for(find_symbols_sett::const_iterator m_it=depnodes_map[index].modified_symbols.begin(); - m_it!=depnodes_map[index].modified_symbols.end(); m_it++){ - out << *m_it << " "; - } - out << "\n"; + out << "Node#" << index << "; -> Modified Symbols: "; + for(find_symbols_sett::const_iterator m_it=depnodes_map[index].modified_symbols.begin(); + m_it!=depnodes_map[index].modified_symbols.end(); m_it++){ + out << *m_it << " "; + } + out << "\n"; - out << "Successors: "; - for(unsigned i = 0; i < depnodes_map[index].successors.size(); i++){ - out << depnodes_map[index].successors[i] << " "; - } - out << "\n"; - - out << "Predecessors:\n"; - for(ssa_dependency_grapht::annotated_predecessorst::const_iterator p_it = depnodes_map[index].predecessors.begin(); - p_it != depnodes_map[index].predecessors.end(); p_it++){ - annotated_predecessort pred = *p_it; - int pred_index = pred.predecessor_node_index; - find_symbols_sett pred_annotation = pred.annotation; - out << " " << "Predecessor Node#" << pred_index << "; Annotation: "; - for(find_symbols_sett::const_iterator s_it=pred_annotation.begin(); - s_it!=pred_annotation.end(); s_it++){ out << *s_it << " "; } - out << "\n"; } out << "\n"; + out << "Successors: "; + for(unsigned i=0; ilocation; + + // loop-head select + // TODO: this is an ugly hack (this can be changed as soon as unwindable_local_SSA provides smooth renaming with odometers) + // if(n_it->loophead!=SSA.nodes.end()) + if(e_it->op1().id()==ID_if && + e_it->op1().op0().id()==ID_symbol) { + std::string var_string=id2string(e_it->op1().op0().get(ID_identifier)); + if(((var_string.substr(0, 14))=="ssa::$guard#ls")) + { + temp_node.is_loop=true; +/* symbol_exprt lsguard=SSA.name(SSA.guard_symbol(), + local_SSAt::LOOP_SELECT, n_it->location); + ssa_local_unwinder.unwinder_rename(lsguard, *n_it, true);*/ + temp_node.guard=not_exprt(e_it->op1().op0()); + } + } + // temp_node.trivial_guard=true; - find_symbols(*e_it,all_ssa_symbols); - - depnodet temp_node; - temp_node.is_assertion = false; - temp_node.is_function_call = false; - temp_node.is_loop = false; - temp_node.node_info = *e_it; - temp_node.location = n_it->location; - - //loop-head select - //TODO: this is an ugly hack (this can be changed as soon as unwindable_local_SSA provides smooth renaming with odometers) - //if(n_it->loophead!=SSA.nodes.end()) - if(e_it->op1().id()==ID_if && - e_it->op1().op0().id()==ID_symbol) - { - std::string var_string = id2string(e_it->op1().op0().get(ID_identifier)); - if(((var_string.substr(0,14)) == "ssa::$guard#ls")) - { - temp_node.is_loop = true; -/* symbol_exprt lsguard = SSA.name(SSA.guard_symbol(), - local_SSAt::LOOP_SELECT, n_it->location); - ssa_local_unwinder.unwinder_rename(lsguard,*n_it,true);*/ - temp_node.guard = not_exprt(e_it->op1().op0()); - } - } - //temp_node.trivial_guard = true; - - equal_exprt e = to_equal_expr(*e_it); - exprt &lhs = e.lhs(); exprt &rhs = e.rhs(); - - find_symbols(rhs,temp_node.used_symbols); - find_symbols(lhs,temp_node.modified_symbols); - - if(!ignore_equality_done){ - std::string var_string = id2string(to_symbol_expr(lhs).get_identifier()); - if(((var_string.substr(0,11)) == "ssa::$guard") && (rhs.is_true())){ - ignore_equality = true; - ignore_equality_done = true; - } - } - - if(first_node && ignore_equality){ - if(entry){ - depnodes_map.push_back(temp_node); - //std::cout << "created equality node, with info: " << from_expr(ns, "", *e_it) << "\n"; - } - ignore_equality = false; - } - else{ - depnodes_map.push_back(temp_node); - //std::cout << "created equality node, with info: " << from_expr(ns, "", *e_it) << "\n"; - } - + equal_exprt e=to_equal_expr(*e_it); + exprt &lhs=e.lhs(); exprt &rhs=e.rhs(); + + find_symbols(rhs, temp_node.used_symbols); + find_symbols(lhs, temp_node.modified_symbols); + + if(!ignore_equality_done){ + std::string var_string=id2string(to_symbol_expr(lhs).get_identifier()); + if(((var_string.substr(0, 11))=="ssa::$guard") && (rhs.is_true())){ + ignore_equality=true; + ignore_equality_done=true; + } } + if(first_node && ignore_equality){ + if(entry){ + depnodes_map.push_back(temp_node); + // std::cout << "created equality node, with info: " << from_expr(ns, "", *e_it) << "\n"; + } + ignore_equality=false; + } + else{ + depnodes_map.push_back(temp_node); + // std::cout << "created equality node, with info: " << from_expr(ns, "", *e_it) << "\n"; + } + + } + // collecting symbols from constraints and populating dependency graph nodes for(local_SSAt::nodet::constraintst::const_iterator c_it=node.constraints.begin(); - c_it!=node.constraints.end(); c_it++) - { - find_symbols(*c_it,all_ssa_symbols); - - depnodet temp_node; - temp_node.is_assertion = false; - temp_node.is_function_call = false; - temp_node.is_loop = false; - temp_node.node_info = *c_it; - temp_node.location = n_it->location; - find_symbols(*c_it,temp_node.used_symbols); - find_symbols(*c_it,temp_node.modified_symbols); - depnodes_map.push_back(temp_node); - //std::cout << "created constraint node, with info: " << from_expr(ns, "", *c_it) << "\n"; - } - + c_it!=node.constraints.end(); c_it++) + { + find_symbols(*c_it, all_ssa_symbols); + + depnodet temp_node; + temp_node.is_assertion=false; + temp_node.is_function_call=false; + temp_node.is_loop=false; + temp_node.node_info=*c_it; + temp_node.location=n_it->location; + find_symbols(*c_it, temp_node.used_symbols); + find_symbols(*c_it, temp_node.modified_symbols); + depnodes_map.push_back(temp_node); + // std::cout << "created constraint node, with info: " << from_expr(ns, "", *c_it) << "\n"; + } + // collecting symbols from assertionst and populating dependency graph nodes for(local_SSAt::nodet::assertionst::const_iterator a_it=node.assertions.begin(); - a_it!=node.assertions.end(); a_it++) - { - find_symbols(*a_it,all_ssa_symbols); - - depnodet temp_node; - temp_node.is_assertion = true; - temp_node.is_function_call = false; - temp_node.is_loop = false; - temp_node.node_info = *a_it; - temp_node.location = n_it->location; - find_symbols(*a_it,temp_node.used_symbols); - depnodes_map.push_back(temp_node); - //std::cout << "created assertion node, with info: " << from_expr(ns, "", *a_it) << "\n"; - } + a_it!=node.assertions.end(); a_it++) + { + find_symbols(*a_it, all_ssa_symbols); + + depnodet temp_node; + temp_node.is_assertion=true; + temp_node.is_function_call=false; + temp_node.is_loop=false; + temp_node.node_info=*a_it; + temp_node.location=n_it->location; + find_symbols(*a_it, temp_node.used_symbols); + depnodes_map.push_back(temp_node); + // std::cout << "created assertion node, with info: " << from_expr(ns, "", *a_it) << "\n"; + } /* // collecting symbols from assumptionst and populating dependency graph nodes for(local_SSAt::nodet::assumptionst::const_iterator a_it=node.assumptions.begin(); - a_it!=node.assumptions.end(); a_it++) - { - find_symbols(*a_it,all_ssa_symbols); - - depnodet temp_node; - temp_node.is_assertion = false; - temp_node.is_function_call = false; - temp_node.node_info = *a_it; - find_symbols(*a_it,temp_node.used_symbols); - find_symbols(*a_it,temp_node.modified_symbols); - depnodes_map.push_back(temp_node); - //std::cout << "created assumption node, with info: " << from_expr(ns, "", *a_it) << "\n"; - } + a_it!=node.assumptions.end(); a_it++) + { + find_symbols(*a_it, all_ssa_symbols); + + depnodet temp_node; + temp_node.is_assertion=false; + temp_node.is_function_call=false; + temp_node.node_info=*a_it; + find_symbols(*a_it, temp_node.used_symbols); + find_symbols(*a_it, temp_node.modified_symbols); + depnodes_map.push_back(temp_node); + // std::cout << "created assumption node, with info: " << from_expr(ns, "", *a_it) << "\n"; + } */ // collecting symbols from function_callst and populating dependency graph nodes for(local_SSAt::nodet::function_callst::const_iterator f_it=node.function_calls.begin(); - f_it!=node.function_calls.end(); f_it++) + f_it!=node.function_calls.end(); f_it++) + { + // find_symbols(*f_it, all_ssa_symbols); + + irep_idt fname=to_symbol_expr(f_it->function()).get_identifier(); + if(ssa_db.exists(fname)) { - //find_symbols(*f_it,all_ssa_symbols); - - irep_idt fname = to_symbol_expr(f_it->function()).get_identifier(); - if(ssa_db.exists(fname)) - { - const local_SSAt &fSSA = ssa_db.get(fname); - - /******************************************************************/ - /******* additional nodes needed to fix the dependency tree *******/ - - exprt guard_binding; - exprt::operandst bindings_in, bindings_out; - int counter = ssa_inliner.get_rename_counter(); - - /**/ - ssa_inliner.get_guard_binding(SSA,fSSA,n_it,guard_binding,counter); - //std::cout << "guard binding: " << from_expr(ns, "", guard_binding) << "\n"; - /* - { - depnodet temp_node; - temp_node.is_assertion = false; - temp_node.is_function_call = false; - temp_node.node_info = guard_binding; - - equal_exprt e = to_equal_expr(guard_binding); - exprt &lhs = e.lhs(); exprt &rhs = e.rhs(); - - find_symbols(rhs,temp_node.used_symbols); - find_symbols(lhs,temp_node.modified_symbols); - depnodes_map.push_back(temp_node); - //std::cout << "created guard binding node, with info: " << from_expr(ns, "", guard_binding) << "\n"; - } - */ - /**/ - - ssa_inliner.get_bindings(SSA,fSSA,n_it,f_it,bindings_in,bindings_out,counter); - - for(exprt::operandst::const_iterator b_it=bindings_in.begin(); - b_it!=bindings_in.end(); b_it++){ - - //std::cout << "binding: " << from_expr(ns, "", *b_it) << "\n"; - - depnodet temp_node; - temp_node.is_assertion = false; - temp_node.is_function_call = false; - temp_node.is_loop = false; - temp_node.node_info = *b_it; - temp_node.location = n_it->location; - - equal_exprt e = to_equal_expr(*b_it); - exprt &lhs = e.lhs(); exprt &rhs = e.rhs(); - - find_symbols(rhs,temp_node.used_symbols); - find_symbols(lhs,temp_node.modified_symbols); - depnodes_map.push_back(temp_node); - //std::cout << "created binding in node, with info: " << from_expr(ns, "", *b_it) << "\n"; - } - - for(exprt::operandst::const_iterator b_it=bindings_out.begin(); - b_it!=bindings_out.end(); b_it++){ - - //std::cout << "binding: " << from_expr(ns, "", *b_it) << "\n"; - - depnodet temp_node; - temp_node.is_assertion = false; - temp_node.is_function_call = false; - temp_node.is_loop = false; - temp_node.node_info = *b_it; - temp_node.location = n_it->location; - - equal_exprt e = to_equal_expr(*b_it); - exprt &lhs = e.lhs(); exprt &rhs = e.rhs(); - - find_symbols(rhs,temp_node.used_symbols); - find_symbols(lhs,temp_node.modified_symbols); - depnodes_map.push_back(temp_node); - //std::cout << "created binding out node, with info: " << from_expr(ns, "", *b_it) << "\n"; - } - - /******************************************************************/ - - depnodet temp_node; - temp_node.guard = guard_binding; - temp_node.is_assertion = false; - temp_node.is_function_call = true; - temp_node.is_loop = false; - temp_node.node_info = *f_it; - temp_node.rename_counter = counter; - temp_node.location = n_it->location; - - find_symbols(guard_binding,temp_node.used_symbols); - - for(local_SSAt::var_listt::const_iterator p_it = fSSA.params.begin(); - p_it != fSSA.params.end(); p_it++){ - irep_idt id = (*p_it).get(ID_identifier); - ssa_inliner.rename(id, counter); - all_ssa_symbols.insert(id); - temp_node.used_symbols.insert(id); - } - - for(local_SSAt::var_sett::const_iterator g_it = fSSA.globals_in.begin(); - g_it != fSSA.globals_in.end(); g_it++){ - irep_idt id = (*g_it).get(ID_identifier); - ssa_inliner.rename(id, counter); - all_ssa_symbols.insert(id); - temp_node.used_symbols.insert(id); - } - - for(local_SSAt::var_sett::const_iterator g_it = fSSA.globals_out.begin(); - g_it != fSSA.globals_out.end(); g_it++){ - irep_idt id = (*g_it).get(ID_identifier); - ssa_inliner.rename(id, counter); - all_ssa_symbols.insert(id); - temp_node.modified_symbols.insert(id); - } - - depnodes_map.push_back(temp_node); - //std::cout << "created function node, with info: " << from_expr(ns, "", *f_it) << "\n"; - } + const local_SSAt &fSSA=ssa_db.get(fname); + + /******************************************************************/ + /******* additional nodes needed to fix the dependency tree *******/ + + exprt guard_binding; + exprt::operandst bindings_in, bindings_out; + int counter=ssa_inliner.get_rename_counter(); + + /**/ + ssa_inliner.get_guard_binding(SSA, fSSA, n_it, guard_binding, counter); + // std::cout << "guard binding: " << from_expr(ns, "", guard_binding) << "\n"; + /* + { + depnodet temp_node; + temp_node.is_assertion=false; + temp_node.is_function_call=false; + temp_node.node_info=guard_binding; + + equal_exprt e=to_equal_expr(guard_binding); + exprt &lhs=e.lhs(); exprt &rhs=e.rhs(); + + find_symbols(rhs, temp_node.used_symbols); + find_symbols(lhs, temp_node.modified_symbols); + depnodes_map.push_back(temp_node); + // std::cout << "created guard binding node, with info: " << from_expr(ns, "", guard_binding) << "\n"; + } + */ + /**/ + + ssa_inliner.get_bindings(SSA, fSSA, n_it, f_it, bindings_in, bindings_out, counter); + + for(exprt::operandst::const_iterator b_it=bindings_in.begin(); + b_it!=bindings_in.end(); b_it++){ + + // std::cout << "binding: " << from_expr(ns, "", *b_it) << "\n"; + + depnodet temp_node; + temp_node.is_assertion=false; + temp_node.is_function_call=false; + temp_node.is_loop=false; + temp_node.node_info=*b_it; + temp_node.location=n_it->location; + + equal_exprt e=to_equal_expr(*b_it); + exprt &lhs=e.lhs(); exprt &rhs=e.rhs(); + + find_symbols(rhs, temp_node.used_symbols); + find_symbols(lhs, temp_node.modified_symbols); + depnodes_map.push_back(temp_node); + // std::cout << "created binding in node, with info: " << from_expr(ns, "", *b_it) << "\n"; + } + + for(exprt::operandst::const_iterator b_it=bindings_out.begin(); + b_it!=bindings_out.end(); b_it++){ + + // std::cout << "binding: " << from_expr(ns, "", *b_it) << "\n"; + + depnodet temp_node; + temp_node.is_assertion=false; + temp_node.is_function_call=false; + temp_node.is_loop=false; + temp_node.node_info=*b_it; + temp_node.location=n_it->location; + + equal_exprt e=to_equal_expr(*b_it); + exprt &lhs=e.lhs(); exprt &rhs=e.rhs(); + + find_symbols(rhs, temp_node.used_symbols); + find_symbols(lhs, temp_node.modified_symbols); + depnodes_map.push_back(temp_node); + // std::cout << "created binding out node, with info: " << from_expr(ns, "", *b_it) << "\n"; + } + + /******************************************************************/ + + depnodet temp_node; + temp_node.guard=guard_binding; + temp_node.is_assertion=false; + temp_node.is_function_call=true; + temp_node.is_loop=false; + temp_node.node_info=*f_it; + temp_node.rename_counter=counter; + temp_node.location=n_it->location; + + find_symbols(guard_binding, temp_node.used_symbols); + + for(local_SSAt::var_listt::const_iterator p_it=fSSA.params.begin(); + p_it!=fSSA.params.end(); p_it++){ + irep_idt id=(*p_it).get(ID_identifier); + ssa_inliner.rename(id, counter); + all_ssa_symbols.insert(id); + temp_node.used_symbols.insert(id); + } + + for(local_SSAt::var_sett::const_iterator g_it=fSSA.globals_in.begin(); + g_it!=fSSA.globals_in.end(); g_it++){ + irep_idt id=(*g_it).get(ID_identifier); + ssa_inliner.rename(id, counter); + all_ssa_symbols.insert(id); + temp_node.used_symbols.insert(id); + } + + for(local_SSAt::var_sett::const_iterator g_it=fSSA.globals_out.begin(); + g_it!=fSSA.globals_out.end(); g_it++){ + irep_idt id=(*g_it).get(ID_identifier); + ssa_inliner.rename(id, counter); + all_ssa_symbols.insert(id); + temp_node.modified_symbols.insert(id); + } + + depnodes_map.push_back(temp_node); + // std::cout << "created function node, with info: " << from_expr(ns, "", *f_it) << "\n"; } + } } - first_node = false; - + first_node=false; + depnodet source_node; - source_node.is_assertion = false; - source_node.is_function_call = false; - source_node.is_loop = false; - + source_node.is_assertion=false; + source_node.is_function_call=false; + source_node.is_loop=false; + // params and globals_in are the modified_symbols at source_node - - for(local_SSAt::var_listt::const_iterator p_it = SSA.params.begin(); - p_it != SSA.params.end(); p_it++){ - irep_idt id = (*p_it).get(ID_identifier); + + for(local_SSAt::var_listt::const_iterator p_it=SSA.params.begin(); + p_it!=SSA.params.end(); p_it++){ + irep_idt id=(*p_it).get(ID_identifier); source_node.modified_symbols.insert(id); } - - for(local_SSAt::var_sett::const_iterator g_it = SSA.globals_in.begin(); - g_it != SSA.globals_in.end(); g_it++){ - irep_idt id = (*g_it).get(ID_identifier); + + for(local_SSAt::var_sett::const_iterator g_it=SSA.globals_in.begin(); + g_it!=SSA.globals_in.end(); g_it++){ + irep_idt id=(*g_it).get(ID_identifier); source_node.modified_symbols.insert(id); } - + depnodes_map.push_back(source_node); // source_node - //std::cout << "created source node, without any info" << "\n"; - - top_node_index = depnodes_map.size() - 1; - + // std::cout << "created source node, without any info" << "\n"; + + top_node_index=depnodes_map.size()-1; + for(find_symbols_sett::const_iterator - s_it=all_ssa_symbols.begin(); s_it!=all_ssa_symbols.end(); s_it++){ - - for(unsigned m_index = 0; m_index < depnodes_map.size(); m_index++){ - if(depnodes_map[m_index].modified_symbols.find(*s_it) != depnodes_map[m_index].modified_symbols.end()){ - - for(unsigned u_index = 0; u_index < depnodes_map.size(); u_index++){ - - if(m_index != u_index){ - if(depnodes_map[u_index].used_symbols.find(*s_it) != depnodes_map[u_index].used_symbols.end()){ - annotated_predecessort temp_pred; - temp_pred.predecessor_node_index = m_index; - temp_pred.annotation.insert(*s_it); - depnodes_map[u_index].predecessors.push_back(temp_pred); - depnodes_map[m_index].successors.push_back(u_index); - } - } - } + s_it=all_ssa_symbols.begin(); s_it!=all_ssa_symbols.end(); s_it++){ + + for(unsigned m_index=0; m_index #include -#include "../summarizer/ssa_db.h" -#include "ssa_inliner.h" #include "local_ssa.h" class ssa_inlinert; class ssa_dbt; class ssa_dependency_grapht{ - public: - - inline ssa_dependency_grapht(ssa_dbt &_db, const namespacet &_ns): +public: +ssa_dependency_grapht(ssa_dbt &_db, const namespacet &_ns): ssa_db(_db), - ns(_ns) - {}; - - struct annotated_predecessort{ + ns(_ns) + { + } + + struct annotated_predecessort + { int predecessor_node_index; find_symbols_sett annotation; }; - + typedef std::list annotated_predecessorst; struct depnodet{ exprt node_info; - exprt guard; //guard binding or loop-head select + exprt guard; // guard binding or loop-head select bool is_assertion; bool is_function_call; bool is_loop; - //bool trivial_guard; + // bool trivial_guard; int rename_counter; find_symbols_sett used_symbols; find_symbols_sett modified_symbols; @@ -41,21 +47,21 @@ class ssa_dependency_grapht{ std::vector successors; local_SSAt::locationt location; }; - - //typedef std::map depnodest; + + // typedef std::map depnodest; typedef std::vector depnodest; depnodest depnodes_map; int top_node_index; - //special source_node and sink_node - //depnodet source_node = depnodes_map[top_node_index]; - //depnodet sink_node = depnodes_map[0]; - + // special source_node and sink_node + // depnodet source_node=depnodes_map[top_node_index]; + // depnodet sink_node=depnodes_map[0]; + void create(const local_SSAt &SSA, ssa_inlinert &ssa_inliner, bool entry); void output(std::ostream &) const; - - protected: + +protected: ssa_dbt &ssa_db; const namespacet &ns; }; diff --git a/src/ssa/ssa_domain.cpp b/src/ssa/ssa_domain.cpp index 193551c75..a9848e8af 100644 --- a/src/ssa/ssa_domain.cpp +++ b/src/ssa/ssa_domain.cpp @@ -135,7 +135,7 @@ bool ssa_domaint::merge( d_it_b++) { const irep_idt &id=d_it_b->first; - + // check if we have a phi node for 'id' phi_nodest::iterator p_it=phi_nodes.find(id); diff --git a/src/ssa/ssa_inliner.cpp b/src/ssa/ssa_inliner.cpp index 1fa429cd5..7574220da 100644 --- a/src/ssa/ssa_inliner.cpp +++ b/src/ssa/ssa_inliner.cpp @@ -17,7 +17,7 @@ Function: ssa_inlinert::get_guard_binding Inputs: - Outputs: + Outputs: Purpose: get guard binding for function call @@ -44,7 +44,7 @@ Function: ssa_inlinert::get_bindings Inputs: - Outputs: + Outputs: Purpose: get bindings for function call @@ -54,18 +54,18 @@ void ssa_inlinert::get_bindings( const local_SSAt &SSA, const local_SSAt &fSSA, local_SSAt::nodest::const_iterator n_it, - local_SSAt::nodet::function_callst::const_iterator f_it, + local_SSAt::nodet::function_callst::const_iterator f_it, exprt::operandst &bindings_in, exprt::operandst &bindings_out, int counter) { - //getting globals at call site - local_SSAt::var_sett cs_globals_in, cs_globals_out; + // getting globals at call site + local_SSAt::var_sett cs_globals_in, cs_globals_out; goto_programt::const_targett loc=n_it->location; - + SSA.get_globals(loc, cs_globals_in); SSA.get_globals(loc, cs_globals_out, false); - + #if 0 std::cout << "cs_globals_in: "; for(summaryt::var_sett::const_iterator it=cs_globals_in.begin(); @@ -80,14 +80,14 @@ void ssa_inlinert::get_bindings( std::cout << std::endl; #endif - //equalities for arguments - get_replace_params(SSA,fSSA.params,n_it,*f_it,bindings_in,counter); + // equalities for arguments + get_replace_params(SSA, fSSA.params, n_it, *f_it, bindings_in, counter); - //equalities for globals_in - get_replace_globals_in(fSSA.globals_in,*f_it,cs_globals_in,bindings_in,counter); + // equalities for globals_in + get_replace_globals_in(fSSA.globals_in, *f_it, cs_globals_in, bindings_in, counter); - //equalities for globals out (including unmodified globals) - get_replace_globals_out(fSSA.globals_out,*f_it,cs_globals_in,cs_globals_out,bindings_out,counter); + // equalities for globals out (including unmodified globals) + get_replace_globals_out(fSSA.globals_out, *f_it, cs_globals_in, cs_globals_out, bindings_out, counter); } @@ -97,7 +97,7 @@ Function: ssa_inlinert::get_inlined Inputs: - Outputs: + Outputs: Purpose: get inlined function call @@ -107,8 +107,8 @@ Function: ssa_inlinert::get_inlined bool ssa_inlinert::get_inlined( const local_SSAt &SSA, local_SSAt::nodest::const_iterator n_it, - local_SSAt::nodet::function_callst::const_iterator f_it, - bool forward, + local_SSAt::nodet::function_callst::const_iterator f_it, + bool forward, exprt::operandst &assert_summaries, exprt::operandst &noassert_summaries, exprt::operandst &bindings, @@ -116,38 +116,38 @@ bool ssa_inlinert::get_inlined( int counter, bool error_summ) { - irep_idt fname = to_symbol_expr(f_it->function()).get_identifier(); - const local_SSAt &fSSA = ssa_db.get(fname); + irep_idt fname=to_symbol_expr(f_it->function()).get_identifier(); + const local_SSAt &fSSA=ssa_db.get(fname); - bool assertion_flag = get_summaries(fSSA, + bool assertion_flag=get_summaries(fSSA, summaryt::call_sitet(fSSA.goto_function.body.instructions.end()), - forward,assert_summaries,noassert_summaries, - bindings,assertion_map,error_summ); + forward, assert_summaries, noassert_summaries, + bindings, assertion_map, error_summ); - //bindings + // bindings exprt guard_binding; - get_guard_binding(SSA,fSSA,n_it,guard_binding,counter); + get_guard_binding(SSA, fSSA, n_it, guard_binding, counter); bindings.push_back(guard_binding); - get_bindings(SSA,fSSA,n_it,f_it,bindings,bindings,counter); + get_bindings(SSA, fSSA, n_it, f_it, bindings, bindings, counter); - bool first_equality = true; - for(local_SSAt::nodest::const_iterator n_it = fSSA.nodes.begin(); - n_it != fSSA.nodes.end(); n_it++) + bool first_equality=true; + for(local_SSAt::nodest::const_iterator n_it=fSSA.nodes.begin(); + n_it!=fSSA.nodes.end(); n_it++) { const local_SSAt::nodet &fnode=*n_it; - - for(local_SSAt::nodet::equalitiest::const_iterator e_it = + + for(local_SSAt::nodet::equalitiest::const_iterator e_it= fnode.equalities.begin(); e_it!=fnode.equalities.end(); e_it++) { // unless lhs starts with "ssa::guard" and rhs is true // because that one is replaced by the guard binding - const equal_exprt &e = to_equal_expr(*e_it); - const exprt &lhs = e.lhs(); const exprt &rhs = e.rhs(); - std::string var_string = id2string(to_symbol_expr(lhs).get_identifier()); - if((var_string.substr(0,11) == "ssa::$guard") && + const equal_exprt &e=to_equal_expr(*e_it); + const exprt &lhs=e.lhs(); const exprt &rhs=e.rhs(); + std::string var_string=id2string(to_symbol_expr(lhs).get_identifier()); + if((var_string.substr(0, 11)=="ssa::$guard") && rhs.is_true() && first_equality) { - first_equality = false; + first_equality=false; } else { @@ -155,20 +155,20 @@ bool ssa_inlinert::get_inlined( rename(noassert_summaries.back(), counter); } } - for(local_SSAt::nodet::constraintst::const_iterator c_it = + for(local_SSAt::nodet::constraintst::const_iterator c_it= fnode.constraints.begin(); c_it!=fnode.constraints.end(); c_it++) { noassert_summaries.push_back(*c_it); rename(noassert_summaries.back(), counter); } - for(local_SSAt::nodet::assertionst::const_iterator a_it = + for(local_SSAt::nodet::assertionst::const_iterator a_it= fnode.assertions.begin(); a_it!=fnode.assertions.end(); a_it++) { #if 0 assert_summaries.push_back(*a_it); rename(assert_summaries.back(), counter); #endif - assertion_flag = true; + assertion_flag=true; } } @@ -192,7 +192,6 @@ bool ssa_inlinert::get_summary( const local_SSAt &SSA, local_SSAt::nodest::const_iterator n_it, local_SSAt::nodet::function_callst::const_iterator f_it, - const summaryt &summary, bool forward, exprt::operandst &assert_summaries, exprt::operandst &noassert_summaries, @@ -200,14 +199,14 @@ bool ssa_inlinert::get_summary( int counter, bool error_summ) { - irep_idt fname = to_symbol_expr(f_it->function()).get_identifier(); - const summaryt &summary = summary_db.get(fname); + irep_idt fname=to_symbol_expr(f_it->function()).get_identifier(); + const summaryt &summary=summary_db.get(fname); - //getting globals at call site - local_SSAt::var_sett cs_globals_in, cs_globals_out; - goto_programt::const_targett loc = n_it->location; - SSA.get_globals(loc,cs_globals_in); - SSA.get_globals(loc,cs_globals_out,false); + // getting globals at call site + local_SSAt::var_sett cs_globals_in, cs_globals_out; + goto_programt::const_targett loc=n_it->location; + SSA.get_globals(loc, cs_globals_in); + SSA.get_globals(loc, cs_globals_out, false); #if 0 std::cout << "cs_globals_in: "; @@ -223,11 +222,11 @@ bool ssa_inlinert::get_summary( std::cout << std::endl; #endif - //equalities for arguments - get_replace_params(SSA,summary.params, n_it, *f_it, bindings, counter); + // equalities for arguments + get_replace_params(SSA, summary.params, n_it, *f_it, bindings, counter); - //equalities for globals_in - get_replace_globals_in(summary.globals_in,*f_it,cs_globals_in,bindings,counter); + // equalities for globals_in + get_replace_globals_in(summary.globals_in, *f_it, cs_globals_in, bindings, counter); // constraints for transformer @@ -237,25 +236,25 @@ bool ssa_inlinert::get_summary( { // update transformer using the error_summaries map summaryt::call_sitet call_site(loc); - summaryt::error_summariest::const_iterator e_it = - summary.error_summaries.find(call_site); + summaryt::error_summariest::const_iterator e_it= + summary.error_summaries.find(call_site); if(e_it!=summary.error_summaries.end() && - !e_it->second.is_nil()) - transformer=e_it->second; + !e_it->second.is_nil()) + transformer=e_it->second; else - transformer=true_exprt(); + transformer=true_exprt(); } else { if(forward) - transformer = summary.fw_transformer.is_nil() ? true_exprt() : + transformer=summary.fw_transformer.is_nil() ? true_exprt() : summary.fw_transformer; - else - transformer = summary.bw_transformer.is_nil() ? true_exprt() : + else + transformer=summary.bw_transformer.is_nil() ? true_exprt() : summary.bw_transformer; } - - rename(transformer,counter); + + rename(transformer, counter); if(summary.has_assertion) { assert_summaries.push_back(implies_exprt(SSA.guard_symbol(n_it->location), @@ -266,9 +265,9 @@ bool ssa_inlinert::get_summary( noassert_summaries.push_back(implies_exprt(SSA.guard_symbol(n_it->location), transformer)); } - - //equalities for globals out (including unmodified globals) - get_replace_globals_out(summary.globals_out,*f_it,cs_globals_in,cs_globals_out,bindings,counter); + + // equalities for globals out (including unmodified globals) + get_replace_globals_out(summary.globals_out, *f_it, cs_globals_in, cs_globals_out, bindings, counter); return summary.has_assertion; } @@ -295,9 +294,9 @@ exprt ssa_inlinert::get_summaries(const local_SSAt &SSA) exprt ssa_inlinert::get_summaries(const local_SSAt &SSA, assertion_mapt &assertion_map) { - exprt::operandst summaries,bindings; - get_summaries(SSA,true,summaries,bindings,assertion_map); - return and_exprt(conjunction(bindings),conjunction(summaries)); + exprt::operandst summaries, bindings; + get_summaries(SSA, true, summaries, bindings, assertion_map); + return and_exprt(conjunction(bindings), conjunction(summaries)); } void ssa_inlinert::get_summaries( @@ -309,7 +308,7 @@ void ssa_inlinert::get_summaries( assertion_mapt assertion_map; get_summaries(SSA, summaryt::call_sitet(SSA.goto_function.body.instructions.end()), - forward,summaries,summaries,bindings,assertion_map); + forward, summaries, summaries, bindings, assertion_map); } void ssa_inlinert::get_summaries(const local_SSAt &SSA, @@ -320,7 +319,7 @@ void ssa_inlinert::get_summaries(const local_SSAt &SSA, { get_summaries(SSA, summaryt::call_sitet(SSA.goto_function.body.instructions.end()), - forward,summaries,summaries,bindings,assertion_map); + forward, summaries, summaries, bindings, assertion_map); } /*******************************************************************\ @@ -341,12 +340,13 @@ bool ssa_inlinert::get_summaries( bool forward, exprt::operandst &assert_summaries, exprt::operandst &noassert_summaries, - exprt::operandst &bindings) + exprt::operandst &bindings, + bool error_summ) { assertion_mapt assertion_map; return get_summaries(SSA, summaryt::call_sitet(SSA.goto_function.body.instructions.end()), - forward,assert_summaries,noassert_summaries,bindings,assertion_map); + forward, assert_summaries, noassert_summaries, bindings, assertion_map); } bool ssa_inlinert::get_summaries(const local_SSAt &SSA, @@ -358,47 +358,47 @@ bool ssa_inlinert::get_summaries(const local_SSAt &SSA, assertion_mapt &assertion_map, bool error_summ) { - bool assertion_flag = false; + bool assertion_flag=false; for(local_SSAt::nodest::const_iterator n_it=SSA.nodes.begin(); n_it!=SSA.nodes.end(); n_it++) { - for(local_SSAt::nodet::assertionst::const_iterator a_it = + for(local_SSAt::nodet::assertionst::const_iterator a_it= n_it->assertions.begin(); - a_it != n_it->assertions.end(); a_it++) + a_it!=n_it->assertions.end(); a_it++) { assertion_map[n_it->location].push_back(*a_it); rename(assertion_map[n_it->location].back(), counter); } - for(local_SSAt::nodet::function_callst::const_iterator f_it = + for(local_SSAt::nodet::function_callst::const_iterator f_it= n_it->function_calls.begin(); f_it!=n_it->function_calls.end(); f_it++) { - //do not use summary for current call site + // do not use summary for current call site summaryt::call_sitet this_call_site(n_it->location); - if(current_call_site == this_call_site) + if(current_call_site==this_call_site) continue; - irep_idt fname = to_symbol_expr(f_it->function()).get_identifier(); + irep_idt fname=to_symbol_expr(f_it->function()).get_identifier(); - //get inlined function + // get inlined function if(n_it->function_calls_inlined) { counter++; - bool new_assertion_flag = - get_inlined(SSA,n_it,f_it, - forward,assert_summaries,noassert_summaries, - bindings,assertion_map,counter,error_summ); - assertion_flag = assertion_flag || new_assertion_flag; + bool new_assertion_flag= + get_inlined(SSA, n_it, f_it, + forward, assert_summaries, noassert_summaries, + bindings, assertion_map, counter, error_summ); + assertion_flag=assertion_flag || new_assertion_flag; } - //get summary + // get summary else if(summary_db.exists(fname)) { counter++; - bool new_assertion_flag = - get_summary(SSA,n_it,f_it, - forward,assert_summaries,noassert_summaries, - bindings,counter,error_summ); - assertion_flag = assertion_flag || new_assertion_flag; + bool new_assertion_flag= + get_summary(SSA, n_it, f_it, + forward, assert_summaries, noassert_summaries, + bindings, counter, error_summ); + assertion_flag=assertion_flag || new_assertion_flag; } } } @@ -423,7 +423,8 @@ Function: ssa_inlinert::replace void ssa_inlinert::replace( local_SSAt &SSA, bool forward, - bool preconditions_as_assertions) + bool preconditions_as_assertions, + int counter) { for(local_SSAt::nodest::iterator n_it=SSA.nodes.begin(); n_it!=SSA.nodes.end(); n_it++) @@ -450,7 +451,7 @@ void ssa_inlinert::replace( // replace replace( SSA, n_it, f_it, cs_globals_in, cs_globals_out, summary, - forward, preconditions_as_assertions); + forward, preconditions_as_assertions, counter); // remove function_call rm_function_calls.insert(f_it); @@ -484,53 +485,53 @@ void ssa_inlinert::replace( bool recursive, bool rename) { - for(local_SSAt::nodest::iterator n_it = SSA.nodes.begin(); - n_it != SSA.nodes.end(); n_it++) + for(local_SSAt::nodest::iterator n_it=SSA.nodes.begin(); + n_it!=SSA.nodes.end(); n_it++) { - for(local_SSAt::nodet::function_callst::iterator - f_it = n_it->function_calls.begin(); - f_it != n_it->function_calls.end(); f_it++) + for(local_SSAt::nodet::function_callst::iterator + f_it=n_it->function_calls.begin(); + f_it!=n_it->function_calls.end(); f_it++) { - assert(f_it->function().id()==ID_symbol); //no function pointers - irep_idt fname = to_symbol_expr(f_it->function()).get_identifier(); - - if(ssa_db.exists(fname)) - { - status() << "Inlining function " << fname << eom; - local_SSAt fSSA = ssa_db.get(fname); //copy - - if(rename) + assert(f_it->function().id()==ID_symbol); // no function pointers + irep_idt fname=to_symbol_expr(f_it->function()).get_identifier(); + + if(ssa_db.exists(fname)) + { + status() << "Inlining function " << fname << eom; + local_SSAt fSSA=ssa_db.get(fname); // copy + + if(rename) { - //getting globals at call site - local_SSAt::var_sett cs_globals_in, cs_globals_out; - goto_programt::const_targett loc = n_it->location; - SSA.get_globals(loc,cs_globals_in); - SSA.get_globals(loc,cs_globals_out,false); - + // getting globals at call site + local_SSAt::var_sett cs_globals_in, cs_globals_out; + goto_programt::const_targett loc=n_it->location; + SSA.get_globals(loc, cs_globals_in); + SSA.get_globals(loc, cs_globals_out, false); + if(recursive) { - replace(fSSA,ssa_db,true,counter); + replace(fSSA, ssa_db, true, counter); } - //replace - replace(SSA.nodes,n_it,f_it,cs_globals_in,cs_globals_out,fSSA,counter); + // replace + replace(SSA.nodes, n_it, f_it, cs_globals_in, cs_globals_out, fSSA, counter); } - else // just add to nodes + else // just add to nodes { - for(local_SSAt::nodest::const_iterator fn_it = fSSA.nodes.begin(); - fn_it != fSSA.nodes.end(); fn_it++) + for(local_SSAt::nodest::const_iterator fn_it=fSSA.nodes.begin(); + fn_it!=fSSA.nodes.end(); fn_it++) { - debug() << "new node: "; fn_it->output(debug(),fSSA.ns); + debug() << "new node: "; fn_it->output(debug(), fSSA.ns); debug() << eom; - + new_nodes.push_back(*fn_it); } } - } + } else debug() << "No body available for function " << fname << eom; commit_node(n_it); } - commit_nodes(SSA.nodes,n_it); + commit_nodes(SSA.nodes, n_it); } } @@ -558,10 +559,10 @@ void ssa_inlinert::replace( int counter) { // equalities for arguments - replace_params(summary.params, *f_it); + replace_params(summary.params, *f_it, counter); // equalities for globals_in - replace_globals_in(summary.globals_in, cs_globals_in); + replace_globals_in(summary.globals_in, cs_globals_in, counter); // constraints for precondition and transformer exprt precondition; @@ -571,14 +572,14 @@ void ssa_inlinert::replace( precondition=summary.bw_precondition; if(!preconditions_as_assertions) { - rename(precondition); + rename(precondition, counter); node->constraints.push_back( implies_exprt(SSA.guard_symbol(node->location), precondition)); } else { - rename(precondition); + rename(precondition, counter); node->assertions.push_back( implies_exprt(SSA.guard_symbol(node->location), precondition)); @@ -596,7 +597,8 @@ void ssa_inlinert::replace( rm_function_calls.insert(f_it); // equalities for globals out (including unmodified globals) - replace_globals_out(summary.globals_out, cs_globals_in, cs_globals_out); + replace_globals_out( + summary.globals_out, cs_globals_in, cs_globals_out, counter); } /*******************************************************************\ @@ -626,17 +628,17 @@ void ssa_inlinert::replace( { // equalities for arguments - replace_params(function.params, *f_it); + replace_params(function.params, *f_it, counter); // equalities for globals_in - replace_globals_in(function.globals_in, cs_globals_in); + replace_globals_in(function.globals_in, cs_globals_in, counter); // add function body for(local_SSAt::nodest::const_iterator n_it=function.nodes.begin(); n_it!=function.nodes.end(); n_it++) { local_SSAt::nodet n=*n_it; // copy - rename(n,counter); + rename(n, counter); new_nodes.push_back(n); } @@ -644,7 +646,8 @@ void ssa_inlinert::replace( rm_function_calls.insert(f_it); // equalities for globals out (including unmodified globals) - replace_globals_out(function.globals_out, cs_globals_in, cs_globals_out); + replace_globals_out( + function.globals_out, cs_globals_in, cs_globals_out, counter); } /*******************************************************************\ @@ -666,52 +669,52 @@ void ssa_inlinert::get_replace_globals_in( exprt::operandst &c, int counter) { - std::string suffix = id2string(funapp_expr.get(ID_suffix)); + std::string suffix=id2string(funapp_expr.get(ID_suffix)); - //equalities for globals_in - for(summaryt::var_sett::const_iterator it = globals_in.begin(); - it != globals_in.end(); it++) + // equalities for globals_in + for(summaryt::var_sett::const_iterator it=globals_in.begin(); + it!=globals_in.end(); it++) { - symbol_exprt lhs = *it; //copy - rename(lhs,counter); + symbol_exprt lhs=*it; // copy + rename(lhs, counter); symbol_exprt rhs; - if(find_corresponding_symbol(*it,globals,rhs)) + if(find_corresponding_symbol(*it, globals, rhs)) { rhs.set_identifier(id2string(rhs.get_identifier())+suffix); - - debug() << "binding: " << lhs.get_identifier() << " == " + + debug() << "binding: " << lhs.get_identifier() << "==" << rhs.get_identifier() << eom; - c.push_back(equal_exprt(lhs,rhs)); + c.push_back(equal_exprt(lhs, rhs)); } #if 0 else - warning() << "'" << it->get_identifier() + warning() << "'" << it->get_identifier() << "' not bound in caller" << eom; #endif } - //return conjunction(c); + // return conjunction(c); } -void ssa_inlinert::replace_globals_in(const local_SSAt::var_sett &globals_in, +void ssa_inlinert::replace_globals_in(const local_SSAt::var_sett &globals_in, const local_SSAt::var_sett &globals, int counter) { - //equalities for globals_in - for(summaryt::var_sett::const_iterator it = globals_in.begin(); - it != globals_in.end(); it++) + // equalities for globals_in + for(summaryt::var_sett::const_iterator it=globals_in.begin(); + it!=globals_in.end(); it++) { - symbol_exprt lhs = *it; //copy - rename(lhs,counter); + symbol_exprt lhs=*it; // copy + rename(lhs, counter); symbol_exprt rhs; - if(find_corresponding_symbol(*it,globals,rhs)) + if(find_corresponding_symbol(*it, globals, rhs)) { - debug() << "binding: " << lhs.get_identifier() << " == " + debug() << "binding: " << lhs.get_identifier() << "==" << rhs.get_identifier() << eom; - new_equs.push_back(equal_exprt(lhs,rhs)); + new_equs.push_back(equal_exprt(lhs, rhs)); } #if 0 else - warning() << "'" << it->get_identifier() + warning() << "'" << it->get_identifier() << "' not bound in caller" << eom; #endif } @@ -737,51 +740,51 @@ void ssa_inlinert::get_replace_params( exprt::operandst &c, int counter) { - //equalities for arguments - local_SSAt::var_listt::const_iterator p_it = params.begin(); - for(exprt::operandst::const_iterator it = funapp_expr.arguments().begin(); - it != funapp_expr.arguments().end(); it++, p_it++) + // equalities for arguments + local_SSAt::var_listt::const_iterator p_it=params.begin(); + for(exprt::operandst::const_iterator it=funapp_expr.arguments().begin(); + it!=funapp_expr.arguments().end(); it++, p_it++) { #if 0 - std::cout << "replace param " << from_expr(SSA.ns,"",*p_it) - << " == " << from_expr(SSA.ns,"",*it) << std::endl; + std::cout << "replace param " << from_expr(SSA.ns, "", *p_it) + << "==" << from_expr(SSA.ns, "", *it) << std::endl; #endif - + #if 0 - local_SSAt::var_listt::const_iterator next_p_it = p_it; - if(funapp_expr.arguments().size() != params.size() && - ++next_p_it==params.end()) //TODO: handle ellipsis + local_SSAt::var_listt::const_iterator next_p_it=p_it; + if(funapp_expr.arguments().size()!=params.size() && + ++next_p_it==params.end()) // TODO: handle ellipsis { - warning() << "ignoring excess function arguments" << eom; + warning() << "ignoring excess function arguments" << eom; break; } #endif if(SSA.ns.follow(it->type()).id()==ID_struct) { - exprt rhs = SSA.read_rhs(*it, n_it->location); //copy + exprt rhs=SSA.read_rhs(*it, n_it->location); // copy #if 0 - std::cout << "split param " << from_expr(SSA.ns,"",*it) - << " into " << from_expr(SSA.ns,"",rhs) << std::endl; + std::cout << "split param " << from_expr(SSA.ns, "", *it) + << " into " << from_expr(SSA.ns, "", rhs) << std::endl; #endif forall_operands(o_it, rhs) { assert(p_it!=params.end()); - exprt lhs = *p_it; //copy - rename(lhs,counter); + exprt lhs=*p_it; // copy + rename(lhs, counter); #if 0 - std::cout << "split replace param " << from_expr(SSA.ns,"",*p_it) - << " == " << from_expr(SSA.ns,"",*o_it) << std::endl; + std::cout << "split replace param " << from_expr(SSA.ns, "", *p_it) + << "==" << from_expr(SSA.ns, "", *o_it) << std::endl; #endif - c.push_back(equal_exprt(lhs,*o_it)); + c.push_back(equal_exprt(lhs, *o_it)); ++p_it; } } else { - exprt lhs = *p_it; //copy - rename(lhs,counter); - c.push_back(equal_exprt(lhs,*it)); + exprt lhs=*p_it; // copy + rename(lhs, counter); + c.push_back(equal_exprt(lhs, *it)); } } } @@ -790,22 +793,22 @@ void ssa_inlinert::replace_params(const local_SSAt::var_listt ¶ms, const function_application_exprt &funapp_expr, int counter) { - //equalities for arguments - local_SSAt::var_listt::const_iterator p_it = params.begin(); - for(exprt::operandst::const_iterator it = funapp_expr.arguments().begin(); - it != funapp_expr.arguments().end(); it++, p_it++) + // equalities for arguments + local_SSAt::var_listt::const_iterator p_it=params.begin(); + for(exprt::operandst::const_iterator it=funapp_expr.arguments().begin(); + it!=funapp_expr.arguments().end(); it++, p_it++) { - local_SSAt::var_listt::const_iterator next_p_it = p_it; - if(funapp_expr.arguments().size() != params.size() && - ++next_p_it==params.end()) //TODO: handle ellipsis + local_SSAt::var_listt::const_iterator next_p_it=p_it; + if(funapp_expr.arguments().size()!=params.size() && + ++next_p_it==params.end()) // TODO: handle ellipsis { - warning() << "ignoring excess function arguments" << eom; + warning() << "ignoring excess function arguments" << eom; break; } - - exprt lhs = *p_it; //copy - rename(lhs,counter); - new_equs.push_back(equal_exprt(lhs,*it)); + + exprt lhs=*p_it; // copy + rename(lhs, counter); + new_equs.push_back(equal_exprt(lhs, *it)); } } @@ -829,45 +832,45 @@ void ssa_inlinert::get_replace_globals_out( exprt::operandst &c, int counter) { - std::string suffix = id2string(funapp_expr.get(ID_suffix)); + std::string suffix=id2string(funapp_expr.get(ID_suffix)); - //equalities for globals_out - for(summaryt::var_sett::const_iterator it = cs_globals_out.begin(); - it != cs_globals_out.end(); it++) + // equalities for globals_out + for(summaryt::var_sett::const_iterator it=cs_globals_out.begin(); + it!=cs_globals_out.end(); it++) { - symbol_exprt lhs = *it; //copy + symbol_exprt lhs=*it; // copy lhs.set_identifier(id2string(lhs.get_identifier())+suffix); symbol_exprt rhs; - if(find_corresponding_symbol(*it,globals_out,rhs)) - rename(rhs,counter); + if(find_corresponding_symbol(*it, globals_out, rhs)) + rename(rhs, counter); else { - bool found = find_corresponding_symbol(*it,cs_globals_in,rhs); + bool found=find_corresponding_symbol(*it, cs_globals_in, rhs); assert(found); rhs.set_identifier(id2string(rhs.get_identifier())+suffix); } - c.push_back(equal_exprt(lhs,rhs)); + c.push_back(equal_exprt(lhs, rhs)); } } -void ssa_inlinert::replace_globals_out(const local_SSAt::var_sett &globals_out, - const local_SSAt::var_sett &cs_globals_in, +void ssa_inlinert::replace_globals_out(const local_SSAt::var_sett &globals_out, + const local_SSAt::var_sett &cs_globals_in, const local_SSAt::var_sett &cs_globals_out, int counter) { - //equalities for globals_out - for(summaryt::var_sett::const_iterator it = cs_globals_out.begin(); - it != cs_globals_out.end(); it++) + // equalities for globals_out + for(summaryt::var_sett::const_iterator it=cs_globals_out.begin(); + it!=cs_globals_out.end(); it++) { - symbol_exprt rhs = *it; //copy + symbol_exprt rhs=*it; // copy symbol_exprt lhs; - if(find_corresponding_symbol(*it,globals_out,lhs)) - rename(lhs,counter); + if(find_corresponding_symbol(*it, globals_out, lhs)) + rename(lhs, counter); else - assert(find_corresponding_symbol(*it,cs_globals_in,lhs)); - new_equs.push_back(equal_exprt(lhs,rhs)); + assert(find_corresponding_symbol(*it, cs_globals_in, lhs)); + new_equs.push_back(equal_exprt(lhs, rhs)); } } @@ -884,10 +887,10 @@ Function: ssa_inlinert::havoc \*******************************************************************/ void ssa_inlinert::havoc( - local_SSAt::nodet &node, + local_SSAt::nodet &node, local_SSAt::nodet::function_callst::iterator f_it) { - //remove function call + // remove function call rm_function_calls.insert(f_it); } @@ -905,33 +908,33 @@ Function: ssa_inlinert::rename void ssa_inlinert::rename(irep_idt &id, int counter, bool attach){ - std::string id_str = id2string(id); + std::string id_str=id2string(id); if(!attach) { - //find first @ where afterwards there are no letters - size_t pos = std::string::npos; + // find first @ where afterwards there are no letters + size_t pos=std::string::npos; for(size_t i=0;i=0) - id = id_str+"@"+i2string(counter); + if(id_str.find('@')==std::string::npos && counter>=0) + id=id_str+"@"+i2string(counter); } } @@ -947,17 +950,17 @@ Function: ssa_inlinert::rename \*******************************************************************/ -void ssa_inlinert::rename(exprt &expr, int counter, bool attach) +void ssa_inlinert::rename(exprt &expr, int counter, bool attach) { - if(expr.id()==ID_symbol || expr.id()==ID_nondet_symbol) + if(expr.id()==ID_symbol || expr.id()==ID_nondet_symbol) { - irep_idt id = expr.get(ID_identifier); + irep_idt id=expr.get(ID_identifier); rename(id, counter, attach); - - expr.set(ID_identifier,id); + + expr.set(ID_identifier, id); } - for(exprt::operandst::iterator it = expr.operands().begin(); - it != expr.operands().end(); it++) + for(exprt::operandst::iterator it=expr.operands().begin(); + it!=expr.operands().end(); it++) { rename(*it, counter, attach); } @@ -975,29 +978,29 @@ Function: ssa_inlinert::rename \*******************************************************************/ -void ssa_inlinert::rename(local_SSAt::nodet &node, int counter) +void ssa_inlinert::rename(local_SSAt::nodet &node, int counter) { - for(local_SSAt::nodet::equalitiest::iterator e_it = node.equalities.begin(); - e_it != node.equalities.end(); e_it++) + for(local_SSAt::nodet::equalitiest::iterator e_it=node.equalities.begin(); + e_it!=node.equalities.end(); e_it++) { rename(*e_it, counter); } - for(local_SSAt::nodet::constraintst::iterator c_it = node.constraints.begin(); - c_it != node.constraints.end(); c_it++) + for(local_SSAt::nodet::constraintst::iterator c_it=node.constraints.begin(); + c_it!=node.constraints.end(); c_it++) { rename(*c_it, counter); - } - for(local_SSAt::nodet::assertionst::iterator a_it = node.assertions.begin(); - a_it != node.assertions.end(); a_it++) + } + for(local_SSAt::nodet::assertionst::iterator a_it=node.assertions.begin(); + a_it!=node.assertions.end(); a_it++) { rename(*a_it, counter); - } - for(local_SSAt::nodet::function_callst::iterator - f_it = node.function_calls.begin(); - f_it != node.function_calls.end(); f_it++) + } + for(local_SSAt::nodet::function_callst::iterator + f_it=node.function_calls.begin(); + f_it!=node.function_calls.end(); f_it++) { rename(*f_it, counter); - } + } } /*******************************************************************\ @@ -1013,10 +1016,10 @@ Function: ssa_inlinert::rename_to_caller \*******************************************************************/ void ssa_inlinert::rename_to_caller( - local_SSAt::nodet::function_callst::const_iterator f_it, - const local_SSAt::var_listt ¶ms, - const local_SSAt::var_sett &cs_globals_in, - const local_SSAt::var_sett &globals_in, + local_SSAt::nodet::function_callst::const_iterator f_it, + const local_SSAt::var_listt ¶ms, + const local_SSAt::var_sett &cs_globals_in, + const local_SSAt::var_sett &globals_in, exprt &expr) { assert(params.size()==f_it->arguments().size()); @@ -1093,17 +1096,17 @@ void ssa_inlinert::rename_to_callee( replace_map[*it]=*p_it; } - /* replace_expr(replace_map,expr); + /* replace_expr(replace_map, expr); - replace_map.clear(); //arguments might contain globals, + replace_map.clear(); // arguments might contain globals, // thus, we have to replace them separately */ - for(summaryt::var_sett::const_iterator it = cs_globals_in.begin(); - it != cs_globals_in.end(); it++) + for(summaryt::var_sett::const_iterator it=cs_globals_in.begin(); + it!=cs_globals_in.end(); it++) { symbol_exprt cg; - if(find_corresponding_symbol(*it,globals_in,cg)) - replace_map[*it] = cg; + if(find_corresponding_symbol(*it, globals_in, cg)) + replace_map[*it]=cg; else { #if 0 @@ -1115,7 +1118,6 @@ void ssa_inlinert::rename_to_callee( id2string(it->get_identifier())+"@"+i2string(++counter), it->type()); } } - } replace_expr(replace_map, expr); } diff --git a/src/ssa/ssa_inliner.h b/src/ssa/ssa_inliner.h index 0fe7581ab..88d114273 100644 --- a/src/ssa/ssa_inliner.h +++ b/src/ssa/ssa_inliner.h @@ -20,57 +20,59 @@ Author: Peter Schrammel class ssa_inlinert:public messaget { public: - explicit ssa_inlinert(summary_dbt &_summary_db, - ssa_dbt &_ssa_db) : - counter(-1), - summary_db(_summary_db), - ssa_db(_ssa_db) - {} + ssa_inlinert( + summary_dbt &_summary_db, + ssa_dbt &_ssa_db): + counter(-1), + summary_db(_summary_db), + ssa_db(_ssa_db) + { + } typedef std::map assertion_mapt; void get_guard_binding(const local_SSAt &SSA, - const local_SSAt &fSSA, - local_SSAt::nodest::const_iterator n_it, - exprt &guard_binding, - int counter); + const local_SSAt &fSSA, + local_SSAt::nodest::const_iterator n_it, + exprt &guard_binding, + int counter); void get_bindings(const local_SSAt &SSA, - const local_SSAt &fSSA, - local_SSAt::nodest::const_iterator n_it, - local_SSAt::nodet::function_callst::const_iterator f_it, - exprt::operandst &bindings_in, - exprt::operandst &bindings_out, - int counter); + const local_SSAt &fSSA, + local_SSAt::nodest::const_iterator n_it, + local_SSAt::nodet::function_callst::const_iterator f_it, + exprt::operandst &bindings_in, + exprt::operandst &bindings_out, + int counter); bool get_summary(const local_SSAt &SSA, - local_SSAt::nodest::const_iterator n_it, - local_SSAt::nodet::function_callst::const_iterator f_it, - bool forward, + local_SSAt::nodest::const_iterator n_it, + local_SSAt::nodet::function_callst::const_iterator f_it, + bool forward, exprt::operandst &assert_summaries, exprt::operandst &noassert_summaries, - exprt::operandst &bindings, - int counter, - bool error_summ = false); + exprt::operandst &bindings, + int counter, + bool error_summ=false); bool get_inlined(const local_SSAt &SSA, - local_SSAt::nodest::const_iterator n_it, - local_SSAt::nodet::function_callst::const_iterator f_it, - bool forward, + local_SSAt::nodest::const_iterator n_it, + local_SSAt::nodet::function_callst::const_iterator f_it, + bool forward, exprt::operandst &assert_summaries, exprt::operandst &noassert_summaries, - exprt::operandst &bindings, + exprt::operandst &bindings, assertion_mapt &assertion_map, - int counter, - bool error_summ); + int counter, + bool error_summ); void get_summaries( const local_SSAt &SSA, - bool forward, - exprt::operandst &summaries, - exprt::operandst &bindings, - assertion_mapt &assertion_map); //TODO: need to explicitly pass the correct counter + bool forward, + exprt::operandst &summaries, + exprt::operandst &bindings, + assertion_mapt &assertion_map); // TODO: need to explicitly pass the correct counter void get_summaries( const local_SSAt &SSA, - bool forward, - exprt::operandst &summaries, - exprt::operandst &bindings); //TODO: need to explicitly pass the correct counter + bool forward, + exprt::operandst &summaries, + exprt::operandst &bindings); // TODO: need to explicitly pass the correct counter bool get_summaries( const local_SSAt &SSA, const summaryt::call_sitet ¤t_call_site, @@ -78,7 +80,7 @@ class ssa_inlinert:public messaget exprt::operandst &assert_summaries, exprt::operandst &noassert_summaries, exprt::operandst &bindings, - bool error_summ=false); //TODO: need to explicitly pass the correct counter + bool error_summ=false); // TODO: need to explicitly pass the correct counter bool get_summaries( const local_SSAt &SSA, const summaryt::call_sitet ¤t_call_site, @@ -87,12 +89,12 @@ class ssa_inlinert:public messaget exprt::operandst &noassert_summaries, exprt::operandst &bindings, assertion_mapt &assertion_map, - bool error_summ=false); //TODO: need to explicitly pass the correct counter + bool error_summ=false); // TODO: need to explicitly pass the correct counter - exprt get_summaries(const local_SSAt &SSA); //TODO: need to explicitly pass the correct counter + exprt get_summaries(const local_SSAt &SSA); // TODO: need to explicitly pass the correct counter exprt get_summaries(const local_SSAt &SSA, - assertion_mapt &assertion_map); //TODO: need to explicitly pass the correct counter - + assertion_mapt &assertion_map); // TODO: need to explicitly pass the correct counter + void replace( local_SSAt &SSA, local_SSAt::nodest::iterator node, @@ -104,13 +106,13 @@ class ssa_inlinert:public messaget const summaryt &summary, bool forward, bool preconditions_as_assertions, - int counter); + int counter); void replace( local_SSAt &SSA, bool forward, bool preconditions_as_assertions, - int counte); + int counter); void replace( local_SSAt::nodest &nodes, @@ -121,11 +123,12 @@ class ssa_inlinert:public messaget const local_SSAt::var_sett &cs_globals_out, // outgoing globals at call site const local_SSAt &function, - int counte); + int counter); void replace( local_SSAt &SSA, const ssa_dbt &ssa_db, + int counter, bool recursive=false, bool rename=true); @@ -159,14 +162,14 @@ class ssa_inlinert:public messaget symbol_exprt &s_found); static irep_idt get_original_identifier(const symbol_exprt &s); - + void rename(irep_idt &id, int counter, bool attach=true); int get_rename_counter() { return ++counter; } // moved from protected to public, for use in summarizer_bw_cex_complete void rename(exprt &expr, int counter, bool attach=true); - + protected: int counter; summary_dbt &summary_db; @@ -177,7 +180,7 @@ class ssa_inlinert:public messaget std::set rm_function_calls; void replace_globals_in( - const local_SSAt::var_sett &globals_in, + const local_SSAt::var_sett &globals_in, const local_SSAt::var_sett &globals, int counter); void replace_params( @@ -185,13 +188,13 @@ class ssa_inlinert:public messaget const function_application_exprt &funapp_expr, int counter); void replace_globals_out( - const local_SSAt::var_sett &globals_out, - const local_SSAt::var_sett &cs_globals_in, + const local_SSAt::var_sett &globals_out, + const local_SSAt::var_sett &cs_globals_in, const local_SSAt::var_sett &cs_globals_out, int counter); void get_replace_globals_in( - const local_SSAt::var_sett &globals_in, + const local_SSAt::var_sett &globals_in, const function_application_exprt &funapp_expr, const local_SSAt::var_sett &globals, exprt::operandst &c, @@ -204,9 +207,9 @@ class ssa_inlinert:public messaget exprt::operandst &c, int counter); void get_replace_globals_out( - const local_SSAt::var_sett &globals_out, + const local_SSAt::var_sett &globals_out, const function_application_exprt &funapp_expr, - const local_SSAt::var_sett &cs_globals_in, + const local_SSAt::var_sett &cs_globals_in, const local_SSAt::var_sett &cs_globals_out, exprt::operandst &c, int counter); diff --git a/src/ssa/ssa_refiner_monolithic.cpp b/src/ssa/ssa_refiner_monolithic.cpp index ceb26639e..6d168fc23 100644 --- a/src/ssa/ssa_refiner_monolithic.cpp +++ b/src/ssa/ssa_refiner_monolithic.cpp @@ -23,7 +23,7 @@ Function: ssa_refiner_monolithict::operator() bool ssa_refiner_monolithict::operator()() { status() << "Unwinding (k=" << unwind << ")" << eom; - summary_db.mark_recompute_all(); //TODO: recompute only functions with loops + summary_db.mark_recompute_all(); // TODO: recompute only functions with loops ssa_unwinder.unwind_all(unwind); return unwind++<=max_unwind; diff --git a/src/ssa/ssa_refiner_monolithic.h b/src/ssa/ssa_refiner_monolithic.h index 77a86fde3..603d214f1 100644 --- a/src/ssa/ssa_refiner_monolithic.h +++ b/src/ssa/ssa_refiner_monolithic.h @@ -11,7 +11,7 @@ Author: Peter Schrammel #include "ssa_refiner.h" -#include "../summarizer/summary_db.h" +#include #include "ssa_unwinder.h" class summary_dbt; @@ -24,16 +24,16 @@ class ssa_refiner_monolithict : public ssa_refinert summary_dbt &_summary_db, ssa_unwindert &_ssa_unwinder, unsigned _max_unwind - ) : + ) : summary_db(_summary_db), ssa_unwinder(_ssa_unwinder), max_unwind(_max_unwind), unwind(0) {} - virtual bool operator()(); + virtual bool operator()(); virtual unsigned get_unwind() { return unwind>0 ? unwind-1 : 0; } - + protected: summary_dbt &summary_db; ssa_unwindert &ssa_unwinder; diff --git a/src/ssa/ssa_refiner_selective.cpp b/src/ssa/ssa_refiner_selective.cpp index 77e520194..6b61c19a7 100644 --- a/src/ssa/ssa_refiner_selective.cpp +++ b/src/ssa/ssa_refiner_selective.cpp @@ -23,35 +23,35 @@ Function: ssa_refiner_selectivet::operator() bool ssa_refiner_selectivet::operator()() { // unwind loops "selectively" (those that seem to be the "reason") - for(reasont::const_iterator it = reason.begin(); it != reason.end(); ++it) + for(reasont::const_iterator it=reason.begin(); it!=reason.end(); ++it) { - for(std::set::const_iterator l_it = + for(std::set::const_iterator l_it= it->second.loops.begin(); - l_it != it->second.loops.end(); l_it++) + l_it!=it->second.loops.end(); l_it++) { - unsigned new_unwind = ssa_unwinder.unwind_loop_once_more(it->first, + unsigned new_unwind=ssa_unwinder.unwind_loop_once_more(it->first, (*l_it)->location_number); - debug() << "Refining function " << it->first << ": unwinding loop at " + debug() << "Refining function " << it->first << ": unwinding loop at " << (*l_it)->location_number << " (k=" << new_unwind << ")" << eom; - unwind = std::max(unwind, new_unwind); + unwind=std::max(unwind, new_unwind); } } // inline functions "selectively" (those that seem to be the "reason") - for(reasont::const_iterator it = reason.begin(); it != reason.end(); ++it) + for(reasont::const_iterator it=reason.begin(); it!=reason.end(); ++it) { - for(std::set::const_iterator f_it = + for(std::set::const_iterator f_it= it->second.functions.begin(); - f_it != it->second.functions.end(); f_it++) + f_it!=it->second.functions.end(); f_it++) { - local_SSAt &SSA = ssa_db.get(it->first); - local_SSAt::nodest::iterator n_it = SSA.find_node(*f_it); + local_SSAt &SSA=ssa_db.get(it->first); + local_SSAt::nodest::iterator n_it=SSA.find_node(*f_it); assert(n_it->function_calls.size()==1); - n_it->function_calls_inlined = true; + n_it->function_calls_inlined=true; - irep_idt fname = to_symbol_expr(n_it->function_calls.begin() + irep_idt fname=to_symbol_expr(n_it->function_calls.begin() ->function()).get_identifier(); - debug() << "Refining function " << it->first << ": inlining call to " + debug() << "Refining function " << it->first << ": inlining call to " << fname << " at " << (*f_it)->location_number<< eom; } } diff --git a/src/ssa/ssa_refiner_selective.h b/src/ssa/ssa_refiner_selective.h index 9d2d8f352..b224a57c2 100644 --- a/src/ssa/ssa_refiner_selective.h +++ b/src/ssa/ssa_refiner_selective.h @@ -11,7 +11,7 @@ Author: Peter Schrammel, Madhukar Kumar #include "ssa_refiner.h" -#include "../summarizer/ssa_db.h" +#include #include "ssa_inliner.h" #include "ssa_unwinder.h" @@ -22,10 +22,10 @@ class ssa_refiner_selectivet : public ssa_refinert public: struct reason_infot { - typedef local_SSAt::locationt function_infot; //call_site; restriction: we assume that there is a single function call in an SSA node + typedef local_SSAt::locationt function_infot; // call_site; restriction: we assume that there is a single function call in an SSA node typedef local_SSAt::locationt loop_infot; std::set functions; - std::set loops; + std::set loops; }; class reasont : public std::map @@ -33,11 +33,11 @@ class ssa_refiner_selectivet : public ssa_refinert public: void merge(const reasont &other) { - for(reasont::const_iterator it = other.begin(); - it != other.end(); ++it) + for(reasont::const_iterator it=other.begin(); + it!=other.end(); ++it) { - reason_infot &r = (*this)[it->first]; - r.functions.insert(it->second.functions.begin(), + reason_infot &r=(*this)[it->first]; + r.functions.insert(it->second.functions.begin(), it->second.functions.end()); r.loops.insert(it->second.loops.begin(), it->second.loops.end()); } @@ -51,7 +51,7 @@ class ssa_refiner_selectivet : public ssa_refinert unsigned _max_unwind, ssa_inlinert &_ssa_inliner, reasont &_reason - ) : + ) : ssa_db(_ssa_db), ssa_unwinder(_ssa_unwinder), max_unwind(_max_unwind), @@ -60,9 +60,9 @@ class ssa_refiner_selectivet : public ssa_refinert reason(_reason) {} - virtual bool operator()(); + virtual bool operator()(); virtual unsigned get_unwind() { return unwind; } - + protected: ssa_dbt &ssa_db; ssa_unwindert &ssa_unwinder; diff --git a/src/ssa/ssa_slicer.cpp b/src/ssa/ssa_slicer.cpp index d1eafcb13..6489db818 100644 --- a/src/ssa/ssa_slicer.cpp +++ b/src/ssa/ssa_slicer.cpp @@ -9,173 +9,173 @@ void print_symbols(std::string msg, const find_symbols_sett &symbols) { std::cout << msg << ": " << std::endl; for(find_symbols_sett::const_iterator - s_it=symbols.begin(); s_it!=symbols.end(); s_it++) + s_it=symbols.begin(); s_it!=symbols.end(); s_it++) std::cout << " " << *s_it << std::endl; } void ssa_slicert::operator()(std::list &dest, - const local_SSAt &src) + const local_SSAt &src) { - //collect symbols in assertions + // collect symbols in assertions find_symbols_sett new_symbols; - for(local_SSAt::nodest::const_iterator n_it = src.nodes.begin(); - n_it != src.nodes.end(); n_it++) + for(local_SSAt::nodest::const_iterator n_it=src.nodes.begin(); + n_it!=src.nodes.end(); n_it++) { if(n_it->marked) continue; if(n_it->assertions.empty()) continue; for(local_SSAt::nodet::assertionst::const_iterator - a_it=n_it->assertions.begin(); - a_it!=n_it->assertions.end(); - a_it++) + a_it=n_it->assertions.begin(); + a_it!=n_it->assertions.end(); + a_it++) { - find_symbols(*a_it,new_symbols); + find_symbols(*a_it, new_symbols); } } #ifdef DEBUG - print_symbols("symbols in assertions",new_symbols); + print_symbols("symbols in assertions", new_symbols); #endif if(new_symbols.empty()) return; - //build map symbol -> (definition, constraint set) + // build map symbol -> (definition, constraint set) symbol_mapt symbol_map; - sliced_equalities = 0; - sliced_constraints = 0; - - for(local_SSAt::nodest::const_iterator n_it = src.nodes.begin(); - n_it != src.nodes.end(); n_it++) + sliced_equalities=0; + sliced_constraints=0; + + for(local_SSAt::nodest::const_iterator n_it=src.nodes.begin(); + n_it!=src.nodes.end(); n_it++) { for(local_SSAt::nodet::equalitiest::const_iterator - e_it=n_it->equalities.begin(); + e_it=n_it->equalities.begin(); e_it!=n_it->equalities.end(); e_it++) { find_symbols_sett e_symbols; - find_symbols(e_it->lhs(),e_symbols); + find_symbols(e_it->lhs(), e_symbols); for(find_symbols_sett::const_iterator - s_it=e_symbols.begin(); s_it!=e_symbols.end(); s_it++) + s_it=e_symbols.begin(); s_it!=e_symbols.end(); s_it++) { - symbol_map[*s_it]; - symbol_map[*s_it].def = e_it; - symbol_map[*s_it].def_node = n_it; + symbol_map[*s_it]; + symbol_map[*s_it].def=e_it; + symbol_map[*s_it].def_node=n_it; } } for(local_SSAt::nodet::constraintst::const_iterator - c_it=n_it->constraints.begin(); + c_it=n_it->constraints.begin(); c_it!=n_it->constraints.end(); c_it++) { find_symbols_sett c_symbols; - find_symbols(*c_it,c_symbols); + find_symbols(*c_it, c_symbols); for(find_symbols_sett::const_iterator - s_it=c_symbols.begin(); s_it!=c_symbols.end(); s_it++) + s_it=c_symbols.begin(); s_it!=c_symbols.end(); s_it++) { - if(symbol_map.find(*s_it)==symbol_map.end()) continue; - symbol_map[*s_it].constraints.push_back(constr_infot()); - constr_infot &constr_info = symbol_map[*s_it].constraints.back(); - constr_info.constr = c_it; - constr_info.node = n_it; + if(symbol_map.find(*s_it)==symbol_map.end()) continue; + symbol_map[*s_it].constraints.push_back(constr_infot()); + constr_infot &constr_info=symbol_map[*s_it].constraints.back(); + constr_info.constr=c_it; + constr_info.node=n_it; } } - //statistics + // statistics if(!n_it->marked) { - sliced_equalities += n_it->equalities.size(); - sliced_constraints += n_it->constraints.size(); + sliced_equalities+=n_it->equalities.size(); + sliced_constraints+=n_it->constraints.size(); } } - //statistics + // statistics std::cout << "Total equalities: " << sliced_equalities - << ", total constraints: " << sliced_constraints << std::endl; + << ", total constraints: " << sliced_constraints << std::endl; - //compute backwards dependencies and add to formula on-the-fly - find_symbols_sett symbols_seen; + // compute backwards dependencies and add to formula on-the-fly + find_symbols_sett symbols_seen; while(!new_symbols.empty()) { - find_symbols_sett old_symbols = new_symbols; - + find_symbols_sett old_symbols=new_symbols; + #ifdef DEBUG - print_symbols("new symbols",new_symbols); + print_symbols("new symbols", new_symbols); #endif - + new_symbols.clear(); for(find_symbols_sett::const_iterator - s_it=old_symbols.begin(); s_it!=old_symbols.end(); s_it++) + s_it=old_symbols.begin(); s_it!=old_symbols.end(); s_it++) { - irep_idt sym = *s_it; + irep_idt sym=*s_it; if(symbols_seen.find(sym)!=symbols_seen.end()) continue; if(symbol_map.find(sym)==symbol_map.end()) { - //handle loopback variables - //here it's getting a bit ugly - std::string sym_str = id2string(sym); - size_t pos1 = sym_str.find("#lb"); - if(pos1==std::string::npos) continue; - size_t pos2 = sym_str.find("%",pos1); - irep_idt basename = sym_str.substr(0,pos1); - std::string unwinder_suffix = ""; - if(pos2 &dest, - const local_SSAt &src); + const local_SSAt &src); - //statistics + // statistics unsigned sliced_equalities; unsigned sliced_constraints; protected: - typedef struct + typedef struct { local_SSAt::nodet::constraintst::const_iterator constr; local_SSAt::nodest::const_iterator node; } constr_infot; typedef std::list constraint_sett; - typedef struct + typedef struct { local_SSAt::nodet::equalitiest::const_iterator def; local_SSAt::nodest::const_iterator def_node; constraint_sett constraints; } symbol_infot; - typedef hash_map_cont symbol_mapt; + typedef hash_map_cont symbol_mapt; }; diff --git a/src/ssa/ssa_unwinder.cpp b/src/ssa/ssa_unwinder.cpp index 1dece3d90..d489cec52 100644 --- a/src/ssa/ssa_unwinder.cpp +++ b/src/ssa/ssa_unwinder.cpp @@ -138,8 +138,8 @@ void ssa_local_unwindert::build_pre_post_map() const ssa_domaint::phi_nodest &phi_nodes= SSA.ssa_analysis[pre_loc].phi_nodes; for(local_SSAt::objectst::const_iterator o_it= - SSA.ssa_objects.objects.begin(); - o_it!=SSA.ssa_objects.objects.end(); o_it++) + SSA.ssa_objects.objects.begin(); + o_it!=SSA.ssa_objects.objects.end(); o_it++) { ssa_domaint::phi_nodest::const_iterator p_it=phi_nodes.find( o_it->get_identifier()); @@ -189,8 +189,8 @@ void ssa_local_unwindert::build_exit_conditions() // need disjunction of all exit conditions // for each symbol name at exit location for(exprt::operandst::const_iterator - s_it=it->second.modified_vars.begin(); - s_it!=it->second.modified_vars.end(); s_it++) + s_it=it->second.modified_vars.begin(); + s_it!=it->second.modified_vars.end(); s_it++) { exprt e=SSA.read_rhs(*s_it, n_it->location); it->second.exit_map[e].push_back(and_exprt(g, c)); @@ -211,8 +211,8 @@ void ssa_local_unwindert::build_exit_conditions() exprt g=SSA.guard_symbol(n_it->location); exprt c=SSA.cond_symbol(n_it->location); for(exprt::operandst::const_iterator - s_it=it->second.modified_vars.begin(); - s_it!=it->second.modified_vars.end(); s_it++) + s_it=it->second.modified_vars.begin(); + s_it!=it->second.modified_vars.end(); s_it++) { exprt e=SSA.read_rhs(*s_it, n_it->location); it->second.exit_map[e].push_back( @@ -254,7 +254,7 @@ void ssa_local_unwindert::build_exit_conditions() if(n_it==prev) --prev; for(local_SSAt::nodet::assertionst::const_iterator a_it= - n_it->assertions.begin(); a_it!=n_it->assertions.end(); a_it++) + n_it->assertions.begin(); a_it!=n_it->assertions.end(); a_it++) { h_it->second.assertions.push_back(*a_it); } @@ -267,9 +267,9 @@ void ssa_local_unwindert::build_exit_conditions() * * Function : ssa_local_unwindert::unwind_loop_at_location() * - * Input : + * Input : * - * Output : + * Output : * * Purpose : unwind the loop at the given location, up to k starting from * previous unwindings @@ -279,8 +279,8 @@ void ssa_local_unwindert::build_exit_conditions() unsigned ssa_local_unwindert::unwind_loop_at_location(unsigned loc) { - unsigned k = loops.at(loc).current_unwinding+1; - unwind_loop_at_location(loc,k); + unsigned k=loops.at(loc).current_unwinding+1; + unwind_loop_at_location(loc, k); return k; } @@ -289,35 +289,35 @@ void ssa_local_unwindert::unwind_loop_at_location(unsigned loc, unsigned k) if(SSA.current_unwinding>=(long)k) return; - loopt &loop = loops[loc]; - loop.loop_enabling_exprs.push_back(symbol_exprt("unwind$"+id2string(fname)+"$loc"+i2string(loc)+"$enable"+i2string(k),bool_typet())); + loopt &loop=loops[loc]; + loop.loop_enabling_exprs.push_back(symbol_exprt("unwind$"+id2string(fname)+"$loc"+i2string(loc)+"$enable"+i2string(k), bool_typet())); - //current_enabling_expr = + // current_enabling_expr= // symbol_exprt("unwind::"+id2string(fname)+"::enable"+i2string(k), // bool_typet()); - //SSA.enabling_exprs.push_back(current_enabling_expr); + // SSA.enabling_exprs.push_back(current_enabling_expr); - - SSA.current_unwinding=k; //TODO: just for exploratory integration, must go away - //recursively unwind everything + + SSA.current_unwinding=k; // TODO: just for exploratory integration, must go away + // recursively unwind everything SSA.current_unwindings.clear(); - for(loop_mapt::iterator it = loops.begin(); it != loops.end(); ++it){ + for(loop_mapt::iterator it=loops.begin(); it!=loops.end(); ++it){ if(!it->second.is_root) continue; - if(it->first == loc) - unwind(it->second,k,false,false); //recursive + if(it->first==loc) + unwind(it->second, k, false, false); // recursive else - unwind(it->second,it->second.current_unwinding,false,true,k,loc); //recursive - + unwind(it->second, it->second.current_unwinding, false, true, k, loc); // recursive + assert(SSA.current_unwindings.empty()); } - - //update current unwinding - for(loop_mapt::iterator it = loops.begin(); it != loops.end(); ++it) + + // update current unwinding + for(loop_mapt::iterator it=loops.begin(); it!=loops.end(); ++it) { - if(it->first == loc) + if(it->first==loc) it->second.current_unwinding=k; } @@ -341,13 +341,13 @@ void ssa_local_unwindert::unwind(unsigned k) { if(SSA.current_unwinding>=(long)k) return; - + current_enabling_expr= symbol_exprt("unwind$"+id2string(fname)+"$enable"+i2string(k), bool_typet()); - for(loop_mapt::iterator it = loops.begin(); it != loops.end(); ++it) + for(loop_mapt::iterator it=loops.begin(); it!=loops.end(); ++it) { - it->second.loop_enabling_exprs.push_back(symbol_exprt("unwind$"+id2string(fname)+"$loc"+i2string(it->first)+"$enable"+i2string(k),bool_typet())); + it->second.loop_enabling_exprs.push_back(symbol_exprt("unwind$"+id2string(fname)+"$loc"+i2string(it->first)+"$enable"+i2string(k), bool_typet())); } // TODO: just for exploratory integration, must go away @@ -359,8 +359,8 @@ void ssa_local_unwindert::unwind(unsigned k) { if(!it->second.is_root) continue; - //unwind(it->second,k,false,false); //recursive - unwind(it->second, k, false, true, k, 0, true); //recursive + // unwind(it->second, k, false, false); // recursive + unwind(it->second, k, false, true, k, 0, true); // recursive assert(SSA.current_unwindings.empty()); } // update current unwinding @@ -386,8 +386,8 @@ Function: ssa_local_unwindert::unwind \*******************************************************************/ void ssa_local_unwindert::unwind(loopt &loop, unsigned k, bool is_new_parent, - bool propagate, unsigned prop_unwind, - unsigned prop_loc, bool propagate_all) + bool propagate, unsigned prop_unwind, + unsigned prop_loc, bool propagate_all) { odometert context=SSA.current_unwindings; #ifdef DEBUG @@ -450,34 +450,46 @@ void ssa_local_unwindert::unwind(loopt &loop, unsigned k, bool is_new_parent, #ifdef DEBUG std::cout << i << ">" << loop.current_unwinding << std::endl; #endif - if(propagate_all == true){ - unwind(loops[*l_it],k,i>loop.current_unwinding || - is_new_parent,false); + if(propagate_all==true) + { + unwind( + loops[l], k, i>loop.current_unwinding || is_new_parent, false); } else{ - if(propagate == true){ - // if this child loop is the desired loop then unwind k and do not propagate - // else unwind loop.current_unwinding and propagate - if(*l_it == prop_loc){ - unwind(loops[*l_it],k,i>loop.current_unwinding || - is_new_parent,false); - } - else{ - unwind(loops[*l_it],loops[*l_it].current_unwinding,i>loop.current_unwinding || - is_new_parent,true,prop_unwind,prop_loc); - } - } - else{ - unwind(loops[*l_it],loops[*l_it].current_unwinding, - i>loop.current_unwinding || is_new_parent,false); - } + if(propagate==true) + { + // if this child loop is the desired loop then unwind k and do not propagate + // else unwind loop.current_unwinding and propagate + if(l==prop_loc) + { + unwind( + loops[l], k, i>loop.current_unwinding || is_new_parent, false); + } + else{ + unwind( + loops[l], + loops[l].current_unwinding, + i>loop.current_unwinding || is_new_parent, + true, + prop_unwind, + prop_loc); + } + } + else + { + unwind( + loops[l], + loops[l].current_unwinding, + i>loop.current_unwinding || is_new_parent, + false); + } } } SSA.increment_unwindings(0); } SSA.increment_unwindings(-1); #if 0 - std::cout << "calling add_exit_merge with k = " << k << "\n"; + std::cout << "calling add_exit_merge with k=" << k << "\n"; #endif add_exit_merges(loop, k); } @@ -514,18 +526,18 @@ void ssa_local_unwindert::add_loop_body(loopt &loop) node.loophead=SSA.nodes.end(); node.marked=false; for(local_SSAt::nodet::equalitiest::iterator e_it= - node.equalities.begin(); e_it!=node.equalities.end(); e_it++) + node.equalities.begin(); e_it!=node.equalities.end(); e_it++) { SSA.rename(*e_it, node.location); } for(local_SSAt::nodet::constraintst::iterator c_it= - node.constraints.begin(); c_it!=node.constraints.end(); c_it++) + node.constraints.begin(); c_it!=node.constraints.end(); c_it++) { SSA.rename(*c_it, node.location); } for(local_SSAt::nodet::function_callst::iterator f_it= - node.function_calls.begin(); - f_it!=node.function_calls.end(); f_it++) + node.function_calls.begin(); + f_it!=node.function_calls.end(); f_it++) { SSA.rename(*f_it, node.location); } @@ -560,7 +572,7 @@ void ssa_local_unwindert::add_assertions(loopt &loop, bool is_last) node.assertions=it->assertions; SSA.current_location=node.location; // TODO: must go away for(local_SSAt::nodet::assertionst::iterator a_it= - node.assertions.begin(); a_it!=node.assertions.end(); a_it++) + node.assertions.begin(); a_it!=node.assertions.end(); a_it++) { SSA.rename(*a_it, node.location); if(!is_last) // only add assumptions if we are not in %0 iteration @@ -607,7 +619,7 @@ void ssa_local_unwindert::add_loop_head(loopt &loop) node.marked=false; node.enabling_expr=current_enabling_expr; for(local_SSAt::nodet::equalitiest::iterator e_it= - node.equalities.begin(); e_it!=node.equalities.end(); e_it++) + node.equalities.begin(); e_it!=node.equalities.end(); e_it++) { SSA.rename(*e_it, node.location); } @@ -640,8 +652,8 @@ void ssa_local_unwindert::add_loop_connector(loopt &loop) local_SSAt::nodet &node=SSA.nodes.back(); SSA.current_location=node.location; // TODO: must go away for(local_SSAt::nodet::equalitiest::const_iterator e_it= - orig_node.equalities.begin(); - e_it!=orig_node.equalities.end(); e_it++) + orig_node.equalities.begin(); + e_it!=orig_node.equalities.end(); e_it++) { if(e_it->rhs().id()==ID_if) { @@ -689,10 +701,10 @@ void ssa_local_unwindert::add_exit_merges(loopt &loop, unsigned k) SSA.nodes.push_back(local_SSAt::nodet(loop.body_nodes.begin()->location, SSA.nodes.end())); // add new node local_SSAt::nodet &node=SSA.nodes.back(); -(??) node.enabling_expr = current_enabling_expr; + node.enabling_expr=current_enabling_expr; for(loopt::exit_mapt::const_iterator x_it=loop.exit_map.begin(); - x_it!=loop.exit_map.end(); x_it++) + x_it!=loop.exit_map.end(); x_it++) { node.equalities.push_back( build_exit_merge( @@ -786,16 +798,16 @@ void ssa_local_unwindert::add_hoisted_assertions(loopt &loop, bool is_last) void ssa_local_unwindert::compute_enable_expr() { SSA.enabling_exprs.clear(); - for(loop_mapt::const_iterator it = loops.begin(); it != loops.end(); ++it) + for(loop_mapt::const_iterator it=loops.begin(); it!=loops.end(); ++it) { - for(exprt::operandst::const_iterator - e_it = ((it->second).loop_enabling_exprs).begin(); - e_it != ((it->second).loop_enabling_exprs).end(); e_it++) + for(exprt::operandst::const_iterator + e_it=((it->second).loop_enabling_exprs).begin(); + e_it!=((it->second).loop_enabling_exprs).end(); e_it++) { - exprt::operandst::const_iterator lh = e_it; lh++; - if(lh != ((it->second).loop_enabling_exprs).end()) + exprt::operandst::const_iterator lh=e_it; lh++; + if(lh!=((it->second).loop_enabling_exprs).end()) SSA.enabling_exprs.push_back(not_exprt(*e_it)); - else + else SSA.enabling_exprs.push_back(*e_it); } } @@ -817,72 +829,41 @@ Function: ssa_local_unwindert::loop_continuation_conditions void ssa_local_unwindert::loop_continuation_conditions( exprt::operandst& loop_cont) const { - //clear old ones - for(loop_mapt::iterator it = loops.begin(); it != loops.end(); ++it) - { - it->second.current_continuation_conditions.clear(); - } - //compute new SSA.current_unwindings.clear(); - for(loop_mapt::const_iterator it=loops.begin(); it!=loops.end(); ++it) + for(const auto &l : loops) { - if(!it->second.is_root) + if(l.second.is_root) continue; - loop_continuation_conditions(it->second, loop_cont); // recursive + loop_continuation_conditions(l.second, loop_cont); // recursive assert(SSA.current_unwindings.empty()); } } -/*****************************************************************************\ - * - * Function : ssa_local_unwindert::loop_continuation_conditions - * - * Input : - * - * Output : - * - * Purpose : return loop continuation conditions for all loops in this function - * - *****************************************************************************/ +/*******************************************************************\ -void ssa_local_unwindert::loop_continuation_conditions( - exprt::operandst &loop_cont) const -{ - for(loop_mapt::const_iterator it = loops.begin(); it != loops.end(); ++it) - { - loop_cont.insert(loop_cont.end(), - it->second.current_continuation_conditions.begin(), - it->second.current_continuation_conditions.end()); - } -} +Function: ssa_local_unwindert::loop_continuation_conditions -/*****************************************************************************\ - * - * Function : ssa_local_unwindert::loop_continuation_conditions - * - * Input : - * - * Output : - * - * Purpose : return loop continuation conditions for all instances - * of the given loop in this function - * - *****************************************************************************/ + Inputs: + + Outputs: + + Purpose: return loop continuation conditions for all instances + of the given loop in this function + +\*******************************************************************/ void ssa_local_unwindert::loop_continuation_conditions( - const locationt& loop_id, + const locationt& loop_id, exprt::operandst &loop_cont) const { - if(loops.empty()) //ignore silently, TBD + if(loops.empty()) // ignore silently, TBD return; - const loopt &loop = loops.at(loop_id->location_number); - loop_cont.insert(loop_cont.end(), + const loopt &loop=loops.at(loop_id->location_number); + loop_cont.insert(loop_cont.end(), loop.current_continuation_conditions.begin(), loop.current_continuation_conditions.end()); } - - /*******************************************************************\ Function: ssa_local_unwindert::get_continuation_condition @@ -921,7 +902,7 @@ void ssa_local_unwindert::loop_continuation_conditions( loop_cont.push_back(get_continuation_condition(loop)); // %0 for(long i=0; i<=loop.current_unwinding; ++i) { - // recurse into child loops + // recur into child loops for(const auto &l : loop.loop_nodes) { loop_continuation_conditions(loops.at(l), loop_cont); @@ -1005,8 +986,8 @@ void ssa_local_unwindert::unwinder_rename( void ssa_unwindert::unwind_loop_alone(const irep_idt fname, unsigned loc, unsigned int k) { assert(is_initialized); - unwinder_mapt::iterator it = unwinder_map.find(fname); - assert(it != unwinder_map.end()); + unwinder_mapt::iterator it=unwinder_map.find(fname); + assert(it!=unwinder_map.end()); it->second.unwind_loop_at_location(loc, k); } @@ -1025,8 +1006,8 @@ void ssa_unwindert::unwind_loop_alone(const irep_idt fname, unsigned loc, unsign unsigned ssa_unwindert::unwind_loop_once_more(const irep_idt fname, unsigned loc) { assert(is_initialized); - unwinder_mapt::iterator it = unwinder_map.find(fname); - assert(it != unwinder_map.end()); + unwinder_mapt::iterator it=unwinder_map.find(fname); + assert(it!=unwinder_map.end()); return it->second.unwind_loop_at_location(loc); } @@ -1117,9 +1098,10 @@ void ssa_unwindert::init(bool is_kinduction, bool is_bmc) ssa_dbt::functionst& funcs=ssa_db.functions(); for(auto &f : funcs) { - unwinder_map.insert(unwinder_pairt( - f.first, - ssa_local_unwindert(f.first, (*(f.second)), is_kinduction, is_bmc))); + unwinder_map.insert( + unwinder_pairt( + f.first, + ssa_local_unwindert(f.first, (*(f.second)), is_kinduction, is_bmc))); } } diff --git a/src/ssa/ssa_unwinder.h b/src/ssa/ssa_unwinder.h index c20dbc280..673756af8 100644 --- a/src/ssa/ssa_unwinder.h +++ b/src/ssa/ssa_unwinder.h @@ -46,10 +46,9 @@ class ssa_local_unwindert // TODO: this should be loop specific in future, // maybe move to unwindable_local_ssa as it is not really unwinder related - void compute_loop_continuation_conditions(); void compute_enable_expr(); void loop_continuation_conditions(exprt::operandst &loop_cont) const; - void loop_continuation_conditions(const locationt& loop_id, + void loop_continuation_conditions(const locationt& loop_id, exprt::operandst &loop_cont) const; #if 0 @@ -59,13 +58,10 @@ class ssa_local_unwindert symbol_exprt &var, const local_SSAt::nodet &node, bool pre) const; #endif - //TODO: this must go away, should use SSA.rename instead + // TODO: this must go away, should use SSA.rename instead void unwinder_rename(symbol_exprt &var, - const local_SSAt::nodet &node, bool pre) const; -protected: - const irep_idt fname; - unwindable_local_SSAt& SSA; - bool is_kinduction,is_bmc; + + const local_SSAt::nodet &node, bool pre) const; class loopt // loop tree { @@ -123,9 +119,9 @@ class ssa_local_unwindert void build_exit_conditions(); void unwind(loopt &loop, unsigned k, bool is_new_parent, - bool propagate = false, unsigned prop_unwind = 0, - unsigned prop_loc = 0, bool propagate_all = false); - + bool propagate=false, unsigned prop_unwind=0, + unsigned prop_loc=0, bool propagate_all=false); + exprt get_continuation_condition(const loopt& loop) const; void loop_continuation_conditions( const loopt& loop, exprt::operandst &loop_cont) const; @@ -154,7 +150,7 @@ class ssa_unwindert:public messaget void init(bool is_kinduction, bool is_bmc); void init_localunwinders(); - + void unwind_loop_alone(const irep_idt fname, unsigned loc, unsigned k); unsigned unwind_loop_once_more(const irep_idt fname, unsigned loc); void unwind(const irep_idt fname, unsigned k); diff --git a/src/ssa/ssa_value_set.cpp b/src/ssa/ssa_value_set.cpp index 315bd1539..aa362160e 100644 --- a/src/ssa/ssa_value_set.cpp +++ b/src/ssa/ssa_value_set.cpp @@ -289,7 +289,8 @@ void ssa_value_domaint::assign_rhs_rec( if(m_it!=value_map.end()) { valuest tmp_values=m_it->second; -(??) + if(offset) + tmp_values.offset=true; tmp_values.alignment=merge_alignment(tmp_values.alignment, alignment); dest.merge(tmp_values); } diff --git a/src/ssa/unwindable_local_ssa.cpp b/src/ssa/unwindable_local_ssa.cpp index c8807ba35..28589b88a 100644 --- a/src/ssa/unwindable_local_ssa.cpp +++ b/src/ssa/unwindable_local_ssa.cpp @@ -279,11 +279,11 @@ Function: unwindable_local_SSAt::rename void unwindable_local_SSAt::rename(exprt &expr, locationt current_loc) { - if (expr.id() == ID_function_application) + if (expr.id()==ID_function_application) { - std::string unwind_suffix = odometer_to_string(current_unwindings, - current_unwindings.size()); - expr.set(ID_suffix,unwind_suffix); + std::string unwind_suffix=odometer_to_string(current_unwindings, + current_unwindings.size()); + expr.set(ID_suffix, unwind_suffix); } if(expr.id()==ID_symbol) { @@ -298,7 +298,7 @@ void unwindable_local_SSAt::rename(exprt &expr, locationt current_loc) std::string unwind_suffix= odometer_to_string(current_unwindings, def_level); s.set_identifier(id2string(id)+unwind_suffix); - s.set(ID_suffix,unwind_suffix); + s.set(ID_suffix, unwind_suffix); #if 0 std::cout << "DEF_LOC: " << def_loc->location_number << std::endl; std::cout << "DEF_LEVEL: " << def_level << std::endl; @@ -313,9 +313,9 @@ void unwindable_local_SSAt::rename(exprt &expr, locationt current_loc) { std::string unwind_suffix= odometer_to_string(current_unwindings, current_unwindings.size()); - expr.set(ID_suffix,unwind_suffix); - expr.set(ID_identifier, - id2string(expr.get(ID_identifier))+unwind_suffix+suffix); + expr.set(ID_suffix, unwind_suffix); + expr.set(ID_identifier, + id2string(expr.get(ID_identifier))+unwind_suffix+suffix); } Forall_operands(it, expr) rename(*it, current_loc); diff --git a/src/storefront/data.cpp b/src/storefront/data.cpp index 391a40991..b9f9b5d68 100644 --- a/src/storefront/data.cpp +++ b/src/storefront/data.cpp @@ -57,7 +57,7 @@ void datat::read(const xmlt &xml) if(it->name=="property") { propertyt property; - + for(xmlt::elementst::const_iterator e_it=it->elements.begin(); e_it!=it->elements.end(); @@ -72,7 +72,7 @@ void datat::read(const xmlt &xml) else if(e_it->name=="message") property.message=e_it->data; } - + properties.push_back(property); } else if(it->name=="description") diff --git a/src/storefront/data.h b/src/storefront/data.h index 046c58ceb..c2813ae64 100644 --- a/src/storefront/data.h +++ b/src/storefront/data.h @@ -25,14 +25,14 @@ class datat typedef std::vector propertiest; propertiest properties; - + std::string description; inline void add(const propertyt &e) { properties.push_back(e); } - + void read(const std::string &file); void read(const class xmlt &); }; diff --git a/src/storefront/file_view.cpp b/src/storefront/file_view.cpp index a20041d77..1370cd7f4 100644 --- a/src/storefront/file_view.cpp +++ b/src/storefront/file_view.cpp @@ -44,7 +44,7 @@ void print_file(const datat &data, irep_idt file, std::ostream &out) { // line to property number std::map > line_map; - + for(datat::propertiest::const_iterator e_it=data.properties.begin(); e_it!=data.properties.end(); @@ -53,7 +53,7 @@ void print_file(const datat &data, irep_idt file, std::ostream &out) { line_map[e_it->line].push_back(e_it-data.properties.begin()); } - + syntax_highlightingt syntax_highlighting(out); unsigned line_no=1; @@ -63,20 +63,20 @@ void print_file(const datat &data, irep_idt file, std::ostream &out) { syntax_highlighting.strong_class=""; syntax_highlighting.line_no=line_no; - + std::vector &properties=line_map[line_no]; - + if(!properties.empty()) { syntax_highlighting.strong_class="alarm"; } - + syntax_highlighting(line); - + line_no++; } } - + out << "\n\n"; } @@ -98,7 +98,7 @@ void file_view(const datat &data) out << "\n\n"; out << "" << html_escape(data.description) << "\n"; - + out << "\n"; out << "\n"; - + out << "\n"; - - out << "
\n"; - + + out << "
\n"; + out << "
\n"; out << html_escape(data.description) << "\n"; out << "
\n"; - + std::set files; - + for(datat::propertiest::const_iterator e_it=data.properties.begin(); e_it!=data.properties.end(); @@ -136,12 +136,12 @@ void file_view(const datat &data) { if(has_prefix(id2string(*f_it), "/usr/include/")) continue; - + if(has_prefix(id2string(*f_it), "")) continue; - + print_file(data, *f_it, out); } - + out << "\n\n"; } diff --git a/src/storefront/storefront_main.cpp b/src/storefront/storefront_main.cpp index 3914e4dbd..6787c27cc 100644 --- a/src/storefront/storefront_main.cpp +++ b/src/storefront/storefront_main.cpp @@ -1,6 +1,6 @@ /*******************************************************************\ -Module: Main Module +Module: Main Module Author: Daniel Kroening, kroening@kroening.com diff --git a/src/storefront/storefront_parse_options.cpp b/src/storefront/storefront_parse_options.cpp index 2cf35655c..e8c566914 100644 --- a/src/storefront/storefront_parse_options.cpp +++ b/src/storefront/storefront_parse_options.cpp @@ -33,7 +33,7 @@ storefront_parse_optionst::storefront_parse_optionst( parse_options_baset(STOREFRONT_OPTIONS, argc, argv) { } - + /*******************************************************************\ Function: storefront_parse_optionst::doit @@ -61,13 +61,13 @@ int storefront_parse_optionst::doit() usage_error(); return 10; } - + // read config datat data; - + for(unsigned i=0; i modifies; std::set reads; diff --git a/src/summarizer/instrument_goto.cpp b/src/summarizer/instrument_goto.cpp index 7cd4b4f3f..e34faf7ba 100644 --- a/src/summarizer/instrument_goto.cpp +++ b/src/summarizer/instrument_goto.cpp @@ -19,18 +19,18 @@ Author: Peter Schrammel local_SSAt::locationt find_loop_by_guard(const local_SSAt &SSA, - const symbol_exprt &guard) + const symbol_exprt &guard) { - std::string gstr = id2string(guard.get_identifier()); - unsigned pos1 = gstr.find("#")+1; - unsigned pos2 = gstr.find("%",pos1); - unsigned n = safe_string2unsigned(gstr.substr(pos1,pos2)); + std::string gstr=id2string(guard.get_identifier()); + unsigned pos1=gstr.find("#")+1; + unsigned pos2=gstr.find("%", pos1); + unsigned n=safe_string2unsigned(gstr.substr(pos1, pos2)); - local_SSAt::nodest::const_iterator n_it =SSA.nodes.begin(); + local_SSAt::nodest::const_iterator n_it=SSA.nodes.begin(); - for(; n_it != SSA.nodes.end(); n_it++) + for(; n_it!=SSA.nodes.end(); n_it++) { - if(n_it->location->location_number == n) { + if(n_it->location->location_number==n) { // find end of loop break; } @@ -48,7 +48,7 @@ void instrument_gotot::instrument_instruction( goto_programt &dest, goto_programt::targett &target) { - + goto_programt::targett where=target; std::cout << "target " << target->type << " : " << target->source_location << std::endl; @@ -59,22 +59,22 @@ void instrument_gotot::instrument_instruction( break; } - + goto_programt tmp; - + goto_programt::targett assumption=tmp.add_instruction(); assumption->make_assumption(expr); assumption->source_location=target->source_location; assumption->source_location.set_comment("invariant generated by 2LS"); - dest.insert_before_swap(where, tmp); + dest.insert_before_swap(where, tmp); #ifdef DEBUG - std::cout << "instrumenting instruction " << std::endl; + std::cout << "instrumenting instruction " << std::endl; #endif - //dest.update(); + // dest.update(); } extern @@ -87,9 +87,9 @@ void instrument_gotot::instrument_body( goto_functionst::goto_functiont &function ) { - //expected format (/\_j g_j) => inv - const exprt &impl = expr.op0(); - exprt inv = expr.op1(); //copy + // expected format (/\_j g_j)=> inv + const exprt &impl=expr.op0(); + exprt inv=expr.op1(); // copy std::cout << "Invariant " << from_expr(inv) << std::endl; @@ -98,12 +98,12 @@ void instrument_gotot::instrument_body( local_SSAt::locationt loc; if(impl.id()==ID_symbol) { - loc = find_loop_by_guard(SSA,to_symbol_expr(impl)); + loc=find_loop_by_guard(SSA, to_symbol_expr(impl)); } else if(impl.id()==ID_and) { assert(impl.op0().id()==ID_symbol); - loc = find_loop_by_guard(SSA,to_symbol_expr(impl.op0())); + loc=find_loop_by_guard(SSA, to_symbol_expr(impl.op0())); } else assert(false); @@ -125,12 +125,12 @@ void instrument_gotot::instrument_function( goto_functionst::goto_functiont &function) { #ifdef DEBUG - std::cout << "instrumenting function " << function_name << std::endl; + std::cout << "instrumenting function " << function_name << std::endl; #endif if(!summary_db.exists(function_name)) return; - + const summaryt summary=summary_db.get(function_name); if(!ssa_db.exists(function_name)) @@ -141,7 +141,7 @@ void instrument_gotot::instrument_function( if(summary.fw_invariant.is_nil()) return; if(summary.fw_invariant.is_true()) return; - //expected format /\_i g_i => inv_i + // expected format /\_i g_i=> inv_i if(summary.fw_invariant.id()==ID_implies) { instrument_body(SSA, summary.fw_invariant, function); @@ -159,21 +159,21 @@ void instrument_gotot::instrument_function( void instrument_gotot::operator()(goto_modelt &goto_model) { - goto_functionst + goto_functionst &goto_functions=goto_model.goto_functions; - - typedef goto_functions_templatet::function_mapt + + typedef goto_functions_templatet::function_mapt function_mapt; - + function_mapt &function_map=goto_functions.function_map; - - for(function_mapt::iterator + + for(function_mapt::iterator fit=function_map.begin(); fit!=function_map.end(); ++fit) - { - instrument_function(fit->first, fit->second); + { + instrument_function(fit->first, fit->second); } goto_model.goto_functions.update(); diff --git a/src/summarizer/instrument_goto.h b/src/summarizer/instrument_goto.h index dbc3a1b41..9a56f4876 100644 --- a/src/summarizer/instrument_goto.h +++ b/src/summarizer/instrument_goto.h @@ -21,10 +21,10 @@ class instrument_gotot:public messaget { public: inline instrument_gotot(optionst &_options, - ssa_dbt &_ssa_db, - summary_dbt &_summary_db): + ssa_dbt &_ssa_db, + summary_dbt &_summary_db): options(_options), - ssa_db(_ssa_db),summary_db(_summary_db) + ssa_db(_ssa_db), summary_db(_summary_db) { } @@ -35,7 +35,7 @@ class instrument_gotot:public messaget ssa_dbt &ssa_db; summary_dbt &summary_db; - + void instrument_function( const irep_idt &function_name, goto_functionst::goto_functiont &function); diff --git a/src/summarizer/preprocessing_util.cpp b/src/summarizer/preprocessing_util.cpp index 0be64ff76..fb8a61a06 100644 --- a/src/summarizer/preprocessing_util.cpp +++ b/src/summarizer/preprocessing_util.cpp @@ -22,15 +22,15 @@ Function: summarizer_parse_optionst::inline_main void summarizer_parse_optionst::inline_main(goto_modelt &goto_model) { - goto_programt &main = goto_model.goto_functions.function_map[ID__start].body; - goto_programt::targett target = main.instructions.begin(); + goto_programt &main=goto_model.goto_functions.function_map[ID__start].body; + goto_programt::targett target=main.instructions.begin(); while(target!=main.instructions.end()) { if(target->is_function_call()) { const code_function_callt &code_function_call= to_code_function_call(target->code); - irep_idt fname = code_function_call.function().get(ID_identifier); + irep_idt fname=code_function_call.function().get(ID_identifier); debug() << "Inlining " << fname << eom; @@ -38,7 +38,7 @@ void summarizer_parse_optionst::inline_main(goto_modelt &goto_model) tmp.copy_from(goto_model.goto_functions.function_map[fname].body); (--tmp.instructions.end())->make_skip(); goto_model.goto_functions.function_map.erase(fname); - + goto_programt::targett next_target(target); target->make_skip(); next_target++; @@ -60,7 +60,7 @@ Function: summarizer_parse_optionst::propagate_constants Outputs: - Purpose: + Purpose: \*******************************************************************/ @@ -69,7 +69,7 @@ void summarizer_parse_optionst::propagate_constants(goto_modelt &goto_model) namespacet ns(goto_model.symbol_table); Forall_goto_functions(f_it, goto_model.goto_functions) { - constant_propagator_ait(f_it->second,ns); + constant_propagator_ait(f_it->second, ns); } } @@ -96,13 +96,13 @@ void summarizer_parse_optionst::nondet_locals(goto_modelt &goto_model) { if(i_it->is_decl()) { - const code_declt& decl = to_code_decl(i_it->code); + const code_declt& decl=to_code_decl(i_it->code); side_effect_expr_nondett nondet(decl.symbol().type()); - goto_programt::targett t = f_it->second.body.insert_after(i_it); + goto_programt::targett t=f_it->second.body.insert_after(i_it); t->make_assignment(); - code_assignt c(decl.symbol(),nondet); + code_assignt c(decl.symbol(), nondet); t->code.swap(c); - t->source_location = i_it->source_location; + t->source_location=i_it->source_location; } } } @@ -123,50 +123,50 @@ Function: goto_unwind void summarizer_parse_optionst::unwind_goto_into_loop(goto_modelt &goto_model, unsigned k) { - typedef std::vector > loopst; + typedef std::vector > loopst; Forall_goto_functions(f_it, goto_model.goto_functions) { goto_programt &body=f_it->second.body; - + loopst loops; Forall_goto_program_instructions(i_it, body) { if(i_it->is_backwards_goto()) { - goto_programt::targett loop_head = i_it->get_target(); - goto_programt::targett loop_exit = i_it; - bool has_goto_into_loop = false; - - goto_programt::targett it = loop_head; + goto_programt::targett loop_head=i_it->get_target(); + goto_programt::targett loop_exit=i_it; + bool has_goto_into_loop=false; + + goto_programt::targett it=loop_head; if(it!=loop_exit) it++; for(; it!=loop_exit; it++) { - for( std::set::iterator - s_it = it->incoming_edges.begin(); + for( std::set::iterator + s_it=it->incoming_edges.begin(); s_it!=it->incoming_edges.end(); ++s_it) { if((*s_it)->is_goto() && - (*s_it)->location_number < loop_head->location_number) + (*s_it)->location_numberlocation_number) { - has_goto_into_loop = true; + has_goto_into_loop=true; break; } } if(has_goto_into_loop) break; } - if(has_goto_into_loop) + if(has_goto_into_loop) { status() << "Unwinding jump into loop" << eom; - loops.push_back(loopst::value_type(++loop_exit,loop_head)); - } + loops.push_back(loopst::value_type(++loop_exit, loop_head)); + } } } - for(loopst::iterator l_it = loops.begin(); l_it != loops.end(); ++l_it) + for(loopst::iterator l_it=loops.begin(); l_it!=loops.end(); ++l_it) { std::vector iteration_points; - unwind(body,l_it->second,l_it->first,k,iteration_points); + unwind(body, l_it->second, l_it->first, k, iteration_points); assert(iteration_points.size()==2); goto_programt::targett t=body.insert_before(l_it->first); t->make_goto(); @@ -193,11 +193,11 @@ void summarizer_parse_optionst::remove_multiple_dereferences(goto_modelt &goto_m { if(expr.id()==ID_member) { - member_exprt &member_expr = to_member_expr(expr); + member_exprt &member_expr=to_member_expr(expr); if(member_expr.compound().id()==ID_dereference) { - dereference_exprt &deref_expr = to_dereference_expr(member_expr.compound()); - remove_multiple_dereferences(goto_model,body,t,deref_expr.pointer(),var_counter,true); + dereference_exprt &deref_expr=to_dereference_expr(member_expr.compound()); + remove_multiple_dereferences(goto_model, body, t, deref_expr.pointer(), var_counter, true); if(deref_seen) { symbolt new_symbol; @@ -206,13 +206,13 @@ void summarizer_parse_optionst::remove_multiple_dereferences(goto_modelt &goto_m new_symbol.base_name=new_symbol.name; new_symbol.pretty_name=new_symbol.name; goto_model.symbol_table.add(new_symbol); - goto_programt::targett t_new = body.insert_before(t); + goto_programt::targett t_new=body.insert_before(t); t_new->make_assignment(); - t_new->code = code_assignt(new_symbol.symbol_expr(),member_expr); - expr = new_symbol.symbol_expr(); - for(std::set::iterator t_it = + t_new->code=code_assignt(new_symbol.symbol_expr(), member_expr); + expr=new_symbol.symbol_expr(); + for(std::set::iterator t_it= t->incoming_edges.begin(); - t_it != t->incoming_edges.end(); ++t_it) + t_it!=t->incoming_edges.end(); ++t_it) { (*t_it)->targets.clear(); (*t_it)->targets.push_back(t_new); @@ -223,17 +223,17 @@ void summarizer_parse_optionst::remove_multiple_dereferences(goto_modelt &goto_m } } else - Forall_operands(o_it,expr) - remove_multiple_dereferences(goto_model,body,t,*o_it,var_counter,deref_seen); + Forall_operands(o_it, expr) + remove_multiple_dereferences(goto_model, body, t, *o_it, var_counter, deref_seen); } else - Forall_operands(o_it,expr) - remove_multiple_dereferences(goto_model,body,t,*o_it,var_counter,deref_seen); + Forall_operands(o_it, expr) + remove_multiple_dereferences(goto_model, body, t, *o_it, var_counter, deref_seen); } void summarizer_parse_optionst::remove_multiple_dereferences(goto_modelt &goto_model) { - unsigned var_counter = 0; + unsigned var_counter=0; namespacet ns(goto_model.symbol_table); Forall_goto_functions(f_it, goto_model.goto_functions) { @@ -259,7 +259,7 @@ void summarizer_parse_optionst::remove_multiple_dereferences(goto_modelt &goto_m i_it, to_code_assign(i_it->code).rhs(), var_counter, false); - } + } } } } diff --git a/src/summarizer/summarizer.cpp b/src/summarizer/summarizer.cpp index 04c170e0f..13f063c2a 100644 --- a/src/summarizer/summarizer.cpp +++ b/src/summarizer/summarizer.cpp @@ -52,7 +52,7 @@ void summarizert::operator()( goto_functionst::function_mapt::const_iterator f_it= goto_model.goto_functions.function_map.find(id); - + if(f_it==goto_model.goto_functions.function_map.end()) throw "function not found"; @@ -76,18 +76,18 @@ void summarizert::summarize( const goto_functionst::function_mapt::const_iterator f_it) { status() << "** Analyzing " << f_it->first << messaget::eom; - + summary_dbt summary_db; - + summary_db.set_message_handler(get_message_handler()); summary_db.read(id2string(f_it->first)); const namespacet ns(goto_model.symbol_table); - + // build SSA progress() << "Building SSA" << messaget::eom; local_SSAt SSA(f_it->second, ns); - + // simplify, if requested if(simplify) { @@ -95,7 +95,7 @@ void summarizert::summarize( ::simplify(SSA, ns); } - + // fixed-point for loops #if 0 progress() << "Fixed-point" << messaget::eom; @@ -103,7 +103,7 @@ void summarizert::summarize( #endif update_function_signature(SSA, summary_db.summary); - + summary_db.write(); } @@ -122,4 +122,4 @@ Function: summarizert::report_statistics() void summarizert::report_statistics() { } - + diff --git a/src/summarizer/summarizer.h b/src/summarizer/summarizer.h index f4cc72785..2979357e3 100644 --- a/src/summarizer/summarizer.h +++ b/src/summarizer/summarizer.h @@ -24,7 +24,7 @@ class summarizert:public messaget fixed_point(false) { } - + bool simplify, fixed_point; void operator()(const goto_modelt &); diff --git a/src/summarizer/summarizer_bw_cex.cpp b/src/summarizer/summarizer_bw_cex.cpp deleted file mode 100644 index 424e11248..000000000 --- a/src/summarizer/summarizer_bw_cex.cpp +++ /dev/null @@ -1,100 +0,0 @@ -/*******************************************************************\ - -Module: Counterexample-based Backward Analysis - -Author: Kumar Madhukar, Peter Schrammel - -\*******************************************************************/ - -#include - -#include -#include -#include -#include -#include - -#include "summarizer_bw_cex.h" -#include "summary_db.h" - -#include "../domains/ssa_analyzer.h" -#include "../domains/template_generator_summary.h" -#include "../domains/template_generator_callingcontext.h" - -#include "../ssa/local_ssa.h" -#include "../ssa/simplify_ssa.h" - - -/*******************************************************************\ - -Function: summarizer_bw_cex_baset::summarize() - - Inputs: - - Outputs: - - Purpose: - -\*******************************************************************/ - -void summarizer_bw_cex_baset::summarize() -{ - assert(false); //unused -} - -/*******************************************************************\ - -Function: summarizer_bw_cex_baset::summarize() - - Inputs: - - Outputs: - - Purpose: - -\*******************************************************************/ - -void summarizer_bw_cex_baset::summarize(const function_namet &function_name) -{ - exprt postcondition = true_exprt(); //initial calling context - - status() << "\nSummarizing function " << function_name << eom; - compute_summary_rec(function_name,postcondition,true); -} - -/*******************************************************************\ - -Function: summarizer_bw_cex_baset::summarize() - - Inputs: - - Outputs: - - Purpose: summarize backwards from given assertion - -\*******************************************************************/ - -void summarizer_bw_cex_baset::summarize(const exprt &_error_assertion) -{ - status() << "\nBackward error analysis..." << eom; - error_assertion = _error_assertion; - - summarize(entry_function); -} - -/*******************************************************************\ - -Function: summarizer_bw_cex_baset::check() - - Inputs: - - Outputs: - - Purpose: - -\*******************************************************************/ - -property_checkert::resultt summarizer_bw_cex_baset::check() -{ - assert(false); -} diff --git a/src/summarizer/summarizer_bw_cex.h b/src/summarizer/summarizer_bw_cex.h deleted file mode 100644 index 8da077347..000000000 --- a/src/summarizer/summarizer_bw_cex.h +++ /dev/null @@ -1,56 +0,0 @@ -/*******************************************************************\ - -Module: Counterexample-based Backward Analysis Base - -Author: Kumar Madhukar, Peter Schrammel - -\*******************************************************************/ - -#ifndef CPROVER_SUMMARIZER_BW_CEX_H -#define CPROVER_SUMMARIZER_BW_CEX_H - -#include -#include -#include -#include "../ssa/ssa_inliner.h" -#include "../ssa/ssa_unwinder.h" -#include "../ssa/ssa_refiner_selective.h" -#include "../ssa/local_ssa.h" -#include "ssa_db.h" - -#include "summarizer_bw.h" - -class summarizer_bw_cex_baset : public summarizer_bwt -{ - public: - typedef ssa_refiner_selectivet::reasont reasont; - - virtual void summarize(); - virtual void summarize(const function_namet &entry_function); - virtual void summarize(const exprt &_error_assertion); - - virtual property_checkert::resultt check(); - virtual void get_reason(reasont &_reason) { _reason.merge(reason); } - - protected: - function_namet entry_function; - function_namet error_function; - exprt error_assertion; - reasont reason; - - explicit summarizer_bw_cex_baset(optionst &_options, - summary_dbt &_summary_db, - ssa_dbt &_ssa_db, - ssa_unwindert &_ssa_unwinder, - ssa_inlinert &_ssa_inliner, - function_namet _entry_function, - function_namet _error_function): - summarizer_bwt(_options,_summary_db,_ssa_db,_ssa_unwinder,_ssa_inliner), - entry_function(_entry_function), - error_function(_error_function) - {} - -}; - - -#endif diff --git a/src/summarizer/summarizer_bw_cex_ai.cpp b/src/summarizer/summarizer_bw_cex_ai.cpp deleted file mode 100644 index 6d676e175..000000000 --- a/src/summarizer/summarizer_bw_cex_ai.cpp +++ /dev/null @@ -1,549 +0,0 @@ -/*******************************************************************\ - -Module: Summarizer for Backward Analysis - -Author: Peter Schrammel - -\*******************************************************************/ - -#include - -#include -#include -#include -#include -#include - -#include "summarizer_bw_cex_ai.h" -#include "summary_db.h" - -#include "../domains/ssa_analyzer.h" -#include "../domains/template_generator_summary.h" -#include "../domains/template_generator_callingcontext.h" - -#include "../domains/disjunctive_analyzer.h" - -#include "../ssa/local_ssa.h" -#include "../ssa/simplify_ssa.h" - - -/*******************************************************************\ - -Function: summarizer_bw_cex_ait::summarize() - - Inputs: - - Outputs: - - Purpose: - -\*******************************************************************/ - -void summarizer_bw_cex_ait::summarize(const function_namet &function_name) -{ - exprt postcondition = true_exprt(); //initial calling context - - status() << "\nSummarizing function " << function_name << eom; - compute_summary_rec(function_name,summaryt::entry_call_site, - postcondition,true); -} - -/*******************************************************************\ - -Function: summarizer_bw_cex_ait::summarize() - - Inputs: - - Outputs: - - Purpose: summarize backwards from given assertion - -\*******************************************************************/ - -void summarizer_bw_cex_ait::summarize(const exprt &_error_assertion) -{ - status() << "\nBackward error analysis (abstract)..." << eom; - error_assertion = _error_assertion; - - summarize(entry_function); -} - -/*******************************************************************\ - -Function: summarizer_bw_cex_ait::check() - - Inputs: - - Outputs: - - Purpose: - -\*******************************************************************/ - -property_checkert::resultt summarizer_bw_cex_ait::check() -{ - property_checkert::resultt result = property_checkert::FAIL; - if(!summary_db.exists(entry_function)) - { - result = property_checkert::UNKNOWN; - } - else - { - const summaryt &summary = summary_db.get(entry_function); - if(summary.error_summaries.empty() || - summary.error_summaries.begin()->second.is_nil() || - summary.error_summaries.begin()->second.is_true()) - result = property_checkert::UNKNOWN; - } - - //we are only complete if we are in the entry function - if(result == property_checkert::UNKNOWN && - entry_function == error_function) - { - incremental_solvert &solver = ssa_db.get_solver(entry_function); - const local_SSAt &ssa = ssa_db.get(entry_function); - ssa_local_unwindert &ssa_local_unwinder = - ssa_unwinder.get(entry_function); - exprt::operandst loophead_selects; - exprt::operandst loop_continues; - get_loophead_selects(ssa, ssa_local_unwinder, - *solver.solver, loophead_selects); - get_loop_continues(ssa, ssa_local_unwinder, loop_continues); - //check whether loops have been fully unwound - bool fully_unwound = - is_fully_unwound(loop_continues,loophead_selects,solver); - status() << "Loops " << (fully_unwound ? "" : "not ") - << "fully unwound" << eom; - - if(fully_unwound) - result = property_checkert::PASS; - } - - return result; -} - -/*******************************************************************\ - -Function: summarizer_bw_cex_ait::compute_summary_rec() - - Inputs: - - Outputs: - - Purpose: - -\*******************************************************************/ - -/*******************************************************************\ - -Function: summarizer_bw_cex_ait::compute_summary_rec() - - Inputs: - - Outputs: - - Purpose: - -\*******************************************************************/ - -void summarizer_bw_cex_ait::compute_summary_rec( - const function_namet &function_name, - const summaryt::call_sitet &call_site, - const exprt &_postcondition, - bool context_sensitive) -{ - local_SSAt &SSA = ssa_db.get(function_name); - - summaryt summary; - if(summary_db.exists(function_name)) - summary = summary_db.get(function_name); - else - { - summary.params = SSA.params; - summary.globals_in = SSA.globals_in; - summary.globals_out = SSA.globals_out; - summary.nondets = SSA.nondets; - } - - // insert assertion - exprt end_guard = SSA.guard_symbol(--SSA.goto_function.body.instructions.end()); - exprt postcondition = implies_exprt(end_guard,_postcondition); - if(function_name == error_function) - { - postcondition = and_exprt(postcondition,not_exprt(error_assertion)); - } - - summary.bw_postcondition = _postcondition; - -#if 0 - debug() << "Postcondition: " << - from_expr(SSA.ns, "", postcondition) << eom; -#endif - - if(_postcondition.is_false()){ - - summary.error_summaries[call_site] = false_exprt(); - - } - else{ - - // recursively compute summaries for function calls - inline_summaries(function_name,SSA,summary, - postcondition,context_sensitive, - true); - - status() << "Analyzing function " << function_name << eom; - - do_summary(function_name,call_site,SSA,summary,summary,postcondition,context_sensitive); - - if(function_name == error_function) - summary.has_assertion = true; - - } - - summary_db.set(function_name,summary); - - { - std::ostringstream out; - out << std::endl << "Summary for function " << function_name << std::endl; - summary_db.get(function_name).output(out,SSA.ns); - debug() << out.str() << eom; - } - -} - -/*******************************************************************\ - -Function: summarizer_bw_cex_ait::do_summary() - - Inputs: - - Outputs: - - Purpose: - -\*******************************************************************/ - -void summarizer_bw_cex_ait::do_summary(const function_namet &function_name, - const summaryt::call_sitet &call_site, - local_SSAt &SSA, - const summaryt &old_summary, - summaryt &summary, - const exprt &postcondition, - bool context_sensitive) -{ - status() << "Computing error summary" << eom; - - // solver - incremental_solvert &solver = ssa_db.get_solver(function_name); - solver.set_message_handler(get_message_handler()); - - //TODO: maybe allow setting this separately on the command line - optionst _options = options; - _options.set_option("intervals",true); - _options.set_option("binsearch-solver",true); - - //TODO: use a template generator without invariants - template_generator_summaryt template_generator( - _options,ssa_db,ssa_unwinder.get(function_name)); - template_generator.set_message_handler(get_message_handler()); - template_generator(solver.next_domain_number(),SSA,false); - - exprt::operandst c; - //add forward information if available - if(!old_summary.fw_precondition.is_nil()) - c.push_back(old_summary.fw_precondition); - if(!old_summary.fw_invariant.is_nil()) - c.push_back(old_summary.fw_invariant); - c.push_back(ssa_inliner.get_summaries(SSA)); //forward summaries - exprt::operandst assert_postcond, noassert_postcond; - // add error summaries for function calls - bool assertion_flag; - assertion_flag = ssa_inliner.get_summaries(SSA,call_site,false, - assert_postcond,noassert_postcond,c); //backward summaries - - assert_postcond.push_back(postcondition); //context - - //add nondet variables from callees to summary.nondets - std::set summary_vars; - find_symbols(conjunction(assert_postcond),summary_vars); - for(std::set::const_iterator it = summary_vars.begin(); - it != summary_vars.end(); ++it) - if(it->id()==ID_nondet_symbol) - summary.nondets.insert(*it); - - // assumptions must hold - for(local_SSAt::nodest::const_iterator - n_it = SSA.nodes.begin(); - n_it != SSA.nodes.end(); - ++n_it) - for(local_SSAt::nodet::assumptionst::const_iterator - a_it = n_it->assumptions.begin(); - a_it != n_it->assumptions.end(); - ++a_it) - c.push_back(*a_it); - - - - -#if 0 - std::cout << from_expr(SSA.ns, "", cc) << std::endl; -#endif - - //TODO: pushing loophead_selects into the solver - - summary.error_summaries[call_site]; - if(!template_generator.empty()) - { - c.push_back(conjunction(assert_postcond)); //with negative information would need: not_exprt - c.push_back(conjunction(noassert_postcond)); //with negative information would need: not_exprt dis - - //std::cout << "unsimplified constraints (if): " << from_expr(SSA.ns, "", conjunction(c)) << "\n\n\n"; - exprt cc = simplify_expr(conjunction(c), SSA.ns); - //exprt cc = conjunction(c); - //std::cout << "simplified constraints passed (if): " << from_expr(SSA.ns, "", cc) << "\n\n\n"; - - /* - ssa_analyzert analyzer; - analyzer.set_message_handler(get_message_handler()); - analyzer(solver,SSA,cc,template_generator); - analyzer.get_result(summary.error_summaries[call_site], - template_generator.inout_vars()); - */ - /**/ - disjunctive_analyzert disjunctive_analyzer; - disjunctive_analyzer.set_message_handler(get_message_handler()); - disjunctive_analyzer(solver,SSA,cc,template_generator, - cc,summary.error_summaries[call_site], - template_generator.inout_vars()); - /**/ - -#if 0 - std::cout << "SUM: " << from_expr(SSA.ns, "", summary.error_summaries[call_site]) << std::endl; -#endif - - - summary.error_summaries[call_site] = - simplify_expr(summary.error_summaries[call_site], SSA.ns); - - -#if 0 - std::cout << "SUM (post simplification): " << from_expr(SSA.ns, "", summary.error_summaries[call_site]) << std::endl; -#endif - - //statistics - /* - solver_instances += analyzer.get_number_of_solver_instances(); - solver_calls += analyzer.get_number_of_solver_calls(); - */ - solver_instances += disjunctive_analyzer.get_number_of_solver_instances(); - solver_calls += disjunctive_analyzer.get_number_of_solver_calls(); - - } - else // TODO: yet another workaround for ssa_analyzer not being able to handle empty templates properly - { - c.push_back(conjunction(assert_postcond)); //with negative information would need: not_exprt - c.push_back(conjunction(noassert_postcond)); //with negative information would need: not_exprt dis - //c.push_back(not_exprt(conjunction(assert_postcond))); - //c.push_back(not_exprt(disjunction(noassert_postcond))); - - //std::cout << "unsimplified constraints (else): " << from_expr(SSA.ns, "", conjunction(c)) << "\n\n\n"; - exprt cc = simplify_expr(conjunction(c), SSA.ns); - //exprt cc = conjunction(c); - //std::cout << "simplified constraints passed (else): " << from_expr(SSA.ns, "", cc) << "\n\n\n"; - - //std::cout << "enabling expressions (else): " << from_expr(SSA.ns, "", SSA.get_enabling_exprs()) << "\n\n\n"; - - solver << SSA; - solver.new_context(); - solver << SSA.get_enabling_exprs(); - solver << cc; - exprt result = true_exprt(); - if(solver()!=decision_proceduret::D_SATISFIABLE) result = false_exprt(); - solver.pop_context(); - summary.error_summaries[call_site] = result; - -#if 0 - std::cout << "SUM: " << from_expr(SSA.ns, "", summary.error_summaries[call_site]) << std::endl; -#endif - } - - summary.error_summaries[call_site] = - simplify_expr((summary.error_summaries[call_site]), SSA.ns); //not_exprt - - summary.has_assertion = assertion_flag; -} - -/*******************************************************************\ - -Function: summarizer_bw_cex_ait::inline_summaries() - - Inputs: - - Outputs: - - Purpose: - -\*******************************************************************/ - -void summarizer_bw_cex_ait::inline_summaries(const function_namet &function_name, - local_SSAt &SSA, - const summaryt &old_summary, - const exprt &postcondition, - bool context_sensitive, - bool sufficient) -{ - for(local_SSAt::nodest::const_iterator n_it = SSA.nodes.end(); - n_it != SSA.nodes.begin(); ) - { - n_it--; - - for(local_SSAt::nodet::function_callst::const_iterator f_it = - n_it->function_calls.begin(); - f_it != n_it->function_calls.end(); f_it++) - { - assert(f_it->function().id()==ID_symbol); //no function pointers - - exprt postcondition_call = true_exprt(); - postcondition_call = compute_calling_context2( - function_name,SSA,old_summary,n_it,f_it,postcondition,sufficient); - - irep_idt fname = to_symbol_expr(f_it->function()).get_identifier(); - status() << "Recursively summarizing function " << fname << eom; - compute_summary_rec(fname,summaryt::call_sitet(n_it->location), - postcondition_call,context_sensitive); - } - } -} - -/*******************************************************************\ - -Function: summarizer_bw_cex_ait::compute_calling_context2() - - Inputs: - - Outputs: - - Purpose: - -\*******************************************************************/ - -exprt summarizer_bw_cex_ait::compute_calling_context2( - const function_namet &function_name, - local_SSAt &SSA, - summaryt old_summary, - local_SSAt::nodest::const_iterator n_it, - local_SSAt::nodet::function_callst::const_iterator f_it, - const exprt &postcondition, - bool sufficient) -{ - assert(f_it->function().id()==ID_symbol); //no function pointers - irep_idt fname = to_symbol_expr(f_it->function()).get_identifier(); - - status() << "Computing calling context for function " << fname << eom; - - // solver - incremental_solvert &solver = ssa_db.get_solver(function_name); - solver.set_message_handler(get_message_handler()); - - //analyze - /* - ssa_analyzert analyzer; - analyzer.set_message_handler(get_message_handler()); - */ - - disjunctive_analyzert disjunctive_analyzer; - disjunctive_analyzer.set_message_handler(get_message_handler()); - - //TODO: maybe allow setting this separately on the command line - optionst _options = options; - _options.set_option("intervals",true); - _options.set_option("binsearch-solver",true); - - //TODO: use a template generator without invariants - template_generator_callingcontextt template_generator( - _options,ssa_db,ssa_unwinder.get(function_name)); - template_generator.set_message_handler(get_message_handler()); - template_generator(solver.next_domain_number(),SSA,n_it,f_it,false); - - // collect globals at call site - std::map - cs_globals_out; - SSA.get_globals(n_it->location,cs_globals_out[f_it],false); - - exprt::operandst c; - - //add forward information if available - if(!old_summary.fw_precondition.is_nil()) - c.push_back(old_summary.fw_precondition); - if(!old_summary.fw_invariant.is_nil()) - c.push_back(old_summary.fw_invariant); - c.push_back(ssa_inliner.get_summaries(SSA)); //forward summaries - - exprt::operandst assert_postcond, noassert_postcond; - // add error summaries for function calls - ssa_inliner.get_summaries(SSA,summaryt::call_sitet(n_it->location),false, - assert_postcond,noassert_postcond,c); //backward summaries - assert_postcond.push_back(postcondition); //context - - - //TODO: pushing loophead_selects into the solver - - // set preconditions - local_SSAt &fSSA = ssa_db.get(fname); - - exprt postcondition_call; - - if(!template_generator.empty()){ - - c.push_back(conjunction(assert_postcond)); //with negative information would need: not_exprt - c.push_back(conjunction(noassert_postcond)); //with negative information would need: not_exprt dis - - /* - analyzer(solver,SSA,conjunction(c),template_generator); - analyzer.get_result(postcondition_call, - template_generator.callingcontext_vars()); - */ - - disjunctive_analyzer(solver,SSA,conjunction(c),template_generator, - conjunction(c), postcondition_call, - template_generator.callingcontext_vars()); - - ssa_inliner.rename_to_callee(f_it, fSSA.params, - cs_globals_out[f_it],fSSA.globals_out, - postcondition_call); - - } - else{ // TODO: yet another workaround for ssa_analyzer not being able to handle empty templates properly - - c.push_back(not_exprt(conjunction(assert_postcond))); - c.push_back(not_exprt(disjunction(noassert_postcond))); - - solver << SSA; - solver.new_context(); - solver << SSA.get_enabling_exprs(); - solver << conjunction(c); - - //std::cout << "passed to solver, else branch, calling context: " << from_expr(SSA.ns, "", conjunction(c)) << "\n\n"; - - postcondition_call = false_exprt(); - if(solver()!=decision_proceduret::D_SATISFIABLE) postcondition_call = true_exprt(); - solver.pop_context(); - } - - debug() << "Backward calling context for " << - from_expr(SSA.ns, "", *f_it) << ": " - << from_expr(SSA.ns, "", postcondition_call) << eom; - - //statistics - /* - solver_instances += analyzer.get_number_of_solver_instances(); - solver_calls += analyzer.get_number_of_solver_calls(); - */ - solver_instances += disjunctive_analyzer.get_number_of_solver_instances(); - solver_calls += disjunctive_analyzer.get_number_of_solver_calls(); - - return postcondition_call; -} - - diff --git a/src/summarizer/summarizer_bw_cex_concrete.h b/src/summarizer/summarizer_bw_cex_concrete.h deleted file mode 100644 index 40b7177dd..000000000 --- a/src/summarizer/summarizer_bw_cex_concrete.h +++ /dev/null @@ -1,77 +0,0 @@ -/*******************************************************************\ - -Module: Simple Counterexample-based Backward Analysis - -Author: Kumar Madhukar, Peter Schrammel - -\*******************************************************************/ - -#ifndef CPROVER_SUMMARIZER_BW_CEX_CONCRETE_H -#define CPROVER_SUMMARIZER_BW_CEX_CONCRETE_H - -#include -#include -#include -#include "../ssa/ssa_inliner.h" -#include "../ssa/ssa_unwinder.h" -#include "../ssa/local_ssa.h" -#include "ssa_db.h" - -#include - -#include "summarizer_bw_cex.h" - -class summarizer_bw_cex_concretet : public summarizer_bw_cex_baset -{ - public: - explicit summarizer_bw_cex_concretet(optionst &_options, - summary_dbt &_summary_db, - ssa_dbt &_ssa_db, - ssa_unwindert &_ssa_unwinder, - ssa_inlinert &_ssa_inliner, - function_namet _entry_function, - function_namet _error_function): - summarizer_bw_cex_baset(_options,_summary_db,_ssa_db, - _ssa_unwinder,_ssa_inliner, - _entry_function,_error_function) - {} - - virtual void summarize(const function_namet &entry_function); - virtual void summarize(const exprt &_error_assertion); - - virtual property_checkert::resultt check(); - - protected: - virtual void compute_summary_rec(const function_namet &function_name, - const summaryt::call_sitet &call_site, - const exprt &postcondition, - bool context_sensitive); - - virtual void inline_summaries(const function_namet &function_name, - local_SSAt &SSA, - const summaryt &old_summary, - const exprt &postcondition, - bool context_sensitive, - bool sufficient); - - virtual void do_summary( - const function_namet &function_name, - const summaryt::call_sitet &call_site, - local_SSAt &SSA, - const summaryt &old_summary, - summaryt &summary, - const exprt &postcondition, - bool context_sensitive); - - virtual exprt compute_calling_context2(const function_namet &function_name, - local_SSAt &SSA, - summaryt old_summary, - local_SSAt::nodest::const_iterator n_it, - local_SSAt::nodet::function_callst::const_iterator f_it, - const exprt &postcondition, - bool sufficient); - -}; - - -#endif diff --git a/src/summarizer/summarizer_bw_cex_wp.cpp b/src/summarizer/summarizer_bw_cex_wp.cpp deleted file mode 100644 index 86b0b6e54..000000000 --- a/src/summarizer/summarizer_bw_cex_wp.cpp +++ /dev/null @@ -1,643 +0,0 @@ -/*******************************************************************\ - -Module: Slicing-based WP Counterexample-based Backward Analysis - -Author: Madhukar Kumar, Peter Schrammel - -\*******************************************************************/ - -#include - -#include -#include -#include -#include -#include - -#include "summary_db.h" - -#include "../domains/ssa_analyzer.h" -#include "../domains/template_generator_summary.h" -#include "../domains/template_generator_callingcontext.h" - -#include "../ssa/local_ssa.h" -#include "../ssa/simplify_ssa.h" -#include "../ssa/ssa_dependency_graph.h" - -#include "summarizer_bw_cex_wp.h" - -/*******************************************************************\ - -Function: summarizer_bw_cex_wpt::summarize() - - Inputs: - - Outputs: - - Purpose: - -\*******************************************************************/ - -void summarizer_bw_cex_wpt::summarize -( - const function_namet &entry_function) -{ - // no dependencies to begin with - find_symbols_sett dependency_set; - - status() << "\nSummarizing function " << entry_function << eom; - compute_summary_rec(entry_function,dependency_set,-1, - summaryt::entry_call_site); -} - -/*******************************************************************\ - -Function: summarizer_bw_cex_wpt::summarize() - - Inputs: - - Outputs: - - Purpose: summarize backwards from given assertion - -\*******************************************************************/ - -void summarizer_bw_cex_wpt::summarize(const exprt &_error_assertion) -{ - status() << "\nBackward error analysis (WP)..." << eom; - error_assertion = _error_assertion; - /* - std::cout << "error assertion: " - << from_expr(ssa_db.get(entry_function).ns, "", error_assertion) - << "\n"; - */ - summarize(entry_function); -} - - -/*******************************************************************\ - -Function: summarizer_bw_cex_wpt::inline_summaries() - - Inputs: - - Outputs: - - Purpose: - -\*******************************************************************/ - -find_symbols_sett summarizer_bw_cex_wpt::inline_summaries -( - const function_namet &function_name, - const find_symbols_sett &dependency_set, - int counter, - exprt &error_summary) -{ - exprt::operandst slice; - - local_SSAt &SSA = ssa_db.get(function_name); - //solver << SSA.get_enabling_exprs(); - - exprt::operandst loophead_selects; - get_loophead_selects(SSA,ssa_unwinder.get(function_name),*solver.solver,loophead_selects); - exprt c = conjunction(loophead_selects); - - //std::cout << "Solver <-- " << function_name << ": (conjunction of loophead_selects):" - // << "\t original info ~ " << from_expr(ssa_db.get(function_name).ns, "", c) << "\n"; - - slice.push_back(c); - ssa_inliner.rename(c, counter); - -#if 0 - std::cout << "Solver <-- " << function_name << ": (conjunction of loophead_selects):" - << "\t renamed info ~ " << from_expr(ssa_db.get(function_name).ns, "", c) << "\n"; -#endif - - solver << c; - - ssa_dependency_grapht &ssa_depgraph = ssa_db.get_depgraph(function_name); - - struct worknodet{ - int node_index; - find_symbols_sett dependency_set; - }; - - worknodet start_node; - start_node.node_index = 0; - start_node.dependency_set = dependency_set; - - typedef std::list worklistt; - worklistt worklist, work_waitlist; - std::vector covered_nodes; - - worklist.push_back(start_node); - - while(!worklist.empty()){ - - /* - std::cout << "worklist: "; - for(worklistt::const_iterator w_it=worklist.begin(); - w_it != worklist.end(); w_it++){ - std::cout << w_it->node_index << " "; - } - std::cout << "\n"; - - std::cout << "\t waitlist: "; - for(worklistt::const_iterator w_it=work_waitlist.begin(); - w_it != work_waitlist.end(); w_it++){ - std::cout << w_it->node_index << " "; - } - std::cout << "\n"; - */ - - worknodet &worknode = worklist.front(); - - //std::cout << "working node: " << function_name << ": " << worknode.node_index << "\n"; - ///////////////////////////////////////////////////////////////////////////////////// - //std::cout << "\t size of dependency set: " << worknode.dependency_set.size() << "\n"; - /* - std::cout << "\t dependency set: "; - for(find_symbols_sett::iterator d_it = worknode.dependency_set.begin(); - d_it != worknode.dependency_set.end(); d_it++){ - std::cout << *d_it; - } - std::cout << "\n\n\n"; - */ - ///////////////////////////////////////////////////////////////////////////////////// - - - // return if the top most node is reached - if(worknode.node_index == ssa_depgraph.top_node_index) - { - find_symbols_sett vars = worknode.dependency_set; - vars.insert(dependency_set.begin(), dependency_set.end()); - error_summary = simplify_summary(SSA.ns, conjunction(slice), vars); - return worknode.dependency_set; - } - - // modify worknode_dependency_set if the node is an assertion - if(ssa_depgraph.depnodes_map[worknode.node_index].is_assertion == true){ - - //std::cout << "\t\t an assertion node\n"; - for(find_symbols_sett::const_iterator d_it = ssa_depgraph.depnodes_map[worknode.node_index].used_symbols.begin(); - d_it != ssa_depgraph.depnodes_map[worknode.node_index].used_symbols.end(); d_it++){ - worknode.dependency_set.insert(*d_it); - } - - ///////////////////////////////////////////////////////////////////////////////////// - /* - std::cout << "\t size of dependency set: " << worknode.dependency_set.size() << "\n"; - - std::cout << "\t dependency set: "; - for(find_symbols_sett::iterator d_it = worknode.dependency_set.begin(); - d_it != worknode.dependency_set.end(); d_it++){ - std::cout << *d_it; - } - std::cout << "\n"; - */ - ///////////////////////////////////////////////////////////////////////////////////// - - - - } - - // if this is a function call - if(ssa_depgraph.depnodes_map[worknode.node_index].is_function_call == true){ - //std::cout << "fcall: working node: " << function_name << ": " << worknode.node_index << "\n"; - irep_idt fname = - to_symbol_expr((to_function_application_expr(ssa_depgraph.depnodes_map[worknode.node_index].node_info)).function()).get_identifier(); - - find_symbols_sett renamed_dependencies; - - ///////////////////////////////////////////////////////////////////////////////////// - /* - std::cout << "\t size of dependency set: " << worknode.dependency_set.size() << "\n"; - - std::cout << "\t dependency set: "; - for(find_symbols_sett::iterator d_it = worknode.dependency_set.begin(); - d_it != worknode.dependency_set.end(); d_it++){ - std::cout << *d_it; - } - std::cout << "\n"; - */ - ///////////////////////////////////////////////////////////////////////////////////// - - for(find_symbols_sett::iterator d_it = worknode.dependency_set.begin(); - d_it != worknode.dependency_set.end(); d_it++){ - irep_idt renamed_id = *d_it; - // detach the '@' symbol if there - ssa_inliner.rename(renamed_id, - ssa_depgraph.depnodes_map[worknode.node_index].rename_counter, false); - renamed_dependencies.insert(renamed_id); - } - - worknode.dependency_set = renamed_dependencies; - - if(!worknode.dependency_set.empty()){ - find_symbols_sett guard_dependencies; - find_symbols(ssa_depgraph.depnodes_map[worknode.node_index].guard, - guard_dependencies); - for(find_symbols_sett::const_iterator d_it = guard_dependencies.begin(); - d_it != guard_dependencies.end(); d_it++){ - worknode.dependency_set.insert(*d_it); - } - } - - ///////////////////////////////////////////////////////////////////////////////////// - /* - std::cout << "\t size of dependency set: " << worknode.dependency_set.size() << "\n"; - - std::cout << "\t dependency set: "; - for(find_symbols_sett::iterator d_it = worknode.dependency_set.begin(); - d_it != worknode.dependency_set.end(); d_it++){ - std::cout << *d_it; - } - std::cout << "\n"; - */ - ///////////////////////////////////////////////////////////////////////////////////// - - worknode.dependency_set = - compute_summary_rec(fname,worknode.dependency_set, - ssa_depgraph.depnodes_map[worknode.node_index].rename_counter,summaryt::call_sitet(ssa_depgraph.depnodes_map[worknode.node_index].location)); - slice.push_back(ssa_depgraph.depnodes_map[worknode.node_index].node_info); - - renamed_dependencies.clear(); - - for(find_symbols_sett::iterator d_it = worknode.dependency_set.begin(); - d_it != worknode.dependency_set.end(); d_it++){ - irep_idt renamed_id = *d_it; - // detach the '@' symbol if there - ssa_inliner.rename(renamed_id, - ssa_depgraph.depnodes_map[worknode.node_index].rename_counter, false); - renamed_dependencies.insert(renamed_id); - } - - worknode.dependency_set = renamed_dependencies; - - if(!worknode.dependency_set.empty()){ - find_symbols_sett guard_dependencies; - find_symbols(ssa_depgraph.depnodes_map[worknode.node_index].guard, guard_dependencies); - for(find_symbols_sett::const_iterator d_it = guard_dependencies.begin(); - d_it != guard_dependencies.end(); d_it++){ - worknode.dependency_set.insert(*d_it); - } - } - - } - - // if the dependency set is non-empty - if(!worknode.dependency_set.empty()){ - exprt worknode_info = ssa_depgraph.depnodes_map[worknode.node_index].node_info; - if(ssa_depgraph.depnodes_map[worknode.node_index].is_assertion == true) - worknode_info = not_exprt(worknode_info); - - if(worknode.node_index != 0){ - if(!(ssa_depgraph.depnodes_map[worknode.node_index].is_function_call)){ - if((ssa_depgraph.depnodes_map[worknode.node_index].is_assertion == false) || - (worknode_info == error_assertion)){ - /* - std::cout << "Solver <-- " << function_name << ": (node) node#:" - << worknode.node_index << "\t original info ~ " - << from_expr((ssa_db.get(function_name)).ns, "", worknode_info) << "\n"; - */ - slice.push_back(worknode_info); - ssa_inliner.rename(worknode_info, counter); -#if 0 - std::cout << "Solver <-- renamed assertion: " << from_expr((ssa_db.get(function_name)).ns, "", worknode_info) << "\n"; - std::cout << "Solver <-- " << function_name << ": (node) node#:" - << worknode.node_index << "\t renamed info ~ " - << from_expr((ssa_db.get(function_name)).ns, "", worknode_info) << "\n"; -#endif - solver << worknode_info; - } - } - else{ - exprt guard_binding = ssa_depgraph.depnodes_map[worknode.node_index].guard; - /* - std::cout << "Solver <-- " << function_name << ": (bind) node#:" - << worknode.node_index << "\t original info ~ " - << from_expr(ssa_db.get(function_name).ns, "", guard_binding) << "\n"; - */ - ssa_inliner.rename(guard_binding, counter); -#if 0 - std::cout << "Solver <-- " << function_name << ": (bind) node#:" - << worknode.node_index << "\t renamed info ~ " - << from_expr(ssa_db.get(function_name).ns, "", guard_binding) << "\n"; -#endif - solver << guard_binding; - slice.push_back(guard_binding); - } - } - } - - // if not a function call and the dependency set is non-empty - if((ssa_depgraph.depnodes_map[worknode.node_index].is_function_call == false) && - (!worknode.dependency_set.empty())){ - - exprt worknode_info = ssa_depgraph.depnodes_map[worknode.node_index].node_info; - if(ssa_depgraph.depnodes_map[worknode.node_index].is_assertion == true) - worknode_info = not_exprt(worknode_info); - - if((ssa_depgraph.depnodes_map[worknode.node_index].is_assertion == false) || - (worknode_info == error_assertion)){ - worknode.dependency_set = - ssa_depgraph.depnodes_map[worknode.node_index].used_symbols; - } - } - - for(ssa_dependency_grapht::annotated_predecessorst::const_iterator - p_it = ssa_depgraph.depnodes_map[worknode.node_index].predecessors.begin(); - p_it != ssa_depgraph.depnodes_map[worknode.node_index].predecessors.end(); - p_it++){ - - ssa_dependency_grapht::annotated_predecessort pred = *p_it; - int pred_node_index = pred.predecessor_node_index; - find_symbols_sett pred_annotation = pred.annotation; - - bool dependencies_merged = false; - for(worklistt::iterator w_it = work_waitlist.begin(); w_it != work_waitlist.end(); w_it++){ - if(w_it->node_index == pred_node_index){ - - dependencies_merged = true; - - for(find_symbols_sett::const_iterator - a_it=pred_annotation.begin(); a_it!=pred_annotation.end(); a_it++) - { - if(worknode.dependency_set.find(*a_it) != worknode.dependency_set.end()){ - if((w_it->dependency_set).find(*a_it) == (w_it->dependency_set).end()){ - (w_it->dependency_set).insert(*a_it); - } - } - } - break; - } - } - - if(dependencies_merged == false){ - worknodet new_worknode; - new_worknode.node_index = pred_node_index; - - for(find_symbols_sett::const_iterator - a_it=pred_annotation.begin(); a_it!=pred_annotation.end(); a_it++) - { - if(worknode.dependency_set.find(*a_it) != worknode.dependency_set.end()) - new_worknode.dependency_set.insert(*a_it); - } - - work_waitlist.push_back(new_worknode); - } - } - -#if 0 - std::cout << function_name << ": worklist: "; - for(worklistt::const_iterator w_it=worklist.begin(); - w_it != worklist.end(); w_it++){ - std::cout << w_it->node_index << " "; - } - std::cout << "\n"; - - - std::cout << "\t" << function_name << ": waitlist: "; - for(worklistt::const_iterator w_it=work_waitlist.begin(); - w_it != work_waitlist.end(); w_it++){ - std::cout << w_it->node_index << " "; - } - std::cout << "\n"; -#endif - - covered_nodes.push_back(worknode.node_index); - worklist.pop_front(); - -#if 0 - std::cout << function_name << ": covered : "; - for(int l = 0; l < covered_nodes.size(); l++){ - std::cout << covered_nodes[l] << " "; - } - std::cout << "\n"; -#endif - - worklistt iterate_work_waitlist = work_waitlist; - work_waitlist.clear(); - - for(worklistt::const_iterator w_it = iterate_work_waitlist.begin(); w_it != iterate_work_waitlist.end(); w_it++){ - worknodet waitlisted_worknode = *w_it; - - bool uncovered_successor = false; - - std::vector &waitlisted_worknode_successors = - ssa_depgraph.depnodes_map[waitlisted_worknode.node_index].successors; - - for(unsigned i = 0; i < waitlisted_worknode_successors.size(); i++){ - bool check_covered = false; - for(unsigned j = 0; j < covered_nodes.size(); j++){ - if(waitlisted_worknode_successors[i] == covered_nodes[j]){ - check_covered = true; - break; - } - } - if(!check_covered){ -#if 0 - std::cout << function_name << ": an uncovered successor of " << waitlisted_worknode.node_index << " : " - << waitlisted_worknode_successors[i] << "\n"; -#endif - uncovered_successor = true; - break; - } - } - - if(!uncovered_successor){ - worklist.push_back(waitlisted_worknode); - } - else{ - work_waitlist.push_back(waitlisted_worknode); - } - - } - } - - /* the following code is to stop a warning; this function must - return from the first if-condition inside the while loop */ - std::cout << "check graph of the function: " << function_name << "\n"; - assert(false); - return dependency_set; -} - -/*******************************************************************\ - -Function: summarizer_bw_cex_wpt::compute_summary_rec() - - Inputs: - - Outputs: - - Purpose: - -\*******************************************************************/ - -find_symbols_sett summarizer_bw_cex_wpt::compute_summary_rec - ( - const function_namet &function_name, - const find_symbols_sett &dependency_set, - int counter, - const summaryt::call_sitet &call_site) -{ - local_SSAt &SSA = ssa_db.get(function_name); - summaryt summary; - if(summary_db.exists(function_name)) - summary = summary_db.get(function_name); - else - { - summary.params = SSA.params; - summary.globals_in = SSA.globals_in; - summary.globals_out = SSA.globals_out; - } - // recursively compute summaries for function calls - find_symbols_sett new_dependency_set = - inline_summaries(function_name,dependency_set,counter, - summary.error_summaries[call_site]); - - summary_db.set(function_name,summary); - - { - std::ostringstream out; - out << std::endl << "Summary for function " << function_name << std::endl; - summary_db.get(function_name).output(out,SSA.ns); - debug() << out.str() << eom; - } - - return new_dependency_set; -} - -/*******************************************************************\ - -Function: summarizer_bw_cex_wpt::check() - - Inputs: - - Outputs: - - Purpose: - -\*******************************************************************/ - -property_checkert::resultt summarizer_bw_cex_wpt::check() -{ - solver_calls++; // for statistics - if(solver() == decision_proceduret::D_SATISFIABLE){ - //std::cout << "Solver <-- renamed info ~ SAT\n"; - return property_checkert::FAIL; - } - //std::cout << "Solver <-- renamed info ~ UNSAT\n"; - return property_checkert::UNKNOWN; -} - -/*******************************************************************\ - -Function: summarizer_bw_cex_wpt::debug_print() - - Inputs: - - Outputs: - - Purpose: - -\*******************************************************************/ - -void summarizer_bw_cex_wpt::debug_print -( - const function_namet &function_name, - find_symbols_sett &dependency_set) -{ - std::cout << "DebugInfo: function -> " << function_name - << " ; dependency_set -> "; - for(find_symbols_sett::iterator d_it = dependency_set.begin(); - d_it != dependency_set.end(); d_it++){ - std::cout << *d_it << ", "; - } - std::cout << "\n"; -} - -/*******************************************************************\ - -Function: summarizer_bw_cex_wpt::simplify_summary() - - Inputs: - - Outputs: - - Purpose: - -\*******************************************************************/ -void summarizer_bw_cex_wpt::simplify_summary_build_map( - replace_mapt &replace_map, const exprt &expr) -{ - if(expr.id()==ID_equal) - { - replace_map[expr.op0()] = expr.op1(); - return; - } - forall_operands(it, expr) - simplify_summary_build_map(replace_map, *it); -} -bool summarizer_bw_cex_wpt::simplify_summary_replace( - const replace_mapt &replace_map, exprt &expr) -{ - if(expr.id()==ID_function_application) - { - bool result = true; - exprt::operandst &args = to_function_application_expr(expr).arguments(); - for(size_t i=0;ifirst)!=excluded_functions.end()) continue; status() << "\nSummarizing function " << it->first << eom; - if(!summary_db.exists(it->first) || - summary_db.get(it->first).mark_recompute) - compute_summary_rec(it->first,precondition,false); - else status() << "Summary for function " << it->first << + if(!summary_db.exists(it->first) || + summary_db.get(it->first).mark_recompute) + compute_summary_rec(it->first, precondition, false); + else status() << "Summary for function " << it->first << " exists already" << eom; } } @@ -70,102 +70,102 @@ Function: summarizer_fw_contextst::inline_summaries() \*******************************************************************/ void summarizer_fw_contextst::inline_summaries( - const function_namet &function_name, - local_SSAt &SSA, const exprt &precondition, - bool context_sensitive) + const function_namet &function_name, + local_SSAt &SSA, const exprt &precondition, + bool context_sensitive) { - for(local_SSAt::nodest::const_iterator n_it = SSA.nodes.begin(); - n_it != SSA.nodes.end(); n_it++) + for(local_SSAt::nodest::const_iterator n_it=SSA.nodes.begin(); + n_it!=SSA.nodes.end(); n_it++) { - for(local_SSAt::nodet::function_callst::const_iterator f_it = - n_it->function_calls.begin(); - f_it != n_it->function_calls.end(); f_it++) + for(local_SSAt::nodet::function_callst::const_iterator f_it= + n_it->function_calls.begin(); + f_it!=n_it->function_calls.end(); f_it++) { - assert(f_it->function().id()==ID_symbol); //no function pointers - if(!check_call_reachable(function_name,SSA,n_it,f_it,precondition,true)) + assert(f_it->function().id()==ID_symbol); // no function pointers + if(!check_call_reachable(function_name, SSA, n_it, f_it, precondition, true)) { - continue; + continue; } - irep_idt fname = to_symbol_expr(f_it->function()).get_identifier(); + irep_idt fname=to_symbol_expr(f_it->function()).get_identifier(); if(excluded_functions.find(fname)!=excluded_functions.end()) { - exprt precondition_call = compute_calling_context( - function_name,SSA,n_it,f_it,precondition,true); - - // output calling context - switch(ui) - { - case ui_message_handlert::PLAIN: - break; - - case ui_message_handlert::XML_UI: - { - xmlt xml_cc("calling-context"); - xml_cc.set_attribute("function",id2string(fname)); - xml_cc.set_attribute("goto_location", - i2string(n_it->location->location_number)); - - //location - const source_locationt &source_location = - n_it->location->source_location; - xmlt xml_location; - if(source_location.is_not_nil() && source_location.get_file()!="") - xml_location=xml(source_location); - if(xml_location.name!="") - xml_cc.new_element().swap(xml_location); - - //argument ranges - xmlt xml_args("argument-ranges"); - assert(precondition_call.operands().size()%2==0); - for(unsigned i=0;ilocation->location_number)); + + // location + const source_locationt &source_location= + n_it->location->source_location; + xmlt xml_location; + if(source_location.is_not_nil() && source_location.get_file()!="") + xml_location=xml(source_location); + if(xml_location.name!="") + xml_cc.new_element().swap(xml_location); + + // argument ranges + xmlt xml_args("argument-ranges"); + assert(precondition_call.operands().size()%2==0); + for(unsigned i=0;i excluded_functions; - virtual void inline_summaries(const function_namet &function_name, - local_SSAt &SSA, - const exprt &precondition, - bool context_sensitive); + virtual void inline_summaries(const function_namet &function_name, + local_SSAt &SSA, + const exprt &precondition, + bool context_sensitive); }; diff --git a/src/summarizer/summarizer_parse_options.cpp b/src/summarizer/summarizer_parse_options.cpp index 15be22a06..d44fac004 100644 --- a/src/summarizer/summarizer_parse_options.cpp +++ b/src/summarizer/summarizer_parse_options.cpp @@ -75,7 +75,7 @@ parse_options_baset(SUMMARIZER_OPTIONS, argc, argv), ui_message_handler(cmdline, "2LS " SUMMARIZER_VERSION) { } - + /*******************************************************************\ Function: summarizer_parse_optionst::eval_verbosity @@ -92,7 +92,7 @@ void summarizer_parse_optionst::eval_verbosity() { // this is our default verbosity int v=messaget::M_STATISTICS; - + if(cmdline.isset("verbosity")) { v=unsafe_string2int(cmdline.get_value("verbosity")); @@ -101,7 +101,7 @@ void summarizer_parse_optionst::eval_verbosity() else if(v>10) v=10; } - + ui_message_handler.set_verbosity(v); } @@ -229,7 +229,7 @@ void summarizer_parse_optionst::get_command_line_options(optionst &options) options.set_option("unit-check", true); else options.set_option("unit-check", false); - + // compute standard invariants (include value at loop entry) if(cmdline.isset("std-invariants")) options.set_option("std-invariants", true); @@ -247,7 +247,7 @@ void summarizer_parse_optionst::get_command_line_options(optionst &options) options.set_option("equalities", true); options.set_option("std-invariants", true); } - else + else { if(cmdline.isset("zones")) options.set_option("zones", true); @@ -255,12 +255,12 @@ void summarizer_parse_optionst::get_command_line_options(optionst &options) options.set_option("qzones", true); else if(cmdline.isset("octagons")) options.set_option("octagons", true); - else //if(cmdline.isset("intervals")) //default + else // if(cmdline.isset("intervals")) // default options.set_option("intervals", true); - if(cmdline.isset("enum-solver")) + if(cmdline.isset("enum-solver")) options.set_option("enum-solver", true); - else //if(cmdline.isset("binsearch-solver")) //default + else // if(cmdline.isset("binsearch-solver")) // default options.set_option("binsearch-solver", true); } @@ -294,17 +294,17 @@ void summarizer_parse_optionst::get_command_line_options(optionst &options) if(cmdline.isset("lexicographic-ranking-function")) { - options.set_option("lexicographic-ranking-function", + options.set_option("lexicographic-ranking-function", cmdline.get_value("lexicographic-ranking-function")); } - else options.set_option("lexicographic-ranking-function",3); + else options.set_option("lexicographic-ranking-function", 3); if(cmdline.isset("max-inner-ranking-iterations")) { - options.set_option("max-inner-ranking-iterations", + options.set_option("max-inner-ranking-iterations", cmdline.get_value("max-inner-ranking-iterations")); } - else options.set_option("max-inner-ranking-iterations",20); + else options.set_option("max-inner-ranking-iterations", 20); // do k-induction refinement if(cmdline.isset("k-induction")) @@ -313,7 +313,7 @@ void summarizer_parse_optionst::get_command_line_options(optionst &options) options.set_option("k-induction", true); // options.set_option("inline", true); if(!cmdline.isset("unwind")) - options.set_option("unwind",UINT_MAX); + options.set_option("unwind", UINT_MAX); } // do incremental bmc @@ -323,7 +323,7 @@ void summarizer_parse_optionst::get_command_line_options(optionst &options) // options.set_option("inline", true); options.set_option("havoc", true); if(!cmdline.isset("unwind")) - options.set_option("unwind",UINT_MAX); + options.set_option("unwind", UINT_MAX); } // check for spuriousness of assertion failures @@ -353,9 +353,9 @@ void summarizer_parse_optionst::get_command_line_options(optionst &options) // instrumentation / output if(cmdline.isset("instrument-output")) - options.set_option("instrument-output", + options.set_option("instrument-output", cmdline.get_value("instrument-output")); - + #ifdef SHOW_CALLING_CONTEXTS if(cmdline.isset("show-calling-contexts")) @@ -363,7 +363,7 @@ void summarizer_parse_optionst::get_command_line_options(optionst &options) if(!options.get_bool_option("intervals")) throw "--show-calling-contexts only possible with --intervals"; options.set_option("show-calling-contexts", true); - options.set_option("do-not-analyze-functions", + options.set_option("do-not-analyze-functions", cmdline.get_value("show-calling-contexts")); } #endif @@ -395,7 +395,7 @@ int summarizer_parse_optionst::doit() std::cout << SUMMARIZER_VERSION " (based on CBMC " CBMC_VERSION ")" << std::endl; return 0; } - + // // command line options // @@ -404,7 +404,7 @@ int summarizer_parse_optionst::doit() get_command_line_options(options); eval_verbosity(); - + // // Print a banner // @@ -427,7 +427,7 @@ int summarizer_parse_optionst::doit() } // options for various debug outputs - + if(cmdline.isset("show-ssa")) { bool simplify=!cmdline.isset("no-simplify"); @@ -464,7 +464,7 @@ int summarizer_parse_optionst::doit() show_guards(goto_model, function, std::cout, ui_message_handler); return 7; } - + if(cmdline.isset("show-value-sets")) { irep_idt function=cmdline.get_value("function"); @@ -472,7 +472,7 @@ int summarizer_parse_optionst::doit() return 7; } - if(cmdline.isset("show-invariants")) + if(cmdline.isset("show-invariants")) { options.set_option("show-invariants", true); } @@ -480,7 +480,7 @@ int summarizer_parse_optionst::doit() if(cmdline.isset("context-sensitive")) { options.set_option("context-sensitive", true); - status() << "Context-sensitive analysis from " << + status() << "Context-sensitive analysis from " << goto_model.goto_functions.entry_point() << eom; } @@ -490,7 +490,7 @@ int summarizer_parse_optionst::doit() status() << "Do not ignore array contents" << eom; } - //TODO: check option inconsistencies, ignored options etc + // TODO: check option inconsistencies, ignored options etc if(options.get_bool_option("havoc")) status() << "Havocking loops and function calls" << eom; else if(options.get_bool_option("equalities")) @@ -511,20 +511,20 @@ int summarizer_parse_optionst::doit() else assert(false); status() << eom; } - + try { - summary_checker_baset *summary_checker = NULL; - if(!options.get_bool_option("k-induction") && + summary_checker_baset *summary_checker=NULL; + if(!options.get_bool_option("k-induction") && !options.get_bool_option("incremental-bmc")) - summary_checker = new summary_checker_ait(options); - if(options.get_bool_option("k-induction") && - !options.get_bool_option("incremental-bmc")) - summary_checker = new summary_checker_kindt(options); - if(!options.get_bool_option("k-induction") && - options.get_bool_option("incremental-bmc")) - summary_checker = new summary_checker_bmct(options); - + summary_checker=new summary_checker_ait(options); + if(options.get_bool_option("k-induction") && + !options.get_bool_option("incremental-bmc")) + summary_checker=new summary_checker_kindt(options); + if(!options.get_bool_option("k-induction") && + options.get_bool_option("incremental-bmc")) + summary_checker=new summary_checker_bmct(options); + summary_checker->set_message_handler(get_message_handler()); summary_checker->simplify=!cmdline.isset("no-simplify"); summary_checker->fixed_point=!cmdline.isset("no-fixed-point"); @@ -543,9 +543,9 @@ int summarizer_parse_optionst::doit() { status() << "Horn-clause encoding" << eom; namespacet ns(symbol_table); - + std::string out_file=cmdline.get_value("horn-encoding"); - + if(out_file=="-") { horn_encoding(goto_model, std::cout); @@ -557,7 +557,7 @@ int summarizer_parse_optionst::doit() #else std::ofstream out(out_file.c_str()); #endif - + if(!out) { error() << "Failed to open output file " @@ -565,44 +565,44 @@ int summarizer_parse_optionst::doit() delete summary_checker; return 1; } - + horn_encoding(goto_model, out); } - + delete summary_checker; return 0; } - - bool report_assertions = + + bool report_assertions= !options.get_bool_option("preconditions") && !options.get_bool_option("termination"); // do actual analysis switch((*summary_checker)(goto_model)) { case property_checkert::PASS: - if(report_assertions) - report_properties(options,goto_model, summary_checker->property_map); + if(report_assertions) + report_properties(options, goto_model, summary_checker->property_map); report_success(); - retval = 0; + retval=0; break; - + case property_checkert::FAIL: - if(report_assertions) - report_properties(options,goto_model, summary_checker->property_map); + if(report_assertions) + report_properties(options, goto_model, summary_checker->property_map); report_failure(); - retval = 10; + retval=10; break; case property_checkert::UNKNOWN: - if(report_assertions) - report_properties(options,goto_model, summary_checker->property_map); - retval = 5; - if(options.get_bool_option("preconditions")) - goto clean_up; + if(report_assertions) + report_properties(options, goto_model, summary_checker->property_map); + retval=5; + if(options.get_bool_option("preconditions")) + goto clean_up; report_properties(goto_model, summary_checker->property_map); report_unknown(); break; - + default: assert(false); } @@ -616,7 +616,7 @@ int summarizer_parse_optionst::doit() delete summary_checker; return retval; } - + catch(const std::string error_msg) { error() << error_msg << messaget::eom; @@ -629,7 +629,7 @@ int summarizer_parse_optionst::doit() return 8; } -#if 0 +#if 0 // let's log some more statistics debug() << "Memory consumption:" << messaget::endl; memory_info(debug()); @@ -647,27 +647,27 @@ void summarizer_parse_optionst::type_stats_rec( if(type.id()==ID_symbol) type_stats_rec(ns.follow(type), stats, ns); - - if(type.id()==ID_pointer || type.id()==ID_array) - { - stats.has_array=true; - - const typet &subtype=ns.follow(type.subtype()); - - if(subtype.id()==ID_signedbv || + + if(type.id()==ID_pointer || type.id()==ID_array) + { + stats.has_array=true; + + const typet &subtype=ns.follow(type.subtype()); + + if(subtype.id()==ID_signedbv || subtype.id()==ID_unsignedbv) { - stats.has_string=(to_bitvector_type(subtype).get_width()==config.ansi_c.char_width); - } - } - + stats.has_string=(to_bitvector_type(subtype).get_width()==config.ansi_c.char_width); + } + } + if(type.has_subtypes()) { - forall_subtypes(it, type) - { - type_stats_rec(*it, stats, ns); - } - } + forall_subtypes(it, type) + { + type_stats_rec(*it, stats, ns); + } + } } @@ -688,7 +688,7 @@ void summarizer_parse_optionst::expr_stats_rec( const exprt &expr, expr_statst &stats) { - + if(expr.id()==ID_side_effect) { const side_effect_exprt &side_effect_expr=to_side_effect_expr(expr); @@ -706,18 +706,18 @@ void summarizer_parse_optionst::expr_stats_rec( if(expr.id()==ID_symbol ) { - + } - + if(expr.has_operands()) { forall_operands(it, expr) { - expr_stats_rec(*it, stats); + expr_stats_rec(*it, stats); } } } - + /*******************************************************************\ @@ -753,7 +753,7 @@ void summarizer_parse_optionst::show_stats(const goto_modelt &goto_model, const goto_programt &goto_program=f_it->second.body; #if 0 - statistics() << "function size of " << f_it->first << ": " + statistics() << "function size of " << f_it->first << ": " << goto_program.instructions.size() << eom; #endif @@ -772,8 +772,8 @@ void summarizer_parse_optionst::show_stats(const goto_modelt &goto_model, case ASSIGN: { const code_assignt &assign=to_code_assign(instruction.code); - expr_stats_rec(assign.lhs(), stats); - expr_stats_rec(assign.rhs(), stats); + expr_stats_rec(assign.lhs(), stats); + expr_stats_rec(assign.rhs(), stats); } break; case ASSUME: @@ -785,13 +785,13 @@ void summarizer_parse_optionst::show_stats(const goto_modelt &goto_model, case GOTO: expr_stats_rec(instruction.guard, stats); break; - + case DECL: // someone declaring an array type_stats_rec(to_code_decl(instruction.code).symbol().type(), stats, ns); - - break; - + + break; + default: // skip break; @@ -799,10 +799,10 @@ void summarizer_parse_optionst::show_stats(const goto_modelt &goto_model, } // forall instructions } // forall functions - out << " =============== STATS =============== " << std::endl; - out << " nr of instructions: " << nr_instructions << std::endl; - out << " nr of functions: " << nr_functions << std::endl; - out << " nr of loops: " << nr_loops << std::endl; + out << "=============== STATS=============== " << std::endl; + out << " nr of instructions: " << nr_instructions << std::endl; + out << " nr of functions: " << nr_functions << std::endl; + out << " nr of loops: " << nr_loops << std::endl; out << " malloc: " << (stats.has_malloc ? "YES" : "NO") << std::endl; out << " arrays: " << (stats.has_array ? "YES" : "NO") << std::endl; out << " strings: " << (stats.has_string ? "YES" : "NO") << std::endl; @@ -840,12 +840,12 @@ bool summarizer_parse_optionst::set_properties(goto_modelt &goto_model) error() << e << eom; return true; } - + catch(int) { return true; } - + return false; } @@ -860,12 +860,12 @@ Function: summarizer_parse_optionst::require_entry Purpose: \*******************************************************************/ - + void summarizer_parse_optionst::require_entry( const goto_modelt &goto_model) { irep_idt entry_point=goto_model.goto_functions.entry_point(); - + if(goto_model.symbol_table.symbols.find(entry_point)==symbol_table.symbols.end()) throw "The program has no entry point; please complete linking"; } @@ -881,7 +881,7 @@ Function: summarizer_parse_optionst::get_goto_program Purpose: \*******************************************************************/ - + bool summarizer_parse_optionst::get_goto_program( const optionst &options, goto_modelt &goto_model) @@ -902,7 +902,7 @@ bool summarizer_parse_optionst::get_goto_program( if(read_goto_binary(cmdline.args[0], goto_model, get_message_handler())) return true; - + config.set_from_symbol_table(goto_model.symbol_table); if(cmdline.isset("show-symbol-table")) @@ -910,9 +910,9 @@ bool summarizer_parse_optionst::get_goto_program( show_symbol_table(); return true; } - + irep_idt entry_point=goto_model.goto_functions.entry_point(); - + if(goto_model.symbol_table.symbols.find(entry_point)==symbol_table.symbols.end()) { error() << "The goto binary has no entry point; please complete linking" << eom; @@ -926,45 +926,45 @@ bool summarizer_parse_optionst::get_goto_program( error() << "Please give one source file only" << eom; return true; } - + std::string filename=cmdline.args[0]; - + #ifdef _MSC_VER std::ifstream infile(widen(filename).c_str()); #else std::ifstream infile(filename.c_str()); #endif - + if(!infile) { error() << "failed to open input file `" << filename << "'" << eom; return true; } - + languaget *language=get_language_from_filename(filename); - + if(language==NULL) { error() << "failed to figure out type of file `" << filename << "'" << eom; return true; } - + language->set_message_handler(get_message_handler()); - + status("Parsing", filename); - + if(language->parse(infile, filename)) { error() << "PARSING ERROR" << eom; return true; } - + language->show_parse(std::cout); return true; } else { - + if(parse()) return true; if(typecheck()) return true; if(final()) return true; @@ -980,14 +980,14 @@ bool summarizer_parse_optionst::get_goto_program( #if 0 irep_idt entry_point=goto_model.goto_functions.entry_point(); - + if(symbol_table.symbols.find(entry_point)==symbol_table.symbols.end()) { error() << "No entry point; please provide a main function" << eom; return true; } #endif - + status() << "Generating GOTO Program" << eom; goto_convert(symbol_table, goto_model, ui_message_handler); @@ -1012,18 +1012,18 @@ bool summarizer_parse_optionst::get_goto_program( error() << e << eom; return true; } - + catch(int) { return true; } - + catch(std::bad_alloc) { error() << "Out of memory" << eom; return true; } - + return false; } @@ -1038,7 +1038,7 @@ Function: summarizer_parse_optionst::process_goto_program Purpose: \*******************************************************************/ - + bool summarizer_parse_optionst::process_goto_program( const optionst &options, goto_modelt &goto_model) @@ -1048,12 +1048,12 @@ bool summarizer_parse_optionst::process_goto_program( // do partial inlining if(options.get_bool_option("inline-partial")) { - unsigned limit = options.get_unsigned_int_option("inline-partial"); + unsigned limit=options.get_unsigned_int_option("inline-partial"); status() << "Performing partial inlining (" << limit << ")" << eom; goto_partial_inline(goto_model, ui_message_handler, limit/2); - //TODO: where is limit multiplied by 2??? + // TODO: where is limit multiplied by 2??? - //remove inlined functions + // remove inlined functions Forall_goto_functions(f_it, goto_model.goto_functions) if(f_it->first!=ID__start && f_it->second.body.instructions.size()<=2*(limit/2)) @@ -1061,7 +1061,7 @@ bool summarizer_parse_optionst::process_goto_program( f_it->second.body.clear(); } } - + // add generic checks status() << "Generic Property Instrumentation" << eom; goto_check(options, goto_model); @@ -1072,10 +1072,10 @@ bool summarizer_parse_optionst::process_goto_program( // remove returns (must be done after function pointer removal) remove_returns(goto_model); - - + + #if UNWIND_GOTO_INTO_LOOP - unwind_goto_into_loop(goto_model,2); + unwind_goto_into_loop(goto_model, 2); #endif remove_skip(goto_model.goto_functions); @@ -1092,15 +1092,15 @@ bool summarizer_parse_optionst::process_goto_program( } } - //preprocessing to improve the structure of the SSA for the unwinder + // preprocessing to improve the structure of the SSA for the unwinder split_loopheads(goto_model); - //explicitly initialize all local variables + // explicitly initialize all local variables nondet_locals(goto_model); #if 1 - //TODO: find a better place for that - replace_malloc(goto_model,""); + // TODO: find a better place for that + replace_malloc(goto_model, ""); #endif #if REMOVE_MULTIPLE_DEREFERENCES @@ -1113,10 +1113,10 @@ bool summarizer_parse_optionst::process_goto_program( // add loop ids goto_model.goto_functions.compute_loop_numbers(); - //inline __CPROVER_initialize and main + // inline __CPROVER_initialize and main if(cmdline.isset("inline-main")) { - inline_main(goto_model); + inline_main(goto_model); } if(!cmdline.isset("no-propagation")) @@ -1176,18 +1176,18 @@ bool summarizer_parse_optionst::process_goto_program( error() << e << eom; return true; } - + catch(int) { return true; } - + catch(std::bad_alloc) { error() << "Out of memory" << eom; return true; } - + return false; } @@ -1213,8 +1213,8 @@ void summarizer_parse_optionst::report_properties( it!=property_map.end(); it++) { - if(it->first=="") //TODO: some properties do not show up in initialize_property_map - continue; + if(it->first=="") // TODO: some properties do not show up in initialize_property_map + continue; if(get_ui()==ui_message_handlert::XML_UI) { @@ -1237,7 +1237,7 @@ void summarizer_parse_optionst::report_properties( show_counterexample(goto_model, it->second.error_trace); if(cmdline.isset("graphml-cex") && it->second.result==property_checkert::FAIL) - output_graphml_cex(options,goto_model, it->second.error_trace); + output_graphml_cex(options, goto_model, it->second.error_trace); if(cmdline.isset("json-cex") && it->second.result==property_checkert::FAIL) output_json_cex(options, @@ -1262,13 +1262,13 @@ void summarizer_parse_optionst::report_properties( if(it->second.result==property_checkert::FAIL) failed++; } - + status() << "** " << unknown << " of " << property_map.size() << " unknown" - << eom; + << eom; status() << "** " << failed << " of " << property_map.size() << " failed" - << eom; + << eom; } } @@ -1292,7 +1292,7 @@ void summarizer_parse_optionst::report_success() { case ui_message_handlert::PLAIN: break; - + case ui_message_handlert::XML_UI: { xmlt xml("cprover-status"); @@ -1301,7 +1301,7 @@ void summarizer_parse_optionst::report_success() std::cout << std::endl; } break; - + default: assert(false); } @@ -1331,7 +1331,7 @@ void summarizer_parse_optionst::show_counterexample( std::cout << std::endl << "Counterexample:" << std::endl; show_goto_trace(std::cout, ns, error_trace); break; - + case ui_message_handlert::XML_UI: { xmlt xml; @@ -1339,7 +1339,7 @@ void summarizer_parse_optionst::show_counterexample( std::cout << xml << std::endl; } break; - + default: assert(false); } @@ -1402,7 +1402,7 @@ void summarizer_parse_optionst::output_json_cex( const namespacet ns(goto_model.symbol_table); jsont json_trace; convert(ns, error_trace, json_trace); - + if(options.get_option("json-cex")=="-") { std::cout << json_trace; @@ -1412,7 +1412,7 @@ void summarizer_parse_optionst::output_json_cex( std::ofstream out((options.get_option("json-cex")+"-"+property_id+".json").c_str()); out << json_trace << '\n'; } - } + } } /*******************************************************************\ @@ -1435,7 +1435,7 @@ void summarizer_parse_optionst::report_failure() { case ui_message_handlert::PLAIN: break; - + case ui_message_handlert::XML_UI: { xmlt xml("cprover-status"); @@ -1444,7 +1444,7 @@ void summarizer_parse_optionst::report_failure() std::cout << std::endl; } break; - + default: assert(false); } @@ -1470,7 +1470,7 @@ void summarizer_parse_optionst::report_unknown() { case ui_message_handlert::PLAIN: break; - + case ui_message_handlert::XML_UI: { xmlt xml("cprover-status"); @@ -1479,7 +1479,7 @@ void summarizer_parse_optionst::report_unknown() std::cout << std::endl; } break; - + default: assert(false); } @@ -1501,13 +1501,13 @@ void summarizer_parse_optionst::help() { std::cout << "\n" - "* * Summarizer " SUMMARIZER_VERSION " - Copyright (C) 2014 * *\n" + "* * Summarizer " SUMMARIZER_VERSION "-Copyright (C) 2014 * *\n" "* * (based on CBMC " CBMC_VERSION " "; - + std::cout << "(" << (sizeof(void *)*8) << "-bit version))"; - + std::cout << " * *\n"; - + std::cout << "* * Daniel Kroening * *\n" "* * University of Oxford * *\n" @@ -1523,7 +1523,7 @@ void summarizer_parse_optionst::help() " -D macro define preprocessor macro (C/C++)\n" " --preprocess stop after preprocessing\n" " --16, --32, --64 set width of int\n" - " --LP64, --ILP64, --LLP64,\n" + " --LP64, --ILP64, --LLP64, \n" " --ILP32, --LP32 set width of int, long and pointers\n" " --little-endian allow little-endian word-byte conversions\n" " --big-endian allow big-endian word-byte conversions\n" diff --git a/src/summarizer/summarizer_parse_options.h b/src/summarizer/summarizer_parse_options.h index 738eb579f..802d99ceb 100644 --- a/src/summarizer/summarizer_parse_options.h +++ b/src/summarizer/summarizer_parse_options.h @@ -58,7 +58,7 @@ class optionst; "(competition-mode)(slice)" \ "(no-unwinding-assertions)(no-propagation)(ssa-propagation)" // the last line is for CBMC-regression testing only - + class summarizer_parse_optionst: public parse_options_baset, public language_uit @@ -75,7 +75,7 @@ class summarizer_parse_optionst: protected: ui_message_handlert ui_message_handler; - virtual void register_languages(); + virtual void register_languages(); void get_command_line_options(optionst &options); @@ -86,7 +86,7 @@ class summarizer_parse_optionst: bool process_goto_program( const optionst &options, goto_modelt &goto_model); - + bool set_properties(goto_modelt &); void report_success(); @@ -94,39 +94,39 @@ class summarizer_parse_optionst: void report_properties( const goto_modelt &, - const summary_checker_baset::property_mapt &); + const summary_checker_baset::property_mapt &); void show_counterexample( const goto_modelt &, const class goto_tracet &); - + struct expr_statst { bool has_malloc; bool has_string; bool has_array; bool has_pointer; - + expr_statst() : has_malloc(false) , has_string(false) , has_array(false) , has_pointer(false) {} - }; - + }; + void type_stats_rec( const typet &type, expr_statst &stats, const namespacet &ns); - + void expr_stats_rec( const exprt &expr, - expr_statst &stats); - + expr_statst &stats); + void show_stats( const goto_modelt &, - std::ostream &); - + std::ostream &); + void eval_verbosity(); void report_unknown(); @@ -137,7 +137,7 @@ class summarizer_parse_optionst: void unwind_goto_into_loop(goto_modelt &goto_model, unsigned k); void replace_types_rec(const replace_symbolt &replace_const, exprt &expr); exprt evaluate_casts_in_constants(const exprt &expr, const typet& parent_type, - bool &valid); + bool &valid); void remove_multiple_dereferences(goto_modelt &goto_model); void remove_multiple_dereferences(goto_modelt &goto_model, goto_programt &body, goto_programt::targett t, exprt &expr, unsigned &var_counter, bool deref_seen); }; diff --git a/src/summarizer/summary_checker_ai.cpp b/src/summarizer/summary_checker_ai.cpp index 51c2411d2..1777d986c 100644 --- a/src/summarizer/summary_checker_ai.cpp +++ b/src/summarizer/summary_checker_ai.cpp @@ -27,11 +27,11 @@ property_checkert::resultt summary_checker_ait::operator()( { const namespacet ns(goto_model.symbol_table); - SSA_functions(goto_model,ns); + SSA_functions(goto_model, ns); - ssa_unwinder.init(false,false); + ssa_unwinder.init(false, false); - unsigned unwind = options.get_unsigned_int_option("unwind"); + unsigned unwind=options.get_unsigned_int_option("unwind"); if(unwind>0) { status() << "Unwinding" << messaget::eom; @@ -49,24 +49,24 @@ property_checkert::resultt summary_checker_ait::operator()( if(unwind > 0){ forall_goto_functions(f_it, goto_model.goto_functions){ if(!f_it->second.body_available()) continue; - if(has_prefix(id2string(f_it->first),TEMPLATE_DECL)) continue; - local_SSAt &SSA = ssa_db.get(f_it->first); + if(has_prefix(id2string(f_it->first), TEMPLATE_DECL)) continue; + local_SSAt &SSA=ssa_db.get(f_it->first); std::cout << "==>> Output SSA for function: " << f_it->first << "\n"; SSA.output(std::cout); } } else{ ssa_unwinder.init_localunwinders(); // possibly required; - + // iterate over the SSA to unwind loops forall_goto_functions(f_it, goto_model.goto_functions){ - + if(!f_it->second.body_available()) continue; - if(has_prefix(id2string(f_it->first),TEMPLATE_DECL)) continue; - - local_SSAt &SSA = ssa_db.get(f_it->first); - for(local_SSAt::nodest::const_iterator n_it = SSA.nodes.begin(); - n_it != SSA.nodes.end(); n_it++){ + if(has_prefix(id2string(f_it->first), TEMPLATE_DECL)) continue; + + local_SSAt &SSA=ssa_db.get(f_it->first); + for(local_SSAt::nodest::const_iterator n_it=SSA.nodes.begin(); + n_it!=SSA.nodes.end(); n_it++){ if(n_it->loophead!=SSA.nodes.end()){ std::cout << "==>> unwinding loop with location number: " << n_it->loophead->location->location_number << "\n"; @@ -75,28 +75,28 @@ property_checkert::resultt summary_checker_ait::operator()( } } } - + forall_goto_functions(f_it, goto_model.goto_functions){ if(!f_it->second.body_available()) continue; - if(has_prefix(id2string(f_it->first),TEMPLATE_DECL)) continue; - local_SSAt &SSA = ssa_db.get(f_it->first); + if(has_prefix(id2string(f_it->first), TEMPLATE_DECL)) continue; + local_SSAt &SSA=ssa_db.get(f_it->first); std::cout << "==>> Output SSA for function: " << f_it->first << "\n"; SSA.output(std::cout); } - + } /**/ /*********************************************************************************/ #endif - irep_idt entry_function = goto_model.goto_functions.entry_point(); + irep_idt entry_function=goto_model.goto_functions.entry_point(); if(options.get_bool_option("unit-check")) - entry_function = ""; + entry_function=""; if(!(options.get_bool_option("inline"))) { - if((options.get_option("spurious-check") != "concrete") && - (options.get_option("spurious-check") != "abstract")) + if((options.get_option("spurious-check")!="concrete") && + (options.get_option("spurious-check")!="abstract")) { SSA_dependency_graphs(goto_model, ns); } @@ -105,27 +105,27 @@ property_checkert::resultt summary_checker_ait::operator()( // properties initialize_property_map(goto_model.goto_functions); - bool preconditions = options.get_bool_option("preconditions"); - bool termination = options.get_bool_option("termination"); - if(!options.get_bool_option("havoc")) + bool preconditions=options.get_bool_option("preconditions"); + bool termination=options.get_bool_option("termination"); + if(!options.get_bool_option("havoc")) { - //forward analysis - summarize(goto_model,true,termination); + // forward analysis + summarize(goto_model, true, termination); } if(!options.get_bool_option("havoc") && preconditions) { - //backward analysis - summarize(goto_model,false,termination); + // backward analysis + summarize(goto_model, false, termination); } - if(preconditions) + if(preconditions) { report_statistics(); report_preconditions(); return property_checkert::UNKNOWN; } - if(termination) + if(termination) { report_statistics(); return report_termination(); @@ -137,13 +137,13 @@ property_checkert::resultt summary_checker_ait::operator()( #endif /* - irep_idt entry_function = goto_model.goto_functions.entry_point(); + irep_idt entry_function=goto_model.goto_functions.entry_point(); if(options.get_bool_option("unit-check")) - entry_function = ""; + entry_function=""; */ std::set seen_function_calls; - property_checkert::resultt result = check_properties(entry_function, entry_function, seen_function_calls, false); + property_checkert::resultt result= check_properties(entry_function, entry_function, seen_function_calls, false); report_statistics(); return result; } @@ -164,20 +164,20 @@ Function: summary_checker_ait::report_preconditions void summary_checker_ait::report_preconditions() { result() << eom; - result() << "** " << (options.get_bool_option("sufficient") ? - "Sufficient" : "Necessary") - << " preconditions: " << eom; - ssa_dbt::functionst &functions = ssa_db.functions(); - for(ssa_dbt::functionst::iterator it = functions.begin(); - it != functions.end(); it++) + result() << "** " << (options.get_bool_option("sufficient") ? + "Sufficient" : "Necessary") + << " preconditions: " << eom; + ssa_dbt::functionst &functions=ssa_db.functions(); + for(ssa_dbt::functionst::iterator it=functions.begin(); + it!=functions.end(); it++) { exprt precondition; - bool computed = summary_db.exists(it->first); - if(computed) precondition = summary_db.get(it->first).bw_precondition; - if(precondition.is_nil()) computed = false; - result() << eom << "[" << it->first << "]: " - << (!computed ? "not computed" : - from_expr(it->second->ns, "", precondition)) << eom; + bool computed=summary_db.exists(it->first); + if(computed) precondition=summary_db.get(it->first).bw_precondition; + if(precondition.is_nil()) computed=false; + result() << eom << "[" << it->first << "]: " + << (!computed ? "not computed" : + from_expr(it->second->ns, "", precondition)) << eom; } } @@ -197,19 +197,19 @@ property_checkert::resultt summary_checker_ait::report_termination() { result() << eom; result() << "** Termination: " << eom; - bool all_terminate = true; - bool one_nonterminate = false; - ssa_dbt::functionst &functions = ssa_db.functions(); - for(ssa_dbt::functionst::iterator it = functions.begin(); - it != functions.end(); it++) + bool all_terminate=true; + bool one_nonterminate=false; + ssa_dbt::functionst &functions=ssa_db.functions(); + for(ssa_dbt::functionst::iterator it=functions.begin(); + it!=functions.end(); it++) { - threevalt terminates = YES; - bool computed = summary_db.exists(it->first); - if(computed) terminates = summary_db.get(it->first).terminates; - all_terminate = all_terminate && (terminates==YES); - one_nonterminate = one_nonterminate || (terminates==NO); - result() << "[" << it->first << "]: " - << (!computed ? "not computed" : threeval2string(terminates)) << eom; + threevalt terminates=YES; + bool computed=summary_db.exists(it->first); + if(computed) terminates=summary_db.get(it->first).terminates; + all_terminate=all_terminate && (terminates==YES); + one_nonterminate=one_nonterminate || (terminates==NO); + result() << "[" << it->first << "]: " + << (!computed ? "not computed" : threeval2string(terminates)) << eom; } if(all_terminate) return property_checkert::PASS; if(one_nonterminate) return property_checkert::FAIL; diff --git a/src/summarizer/summary_checker_ai.h b/src/summarizer/summary_checker_ai.h index edde3fe34..2a9bc7eb5 100644 --- a/src/summarizer/summary_checker_ai.h +++ b/src/summarizer/summary_checker_ai.h @@ -18,7 +18,7 @@ class summary_checker_ait:public summary_checker_baset summary_checker_baset(_options) { } - + virtual resultt operator()(const goto_modelt &); protected: diff --git a/src/summarizer/summary_checker_base.cpp b/src/summarizer/summary_checker_base.cpp index 0879ea8bf..6e10ab1bf 100644 --- a/src/summarizer/summary_checker_base.cpp +++ b/src/summarizer/summary_checker_base.cpp @@ -61,26 +61,26 @@ Function: summary_checker_baset::SSA_dependency_graphs \*******************************************************************/ void summary_checker_baset::SSA_dependency_graphs( - const goto_modelt &goto_model, + const goto_modelt &goto_model, const namespacet &ns) { // compute dependency graph for all the functions forall_goto_functions(f_it, goto_model.goto_functions) { if(!f_it->second.body_available()) continue; - if(has_prefix(id2string(f_it->first),TEMPLATE_DECL)) continue; - + if(has_prefix(id2string(f_it->first), TEMPLATE_DECL)) continue; + status() << "Computing dependency graph of " << f_it->first << messaget::eom; - - //ssa_db.depgraph_create(f_it->first, ns, ssa_inliner); - - if(entry_function == f_it->first) + + // ssa_db.depgraph_create(f_it->first, ns, ssa_inliner); + + if(entry_function==f_it->first) ssa_db.depgraph_create(f_it->first, ns, ssa_inliner, true); else ssa_db.depgraph_create(f_it->first, ns, ssa_inliner, false); // change to true if all functions are to be treated equal #if 0 - ssa_dependency_grapht &ssa_depgraph = ssa_db.get_depgraph(f_it->first); + ssa_dependency_grapht &ssa_depgraph=ssa_db.get_depgraph(f_it->first); ssa_depgraph.output(debug()); debug() << eom; std::cout << "output SSA for function: " << f_it->first << "\n"; ssa_db.get(f_it->first).output_verbose(std::cout); @@ -101,19 +101,19 @@ Function: summary_checker_baset::SSA_functions \*******************************************************************/ void summary_checker_baset::SSA_functions(const goto_modelt &goto_model, const namespacet &ns) -{ - entry_function = goto_model.goto_functions.entry_point(); +{ + entry_function=goto_model.goto_functions.entry_point(); // compute SSA for all the functions forall_goto_functions(f_it, goto_model.goto_functions) { if(!f_it->second.body_available()) continue; - if(has_prefix(id2string(f_it->first),TEMPLATE_DECL)) continue; + if(has_prefix(id2string(f_it->first), TEMPLATE_DECL)) continue; status() << "Computing SSA of " << f_it->first << messaget::eom; - + ssa_db.create(f_it->first, f_it->second, ns); - local_SSAt &SSA = ssa_db.get(f_it->first); - + local_SSAt &SSA=ssa_db.get(f_it->first); + // simplify, if requested if(simplify) { @@ -121,11 +121,11 @@ void summary_checker_baset::SSA_functions(const goto_modelt &goto_model, const ::simplify(SSA, ns); } - //SSA.output_verbose(std::cout); + // SSA.output_verbose(std::cout); - //SSA.output(debug()); debug() << eom; + // SSA.output(debug()); debug() << eom; } - + // properties initialize_property_map(goto_model.goto_functions); } @@ -142,33 +142,33 @@ Function: summary_checker_baset::summarize \*******************************************************************/ -void summary_checker_baset::summarize(const goto_modelt &goto_model, +void summary_checker_baset::summarize(const goto_modelt &goto_model, bool forward, bool termination) -{ - summarizer_baset *summarizer = NULL; +{ + summarizer_baset *summarizer=NULL; #ifdef SHOW_CALLING_CONTEXTS if(options.get_bool_option("show-calling-contexts")) - summarizer = new summarizer_fw_contextst( - options,summary_db,ssa_db,ssa_unwinder,ssa_inliner); + summarizer=new summarizer_fw_contextst( + options, summary_db, ssa_db, ssa_unwinder, ssa_inliner); else #endif { if(forward && !termination) - summarizer = new summarizer_fwt( - options,summary_db,ssa_db,ssa_unwinder,ssa_inliner); + summarizer=new summarizer_fwt( + options, summary_db, ssa_db, ssa_unwinder, ssa_inliner); if(forward && termination) - summarizer = new summarizer_fw_termt( - options,summary_db,ssa_db,ssa_unwinder,ssa_inliner); + summarizer=new summarizer_fw_termt( + options, summary_db, ssa_db, ssa_unwinder, ssa_inliner); if(!forward && !termination) - summarizer = new summarizer_bwt( - options,summary_db,ssa_db,ssa_unwinder,ssa_inliner); + summarizer=new summarizer_bwt( + options, summary_db, ssa_db, ssa_unwinder, ssa_inliner); if(!forward && termination) - summarizer = new summarizer_bw_termt( - options,summary_db,ssa_db,ssa_unwinder,ssa_inliner); + summarizer=new summarizer_bw_termt( + options, summary_db, ssa_db, ssa_unwinder, ssa_inliner); } - assert(summarizer != NULL); + assert(summarizer!=NULL); summarizer->set_message_handler(get_message_handler()); @@ -177,10 +177,10 @@ void summary_checker_baset::summarize(const goto_modelt &goto_model, else summarizer->summarize(entry_function); - //statistics - solver_instances += summarizer->get_number_of_solver_instances(); - solver_calls += summarizer->get_number_of_solver_calls(); - summaries_used += summarizer->get_number_of_summaries_used(); + // statistics + solver_instances+=summarizer->get_number_of_solver_instances(); + solver_calls+=summarizer->get_number_of_solver_calls(); + summaries_used+=summarizer->get_number_of_summaries_used(); delete summarizer; } @@ -189,14 +189,14 @@ void summary_checker_baset::summarize(const goto_modelt &goto_model, Function: summary_checker_baset::check_properties - Inputs: function_name != nil + Inputs: function_name!=nil checks all functions in the call graph from the entry point - else - checks all functions + else + checks all functions Outputs: - Purpose: + Purpose: \*******************************************************************/ summary_checker_baset::resultt summary_checker_baset::check_properties() @@ -206,38 +206,38 @@ summary_checker_baset::resultt summary_checker_baset::check_properties() } summary_checker_baset::resultt summary_checker_baset::check_properties( - irep_idt function_name, - irep_idt entry_function, + irep_idt function_name, + irep_idt entry_function, std::set seen_function_calls, bool is_inlined) { if(function_name!="") { - ssa_dbt::functionst::const_iterator f_it = + ssa_dbt::functionst::const_iterator f_it= ssa_db.functions().find(function_name); - assert(f_it != ssa_db.functions().end()); - local_SSAt &SSA = *f_it->second; + assert(f_it!=ssa_db.functions().end()); + local_SSAt &SSA=*f_it->second; // call recursively for all function calls first - for(local_SSAt::nodest::const_iterator n_it = SSA.nodes.begin(); - n_it != SSA.nodes.end(); ++n_it) + for(local_SSAt::nodest::const_iterator n_it=SSA.nodes.begin(); + n_it!=SSA.nodes.end(); ++n_it) { - for(local_SSAt::nodet::function_callst::const_iterator ff_it = + for(local_SSAt::nodet::function_callst::const_iterator ff_it= n_it->function_calls.begin(); - ff_it != n_it->function_calls.end(); ff_it++) + ff_it!=n_it->function_calls.end(); ff_it++) { - assert(ff_it->function().id()==ID_symbol); //no function pointers - irep_idt fname = to_symbol_expr(ff_it->function()).get_identifier(); - - //ENHANCE?: can the return value be exploited? + assert(ff_it->function().id()==ID_symbol); // no function pointers + irep_idt fname=to_symbol_expr(ff_it->function()).get_identifier(); + + // ENHANCE?: can the return value be exploited? if(ssa_db.functions().find(fname)!=ssa_db.functions().end() && - (!summary_db.exists(fname) || + (!summary_db.exists(fname) || summary_db.get(fname).bw_transformer.is_nil())) { #if 0 debug() << "Checking call " << fname << messaget::eom; #endif - if(seen_function_calls.find(fname) == seen_function_calls.end()){ + if(seen_function_calls.find(fname)==seen_function_calls.end()){ seen_function_calls.insert(fname); check_properties(fname, entry_function, seen_function_calls, n_it->function_calls_inlined); @@ -248,35 +248,35 @@ summary_checker_baset::resultt summary_checker_baset::check_properties( if(!is_inlined) { - //now check function itself + // now check function itself status() << "Checking properties of " << f_it->first << messaget::eom; check_properties(f_it, entry_function); } } else // check all the functions { - for(ssa_dbt::functionst::const_iterator f_it = ssa_db.functions().begin(); - f_it != ssa_db.functions().end(); f_it++) + for(ssa_dbt::functionst::const_iterator f_it=ssa_db.functions().begin(); + f_it!=ssa_db.functions().end(); f_it++) { status() << "Checking properties of " << f_it->first << messaget::eom; #if 0 - //for debugging - show_ssa_symbols(*f_it->second,std::cerr); + // for debugging + show_ssa_symbols(*f_it->second, std::cerr); #endif check_properties(f_it); - if(options.get_bool_option("show-invariants")) + if(options.get_bool_option("show-invariants")) { if(!summary_db.exists(f_it->first)) continue; - show_invariants(*(f_it->second),summary_db.get(f_it->first),result()); + show_invariants(*(f_it->second), summary_db.get(f_it->first), result()); result() << eom; } } } - summary_checker_baset::resultt result = property_checkert::PASS; + summary_checker_baset::resultt result=property_checkert::PASS; if(function_name=="" || function_name==entry_function) { // determine overall status @@ -286,10 +286,10 @@ summary_checker_baset::resultt summary_checker_baset::check_properties( if(p_it->second.result==FAIL) return property_checkert::FAIL; if(p_it->second.result==UNKNOWN) - result = property_checkert::UNKNOWN; + result=property_checkert::UNKNOWN; } } - + return result; } @@ -301,7 +301,7 @@ Function: summary_checker_baset::check_properties Outputs: - Purpose: + Purpose: \*******************************************************************/ @@ -309,21 +309,21 @@ void summary_checker_baset::check_properties( const ssa_dbt::functionst::const_iterator f_it, irep_idt entry_function) { - unwindable_local_SSAt &SSA = *f_it->second; + unwindable_local_SSAt &SSA=*f_it->second; - //check whether function has assertions + // check whether function has assertions if(!has_assertion(f_it->first)) return; - bool all_properties = options.get_bool_option("all-properties"); - bool build_error_trace = options.get_bool_option("show-trace"); + bool all_properties=options.get_bool_option("all-properties"); + bool build_error_trace=options.get_bool_option("show-trace"); SSA.output(debug()); debug() << eom; - + // incremental version // solver - incremental_solvert &solver = ssa_db.get_solver(f_it->first); + incremental_solvert &solver=ssa_db.get_solver(f_it->first); solver.set_message_handler(get_message_handler()); #if 0 @@ -332,83 +332,83 @@ void summary_checker_baset::check_properties( { ssa_const_propagatort ssa_const_propagator; std::list c; - ssa_const_propagator(c,SSA); + ssa_const_propagator(c, SSA); solver << c; debug() << "SSA const propagation: " << eom; - for(std::list::iterator it = c.begin(); + for(std::list::iterator it=c.begin(); it!=c.end(); it++) - debug() << " " << from_expr(SSA.ns,"",*it) << eom; + debug() << " " << from_expr(SSA.ns, "", *it) << eom; } #endif - + // give SSA to solver solver << SSA; SSA.mark_nodes(); solver.new_context(); - exprt enabling_expr = SSA.get_enabling_exprs(); + exprt enabling_expr=SSA.get_enabling_exprs(); solver << enabling_expr; // invariant, calling contexts if(summary_db.exists(f_it->first)) { - const summaryt &summary = summary_db.get(f_it->first); + const summaryt &summary=summary_db.get(f_it->first); if(!summary.fw_invariant.is_nil()) solver << summary.fw_invariant; if(!summary.fw_precondition.is_nil()) solver << summary.fw_precondition; } - //callee summaries and inlined functions + // callee summaries and inlined functions ssa_inlinert::assertion_mapt assertion_map; solver << ssa_inliner.get_summaries(SSA, assertion_map); - //spuriousness checkers - summarizer_bw_cex_baset *summarizer_bw_cex = NULL; - incremental_solvert* cex_complete_solver = + // spuriousness checkers + summarizer_bw_cex_baset *summarizer_bw_cex=NULL; + incremental_solvert* cex_complete_solver= incremental_solvert::allocate(SSA.ns, options.get_bool_option("refine")); #if 1 cex_complete_solver->set_message_handler(get_message_handler()); #endif if(options.get_bool_option("inline") || - options.get_option("spurious-check") == "concrete") + options.get_option("spurious-check")=="concrete") { - summarizer_bw_cex = new summarizer_bw_cex_concretet( - options,summary_db,ssa_db, - ssa_unwinder,ssa_inliner, - entry_function,f_it->first); + summarizer_bw_cex=new summarizer_bw_cex_concretet( + options, summary_db, ssa_db, + ssa_unwinder, ssa_inliner, + entry_function, f_it->first); } - else if(options.get_option("spurious-check") == "abstract") + else if(options.get_option("spurious-check")=="abstract") { - summarizer_bw_cex = new summarizer_bw_cex_ait( - options,summary_db,ssa_db, - ssa_unwinder,ssa_inliner, - entry_function,f_it->first); + summarizer_bw_cex=new summarizer_bw_cex_ait( + options, summary_db, ssa_db, + ssa_unwinder, ssa_inliner, + entry_function, f_it->first); } - else if(options.get_option("spurious-check") == "complete") + else if(options.get_option("spurious-check")=="complete") { - summarizer_bw_cex = new summarizer_bw_cex_completet( - options,summary_db,ssa_db, - ssa_unwinder,ssa_inliner,*cex_complete_solver, - entry_function,f_it->first); + summarizer_bw_cex=new summarizer_bw_cex_completet( + options, summary_db, ssa_db, + ssa_unwinder, ssa_inliner, *cex_complete_solver, + entry_function, f_it->first); } - else if(options.get_option("spurious-check") == "wp") + else if(options.get_option("spurious-check")=="wp") { - summarizer_bw_cex = new summarizer_bw_cex_wpt( - options,summary_db,ssa_db, - ssa_unwinder,ssa_inliner,*cex_complete_solver, - entry_function,f_it->first); + summarizer_bw_cex=new summarizer_bw_cex_wpt( + options, summary_db, ssa_db, + ssa_unwinder, ssa_inliner, *cex_complete_solver, + entry_function, f_it->first); } - else if(options.get_option("spurious-check") == "all") + else if(options.get_option("spurious-check")=="all") { - summarizer_bw_cex = new summarizer_bw_cex_allt( - options,summary_db,ssa_db, - ssa_unwinder,ssa_inliner,*cex_complete_solver, - entry_function,f_it->first); + summarizer_bw_cex=new summarizer_bw_cex_allt( + options, summary_db, ssa_db, + ssa_unwinder, ssa_inliner, *cex_complete_solver, + entry_function, f_it->first); } - assert(summarizer_bw_cex != NULL); + assert(summarizer_bw_cex!=NULL); summarizer_bw_cex->set_message_handler(get_message_handler()); cover_goals_extt cover_goals( @@ -421,15 +421,15 @@ void summary_checker_baset::check_properties( aa_it!=assertion_map.end(); aa_it++) { - irep_idt property_id = aa_it->first->source_location.get_property_id(); + irep_idt property_id=aa_it->first->source_location.get_property_id(); - //do not recheck properties that have already been decided - if(property_map[property_id].result!=UNKNOWN) - continue; + // do not recheck properties that have already been decided + if(property_map[property_id].result!=UNKNOWN) + continue; #if 0 - if(property_id=="") //TODO: some properties do not show up in initialize_property_map - continue; + if(property_id=="") // TODO: some properties do not show up in initialize_property_map + continue; #endif for(exprt::operandst::const_iterator @@ -445,12 +445,12 @@ void summary_checker_baset::check_properties( #if 1 debug() << "property: " << from_expr(SSA.ns, "", property) << eom; #endif - - property_map[property_id].location = aa_it->first; + + property_map[property_id].location=aa_it->first; cover_goals.goal_map[property_id].conjuncts.push_back(property); } } - + for(cover_goals_extt::goal_mapt::const_iterator it=cover_goals.goal_map.begin(); @@ -459,22 +459,22 @@ void summary_checker_baset::check_properties( { // Our goal is to falsify a property. // The following is TRUE if the conjunction is empty. - //literalt p=!solver.convert(conjunction(it->second.conjuncts)); - //cover_goals.add(p); + // literalt p=!solver.convert(conjunction(it->second.conjuncts)); + // cover_goals.add(p); cover_goals.add(not_exprt(conjunction(it->second.conjuncts))); } - + status() << "Running " << solver.solver->decision_procedure_text() << eom; - cover_goals(); + cover_goals(); /* std::cout << "Output Verbose: " << entry_function << "\n"; (ssa_db.get(entry_function)).output_verbose(std::cout); assert(false); */ - //set all non-covered goals to PASS except if we do not try + // set all non-covered goals to PASS except if we do not try // to cover all goals and we have found a FAIL - if(all_properties || cover_goals.number_covered()==0) + if(all_properties || cover_goals.number_covered()==0) { std::list::const_iterator g_it= cover_goals.goals.begin(); @@ -497,7 +497,7 @@ void summary_checker_baset::check_properties( delete summarizer_bw_cex; delete cex_complete_solver; -} +} /*******************************************************************\ @@ -513,22 +513,22 @@ Function: summary_checker_baset::report_statistics() void summary_checker_baset::report_statistics() { - for(ssa_dbt::functionst::const_iterator f_it = ssa_db.functions().begin(); - f_it != ssa_db.functions().end(); f_it++) + for(ssa_dbt::functionst::const_iterator f_it=ssa_db.functions().begin(); + f_it!=ssa_db.functions().end(); f_it++) { - incremental_solvert &solver = ssa_db.get_solver(f_it->first); - unsigned calls = solver.get_number_of_solver_calls(); + incremental_solvert &solver=ssa_db.get_solver(f_it->first); + unsigned calls=solver.get_number_of_solver_calls(); if(calls>0) solver_instances++; - solver_calls += calls; + solver_calls+=calls; } statistics() << "** statistics: " << eom; statistics() << " number of solver instances: " << solver_instances << eom; statistics() << " number of solver calls: " << solver_calls << eom; - statistics() << " number of summaries used: " + statistics() << " number of summaries used: " << summaries_used << eom; statistics() << eom; } - + /*******************************************************************\ Function: summary_checker_baset::do_show_vcc @@ -548,7 +548,7 @@ void summary_checker_baset::do_show_vcc( { std::cout << i_it->source_location << "\n"; std::cout << i_it->source_location.get_comment() << "\n"; - + std::list ssa_constraints; ssa_constraints << SSA; @@ -559,9 +559,9 @@ void summary_checker_baset::do_show_vcc( std::cout << "{-" << i << "} " << from_expr(SSA.ns, "", *c_it) << "\n"; std::cout << "|--------------------------\n"; - + std::cout << "{1} " << from_expr(SSA.ns, "", *a_it) << "\n"; - + std::cout << "\n"; (??)} (??) @@ -578,38 +578,38 @@ void summary_checker_baset::do_show_vcc( (??) (??)\*******************************************************************/ (??) -(??)bool summary_checker_baset::is_spurious(const exprt::operandst &loophead_selects, +(??)bool summary_checker_baset::is_spurious(const exprt::operandst &loophead_selects, (??) incremental_solvert &solver) (??){ -(??) //check loop head choices in model -(??) bool invariants_involved = false; -(??) for(exprt::operandst::const_iterator l_it = loophead_selects.begin(); -(??) l_it != loophead_selects.end(); l_it++) +(??) // check loop head choices in model +(??) bool invariants_involved=false; +(??) for(exprt::operandst::const_iterator l_it=loophead_selects.begin(); +(??) l_it!=loophead_selects.end(); l_it++) (??) { -(??) if(solver.get(l_it->op0()).is_true()) +(??) if(solver.get(l_it->op0()).is_true()) (??) { -(??) invariants_involved = true; +(??) invariants_involved=true; (??) break; (??) } (??) } (??) if(!invariants_involved) return false; -(??) +(??) (??) // force avoiding paths going through invariants (??) solver << conjunction(loophead_selects); (??) -(??) solver_calls++; //statistics +(??) solver_calls++; // statistics (??) (??) switch(solver()) (??) { (??) case decision_proceduret::D_SATISFIABLE: (??) return false; (??) break; -(??) +(??) (??) case decision_proceduret::D_UNSATISFIABLE: (??) return true; (??) break; (??) -(??) case decision_proceduret::D_ERROR: +(??) case decision_proceduret::D_ERROR: (??) default: (??) throw "error from decision procedure"; (??) } @@ -630,12 +630,12 @@ Function: summary_checker_baset::instrument_and_output void summary_checker_baset::instrument_and_output(goto_modelt &goto_model) { - instrument_gotot instrument_goto(options,ssa_db,summary_db); + instrument_gotot instrument_goto(options, ssa_db, summary_db); instrument_goto(goto_model); - std::string filename = options.get_option("instrument-output"); + std::string filename=options.get_option("instrument-output"); status() << "Writing instrumented goto-binary " << filename << eom; - write_goto_binary(filename, - goto_model.symbol_table, + write_goto_binary(filename, + goto_model.symbol_table, goto_model.goto_functions, get_message_handler()); } @@ -645,7 +645,7 @@ Function: summary_checker_baset::has_assertion Inputs: - Outputs: + Outputs: Purpose: searches recursively for assertions in inlined functions @@ -654,17 +654,17 @@ Function: summary_checker_baset::has_assertion bool summary_checker_baset::has_assertion(irep_idt function_name) { // SSA.goto_function.body.has_assertion() has become too semantic - bool _has_assertion = false; - const local_SSAt &SSA = ssa_db.get(function_name); + bool _has_assertion=false; + const local_SSAt &SSA=ssa_db.get(function_name); - for(local_SSAt::nodest::const_iterator - n_it = SSA.nodes.begin(); n_it != SSA.nodes.end(); ++n_it) + for(local_SSAt::nodest::const_iterator + n_it=SSA.nodes.begin(); n_it!=SSA.nodes.end(); ++n_it) { - for(local_SSAt::nodet::assertionst::const_iterator - a_it = n_it->assertions.begin(); a_it != n_it->assertions.end(); ++a_it) + for(local_SSAt::nodet::assertionst::const_iterator + a_it=n_it->assertions.begin(); a_it!=n_it->assertions.end(); ++a_it) { - irep_idt property_id = n_it->location->source_location.get_property_id(); - + irep_idt property_id=n_it->location->source_location.get_property_id(); + if(n_it->location->guard.is_true()) property_map[property_id].result=PASS; else @@ -673,16 +673,16 @@ bool summary_checker_baset::has_assertion(irep_idt function_name) if(!n_it->function_calls_inlined) continue; - for(local_SSAt::nodet::function_callst::const_iterator - f_it = n_it->function_calls.begin(); - f_it != n_it->function_calls.end(); ++f_it) + for(local_SSAt::nodet::function_callst::const_iterator + f_it=n_it->function_calls.begin(); + f_it!=n_it->function_calls.end(); ++f_it) { - irep_idt fname = to_symbol_expr(f_it->function()).get_identifier(); + irep_idt fname=to_symbol_expr(f_it->function()).get_identifier(); if(ssa_db.functions().find(fname)==ssa_db.functions().end()) continue; - bool new_has_assertion = has_assertion(fname); //recurse - _has_assertion = _has_assertion || new_has_assertion; + bool new_has_assertion=has_assertion(fname); // recurse + _has_assertion=_has_assertion || new_has_assertion; } } diff --git a/src/summarizer/summary_checker_base.h b/src/summarizer/summary_checker_base.h index bbcd9bd6b..339f3ae01 100644 --- a/src/summarizer/summary_checker_base.h +++ b/src/summarizer/summary_checker_base.h @@ -31,7 +31,7 @@ class summary_checker_baset:public property_checkert simplify(false), fixed_point(false), options(_options), - ssa_db(_options),summary_db(), + ssa_db(_options), summary_db(), ssa_unwinder(ssa_db), ssa_inliner(summary_db, ssa_db), solver_instances(0), @@ -40,7 +40,7 @@ class summary_checker_baset:public property_checkert { ssa_inliner.set_message_handler(get_message_handler()); } - + bool show_vcc, simplify, fixed_point; irep_idt function_to_check; @@ -77,8 +77,8 @@ class summary_checker_baset:public property_checkert void SSA_functions(const goto_modelt &, const namespacet &ns); void SSA_dependency_graphs(const goto_modelt &, const namespacet &ns); - void summarize(const goto_modelt &, - bool forward=true, bool termination=false); + void summarize(const goto_modelt &, + bool forward=true, bool termination=false); property_checkert::resultt check_properties(); property_checkert::resultt check_properties( diff --git a/src/summarizer/summary_checker_bmc.cpp b/src/summarizer/summary_checker_bmc.cpp index 9ce39f96f..7c6b21c71 100644 --- a/src/summarizer/summary_checker_bmc.cpp +++ b/src/summarizer/summary_checker_bmc.cpp @@ -29,61 +29,61 @@ property_checkert::resultt summary_checker_bmct::operator()( const goto_modelt &goto_model) { const namespacet ns(goto_model.symbol_table); - irep_idt entry_function = goto_model.goto_functions.entry_point(); + irep_idt entry_function=goto_model.goto_functions.entry_point(); if(options.get_bool_option("unit-check")) - entry_function = ""; + entry_function=""; - SSA_functions(goto_model,ns); + SSA_functions(goto_model, ns); - ssa_unwinder.init(false,true); + ssa_unwinder.init(false, true); - property_checkert::resultt result = property_checkert::UNKNOWN; - unsigned max_unwind = options.get_unsigned_int_option("unwind"); + property_checkert::resultt result=property_checkert::UNKNOWN; + unsigned max_unwind=options.get_unsigned_int_option("unwind"); status() << "Max-unwind is " << max_unwind << eom; ssa_unwinder.init_localunwinders(); ssa_refinert *ssa_refiner; if((options.get_bool_option("inline"))) - ssa_refiner = new ssa_refiner_monolithict(summary_db, ssa_unwinder, + ssa_refiner=new ssa_refiner_monolithict(summary_db, ssa_unwinder, max_unwind); else - ssa_refiner = new ssa_refiner_selectivet(ssa_db, ssa_unwinder, + ssa_refiner=new ssa_refiner_selectivet(ssa_db, ssa_unwinder, max_unwind, ssa_inliner, reason); ssa_refiner->set_message_handler(get_message_handler()); - //while can refine + // while can refine while((*ssa_refiner)()) { status() << "Unwinding (k=" << unwind << ")" << messaget::eom; summary_db.mark_recompute_all(); ssa_unwinder.unwind_all(unwind+1); - //dependency graphs + // dependency graphs if(!(options.get_bool_option("inline"))) { if((options.get_option("spurious-check")!="concrete") && - (options.get_option("spurious-check")!="abstract")) + (options.get_option("spurious-check")!="abstract")) { SSA_dependency_graphs(goto_model, ns); } } - //check + // check std::set seen_function_calls; - result = check_properties(entry_function, entry_function, - seen_function_calls, false); + result= check_properties(entry_function, entry_function, + seen_function_calls, false); - //result - if(result == property_checkert::PASS) + // result + if(result==property_checkert::PASS) { - status() << "incremental BMC proof found after " - << unwind << " unwinding(s)" << messaget::eom; + status() << "incremental BMC proof found after " + << unwind << " unwinding(s)" << messaget::eom; break; } - else if(result == property_checkert::FAIL) + else if(result==property_checkert::FAIL) { - status() << "incremental BMC counterexample found after " - << unwind << " unwinding(s)" << messaget::eom; + status() << "incremental BMC counterexample found after " + << unwind << " unwinding(s)" << messaget::eom; break; } } diff --git a/src/summarizer/summary_checker_bmc.h b/src/summarizer/summary_checker_bmc.h index 8345a41fe..ab8294099 100644 --- a/src/summarizer/summary_checker_bmc.h +++ b/src/summarizer/summary_checker_bmc.h @@ -18,7 +18,7 @@ class summary_checker_bmct:public summary_checker_baset summary_checker_baset(_options) { } - + virtual resultt operator()(const goto_modelt &); }; diff --git a/src/summarizer/summary_checker_kind.cpp b/src/summarizer/summary_checker_kind.cpp index 895b1a49d..04059b699 100644 --- a/src/summarizer/summary_checker_kind.cpp +++ b/src/summarizer/summary_checker_kind.cpp @@ -29,71 +29,71 @@ property_checkert::resultt summary_checker_kindt::operator()( const goto_modelt &goto_model) { const namespacet ns(goto_model.symbol_table); - irep_idt entry_function = goto_model.goto_functions.entry_point(); + irep_idt entry_function=goto_model.goto_functions.entry_point(); if(options.get_bool_option("unit-check")) - entry_function = ""; + entry_function=""; - SSA_functions(goto_model,ns); + SSA_functions(goto_model, ns); - ssa_unwinder.init(true,false); + ssa_unwinder.init(true, false); - property_checkert::resultt result = property_checkert::UNKNOWN; - unsigned max_unwind = options.get_unsigned_int_option("unwind"); + property_checkert::resultt result=property_checkert::UNKNOWN; + unsigned max_unwind=options.get_unsigned_int_option("unwind"); status() << "Max-unwind is " << max_unwind << eom; ssa_unwinder.init_localunwinders(); ssa_refinert *ssa_refiner; if((options.get_bool_option("inline"))) - ssa_refiner = new ssa_refiner_monolithict(summary_db, ssa_unwinder, + ssa_refiner=new ssa_refiner_monolithict(summary_db, ssa_unwinder, max_unwind); else - ssa_refiner = new ssa_refiner_selectivet(ssa_db, ssa_unwinder, + ssa_refiner=new ssa_refiner_selectivet(ssa_db, ssa_unwinder, max_unwind, ssa_inliner, reason); ssa_refiner->set_message_handler(get_message_handler()); - //while can refine + // while can refine while((*ssa_refiner)()) { - unsigned unwind = ssa_refiner->get_unwind(); + unsigned unwind=ssa_refiner->get_unwind(); - //dependency graphs + // dependency graphs if(!(options.get_bool_option("inline"))) { if((options.get_option("spurious-check")!="concrete") && - (options.get_option("spurious-check")!="abstract")) + (options.get_option("spurious-check")!="abstract")) { - //TODO: update only those that were refined by unwinding + // TODO: update only those that were refined by unwinding SSA_dependency_graphs(goto_model, ns); } } - //check + // check std::set seen_function_calls; - result = check_properties(entry_function, entry_function, - seen_function_calls, false); - - //do static analysis and check again - if(result == property_checkert::UNKNOWN && - !options.get_bool_option("havoc") && - (unwind seen_function_calls; - result = check_properties(entry_function, entry_function, - seen_function_calls, false); + result= check_properties(entry_function, entry_function, + seen_function_calls, false); } - //result - if(result == property_checkert::PASS) + // result + if(result==property_checkert::PASS) { - status() << "k-induction proof found after " + status() << "k-induction proof found after " << unwind << " unwinding(s)" << eom; break; } - else if(result == property_checkert::FAIL) + else if(result==property_checkert::FAIL) { - status() << "k-induction counterexample found after " + status() << "k-induction counterexample found after " << unwind << " unwinding(s)" << eom; break; } diff --git a/src/summarizer/summary_checker_kind.h b/src/summarizer/summary_checker_kind.h index 087ba6fae..792347485 100644 --- a/src/summarizer/summary_checker_kind.h +++ b/src/summarizer/summary_checker_kind.h @@ -18,7 +18,7 @@ class summary_checker_kindt:public summary_checker_baset summary_checker_baset(_options) { } - + virtual resultt operator()(const goto_modelt &); }; From c5925c831bf62b7f26cf748b9d9ddfaac5394ec3 Mon Sep 17 00:00:00 2001 From: Peter Schrammel Date: Tue, 9 May 2017 18:33:06 +0200 Subject: [PATCH 74/82] Improved gitignore --- .gitignore | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.gitignore b/.gitignore index 1aaff666b..773f472e9 100644 --- a/.gitignore +++ b/.gitignore @@ -19,3 +19,7 @@ tests.log # binaries src/2ls/2ls + +*.orig +*.bak +*\# From fe8f4539bba802f1370362f3cb858f7eed3e7ef8 Mon Sep 17 00:00:00 2001 From: Peter Schrammel Date: Tue, 9 May 2017 22:52:02 +0100 Subject: [PATCH 75/82] Clean up --- src/2ls/2ls_parse_options.cpp | 2 +- src/2ls/cover_goals_ext.cpp | 14 +- src/2ls/dynamic_cfg.cpp | 7 +- src/2ls/graphml_witness_ext.h | 4 +- src/2ls/instrument_goto.cpp | 3 +- src/2ls/summary_checker_base.cpp | 91 +- src/2ls/summary_checker_base.h | 8 +- src/deltacheck/deltacheck_parse_options.cpp | 347 ---- src/deltacheck/deltacheck_parse_options.h | 52 - src/deltagit/deltagit_parse_options.cpp | 206 --- src/deltagit/deltagit_parse_options.h | 30 - src/domains/disjunctive_analyzer.cpp | 285 +-- src/domains/disjunctive_analyzer.h | 4 +- src/domains/domain_refinement.h | 8 +- src/domains/incremental_solver.h | 6 +- src/domains/lexlinrank_solver_enumeration.cpp | 3 +- src/domains/predabs_domain.h | 4 +- src/domains/ranking_solver_enumeration.cpp | 3 +- src/domains/simplify_bounds.h | 6 +- src/domains/simplify_bounds_class.h | 19 +- src/domains/simplify_transformer.cpp | 33 +- src/domains/simplify_transformer.h | 6 +- src/domains/simplify_transformer_class.h | 16 +- src/domains/ssa_analyzer.cpp | 8 +- src/domains/strategy_solver_binsearch.cpp | 3 +- src/domains/strategy_solver_enumeration.cpp | 3 +- src/domains/template_generator_base.h | 9 +- src/domains/template_generator_summary.cpp | 3 +- src/domains/tpolyhedra_domain.cpp | 3 - src/domains/tpolyhedra_domain.h | 3 +- src/domains/util.cpp | 9 +- src/html/syntax_highlighting.cpp | 306 ---- src/html/syntax_highlighting.h | 35 - src/solver/summarizer_bw_cex.cpp | 9 +- src/solver/summarizer_bw_cex.h | 4 +- src/solver/summarizer_bw_cex_ai.cpp | 230 ++- src/solver/summarizer_bw_cex_ai.h | 80 +- src/solver/summarizer_bw_cex_all.h | 76 +- src/solver/summarizer_bw_cex_complete.cpp | 361 ++-- src/solver/summarizer_bw_cex_complete.h | 59 +- src/solver/summarizer_bw_cex_concrete.cpp | 160 +- src/solver/summarizer_bw_cex_concrete.h | 32 +- src/solver/summarizer_bw_cex_wp.cpp | 577 +++--- src/solver/summarizer_bw_cex_wp.h | 68 +- src/solver/summary.h | 22 +- src/ssa/Makefile | 26 +- src/ssa/const_propagator.cpp | 467 ----- src/ssa/const_propagator.h | 101 -- src/ssa/local_ssa.cpp | 23 +- src/ssa/replace_symbol_ext.cpp | 82 - src/ssa/replace_symbol_ext.h | 20 - src/ssa/ssa_const_propagator.cpp | 260 +-- src/ssa/ssa_const_propagator.h | 41 +- src/ssa/ssa_db.cpp | 7 +- src/ssa/ssa_dependency_graph.cpp | 219 +-- src/ssa/ssa_dependency_graph.h | 16 +- src/ssa/ssa_inliner.cpp | 181 +- src/ssa/ssa_inliner.h | 142 +- src/ssa/ssa_refiner.h | 8 +- src/ssa/ssa_refiner_monolithic.h | 36 +- src/ssa/ssa_refiner_selective.cpp | 4 +- src/ssa/ssa_refiner_selective.h | 53 +- src/ssa/ssa_slicer.cpp | 181 -- src/ssa/ssa_slicer.h | 44 - src/ssa/ssa_unwinder.cpp | 98 +- src/ssa/ssa_unwinder.h | 25 +- src/ssa/unwindable_local_ssa.cpp | 6 +- src/storefront/Makefile | 27 - src/storefront/data.cpp | 84 - src/storefront/data.h | 40 - src/storefront/file_view.cpp | 147 -- src/storefront/file_view.h | 14 - src/storefront/property_view.cpp | 30 - src/storefront/property_view.h | 14 - src/storefront/storefront_main.cpp | 38 - src/storefront/storefront_parse_options.cpp | 121 -- src/storefront/storefront_parse_options.h | 29 - src/storefront/trace_view.cpp | 29 - src/storefront/trace_view.h | 14 - src/summarizer/function_signature.cpp | 78 - src/summarizer/function_signature.h | 17 - src/summarizer/instrument_goto.cpp | 180 -- src/summarizer/instrument_goto.h | 55 - src/summarizer/preprocessing_util.cpp | 265 --- src/summarizer/summarizer.cpp | 125 -- src/summarizer/summarizer.h | 45 - src/summarizer/summarizer_fw_contexts.cpp | 174 -- src/summarizer/summarizer_fw_contexts.h | 59 - src/summarizer/summarizer_parse_options.cpp | 1593 ----------------- src/summarizer/summarizer_parse_options.h | 145 -- src/summarizer/summary_checker_ai.cpp | 217 --- src/summarizer/summary_checker_ai.h | 29 - src/summarizer/summary_checker_base.cpp | 690 ------- src/summarizer/summary_checker_base.h | 97 - src/summarizer/summary_checker_bmc.cpp | 92 - src/summarizer/summary_checker_bmc.h | 26 - src/summarizer/summary_checker_kind.cpp | 105 -- src/summarizer/summary_checker_kind.h | 26 - 98 files changed, 1898 insertions(+), 7964 deletions(-) delete mode 100644 src/deltacheck/deltacheck_parse_options.cpp delete mode 100644 src/deltacheck/deltacheck_parse_options.h delete mode 100644 src/deltagit/deltagit_parse_options.cpp delete mode 100644 src/deltagit/deltagit_parse_options.h delete mode 100644 src/html/syntax_highlighting.cpp delete mode 100644 src/html/syntax_highlighting.h delete mode 100644 src/ssa/const_propagator.cpp delete mode 100644 src/ssa/const_propagator.h delete mode 100644 src/ssa/replace_symbol_ext.cpp delete mode 100644 src/ssa/replace_symbol_ext.h delete mode 100644 src/ssa/ssa_slicer.cpp delete mode 100644 src/ssa/ssa_slicer.h delete mode 100644 src/storefront/Makefile delete mode 100644 src/storefront/data.cpp delete mode 100644 src/storefront/data.h delete mode 100644 src/storefront/file_view.cpp delete mode 100644 src/storefront/file_view.h delete mode 100644 src/storefront/property_view.cpp delete mode 100644 src/storefront/property_view.h delete mode 100644 src/storefront/storefront_main.cpp delete mode 100644 src/storefront/storefront_parse_options.cpp delete mode 100644 src/storefront/storefront_parse_options.h delete mode 100644 src/storefront/trace_view.cpp delete mode 100644 src/storefront/trace_view.h delete mode 100644 src/summarizer/function_signature.cpp delete mode 100644 src/summarizer/function_signature.h delete mode 100644 src/summarizer/instrument_goto.cpp delete mode 100644 src/summarizer/instrument_goto.h delete mode 100644 src/summarizer/preprocessing_util.cpp delete mode 100644 src/summarizer/summarizer.cpp delete mode 100644 src/summarizer/summarizer.h delete mode 100644 src/summarizer/summarizer_fw_contexts.cpp delete mode 100644 src/summarizer/summarizer_fw_contexts.h delete mode 100644 src/summarizer/summarizer_parse_options.cpp delete mode 100644 src/summarizer/summarizer_parse_options.h delete mode 100644 src/summarizer/summary_checker_ai.cpp delete mode 100644 src/summarizer/summary_checker_ai.h delete mode 100644 src/summarizer/summary_checker_base.cpp delete mode 100644 src/summarizer/summary_checker_base.h delete mode 100644 src/summarizer/summary_checker_bmc.cpp delete mode 100644 src/summarizer/summary_checker_bmc.h delete mode 100644 src/summarizer/summary_checker_kind.cpp delete mode 100644 src/summarizer/summary_checker_kind.h diff --git a/src/2ls/2ls_parse_options.cpp b/src/2ls/2ls_parse_options.cpp index b1363d104..cc8646bcf 100644 --- a/src/2ls/2ls_parse_options.cpp +++ b/src/2ls/2ls_parse_options.cpp @@ -840,7 +840,7 @@ void twols_parse_optionst::require_entry( if(goto_model.symbol_table.symbols.find(entry_point)== symbol_table.symbols.end()) - throw "The program has no entry point; please complete linking"; + throw "the program has no entry point; please complete linking"; } /*******************************************************************\ diff --git a/src/2ls/cover_goals_ext.cpp b/src/2ls/cover_goals_ext.cpp index b3167f479..fc8c3a234 100644 --- a/src/2ls/cover_goals_ext.cpp +++ b/src/2ls/cover_goals_ext.cpp @@ -182,7 +182,9 @@ void cover_goals_extt::assignment() solver.l_get(g_it->condition).is_true()) { #if 1 - solver.pop_context(); // otherwise this would interfere with necessary preconditions + // otherwise this would interfere with necessary preconditions + solver.pop_context(); + summarizer_bw_cex.summarize(g_it->cond_expression); property_map[it->first].result=summarizer_bw_cex.check(); solver.new_context(); @@ -192,12 +194,13 @@ void cover_goals_extt::assignment() exprt conjunct_expr=(g_it->cond_expression).op0(); #if 0 std::cout << "FAILED EXPR: " - << from_expr(SSA.ns, "", conjunct_expr) << std::endl; + << from_expr(SSA.ns, "", conjunct_expr) << std::endl; #endif if(conjunct_expr.id()!=ID_and) { - solver.pop_context(); // otherwise this would interfere with necessary preconditions + // otherwise this would interfere with necessary preconditions + solver.pop_context(); summarizer_bw_cex.summarize(g_it->cond_expression); property_map[it->first].result=summarizer_bw_cex.check(); solver.new_context(); @@ -220,7 +223,9 @@ void cover_goals_extt::assignment() #endif } } - solver.pop_context(); // otherwise this would interfere with necessary preconditions + // otherwise this would interfere with necessary preconditions + solver.pop_context(); + summarizer_bw_cex.summarize(not_exprt(conjunction(failed_exprs))); property_map[it->first].result=summarizer_bw_cex.check(); solver.new_context(); @@ -242,4 +247,3 @@ void cover_goals_extt::assignment() _iterations++; // statistics } - diff --git a/src/2ls/dynamic_cfg.cpp b/src/2ls/dynamic_cfg.cpp index 807ec5ed3..c747a59e2 100644 --- a/src/2ls/dynamic_cfg.cpp +++ b/src/2ls/dynamic_cfg.cpp @@ -284,7 +284,8 @@ void dynamic_cfgt::build_from_invariants( if(summary.fw_invariant.id()==ID_implies) { build_from_invariant( - ssa, summary.fw_invariant, + ssa, + summary.fw_invariant, assumptions); } else if(summary.fw_invariant.id()==ID_and) @@ -293,9 +294,9 @@ void dynamic_cfgt::build_from_invariants( { assert(summary.fw_invariant.operands()[i].id()==ID_implies); build_from_invariant( - ssa, summary.fw_invariant.operands()[i], + ssa, + summary.fw_invariant.operands()[i], assumptions); } } } - diff --git a/src/2ls/graphml_witness_ext.h b/src/2ls/graphml_witness_ext.h index df62a2b6d..0b573dba5 100644 --- a/src/2ls/graphml_witness_ext.h +++ b/src/2ls/graphml_witness_ext.h @@ -27,8 +27,10 @@ class graphml_witness_extt:public graphml_witnesst void operator()(const summary_checker_baset &summary_checker); protected: + typedef std::map loc_to_node_mapt; + graphmlt::node_indext add_node( - std::map &loc_to_node, + loc_to_node_mapt &loc_to_node, goto_programt::const_targett it); void add_edge( diff --git a/src/2ls/instrument_goto.cpp b/src/2ls/instrument_goto.cpp index 3e550c6e1..647aaab10 100644 --- a/src/2ls/instrument_goto.cpp +++ b/src/2ls/instrument_goto.cpp @@ -115,8 +115,7 @@ Function: instrument_gotot::instrument_body void instrument_gotot::instrument_body( const local_SSAt &SSA, const exprt &expr, - goto_functionst::goto_functiont &function -) + goto_functionst::goto_functiont &function) { // expected format (/\_j g_j)=> inv const exprt &impl=expr.op0(); diff --git a/src/2ls/summary_checker_base.cpp b/src/2ls/summary_checker_base.cpp index 2c34120b6..786150630 100644 --- a/src/2ls/summary_checker_base.cpp +++ b/src/2ls/summary_checker_base.cpp @@ -104,7 +104,7 @@ void summary_checker_baset::summarize( bool forward, bool termination) { - summarizer_baset *summarizer=NULL; + summarizer_baset *summarizer=nullptr; #ifdef SHOW_CALLING_CONTEXTS if(options.get_bool_option("show-calling-contexts")) @@ -126,7 +126,7 @@ void summary_checker_baset::summarize( summarizer=new summarizer_bw_termt( options, summary_db, ssa_db, ssa_unwinder, ssa_inliner); } - assert(summarizer!=NULL); + assert(summarizer!=nullptr); summarizer->set_message_handler(get_message_handler()); @@ -198,9 +198,13 @@ summary_checker_baset::resultt summary_checker_baset::check_properties( #if 0 debug() << "Checking call " << fname << messaget::eom; #endif - if(seen_function_calls.find(fname)==seen_function_calls.end()){ + if(seen_function_calls.find(fname)==seen_function_calls.end()) + { seen_function_calls.insert(fname); - check_properties(fname, entry_function, seen_function_calls, + check_properties( + fname, + entry_function, + seen_function_calls, n_it->function_calls_inlined); } } @@ -230,7 +234,8 @@ summary_checker_baset::resultt summary_checker_baset::check_properties( if(options.get_bool_option("show-invariants")) { - if(!summary_db.exists(f_it->first)) continue; + if(!summary_db.exists(f_it->first)) + continue; show_invariants(*(f_it->second), summary_db.get(f_it->first), result()); result() << eom; } @@ -310,53 +315,77 @@ void summary_checker_baset::check_properties( solver << ssa_inliner.get_summaries(SSA); // spuriousness checkers - summarizer_bw_cex_baset *summarizer_bw_cex=NULL; - incremental_solvert* cex_complete_solver= - incremental_solvert::allocate(SSA.ns, - options.get_bool_option("refine")); + summarizer_bw_cex_baset *summarizer_bw_cex=nullptr; + incremental_solvert *cex_complete_solver= + incremental_solvert::allocate( + SSA.ns, + options.get_bool_option("refine")); #if 1 cex_complete_solver->set_message_handler(get_message_handler()); #endif if(options.get_option("spurious-check")=="abstract") { summarizer_bw_cex=new summarizer_bw_cex_ait( - options, summary_db, ssa_db, - ssa_unwinder, ssa_inliner, - entry_function, f_it->first); + options, + summary_db, + ssa_db, + ssa_unwinder, + ssa_inliner, + entry_function, + f_it->first); } else if(options.get_option("spurious-check")=="complete") { summarizer_bw_cex=new summarizer_bw_cex_completet( - options, summary_db, ssa_db, - ssa_unwinder, ssa_inliner, *cex_complete_solver, - entry_function, f_it->first); + options, + summary_db, + ssa_db, + ssa_unwinder, + ssa_inliner, + *cex_complete_solver, + entry_function, + f_it->first); } else if(options.get_option("spurious-check")=="wp") { summarizer_bw_cex=new summarizer_bw_cex_wpt( - options, summary_db, ssa_db, - ssa_unwinder, ssa_inliner, *cex_complete_solver, - entry_function, f_it->first); + options, + summary_db, + ssa_db, + ssa_unwinder, + ssa_inliner, + *cex_complete_solver, + entry_function, + f_it->first); } else if(options.get_option("spurious-check")=="all") { summarizer_bw_cex=new summarizer_bw_cex_allt( - options, summary_db, ssa_db, - ssa_unwinder, ssa_inliner, *cex_complete_solver, - entry_function, f_it->first); + options, + summary_db, + ssa_db, + ssa_unwinder, + ssa_inliner, + *cex_complete_solver, + entry_function, + f_it->first); } - else + else //NOLINT(*) #if 0 - if(options.get_bool_option("inline") || - options.get_option("spurious-check")=="concrete") + if(options.get_bool_option("inline") || + options.get_option("spurious-check")=="concrete") #endif - { - summarizer_bw_cex=new summarizer_bw_cex_concretet( - options, summary_db, ssa_db, - ssa_unwinder, ssa_inliner, - entry_function, f_it->first); - } - assert(summarizer_bw_cex!=NULL); + { + summarizer_bw_cex=new summarizer_bw_cex_concretet( + options, + summary_db, + ssa_db, + ssa_unwinder, + ssa_inliner, + entry_function, + f_it->first); + } + assert(summarizer_bw_cex!=nullptr); summarizer_bw_cex->set_message_handler(get_message_handler()); cover_goals_extt cover_goals( diff --git a/src/2ls/summary_checker_base.h b/src/2ls/summary_checker_base.h index 616705696..bf97dbabf 100644 --- a/src/2ls/summary_checker_base.h +++ b/src/2ls/summary_checker_base.h @@ -82,10 +82,10 @@ class summary_checker_baset:public property_checkert property_checkert::resultt check_properties(); property_checkert::resultt check_properties( - irep_idt function_name, - irep_idt entry_function, - std::set seen_function_calls, - bool is_inlined); + irep_idt function_name, + irep_idt entry_function, + std::set seen_function_calls, + bool is_inlined); void check_properties( const ssa_dbt::functionst::const_iterator f_it, irep_idt entry_function=""); diff --git a/src/deltacheck/deltacheck_parse_options.cpp b/src/deltacheck/deltacheck_parse_options.cpp deleted file mode 100644 index 7a5b44378..000000000 --- a/src/deltacheck/deltacheck_parse_options.cpp +++ /dev/null @@ -1,347 +0,0 @@ -/*******************************************************************\ - -Module: Command Line Interface - -Author: Daniel Kroening, kroening@kroening.com - -\*******************************************************************/ - -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "deltacheck_parse_options.h" -#include "version.h" -#include "analyzer.h" -#include "change_impact.h" -#include "../functions/path_util.h" - -/*******************************************************************\ - -Function: deltacheck_parse_optionst::deltacheck_parse_optionst - - Inputs: - - Outputs: - - Purpose: - -\*******************************************************************/ - -deltacheck_parse_optionst::deltacheck_parse_optionst( - int argc, const char **argv): - parse_options_baset(DELTACHECK_OPTIONS, argc, argv), - xml_interfacet(cmdline), - ui_message_handler( - cmdline.isset("xml-ui")?ui_message_handlert::XML_UI:ui_message_handlert::PLAIN, - "DeltaCheck " DELTACHECK_VERSION) -{ -} - -/*******************************************************************\ - -Function: deltacheck_parse_optionst::eval_verbosity - - Inputs: - - Outputs: - - Purpose: - -\*******************************************************************/ - -void deltacheck_parse_optionst::eval_verbosity() -{ - // our default verbosity - int v=messaget::M_STATISTICS; - - if(cmdline.isset("verbosity")) - { - v=unsafe_string2int(cmdline.get_value("verbosity")); - if(v<0) - v=0; - else if(v>10) - v=10; - } - - ui_message_handler.set_verbosity(v); -} - -/*******************************************************************\ - -Function: deltacheck_parse_optionst::get_command_line_options - - Inputs: - - Outputs: - - Purpose: - -\*******************************************************************/ - -void deltacheck_parse_optionst::get_command_line_options(optionst &options) -{ - if(config.set(cmdline)) - { - usage_error(); - exit(1); - } - - if(cmdline.isset("debug-level")) - options.set_option("debug-level", cmdline.get_value("debug-level")); - - // check array bounds - if(cmdline.isset("bounds-check")) - options.set_option("bounds-check", true); - else - options.set_option("bounds-check", false); - - // check division by zero - if(cmdline.isset("div-by-zero-check")) - options.set_option("div-by-zero-check", true); - else - options.set_option("div-by-zero-check", false); - - // check overflow/underflow - if(cmdline.isset("signed-overflow-check")) - options.set_option("signed-overflow-check", true); - else - options.set_option("signed-overflow-check", false); - - // check overflow/underflow - if(cmdline.isset("unsigned-overflow-check")) - options.set_option("unsigned-overflow-check", true); - else - options.set_option("unsigned-overflow-check", false); - - // check for NaN (not a number) - if(cmdline.isset("nan-check")) - options.set_option("nan-check", true); - else - options.set_option("nan-check", false); - - // check pointers - if(cmdline.isset("pointer-check")) - options.set_option("pointer-check", true); - else - options.set_option("pointer-check", false); - - // do we do inlining? - if(cmdline.isset("no-inlining")) - options.set_option("partial-inlining", false); - else - options.set_option("partial-inlining", true); - - // check assertions - options.set_option("assertions", true); - - // use assumptions - options.set_option("assumptions", true); -} - -/*******************************************************************\ - -Function: deltacheck_parse_optionst::register_langauges - - Inputs: - - Outputs: - - Purpose: - -\*******************************************************************/ - -void deltacheck_parse_optionst::register_languages() -{ - register_language(new_ansi_c_language); - register_language(new_cpp_language); -} - -/*******************************************************************\ - -Function: deltacheck_parse_optionst::doit - - Inputs: - - Outputs: - - Purpose: invoke main modules - -\*******************************************************************/ - -int deltacheck_parse_optionst::doit() -{ - if(cmdline.isset("version")) - { - std::cout << DELTACHECK_VERSION << std::endl; - return 0; - } - - register_languages(); - - // command line options - - optionst options; - get_command_line_options(options); - set_message_handler(ui_message_handler); - eval_verbosity(); - - try - { - options.set_option("simplify", true); - options.set_option("assertions", true); - options.set_option("assumptions", true); - - if(cmdline.isset("function")) - options.set_option("function", cmdline.get_value("function")); - - if(cmdline.args.size()!=2) - { - usage_error(); - return 10; - } - - if(cmdline.isset("description-old")) - options.set_option("description-old", cmdline.get_value("description-old")); - else - options.set_option("description-old", cmdline.args[0]); - - if(cmdline.isset("description-new")) - options.set_option("description-new", cmdline.get_value("description-new")); - else - options.set_option("description-new", cmdline.args[1]); - - status() << "Reading first GOTO program from file" << eom; - - goto_modelt goto_model1; - - if(read_goto_binary(cmdline.args[0], - goto_model1, get_message_handler())) - return 10; - - status() << "Reading second GOTO program from file" << eom; - - goto_modelt goto_model2; - - if(read_goto_binary(cmdline.args[1], - goto_model2, get_message_handler())) - return 10; - - if(cmdline.isset("show-diff")) - { - change_impactt change_impact; - change_impact.set_message_handler(get_message_handler()); - - change_impact.diff(goto_model1, goto_model2); - change_impact.output_diff(std::cout); - } - else if(cmdline.isset("show-change-impact")) - { - change_impactt change_impact; - change_impact.set_message_handler(get_message_handler()); - - status() << "Computing syntactic difference" << eom; - change_impact.diff(goto_model1, goto_model2); - - status() << "Change-impact analysis" << eom; - change_impact.change_impact(goto_model2); - - change_impact.output_change_impact(std::cout); - } - else - { - std::string path1=get_directory(cmdline.args[0]); - std::string path2=get_directory(cmdline.args[1]); - - deltacheck_analyzer( - path1, goto_model1, - path2, goto_model2, - options, get_message_handler()); - } - - return 0; - } - - catch(const char *e) - { - error() << e << eom; - return 13; - } - - catch(const std::string &e) - { - error() << e << eom; - return 13; - } - - catch(int) - { - return 13; - } - - catch(std::bad_alloc) - { - error() << "Out of memory" << eom; - return 14; - } - - return 0; -} - -/*******************************************************************\ - -Function: deltacheck_parse_optionst::help - - Inputs: - - Outputs: - - Purpose: display command line help - -\*******************************************************************/ - -void deltacheck_parse_optionst::help() -{ - std::cout << - "\n" - "* * DELTACHECK " DELTACHECK_VERSION "-Copyright (C) 2011-2015 * *\n" - "* * based on CBMC " CBMC_VERSION " * *\n" - "* * Daniel Kroening * *\n" - "* * Oxford University, Computer Science Department * *\n" - "* * kroening@kroening.com * *\n" - "\n" - "Usage: Purpose:\n" - "\n" - " deltacheck [-?] [-h] [--help] show help\n" - " deltacheck prog1 prog2 delta check two programs\n" - "\n" - "Delta checking options:\n" - " --show-change-impact show syntactic change-impact\n" - " --description-old text description of old version\n" - " --description-new text description of new version\n" - "\n" - "Safety checks:\n" - " --bounds-check add array bounds checks\n" - " --div-by-zero-check add division by zero checks\n" - " --pointer-check add pointer checks\n" - " --signed-overflow-check add arithmetic over- and underflow checks\n" - " --unsigned-overflow-check add arithmetic over- and underflow checks\n" - " --nan-check add floating-point NaN checks\n" - "\n" - "Other options:\n" - " --version show version and exit\n" - " --xml-ui use XML-formatted output\n" - " --xml-interface stdio-XML interface\n" - "\n"; -} diff --git a/src/deltacheck/deltacheck_parse_options.h b/src/deltacheck/deltacheck_parse_options.h deleted file mode 100644 index bb3241d33..000000000 --- a/src/deltacheck/deltacheck_parse_options.h +++ /dev/null @@ -1,52 +0,0 @@ -/*******************************************************************\ - -Module: Command Line Interface - -Author: Daniel Kroening, kroening@kroening.com - -\*******************************************************************/ - -#ifndef CPROVER_DELTACHECK_PARSE_OPTIONS_H -#define CPROVER_DELTACHECK_PARSE_OPTIONS_H - -#include -#include -#include - -#include -#include - -#define DELTACHECK_OPTIONS \ - "(function):" \ - "(debug-level):" \ - "(xml-ui)(xml-interface)" \ - "(verbosity):(version)(index):(description-old):(description-new):" \ - "(bounds-check)(pointer-check)(div-by-zero-check)" \ - "(signed-overflow-check)(unsigned-overflow-check)(nan-check)" \ - "(show-ssa)(show-defs)(show-guards)(show-fixed-points)" \ - "(show-properties)(show-change-impact)(show-diff)" \ - "(no-inline)(sat)" - -class deltacheck_parse_optionst: - public parse_options_baset, - public xml_interfacet, - public messaget -{ -public: - virtual int doit(); - virtual void help(); - - deltacheck_parse_optionst( - int argc, const char **argv); - -protected: - virtual void register_languages(); - - virtual void get_command_line_options(optionst &options); - - void eval_verbosity(); - - ui_message_handlert ui_message_handler; -}; - -#endif diff --git a/src/deltagit/deltagit_parse_options.cpp b/src/deltagit/deltagit_parse_options.cpp deleted file mode 100644 index 3868415b1..000000000 --- a/src/deltagit/deltagit_parse_options.cpp +++ /dev/null @@ -1,206 +0,0 @@ -/*******************************************************************\ - -Module: Command Line Interface - -Author: Daniel Kroening, kroening@kroening.com - -\*******************************************************************/ - -#include - -#include - -#include - -#include "../deltacheck/version.h" - -#include "show_jobs.h" -#include "do_job.h" -#include "init.h" -#include "reset.h" -#include "reanalyse.h" -#include "deltagit_parse_options.h" -#include "revisions_report.h" - -/*******************************************************************\ - -Function: deltagit_parse_optionst::deltagit_parse_optionst - - Inputs: - - Outputs: - - Purpose: - -\*******************************************************************/ - -deltagit_parse_optionst::deltagit_parse_optionst( - int argc, const char **argv): - parse_options_baset(DELTACHECK_OPTIONS, argc, argv) -{ -} - -/*******************************************************************\ - -Function: deltagit_parse_optionst::doit - - Inputs: - - Outputs: - - Purpose: invoke main modules - -\*******************************************************************/ - -int deltagit_parse_optionst::doit() -{ - if(cmdline.isset("version")) - { - std::cout << DELTACHECK_VERSION << std::endl; - return 0; - } - - try - { - if(cmdline.args.size()==0) - { - usage_error(); - return 10; - } - - const std::string command=cmdline.args[0]; - - if(command=="jobs") - { - show_jobs(std::cout); - } - else if(command=="init") - { - if(cmdline.args.size()==1) - { - init(0); - } - else if(cmdline.args.size()==2) - { - init(atoi(cmdline.args[1].c_str())); - } - else - { - usage_error(); - return 10; - } - } - else if(command=="do") - { - if(cmdline.args.size()==2) - { - do_job(cmdline.args[1]); - } - else if(cmdline.args.size()==1) - { - do_job(); - } - else - { - usage_error(); - return 10; - } - } - else if(command=="reset") - { - if(cmdline.args.size()==2) - reset(cmdline.args[1]); - else if(cmdline.args.size()==1) - reset(); - else - { - usage_error(); - return 10; - } - } - else if(command=="reanalyse") - { - if(cmdline.args.size()==2) - reanalyse(cmdline.args[1]); - else if(cmdline.args.size()==1) - reanalyse(); - else - { - usage_error(); - return 10; - } - } - else if(command=="report") - { - bool partial_html=cmdline.isset("partial-html"); - unsigned max_revs=0; - std::string rel_path; - if(cmdline.isset("max-revs")) - max_revs=unsafe_string2unsigned(cmdline.get_value("max-revs")); - if(partial_html) - rel_path=cmdline.get_value("partial-html"); - revisions_report(partial_html, rel_path, max_revs); - } - else - { - usage_error(); - return 10; - } - } - - catch(const std::string &e) - { - std::cerr << e << std::endl; - return 13; - } - - catch(std::bad_alloc) - { - std::cerr << "Out of memory" << std::endl; - return 14; - } - - return 0; -} - -/*******************************************************************\ - -Function: deltagit_parse_optionst::help - - Inputs: - - Outputs: - - Purpose: display command line help - -\*******************************************************************/ - -void deltagit_parse_optionst::help() -{ - std::cout << - "\n" - "* * DELTAGIT " DELTACHECK_VERSION "-Copyright (C) 2012-2013 * *\n" - "* * Daniel Kroening * *\n" - "* * Oxford University, Computer Science Department * *\n" - "* * kroening@kroening.com * *\n" - "\n" - "Usage: Purpose:\n" - "\n" - " deltagit [-?] [-h] [--help] show help\n" - " deltagit init set up the jobs\n" - " deltagit jobs list the jobs\n" - " deltagit do do given job\n" - " deltagit do do a job that needs work\n" - " deltagit reset clear failure bit on all jobs\n" - " deltagit reanalyse redo analysis\n" - " deltagit report generate top-level report\n" - "\n" - "Reporting options:\n" - " --partial-html generate a partial HTML file \"include.html\"\n" - " --max-revs report on the last revisions\n" - "\n" - "Other options:\n" - " --version show version and exit\n" - " --xml-ui use XML-formatted output\n" - "\n"; -} diff --git a/src/deltagit/deltagit_parse_options.h b/src/deltagit/deltagit_parse_options.h deleted file mode 100644 index 357f563ab..000000000 --- a/src/deltagit/deltagit_parse_options.h +++ /dev/null @@ -1,30 +0,0 @@ -/*******************************************************************\ - -Module: Command Line Interface - -Author: Daniel Kroening, kroening@kroening.com - -\*******************************************************************/ - -#ifndef CPROVER_DELTACHECK_PARSE_OPTIONS_H -#define CPROVER_DELTACHECK_PARSE_OPTIONS_H - -#include - -#define DELTACHECK_OPTIONS \ - "(verbosity):(version)(description):" \ - "(max-revs):(partial-html):" - -class deltagit_parse_optionst:public parse_options_baset -{ -public: - virtual int doit(); - virtual void help(); - - deltagit_parse_optionst( - int argc, const char **argv); - -protected: -}; - -#endif diff --git a/src/domains/disjunctive_analyzer.cpp b/src/domains/disjunctive_analyzer.cpp index 9424d1945..28d506624 100644 --- a/src/domains/disjunctive_analyzer.cpp +++ b/src/domains/disjunctive_analyzer.cpp @@ -12,7 +12,6 @@ Author: Peter Schrammel, Kumar Madhukar #include "ssa_analyzer.h" #include "disjunctive_analyzer.h" - /*******************************************************************\ Function: disjunctive_analyzert::eliminate_implication() @@ -32,8 +31,6 @@ void disjunctive_analyzert::eliminate_implication(exprt &formula) Forall_operands(it, formula) eliminate_implication(*it); - - return; } /*******************************************************************\ @@ -50,30 +47,34 @@ Function: disjunctive_analyzert::push_negation_to_atoms() void disjunctive_analyzert::push_negation_to_atoms(exprt &formula) { - if(formula.id()==ID_not){ - if((formula.op0()).id()==ID_not){ + if(formula.id()==ID_not) + { + if((formula.op0()).id()==ID_not) + { formula=(formula.op0()).op0(); } - else{ + else + { exprt::operandst operands; Forall_operands(it, formula.op0()) - operands.push_back(not_exprt(*it)); + operands.push_back(not_exprt(*it)); - if((formula.op0()).id()==ID_and){ - formula=disjunction(operands); + if((formula.op0()).id()==ID_and) + { + formula=disjunction(operands); } - else{ - if((formula.op0()).id()==ID_or){ - formula=conjunction(operands); - } + else + { + if((formula.op0()).id()==ID_or) + { + formula=conjunction(operands); + } } } } Forall_operands(it, formula) push_negation_to_atoms(*it); - - return; } /*******************************************************************\ @@ -90,11 +91,9 @@ Function: disjunctive_analyzert::convert_to_dnf() void disjunctive_analyzert::convert_to_dnf(exprt &formula) { - this->eliminate_implication(formula); - this->push_negation_to_atoms(formula); - this->convert_to_dnf_rec(formula); - - return; + eliminate_implication(formula); + push_negation_to_atoms(formula); + convert_to_dnf_rec(formula); } /*******************************************************************\ @@ -111,44 +110,47 @@ Function: disjunctive_analyzert::convert_to_dnf_rec() void disjunctive_analyzert::convert_to_dnf_rec(exprt &formula) { - if(formula.id()==ID_or){ + if(formula.id()==ID_or) + { Forall_operands(it, formula) convert_to_dnf_rec(*it); } - else{ - if(formula.id()==ID_and){ - - Forall_operands(it, formula) - convert_to_dnf_rec(*it); - - while((formula.operands()).size() > 1){ - exprt::operandst first_operands, second_operands, combination; - - if(((formula.operands()).back()).id()==ID_or) - first_operands=((formula.operands()).back()).operands(); else - first_operands.push_back((formula.operands()).back()); - formula.operands().pop_back(); - - if(((formula.operands()).back()).id()==ID_or) - second_operands=((formula.operands()).back()).operands(); - else - second_operands.push_back((formula.operands()).back()); - formula.operands().pop_back(); - - for(exprt::operandst::iterator f_it=first_operands.begin();f_it!=first_operands.end();f_it++){ - for(exprt::operandst::iterator s_it=second_operands.begin();s_it!=second_operands.end();s_it++){ - combination.push_back(and_exprt(*f_it, *s_it)); - } - } - - (formula.operands()).push_back(disjunction(combination)); + { + if(formula.id()==ID_and) + { + Forall_operands(it, formula) + convert_to_dnf_rec(*it); + + while((formula.operands()).size()>1) + { + exprt::operandst first_operands, second_operands, combination; + + if(((formula.operands()).back()).id()==ID_or) + first_operands=((formula.operands()).back()).operands(); + else + first_operands.push_back((formula.operands()).back()); + formula.operands().pop_back(); + + if(((formula.operands()).back()).id()==ID_or) + second_operands=((formula.operands()).back()).operands(); + else + second_operands.push_back((formula.operands()).back()); + formula.operands().pop_back(); + + for(const auto &fo : first_operands) + { + for(const auto &so : second_operands) + { + combination.push_back(and_exprt(fo, so)); + } + } + + formula.operands().push_back(disjunction(combination)); } formula=formula.op0(); } } - - return; } /*******************************************************************\ @@ -164,127 +166,137 @@ Function: disjunctive_analyzert::operator() \*******************************************************************/ bool disjunctive_analyzert::operator()( - incremental_solvert &solver, - local_SSAt &SSA, - const exprt &side_conditions, - template_generator_baset &template_generator, - const exprt &disjunctive_conditions, - exprt &result_expr, - const domaint::var_sett &vars - ) + incremental_solvert &solver, + local_SSAt &SSA, + const exprt &side_conditions, + template_generator_baset &template_generator, + const exprt &disjunctive_conditions, + exprt &result_expr, + const domaint::var_sett &vars) { bool response=true; exprt::operandst result; - // std::cout << "unsimplified disjunctive cond: " << from_expr(SSA.ns, "", disjunctive_conditions) << "\n\n"; - exprt simple_disjunctive_conditions=simplify_expr(disjunctive_conditions, SSA.ns); // disjunctive_conditions; - // std::cout << " simplified disjunctive cond: " << from_expr(SSA.ns, "", simple_disjunctive_conditions) << "\n\n"; + exprt simple_disjunctive_conditions= + simplify_expr(disjunctive_conditions, SSA.ns); // disjunctive_conditions // converting simple_disjunctive_conditions into DNF - // std::cout << "before conversion: " << from_expr(SSA.ns, "", simple_disjunctive_conditions) << "\n\n\n"; - this->convert_to_dnf(simple_disjunctive_conditions); - // std::cout << " after conversion: " << from_expr(SSA.ns, "", simple_disjunctive_conditions) << "\n\n\n"; - - if(simple_disjunctive_conditions.id()==ID_or){ + convert_to_dnf(simple_disjunctive_conditions); + if(simple_disjunctive_conditions.id()==ID_or) + { exprt::operandst processed_disjuncts; exprt::operandst disjuncts=simple_disjunctive_conditions.operands(); - for(exprt::operandst::iterator d_it=disjuncts.begin();d_it!=disjuncts.end();d_it++){ - if((*d_it).id()==ID_not){ - // std::cout << "processing (not) disjunct: " << from_expr(SSA.ns, "", *d_it) << "\n"; - - exprt::operandst ops=(*d_it).operands(); - for(exprt::operandst::iterator o_it=ops.begin();o_it!=ops.end();o_it++){ - if((*o_it).id()==ID_equal){ - exprt::operandst ops_equality=(*o_it).operands(); - equal_exprt equal_expr_in_not=to_equal_expr(*o_it); - - bool constant_comparison=false; - for(exprt::operandst::iterator oe_it=ops_equality.begin();oe_it!=ops_equality.end();oe_it++){ - if((*oe_it).id()==ID_constant) - constant_comparison=true; - } - if(constant_comparison){ - processed_disjuncts.push_back(binary_relation_exprt(equal_expr_in_not.rhs(), ID_gt, equal_expr_in_not.lhs())); - processed_disjuncts.push_back(binary_relation_exprt(equal_expr_in_not.rhs(), ID_lt, equal_expr_in_not.lhs())); - } - else{ - processed_disjuncts.push_back(*d_it); - } - } - else{ - processed_disjuncts.push_back(*d_it); - } - } + for(auto &d : disjuncts) + { + if(d.id()==ID_not) + { + exprt::operandst ops=d.operands(); + for(auto &op : ops) + { + if(op.id()==ID_equal) + { + exprt::operandst ops_equality=op.operands(); + equal_exprt equal_expr_in_not=to_equal_expr(op); + + bool constant_comparison=false; + for(auto &oe : ops_equality) + { + if(oe.id()==ID_constant) + constant_comparison=true; + } + if(constant_comparison) + { + processed_disjuncts.push_back( + binary_relation_exprt( + equal_expr_in_not.rhs(), ID_gt, equal_expr_in_not.lhs())); + processed_disjuncts.push_back( + binary_relation_exprt( + equal_expr_in_not.rhs(), ID_lt, equal_expr_in_not.lhs())); + } + else + { + processed_disjuncts.push_back(d); + } + } + else + { + processed_disjuncts.push_back(d); + } + } } - else{ - processed_disjuncts.push_back(*d_it); + else + { + processed_disjuncts.push_back(d); } } - for(exprt::operandst::iterator it=processed_disjuncts.begin();it!=processed_disjuncts.end();it++){ - - // std::cout << "disjunct: " << from_expr(SSA.ns, "", *it) << "\n"; - + for(auto &d : processed_disjuncts) + { std::set disjunct_symbols; - find_symbols(*it, disjunct_symbols); + find_symbols(d, disjunct_symbols); // TODO: decompose into convex regions for all variables // assert(disjunct_symbols.size()==1); + // TODO: unclear what this loop should be doing symbol_exprt var; - for(std::set::const_iterator ds_it=disjunct_symbols.begin(); - ds_it!=disjunct_symbols.end(); ds_it++){ - var=*ds_it; + for(const auto &ds : disjunct_symbols) + { + var=ds; } - // std::cout << "symbol expr in disjunct: " << var << "\n\n"; exprt::operandst split_disjuncts; - if((var.type().id()==ID_signedbv) || (var.type().id()==ID_unsignedbv)){ - - exprt smallest; - if(var.type().id()==ID_signedbv) - smallest=to_signedbv_type(var.type()).smallest_expr(); - if(var.type().id()==ID_unsignedbv) - smallest=to_unsignedbv_type(var.type()).smallest_expr(); - - split_disjuncts.push_back - (and_exprt(*it, binary_relation_exprt(var, ID_ge, plus_exprt(smallest, from_integer(mp_integer(1), var.type()))))); - - split_disjuncts.push_back(and_exprt(*it, binary_relation_exprt(var, ID_equal, smallest))); + if((var.type().id()==ID_signedbv) || (var.type().id()==ID_unsignedbv)) + { + exprt smallest; + if(var.type().id()==ID_signedbv) + smallest=to_signedbv_type(var.type()).smallest_expr(); + if(var.type().id()==ID_unsignedbv) + smallest=to_unsignedbv_type(var.type()).smallest_expr(); + + split_disjuncts.push_back( + and_exprt( + d, + binary_relation_exprt( + var, + ID_ge, + plus_exprt(smallest, from_integer(mp_integer(1), var.type()))))); + + split_disjuncts.push_back( + and_exprt(d, binary_relation_exprt(var, ID_equal, smallest))); } - else{ - split_disjuncts.push_back(*it); + else + { + split_disjuncts.push_back(d); } - for(exprt::operandst::iterator s_it=split_disjuncts.begin();s_it!=split_disjuncts.end();s_it++){ + for(auto &sd : split_disjuncts) + { ssa_analyzert analyzer; - analyzer.set_message_handler(get_message_handler()); - exprt cc=simplify_expr((and_exprt(side_conditions, *s_it)), SSA.ns); - response=response && (analyzer(solver, SSA, cc, template_generator)); + analyzer.set_message_handler(get_message_handler()); + exprt cc=simplify_expr((and_exprt(side_conditions, sd)), SSA.ns); + response=response && (analyzer(solver, SSA, cc, template_generator)); - exprt res; - analyzer.get_result(res, vars); - result.push_back(res); + exprt res; + analyzer.get_result(res, vars); + result.push_back(res); - // std::cout << "disjunct passed: " << from_expr(SSA.ns, "", cc) << "\n"; - // std::cout << "disjunct's result: " << from_expr(SSA.ns, "", res) << "\n"; - - // statistics - solver_instances+=analyzer.get_number_of_solver_instances(); - solver_calls+=analyzer.get_number_of_solver_calls(); + // statistics + solver_instances+=analyzer.get_number_of_solver_instances(); + solver_calls+=analyzer.get_number_of_solver_calls(); } } } - else{ + else + { // for the complete disjunctive_conditions at once - // std::cout << "disjunction not at top-level" << "\n"; - ssa_analyzert analyzer; analyzer.set_message_handler(get_message_handler()); - exprt cc=simplify_expr((and_exprt(side_conditions, simple_disjunctive_conditions)), SSA.ns); + exprt cc=simplify_expr( + and_exprt(side_conditions, simple_disjunctive_conditions), SSA.ns); response=analyzer(solver, SSA, cc, template_generator); @@ -292,9 +304,6 @@ bool disjunctive_analyzert::operator()( analyzer.get_result(res, vars); result.push_back(res); - // std::cout << "disjunct passed: " << from_expr(SSA.ns, "", cc) << "\n"; - // std::cout << "disjunct's result: " << from_expr(SSA.ns, "", res) << "\n"; - // statistics solver_instances+=analyzer.get_number_of_solver_instances(); solver_calls+=analyzer.get_number_of_solver_calls(); diff --git a/src/domains/disjunctive_analyzer.h b/src/domains/disjunctive_analyzer.h index 7a1cafbca..1b021bbb3 100644 --- a/src/domains/disjunctive_analyzer.h +++ b/src/domains/disjunctive_analyzer.h @@ -9,10 +9,10 @@ Author: Peter Schrammel, Kumar Madhukar #ifndef CPROVER_2LS_DOMAINS_DISJUNCTIVE_ANALYZER_H #define CPROVER_2LS_DOMAINS_DISJUNCTIVE_ANALYZER_H -class disjunctive_analyzert : public messaget +class disjunctive_analyzert:public messaget { public: - explicit disjunctive_analyzert(): + disjunctive_analyzert(): solver_instances(0), solver_calls(0) { diff --git a/src/domains/domain_refinement.h b/src/domains/domain_refinement.h index b265b0ea0..7cd6155ae 100644 --- a/src/domains/domain_refinement.h +++ b/src/domains/domain_refinement.h @@ -6,12 +6,12 @@ Author: Peter Schrammel \*******************************************************************/ -#ifndef CPROVER_DOMAIN_REFINEMENT_H -#define CPROVER_DOMAIN_REFINEMENT_H +#ifndef CPROVER_2LS_DOMAINS_DOMAIN_REFINEMENT_H +#define CPROVER_2LS_DOMAINS_DOMAIN_REFINEMENT_H #include "incremental_solver.h" #include "template_generator_base.h" -#include "../ssa/local_SSA.h" +#include class domain_refinementt { @@ -36,4 +36,4 @@ class domain_refinementt incremental_solvert &solver; }; -#endif +#endif // CPROVER_2LS_DOMAINS_DOMAIN_REFINEMENT_H diff --git a/src/domains/incremental_solver.h b/src/domains/incremental_solver.h index f25f2ef57..4c7acc3b1 100644 --- a/src/domains/incremental_solver.h +++ b/src/domains/incremental_solver.h @@ -108,7 +108,7 @@ class incremental_solvert:public messaget } } #endif -#if (defined(DEBUG_FORMULA) && defined(DEBUG_OUTPUT)) || defined(DISPLAY_FORMULA) +#if (defined(DEBUG_FORMULA) && defined(DEBUG_OUTPUT)) || defined(DISPLAY_FORMULA) // NOLINT(whitespace/line_length) if(result==decision_proceduret::D_SATISFIABLE) { std::set vars; @@ -236,7 +236,9 @@ static inline incremental_solvert &operator<<( #else if(!dest.activation_literals.empty()) dest.debug_add_to_formula( - or_exprt(src, literal_exprt(!dest.activation_literals.back()))); + or_exprt( + src, + literal_exprt(!dest.activation_literals.back()))); else dest.debug_add_to_formula(src); #endif diff --git a/src/domains/lexlinrank_solver_enumeration.cpp b/src/domains/lexlinrank_solver_enumeration.cpp index 223ad8b8d..68633968f 100644 --- a/src/domains/lexlinrank_solver_enumeration.cpp +++ b/src/domains/lexlinrank_solver_enumeration.cpp @@ -32,7 +32,8 @@ Function: lexlinrank_solver_enumerationt::iterate \*******************************************************************/ -lexlinrank_solver_enumerationt::progresst lexlinrank_solver_enumerationt::iterate(invariantt &_rank) +lexlinrank_solver_enumerationt::progresst +lexlinrank_solver_enumerationt::iterate(invariantt &_rank) { lexlinrank_domaint::templ_valuet &rank= static_cast(_rank); diff --git a/src/domains/predabs_domain.h b/src/domains/predabs_domain.h index b63e8520c..cb3095e85 100644 --- a/src/domains/predabs_domain.h +++ b/src/domains/predabs_domain.h @@ -73,8 +73,8 @@ class predabs_domaint:public domaint // printing virtual void output_value( std::ostream &out, - const valuet &value, const - namespacet &ns) const; + const valuet &value, + const namespacet &ns) const; virtual void output_domain(std::ostream &out, const namespacet &ns) const; // projection diff --git a/src/domains/ranking_solver_enumeration.cpp b/src/domains/ranking_solver_enumeration.cpp index 2d35335be..bd04196d9 100644 --- a/src/domains/ranking_solver_enumeration.cpp +++ b/src/domains/ranking_solver_enumeration.cpp @@ -28,7 +28,8 @@ Function: ranking_solver_enumerationt::iterate \*******************************************************************/ -ranking_solver_enumerationt::progresst ranking_solver_enumerationt::iterate(invariantt &_rank) +ranking_solver_enumerationt::progresst +ranking_solver_enumerationt::iterate(invariantt &_rank) { linrank_domaint::templ_valuet &rank= static_cast(_rank); diff --git a/src/domains/simplify_bounds.h b/src/domains/simplify_bounds.h index 6799b76a2..df8ce143c 100644 --- a/src/domains/simplify_bounds.h +++ b/src/domains/simplify_bounds.h @@ -6,8 +6,8 @@ Author: Peter Schrammel \*******************************************************************/ -#ifndef CPROVER_SIMPLIFY_BOUNDS_H -#define CPROVER_SIMPLIFY_BOUNDS_H +#ifndef CPROVER_2LS_DOMAINS_SIMPLIFY_BOUNDS_H +#define CPROVER_2LS_DOMAINS_SIMPLIFY_BOUNDS_H #include @@ -29,4 +29,4 @@ exprt simplify_bounds( const exprt &src, const namespacet &ns); -#endif +#endif // CPROVER_2LS_DOMAINS_SIMPLIFY_BOUNDS_H diff --git a/src/domains/simplify_bounds_class.h b/src/domains/simplify_bounds_class.h index 941320572..c4622c100 100644 --- a/src/domains/simplify_bounds_class.h +++ b/src/domains/simplify_bounds_class.h @@ -6,8 +6,8 @@ Author: Peter Schrammel \*******************************************************************/ -#ifndef CPROVER_SIMPLIFY_BOUNDS_CLASS_H -#define CPROVER_SIMPLIFY_BOUNDS_CLASS_H +#ifndef CPROVER_2LS_DOMAINS_SIMPLIFY_BOUNDS_CLASS_H +#define CPROVER_2LS_DOMAINS_SIMPLIFY_BOUNDS_CLASS_H #include #include @@ -39,14 +39,18 @@ class simplify_boundst } inline static mp_integer get_largest(const typet &type) { - if(type.id()==ID_signedbv) return to_signedbv_type(type).largest(); - else if(type.id()==ID_unsignedbv) return to_unsignedbv_type(type).largest(); + if(type.id()==ID_signedbv) + return to_signedbv_type(type).largest(); + else if(type.id()==ID_unsignedbv) + return to_unsignedbv_type(type).largest(); assert(false); } inline static mp_integer get_smallest(const typet &type) { - if(type.id()==ID_signedbv) return to_signedbv_type(type).smallest(); - else if(type.id()==ID_unsignedbv) return to_unsignedbv_type(type).smallest(); + if(type.id()==ID_signedbv) + return to_signedbv_type(type).smallest(); + else if(type.id()==ID_unsignedbv) + return to_unsignedbv_type(type).smallest(); assert(false); } @@ -60,7 +64,6 @@ class simplify_boundst bool clean_up_implications(exprt &expr); bool regroup_implications(exprt &expr); bool clean_up_typecast(exprt &expr, const mp_integer &value); - }; -#endif +#endif // CPROVER_2LS_DOMAINS_SIMPLIFY_BOUNDS_CLASS_H diff --git a/src/domains/simplify_transformer.cpp b/src/domains/simplify_transformer.cpp index 4a8db3274..ebddc12ea 100644 --- a/src/domains/simplify_transformer.cpp +++ b/src/domains/simplify_transformer.cpp @@ -31,10 +31,11 @@ Function: simplify_transformert::collect_node \*******************************************************************/ -void simplify_transformert::collect_node(const exprt &expr, - replace_mapt &substitutions, - bool frozen_only, - bool make_copy) +void simplify_transformert::collect_node( + const exprt &expr, + replace_mapt &substitutions, + bool frozen_only, + bool make_copy) { if(expr.id()==ID_equal) { @@ -99,8 +100,9 @@ Function: simplify_transformert::simplify_node \*******************************************************************/ -bool simplify_transformert::simplify_node(exprt &expr, - const replace_mapt &substitutions) +bool simplify_transformert::simplify_node( + exprt &expr, + const replace_mapt &substitutions) { return replace_expr(substitutions, expr); } @@ -118,8 +120,9 @@ Function: simplify_transformert::simplify_rec \*******************************************************************/ -bool simplify_transformert::simplify_rec(exprt &expr, - replace_mapt &substitutions) +bool simplify_transformert::simplify_rec( + exprt &expr, + replace_mapt &substitutions) { #ifdef DEBUGX exprt old(expr); @@ -217,9 +220,10 @@ Function: simplify \*******************************************************************/ -bool simplify(exprt &expr, - const std::set &frozen_vars, - const namespacet &ns) +bool simplify( + exprt &expr, + const std::set &frozen_vars, + const namespacet &ns) { return simplify_transformert(ns, frozen_vars)(expr); } @@ -236,9 +240,10 @@ Function: simplify_transformer \*******************************************************************/ -exprt simplify_transformer(const exprt &src, - const std::set &frozen_vars, - const namespacet &ns) +exprt simplify_transformer( + const exprt &src, + const std::set &frozen_vars, + const namespacet &ns) { #ifdef DEBUGX std::cout << "FROZEN:"; diff --git a/src/domains/simplify_transformer.h b/src/domains/simplify_transformer.h index 19d6b7c99..31779d6f0 100644 --- a/src/domains/simplify_transformer.h +++ b/src/domains/simplify_transformer.h @@ -6,8 +6,8 @@ Author: Peter Schrammel \*******************************************************************/ -#ifndef CPROVER_SIMPLIFY_TRANSFORMER_H -#define CPROVER_SIMPLIFY_TRANSFORMER_H +#ifndef CPROVER_2LS_DOMAINS_SIMPLIFY_TRANSFORMER_H +#define CPROVER_2LS_DOMAINS_SIMPLIFY_TRANSFORMER_H #include #include @@ -32,4 +32,4 @@ exprt simplify_transformer( const std::set &frozen_vars, // do not eliminate these const namespacet &ns); -#endif +#endif // CPROVER_2LS_DOMAINS_SIMPLIFY_TRANSFORMER_H diff --git a/src/domains/simplify_transformer_class.h b/src/domains/simplify_transformer_class.h index 2129c44f6..9a9218516 100644 --- a/src/domains/simplify_transformer_class.h +++ b/src/domains/simplify_transformer_class.h @@ -6,8 +6,8 @@ Author: Peter Schrammel \*******************************************************************/ -#ifndef CPROVER_SIMPLIFY_TRANSFORMER_CLASS_H -#define CPROVER_SIMPLIFY_TRANSFORMER_CLASS_H +#ifndef CPROVER_2LS_DOMAINS_SIMPLIFY_TRANSFORMER_CLASS_H +#define CPROVER_2LS_DOMAINS_SIMPLIFY_TRANSFORMER_CLASS_H #include #include @@ -18,8 +18,9 @@ class namespacet; class simplify_transformert { public: - explicit simplify_transformert(const namespacet &_ns, - const std::set &_frozen_symbols): + simplify_transformert( + const namespacet &_ns, + const std::set &_frozen_symbols): ns(_ns), frozen_symbols(_frozen_symbols) { @@ -49,11 +50,12 @@ class simplify_transformert const std::set &frozen_symbols; void collect_node( - const exprt &expr, replace_mapt &substitutions, + const exprt &expr, + replace_mapt &substitutions, bool frozen_only, bool make_copy); - bool simplify_node(exprt &expr, const replace_mapt &substitutions); + bool simplify_node(exprt &expr, const replace_mapt &substitutions); }; -#endif +#endif // CPROVER_2LS_DOMAINS_SIMPLIFY_TRANSFORMER_CLASS_H diff --git a/src/domains/ssa_analyzer.cpp b/src/domains/ssa_analyzer.cpp index c01a1917e..8546b5186 100644 --- a/src/domains/ssa_analyzer.cpp +++ b/src/domains/ssa_analyzer.cpp @@ -175,14 +175,16 @@ bool ssa_analyzert::operator()( status==strategy_solver_baset::FAILED) { nonpassed_assertionst::iterator it=nonpassed_assertions.begin(); - for(unsigned i=0;il_get(assertion_literals[i]).is_true()) nonpassed_assertions.erase(it++); - else ++it; + else + ++it; } } - else nonpassed_assertions.clear(); + else + nonpassed_assertions.clear(); solver.pop_context(); diff --git a/src/domains/strategy_solver_binsearch.cpp b/src/domains/strategy_solver_binsearch.cpp index 6731ef713..687eed4da 100644 --- a/src/domains/strategy_solver_binsearch.cpp +++ b/src/domains/strategy_solver_binsearch.cpp @@ -25,7 +25,8 @@ Function: strategy_solver_binsearcht::iterate \*******************************************************************/ -strategy_solver_baset::progresst strategy_solver_binsearcht::iterate(invariantt &_inv) +strategy_solver_baset::progresst strategy_solver_binsearcht::iterate( + invariantt &_inv) { tpolyhedra_domaint::templ_valuet &inv= static_cast(_inv); diff --git a/src/domains/strategy_solver_enumeration.cpp b/src/domains/strategy_solver_enumeration.cpp index 6da344a50..7d6f3e976 100644 --- a/src/domains/strategy_solver_enumeration.cpp +++ b/src/domains/strategy_solver_enumeration.cpp @@ -28,7 +28,8 @@ Function: strategy_solver_enumerationt::iterate \*******************************************************************/ -strategy_solver_baset::progresst strategy_solver_enumerationt::iterate(invariantt &_inv) +strategy_solver_baset::progresst strategy_solver_enumerationt::iterate( + invariantt &_inv) { tpolyhedra_domaint::templ_valuet &inv= static_cast(_inv); diff --git a/src/domains/template_generator_base.h b/src/domains/template_generator_base.h index 8b9b802dc..031d4ac49 100644 --- a/src/domains/template_generator_base.h +++ b/src/domains/template_generator_base.h @@ -50,7 +50,11 @@ class template_generator_baset:public messaget } virtual domaint::var_sett all_vars(); - bool empty() { assert(domain_ptr!=nullptr); return domain_ptr->is_spec_empty(); } + bool empty() + { + assert(domain_ptr!=nullptr); + return domain_ptr->is_spec_empty(); + } domaint *domain() { assert(domain_ptr!=nullptr); return domain_ptr; } domaint::var_specst var_specs; @@ -108,7 +112,8 @@ class template_generator_baset:public messaget void get_pre_post_guards( const local_SSAt &SSA, local_SSAt::nodest::const_iterator n_it, - exprt &pre_guard, exprt &post_guard); + exprt &pre_guard, + exprt &post_guard); void get_pre_var( const local_SSAt &SSA, local_SSAt::objectst::const_iterator o_it, diff --git a/src/domains/template_generator_summary.cpp b/src/domains/template_generator_summary.cpp index 3fbddd77f..b9fc4f68b 100644 --- a/src/domains/template_generator_summary.cpp +++ b/src/domains/template_generator_summary.cpp @@ -107,8 +107,7 @@ void template_generator_summaryt::collect_variables_inout( // add nondets for backwards analysis if(!forward) { - add_vars(SSA.nondets, first_guard, first_guard, - domaint::OUT, var_specs); + add_vars(SSA.nondets, first_guard, first_guard, domaint::OUT, var_specs); } } diff --git a/src/domains/tpolyhedra_domain.cpp b/src/domains/tpolyhedra_domain.cpp index 917d45830..b2c7a2075 100644 --- a/src/domains/tpolyhedra_domain.cpp +++ b/src/domains/tpolyhedra_domain.cpp @@ -17,9 +17,6 @@ Author: Peter Schrammel #include "tpolyhedra_domain.h" #include "util.h" - -#include "simplify_bounds.h" - #include "simplify_bounds.h" #define SYMB_BOUND_VAR "symb_bound#" diff --git a/src/domains/tpolyhedra_domain.h b/src/domains/tpolyhedra_domain.h index 5b55dcd21..efe7ad4b6 100644 --- a/src/domains/tpolyhedra_domain.h +++ b/src/domains/tpolyhedra_domain.h @@ -77,7 +77,8 @@ class tpolyhedra_domaint:public domaint exprt to_symb_post_constraints(const std::set &symb_rows); exprt get_row_symb_value_constraint( const rowt &row, - const row_valuet &row_value, bool geq=false); + const row_valuet &row_value, + bool geq=false); exprt get_row_symb_pre_constraint( const rowt &row, const row_valuet &row_value); diff --git a/src/domains/util.cpp b/src/domains/util.cpp index 6a726f796..159a813d8 100644 --- a/src/domains/util.cpp +++ b/src/domains/util.cpp @@ -123,7 +123,6 @@ void extend_expr_types(exprt &expr) extend_expr_types(expr.op0()); extend_expr_types(expr.op1()); unsigned size0=get_bitvector_width(expr.op0()); -// std::cerr << "expr1: " << expr.op1() << std::endl; unsigned size1=get_bitvector_width(expr.op1()); assert(size0>0); assert(size1>0); @@ -133,8 +132,9 @@ void extend_expr_types(exprt &expr) expr.op1().type().id()==ID_signedbv)) { typet new_type=signedbv_typet(size0+size1+1); - expr=mult_exprt(typecast_exprt(expr.op0(), new_type), - typecast_exprt(expr.op1(), new_type)); + expr=mult_exprt( + typecast_exprt(expr.op0(), new_type), + typecast_exprt(expr.op1(), new_type)); return; } else if(expr.op0().type().id()==ID_floatbv && @@ -333,7 +333,8 @@ ieee_floatt simplify_const_float(const exprt &expr) v1/=v2; return v1; } - if(expr.id()==ID_symbol || expr.id()==ID_nondet_symbol) // default value if not substituted in expr + // default value if not substituted in expr + if(expr.id()==ID_symbol || expr.id()==ID_nondet_symbol) { ieee_floatt v; v.make_zero(); diff --git a/src/html/syntax_highlighting.cpp b/src/html/syntax_highlighting.cpp deleted file mode 100644 index bc3cb230c..000000000 --- a/src/html/syntax_highlighting.cpp +++ /dev/null @@ -1,306 +0,0 @@ -/*******************************************************************\ - -Module: Syntax Highlighting - -Author: Daniel Kroening, kroening@kroening.com - -\*******************************************************************/ - -// may wish to try http:// www.gnu.org/software/src-highlite/ - -#include -#include -#include -#include - -#include "../html/html_escape.h" -#include "syntax_highlighting.h" - -/*******************************************************************\ - -Function: is_keyword - - Inputs: - - Outputs: - - Purpose: - -\*******************************************************************/ - -const char *keywords[]= -{ - "auto", "_Bool", "break", "case", "char", "_Complex", "const", "continue", - "default", "do", "double", "else", "enum", "extern", "float", "for", - "goto", "if", "inline", "int", "long", "register", "restrict", "return", - "short", "signed", "sizeof", "static", "struct", "switch", "typedef", - "union", "unsigned", "void", "volatile", "while", "__float128", - "__int128", "__int8", "__int16", "__int32", "__int64", "__ptr32", - "__ptr64", "__complex__", "__complex", "__real__" , "__real", "__imag__" , - "__imag", "offsetof", "__asm", "asm", "__asm__", "bool", "catch", "class", - "constexpr", "delete", "decltype", "explicit", "friend", "mutable", - "namespace", "new", "nullptr", "operator", "private", "protected", - "public", "static_assert", "template", "this", "thread_local", "throw", - "typeid", "typename", "using", "virtual", "wchar_t", "typeof", NULL -}; - -bool is_keyword(const std::string &token) -{ - for(unsigned i=0; keywords[i]!=NULL; i++) - { - if(strcmp(keywords[i], token.c_str())==0) - return true; - } - - return false; -} - -/*******************************************************************\ - - Class: tokenizert - - Purpose: - -\*******************************************************************/ - -const char *tokens[]= -{ "++", "+=", "--", "-=", "&&", "&=", "||", "|=", "/*", - "*/", "// ", "%=", "/=", "<<", ">>", "<<=", ">>=", "==", - "!=", "<=", ">=", "::", "->", "##", ".*", "->*", NULL }; - -class tokenizert -{ -public: - explicit tokenizert(const std::string &_buf):buf(_buf) - { - } - - std::string get(); - std::string peek(); - std::string buf; - bool eol() const { return buf.empty(); } - - char get_char() - { - if(buf.empty()) return 0; - char result=buf[0]; - buf.erase(0, 1); - return result; - } - - static inline bool is_identifier_char(char ch) - { - return isalnum(ch) || ch=='_'; - } -}; - -/*******************************************************************\ - -Function: tokenizert::peek - - Inputs: - - Outputs: - - Purpose: - -\*******************************************************************/ - -std::string tokenizert::peek() -{ - if(buf.empty()) return buf; - - char first=buf[0]; - - unsigned pos=1; - - if(is_identifier_char(first)) - { - // identifier or keyword or number - for(pos=1; pos"; - - if(comment) out << ""; - - std::string token; - - std::map var_count; - - while(!tokenizer.eol()) - { - if(comment) - { - std::string buf; - bool end_of_comment=false; - - while(!end_of_comment) - { - char ch=tokenizer.get_char(); - if(ch==0) break; - buf+=ch; - if(buf.size()>=2 && buf[buf.size()-2]=='*' && buf[buf.size()-1]=='/') - end_of_comment=true; - } - - out << html_escape(buf); - - if(end_of_comment) - { - out << ""; - comment=false; - } - } - else - { - token=tokenizer.get(); - assert(!token.empty()); - - if(isdigit(token[0])) // numeral - { - out << html_escape(token); - } - else if(isalpha(token[0])) - { - if(is_keyword(token)) - out << "" << html_escape(token) << ""; - else - { - if(identifier_tooltip) - out << ""; - else - out << ""; - - out << html_escape(token); - - out << ""; - } - } - else if(token=="/*") - { - comment=true; - out << "" << token; - } - else if(token=="// ") - { - out << "" << token; - while(!(token=tokenizer.get()).empty()) - out << html_escape(token); - out << ""; - } - else if(token[0]=='"' || token[0]=='\'') - { - out << "" << html_escape(token) << ""; - } - else - { - // hack to distinguish lhs from rhs without parsing - #if 0 - if(token=="+=" || token=="=" || - token=="-=" || token=="<<=" || - token==">>=" || token=="&=" || - token=="^=" || token=="|=") - lhs=false; - else if(token==";") - lhs=true; - #endif - - out << html_escape(token); - } - } - } - - // close tags - if(comment) out << ""; - if(!strong_class.empty()) out << ""; - - out << "\n"; -} - diff --git a/src/html/syntax_highlighting.h b/src/html/syntax_highlighting.h deleted file mode 100644 index 412a8434b..000000000 --- a/src/html/syntax_highlighting.h +++ /dev/null @@ -1,35 +0,0 @@ -/*******************************************************************\ - -Module: Syntax Highlighting - -Author: Daniel Kroening, kroening@kroening.com - -\*******************************************************************/ - -#ifndef CPROVER_SYNTAX_HIGHLIGHTING_H -#define CPROVER_SYNTAX_HIGHLIGHTING_H - -#include -#include - -class syntax_highlightingt -{ -public: - explicit syntax_highlightingt(std::ostream &_out): - line_no(0), identifier_tooltip(false), - out(_out), comment(false) { } - - std::string strong_class; - unsigned line_no; - std::string id_suffix; - - bool identifier_tooltip; - - void operator()(const std::string &line); - -protected: - std::ostream &out; - bool comment; -}; - -#endif diff --git a/src/solver/summarizer_bw_cex.cpp b/src/solver/summarizer_bw_cex.cpp index 7307697bf..33501d783 100644 --- a/src/solver/summarizer_bw_cex.cpp +++ b/src/solver/summarizer_bw_cex.cpp @@ -214,8 +214,10 @@ void summarizer_bw_cex_baset::get_loop_continues( for(local_SSAt::nodest::const_iterator n_it=SSA.nodes.begin(); n_it!=SSA.nodes.end(); n_it++) { - if(n_it->loophead==SSA.nodes.end()) continue; - if(n_it->loophead->location!=loop_id) continue; + if(n_it->loophead==SSA.nodes.end()) + continue; + if(n_it->loophead->location!=loop_id) + continue; symbol_exprt guard=SSA.guard_symbol(n_it->location); symbol_exprt cond=SSA.cond_symbol(n_it->location); loop_continues.push_back(and_exprt(guard, cond)); @@ -224,7 +226,8 @@ void summarizer_bw_cex_baset::get_loop_continues( } #if 0 - std::cout << "loophead_continues: " << from_expr(SSA.ns, "", disjunction(loop_continues)) << std::endl; + std::cout << "loophead_continues: " + << from_expr(SSA.ns, "", disjunction(loop_continues)) << std::endl; #endif } diff --git a/src/solver/summarizer_bw_cex.h b/src/solver/summarizer_bw_cex.h index 117a47416..8e3f70e1b 100644 --- a/src/solver/summarizer_bw_cex.h +++ b/src/solver/summarizer_bw_cex.h @@ -21,7 +21,7 @@ Author: Kumar Madhukar, Peter Schrammel #include "summarizer_bw.h" -class summarizer_bw_cex_baset : public summarizer_bwt +class summarizer_bw_cex_baset:public summarizer_bwt { public: typedef ssa_refiner_selectivet::reasont reasont; @@ -77,4 +77,4 @@ class summarizer_bw_cex_baset : public summarizer_bwt incremental_solvert&); }; -#endif +#endif // CPROVER_2LS_SOLVER_SUMMARIZER_BW_CEX_H diff --git a/src/solver/summarizer_bw_cex_ai.cpp b/src/solver/summarizer_bw_cex_ai.cpp index f796c3cad..8607afa5c 100644 --- a/src/solver/summarizer_bw_cex_ai.cpp +++ b/src/solver/summarizer_bw_cex_ai.cpp @@ -44,8 +44,8 @@ void summarizer_bw_cex_ait::summarize(const function_namet &function_name) exprt postcondition=true_exprt(); // initial calling context status() << "\nSummarizing function " << function_name << eom; - compute_summary_rec(function_name, summaryt::entry_call_site, - postcondition, true); + compute_summary_rec( + function_name, summaryt::entry_call_site, postcondition, true); } /*******************************************************************\ @@ -166,25 +166,34 @@ void summarizer_bw_cex_ait::compute_summary_rec( from_expr(SSA.ns, "", postcondition) << eom; #endif - if(_postcondition.is_false()){ - + if(_postcondition.is_false()) + { summary.error_summaries[call_site]=false_exprt(); - } - else{ - + else + { // recursively compute summaries for function calls - inline_summaries(function_name, SSA, summary, - postcondition, context_sensitive, - true); + inline_summaries( + function_name, + SSA, + summary, + postcondition, + context_sensitive, + true); status() << "Analyzing function " << function_name << eom; - do_summary(function_name, call_site, SSA, summary, summary, postcondition, context_sensitive); + do_summary( + function_name, + call_site, + SSA, + summary, + summary, + postcondition, + context_sensitive); if(function_name==error_function) summary.has_assertion=true; - } summary_db.set(function_name, summary); @@ -195,7 +204,6 @@ void summarizer_bw_cex_ait::compute_summary_rec( summary_db.get(function_name).output(out, SSA.ns); debug() << out.str() << eom; } - } /*******************************************************************\ @@ -210,13 +218,14 @@ Function: summarizer_bw_cex_ait::do_summary() \*******************************************************************/ -void summarizer_bw_cex_ait::do_summary(const function_namet &function_name, - const summaryt::call_sitet &call_site, - local_SSAt &SSA, - const summaryt &old_summary, - summaryt &summary, - const exprt &postcondition, - bool context_sensitive) +void summarizer_bw_cex_ait::do_summary( + const function_namet &function_name, + const summaryt::call_sitet &call_site, + local_SSAt &SSA, + const summaryt &old_summary, + summaryt &summary, + const exprt &postcondition, + bool context_sensitive) { status() << "Computing error summary" << eom; @@ -245,32 +254,26 @@ void summarizer_bw_cex_ait::do_summary(const function_namet &function_name, exprt::operandst assert_postcond, noassert_postcond; // add error summaries for function calls bool assertion_flag; - assertion_flag=ssa_inliner.get_summaries(SSA, call_site, false, - assert_postcond, noassert_postcond, c); // backward summaries + // backward summaries + assertion_flag= + ssa_inliner.get_summaries( + SSA, call_site, false, assert_postcond, noassert_postcond, c); assert_postcond.push_back(postcondition); // context // add nondet variables from callees to summary.nondets std::set summary_vars; find_symbols(conjunction(assert_postcond), summary_vars); - for(std::set::const_iterator it=summary_vars.begin(); - it!=summary_vars.end(); ++it) - if(it->id()==ID_nondet_symbol) - summary.nondets.insert(*it); + for(const auto &var : summary_vars) + { + if(var.id()==ID_nondet_symbol) + summary.nondets.insert(var); + } // assumptions must hold - for(local_SSAt::nodest::const_iterator - n_it=SSA.nodes.begin(); - n_it!=SSA.nodes.end(); - ++n_it) - for(local_SSAt::nodet::assumptionst::const_iterator - a_it=n_it->assumptions.begin(); - a_it!=n_it->assumptions.end(); - ++a_it) - c.push_back(*a_it); - - - + for(const auto &node : SSA.nodes) + for(const auto &assumption : node.assumptions) + c.push_back(assumption); #if 0 std::cout << from_expr(SSA.ns, "", cc) << std::endl; @@ -281,76 +284,71 @@ void summarizer_bw_cex_ait::do_summary(const function_namet &function_name, summary.error_summaries[call_site]; if(!template_generator.empty()) { - c.push_back(conjunction(assert_postcond)); // with negative information would need: not_exprt - c.push_back(conjunction(noassert_postcond)); // with negative information would need: not_exprt dis + // with negative information would need: not_exprt + c.push_back(conjunction(assert_postcond)); + // with negative information would need: not_exprt dis + c.push_back(conjunction(noassert_postcond)); - // std::cout << "unsimplified constraints (if): " << from_expr(SSA.ns, "", conjunction(c)) << "\n\n\n"; exprt cc=simplify_expr(conjunction(c), SSA.ns); - // exprt cc=conjunction(c); - // std::cout << "simplified constraints passed (if): " << from_expr(SSA.ns, "", cc) << "\n\n\n"; - - /* - ssa_analyzert analyzer; - analyzer.set_message_handler(get_message_handler()); - analyzer(solver, SSA, cc, template_generator); - analyzer.get_result(summary.error_summaries[call_site], - template_generator.inout_vars()); - */ - /**/ + disjunctive_analyzert disjunctive_analyzer; disjunctive_analyzer.set_message_handler(get_message_handler()); - disjunctive_analyzer(solver, SSA, cc, template_generator, - cc, summary.error_summaries[call_site], - template_generator.inout_vars()); - /**/ + disjunctive_analyzer( + solver, + SSA, + cc, + template_generator, + cc, + summary.error_summaries[call_site], + template_generator.inout_vars()); #if 0 - std::cout << "SUM: " << from_expr(SSA.ns, "", summary.error_summaries[call_site]) << std::endl; + std::cout << "SUM: " + << from_expr(SSA.ns, "", summary.error_summaries[call_site]) + << std::endl; #endif - summary.error_summaries[call_site]= simplify_expr(summary.error_summaries[call_site], SSA.ns); - #if 0 - std::cout << "SUM (post simplification): " << from_expr(SSA.ns, "", summary.error_summaries[call_site]) << std::endl; + std::cout << "SUM (post simplification): " + << from_expr(SSA.ns, "", summary.error_summaries[call_site]) + << std::endl; #endif // statistics - /* - solver_instances+=analyzer.get_number_of_solver_instances(); - solver_calls+=analyzer.get_number_of_solver_calls(); - */ solver_instances+=disjunctive_analyzer.get_number_of_solver_instances(); solver_calls+=disjunctive_analyzer.get_number_of_solver_calls(); - } - else // TODO: yet another workaround for ssa_analyzer not being able to handle empty templates properly + else { - c.push_back(conjunction(assert_postcond)); // with negative information would need: not_exprt - c.push_back(conjunction(noassert_postcond)); // with negative information would need: not_exprt dis + // TODO: yet another workaround for ssa_analyzer + // not being able to handle empty templates properly + + // with negative information would need: not_exprt + c.push_back(conjunction(assert_postcond)); + // with negative information would need: not_exprt dis + c.push_back(conjunction(noassert_postcond)); // c.push_back(not_exprt(conjunction(assert_postcond))); // c.push_back(not_exprt(disjunction(noassert_postcond))); - // std::cout << "unsimplified constraints (else): " << from_expr(SSA.ns, "", conjunction(c)) << "\n\n\n"; exprt cc=simplify_expr(conjunction(c), SSA.ns); - // exprt cc=conjunction(c); - // std::cout << "simplified constraints passed (else): " << from_expr(SSA.ns, "", cc) << "\n\n\n"; - - // std::cout << "enabling expressions (else): " << from_expr(SSA.ns, "", SSA.get_enabling_exprs()) << "\n\n\n"; solver << SSA; solver.new_context(); solver << SSA.get_enabling_exprs(); solver << cc; exprt result=true_exprt(); - if(solver()!=decision_proceduret::D_SATISFIABLE) result=false_exprt(); + if(solver()!=decision_proceduret::D_SATISFIABLE) + result=false_exprt(); solver.pop_context(); summary.error_summaries[call_site]=result; #if 0 - std::cout << "SUM: " << from_expr(SSA.ns, "", summary.error_summaries[call_site]) << std::endl; + std::cout << "SUM: " + << from_expr(SSA.ns, "", summary.error_summaries[call_site]) + << std::endl; #endif } @@ -372,12 +370,13 @@ Function: summarizer_bw_cex_ait::inline_summaries() \*******************************************************************/ -void summarizer_bw_cex_ait::inline_summaries(const function_namet &function_name, - local_SSAt &SSA, - const summaryt &old_summary, - const exprt &postcondition, - bool context_sensitive, - bool sufficient) +void summarizer_bw_cex_ait::inline_summaries( + const function_namet &function_name, + local_SSAt &SSA, + const summaryt &old_summary, + const exprt &postcondition, + bool context_sensitive, + bool sufficient) { for(local_SSAt::nodest::const_iterator n_it=SSA.nodes.end(); n_it!=SSA.nodes.begin(); ) @@ -385,19 +384,22 @@ void summarizer_bw_cex_ait::inline_summaries(const function_namet &function_name n_it--; for(local_SSAt::nodet::function_callst::const_iterator f_it= - n_it->function_calls.begin(); + n_it->function_calls.begin(); f_it!=n_it->function_calls.end(); f_it++) { assert(f_it->function().id()==ID_symbol); // no function pointers - exprt postcondition_call= true_exprt(); + exprt postcondition_call=true_exprt(); postcondition_call=compute_calling_context2( - function_name, SSA, old_summary, n_it, f_it, postcondition, sufficient); + function_name, SSA, old_summary, n_it, f_it, postcondition, sufficient); irep_idt fname=to_symbol_expr(f_it->function()).get_identifier(); status() << "Recursively summarizing function " << fname << eom; - compute_summary_rec(fname, summaryt::call_sitet(n_it->location), - postcondition_call, context_sensitive); + compute_summary_rec( + fname, + summaryt::call_sitet(n_it->location), + postcondition_call, + context_sensitive); } } } @@ -433,11 +435,6 @@ exprt summarizer_bw_cex_ait::compute_calling_context2( solver.set_message_handler(get_message_handler()); // analyze - /* - ssa_analyzert analyzer; - analyzer.set_message_handler(get_message_handler()); - */ - disjunctive_analyzert disjunctive_analyzer; disjunctive_analyzer.set_message_handler(get_message_handler()); @@ -453,7 +450,9 @@ exprt summarizer_bw_cex_ait::compute_calling_context2( template_generator(solver.next_domain_number(), SSA, n_it, f_it, false); // collect globals at call site - std::map + std::map< + local_SSAt::nodet::function_callst::const_iterator, + local_SSAt::var_sett> cs_globals_out; SSA.get_globals(n_it->location, cs_globals_out[f_it], false); @@ -480,27 +479,28 @@ exprt summarizer_bw_cex_ait::compute_calling_context2( exprt postcondition_call; - if(!template_generator.empty()){ - - c.push_back(conjunction(assert_postcond)); // with negative information would need: not_exprt - c.push_back(conjunction(noassert_postcond)); // with negative information would need: not_exprt dis - - /* - analyzer(solver, SSA, conjunction(c), template_generator); - analyzer.get_result(postcondition_call, - template_generator.callingcontext_vars()); - */ + if(!template_generator.empty()) + { + // with negative information would need: not_exprt + c.push_back(conjunction(assert_postcond)); + // with negative information would need: not_exprt dis + c.push_back(conjunction(noassert_postcond)); disjunctive_analyzer(solver, SSA, conjunction(c), template_generator, conjunction(c), postcondition_call, template_generator.callingcontext_vars()); - ssa_inliner.rename_to_callee(f_it, fSSA.params, - cs_globals_out[f_it], fSSA.globals_out, - postcondition_call); - + ssa_inliner.rename_to_callee( + f_it, + fSSA.params, + cs_globals_out[f_it], + fSSA.globals_out, + postcondition_call); } - else{ // TODO: yet another workaround for ssa_analyzer not being able to handle empty templates properly + else + { + // TODO: yet another workaround for ssa_analyzer + // not being able to handle empty templates properly c.push_back(not_exprt(conjunction(assert_postcond))); c.push_back(not_exprt(disjunction(noassert_postcond))); @@ -510,26 +510,20 @@ exprt summarizer_bw_cex_ait::compute_calling_context2( solver << SSA.get_enabling_exprs(); solver << conjunction(c); - // std::cout << "passed to solver, else branch, calling context: " << from_expr(SSA.ns, "", conjunction(c)) << "\n\n"; - postcondition_call=false_exprt(); - if(solver()!=decision_proceduret::D_SATISFIABLE) postcondition_call=true_exprt(); + if(solver()!=decision_proceduret::D_SATISFIABLE) + postcondition_call=true_exprt(); solver.pop_context(); } - debug() << "Backward calling context for " << - from_expr(SSA.ns, "", *f_it) << ": " - << from_expr(SSA.ns, "", postcondition_call) << eom; + debug() << "Backward calling context for " + << from_expr(SSA.ns, "", *f_it) << ": " + << from_expr(SSA.ns, "", postcondition_call) << eom; // statistics - /* - solver_instances+=analyzer.get_number_of_solver_instances(); - solver_calls+=analyzer.get_number_of_solver_calls(); - */ solver_instances+=disjunctive_analyzer.get_number_of_solver_instances(); solver_calls+=disjunctive_analyzer.get_number_of_solver_calls(); return postcondition_call; } - diff --git a/src/solver/summarizer_bw_cex_ai.h b/src/solver/summarizer_bw_cex_ai.h index 3448a1422..af779376f 100644 --- a/src/solver/summarizer_bw_cex_ai.h +++ b/src/solver/summarizer_bw_cex_ai.h @@ -20,57 +20,65 @@ Author: Kumar Madhukar, Peter Schrammel #include "summarizer_bw_cex.h" -class summarizer_bw_cex_ait : public summarizer_bw_cex_baset +class summarizer_bw_cex_ait:public summarizer_bw_cex_baset { - public: - explicit summarizer_bw_cex_ait(optionst &_options, - summary_dbt &_summary_db, - ssa_dbt &_ssa_db, - ssa_unwindert &_ssa_unwinder, - ssa_inlinert &_ssa_inliner, - function_namet _entry_function, - function_namet _error_function): - summarizer_bw_cex_baset(_options, _summary_db, _ssa_db, - _ssa_unwinder, _ssa_inliner, - _entry_function, _error_function) - {} +public: + summarizer_bw_cex_ait( + optionst &_options, + summary_dbt &_summary_db, + ssa_dbt &_ssa_db, + ssa_unwindert &_ssa_unwinder, + ssa_inlinert &_ssa_inliner, + function_namet _entry_function, + function_namet _error_function): + summarizer_bw_cex_baset( + _options, + _summary_db, + _ssa_db, + _ssa_unwinder, + _ssa_inliner, + _entry_function, + _error_function) + { + } virtual void summarize(const function_namet &entry_function); virtual void summarize(const exprt &_error_assertion); virtual property_checkert::resultt check(); - protected: - - virtual void compute_summary_rec(const function_namet &function_name, - const summaryt::call_sitet &call_site, - const exprt &postcondition, - bool context_sensitive); +protected: + virtual void compute_summary_rec( + const function_namet &function_name, + const summaryt::call_sitet &call_site, + const exprt &postcondition, + bool context_sensitive); - virtual void inline_summaries(const function_namet &function_name, - local_SSAt &SSA, - const summaryt &old_summary, - const exprt &postcondition, - bool context_sensitive, - bool sufficient); + virtual void inline_summaries( + const function_namet &function_name, + local_SSAt &SSA, + const summaryt &old_summary, + const exprt &postcondition, + bool context_sensitive, + bool sufficient); - virtual void do_summary(const function_namet &function_name, - const summaryt::call_sitet &call_site, - local_SSAt &SSA, - const summaryt &old_summary, - summaryt &summary, - const exprt &postcondition, - bool context_sensitive); + virtual void do_summary( + const function_namet &function_name, + const summaryt::call_sitet &call_site, + local_SSAt &SSA, + const summaryt &old_summary, + summaryt &summary, + const exprt &postcondition, + bool context_sensitive); - virtual exprt compute_calling_context2(const function_namet &function_name, + virtual exprt compute_calling_context2( + const function_namet &function_name, local_SSAt &SSA, summaryt old_summary, local_SSAt::nodest::const_iterator n_it, local_SSAt::nodet::function_callst::const_iterator f_it, const exprt &postcondition, bool sufficient); - }; - -#endif +#endif // CPROVER_2LS_SOLVER_SUMMARIZER_BW_CEX_AI_H diff --git a/src/solver/summarizer_bw_cex_all.h b/src/solver/summarizer_bw_cex_all.h index f29326931..c12afcf8b 100644 --- a/src/solver/summarizer_bw_cex_all.h +++ b/src/solver/summarizer_bw_cex_all.h @@ -22,31 +22,54 @@ Author: Kumar Madhukar, Peter Schrammel #include "summarizer_bw_cex_ai.h" #include "summarizer_bw_cex_complete.h" -class summarizer_bw_cex_allt : public summarizer_bw_cex_baset +class summarizer_bw_cex_allt:public summarizer_bw_cex_baset { - public: - explicit summarizer_bw_cex_allt(optionst &_options, - summary_dbt &_summary_db, - ssa_dbt &_ssa_db, - ssa_unwindert &_ssa_unwinder, - ssa_inlinert &_ssa_inliner, - incremental_solvert &_solver, - function_namet _entry_function, - function_namet _error_function): - summarizer_bw_cex_baset(_options, _summary_db, _ssa_db, - _ssa_unwinder, _ssa_inliner, - _entry_function, _error_function), - summarizer_bw_cex_concrete(_options, _summary_db, _ssa_db, - _ssa_unwinder, _ssa_inliner, - _entry_function, _error_function), - summarizer_bw_cex_ai(_options, _summary_db, _ssa_db, - _ssa_unwinder, _ssa_inliner, - _entry_function, _error_function), - summarizer_bw_cex_complete(_options, _summary_db, _ssa_db, - _ssa_unwinder, _ssa_inliner, - _solver, _entry_function, _error_function), - result(property_checkert::UNKNOWN) - {} +public: + summarizer_bw_cex_allt( + optionst &_options, + summary_dbt &_summary_db, + ssa_dbt &_ssa_db, + ssa_unwindert &_ssa_unwinder, + ssa_inlinert &_ssa_inliner, + incremental_solvert &_solver, + function_namet _entry_function, + function_namet _error_function): + summarizer_bw_cex_baset( + _options, + _summary_db, + _ssa_db, + _ssa_unwinder, + _ssa_inliner, + _entry_function, + _error_function), + summarizer_bw_cex_concrete( + _options, + _summary_db, + _ssa_db, + _ssa_unwinder, + _ssa_inliner, + _entry_function, + _error_function), + summarizer_bw_cex_ai( + _options, + _summary_db, + _ssa_db, + _ssa_unwinder, + _ssa_inliner, + _entry_function, + _error_function), + summarizer_bw_cex_complete( + _options, + _summary_db, + _ssa_db, + _ssa_unwinder, + _ssa_inliner, + _solver, + _entry_function, + _error_function), + result(property_checkert::UNKNOWN) + { + } virtual void summarize(const exprt &_error_assertion); @@ -58,7 +81,6 @@ class summarizer_bw_cex_allt : public summarizer_bw_cex_baset messaget::set_message_handler(handler); } - virtual property_checkert::resultt check(); protected: @@ -66,8 +88,6 @@ class summarizer_bw_cex_allt : public summarizer_bw_cex_baset summarizer_bw_cex_ait summarizer_bw_cex_ai; summarizer_bw_cex_completet summarizer_bw_cex_complete; property_checkert::resultt result; - }; - -#endif +#endif // CPROVER_2LS_SOLVER_SUMMARIZER_BW_CEX_ALL_H diff --git a/src/solver/summarizer_bw_cex_complete.cpp b/src/solver/summarizer_bw_cex_complete.cpp index c658c91eb..7df4f3c23 100644 --- a/src/solver/summarizer_bw_cex_complete.cpp +++ b/src/solver/summarizer_bw_cex_complete.cpp @@ -6,7 +6,9 @@ Author: Madhukar Kumar, Peter Schrammel \*******************************************************************/ +#ifdef DEBUG #include +#endif #include #include @@ -16,13 +18,13 @@ Author: Madhukar Kumar, Peter Schrammel #include "summary_db.h" -#include "../domains/ssa_analyzer.h" -#include "../domains/template_generator_summary.h" -#include "../domains/template_generator_callingcontext.h" +#include +#include +#include -#include "../ssa/local_ssa.h" -#include "../ssa/simplify_ssa.h" -#include "../ssa/ssa_dependency_graph.h" +#include +#include +#include #include "summarizer_bw_cex_complete.h" @@ -119,15 +121,15 @@ find_symbols_sett summarizer_bw_cex_completet::inline_summaries #ifdef REFINE_ALL // TODO: let's just put all loops into the reason - for(local_SSAt::nodest::iterator n_it=SSA.nodes.begin(); - n_it!=SSA.nodes.end(); ++n_it) - if (n_it->loophead!=SSA.nodes.end()) - reason[function_name].loops.insert(n_it->loophead->location); + for(const auto node : SSA.nodes) + if(node.loophead!=SSA.nodes.end()) + reason[function_name].loops.insert(node.loophead->location); #endif ssa_dependency_grapht &ssa_depgraph=ssa_db.get_depgraph(function_name); - struct worknodet{ + struct worknodet + { int node_index; find_symbols_sett dependency_set; }; @@ -142,126 +144,135 @@ find_symbols_sett summarizer_bw_cex_completet::inline_summaries worklist.push_back(start_node); - while(!worklist.empty()){ - - /* - std::cout << "worklist: "; - for(worklistt::const_iterator w_it=worklist.begin(); - w_it!=worklist.end(); w_it++){ + while(!worklist.empty()) + { +#ifdef DEBUG + std::cout << "worklist: "; + for(worklistt::const_iterator w_it=worklist.begin(); + w_it!=worklist.end(); w_it++) + { std::cout << w_it->node_index << " "; - } - std::cout << "\n"; + } + std::cout << "\n"; - std::cout << "\t waitlist: "; - for(worklistt::const_iterator w_it=work_waitlist.begin(); - w_it!=work_waitlist.end(); w_it++){ + std::cout << "\t waitlist: "; + for(worklistt::const_iterator w_it=work_waitlist.begin(); + w_it!=work_waitlist.end(); w_it++) + { std::cout << w_it->node_index << " "; - } - std::cout << "\n"; - */ + } + std::cout << "\n"; +#endif worknodet &worknode=worklist.front(); const ssa_dependency_grapht::depnodet &depnode= ssa_depgraph.depnodes_map[worknode.node_index]; - // std::cout << "working node: " << function_name << ": " << worknode.node_index << "\n"; - // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // / - // std::cout << "\t size of dependency set: " << worknode.dependency_set.size() << "\n"; - /* - std::cout << "\t dependency set: "; - for(find_symbols_sett::iterator d_it=worknode.dependency_set.begin(); - d_it!=worknode.dependency_set.end(); d_it++){ +#ifdef DEBUG + std::cout << "working node: " << function_name << ": " + << worknode.node_index << "\n"; + std::cout << "\t size of dependency set: " + << worknode.dependency_set.size() << "\n"; + std::cout << "\t dependency set: "; + for(find_symbols_sett::iterator d_it=worknode.dependency_set.begin(); + d_it!=worknode.dependency_set.end(); d_it++) + { std::cout << *d_it; - } - std::cout << "\n\n\n"; - */ - // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // / - + } + std::cout << "\n\n\n"; +#endif // return if the top most node is reached if(worknode.node_index==ssa_depgraph.top_node_index) return worknode.dependency_set; // modify worknode_dependency_set if the node is an assertion - if(depnode.is_assertion==true){ - - // std::cout << "\t\t an assertion node\n"; + if(depnode.is_assertion==true) + { +#ifdef DEBUG + std::cout << "\t\t an assertion node\n"; +#endif for(find_symbols_sett::const_iterator d_it=depnode.used_symbols.begin(); - d_it!=depnode.used_symbols.end(); d_it++){ + d_it!=depnode.used_symbols.end(); d_it++) + { worknode.dependency_set.insert(*d_it); } - // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // / - /* - std::cout << "\t size of dependency set: " << worknode.dependency_set.size() << "\n"; +#ifdef DEBUG + std::cout << "\t size of dependency set: " + << worknode.dependency_set.size() << "\n"; - std::cout << "\t dependency set: "; - for(find_symbols_sett::iterator d_it=worknode.dependency_set.begin(); - d_it!=worknode.dependency_set.end(); d_it++){ + std::cout << "\t dependency set: "; + for(find_symbols_sett::iterator d_it=worknode.dependency_set.begin(); + d_it!=worknode.dependency_set.end(); d_it++) + { std::cout << *d_it; - } - std::cout << "\n"; - */ - // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // / - - - + } + std::cout << "\n"; +#endif } // if this is a function call - if(depnode.is_function_call==true){ - // std::cout << "fcall: working node: " << function_name << ": " << worknode.node_index << "\n"; + if(depnode.is_function_call==true) + { +#ifdef DEBUG + std::cout << "fcall: working node: " << function_name << ": " + << worknode.node_index << "\n"; +#endif irep_idt fname= - to_symbol_expr((to_function_application_expr(depnode.node_info)).function()).get_identifier(); + to_symbol_expr( + (to_function_application_expr(depnode.node_info)).function()) + .get_identifier(); find_symbols_sett renamed_dependencies; - // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // / - /* - std::cout << "\t size of dependency set: " << worknode.dependency_set.size() << "\n"; +#ifdef DEBUG + std::cout << "\t size of dependency set: " + << worknode.dependency_set.size() << "\n"; - std::cout << "\t dependency set: "; - for(find_symbols_sett::iterator d_it=worknode.dependency_set.begin(); - d_it!=worknode.dependency_set.end(); d_it++){ + std::cout << "\t dependency set: "; + for(find_symbols_sett::iterator d_it=worknode.dependency_set.begin(); + d_it!=worknode.dependency_set.end(); d_it++) + { std::cout << *d_it; - } - std::cout << "\n"; - */ - // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // / + } + std::cout << "\n"; +#endif for(find_symbols_sett::iterator d_it=worknode.dependency_set.begin(); - d_it!=worknode.dependency_set.end(); d_it++){ + d_it!=worknode.dependency_set.end(); d_it++) + { irep_idt renamed_id=*d_it; // detach the '@' symbol if there - ssa_inliner.rename(renamed_id, - depnode.rename_counter, false); + ssa_inliner.rename(renamed_id, depnode.rename_counter, false); renamed_dependencies.insert(renamed_id); } worknode.dependency_set=renamed_dependencies; - if(!worknode.dependency_set.empty()){ + if(!worknode.dependency_set.empty()) + { find_symbols_sett guard_dependencies; - find_symbols(depnode.guard, - guard_dependencies); + find_symbols(depnode.guard, guard_dependencies); for(find_symbols_sett::const_iterator d_it=guard_dependencies.begin(); - d_it!=guard_dependencies.end(); d_it++){ + d_it!=guard_dependencies.end(); d_it++) + { worknode.dependency_set.insert(*d_it); } } - // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // / - /* - std::cout << "\t size of dependency set: " << worknode.dependency_set.size() << "\n"; +#ifdef DEBUG + std::cout << "\t size of dependency set: " + << worknode.dependency_set.size() << "\n"; - std::cout << "\t dependency set: "; - for(find_symbols_sett::iterator d_it=worknode.dependency_set.begin(); - d_it!=worknode.dependency_set.end(); d_it++){ + std::cout << "\t dependency set: "; + for(find_symbols_sett::iterator d_it=worknode.dependency_set.begin(); + d_it!=worknode.dependency_set.end(); d_it++) + { std::cout << *d_it; - } - std::cout << "\n"; - */ - // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // / + } + std::cout << "\n"; +#endif #ifdef REFINE_ALL // TODO: just put all function calls into reason @@ -270,32 +281,32 @@ find_symbols_sett summarizer_bw_cex_completet::inline_summaries // recurse worknode.dependency_set= - compute_summary_rec(fname, worknode.dependency_set, - depnode.rename_counter); - + compute_summary_rec( + fname, worknode.dependency_set, depnode.rename_counter); renamed_dependencies.clear(); for(find_symbols_sett::iterator d_it=worknode.dependency_set.begin(); - d_it!=worknode.dependency_set.end(); d_it++){ + d_it!=worknode.dependency_set.end(); d_it++) + { irep_idt renamed_id=*d_it; // attach the '@' symbol if not already there - ssa_inliner.rename(renamed_id, - depnode.rename_counter, true); + ssa_inliner.rename(renamed_id, depnode.rename_counter, true); renamed_dependencies.insert(renamed_id); } worknode.dependency_set=renamed_dependencies; - if(!worknode.dependency_set.empty()){ + if(!worknode.dependency_set.empty()) + { find_symbols_sett guard_dependencies; find_symbols(depnode.guard, guard_dependencies); for(find_symbols_sett::const_iterator d_it=guard_dependencies.begin(); - d_it!=guard_dependencies.end(); d_it++){ + d_it!=guard_dependencies.end(); d_it++) + { worknode.dependency_set.insert(*d_it); } } - } // if the dependency set is non-empty @@ -306,37 +317,52 @@ find_symbols_sett summarizer_bw_cex_completet::inline_summaries bool is_error_assertion=false; if(depnode.is_assertion) { -#if 0 - std::cout << "assertion: " << from_expr(SSA.ns, "", error_assertion) << std::endl; - std::cout << "to check: " << from_expr(SSA.ns, "", worknode_info) << std::endl; +#ifdef DEBUG + std::cout << "assertion: " << from_expr(SSA.ns, "", error_assertion) + << std::endl; + std::cout << "to check: " << from_expr(SSA.ns, "", worknode_info) + << std::endl; #endif assert(error_assertion.id()==ID_not); if(error_assertion.op0().id()!=ID_and) is_error_assertion=(worknode_info==error_assertion.op0()); else + { forall_operands(a_it, error_assertion.op0()) + { if(worknode_info==*a_it) { is_error_assertion=true; break; } + } + } } - if(worknode.node_index!=0){ - if(!(depnode.is_function_call)){ + if(worknode.node_index!=0) + { + if(!(depnode.is_function_call)) + { if(!depnode.is_assertion || is_error_assertion) { - /* - std::cout << "Solver <-- " << function_name << ": (node) node#:" - << worknode.node_index << "\t original info ~ " - << from_expr((ssa_db.get(function_name)).ns, "", worknode_info) << "\n"; - */ +#ifdef DEBUG + std::cout << "Solver <-- " << function_name << ": (node) node#:" + << worknode.node_index << "\t original info ~ " + << from_expr( + (ssa_db.get(function_name)).ns, "", worknode_info) + << "\n"; +#endif ssa_inliner.rename(worknode_info, counter); #if 0 - std::cout << "Solver <-- renamed assertion: " << from_expr((ssa_db.get(function_name)).ns, "", worknode_info) << "\n"; + std::cout << "Solver <-- renamed assertion: " + << from_expr( + (ssa_db.get(function_name)).ns, "", worknode_info) + << "\n"; std::cout << "Solver <-- " << function_name << ": (node) node#:" << worknode.node_index << "\t renamed info ~ " - << from_expr((ssa_db.get(function_name)).ns, "", worknode_info) << "\n"; + << from_expr( + (ssa_db.get(function_name)).ns, "", worknode_info) + << "\n"; #endif if(depnode.is_assertion) // keep for later @@ -350,40 +376,45 @@ find_symbols_sett summarizer_bw_cex_completet::inline_summaries exprt lsguard=depnode.guard; ssa_inliner.rename(lsguard, counter); loophead_selects.push_back(lsguard); - // solver.solver->set_frozen(solver.convert(lsguard)); - add_reason_to_check(lsguard, function_name, false, depnode.location); + add_reason_to_check( + lsguard, function_name, false, depnode.location); // loop continuations exprt::operandst local_loop_continues; - get_loop_continues(function_name, SSA, depnode.location, - local_loop_continues); + get_loop_continues( + function_name, SSA, depnode.location, local_loop_continues); for(size_t i=0; inode_index==pred_node_index){ - + for(worklistt::iterator w_it= + work_waitlist.begin(); w_it!=work_waitlist.end(); w_it++) + { + if(w_it->node_index==pred_node_index) + { dependencies_merged=true; for(find_symbols_sett::const_iterator - a_it=pred_annotation.begin(); a_it!=pred_annotation.end(); a_it++) + a_it=pred_annotation.begin(); + a_it!=pred_annotation.end(); a_it++) { - if(worknode.dependency_set.find(*a_it)!=worknode.dependency_set.end()){ - if((w_it->dependency_set).find(*a_it)==(w_it->dependency_set).end()){ + if(worknode.dependency_set.find(*a_it)!= + worknode.dependency_set.end()) + { + if((w_it->dependency_set).find(*a_it)== + (w_it->dependency_set).end()) + { (w_it->dependency_set).insert(*a_it); } } @@ -432,7 +471,8 @@ find_symbols_sett summarizer_bw_cex_completet::inline_summaries } } - if(dependencies_merged==false){ + if(dependencies_merged==false) + { worknodet new_worknode; new_worknode.node_index=pred_node_index; @@ -450,7 +490,8 @@ find_symbols_sett summarizer_bw_cex_completet::inline_summaries #if 0 std::cout << function_name << ": worklist: "; for(worklistt::const_iterator w_it=worklist.begin(); - w_it!=worklist.end(); w_it++){ + w_it!=worklist.end(); w_it++) + { std::cout << w_it->node_index << " "; } std::cout << "\n"; @@ -458,7 +499,8 @@ find_symbols_sett summarizer_bw_cex_completet::inline_summaries std::cout << "\t" << function_name << ": waitlist: "; for(worklistt::const_iterator w_it=work_waitlist.begin(); - w_it!=work_waitlist.end(); w_it++){ + w_it!=work_waitlist.end(); w_it++) + { std::cout << w_it->node_index << " "; } std::cout << "\n"; @@ -469,7 +511,8 @@ find_symbols_sett summarizer_bw_cex_completet::inline_summaries #if 0 std::cout << function_name << ": covered : "; - for(int l=0; l &waitlisted_worknode_successors= ssa_depgraph.depnodes_map[waitlisted_worknode.node_index].successors; - for(unsigned i=0; iconvert( - not_exprt(conjunction(renamed_error_assertion)))); + formula.push_back( + solver.solver->convert(not_exprt(conjunction(renamed_error_assertion)))); solver.solver->set_assumptions(formula); #endif @@ -585,7 +636,8 @@ property_checkert::resultt summarizer_bw_cex_completet::check() { if(solver.solver->is_in_conflict(formula[i])) { - debug() << "is_in_conflict: " << from_expr(ns, "", formula_expr[i]) << eom; + debug() << "is_in_conflict: " + << from_expr(ns, "", formula_expr[i]) << eom; const reason_to_checkt &r=reasons_to_check[i]; if(r.is_function) reason[r.function_name].functions.insert(r.info); @@ -637,7 +689,8 @@ void summarizer_bw_cex_completet::debug_print std::cout << "DebugInfo: function -> " << function_name << " ; dependency_set -> "; for(find_symbols_sett::iterator d_it=dependency_set.begin(); - d_it!=dependency_set.end(); d_it++){ + d_it!=dependency_set.end(); d_it++) + { std::cout << *d_it << ", "; } std::cout << "\n"; @@ -664,8 +717,8 @@ void summarizer_bw_cex_completet::add_reason_to_check( literalt l=solver.solver->convert(expr); if(l.is_false()) { - literalt dummy=solver.solver->convert(symbol_exprt("goto_symex::\\dummy", - bool_typet())); + literalt dummy= + solver.solver->convert(symbol_exprt("goto_symex::\\dummy", bool_typet())); formula.push_back(dummy); formula.push_back(!dummy); } diff --git a/src/solver/summarizer_bw_cex_complete.h b/src/solver/summarizer_bw_cex_complete.h index df4ca0094..098395872 100644 --- a/src/solver/summarizer_bw_cex_complete.h +++ b/src/solver/summarizer_bw_cex_complete.h @@ -21,21 +21,29 @@ Author: Madhukar Kumar, Peter Schrammel #include "summarizer_bw_cex.h" -class summarizer_bw_cex_completet : public summarizer_bw_cex_baset +class summarizer_bw_cex_completet:public summarizer_bw_cex_baset { - public: - explicit summarizer_bw_cex_completet(optionst &_options, - summary_dbt &_summary_db, - ssa_dbt &_ssa_db, - ssa_unwindert &_ssa_unwinder, - ssa_inlinert &_ssa_inliner, - incremental_solvert &_solver, - function_namet _entry_function, - function_namet _error_function): - summarizer_bw_cex_baset(_options, _summary_db, _ssa_db, _ssa_unwinder, _ssa_inliner, - _entry_function, _error_function), +public: + summarizer_bw_cex_completet( + optionst &_options, + summary_dbt &_summary_db, + ssa_dbt &_ssa_db, + ssa_unwindert &_ssa_unwinder, + ssa_inlinert &_ssa_inliner, + incremental_solvert &_solver, + function_namet _entry_function, + function_namet _error_function): + summarizer_bw_cex_baset( + _options, + _summary_db, + _ssa_db, + _ssa_unwinder, + _ssa_inliner, + _entry_function, + _error_function), solver(_solver) - {} + { + } virtual void summarize(const function_namet &entry_function); virtual void summarize(const exprt &_error_assertion); @@ -50,7 +58,8 @@ class summarizer_bw_cex_completet : public summarizer_bw_cex_baset exprt::operandst loop_continues; exprt::operandst renamed_error_assertion; - struct reason_to_checkt { + struct reason_to_checkt + { function_namet function_name; bool is_function; local_SSAt::locationt info; @@ -60,22 +69,20 @@ class summarizer_bw_cex_completet : public summarizer_bw_cex_baset const exprt &expr, const function_namet &function_name, bool is_function, - const local_SSAt::locationt & info); + const local_SSAt::locationt &info); virtual find_symbols_sett inline_summaries( - const function_namet &function_name, - find_symbols_sett &dependency_set, - int counter); + const function_namet &function_name, + find_symbols_sett &dependency_set, + int counter); virtual find_symbols_sett compute_summary_rec( - const function_namet &function_name, - find_symbols_sett &dependency_set, - int counter); + const function_namet &function_name, + find_symbols_sett &dependency_set, + int counter); virtual void debug_print( - const function_namet &function_name, - find_symbols_sett &dependency_set); - + const function_namet &function_name, + find_symbols_sett &dependency_set); }; - -#endif +#endif // CPROVER_2LS_SOLVER_SUMMARIZER_BW_CEX_COMPLETE_H diff --git a/src/solver/summarizer_bw_cex_concrete.cpp b/src/solver/summarizer_bw_cex_concrete.cpp index 9678ebc15..9f5882334 100644 --- a/src/solver/summarizer_bw_cex_concrete.cpp +++ b/src/solver/summarizer_bw_cex_concrete.cpp @@ -16,7 +16,9 @@ Author: Kumar Madhukar, Peter Schrammel // #define DEBUG +#ifdef DEBUG #include +#endif #include #include @@ -27,12 +29,12 @@ Author: Kumar Madhukar, Peter Schrammel #include "summarizer_bw_cex_concrete.h" #include "summary_db.h" -#include "../domains/ssa_analyzer.h" -#include "../domains/template_generator_summary.h" -#include "../domains/template_generator_callingcontext.h" +#include +#include +#include -#include "../ssa/local_ssa.h" -#include "../ssa/simplify_ssa.h" +#include +#include /*******************************************************************\ @@ -51,8 +53,8 @@ void summarizer_bw_cex_concretet::summarize(const function_namet &function_name) exprt postcondition=true_exprt(); // initial calling context status() << "\nSummarizing function " << function_name << eom; - compute_summary_rec(function_name, summaryt::entry_call_site, - postcondition, true); + compute_summary_rec( + function_name, summaryt::entry_call_site, postcondition, true); } /*******************************************************************\ @@ -111,8 +113,8 @@ property_checkert::resultt summarizer_bw_cex_concretet::check() const local_SSAt &ssa=ssa_db.get(entry_function); exprt::operandst loophead_selects; exprt::operandst loop_continues; - get_loophead_selects(entry_function, ssa, - *solver.solver, loophead_selects); + get_loophead_selects( + entry_function, ssa, *solver.solver, loophead_selects); get_loop_continues(entry_function, ssa, *solver.solver, loop_continues); // check whether loops have been fully unwound bool fully_unwound= @@ -148,10 +150,9 @@ void summarizer_bw_cex_concretet::compute_summary_rec( local_SSAt &SSA=ssa_db.get(function_name); // TODO: let's just put all loops into the reason - for(local_SSAt::nodest::iterator n_it=SSA.nodes.begin(); - n_it!=SSA.nodes.end(); ++n_it) - if (n_it->loophead!=SSA.nodes.end()) - reason[function_name].loops.insert(n_it->loophead->location); + for(const auto &node : SSA.nodes) + if(node.loophead!=SSA.nodes.end()) + reason[function_name].loops.insert(node.loophead->location); summaryt summary; if(summary_db.exists(function_name)) @@ -179,13 +180,24 @@ void summarizer_bw_cex_concretet::compute_summary_rec( #endif // recursively compute summaries for function calls - inline_summaries(function_name, SSA, summary, - postcondition, context_sensitive, - true); + inline_summaries( + function_name, + SSA, + summary, + postcondition, + context_sensitive, + true); status() << "Analyzing function " << function_name << eom; - do_summary(function_name, call_site, SSA, summary, summary, postcondition, context_sensitive); + do_summary( + function_name, + call_site, + SSA, + summary, + summary, + postcondition, + context_sensitive); if(function_name==error_function) summary.has_assertion=true; @@ -198,7 +210,6 @@ void summarizer_bw_cex_concretet::compute_summary_rec( summary_db.get(function_name).output(out, SSA.ns); debug() << out.str() << eom; } - } /*******************************************************************\ @@ -227,7 +238,7 @@ void summarizer_bw_cex_concretet::do_summary( // solver #ifdef OPT_2 - incremental_solvert* fresh_solver= + incremental_solvert *fresh_solver= incremental_solvert::allocate(SSA.ns, options.get_bool_option("refine")); incremental_solvert &solver=(*fresh_solver); SSA.unmark_nodes(); @@ -256,7 +267,9 @@ void summarizer_bw_cex_concretet::do_summary( exprt::operandst assert_postcond, noassert_postcond; // add error summaries for function calls bool assertion_flag; - assertion_flag=ssa_inliner.get_summaries(SSA, call_site, false, assert_postcond, noassert_postcond, c); // backward summaries + // backward summaries + assertion_flag=ssa_inliner.get_summaries( + SSA, call_site, false, assert_postcond, noassert_postcond, c); assert_postcond.push_back(postcondition); // context // add nondet variables from callees to summary.nondets @@ -268,8 +281,10 @@ void summarizer_bw_cex_concretet::do_summary( summary.nondets.insert(*it); #ifdef DEBUG - std::cout << "Assert Summary: " << from_expr(SSA.ns, "", conjunction(assert_postcond)) << "\n\n"; - std::cout << "Noassert Summary: " << from_expr(SSA.ns, "", conjunction(noassert_postcond)) << "\n\n"; + std::cout << "Assert Summary: " + << from_expr(SSA.ns, "", conjunction(assert_postcond)) << "\n\n"; + std::cout << "Noassert Summary: " + << from_expr(SSA.ns, "", conjunction(noassert_postcond)) << "\n\n"; #endif c.push_back(not_exprt(conjunction(assert_postcond))); @@ -295,31 +310,25 @@ void summarizer_bw_cex_concretet::do_summary( #endif // assumptions must hold - for(local_SSAt::nodest::const_iterator - n_it=SSA.nodes.begin(); - n_it!=SSA.nodes.end(); - ++n_it) - for(local_SSAt::nodet::assumptionst::const_iterator - a_it=n_it->assumptions.begin(); - a_it!=n_it->assumptions.end(); - ++a_it) + for(const auto &node : SSA.nodes) + { + for(const auto &a : node.assumptions) { - #ifdef OPT_11 - solver << simplify_expr(*a_it, SSA.ns); + solver << simplify_expr(a, SSA.ns); #else #ifdef OPT_12 - store.push_back(*a_it); + store.push_back(a); #else #ifdef OPT_2 - store.push_back(*a_it); + store.push_back(a); #else - solver << *a_it; + solver << a; #endif #endif #endif - } + } #ifdef OPT_12 store.push_back(SSA.get_enabling_exprs()); @@ -364,13 +373,16 @@ void summarizer_bw_cex_concretet::do_summary( #ifdef OPT_12 #ifdef DEBUG - std::cout << "\n\n\n pushing to the solver in do_summary:" << from_expr(SSA.ns, "", conjunction(store)) << "\n\n\n"; + std::cout << "\n\n\n pushing to the solver in do_summary:" + << from_expr(SSA.ns, "", conjunction(store)) << "\n\n\n"; #endif solver << simplify_expr(conjunction(store), SSA.ns); #endif #ifdef OPT_2 #ifdef DEBUG - std::cout << "\n\n\n pushing to the solver in do_summary:" << from_expr(SSA.ns, "", simplify_expr(conjunction(store), SSA.ns)) << "\n\n\n"; + std::cout << "\n\n\n pushing to the solver in do_summary:" + << from_expr(SSA.ns, "", simplify_expr(conjunction(store), SSA.ns)) + << "\n\n\n"; #endif solver << simplify_expr(conjunction(store), SSA.ns); #endif @@ -381,7 +393,8 @@ void summarizer_bw_cex_concretet::do_summary( // solve if(solver()==decision_proceduret::D_UNSATISFIABLE) { - summary.error_summaries[call_site]=true_exprt(); // TODO: this is likely to be incomplete + // TODO: this is likely to be incomplete + summary.error_summaries[call_site]=true_exprt(); summary.has_assertion=assertion_flag; #ifndef OPT_2 solver.pop_context(); @@ -393,32 +406,32 @@ void summarizer_bw_cex_concretet::do_summary( // build error summary and add to summary exprt::operandst var_values; - for(local_SSAt::var_listt::const_iterator it=SSA.params.begin(); - it!=SSA.params.end(); it++){ - exprt summ_value=solver.get(*it); + for(const auto &var : SSA.params) + { + exprt summ_value=solver.get(var); if(!summ_value.is_nil()) - var_values.push_back(equal_exprt(*it, summ_value)); + var_values.push_back(equal_exprt(var, summ_value)); } - for(local_SSAt::var_sett::const_iterator it=SSA.globals_in.begin(); - it!=SSA.globals_in.end(); it++){ - exprt summ_value=solver.get(*it); + for(const auto &var : SSA.globals_in) + { + exprt summ_value=solver.get(var); if(!summ_value.is_nil()) - var_values.push_back(equal_exprt(*it, summ_value)); + var_values.push_back(equal_exprt(var, summ_value)); } - for(local_SSAt::var_sett::const_iterator it=SSA.globals_out.begin(); - it!=SSA.globals_out.end(); it++){ - exprt summ_value=solver.get(*it); + for(const auto &var : SSA.globals_out) + { + exprt summ_value=solver.get(var); if(!summ_value.is_nil()) - var_values.push_back(equal_exprt(*it, summ_value)); + var_values.push_back(equal_exprt(var, summ_value)); } - for(std::set::const_iterator it=summary.nondets.begin(); - it!=summary.nondets.end(); it++){ - exprt summ_value=solver.get(*it); + for(const auto &var : SSA.nondets) + { + exprt summ_value=solver.get(var); if(!summ_value.is_nil()) - var_values.push_back(equal_exprt(*it, summ_value)); + var_values.push_back(equal_exprt(var, summ_value)); } summary.error_summaries[call_site]=not_exprt(conjunction(var_values)); @@ -431,7 +444,6 @@ void summarizer_bw_cex_concretet::do_summary( #ifdef OPT_2 delete fresh_solver; #endif - } /*******************************************************************\ @@ -465,7 +477,7 @@ void summarizer_bw_cex_concretet::inline_summaries( { assert(f_it->function().id()==ID_symbol); // no function pointers - exprt postcondition_call= true_exprt(); + exprt postcondition_call=true_exprt(); postcondition_call=compute_calling_context2( function_name, SSA, old_summary, n_it, f_it, postcondition, sufficient); @@ -509,7 +521,7 @@ exprt summarizer_bw_cex_concretet::compute_calling_context2( // solver #ifdef OPT_2 - incremental_solvert* fresh_solver= + incremental_solvert *fresh_solver= incremental_solvert::allocate(SSA.ns, options.get_bool_option("refine")); incremental_solvert &solver=(*fresh_solver); #else @@ -519,7 +531,9 @@ exprt summarizer_bw_cex_concretet::compute_calling_context2( solver.set_message_handler(get_message_handler()); // collect globals at call site - std::map + std::map< + local_SSAt::nodet::function_callst::const_iterator, + local_SSAt::var_sett> cs_globals_out; SSA.get_globals(n_it->location, cs_globals_out[f_it], false); @@ -538,7 +552,13 @@ exprt summarizer_bw_cex_concretet::compute_calling_context2( exprt::operandst assert_postcond, noassert_postcond; // add error summaries for function calls - ssa_inliner.get_summaries(SSA, summaryt::call_sitet(n_it->location), false, assert_postcond, noassert_postcond, c); // backward summaries + ssa_inliner.get_summaries( + SSA, + summaryt::call_sitet(n_it->location), + false, + assert_postcond, + noassert_postcond, + c); assert_postcond.push_back(postcondition); // context c.push_back(not_exprt(conjunction(assert_postcond))); c.push_back(not_exprt(disjunction(noassert_postcond))); @@ -582,7 +602,8 @@ exprt summarizer_bw_cex_concretet::compute_calling_context2( #ifdef OPT_12 #ifdef DEBUG - std::cout << "\n\n\n pushing to the solver in compute_calling_context2:" << from_expr(SSA.ns, "", conjunction(store)) << "\n\n\n"; + std::cout << "\n\n\n pushing to the solver in compute_calling_context2:" + << from_expr(SSA.ns, "", conjunction(store)) << "\n\n\n"; #endif solver << simplify_expr(conjunction(store), SSA.ns); #endif @@ -614,13 +635,16 @@ exprt summarizer_bw_cex_concretet::compute_calling_context2( // get callee SSA and rename local_SSAt &fSSA=ssa_db.get(fname); - ssa_inliner.rename_to_callee(f_it, fSSA.params, - cs_globals_out[f_it], fSSA.globals_out, - postcondition_call); + ssa_inliner.rename_to_callee( + f_it, + fSSA.params, + cs_globals_out[f_it], + fSSA.globals_out, + postcondition_call); - debug() << "Backward calling context for " << - from_expr(SSA.ns, "", *f_it) << ": " - << from_expr(SSA.ns, "", postcondition_call) << eom; + debug() << "Backward calling context for " + << from_expr(SSA.ns, "", *f_it) << ": " + << from_expr(SSA.ns, "", postcondition_call) << eom; // statistics solver_calls++; @@ -631,5 +655,3 @@ exprt summarizer_bw_cex_concretet::compute_calling_context2( return not_exprt(postcondition_call); } - - diff --git a/src/solver/summarizer_bw_cex_concrete.h b/src/solver/summarizer_bw_cex_concrete.h index ec517ccdc..b13d9509c 100644 --- a/src/solver/summarizer_bw_cex_concrete.h +++ b/src/solver/summarizer_bw_cex_concrete.h @@ -21,20 +21,25 @@ Author: Kumar Madhukar, Peter Schrammel #include "summarizer_bw_cex.h" -class summarizer_bw_cex_concretet : public summarizer_bw_cex_baset +class summarizer_bw_cex_concretet:public summarizer_bw_cex_baset { public: -summarizer_bw_cex_concretet( - optionst &_options, - summary_dbt &_summary_db, - ssa_dbt &_ssa_db, - ssa_unwindert &_ssa_unwinder, - ssa_inlinert &_ssa_inliner, - function_namet _entry_function, - function_namet _error_function): - summarizer_bw_cex_baset(_options, _summary_db, _ssa_db, - _ssa_unwinder, _ssa_inliner, - _entry_function, _error_function) + summarizer_bw_cex_concretet( + optionst &_options, + summary_dbt &_summary_db, + ssa_dbt &_ssa_db, + ssa_unwindert &_ssa_unwinder, + ssa_inlinert &_ssa_inliner, + function_namet _entry_function, + function_namet _error_function): + summarizer_bw_cex_baset( + _options, + _summary_db, + _ssa_db, + _ssa_unwinder, + _ssa_inliner, + _entry_function, + _error_function) {} virtual void summarize(const function_namet &entry_function); @@ -74,7 +79,6 @@ summarizer_bw_cex_concretet( local_SSAt::nodet::function_callst::const_iterator f_it, const exprt &postcondition, bool sufficient); - }; -#endif +#endif // CPROVER_2LS_SOLVER_SUMMARIZER_BW_CEX_CONCRETE_H diff --git a/src/solver/summarizer_bw_cex_wp.cpp b/src/solver/summarizer_bw_cex_wp.cpp index f7535f6dd..5f4d43e0f 100644 --- a/src/solver/summarizer_bw_cex_wp.cpp +++ b/src/solver/summarizer_bw_cex_wp.cpp @@ -6,7 +6,11 @@ Author: Madhukar Kumar, Peter Schrammel \*******************************************************************/ +// #define DEBUG + +#ifdef DEBUG #include +#endif #include #include @@ -16,13 +20,13 @@ Author: Madhukar Kumar, Peter Schrammel #include "summary_db.h" -#include "../domains/ssa_analyzer.h" -#include "../domains/template_generator_summary.h" -#include "../domains/template_generator_callingcontext.h" +#include +#include +#include -#include "../ssa/local_ssa.h" -#include "../ssa/simplify_ssa.h" -#include "../ssa/ssa_dependency_graph.h" +#include +#include +#include #include "summarizer_bw_cex_wp.h" @@ -38,16 +42,15 @@ Function: summarizer_bw_cex_wpt::summarize() \*******************************************************************/ -void summarizer_bw_cex_wpt::summarize -( - const function_namet &entry_function) +void summarizer_bw_cex_wpt::summarize( + const function_namet &entry_function) { // no dependencies to begin with find_symbols_sett dependency_set; status() << "\nSummarizing function " << entry_function << eom; - compute_summary_rec(entry_function, dependency_set, -1, - summaryt::entry_call_site); + compute_summary_rec( + entry_function, dependency_set, -1, summaryt::entry_call_site); } /*******************************************************************\ @@ -66,11 +69,11 @@ void summarizer_bw_cex_wpt::summarize(const exprt &_error_assertion) { status() << "\nBackward error analysis (WP)..." << eom; error_assertion=_error_assertion; - /* +#ifdef DEBUG std::cout << "error assertion: " - << from_expr(ssa_db.get(entry_function).ns, "", error_assertion) - << "\n"; - */ + << from_expr(ssa_db.get(entry_function).ns, "", error_assertion) + << "\n"; +#endif summarize(entry_function); } @@ -87,38 +90,43 @@ Function: summarizer_bw_cex_wpt::inline_summaries() \*******************************************************************/ -find_symbols_sett summarizer_bw_cex_wpt::inline_summaries -( - const function_namet &function_name, - const find_symbols_sett &dependency_set, - int counter, - exprt &error_summary) +find_symbols_sett summarizer_bw_cex_wpt::inline_summaries( + const function_namet &function_name, + const find_symbols_sett &dependency_set, + int counter, + exprt &error_summary) { exprt::operandst slice; local_SSAt &SSA=ssa_db.get(function_name); - // solver << SSA.get_enabling_exprs(); exprt::operandst loophead_selects; get_loophead_selects(function_name, SSA, *solver.solver, loophead_selects); exprt c=conjunction(loophead_selects); - // std::cout << "Solver <-- " << function_name << ": (conjunction of loophead_selects):" - // << "\t original info ~ " << from_expr(ssa_db.get(function_name).ns, "", c) << "\n"; +#ifdef DEBUG + std::cout << "Solver <-- " << function_name + << ": (conjunction of loophead_selects):" + << "\t original info ~ " + << from_expr(ssa_db.get(function_name).ns, "", c) << "\n"; +#endif slice.push_back(c); ssa_inliner.rename(c, counter); -#if 0 - std::cout << "Solver <-- " << function_name << ": (conjunction of loophead_selects):" - << "\t renamed info ~ " << from_expr(ssa_db.get(function_name).ns, "", c) << "\n"; +#ifdef DEBUG + std::cout << "Solver <-- " << function_name + << ": (conjunction of loophead_selects):" + << "\t renamed info ~ " + << from_expr(ssa_db.get(function_name).ns, "", c) << "\n"; #endif solver << c; ssa_dependency_grapht &ssa_depgraph=ssa_db.get_depgraph(function_name); - struct worknodet{ + struct worknodet + { int node_index; find_symbols_sett dependency_set; }; @@ -133,39 +141,41 @@ find_symbols_sett summarizer_bw_cex_wpt::inline_summaries worklist.push_back(start_node); - while(!worklist.empty()){ - - /* + while(!worklist.empty()) + { +#ifdef DEBUG std::cout << "worklist: "; for(worklistt::const_iterator w_it=worklist.begin(); - w_it!=worklist.end(); w_it++){ + w_it!=worklist.end(); w_it++) + { std::cout << w_it->node_index << " "; } std::cout << "\n"; std::cout << "\t waitlist: "; for(worklistt::const_iterator w_it=work_waitlist.begin(); - w_it!=work_waitlist.end(); w_it++){ + w_it!=work_waitlist.end(); w_it++) + { std::cout << w_it->node_index << " "; } std::cout << "\n"; - */ +#endif worknodet &worknode=worklist.front(); - // std::cout << "working node: " << function_name << ": " << worknode.node_index << "\n"; - // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // / - // std::cout << "\t size of dependency set: " << worknode.dependency_set.size() << "\n"; - /* +#ifdef DEBUG + std::cout << "working node: " << function_name + << ": " << worknode.node_index << "\n"; + std::cout << "\t size of dependency set: " + << worknode.dependency_set.size() << "\n"; std::cout << "\t dependency set: "; for(find_symbols_sett::iterator d_it=worknode.dependency_set.begin(); - d_it!=worknode.dependency_set.end(); d_it++){ + d_it!=worknode.dependency_set.end(); d_it++) + { std::cout << *d_it; } std::cout << "\n\n\n"; - */ - // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // / - +#endif // return if the top most node is reached if(worknode.node_index==ssa_depgraph.top_node_index) @@ -177,230 +187,291 @@ find_symbols_sett summarizer_bw_cex_wpt::inline_summaries } // modify worknode_dependency_set if the node is an assertion - if(ssa_depgraph.depnodes_map[worknode.node_index].is_assertion==true){ - - // std::cout << "\t\t an assertion node\n"; - for(find_symbols_sett::const_iterator d_it=ssa_depgraph.depnodes_map[worknode.node_index].used_symbols.begin(); - d_it!=ssa_depgraph.depnodes_map[worknode.node_index].used_symbols.end(); d_it++){ - worknode.dependency_set.insert(*d_it); + if(ssa_depgraph.depnodes_map[worknode.node_index].is_assertion==true) + { +#ifdef DEBUG + std::cout << "\t\t an assertion node\n"; +#endif + for(find_symbols_sett::const_iterator d_it= + ssa_depgraph.depnodes_map[worknode.node_index].used_symbols.begin(); + d_it!= + ssa_depgraph.depnodes_map[worknode.node_index].used_symbols.end(); + d_it++) + { + worknode.dependency_set.insert(*d_it); } - // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // / - /* - std::cout << "\t size of dependency set: " << worknode.dependency_set.size() << "\n"; +#ifdef DEBUG + std::cout << "\t size of dependency set: " + << worknode.dependency_set.size() << "\n"; std::cout << "\t dependency set: "; for(find_symbols_sett::iterator d_it=worknode.dependency_set.begin(); - d_it!=worknode.dependency_set.end(); d_it++){ - std::cout << *d_it; + d_it!=worknode.dependency_set.end(); d_it++) + { + std::cout << *d_it; } std::cout << "\n"; - */ - // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // / - - - +#endif } // if this is a function call - if(ssa_depgraph.depnodes_map[worknode.node_index].is_function_call==true){ - // std::cout << "fcall: working node: " << function_name << ": " << worknode.node_index << "\n"; + if(ssa_depgraph.depnodes_map[worknode.node_index].is_function_call==true) + { +#ifdef DEBUG + std::cout << "fcall: working node: " << function_name << ": " + << worknode.node_index << "\n"; +#endif irep_idt fname= - to_symbol_expr((to_function_application_expr(ssa_depgraph.depnodes_map[worknode.node_index].node_info)).function()).get_identifier(); + to_symbol_expr( + to_function_application_expr( + ssa_depgraph.depnodes_map[worknode.node_index].node_info) + .function()).get_identifier(); find_symbols_sett renamed_dependencies; - // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // / - /* - std::cout << "\t size of dependency set: " << worknode.dependency_set.size() << "\n"; +#ifdef DEBUG + std::cout << "\t size of dependency set: " + << worknode.dependency_set.size() << "\n"; std::cout << "\t dependency set: "; for(find_symbols_sett::iterator d_it=worknode.dependency_set.begin(); - d_it!=worknode.dependency_set.end(); d_it++){ - std::cout << *d_it; + d_it!=worknode.dependency_set.end(); d_it++) + { + std::cout << *d_it; } std::cout << "\n"; - */ - // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // / +#endif for(find_symbols_sett::iterator d_it=worknode.dependency_set.begin(); - d_it!=worknode.dependency_set.end(); d_it++){ + d_it!=worknode.dependency_set.end(); d_it++) + { irep_idt renamed_id=*d_it; // detach the '@' symbol if there - ssa_inliner.rename(renamed_id, - ssa_depgraph.depnodes_map[worknode.node_index].rename_counter, false); + ssa_inliner.rename( + renamed_id, + ssa_depgraph.depnodes_map[worknode.node_index].rename_counter, + false); renamed_dependencies.insert(renamed_id); } worknode.dependency_set=renamed_dependencies; - if(!worknode.dependency_set.empty()){ - find_symbols_sett guard_dependencies; - find_symbols(ssa_depgraph.depnodes_map[worknode.node_index].guard, - guard_dependencies); - for(find_symbols_sett::const_iterator d_it=guard_dependencies.begin(); - d_it!=guard_dependencies.end(); d_it++){ - worknode.dependency_set.insert(*d_it); + if(!worknode.dependency_set.empty()) + { + find_symbols_sett guard_dependencies; + find_symbols( + ssa_depgraph.depnodes_map[worknode.node_index].guard, + guard_dependencies); + for(find_symbols_sett::const_iterator d_it=guard_dependencies.begin(); + d_it!=guard_dependencies.end(); d_it++) + { + worknode.dependency_set.insert(*d_it); } } - // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // / - /* - std::cout << "\t size of dependency set: " << worknode.dependency_set.size() << "\n"; +#ifdef DEBUG + std::cout << "\t size of dependency set: " + << worknode.dependency_set.size() << "\n"; std::cout << "\t dependency set: "; for(find_symbols_sett::iterator d_it=worknode.dependency_set.begin(); - d_it!=worknode.dependency_set.end(); d_it++){ - std::cout << *d_it; + d_it!=worknode.dependency_set.end(); d_it++) + { + std::cout << *d_it; } std::cout << "\n"; - */ - // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // / +#endif worknode.dependency_set= - compute_summary_rec(fname, worknode.dependency_set, - ssa_depgraph.depnodes_map[worknode.node_index].rename_counter, summaryt::call_sitet(ssa_depgraph.depnodes_map[worknode.node_index].location)); + compute_summary_rec( + fname, + worknode.dependency_set, + ssa_depgraph.depnodes_map[worknode.node_index].rename_counter, + summaryt::call_sitet( + ssa_depgraph.depnodes_map[worknode.node_index].location)); slice.push_back(ssa_depgraph.depnodes_map[worknode.node_index].node_info); renamed_dependencies.clear(); for(find_symbols_sett::iterator d_it=worknode.dependency_set.begin(); - d_it!=worknode.dependency_set.end(); d_it++){ + d_it!=worknode.dependency_set.end(); d_it++) + { irep_idt renamed_id=*d_it; // detach the '@' symbol if there - ssa_inliner.rename(renamed_id, - ssa_depgraph.depnodes_map[worknode.node_index].rename_counter, false); + ssa_inliner.rename( + renamed_id, + ssa_depgraph.depnodes_map[worknode.node_index].rename_counter, + false); renamed_dependencies.insert(renamed_id); } worknode.dependency_set=renamed_dependencies; - if(!worknode.dependency_set.empty()){ - find_symbols_sett guard_dependencies; - find_symbols(ssa_depgraph.depnodes_map[worknode.node_index].guard, guard_dependencies); - for(find_symbols_sett::const_iterator d_it=guard_dependencies.begin(); - d_it!=guard_dependencies.end(); d_it++){ - worknode.dependency_set.insert(*d_it); + if(!worknode.dependency_set.empty()) + { + find_symbols_sett guard_dependencies; + find_symbols( + ssa_depgraph.depnodes_map[worknode.node_index].guard, + guard_dependencies); + for(find_symbols_sett::const_iterator d_it=guard_dependencies.begin(); + d_it!=guard_dependencies.end(); d_it++) + { + worknode.dependency_set.insert(*d_it); } } - } // if the dependency set is non-empty - if(!worknode.dependency_set.empty()){ - exprt worknode_info=ssa_depgraph.depnodes_map[worknode.node_index].node_info; + if(!worknode.dependency_set.empty()) + { + exprt worknode_info= + ssa_depgraph.depnodes_map[worknode.node_index].node_info; if(ssa_depgraph.depnodes_map[worknode.node_index].is_assertion==true) - worknode_info=not_exprt(worknode_info); - - if(worknode.node_index!=0){ - if(!(ssa_depgraph.depnodes_map[worknode.node_index].is_function_call)){ - if((ssa_depgraph.depnodes_map[worknode.node_index].is_assertion==false) || - (worknode_info==error_assertion)){ - /* - std::cout << "Solver <-- " << function_name << ": (node) node#:" - << worknode.node_index << "\t original info ~ " - << from_expr((ssa_db.get(function_name)).ns, "", worknode_info) << "\n"; - */ + worknode_info=not_exprt(worknode_info); + + if(worknode.node_index!=0) + { + if(!(ssa_depgraph.depnodes_map[worknode.node_index].is_function_call)) + { + if((ssa_depgraph.depnodes_map[worknode.node_index] + .is_assertion==false) || + (worknode_info==error_assertion)) + { +#ifdef DEBUG + std::cout << "Solver <-- " << function_name << ": (node) node#:" + << worknode.node_index << "\t original info ~ " + << from_expr( + (ssa_db.get(function_name)).ns, "", worknode_info) + << "\n"; +#endif + slice.push_back(worknode_info); - ssa_inliner.rename(worknode_info, counter); -#if 0 - std::cout << "Solver <-- renamed assertion: " << from_expr((ssa_db.get(function_name)).ns, "", worknode_info) << "\n"; - std::cout << "Solver <-- " << function_name << ": (node) node#:" - << worknode.node_index << "\t renamed info ~ " - << from_expr((ssa_db.get(function_name)).ns, "", worknode_info) << "\n"; + ssa_inliner.rename(worknode_info, counter); + +#ifdef DEBUG + std::cout << "Solver <-- renamed assertion: " + << from_expr( + (ssa_db.get(function_name)).ns, "", worknode_info) + << "\n"; + std::cout << "Solver <-- " << function_name << ": (node) node#:" + << worknode.node_index << "\t renamed info ~ " + << from_expr( + (ssa_db.get(function_name)).ns, "", worknode_info) + << "\n"; #endif - solver << worknode_info; - } - } - else{ - exprt guard_binding=ssa_depgraph.depnodes_map[worknode.node_index].guard; - /* - std::cout << "Solver <-- " << function_name << ": (bind) node#:" - << worknode.node_index << "\t original info ~ " - << from_expr(ssa_db.get(function_name).ns, "", guard_binding) << "\n"; - */ - ssa_inliner.rename(guard_binding, counter); -#if 0 - std::cout << "Solver <-- " << function_name << ": (bind) node#:" - << worknode.node_index << "\t renamed info ~ " - << from_expr(ssa_db.get(function_name).ns, "", guard_binding) << "\n"; + solver << worknode_info; + } + } + else + { + exprt guard_binding= + ssa_depgraph.depnodes_map[worknode.node_index].guard; +#ifdef DEBUG + std::cout << "Solver <-- " << function_name << ": (bind) node#:" + << worknode.node_index << "\t original info ~ " + << from_expr(ssa_db.get(function_name).ns, "", guard_binding) + << "\n"; #endif - solver << guard_binding; + + ssa_inliner.rename(guard_binding, counter); + +#ifdef DEBUG + std::cout << "Solver <-- " << function_name << ": (bind) node#:" + << worknode.node_index << "\t renamed info ~ " + << from_expr( + ssa_db.get(function_name).ns, "", guard_binding) + << "\n"; +#endif + solver << guard_binding; slice.push_back(guard_binding); - } + } } } // if not a function call and the dependency set is non-empty - if((ssa_depgraph.depnodes_map[worknode.node_index].is_function_call==false) && - (!worknode.dependency_set.empty())){ - - exprt worknode_info=ssa_depgraph.depnodes_map[worknode.node_index].node_info; + if((ssa_depgraph.depnodes_map[worknode.node_index] + .is_function_call==false) && + (!worknode.dependency_set.empty())) + { + exprt worknode_info= + ssa_depgraph.depnodes_map[worknode.node_index].node_info; if(ssa_depgraph.depnodes_map[worknode.node_index].is_assertion==true) - worknode_info=not_exprt(worknode_info); + worknode_info=not_exprt(worknode_info); if((ssa_depgraph.depnodes_map[worknode.node_index].is_assertion==false) || - (worknode_info==error_assertion)){ - worknode.dependency_set= - ssa_depgraph.depnodes_map[worknode.node_index].used_symbols; + (worknode_info==error_assertion)) + { + worknode.dependency_set= + ssa_depgraph.depnodes_map[worknode.node_index].used_symbols; } } for(ssa_dependency_grapht::annotated_predecessorst::const_iterator - p_it=ssa_depgraph.depnodes_map[worknode.node_index].predecessors.begin(); - p_it!=ssa_depgraph.depnodes_map[worknode.node_index].predecessors.end(); - p_it++){ - + p_it=ssa_depgraph.depnodes_map[worknode.node_index] + .predecessors.begin(); + p_it!=ssa_depgraph.depnodes_map[worknode.node_index].predecessors.end(); + p_it++) + { ssa_dependency_grapht::annotated_predecessort pred=*p_it; int pred_node_index=pred.predecessor_node_index; find_symbols_sett pred_annotation=pred.annotation; bool dependencies_merged=false; - for(worklistt::iterator w_it=work_waitlist.begin(); w_it!=work_waitlist.end(); w_it++){ - if(w_it->node_index==pred_node_index){ - - dependencies_merged=true; - - for(find_symbols_sett::const_iterator - a_it=pred_annotation.begin(); a_it!=pred_annotation.end(); a_it++) + for(worklistt::iterator w_it=work_waitlist.begin(); + w_it!=work_waitlist.end(); w_it++) { - if(worknode.dependency_set.find(*a_it)!=worknode.dependency_set.end()){ - if((w_it->dependency_set).find(*a_it)==(w_it->dependency_set).end()){ - (w_it->dependency_set).insert(*a_it); - } + if(w_it->node_index==pred_node_index) + { + dependencies_merged=true; + + for(find_symbols_sett::const_iterator + a_it=pred_annotation.begin(); + a_it!=pred_annotation.end(); a_it++) + { + if(worknode.dependency_set.find(*a_it)!= + worknode.dependency_set.end()) + { + if((w_it->dependency_set).find(*a_it)== + (w_it->dependency_set).end()) + { + (w_it->dependency_set).insert(*a_it); + } + } + } + break; } } - break; - } - } - - if(dependencies_merged==false){ - worknodet new_worknode; - new_worknode.node_index=pred_node_index; - for(find_symbols_sett::const_iterator - a_it=pred_annotation.begin(); a_it!=pred_annotation.end(); a_it++) - { - if(worknode.dependency_set.find(*a_it)!=worknode.dependency_set.end()) - new_worknode.dependency_set.insert(*a_it); - } + if(dependencies_merged==false) + { + worknodet new_worknode; + new_worknode.node_index=pred_node_index; + + for(find_symbols_sett::const_iterator + a_it=pred_annotation.begin(); a_it!=pred_annotation.end(); a_it++) + { + if(worknode.dependency_set.find(*a_it)!=worknode.dependency_set.end()) + new_worknode.dependency_set.insert(*a_it); + } - work_waitlist.push_back(new_worknode); + work_waitlist.push_back(new_worknode); } } -#if 0 +#ifdef DEBUG std::cout << function_name << ": worklist: "; for(worklistt::const_iterator w_it=worklist.begin(); - w_it!=worklist.end(); w_it++){ + w_it!=worklist.end(); w_it++) + { std::cout << w_it->node_index << " "; } std::cout << "\n"; - std::cout << "\t" << function_name << ": waitlist: "; for(worklistt::const_iterator w_it=work_waitlist.begin(); - w_it!=work_waitlist.end(); w_it++){ + w_it!=work_waitlist.end(); w_it++) + { std::cout << w_it->node_index << " "; } std::cout << "\n"; @@ -409,9 +480,10 @@ find_symbols_sett summarizer_bw_cex_wpt::inline_summaries covered_nodes.push_back(worknode.node_index); worklist.pop_front(); -#if 0 +#ifdef DEBUG std::cout << function_name << ": covered : "; - for(int l=0; l &waitlisted_worknode_successors= - ssa_depgraph.depnodes_map[waitlisted_worknode.node_index].successors; - - for(unsigned i=0; i " << function_name - << " ; dependency_set -> "; + << " ; dependency_set -> "; for(find_symbols_sett::iterator d_it=dependency_set.begin(); - d_it!=dependency_set.end(); d_it++){ + d_it!=dependency_set.end(); d_it++) + { std::cout << *d_it << ", "; } std::cout << "\n"; @@ -569,6 +648,7 @@ Function: summarizer_bw_cex_wpt::simplify_summary() Purpose: \*******************************************************************/ + void summarizer_bw_cex_wpt::simplify_summary_build_map( replace_mapt &replace_map, const exprt &expr) { @@ -580,6 +660,20 @@ void summarizer_bw_cex_wpt::simplify_summary_build_map( forall_operands(it, expr) simplify_summary_build_map(replace_map, *it); } + + +/*******************************************************************\ + +Function: summarizer_bw_cex_wpt::simplify_summary_replace() + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + bool summarizer_bw_cex_wpt::simplify_summary_replace( const replace_mapt &replace_map, exprt &expr) { @@ -587,7 +681,7 @@ bool summarizer_bw_cex_wpt::simplify_summary_replace( { bool result=true; exprt::operandst &args=to_function_application_expr(expr).arguments(); - for(size_t i=0;i nonpassed_assertions; - struct call_sitet { // TODO: we also need unwinding information here - call_sitet() - : location_number(UINT_MAX) {} - explicit call_sitet(local_SSAt::locationt loc) - : location_number(loc->location_number) {} + struct call_sitet + { // TODO: we also need unwinding information here + call_sitet():location_number(UINT_MAX) {} + explicit call_sitet(local_SSAt::locationt loc): + location_number(loc->location_number) + { + } unsigned location_number; bool operator<(const call_sitet &other) const - { return (location_number error_summariest; error_summariest error_summaries; // -------------- diff --git a/src/ssa/Makefile b/src/ssa/Makefile index 54979d27f..b997fff90 100644 --- a/src/ssa/Makefile +++ b/src/ssa/Makefile @@ -1,11 +1,23 @@ SRC = local_ssa.cpp \ - ssa_domain.cpp translate_union_member.cpp malloc_ssa.cpp \ - guard_map.cpp ssa_object.cpp assignments.cpp ssa_dereference.cpp \ - ssa_value_set.cpp address_canonizer.cpp simplify_ssa.cpp \ - ssa_build_goto_trace.cpp ssa_inliner.cpp ssa_unwinder.cpp \ - unwindable_local_ssa.cpp ssa_const_propagator.cpp \ - replace_symbol_ext.cpp ssa_dependency_graph.cpp \ - ssa_refiner_monolithic.cpp ssa_refiner_selective.cpp + ssa_domain.cpp \ + translate_union_member.cpp \ + malloc_ssa.cpp \ + guard_map.cpp \ + ssa_object.cpp \ + assignments.cpp \ + ssa_dereference.cpp \ + ssa_value_set.cpp \ + address_canonizer.cpp \ + simplify_ssa.cpp \ + ssa_build_goto_trace.cpp \ + ssa_inliner.cpp \ + ssa_unwinder.cpp \ + unwindable_local_ssa.cpp \ + ssa_const_propagator.cpp \ + ssa_dependency_graph.cpp \ + ssa_refiner_monolithic.cpp \ + ssa_refiner_selective.cpp \ + # empty last line include ../config.inc include $(CBMC)/src/config.inc diff --git a/src/ssa/const_propagator.cpp b/src/ssa/const_propagator.cpp deleted file mode 100644 index e418be0a9..000000000 --- a/src/ssa/const_propagator.cpp +++ /dev/null @@ -1,467 +0,0 @@ -/*******************************************************************\ - -Module: Constant Propagation - -Author: Peter Schrammel - -\*******************************************************************/ - -// #define DEBUG - -#include - -#include -#include - -#include "const_propagator.h" - -/*******************************************************************\ - -Function: const_propagator_domaint::assign_rec - - Inputs: - - Outputs: - - Purpose: - -\*******************************************************************/ - -void const_propagator_domaint::assign_rec(const exprt &lhs, const exprt &rhs, - const namespacet &ns) -{ - const typet & rhs_type=ns.follow(rhs.type()); - -#ifdef DEBUG - std::cout << "assign: " << from_expr(ns, "", lhs) - << " := " << from_type(ns, "", rhs_type) << std::endl; -#endif - - if(lhs.id()==ID_symbol && rhs_type.id()!=ID_array - && rhs_type.id()!=ID_struct - && rhs_type.id()!=ID_union) - { - if(!values.maps_to_top(rhs)) - assign(values, lhs, rhs, ns); - else - values.set_to_top(lhs); - } -#if 0 - else // TODO: could make field or array element-sensitive - { - } -#endif -} - -/*******************************************************************\ - -Function: const_propagator_domaint::transform - - Inputs: - - Outputs: - - Purpose: - -\*******************************************************************/ - -void const_propagator_domaint::transform( - locationt from, - locationt to, - ai_baset &ai, - const namespacet &ns) -{ -#ifdef DEBUG - std::cout << from->location_number << " --> " - << to->location_number << std::endl; -#endif - - if(from->is_decl()) - { - values.set_to_top(to_code_decl(from->code).symbol()); - } - else if(from->is_assign()) - { - const code_assignt &assignment=to_code_assign(from->code); - const exprt &lhs=assignment.lhs(); - const exprt &rhs=assignment.rhs(); - assign_rec(lhs, rhs, ns); - } - else if(from->is_goto()) - { - if(from->guard.id()==ID_equal && from->get_target()==to) - { - const exprt &lhs=from->guard.op0(); - const exprt &rhs=from->guard.op1(); - - assign_rec(lhs, rhs, ns); - assign_rec(rhs, lhs, ns); - } - } - else if(from->is_dead()) - { - const code_deadt &code_dead=to_code_dead(from->code); - values.set_to_top(code_dead.symbol()); - } - else if(from->is_function_call()) - { - values.set_all_to_top(); - } - -#ifdef DEBUG - output(std::cout, ai, ns); -#endif -} - -/*******************************************************************\ - -Function: const_propagator_domaint::assign - - Inputs: - - Outputs: - - Purpose: - -\*******************************************************************/ - -void const_propagator_domaint::assign( - valuest &dest, - const exprt &lhs, - exprt rhs, - const namespacet &ns) const -{ -#ifdef DEBUG - std::cout << "assign: " << from_expr(ns, "", lhs) - << " := " << from_expr(ns, "", rhs) << std::endl; -#endif - - values.replace_const(rhs); - - // this is to remove casts in constants propagated into the size of array types - bool valid=true; - exprt rhs_val=evaluate_casts_in_constants(rhs, lhs.type(), valid); - if(valid) - dest.set_to(lhs, rhs_val); -} - -/*******************************************************************\ - -Function: const_propagator_domaint::valuest::maps_to_top - - Inputs: - - Outputs: - - Purpose: - -\*******************************************************************/ - -bool const_propagator_domaint::valuest::maps_to_top(const exprt &expr) const -{ - if(expr.id()==ID_side_effect && - to_side_effect_expr(expr).get_statement()==ID_nondet) - return true; - if(expr.id()==ID_symbol) - if(replace_const.expr_map.find(expr.get(ID_identifier)) - ==replace_const.expr_map.end()) - return true; - forall_operands(it, expr) - { - if(maps_to_top(*it)) - return true; - } - return false; -} - -/*******************************************************************\ - -Function: const_propagator_domaint::valuest::set_to_top - - Inputs: - - Outputs: - - Purpose: - -\*******************************************************************/ - -bool const_propagator_domaint::valuest::set_to_top(const irep_idt &id) -{ - bool result=false; - replace_symbolt::expr_mapt::iterator r_it= - replace_const.expr_map.find(id); - if(r_it!=replace_const.expr_map.end()) - { - replace_const.expr_map.erase(r_it); - result=true; - } - if(top_ids.find(id)==top_ids.end()) - { - top_ids.insert(id); - result=true; - } - return result; -} - -bool const_propagator_domaint::valuest::set_to_top(const exprt &expr) -{ - return set_to_top(to_symbol_expr(expr).get_identifier()); -} - -void const_propagator_domaint::valuest::set_all_to_top() -{ - for(replace_symbolt::expr_mapt::iterator it= - replace_const.expr_map.begin(); - it!=replace_const.expr_map.end(); ++it) - top_ids.insert(it->first); - replace_const.expr_map.clear(); -} - - -/*******************************************************************\ - -Function: const_propagator_domaint::valuest::add - - Inputs: - - Outputs: - - Purpose: - -\*******************************************************************/ - -void const_propagator_domaint::valuest::set_to(const irep_idt &lhs_id, - const exprt &rhs_val) -{ - replace_const.expr_map[lhs_id]=rhs_val; - std::set::iterator it=top_ids.find(lhs_id); - if(it!=top_ids.end()) top_ids.erase(it); -} - -void const_propagator_domaint::valuest::set_to(const exprt &lhs, - const exprt &rhs_val) -{ - const irep_idt &lhs_id=to_symbol_expr(lhs).get_identifier(); - set_to(lhs_id, rhs_val); -} - -/*******************************************************************\ - -Function: const_propagator_domaint::valuest::output - - Inputs: - - Outputs: - - Purpose: - -\*******************************************************************/ - -void const_propagator_domaint::valuest::output( - std::ostream &out, - const namespacet &ns) const -{ - out << "const map: " << std::endl; - for(replace_symbolt::expr_mapt::const_iterator - it=replace_const.expr_map.begin(); - it!=replace_const.expr_map.end(); - ++it) - out << ' ' << it->first << "=" << - from_expr(ns, "", it->second) << std::endl; - out << "top ids: " << std::endl; - for(std::set::const_iterator - it=top_ids.begin(); - it!=top_ids.end(); - ++it) - out << ' ' << *it << std::endl; -} - -/*******************************************************************\ - -Function: const_propagator_domaint::output - - Inputs: - - Outputs: - - Purpose: - -\*******************************************************************/ - -void const_propagator_domaint::output( - std::ostream &out, - const ai_baset &ai, - const namespacet &ns) const -{ - values.output(out, ns); -} - -/*******************************************************************\ - -Function: const_propagator_domaint::valuest::merge - - Inputs: - - Outputs: Return true if "this" has changed. - - Purpose: - -\*******************************************************************/ - -bool const_propagator_domaint::valuest::merge(const valuest &src) -{ - bool changed=false; - for(replace_symbolt::expr_mapt::const_iterator - it=src.replace_const.expr_map.begin(); - it!=src.replace_const.expr_map.end(); ++it) - { - replace_symbolt::expr_mapt::iterator - c_it=replace_const.expr_map.find(it->first); - if(c_it!=replace_const.expr_map.end()) - { - if(c_it->second!=it->second) - { - set_to_top(it->first); - changed=true; - } - } - else if(top_ids.find(it->first)==top_ids.end()) - { - set_to(it->first, it->second); - changed=true; - } - } - for(std::set::const_iterator it=src.top_ids.begin(); - it!=src.top_ids.end(); ++it) - { - bool c=set_to_top(*it); - changed=changed || c; - } - - return changed; -} - -/*******************************************************************\ - -Function: const_propagator_domaint::merge - - Inputs: - - Outputs: Return true if "this" has changed. - - Purpose: - -\*******************************************************************/ - -bool const_propagator_domaint::merge( - const const_propagator_domaint &other, - locationt from, - locationt to) -{ - return values.merge(other.values); -} - -/*******************************************************************\ - -Function: const_propagator_domaint::evaluate_casts_in_constants - - Inputs: - - Outputs: - - Purpose: - -\*******************************************************************/ - -exprt const_propagator_domaint::evaluate_casts_in_constants(exprt expr, - const typet& parent_type, bool &valid) const -{ - if(expr.id()==ID_side_effect) - { - valid=false; - return expr; - } - if(expr.type().id()!=ID_signedbv && expr.type().id()!=ID_unsignedbv) - return expr; - if(expr.id()==ID_typecast) - expr=evaluate_casts_in_constants(expr.op0(), expr.type(), valid); - if(expr.id()!=ID_constant) - { - if(expr.type()!=parent_type) - return typecast_exprt(expr, parent_type); - else - return expr; - } - // TODO: could be improved to resolve float casts as well... - if(expr.type().id()!=ID_signedbv && expr.type().id()!=ID_unsignedbv) - return expr; - mp_integer v; - to_integer(to_constant_expr(expr), v); - return from_integer(v, parent_type); -} - -/*******************************************************************\ - -Function: const_propagator_ait::replace - - Inputs: - - Outputs: - - Purpose: - -\*******************************************************************/ - -void const_propagator_ait::replace( - goto_functionst::goto_functiont &goto_function, - const namespacet &ns) -{ - Forall_goto_program_instructions(it, goto_function.body) - { - state_mapt::iterator s_it=state_map.find(it); - if(s_it==state_map.end()) - continue; - replace_types_rec(s_it->second.values.replace_const, it->code); - replace_types_rec(s_it->second.values.replace_const, it->guard); - if(it->is_goto() || it->is_assume() || it->is_assert()) - { - s_it->second.values.replace_const(it->guard); - } - else if(it->is_assign()) - { - exprt &rhs=to_code_assign(it->code).rhs(); - s_it->second.values.replace_const(rhs); - } - else if(it->is_function_call()) - { - exprt::operandst &args= - to_code_function_call(it->code).arguments(); - for(exprt::operandst::iterator o_it=args.begin(); - o_it!=args.end(); ++o_it) - s_it->second.values.replace_const(*o_it); - } - } -} - -/*******************************************************************\ - -Function: const_propagator_ait::replace_types_rec - - Inputs: - - Outputs: - - Purpose: - -\*******************************************************************/ - -void const_propagator_ait::replace_types_rec( - const replace_symbolt &replace_const, - exprt &expr) -{ - replace_const(expr.type()); - Forall_operands(it, expr) - replace_types_rec(replace_const, *it); -} - diff --git a/src/ssa/const_propagator.h b/src/ssa/const_propagator.h deleted file mode 100644 index a1e373e52..000000000 --- a/src/ssa/const_propagator.h +++ /dev/null @@ -1,101 +0,0 @@ -/*******************************************************************\ - -Module: Constant propagation - -Author: Peter Schrammel - -\*******************************************************************/ - -#ifndef CPROVER_CONST_PROPAGATOR_H -#define CPROVER_CONST_PROPAGATOR_H - -#include - -#include -#include "replace_symbol_ext.h" - -class const_propagator_domaint:public ai_domain_baset -{ -public: - virtual void transform(locationt, locationt, ai_baset &, const namespacet &); - virtual void output(std::ostream &, const ai_baset &, const namespacet &) const; - bool merge(const const_propagator_domaint &, locationt, locationt); - - struct valuest - { - public: - // maps variables to constants - replace_symbol_extt replace_const; - std::set top_ids; - - void output(std::ostream &, const namespacet &) const; - - bool merge(const valuest &src); - - inline void clear() - { - replace_const.expr_map.clear(); - replace_const.type_map.clear(); - top_ids.clear(); - } - - bool empty() const - { - return replace_const.expr_map.empty() && - replace_const.type_map.empty() && - top_ids.empty(); - } - - void set_to(const exprt &lhs, const exprt &rhs_val); - void set_to(const irep_idt &lhs_id, const exprt &rhs_val); - - bool maps_to_top(const exprt &expr) const; - bool set_to_top(const exprt &expr); - bool set_to_top(const irep_idt &id); - void set_all_to_top(); - }; - - valuest values; - -protected: - void assign( - valuest &dest, - const exprt &lhs, - exprt rhs, - const namespacet &ns) const; - - void assign_rec(const exprt &lhs, const exprt &rhs, - const namespacet &ns); - - exprt evaluate_casts_in_constants( - exprt expr, - const typet& parent_type, - bool &valid) const; - -}; - -class const_propagator_ait:public ait -{ -public: - const_propagator_ait( - goto_functionst::goto_functiont &goto_function, - const namespacet &ns) - { - operator()(goto_function, ns); -// output(ns, goto_function.body, "", std::cout); - replace(goto_function, ns); - } - -protected: - friend class const_propagator_domaint; - -void replace( - goto_functionst::goto_functiont &goto_function, - const namespacet &ns); - -void replace_types_rec( - const replace_symbolt &replace_const, - exprt &expr); -}; - -#endif diff --git a/src/ssa/local_ssa.cpp b/src/ssa/local_ssa.cpp index 84da5f932..af3727737 100644 --- a/src/ssa/local_ssa.cpp +++ b/src/ssa/local_ssa.cpp @@ -349,14 +349,15 @@ Function: local_SSAt::find_location_by_number \*******************************************************************/ -local_SSAt::locationt local_SSAt::find_location_by_number(unsigned location_number) const +local_SSAt::locationt local_SSAt::find_location_by_number( + unsigned location_number) const { - local_SSAt::nodest::const_iterator n_it=nodes.begin(); - for(; n_it!=nodes.end(); n_it++) + for(const auto &node : nodes) { - if(n_it->location->location_number==location_number) break; + if(node.location->location_number==location_number) + return node.location; } - return n_it->location; + assert(false); } /*******************************************************************\ @@ -629,15 +630,15 @@ void local_SSAt::build_function_call(locationt loc) { symbol_exprt arg( id2string(fname)+"#"+i2string(loc->location_number)+ - "#arg"+i2string(i), it->type()); + "#arg"+i2string(i), it->type()); const typet &argtype=ns.follow(it->type()); if(argtype.id()==ID_struct) { - exprt lhs=read_rhs(arg, loc); - for(size_t j=0; jequalities.push_back( - equal_exprt(lhs.operands()[j], it->operands()[j])); + n_it->equalities.push_back( + equal_exprt(lhs.operands()[j], it->operands()[j])); } } else @@ -1492,7 +1493,7 @@ void local_SSAt::assign_rec( assign_rec(new_lhs, new_rhs, guard, loc); } else - throw "UNKNOWN LHS: "+lhs.id_string(); + throw "UNKNOWN LHS: "+lhs.id_string(); // NOLINT(readability/throw) } /*******************************************************************\ diff --git a/src/ssa/replace_symbol_ext.cpp b/src/ssa/replace_symbol_ext.cpp deleted file mode 100644 index d978d2f99..000000000 --- a/src/ssa/replace_symbol_ext.cpp +++ /dev/null @@ -1,82 +0,0 @@ -/*******************************************************************\ - -Module: Modified expression replacement for constant propagator - -Author: Peter Schrammel - -\*******************************************************************/ - -#include -#include - -#include "replace_symbol_ext.h" - -/*******************************************************************\ - -Function: replace_symbol_extt::replace - - Inputs: - - Outputs: - - Purpose: does not replace object in address_of expressions - -\*******************************************************************/ - -bool replace_symbol_extt::replace(exprt &dest) const -{ - bool result=true; - - // first look at type - - if(have_to_replace(dest.type())) - if(!replace_symbolt::replace(dest.type())) - result=false; - - // now do expression itself - - if(!have_to_replace(dest)) - return result; - - if(dest.id()==ID_address_of) - { - const exprt &object=to_address_of_expr(dest).object(); - if(object.id()==ID_symbol) - { - expr_mapt::const_iterator it= - expr_map.find(object.get(ID_identifier)); - - if(it!=expr_map.end()) - return false; - } - } - else if(dest.id()==ID_symbol) - { - expr_mapt::const_iterator it= - expr_map.find(dest.get(ID_identifier)); - - if(it!=expr_map.end()) - { - dest=it->second; - return false; - } - } - - Forall_operands(it, dest) - if(!replace(*it)) - result=false; - - const irept &c_sizeof_type=dest.find(ID_C_c_sizeof_type); - - if(c_sizeof_type.is_not_nil() && - !replace_symbolt::replace(static_cast(dest.add(ID_C_c_sizeof_type)))) - result=false; - - const irept &va_arg_type=dest.find(ID_C_va_arg_type); - - if(va_arg_type.is_not_nil() && - !replace_symbolt::replace(static_cast(dest.add(ID_C_va_arg_type)))) - result=false; - - return result; -} diff --git a/src/ssa/replace_symbol_ext.h b/src/ssa/replace_symbol_ext.h deleted file mode 100644 index 2aac30957..000000000 --- a/src/ssa/replace_symbol_ext.h +++ /dev/null @@ -1,20 +0,0 @@ -/*******************************************************************\ - -Module: Modified expression replacement for constant propagator - -Author: Peter Schrammel - -\*******************************************************************/ - -#ifndef CPROVER_REPLACE_SYMBOL_EXT_H -#define CPROVER_REPLACE_SYMBOL_EXT_H - -#include - -class replace_symbol_extt : public replace_symbolt -{ -public: - virtual bool replace(exprt &dest) const; -}; - -#endif diff --git a/src/ssa/ssa_const_propagator.cpp b/src/ssa/ssa_const_propagator.cpp index 1c16c1da3..ab5c9fd68 100644 --- a/src/ssa/ssa_const_propagator.cpp +++ b/src/ssa/ssa_const_propagator.cpp @@ -2,7 +2,7 @@ Module: SSA Constant Propagator -Author: Kumar Madhukar, Peter Schrammel +Author: Kumar Madhukar \*******************************************************************/ @@ -19,10 +19,6 @@ Author: Kumar Madhukar, Peter Schrammel #include "ssa_const_propagator.h" - -// bool iterate=true; - - /*******************************************************************\ Function: ssa_const_propagatort::operator() @@ -35,123 +31,130 @@ Function: ssa_const_propagatort::operator() \*******************************************************************/ -void ssa_const_propagatort::operator()(std::list &dest, - const local_SSAt &src) +void ssa_const_propagatort::operator()( + std::list &dest, const local_SSAt &src) { values.iterate=true; - while(values.iterate){ + while(values.iterate) + { values.iterate=false; for(local_SSAt::nodest::const_iterator n_it=src.nodes.begin(); - n_it!=src.nodes.end(); n_it++) - { - const local_SSAt::nodet &node=*n_it; - - // check if node is active; 'continue' if not active - if(!node.enabling_expr.is_true()) - continue; + n_it!=src.nodes.end(); n_it++) + { + const local_SSAt::nodet &node=*n_it; - // if src.enabling_exprs does not have a true in the end, then also continue - if(src.enabling_exprs.size() > 0) - if((src.enabling_exprs.back()).is_true()) - continue; + // check if node is active; 'continue' if not active + if(!node.enabling_expr.is_true()) + continue; - for(local_SSAt::nodet::equalitiest::const_iterator e_it=node.equalities.begin(); - e_it!=node.equalities.end(); e_it++) - { - equal_exprt e=to_equal_expr(*e_it); - const exprt &lhs=e.lhs(); - exprt &temprhs=e.rhs(); + // if src.enabling_exprs does not have a true in the end, + // then also continue + if(src.enabling_exprs.size()>0) + if((src.enabling_exprs.back()).is_true()) + continue; - // resolving conditional expressions - while(temprhs.id()==ID_if){ - exprt simp_guard; + for(local_SSAt::nodet::equalitiest::const_iterator e_it= + node.equalities.begin(); + e_it!=node.equalities.end(); e_it++) + { + equal_exprt e=to_equal_expr(*e_it); + const exprt &lhs=e.lhs(); + exprt &temprhs=e.rhs(); + + // resolving conditional expressions + while(temprhs.id()==ID_if) + { + exprt simp_guard; #ifdef DEBUG - std::cout << "guard: " << from_expr(src.ns, "", temprhs.op0()) << std::endl; + std::cout << "guard: " << from_expr(src.ns, "", temprhs.op0()) + << std::endl; #endif - simp_guard=simplify_expr(temprhs.op0(), src.ns); + simp_guard=simplify_expr(temprhs.op0(), src.ns); #ifdef DEBUG - std::cout << "simplified: " << from_expr(src.ns, "", simp_guard) << std::endl; + std::cout << "simplified: " << from_expr(src.ns, "", simp_guard) + << std::endl; #endif - if(simp_guard.is_true()) - temprhs=temprhs.op1(); - else if(simp_guard.is_false()) - temprhs=temprhs.op2(); + if(simp_guard.is_true()) + temprhs=temprhs.op1(); + else if(simp_guard.is_false()) + temprhs=temprhs.op2(); + else + break; + } + + const exprt &rhs=temprhs; + valuest copy_values=values; + + if(!copy_values.maps_to_top(rhs)) + assign(copy_values, lhs, rhs, src.ns); else - break; - } - - const exprt &rhs=temprhs; - valuest copy_values=values; - - if(!copy_values.maps_to_top(rhs)) - assign(copy_values, lhs, rhs, src.ns); - else - copy_values.set_to_top(lhs); + copy_values.set_to_top(lhs); #ifdef DEBUG - copy_values.output(std::cout, src.ns); + copy_values.output(std::cout, src.ns); #endif - if(rhs.id()==ID_symbol){ - if(!values.maps_to_top(lhs)) - assign(values, rhs, lhs, src.ns); - else - values.set_to_top(rhs); - } + if(rhs.id()==ID_symbol) + { + if(!values.maps_to_top(lhs)) + assign(values, rhs, lhs, src.ns); + else + values.set_to_top(rhs); + } #ifdef DEBUG - values.output(std::cout, src.ns); + values.output(std::cout, src.ns); #endif - values.merge(copy_values); + values.merge(copy_values); #ifdef DEBUG - values.output(std::cout, src.ns); + values.output(std::cout, src.ns); #endif - } + } - for(local_SSAt::nodet::constraintst::const_iterator c_it=n_it->constraints.begin(); - c_it!=n_it->constraints.end(); c_it++) - { - if(c_it->id()!=ID_equal) - continue; + for(local_SSAt::nodet::constraintst::const_iterator c_it= + n_it->constraints.begin(); + c_it!=n_it->constraints.end(); c_it++) + { + if(c_it->id()!=ID_equal) + continue; - const equal_exprt e=to_equal_expr(*c_it); - const exprt &lhs=e.lhs(); - const exprt &rhs=e.rhs(); + const equal_exprt e=to_equal_expr(*c_it); + const exprt &lhs=e.lhs(); + const exprt &rhs=e.rhs(); - // if lhs is a variable and rhs is a constant expression + // if lhs is a variable and rhs is a constant expression - valuest copy_values=values; + valuest copy_values=values; - if(!copy_values.maps_to_top(rhs)) - assign(copy_values, lhs, rhs, src.ns); - else - copy_values.set_to_top(lhs); + if(!copy_values.maps_to_top(rhs)) + assign(copy_values, lhs, rhs, src.ns); + else + copy_values.set_to_top(lhs); #ifdef DEBUG - copy_values.output(std::cout, src.ns); + copy_values.output(std::cout, src.ns); #endif - // if rhs is a variable and lhs is a constant expression + // if rhs is a variable and lhs is a constant expression - if(!values.maps_to_top(lhs)) - assign(values, rhs, lhs, src.ns); - else - values.set_to_top(rhs); + if(!values.maps_to_top(lhs)) + assign(values, rhs, lhs, src.ns); + else + values.set_to_top(rhs); #ifdef DEBUG - values.output(std::cout, src.ns); + values.output(std::cout, src.ns); #endif - values.merge(copy_values); + values.merge(copy_values); #ifdef DEBUG - values.output(std::cout, src.ns); + values.output(std::cout, src.ns); #endif - - } } + } } #ifdef DEBUG @@ -162,13 +165,11 @@ void ssa_const_propagatort::operator()(std::list &dest, for(replace_symbolt::expr_mapt::const_iterator it=values.replace_const.expr_map.begin(); it!=values.replace_const.expr_map.end(); - ++it){ - - // std::cout << ' ' << it->first << "=" << - // from_expr(src.ns, "", it->second) << std::endl; - - dest.push_back(equal_exprt(symbol_exprt(it->first, it->second.type()), it->second)); - + ++it) + { + dest.push_back( + equal_exprt( + symbol_exprt(it->first, it->second.type()), it->second)); } } @@ -178,20 +179,19 @@ bool ssa_const_propagatort::valuest::maps_to_top(const exprt &expr) const find_symbols(expr, symbols); for(find_symbols_sett::const_iterator it=symbols.begin(); it!=symbols.end(); ++it) - { - if(replace_const.expr_map.find(*it) -==replace_const.expr_map.end()) - return true; - } + { + if(replace_const.expr_map.find(*it)== + replace_const.expr_map.end()) + return true; + } return false; } - void ssa_const_propagatort::assign( - valuest &dest, - const exprt &lhs, - exprt rhs, - const namespacet &ns) const + valuest &dest, + const exprt &lhs, + exprt rhs, + const namespacet &ns) const { #ifdef DEBUG std::cout << "assign: " << from_expr(ns, "", lhs) @@ -221,15 +221,15 @@ bool ssa_const_propagatort::valuest::set_to_top(const irep_idt &id) replace_symbolt::expr_mapt::iterator r_it= replace_const.expr_map.find(id); if(r_it!=replace_const.expr_map.end()) - { - replace_const.expr_map.erase(r_it); - result=true; - } + { + replace_const.expr_map.erase(r_it); + result=true; + } if(top_ids.find(id)==top_ids.end()) - { - top_ids.insert(id); - result=true; - } + { + top_ids.insert(id); + result=true; + } return result; } @@ -238,36 +238,39 @@ bool ssa_const_propagatort::valuest::set_to_top(const exprt &expr) return set_to_top(to_symbol_expr(expr).get_identifier()); } -void ssa_const_propagatort::valuest::set_to(const irep_idt &lhs_id, - const exprt &rhs_val) +void ssa_const_propagatort::valuest::set_to( + const irep_idt &lhs_id, + const exprt &rhs_val) { - - if(replace_const.expr_map[lhs_id]!=rhs_val){ + if(replace_const.expr_map[lhs_id]!=rhs_val) + { replace_const.expr_map[lhs_id]=rhs_val; iterate=true; } std::set::iterator it=top_ids.find(lhs_id); - if(it!=top_ids.end()) top_ids.erase(it); + if(it!=top_ids.end()) + top_ids.erase(it); } -void ssa_const_propagatort::valuest::set_to(const exprt &lhs, - const exprt &rhs_val) +void ssa_const_propagatort::valuest::set_to( + const exprt &lhs, + const exprt &rhs_val) { const irep_idt &lhs_id=to_symbol_expr(lhs).get_identifier(); set_to(lhs_id, rhs_val); } void ssa_const_propagatort::valuest::output( - std::ostream &out, - const namespacet &ns) const + std::ostream &out, + const namespacet &ns) const { out << "const map: " << std::endl; for(replace_symbolt::expr_mapt::const_iterator it=replace_const.expr_map.begin(); it!=replace_const.expr_map.end(); ++it) - out << ' ' << it->first << "=" << - from_expr(ns, "", it->second) << std::endl; + out << ' ' << it->first << "=" + << from_expr(ns, "", it->second) << std::endl; out << "top ids: " << std::endl; for(std::set::const_iterator it=top_ids.begin(); @@ -282,24 +285,23 @@ bool ssa_const_propagatort::valuest::merge(const valuest &src) for(replace_symbolt::expr_mapt::const_iterator it=src.replace_const.expr_map.begin(); it!=src.replace_const.expr_map.end(); ++it) - { - replace_symbolt::expr_mapt::iterator - c_it=replace_const.expr_map.find(it->first); - if(c_it!=replace_const.expr_map.end()) { - if(c_it->second!=it->second) + replace_symbolt::expr_mapt::iterator + c_it=replace_const.expr_map.find(it->first); + if(c_it!=replace_const.expr_map.end()) + { + if(c_it->second!=it->second) { set_to_top(it->first); changed=true; } - } - else if(top_ids.find(it->first)==top_ids.end()) - { - set_to(it->first, it->second); - changed=true; - } } + else if(top_ids.find(it->first)==top_ids.end()) + { + set_to(it->first, it->second); + changed=true; + } + } return changed; } - diff --git a/src/ssa/ssa_const_propagator.h b/src/ssa/ssa_const_propagator.h index 5620ce57b..c8db8df51 100644 --- a/src/ssa/ssa_const_propagator.h +++ b/src/ssa/ssa_const_propagator.h @@ -2,24 +2,24 @@ Module: SSA Constant Propagator -Author: Kumar Madhukar, Peter Schrammel +Author: Kumar Madhukar \*******************************************************************/ -#ifndef CPROVER_SSA_CONST_PROPAGATOR_H -#define CPROVER_SSA_CONST_PROPAGATOR_H +#ifndef CPROVER_2LS_SSA_SSA_CONST_PROPAGATOR_H +#define CPROVER_2LS_SSA_SSA_CONST_PROPAGATOR_H #include #include #include "local_ssa.h" -class ssa_const_propagatort : public messaget +class ssa_const_propagatort:public messaget { - public: - - void operator()(std::list &dest, - const local_SSAt &src); +public: + void operator()( + std::list &dest, + const local_SSAt &src); struct valuest { @@ -33,7 +33,7 @@ class ssa_const_propagatort : public messaget bool merge(const valuest &src); - inline void clear() + void clear() { replace_const.expr_map.clear(); replace_const.type_map.clear(); @@ -55,26 +55,21 @@ class ssa_const_propagatort : public messaget bool set_to_top(const irep_idt &id); bool iterate; - }; valuest values; - protected: - +protected: void assign( - valuest &dest, - const exprt &lhs, - exprt rhs, - const namespacet &ns) const; + valuest &dest, + const exprt &lhs, + exprt rhs, + const namespacet &ns) const; exprt evaluate_casts_in_constants( - exprt expr, - const typet& parent_type, - bool &valid) const; - - - + exprt expr, + const typet& parent_type, + bool &valid) const; }; -#endif +#endif // CPROVER_2LS_SSA_SSA_CONST_PROPAGATOR_H diff --git a/src/ssa/ssa_db.cpp b/src/ssa/ssa_db.cpp index 3eae31ea4..cfb570f0e 100644 --- a/src/ssa/ssa_db.cpp +++ b/src/ssa/ssa_db.cpp @@ -8,8 +8,11 @@ Author: Peter Schrammel #include "ssa_db.h" -// void ssa_dbt::depgraph_create(const function_namet &function_name, const namespacet &ns, ssa_inlinert &ssa_inliner) -void ssa_dbt::depgraph_create(const function_namet &function_name, const namespacet &ns, ssa_inlinert &ssa_inliner, bool entry) +void ssa_dbt::depgraph_create( + const function_namet &function_name, + const namespacet &ns, + ssa_inlinert &ssa_inliner, + bool entry) { depgraph_store[function_name]=new ssa_dependency_grapht(*this, ns); const local_SSAt &SSA=this->get(function_name); diff --git a/src/ssa/ssa_dependency_graph.cpp b/src/ssa/ssa_dependency_graph.cpp index f419fbac7..e7490c685 100644 --- a/src/ssa/ssa_dependency_graph.cpp +++ b/src/ssa/ssa_dependency_graph.cpp @@ -18,42 +18,56 @@ void ssa_dependency_grapht::output(std::ostream &out) const { for(unsigned index=0; index Used Symbols: "; - for(find_symbols_sett::const_iterator u_it=depnodes_map[index].used_symbols.begin(); - u_it!=depnodes_map[index].used_symbols.end(); u_it++){ + for(find_symbols_sett::const_iterator u_it= + depnodes_map[index].used_symbols.begin(); + u_it!=depnodes_map[index].used_symbols.end(); u_it++) + { out << *u_it << " "; } out << "\n"; out << "Node#" << index << "; -> Modified Symbols: "; - for(find_symbols_sett::const_iterator m_it=depnodes_map[index].modified_symbols.begin(); - m_it!=depnodes_map[index].modified_symbols.end(); m_it++){ + for(find_symbols_sett::const_iterator m_it= + depnodes_map[index].modified_symbols.begin(); + m_it!=depnodes_map[index].modified_symbols.end(); m_it++) + { out << *m_it << " "; } out << "\n"; out << "Successors: "; - for(unsigned i=0; ilocation; // loop-head select - // TODO: this is an ugly hack (this can be changed as soon as unwindable_local_SSA provides smooth renaming with odometers) - // if(n_it->loophead!=SSA.nodes.end()) + // TODO: this is an ugly hack (this can be changed + // as soon as unwindable_local_SSA provides + // smooth renaming with odometers) if(e_it->op1().id()==ID_if && e_it->op1().op0().id()==ID_symbol) { @@ -132,13 +149,9 @@ void ssa_dependency_grapht::create(const local_SSAt &SSA, ssa_inlinert &ssa_inli if(((var_string.substr(0, 14))=="ssa::$guard#ls")) { temp_node.is_loop=true; -/* symbol_exprt lsguard=SSA.name(SSA.guard_symbol(), - local_SSAt::LOOP_SELECT, n_it->location); - ssa_local_unwinder.unwinder_rename(lsguard, *n_it, true);*/ temp_node.guard=not_exprt(e_it->op1().op0()); } } - // temp_node.trivial_guard=true; equal_exprt e=to_equal_expr(*e_it); exprt &lhs=e.lhs(); exprt &rhs=e.rhs(); @@ -146,30 +159,33 @@ void ssa_dependency_grapht::create(const local_SSAt &SSA, ssa_inlinert &ssa_inli find_symbols(rhs, temp_node.used_symbols); find_symbols(lhs, temp_node.modified_symbols); - if(!ignore_equality_done){ + if(!ignore_equality_done) + { std::string var_string=id2string(to_symbol_expr(lhs).get_identifier()); - if(((var_string.substr(0, 11))=="ssa::$guard") && (rhs.is_true())){ + if(((var_string.substr(0, 11))=="ssa::$guard") && (rhs.is_true())) + { ignore_equality=true; ignore_equality_done=true; } } - if(first_node && ignore_equality){ - if(entry){ + if(first_node && ignore_equality) + { + if(entry) + { depnodes_map.push_back(temp_node); - // std::cout << "created equality node, with info: " << from_expr(ns, "", *e_it) << "\n"; } ignore_equality=false; } - else{ + else + { depnodes_map.push_back(temp_node); - // std::cout << "created equality node, with info: " << from_expr(ns, "", *e_it) << "\n"; } - } // collecting symbols from constraints and populating dependency graph nodes - for(local_SSAt::nodet::constraintst::const_iterator c_it=node.constraints.begin(); + for(local_SSAt::nodet::constraintst::const_iterator c_it= + node.constraints.begin(); c_it!=node.constraints.end(); c_it++) { find_symbols(*c_it, all_ssa_symbols); @@ -183,11 +199,11 @@ void ssa_dependency_grapht::create(const local_SSAt &SSA, ssa_inlinert &ssa_inli find_symbols(*c_it, temp_node.used_symbols); find_symbols(*c_it, temp_node.modified_symbols); depnodes_map.push_back(temp_node); - // std::cout << "created constraint node, with info: " << from_expr(ns, "", *c_it) << "\n"; } // collecting symbols from assertionst and populating dependency graph nodes - for(local_SSAt::nodet::assertionst::const_iterator a_it=node.assertions.begin(); + for(local_SSAt::nodet::assertionst::const_iterator a_it= + node.assertions.begin(); a_it!=node.assertions.end(); a_it++) { find_symbols(*a_it, all_ssa_symbols); @@ -200,33 +216,33 @@ void ssa_dependency_grapht::create(const local_SSAt &SSA, ssa_inlinert &ssa_inli temp_node.location=n_it->location; find_symbols(*a_it, temp_node.used_symbols); depnodes_map.push_back(temp_node); - // std::cout << "created assertion node, with info: " << from_expr(ns, "", *a_it) << "\n"; } - /* - // collecting symbols from assumptionst and populating dependency graph nodes - for(local_SSAt::nodet::assumptionst::const_iterator a_it=node.assumptions.begin(); - a_it!=node.assumptions.end(); a_it++) +#if 0 + // collecting symbols from assumptionst + // and populating dependency graph nodes + for(local_SSAt::nodet::assumptionst::const_iterator a_it= + node.assumptions.begin(); + a_it!=node.assumptions.end(); a_it++) { - find_symbols(*a_it, all_ssa_symbols); - - depnodet temp_node; - temp_node.is_assertion=false; - temp_node.is_function_call=false; - temp_node.node_info=*a_it; - find_symbols(*a_it, temp_node.used_symbols); - find_symbols(*a_it, temp_node.modified_symbols); - depnodes_map.push_back(temp_node); - // std::cout << "created assumption node, with info: " << from_expr(ns, "", *a_it) << "\n"; + find_symbols(*a_it, all_ssa_symbols); + + depnodet temp_node; + temp_node.is_assertion=false; + temp_node.is_function_call=false; + temp_node.node_info=*a_it; + find_symbols(*a_it, temp_node.used_symbols); + find_symbols(*a_it, temp_node.modified_symbols); + depnodes_map.push_back(temp_node); } - */ +#endif - // collecting symbols from function_callst and populating dependency graph nodes - for(local_SSAt::nodet::function_callst::const_iterator f_it=node.function_calls.begin(); + // collecting symbols from function_callst + // and populating dependency graph nodes + for(local_SSAt::nodet::function_callst::const_iterator f_it= + node.function_calls.begin(); f_it!=node.function_calls.end(); f_it++) { - // find_symbols(*f_it, all_ssa_symbols); - irep_idt fname=to_symbol_expr(f_it->function()).get_identifier(); if(ssa_db.exists(fname)) { @@ -239,11 +255,10 @@ void ssa_dependency_grapht::create(const local_SSAt &SSA, ssa_inlinert &ssa_inli exprt::operandst bindings_in, bindings_out; int counter=ssa_inliner.get_rename_counter(); - /**/ ssa_inliner.get_guard_binding(SSA, fSSA, n_it, guard_binding, counter); - // std::cout << "guard binding: " << from_expr(ns, "", guard_binding) << "\n"; - /* - { + +#if 0 + { depnodet temp_node; temp_node.is_assertion=false; temp_node.is_function_call=false; @@ -255,18 +270,15 @@ void ssa_dependency_grapht::create(const local_SSAt &SSA, ssa_inlinert &ssa_inli find_symbols(rhs, temp_node.used_symbols); find_symbols(lhs, temp_node.modified_symbols); depnodes_map.push_back(temp_node); - // std::cout << "created guard binding node, with info: " << from_expr(ns, "", guard_binding) << "\n"; - } - */ - /**/ + } +#endif - ssa_inliner.get_bindings(SSA, fSSA, n_it, f_it, bindings_in, bindings_out, counter); + ssa_inliner.get_bindings( + SSA, fSSA, n_it, f_it, bindings_in, bindings_out, counter); for(exprt::operandst::const_iterator b_it=bindings_in.begin(); - b_it!=bindings_in.end(); b_it++){ - - // std::cout << "binding: " << from_expr(ns, "", *b_it) << "\n"; - + b_it!=bindings_in.end(); b_it++) + { depnodet temp_node; temp_node.is_assertion=false; temp_node.is_function_call=false; @@ -280,14 +292,11 @@ void ssa_dependency_grapht::create(const local_SSAt &SSA, ssa_inlinert &ssa_inli find_symbols(rhs, temp_node.used_symbols); find_symbols(lhs, temp_node.modified_symbols); depnodes_map.push_back(temp_node); - // std::cout << "created binding in node, with info: " << from_expr(ns, "", *b_it) << "\n"; } for(exprt::operandst::const_iterator b_it=bindings_out.begin(); - b_it!=bindings_out.end(); b_it++){ - - // std::cout << "binding: " << from_expr(ns, "", *b_it) << "\n"; - + b_it!=bindings_out.end(); b_it++) + { depnodet temp_node; temp_node.is_assertion=false; temp_node.is_function_call=false; @@ -301,7 +310,6 @@ void ssa_dependency_grapht::create(const local_SSAt &SSA, ssa_inlinert &ssa_inli find_symbols(rhs, temp_node.used_symbols); find_symbols(lhs, temp_node.modified_symbols); depnodes_map.push_back(temp_node); - // std::cout << "created binding out node, with info: " << from_expr(ns, "", *b_it) << "\n"; } /******************************************************************/ @@ -318,7 +326,8 @@ void ssa_dependency_grapht::create(const local_SSAt &SSA, ssa_inlinert &ssa_inli find_symbols(guard_binding, temp_node.used_symbols); for(local_SSAt::var_listt::const_iterator p_it=fSSA.params.begin(); - p_it!=fSSA.params.end(); p_it++){ + p_it!=fSSA.params.end(); p_it++) + { irep_idt id=(*p_it).get(ID_identifier); ssa_inliner.rename(id, counter); all_ssa_symbols.insert(id); @@ -326,7 +335,8 @@ void ssa_dependency_grapht::create(const local_SSAt &SSA, ssa_inlinert &ssa_inli } for(local_SSAt::var_sett::const_iterator g_it=fSSA.globals_in.begin(); - g_it!=fSSA.globals_in.end(); g_it++){ + g_it!=fSSA.globals_in.end(); g_it++) + { irep_idt id=(*g_it).get(ID_identifier); ssa_inliner.rename(id, counter); all_ssa_symbols.insert(id); @@ -334,7 +344,8 @@ void ssa_dependency_grapht::create(const local_SSAt &SSA, ssa_inlinert &ssa_inli } for(local_SSAt::var_sett::const_iterator g_it=fSSA.globals_out.begin(); - g_it!=fSSA.globals_out.end(); g_it++){ + g_it!=fSSA.globals_out.end(); g_it++) + { irep_idt id=(*g_it).get(ID_identifier); ssa_inliner.rename(id, counter); all_ssa_symbols.insert(id); @@ -342,7 +353,6 @@ void ssa_dependency_grapht::create(const local_SSAt &SSA, ssa_inlinert &ssa_inli } depnodes_map.push_back(temp_node); - // std::cout << "created function node, with info: " << from_expr(ns, "", *f_it) << "\n"; } } } @@ -356,32 +366,38 @@ void ssa_dependency_grapht::create(const local_SSAt &SSA, ssa_inlinert &ssa_inli // params and globals_in are the modified_symbols at source_node for(local_SSAt::var_listt::const_iterator p_it=SSA.params.begin(); - p_it!=SSA.params.end(); p_it++){ + p_it!=SSA.params.end(); p_it++) + { irep_idt id=(*p_it).get(ID_identifier); source_node.modified_symbols.insert(id); } for(local_SSAt::var_sett::const_iterator g_it=SSA.globals_in.begin(); - g_it!=SSA.globals_in.end(); g_it++){ + g_it!=SSA.globals_in.end(); g_it++) + { irep_idt id=(*g_it).get(ID_identifier); source_node.modified_symbols.insert(id); } depnodes_map.push_back(source_node); // source_node - // std::cout << "created source node, without any info" << "\n"; top_node_index=depnodes_map.size()-1; for(find_symbols_sett::const_iterator - s_it=all_ssa_symbols.begin(); s_it!=all_ssa_symbols.end(); s_it++){ - - for(unsigned m_index=0; m_index annotated_predecessorst; - struct depnodet{ + struct depnodet + { exprt node_info; exprt guard; // guard binding or loop-head select bool is_assertion; @@ -66,4 +68,4 @@ ssa_dependency_grapht(ssa_dbt &_db, const namespacet &_ns): const namespacet &ns; }; -#endif +#endif // CPROVER_2LS_SSA_SSA_DEPENDENCY_GRAPH_H diff --git a/src/ssa/ssa_inliner.cpp b/src/ssa/ssa_inliner.cpp index 7574220da..9949eb0dc 100644 --- a/src/ssa/ssa_inliner.cpp +++ b/src/ssa/ssa_inliner.cpp @@ -84,11 +84,17 @@ void ssa_inlinert::get_bindings( get_replace_params(SSA, fSSA.params, n_it, *f_it, bindings_in, counter); // equalities for globals_in - get_replace_globals_in(fSSA.globals_in, *f_it, cs_globals_in, bindings_in, counter); + get_replace_globals_in( + fSSA.globals_in, *f_it, cs_globals_in, bindings_in, counter); // equalities for globals out (including unmodified globals) - get_replace_globals_out(fSSA.globals_out, *f_it, cs_globals_in, cs_globals_out, bindings_out, counter); - + get_replace_globals_out( + fSSA.globals_out, + *f_it, + cs_globals_in, + cs_globals_out, + bindings_out, + counter); } /*******************************************************************\ @@ -119,10 +125,15 @@ bool ssa_inlinert::get_inlined( irep_idt fname=to_symbol_expr(f_it->function()).get_identifier(); const local_SSAt &fSSA=ssa_db.get(fname); - bool assertion_flag=get_summaries(fSSA, + bool assertion_flag=get_summaries( + fSSA, summaryt::call_sitet(fSSA.goto_function.body.instructions.end()), - forward, assert_summaries, noassert_summaries, - bindings, assertion_map, error_summ); + forward, + assert_summaries, + noassert_summaries, + bindings, + assertion_map, + error_summ); // bindings exprt guard_binding; @@ -226,24 +237,25 @@ bool ssa_inlinert::get_summary( get_replace_params(SSA, summary.params, n_it, *f_it, bindings, counter); // equalities for globals_in - get_replace_globals_in(summary.globals_in, *f_it, cs_globals_in, bindings, counter); + get_replace_globals_in( + summary.globals_in, *f_it, cs_globals_in, bindings, counter); // constraints for transformer exprt transformer; if(error_summ) - { - // update transformer using the error_summaries map - summaryt::call_sitet call_site(loc); - summaryt::error_summariest::const_iterator e_it= - summary.error_summaries.find(call_site); - if(e_it!=summary.error_summaries.end() && - !e_it->second.is_nil()) - transformer=e_it->second; - else - transformer=true_exprt(); - } + { + // update transformer using the error_summaries map + summaryt::call_sitet call_site(loc); + summaryt::error_summariest::const_iterator e_it= + summary.error_summaries.find(call_site); + if(e_it!=summary.error_summaries.end() && + !e_it->second.is_nil()) + transformer=e_it->second; + else + transformer=true_exprt(); + } else { if(forward) @@ -257,17 +269,23 @@ bool ssa_inlinert::get_summary( rename(transformer, counter); if(summary.has_assertion) { - assert_summaries.push_back(implies_exprt(SSA.guard_symbol(n_it->location), - transformer)); + assert_summaries.push_back( + implies_exprt(SSA.guard_symbol(n_it->location), transformer)); } else { - noassert_summaries.push_back(implies_exprt(SSA.guard_symbol(n_it->location), - transformer)); + noassert_summaries.push_back( + implies_exprt(SSA.guard_symbol(n_it->location), transformer)); } // equalities for globals out (including unmodified globals) - get_replace_globals_out(summary.globals_out, *f_it, cs_globals_in, cs_globals_out, bindings, counter); + get_replace_globals_out( + summary.globals_out, + *f_it, + cs_globals_in, + cs_globals_out, + bindings, + counter); return summary.has_assertion; } @@ -291,7 +309,8 @@ exprt ssa_inlinert::get_summaries(const local_SSAt &SSA) return and_exprt(conjunction(bindings), conjunction(summaries)); } -exprt ssa_inlinert::get_summaries(const local_SSAt &SSA, +exprt ssa_inlinert::get_summaries( + const local_SSAt &SSA, assertion_mapt &assertion_map) { exprt::operandst summaries, bindings; @@ -306,20 +325,23 @@ void ssa_inlinert::get_summaries( exprt::operandst &bindings) { assertion_mapt assertion_map; - get_summaries(SSA, - summaryt::call_sitet(SSA.goto_function.body.instructions.end()), - forward, summaries, summaries, bindings, assertion_map); + get_summaries( + SSA, + summaryt::call_sitet(SSA.goto_function.body.instructions.end()), + forward, summaries, summaries, bindings, assertion_map); } -void ssa_inlinert::get_summaries(const local_SSAt &SSA, - bool forward, - exprt::operandst &summaries, - exprt::operandst &bindings, - assertion_mapt &assertion_map) +void ssa_inlinert::get_summaries( + const local_SSAt &SSA, + bool forward, + exprt::operandst &summaries, + exprt::operandst &bindings, + assertion_mapt &assertion_map) { - get_summaries(SSA, - summaryt::call_sitet(SSA.goto_function.body.instructions.end()), - forward, summaries, summaries, bindings, assertion_map); + get_summaries( + SSA, + summaryt::call_sitet(SSA.goto_function.body.instructions.end()), + forward, summaries, summaries, bindings, assertion_map); } /*******************************************************************\ @@ -344,19 +366,21 @@ bool ssa_inlinert::get_summaries( bool error_summ) { assertion_mapt assertion_map; - return get_summaries(SSA, - summaryt::call_sitet(SSA.goto_function.body.instructions.end()), - forward, assert_summaries, noassert_summaries, bindings, assertion_map); + return get_summaries( + SSA, + summaryt::call_sitet(SSA.goto_function.body.instructions.end()), + forward, assert_summaries, noassert_summaries, bindings, assertion_map); } -bool ssa_inlinert::get_summaries(const local_SSAt &SSA, - const summaryt::call_sitet ¤t_call_site, - bool forward, - exprt::operandst &assert_summaries, - exprt::operandst &noassert_summaries, - exprt::operandst &bindings, - assertion_mapt &assertion_map, - bool error_summ) +bool ssa_inlinert::get_summaries( + const local_SSAt &SSA, + const summaryt::call_sitet ¤t_call_site, + bool forward, + exprt::operandst &assert_summaries, + exprt::operandst &noassert_summaries, + exprt::operandst &bindings, + assertion_mapt &assertion_map, + bool error_summ) { bool assertion_flag=false; for(local_SSAt::nodest::const_iterator n_it=SSA.nodes.begin(); @@ -385,9 +409,10 @@ bool ssa_inlinert::get_summaries(const local_SSAt &SSA, { counter++; bool new_assertion_flag= - get_inlined(SSA, n_it, f_it, - forward, assert_summaries, noassert_summaries, - bindings, assertion_map, counter, error_summ); + get_inlined( + SSA, n_it, f_it, + forward, assert_summaries, noassert_summaries, + bindings, assertion_map, counter, error_summ); assertion_flag=assertion_flag || new_assertion_flag; } // get summary @@ -395,9 +420,10 @@ bool ssa_inlinert::get_summaries(const local_SSAt &SSA, { counter++; bool new_assertion_flag= - get_summary(SSA, n_it, f_it, - forward, assert_summaries, noassert_summaries, - bindings, counter, error_summ); + get_summary( + SSA, n_it, f_it, + forward, assert_summaries, noassert_summaries, + bindings, counter, error_summ); assertion_flag=assertion_flag || new_assertion_flag; } } @@ -514,7 +540,10 @@ void ssa_inlinert::replace( } // replace - replace(SSA.nodes, n_it, f_it, cs_globals_in, cs_globals_out, fSSA, counter); + replace( + SSA.nodes, n_it, f_it, + cs_globals_in, cs_globals_out, + fSSA, counter); } else // just add to nodes { @@ -528,7 +557,8 @@ void ssa_inlinert::replace( } } } - else debug() << "No body available for function " << fname << eom; + else + debug() << "No body available for function " << fname << eom; commit_node(n_it); } commit_nodes(SSA.nodes, n_it); @@ -574,15 +604,17 @@ void ssa_inlinert::replace( { rename(precondition, counter); node->constraints.push_back( - implies_exprt(SSA.guard_symbol(node->location), - precondition)); + implies_exprt( + SSA.guard_symbol(node->location), + precondition)); } else { rename(precondition, counter); node->assertions.push_back( - implies_exprt(SSA.guard_symbol(node->location), - precondition)); + implies_exprt( + SSA.guard_symbol(node->location), + precondition)); } exprt transformer; if(forward) @@ -626,7 +658,6 @@ void ssa_inlinert::replace( const local_SSAt &function, int counter) { - // equalities for arguments replace_params(function.params, *f_it, counter); @@ -695,9 +726,10 @@ void ssa_inlinert::get_replace_globals_in( // return conjunction(c); } -void ssa_inlinert::replace_globals_in(const local_SSAt::var_sett &globals_in, - const local_SSAt::var_sett &globals, - int counter) +void ssa_inlinert::replace_globals_in( + const local_SSAt::var_sett &globals_in, + const local_SSAt::var_sett &globals, + int counter) { // equalities for globals_in for(summaryt::var_sett::const_iterator it=globals_in.begin(); @@ -789,9 +821,10 @@ void ssa_inlinert::get_replace_params( } } -void ssa_inlinert::replace_params(const local_SSAt::var_listt ¶ms, - const function_application_exprt &funapp_expr, - int counter) +void ssa_inlinert::replace_params( + const local_SSAt::var_listt ¶ms, + const function_application_exprt &funapp_expr, + int counter) { // equalities for arguments local_SSAt::var_listt::const_iterator p_it=params.begin(); @@ -855,10 +888,11 @@ void ssa_inlinert::get_replace_globals_out( } } -void ssa_inlinert::replace_globals_out(const local_SSAt::var_sett &globals_out, - const local_SSAt::var_sett &cs_globals_in, - const local_SSAt::var_sett &cs_globals_out, - int counter) +void ssa_inlinert::replace_globals_out( + const local_SSAt::var_sett &globals_out, + const local_SSAt::var_sett &cs_globals_in, + const local_SSAt::var_sett &cs_globals_out, + int counter) { // equalities for globals_out for(summaryt::var_sett::const_iterator it=cs_globals_out.begin(); @@ -906,15 +940,15 @@ Function: ssa_inlinert::rename \*******************************************************************/ -void ssa_inlinert::rename(irep_idt &id, int counter, bool attach){ - +void ssa_inlinert::rename(irep_idt &id, int counter, bool attach) +{ std::string id_str=id2string(id); if(!attach) { // find first @ where afterwards there are no letters size_t pos=std::string::npos; - for(size_t i=0;i assertion_mapt; - void get_guard_binding(const local_SSAt &SSA, - const local_SSAt &fSSA, - local_SSAt::nodest::const_iterator n_it, - exprt &guard_binding, - int counter); - void get_bindings(const local_SSAt &SSA, - const local_SSAt &fSSA, - local_SSAt::nodest::const_iterator n_it, - local_SSAt::nodet::function_callst::const_iterator f_it, - exprt::operandst &bindings_in, - exprt::operandst &bindings_out, - int counter); - bool get_summary(const local_SSAt &SSA, - local_SSAt::nodest::const_iterator n_it, - local_SSAt::nodet::function_callst::const_iterator f_it, - bool forward, - exprt::operandst &assert_summaries, - exprt::operandst &noassert_summaries, - exprt::operandst &bindings, - int counter, - bool error_summ=false); - bool get_inlined(const local_SSAt &SSA, - local_SSAt::nodest::const_iterator n_it, - local_SSAt::nodet::function_callst::const_iterator f_it, - bool forward, - exprt::operandst &assert_summaries, - exprt::operandst &noassert_summaries, - exprt::operandst &bindings, - assertion_mapt &assertion_map, - int counter, - bool error_summ); + void get_guard_binding( + const local_SSAt &SSA, + const local_SSAt &fSSA, + local_SSAt::nodest::const_iterator n_it, + exprt &guard_binding, + int counter); + void get_bindings( + const local_SSAt &SSA, + const local_SSAt &fSSA, + local_SSAt::nodest::const_iterator n_it, + local_SSAt::nodet::function_callst::const_iterator f_it, + exprt::operandst &bindings_in, + exprt::operandst &bindings_out, + int counter); + bool get_summary( + const local_SSAt &SSA, + local_SSAt::nodest::const_iterator n_it, + local_SSAt::nodet::function_callst::const_iterator f_it, + bool forward, + exprt::operandst &assert_summaries, + exprt::operandst &noassert_summaries, + exprt::operandst &bindings, + int counter, + bool error_summ=false); + bool get_inlined( + const local_SSAt &SSA, + local_SSAt::nodest::const_iterator n_it, + local_SSAt::nodet::function_callst::const_iterator f_it, + bool forward, + exprt::operandst &assert_summaries, + exprt::operandst &noassert_summaries, + exprt::operandst &bindings, + assertion_mapt &assertion_map, + int counter, + bool error_summ); void get_summaries( - const local_SSAt &SSA, - bool forward, - exprt::operandst &summaries, - exprt::operandst &bindings, - assertion_mapt &assertion_map); // TODO: need to explicitly pass the correct counter + const local_SSAt &SSA, + bool forward, + exprt::operandst &summaries, + exprt::operandst &bindings, + assertion_mapt &assertion_map); void get_summaries( - const local_SSAt &SSA, - bool forward, - exprt::operandst &summaries, - exprt::operandst &bindings); // TODO: need to explicitly pass the correct counter + const local_SSAt &SSA, + bool forward, + exprt::operandst &summaries, + exprt::operandst &bindings); bool get_summaries( - const local_SSAt &SSA, - const summaryt::call_sitet ¤t_call_site, - bool forward, - exprt::operandst &assert_summaries, - exprt::operandst &noassert_summaries, - exprt::operandst &bindings, - bool error_summ=false); // TODO: need to explicitly pass the correct counter + const local_SSAt &SSA, + const summaryt::call_sitet ¤t_call_site, + bool forward, + exprt::operandst &assert_summaries, + exprt::operandst &noassert_summaries, + exprt::operandst &bindings, + bool error_summ=false); bool get_summaries( - const local_SSAt &SSA, - const summaryt::call_sitet ¤t_call_site, - bool forward, - exprt::operandst &assert_summaries, - exprt::operandst &noassert_summaries, - exprt::operandst &bindings, - assertion_mapt &assertion_map, - bool error_summ=false); // TODO: need to explicitly pass the correct counter - - exprt get_summaries(const local_SSAt &SSA); // TODO: need to explicitly pass the correct counter - exprt get_summaries(const local_SSAt &SSA, - assertion_mapt &assertion_map); // TODO: need to explicitly pass the correct counter + const local_SSAt &SSA, + const summaryt::call_sitet ¤t_call_site, + bool forward, + exprt::operandst &assert_summaries, + exprt::operandst &noassert_summaries, + exprt::operandst &bindings, + assertion_mapt &assertion_map, + bool error_summ=false); + + // TODO: need to explicitly pass the correct counter + exprt get_summaries(const local_SSAt &SSA); + exprt get_summaries( + const local_SSAt &SSA, + assertion_mapt &assertion_map); void replace( local_SSAt &SSA, local_SSAt::nodest::iterator node, local_SSAt::nodet::function_callst::iterator f_it, - const local_SSAt::var_sett &cs_globals_in, - // incoming globals at call site - const local_SSAt::var_sett &cs_globals_out, - // outgoing globals at call site + const local_SSAt::var_sett &cs_globals_in, // incoming globals at call site + const local_SSAt::var_sett &cs_globals_out, // outgoing globals at call site const summaryt &summary, bool forward, bool preconditions_as_assertions, @@ -118,10 +122,8 @@ class ssa_inlinert:public messaget local_SSAt::nodest &nodes, local_SSAt::nodest::iterator node, local_SSAt::nodet::function_callst::iterator f_it, - const local_SSAt::var_sett &cs_globals_in, - // incoming globals at call site - const local_SSAt::var_sett &cs_globals_out, - // outgoing globals at call site + const local_SSAt::var_sett &cs_globals_in, // incoming globals at call site + const local_SSAt::var_sett &cs_globals_out, // outgoing globals at call site const local_SSAt &function, int counter); diff --git a/src/ssa/ssa_refiner.h b/src/ssa/ssa_refiner.h index 0c933e0da..087dd2e91 100644 --- a/src/ssa/ssa_refiner.h +++ b/src/ssa/ssa_refiner.h @@ -6,16 +6,16 @@ Author: Peter Schrammel \*******************************************************************/ -#ifndef CPROVER_SSA_REFINER_H -#define CPROVER_SSA_REFINER_H +#ifndef CPROVER_SSA_SSA_REFINER_H +#define CPROVER_SSA_SSA_REFINER_H #include -class ssa_refinert : public messaget +class ssa_refinert:public messaget { public: virtual bool operator()() { assert(false); } virtual unsigned get_unwind() { assert(false); } }; -#endif +#endif // CPROVER_SSA_SSA_REFINER_H diff --git a/src/ssa/ssa_refiner_monolithic.h b/src/ssa/ssa_refiner_monolithic.h index 603d214f1..e14e23b01 100644 --- a/src/ssa/ssa_refiner_monolithic.h +++ b/src/ssa/ssa_refiner_monolithic.h @@ -6,8 +6,8 @@ Author: Peter Schrammel \*******************************************************************/ -#ifndef CPROVER_SSA_REFINER_MONOLITHIC_H -#define CPROVER_SSA_REFINER_MONOLITHIC_H +#ifndef CPROVER_2LS_SSA_SSA_REFINER_MONOLITHIC_H +#define CPROVER_2LS_SSA_SSA_REFINER_MONOLITHIC_H #include "ssa_refiner.h" @@ -17,28 +17,28 @@ Author: Peter Schrammel class summary_dbt; class ssa_unwindert; -class ssa_refiner_monolithict : public ssa_refinert +class ssa_refiner_monolithict:public ssa_refinert { - public: - explicit ssa_refiner_monolithict( +public: + ssa_refiner_monolithict( summary_dbt &_summary_db, ssa_unwindert &_ssa_unwinder, - unsigned _max_unwind - ) : - summary_db(_summary_db), - ssa_unwinder(_ssa_unwinder), - max_unwind(_max_unwind), - unwind(0) - {} - - virtual bool operator()(); - virtual unsigned get_unwind() { return unwind>0 ? unwind-1 : 0; } - - protected: + unsigned _max_unwind): + summary_db(_summary_db), + ssa_unwinder(_ssa_unwinder), + max_unwind(_max_unwind), + unwind(0) + { + } + + virtual bool operator()(); + virtual unsigned get_unwind() { return unwind>0 ? unwind-1 : 0; } + +protected: summary_dbt &summary_db; ssa_unwindert &ssa_unwinder; const unsigned max_unwind; unsigned unwind; }; -#endif +#endif // CPROVER_2LS_SSA_SSA_REFINER_MONOLITHIC_H diff --git a/src/ssa/ssa_refiner_selective.cpp b/src/ssa/ssa_refiner_selective.cpp index 6b61c19a7..ae16ad2bc 100644 --- a/src/ssa/ssa_refiner_selective.cpp +++ b/src/ssa/ssa_refiner_selective.cpp @@ -29,8 +29,8 @@ bool ssa_refiner_selectivet::operator()() it->second.loops.begin(); l_it!=it->second.loops.end(); l_it++) { - unsigned new_unwind=ssa_unwinder.unwind_loop_once_more(it->first, - (*l_it)->location_number); + unsigned new_unwind= + ssa_unwinder.unwind_loop_once_more(it->first, (*l_it)->location_number); debug() << "Refining function " << it->first << ": unwinding loop at " << (*l_it)->location_number << " (k=" << new_unwind << ")" << eom; unwind=std::max(unwind, new_unwind); diff --git a/src/ssa/ssa_refiner_selective.h b/src/ssa/ssa_refiner_selective.h index b224a57c2..2ffcd166c 100644 --- a/src/ssa/ssa_refiner_selective.h +++ b/src/ssa/ssa_refiner_selective.h @@ -6,8 +6,8 @@ Author: Peter Schrammel, Madhukar Kumar \*******************************************************************/ -#ifndef CPROVER_SSA_REFINER_SELECTIVE_H -#define CPROVER_SSA_REFINER_SELECTIVE_H +#ifndef CPROVER_2LS_SSA_SSA_REFINER_SELECTIVE_H +#define CPROVER_2LS_SSA_SSA_REFINER_SELECTIVE_H #include "ssa_refiner.h" @@ -17,51 +17,52 @@ Author: Peter Schrammel, Madhukar Kumar class ssa_dbt; -class ssa_refiner_selectivet : public ssa_refinert +class ssa_refiner_selectivet:public ssa_refinert { - public: +public: struct reason_infot { - typedef local_SSAt::locationt function_infot; // call_site; restriction: we assume that there is a single function call in an SSA node + // call_site; restriction: + // we assume that there is a single function call in an SSA node + typedef local_SSAt::locationt function_infot; typedef local_SSAt::locationt loop_infot; std::set functions; std::set loops; }; - class reasont : public std::map + class reasont:public std::map { public: void merge(const reasont &other) { - for(reasont::const_iterator it=other.begin(); - it!=other.end(); ++it) + for(const auto &reason : other) { - reason_infot &r=(*this)[it->first]; - r.functions.insert(it->second.functions.begin(), - it->second.functions.end()); - r.loops.insert(it->second.loops.begin(), it->second.loops.end()); + reason_infot &r=(*this)[reason.first]; + r.functions.insert( + reason.second.functions.begin(), + reason.second.functions.end()); + r.loops.insert(reason.second.loops.begin(), reason.second.loops.end()); } } }; - - explicit ssa_refiner_selectivet( + ssa_refiner_selectivet( ssa_dbt &_ssa_db, ssa_unwindert &_ssa_unwinder, unsigned _max_unwind, ssa_inlinert &_ssa_inliner, - reasont &_reason - ) : - ssa_db(_ssa_db), - ssa_unwinder(_ssa_unwinder), - max_unwind(_max_unwind), - ssa_inliner(_ssa_inliner), - unwind(0), - reason(_reason) - {} + reasont &_reason): + ssa_db(_ssa_db), + ssa_unwinder(_ssa_unwinder), + max_unwind(_max_unwind), + ssa_inliner(_ssa_inliner), + unwind(0), + reason(_reason) + { + } - virtual bool operator()(); - virtual unsigned get_unwind() { return unwind; } + virtual bool operator()(); + virtual unsigned get_unwind() { return unwind; } protected: ssa_dbt &ssa_db; @@ -72,4 +73,4 @@ class ssa_refiner_selectivet : public ssa_refinert reasont &reason; }; -#endif +#endif // CPROVER_2LS_SSA_SSA_REFINER_SELECTIVE_H diff --git a/src/ssa/ssa_slicer.cpp b/src/ssa/ssa_slicer.cpp deleted file mode 100644 index 6489db818..000000000 --- a/src/ssa/ssa_slicer.cpp +++ /dev/null @@ -1,181 +0,0 @@ -#include - -#include -#include - -#include "local_ssa.cpp" - -void print_symbols(std::string msg, const find_symbols_sett &symbols) -{ - std::cout << msg << ": " << std::endl; - for(find_symbols_sett::const_iterator - s_it=symbols.begin(); s_it!=symbols.end(); s_it++) - std::cout << " " << *s_it << std::endl; - -} - -void ssa_slicert::operator()(std::list &dest, - const local_SSAt &src) -{ - // collect symbols in assertions - find_symbols_sett new_symbols; - for(local_SSAt::nodest::const_iterator n_it=src.nodes.begin(); - n_it!=src.nodes.end(); n_it++) - { - if(n_it->marked) continue; - if(n_it->assertions.empty()) continue; - for(local_SSAt::nodet::assertionst::const_iterator - a_it=n_it->assertions.begin(); - a_it!=n_it->assertions.end(); - a_it++) - { - find_symbols(*a_it, new_symbols); - } - } -#ifdef DEBUG - print_symbols("symbols in assertions", new_symbols); -#endif - if(new_symbols.empty()) return; - - // build map symbol -> (definition, constraint set) - symbol_mapt symbol_map; - sliced_equalities=0; - sliced_constraints=0; - - for(local_SSAt::nodest::const_iterator n_it=src.nodes.begin(); - n_it!=src.nodes.end(); n_it++) - { - for(local_SSAt::nodet::equalitiest::const_iterator - e_it=n_it->equalities.begin(); - e_it!=n_it->equalities.end(); - e_it++) - { - find_symbols_sett e_symbols; - find_symbols(e_it->lhs(), e_symbols); - - for(find_symbols_sett::const_iterator - s_it=e_symbols.begin(); s_it!=e_symbols.end(); s_it++) - { - symbol_map[*s_it]; - symbol_map[*s_it].def=e_it; - symbol_map[*s_it].def_node=n_it; - } - } - for(local_SSAt::nodet::constraintst::const_iterator - c_it=n_it->constraints.begin(); - c_it!=n_it->constraints.end(); - c_it++) - { - find_symbols_sett c_symbols; - find_symbols(*c_it, c_symbols); - for(find_symbols_sett::const_iterator - s_it=c_symbols.begin(); s_it!=c_symbols.end(); s_it++) - { - if(symbol_map.find(*s_it)==symbol_map.end()) continue; - symbol_map[*s_it].constraints.push_back(constr_infot()); - constr_infot &constr_info=symbol_map[*s_it].constraints.back(); - constr_info.constr=c_it; - constr_info.node=n_it; - } - } - // statistics - if(!n_it->marked) - { - sliced_equalities+=n_it->equalities.size(); - sliced_constraints+=n_it->constraints.size(); - } - } - // statistics - std::cout << "Total equalities: " << sliced_equalities - << ", total constraints: " << sliced_constraints << std::endl; - - // compute backwards dependencies and add to formula on-the-fly - find_symbols_sett symbols_seen; - while(!new_symbols.empty()) - { - find_symbols_sett old_symbols=new_symbols; - -#ifdef DEBUG - print_symbols("new symbols", new_symbols); -#endif - - new_symbols.clear(); - for(find_symbols_sett::const_iterator - s_it=old_symbols.begin(); s_it!=old_symbols.end(); s_it++) - { - irep_idt sym=*s_it; - if(symbols_seen.find(sym)!=symbols_seen.end()) continue; - if(symbol_map.find(sym)==symbol_map.end()) - { - // handle loopback variables - // here it's getting a bit ugly - std::string sym_str=id2string(sym); - size_t pos1=sym_str.find("#lb"); - if(pos1==std::string::npos) continue; - size_t pos2=sym_str.find("%", pos1); - irep_idt basename=sym_str.substr(0, pos1); - std::string unwinder_suffix=""; - if(pos2 - -#include "local_ssa.h" - -class ssa_slicert : public messaget -{ - public: - - void operator()(std::list &dest, - const local_SSAt &src); - - // statistics - unsigned sliced_equalities; - unsigned sliced_constraints; - - protected: - typedef struct - { - local_SSAt::nodet::constraintst::const_iterator constr; - local_SSAt::nodest::const_iterator node; - } constr_infot; - typedef std::list constraint_sett; - typedef struct - { - local_SSAt::nodet::equalitiest::const_iterator def; - local_SSAt::nodest::const_iterator def_node; - constraint_sett constraints; - } symbol_infot; - typedef hash_map_cont symbol_mapt; - -}; - -#endif diff --git a/src/ssa/ssa_unwinder.cpp b/src/ssa/ssa_unwinder.cpp index d489cec52..1c8dead21 100644 --- a/src/ssa/ssa_unwinder.cpp +++ b/src/ssa/ssa_unwinder.cpp @@ -290,26 +290,27 @@ void ssa_local_unwindert::unwind_loop_at_location(unsigned loc, unsigned k) return; loopt &loop=loops[loc]; - loop.loop_enabling_exprs.push_back(symbol_exprt("unwind$"+id2string(fname)+"$loc"+i2string(loc)+"$enable"+i2string(k), bool_typet())); - - // current_enabling_expr= - // symbol_exprt("unwind::"+id2string(fname)+"::enable"+i2string(k), - // bool_typet()); - // SSA.enabling_exprs.push_back(current_enabling_expr); + loop.loop_enabling_exprs.push_back( + symbol_exprt( + "unwind$"+id2string(fname)+"$loc"+i2string(loc)+"$enable"+i2string(k), + bool_typet())); + // TODO: just for exploratory integration, must go away + SSA.current_unwinding=k; - SSA.current_unwinding=k; // TODO: just for exploratory integration, must go away // recursively unwind everything SSA.current_unwindings.clear(); - for(loop_mapt::iterator it=loops.begin(); it!=loops.end(); ++it){ + for(loop_mapt::iterator it=loops.begin(); it!=loops.end(); ++it) + { if(!it->second.is_root) continue; if(it->first==loc) unwind(it->second, k, false, false); // recursive else - unwind(it->second, it->second.current_unwinding, false, true, k, loc); // recursive + unwind(it->second, it->second.current_unwinding, false, true, k, loc); + // recursive assert(SSA.current_unwindings.empty()); } @@ -347,7 +348,11 @@ void ssa_local_unwindert::unwind(unsigned k) bool_typet()); for(loop_mapt::iterator it=loops.begin(); it!=loops.end(); ++it) { - it->second.loop_enabling_exprs.push_back(symbol_exprt("unwind$"+id2string(fname)+"$loc"+i2string(it->first)+"$enable"+i2string(k), bool_typet())); + it->second.loop_enabling_exprs.push_back( + symbol_exprt( + "unwind$"+id2string(fname)+"$loc"+i2string(it->first)+ + "$enable"+i2string(k), + bool_typet())); } // TODO: just for exploratory integration, must go away @@ -385,9 +390,14 @@ Function: ssa_local_unwindert::unwind \*******************************************************************/ -void ssa_local_unwindert::unwind(loopt &loop, unsigned k, bool is_new_parent, - bool propagate, unsigned prop_unwind, - unsigned prop_loc, bool propagate_all) +void ssa_local_unwindert::unwind( + loopt &loop, + unsigned k, + bool is_new_parent, + bool propagate, + unsigned prop_unwind, + unsigned prop_loc, + bool propagate_all) { odometert context=SSA.current_unwindings; #ifdef DEBUG @@ -455,17 +465,20 @@ void ssa_local_unwindert::unwind(loopt &loop, unsigned k, bool is_new_parent, unwind( loops[l], k, i>loop.current_unwinding || is_new_parent, false); } - else{ + else + { if(propagate==true) { - // if this child loop is the desired loop then unwind k and do not propagate + // if this child loop is the desired loop then unwind k + // and do not propagate // else unwind loop.current_unwinding and propagate if(l==prop_loc) { unwind( loops[l], k, i>loop.current_unwinding || is_new_parent, false); } - else{ + else + { unwind( loops[l], loops[l].current_unwinding, @@ -971,19 +984,22 @@ void ssa_local_unwindert::unwinder_rename( #endif } -/*****************************************************************************\ - * - * Function : ssa_unwindert::unwind_loop_alone() - * - * Input : - * - * Output : - * - * Purpose : - * - *****************************************************************************/ +/*******************************************************************\ + +Function: ssa_local_unwindert::unwind_loop_alone + + Inputs: + + Outputs: -void ssa_unwindert::unwind_loop_alone(const irep_idt fname, unsigned loc, unsigned int k) + Purpose: + +\*******************************************************************/ + +void ssa_unwindert::unwind_loop_alone( + const irep_idt fname, + unsigned loc, + unsigned int k) { assert(is_initialized); unwinder_mapt::iterator it=unwinder_map.find(fname); @@ -991,19 +1007,21 @@ void ssa_unwindert::unwind_loop_alone(const irep_idt fname, unsigned loc, unsign it->second.unwind_loop_at_location(loc, k); } -/*****************************************************************************\ - * - * Function : ssa_unwindert::unwind_loop_once_more() - * - * Input : - * - * Output : - * - * Purpose : - * - *****************************************************************************/ +/*******************************************************************\ + +Function: ssa_local_unwindert::unwind_loop_once_more + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ -unsigned ssa_unwindert::unwind_loop_once_more(const irep_idt fname, unsigned loc) +unsigned ssa_unwindert::unwind_loop_once_more( + const irep_idt fname, + unsigned loc) { assert(is_initialized); unwinder_mapt::iterator it=unwinder_map.find(fname); diff --git a/src/ssa/ssa_unwinder.h b/src/ssa/ssa_unwinder.h index 673756af8..57a02c007 100644 --- a/src/ssa/ssa_unwinder.h +++ b/src/ssa/ssa_unwinder.h @@ -48,8 +48,9 @@ class ssa_local_unwindert // maybe move to unwindable_local_ssa as it is not really unwinder related void compute_enable_expr(); void loop_continuation_conditions(exprt::operandst &loop_cont) const; - void loop_continuation_conditions(const locationt& loop_id, - exprt::operandst &loop_cont) const; + void loop_continuation_conditions( + const locationt& loop_id, + exprt::operandst &loop_cont) const; #if 0 // TODO: these two should be possible with unwindable_local_ssa facilities @@ -59,9 +60,10 @@ class ssa_local_unwindert #endif // TODO: this must go away, should use SSA.rename instead - void unwinder_rename(symbol_exprt &var, - - const local_SSAt::nodet &node, bool pre) const; + void unwinder_rename( + symbol_exprt &var, + const local_SSAt::nodet &node, + bool pre) const; class loopt // loop tree { @@ -118,9 +120,14 @@ class ssa_local_unwindert void build_pre_post_map(); void build_exit_conditions(); - void unwind(loopt &loop, unsigned k, bool is_new_parent, - bool propagate=false, unsigned prop_unwind=0, - unsigned prop_loc=0, bool propagate_all=false); + void unwind( + loopt &loop, + unsigned k, + bool is_new_parent, + bool propagate=false, + unsigned prop_unwind=0, + unsigned prop_loc=0, + bool propagate_all=false); exprt get_continuation_condition(const loopt& loop) const; void loop_continuation_conditions( @@ -172,4 +179,4 @@ class ssa_unwindert:public messaget unwinder_mapt unwinder_map; }; -#endif +#endif // CPROVER_2LS_SSA_SSA_UNWINDER_H diff --git a/src/ssa/unwindable_local_ssa.cpp b/src/ssa/unwindable_local_ssa.cpp index 28589b88a..4dc6d1c99 100644 --- a/src/ssa/unwindable_local_ssa.cpp +++ b/src/ssa/unwindable_local_ssa.cpp @@ -279,10 +279,10 @@ Function: unwindable_local_SSAt::rename void unwindable_local_SSAt::rename(exprt &expr, locationt current_loc) { - if (expr.id()==ID_function_application) + if(expr.id()==ID_function_application) { - std::string unwind_suffix=odometer_to_string(current_unwindings, - current_unwindings.size()); + std::string unwind_suffix= + odometer_to_string(current_unwindings, current_unwindings.size()); expr.set(ID_suffix, unwind_suffix); } if(expr.id()==ID_symbol) diff --git a/src/storefront/Makefile b/src/storefront/Makefile deleted file mode 100644 index 55c7aa7ce..000000000 --- a/src/storefront/Makefile +++ /dev/null @@ -1,27 +0,0 @@ -include ../config.inc - -SRC = storefront_main.cpp storefront_parse_options.cpp data.cpp \ - property_view.cpp file_view.cpp trace_view.cpp - -OBJ+= $(CBMC)/src/util/util$(LIBEXT) \ - $(CBMC)/src/xmllang/xmllang$(LIBEXT) \ - ../html/html_escape$(OBJEXT) \ - ../html/syntax_highlighting$(OBJEXT) \ - ../html/logo$(OBJEXT) - -include $(CBMC)/src/config.inc -include $(CBMC)/src/common - -INCLUDES= -I $(CBMC)/src - -LIBS = - -CLEANFILES = storefront$(EXEEXT) - -all: storefront$(EXEEXT) - -############################################################################### - -storefront$(EXEEXT): $(OBJ) - $(LINKBIN) - diff --git a/src/storefront/data.cpp b/src/storefront/data.cpp deleted file mode 100644 index b9f9b5d68..000000000 --- a/src/storefront/data.cpp +++ /dev/null @@ -1,84 +0,0 @@ -/*******************************************************************\ - -Module: Trace View - -Author: Daniel Kroening, kroening@kroening.com - -\*******************************************************************/ - -#include -#include - -#include - -#include "data.h" - -/*******************************************************************\ - -Function: datat::read - - Inputs: - - Outputs: - - Purpose: - -\*******************************************************************/ - -void datat::read(const std::string &file) -{ - xmlt xml; - - console_message_handlert message_handler; - parse_xml(file, message_handler, xml); - - read(xml); -} - -/*******************************************************************\ - -Function: datat::read - - Inputs: - - Outputs: - - Purpose: - -\*******************************************************************/ - -void datat::read(const xmlt &xml) -{ - for(xmlt::elementst::const_iterator - it=xml.elements.begin(); - it!=xml.elements.end(); - it++) - { - if(it->name=="property") - { - propertyt property; - - for(xmlt::elementst::const_iterator - e_it=it->elements.begin(); - e_it!=it->elements.end(); - e_it++) - { - if(e_it->name=="file") - property.file=e_it->data; - else if(e_it->name=="line") - property.line=unsafe_string2unsigned(e_it->data); - else if(e_it->name=="category") - property.category=e_it->data; - else if(e_it->name=="message") - property.message=e_it->data; - } - - properties.push_back(property); - } - else if(it->name=="description") - { - description=it->data; - } - } -} - diff --git a/src/storefront/data.h b/src/storefront/data.h deleted file mode 100644 index c2813ae64..000000000 --- a/src/storefront/data.h +++ /dev/null @@ -1,40 +0,0 @@ -/*******************************************************************\ - -Module: Data - -Author: Daniel Kroening, kroening@kroening.com - -\*******************************************************************/ - -#ifndef CPROVER_DELTACHECK_DATA_H -#define CPROVER_DELTACHECK_DATA_H - -#include - -class datat -{ -public: - class propertyt - { - public: - irep_idt file; - unsigned line; - irep_idt category; - std::string message; - }; - - typedef std::vector propertiest; - propertiest properties; - - std::string description; - - inline void add(const propertyt &e) - { - properties.push_back(e); - } - - void read(const std::string &file); - void read(const class xmlt &); -}; - -#endif diff --git a/src/storefront/file_view.cpp b/src/storefront/file_view.cpp deleted file mode 100644 index 1370cd7f4..000000000 --- a/src/storefront/file_view.cpp +++ /dev/null @@ -1,147 +0,0 @@ -/*******************************************************************\ - -Module: Trace View - -Author: Daniel Kroening, kroening@kroening.com - -\*******************************************************************/ - -#include -#include - -#include - -#include "../html/html_escape.h" -#include "../html/syntax_highlighting.h" - -#include "data.h" - -/*******************************************************************\ - -Function: file_view - - Inputs: - - Outputs: - - Purpose: - -\*******************************************************************/ - -void print_file(const datat &data, irep_idt file, std::ostream &out) -{ - out << "
\n"; - out << "
" << html_escape(file) << "
\n"; - out << "
\n"; - - std::ifstream in(file.c_str()); - if(!in) - { - } - else - { - // line to property number - std::map > line_map; - - for(datat::propertiest::const_iterator - e_it=data.properties.begin(); - e_it!=data.properties.end(); - e_it++) - if(e_it->file==file) - { - line_map[e_it->line].push_back(e_it-data.properties.begin()); - } - - syntax_highlightingt syntax_highlighting(out); - - unsigned line_no=1; - - std::string line; - while(std::getline(in, line)) - { - syntax_highlighting.strong_class=""; - syntax_highlighting.line_no=line_no; - - std::vector &properties=line_map[line_no]; - - if(!properties.empty()) - { - syntax_highlighting.strong_class="alarm"; - } - - syntax_highlighting(line); - - line_no++; - } - } - - out << "
\n\n"; -} - -/*******************************************************************\ - -Function: file_view - - Inputs: - - Outputs: - - Purpose: - -\*******************************************************************/ - -void file_view(const datat &data) -{ - std::ofstream out("file_view.html"); - - out << "\n\n"; - out << "" << html_escape(data.description) << "\n"; - - out << "\n"; - out << "\n"; - - out << "\n"; - - out << "
\n"; - - out << "
\n"; - out << html_escape(data.description) << "\n"; - out << "
\n"; - - std::set files; - - for(datat::propertiest::const_iterator - e_it=data.properties.begin(); - e_it!=data.properties.end(); - e_it++) - files.insert(e_it->file); - - for(std::set::const_iterator - f_it=files.begin(); - f_it!=files.end(); - f_it++) - { - if(has_prefix(id2string(*f_it), "/usr/include/")) - continue; - - if(has_prefix(id2string(*f_it), "")) - continue; - - print_file(data, *f_it, out); - } - - out << "\n\n"; -} diff --git a/src/storefront/file_view.h b/src/storefront/file_view.h deleted file mode 100644 index e0c5ca8ee..000000000 --- a/src/storefront/file_view.h +++ /dev/null @@ -1,14 +0,0 @@ -/*******************************************************************\ - -Module: File View - -Author: Daniel Kroening, kroening@kroening.com - -\*******************************************************************/ - -#ifndef CPROVER_DELTACHECK_FILE_VIEW_H -#define CPROVER_DELTACHECK_FILE_VIEW_H - -void file_view(const class datat &); - -#endif diff --git a/src/storefront/property_view.cpp b/src/storefront/property_view.cpp deleted file mode 100644 index 21c5b31e8..000000000 --- a/src/storefront/property_view.cpp +++ /dev/null @@ -1,30 +0,0 @@ -/*******************************************************************\ - -Module: Property View - -Author: Daniel Kroening, kroening@kroening.com - -\*******************************************************************/ - -#include "data.h" - -/*******************************************************************\ - -Function: property_view - - Inputs: - - Outputs: - - Purpose: - -\*******************************************************************/ - -void property_view(const class datat &) -{ - -} - - - - diff --git a/src/storefront/property_view.h b/src/storefront/property_view.h deleted file mode 100644 index 83f1eae61..000000000 --- a/src/storefront/property_view.h +++ /dev/null @@ -1,14 +0,0 @@ -/*******************************************************************\ - -Module: Property View - -Author: Daniel Kroening, kroening@kroening.com - -\*******************************************************************/ - -#ifndef CPROVER_DELTACHECK_PROPERTY_VIEW_H -#define CPROVER_DELTACHECK_PROPERTY_VIEW_H - -void property_view(const class datat &); - -#endif diff --git a/src/storefront/storefront_main.cpp b/src/storefront/storefront_main.cpp deleted file mode 100644 index 6787c27cc..000000000 --- a/src/storefront/storefront_main.cpp +++ /dev/null @@ -1,38 +0,0 @@ -/*******************************************************************\ - -Module: Main Module - -Author: Daniel Kroening, kroening@kroening.com - -\*******************************************************************/ - -#include - -#include "storefront_parse_options.h" - -/*******************************************************************\ - -Function: main - - Inputs: - - Outputs: - - Purpose: - -\*******************************************************************/ - -#ifdef _MSC_VER -int wmain(int argc, const wchar_t **argv_wide) -{ - const char **argv=narrow_argv(argc, argv_wide); - storefront_parse_optionst parse_options(argc, argv); - return parse_options.main(); -} -#else -int main(int argc, const char **argv) -{ - storefront_parse_optionst parse_options(argc, argv); - return parse_options.main(); -} -#endif diff --git a/src/storefront/storefront_parse_options.cpp b/src/storefront/storefront_parse_options.cpp deleted file mode 100644 index e8c566914..000000000 --- a/src/storefront/storefront_parse_options.cpp +++ /dev/null @@ -1,121 +0,0 @@ -/*******************************************************************\ - -Module: Command Line Interface - -Author: Daniel Kroening, kroening@kroening.com - -\*******************************************************************/ - -#include - -#include "../deltacheck/version.h" - -#include "storefront_parse_options.h" -#include "data.h" -#include "file_view.h" -#include "trace_view.h" -#include "property_view.h" - -/*******************************************************************\ - -Function: storefront_parse_optionst::storefront_parse_optionst - - Inputs: - - Outputs: - - Purpose: - -\*******************************************************************/ - -storefront_parse_optionst::storefront_parse_optionst( - int argc, const char **argv): - parse_options_baset(STOREFRONT_OPTIONS, argc, argv) -{ -} - -/*******************************************************************\ - -Function: storefront_parse_optionst::doit - - Inputs: - - Outputs: - - Purpose: invoke main modules - -\*******************************************************************/ - -int storefront_parse_optionst::doit() -{ - if(cmdline.isset("version")) - { - std::cout << DELTACHECK_VERSION << std::endl; - return 0; - } - - try - { - if(cmdline.args.empty()) - { - usage_error(); - return 10; - } - - // read config - datat data; - - for(unsigned i=0; i - -#define STOREFRONT_OPTIONS \ - "(verbosity):(version)" - -class storefront_parse_optionst:public parse_options_baset -{ -public: - virtual int doit(); - virtual void help(); - - storefront_parse_optionst( - int argc, const char **argv); - -protected: -}; - -#endif diff --git a/src/storefront/trace_view.cpp b/src/storefront/trace_view.cpp deleted file mode 100644 index 73c2a30b3..000000000 --- a/src/storefront/trace_view.cpp +++ /dev/null @@ -1,29 +0,0 @@ -/*******************************************************************\ - -Module: Trace View - -Author: Daniel Kroening, kroening@kroening.com - -\*******************************************************************/ - -#include "data.h" - -/*******************************************************************\ - -Function: trace_view - - Inputs: - - Outputs: - - Purpose: - -\*******************************************************************/ - -void trace_view(const class datat &) -{ - -} - - - diff --git a/src/storefront/trace_view.h b/src/storefront/trace_view.h deleted file mode 100644 index fcaaf7a4f..000000000 --- a/src/storefront/trace_view.h +++ /dev/null @@ -1,14 +0,0 @@ -/*******************************************************************\ - -Module: Trace View - -Author: Daniel Kroening, kroening@kroening.com - -\*******************************************************************/ - -#ifndef CPROVER_DELTACHECK_TRACE_VIEW_H -#define CPROVER_DELTACHECK_TRACE_VIEW_H - -void trace_view(const class datat &); - -#endif diff --git a/src/summarizer/function_signature.cpp b/src/summarizer/function_signature.cpp deleted file mode 100644 index 0b51648f4..000000000 --- a/src/summarizer/function_signature.cpp +++ /dev/null @@ -1,78 +0,0 @@ -/*******************************************************************\ - -Module: Signature of a Function - -Author: Daniel Kroening, kroening@kroening.com - -\*******************************************************************/ - -#include - -#include "../ssa/local_ssa.h" -#include "function_signature.h" - -/*******************************************************************\ - -Function: update_function_signature - - Inputs: - - Outputs: - - Purpose: - -\*******************************************************************/ - -void update_function_signature( - const local_SSAt &SSA, - class jsont &dest) -{ - jsont &j_signature=dest["signature"]; - jsont &j_reads=j_signature["reads"]; - jsont &j_modifies=j_signature["modifies"]; - - j_signature.kind=jsont::J_OBJECT; - j_reads=jsont::json_array(); - j_modifies=jsont::json_array(); - - std::set modifies; - std::set reads; - - for(assignmentst::assignment_mapt::const_iterator - a_it=SSA.assignments.assignment_map.begin(); - a_it!=SSA.assignments.assignment_map.end(); - a_it++) - { - for(assignmentst::objectst::const_iterator - o_it=a_it->second.begin(); - o_it!=a_it->second.end(); - o_it++) - { - modifies.insert(o_it->get_identifier()); - } - } - - for(ssa_objectst::objectst::const_iterator - o_it=SSA.ssa_objects.objects.begin(); - o_it!=SSA.ssa_objects.objects.end(); - o_it++) - { - reads.insert(o_it->get_identifier()); - } - - for(std::set::const_iterator it=reads.begin(); - it!=reads.end(); - it++) - { - j_reads.array.push_back(jsont::json_string(id2string(*it))); - } - - for(std::set::const_iterator it=modifies.begin(); - it!=modifies.end(); - it++) - { - j_modifies.array.push_back(jsont::json_string(id2string(*it))); - } - -} - diff --git a/src/summarizer/function_signature.h b/src/summarizer/function_signature.h deleted file mode 100644 index 16a7eaf09..000000000 --- a/src/summarizer/function_signature.h +++ /dev/null @@ -1,17 +0,0 @@ -/*******************************************************************\ - -Module: Signature of a Function - -Author: Daniel Kroening, kroening@kroening.com - -\*******************************************************************/ - -#ifndef CPROVER_SUMMARIZER_FUNCTION_SIGNATURE_H -#define CPROVER_SUMMARIZER_FUNCTION_SIGNATURE_H - -#include - -void update_function_signature(const class local_SSAt &, jsont &); - -#endif - diff --git a/src/summarizer/instrument_goto.cpp b/src/summarizer/instrument_goto.cpp deleted file mode 100644 index e34faf7ba..000000000 --- a/src/summarizer/instrument_goto.cpp +++ /dev/null @@ -1,180 +0,0 @@ -/*******************************************************************\ - -Module: Instrument Goto Program with Inferred Information - -Author: Peter Schrammel - -\*******************************************************************/ - -#include - -#define DEBUG - -#ifdef DEBUG -#include -#endif - -#include "instrument_goto.h" - - - -local_SSAt::locationt find_loop_by_guard(const local_SSAt &SSA, - const symbol_exprt &guard) -{ - std::string gstr=id2string(guard.get_identifier()); - unsigned pos1=gstr.find("#")+1; - unsigned pos2=gstr.find("%", pos1); - unsigned n=safe_string2unsigned(gstr.substr(pos1, pos2)); - - local_SSAt::nodest::const_iterator n_it=SSA.nodes.begin(); - - for(; n_it!=SSA.nodes.end(); n_it++) - { - if(n_it->location->location_number==n) { - // find end of loop - break; - } - } - - if(n_it->loophead==SSA.nodes.end()) - return n_it->location; - else - return n_it->loophead->location; -} - - -void instrument_gotot::instrument_instruction( - const exprt &expr, - goto_programt &dest, - goto_programt::targett &target) -{ - - goto_programt::targett where=target; - - std::cout << "target " << target->type << " : " << target->source_location << std::endl; - - for(;;++where) - { - if(where->is_goto() && where->get_target()==target) - break; - } - - - goto_programt tmp; - - goto_programt::targett assumption=tmp.add_instruction(); - assumption->make_assumption(expr); - assumption->source_location=target->source_location; - assumption->source_location.set_comment("invariant generated by 2LS"); - - dest.insert_before_swap(where, tmp); - - #ifdef DEBUG - std::cout << "instrumenting instruction " << std::endl; - #endif - - - // dest.update(); -} - -extern -void purify_identifiers(exprt &expr); - - -void instrument_gotot::instrument_body( - const local_SSAt &SSA, - const exprt &expr, - goto_functionst::goto_functiont &function -) -{ - // expected format (/\_j g_j)=> inv - const exprt &impl=expr.op0(); - exprt inv=expr.op1(); // copy - - std::cout << "Invariant " << from_expr(inv) << std::endl; - - purify_identifiers(inv); - - local_SSAt::locationt loc; - if(impl.id()==ID_symbol) - { - loc=find_loop_by_guard(SSA, to_symbol_expr(impl)); - } - else if(impl.id()==ID_and) - { - assert(impl.op0().id()==ID_symbol); - loc=find_loop_by_guard(SSA, to_symbol_expr(impl.op0())); - - } - else assert(false); - - - Forall_goto_program_instructions(it, function.body) - if(it==loc) - { - - instrument_instruction(inv, function.body, it); - break; - } -} - - - -void instrument_gotot::instrument_function( - const irep_idt &function_name, - goto_functionst::goto_functiont &function) -{ - #ifdef DEBUG - std::cout << "instrumenting function " << function_name << std::endl; - #endif - - if(!summary_db.exists(function_name)) - return; - - const summaryt summary=summary_db.get(function_name); - - if(!ssa_db.exists(function_name)) - return; - - const local_SSAt &SSA=ssa_db.get(function_name); - - if(summary.fw_invariant.is_nil()) return; - if(summary.fw_invariant.is_true()) return; - - // expected format /\_i g_i=> inv_i - if(summary.fw_invariant.id()==ID_implies) - { - instrument_body(SSA, summary.fw_invariant, function); - } - else if(summary.fw_invariant.id()==ID_and) - { - for(unsigned i=0; i::function_mapt - function_mapt; - - function_mapt - &function_map=goto_functions.function_map; - - for(function_mapt::iterator - fit=function_map.begin(); - fit!=function_map.end(); - ++fit) - { - instrument_function(fit->first, fit->second); - } - - goto_model.goto_functions.update(); -} diff --git a/src/summarizer/instrument_goto.h b/src/summarizer/instrument_goto.h deleted file mode 100644 index 9a56f4876..000000000 --- a/src/summarizer/instrument_goto.h +++ /dev/null @@ -1,55 +0,0 @@ -/*******************************************************************\ - -Module: Instrument Goto Program with Inferred Information - -Author: Peter Schrammel - -\*******************************************************************/ - -#ifndef CPROVER_INSTRUMENT_GOTO_H -#define CPROVER_INSTRUMENT_GOTO_H - -#include -#include - -#include "../ssa/local_ssa.h" -#include "../ssa/ssa_unwinder.h" -#include "ssa_db.h" -#include "summary_db.h" - -class instrument_gotot:public messaget -{ -public: - inline instrument_gotot(optionst &_options, - ssa_dbt &_ssa_db, - summary_dbt &_summary_db): - options(_options), - ssa_db(_ssa_db), summary_db(_summary_db) - { - } - - void operator()(goto_modelt &goto_model); - - protected: - optionst &options; - - ssa_dbt &ssa_db; - summary_dbt &summary_db; - - void instrument_function( - const irep_idt &function_name, - goto_functionst::goto_functiont &function); - - void instrument_body( - const local_SSAt &SSA, - const exprt &expr, - goto_functionst::goto_functiont &function); - - void instrument_instruction( - const exprt &expr, - goto_programt &dest, - goto_programt::targett &target); - -}; - -#endif diff --git a/src/summarizer/preprocessing_util.cpp b/src/summarizer/preprocessing_util.cpp deleted file mode 100644 index fb8a61a06..000000000 --- a/src/summarizer/preprocessing_util.cpp +++ /dev/null @@ -1,265 +0,0 @@ -#include -#include -#include - -#include -#include - -#include "summarizer_parse_options.h" - - -/*******************************************************************\ - -Function: summarizer_parse_optionst::inline_main - - Inputs: - - Outputs: - - Purpose: - -\*******************************************************************/ - -void summarizer_parse_optionst::inline_main(goto_modelt &goto_model) -{ - goto_programt &main=goto_model.goto_functions.function_map[ID__start].body; - goto_programt::targett target=main.instructions.begin(); - while(target!=main.instructions.end()) - { - if(target->is_function_call()) - { - const code_function_callt &code_function_call= - to_code_function_call(target->code); - irep_idt fname=code_function_call.function().get(ID_identifier); - - debug() << "Inlining " << fname << eom; - - goto_programt tmp; - tmp.copy_from(goto_model.goto_functions.function_map[fname].body); - (--tmp.instructions.end())->make_skip(); - goto_model.goto_functions.function_map.erase(fname); - - goto_programt::targett next_target(target); - target->make_skip(); - next_target++; - main.instructions.splice(next_target, tmp.instructions); - target=next_target; - } - else target++; - } - - goto_model.goto_functions.update(); - goto_model.goto_functions.compute_loop_numbers(); -} - -/*******************************************************************\ - -Function: summarizer_parse_optionst::propagate_constants - - Inputs: - - Outputs: - - Purpose: - -\*******************************************************************/ - -void summarizer_parse_optionst::propagate_constants(goto_modelt &goto_model) -{ - namespacet ns(goto_model.symbol_table); - Forall_goto_functions(f_it, goto_model.goto_functions) - { - constant_propagator_ait(f_it->second, ns); - } -} - -/*******************************************************************\ - -Function: summarizer_parse_optionst::nondet_locals - - Inputs: - - Outputs: - - Purpose: explicitly assign a nondet_symbol to local variables - this is required by the unwinder, which would be unable - to recognise in which scope variables have been declared - -\*******************************************************************/ - -void summarizer_parse_optionst::nondet_locals(goto_modelt &goto_model) -{ - namespacet ns(goto_model.symbol_table); - Forall_goto_functions(f_it, goto_model.goto_functions) - { - Forall_goto_program_instructions(i_it, f_it->second.body) - { - if(i_it->is_decl()) - { - const code_declt& decl=to_code_decl(i_it->code); - side_effect_expr_nondett nondet(decl.symbol().type()); - goto_programt::targett t=f_it->second.body.insert_after(i_it); - t->make_assignment(); - code_assignt c(decl.symbol(), nondet); - t->code.swap(c); - t->source_location=i_it->source_location; - } - } - } - goto_model.goto_functions.update(); -} - -/*******************************************************************\ - -Function: goto_unwind - - Inputs: - - Outputs: - - Purpose: unwind all loops - -\*******************************************************************/ - -void summarizer_parse_optionst::unwind_goto_into_loop(goto_modelt &goto_model, unsigned k) -{ - typedef std::vector > loopst; - - Forall_goto_functions(f_it, goto_model.goto_functions) - { - goto_programt &body=f_it->second.body; - - loopst loops; - Forall_goto_program_instructions(i_it, body) - { - if(i_it->is_backwards_goto()) - { - goto_programt::targett loop_head=i_it->get_target(); - goto_programt::targett loop_exit=i_it; - bool has_goto_into_loop=false; - - goto_programt::targett it=loop_head; - if(it!=loop_exit) it++; - for(; it!=loop_exit; it++) - { - for( std::set::iterator - s_it=it->incoming_edges.begin(); - s_it!=it->incoming_edges.end(); ++s_it) - { - if((*s_it)->is_goto() && - (*s_it)->location_numberlocation_number) - { - has_goto_into_loop=true; - break; - } - } - if(has_goto_into_loop) break; - } - if(has_goto_into_loop) - { - status() << "Unwinding jump into loop" << eom; - loops.push_back(loopst::value_type(++loop_exit, loop_head)); - } - } - } - - for(loopst::iterator l_it=loops.begin(); l_it!=loops.end(); ++l_it) - { - std::vector iteration_points; - unwind(body, l_it->second, l_it->first, k, iteration_points); - assert(iteration_points.size()==2); - goto_programt::targett t=body.insert_before(l_it->first); - t->make_goto(); - t->targets.push_back(iteration_points.front()); - } - } - goto_model.goto_functions.update(); - goto_model.goto_functions.compute_loop_numbers(); -} - -/*******************************************************************\ - -Function: remove_multiple_dereferences - - Inputs: - - Outputs: - - Purpose: temporary fix to circumvent ssa_dereference problem - -\*******************************************************************/ - -void summarizer_parse_optionst::remove_multiple_dereferences(goto_modelt &goto_model, goto_programt &body, goto_programt::targett t, exprt &expr, unsigned &var_counter, bool deref_seen) -{ - if(expr.id()==ID_member) - { - member_exprt &member_expr=to_member_expr(expr); - if(member_expr.compound().id()==ID_dereference) - { - dereference_exprt &deref_expr=to_dereference_expr(member_expr.compound()); - remove_multiple_dereferences(goto_model, body, t, deref_expr.pointer(), var_counter, true); - if(deref_seen) - { - symbolt new_symbol; - new_symbol.type=member_expr.type(); - new_symbol.name="$deref"+i2string(var_counter++); - new_symbol.base_name=new_symbol.name; - new_symbol.pretty_name=new_symbol.name; - goto_model.symbol_table.add(new_symbol); - goto_programt::targett t_new=body.insert_before(t); - t_new->make_assignment(); - t_new->code=code_assignt(new_symbol.symbol_expr(), member_expr); - expr=new_symbol.symbol_expr(); - for(std::set::iterator t_it= - t->incoming_edges.begin(); - t_it!=t->incoming_edges.end(); ++t_it) - { - (*t_it)->targets.clear(); - (*t_it)->targets.push_back(t_new); - } - body.compute_location_numbers(); - body.compute_target_numbers(); - body.compute_incoming_edges(); - } - } - else - Forall_operands(o_it, expr) - remove_multiple_dereferences(goto_model, body, t, *o_it, var_counter, deref_seen); - } - else - Forall_operands(o_it, expr) - remove_multiple_dereferences(goto_model, body, t, *o_it, var_counter, deref_seen); -} - -void summarizer_parse_optionst::remove_multiple_dereferences(goto_modelt &goto_model) -{ - unsigned var_counter=0; - namespacet ns(goto_model.symbol_table); - Forall_goto_functions(f_it, goto_model.goto_functions) - { - Forall_goto_program_instructions(i_it, f_it->second.body) - { - if(i_it->is_goto()) - { - remove_multiple_dereferences(goto_model, - f_it->second.body, - i_it, - i_it->guard, - var_counter, false); - } - else if(i_it->is_assign()) - { - remove_multiple_dereferences(goto_model, - f_it->second.body, - i_it, - to_code_assign(i_it->code).lhs(), - var_counter, false); - remove_multiple_dereferences(goto_model, - f_it->second.body, - i_it, - to_code_assign(i_it->code).rhs(), - var_counter, false); - } - } - } -} diff --git a/src/summarizer/summarizer.cpp b/src/summarizer/summarizer.cpp deleted file mode 100644 index 13f063c2a..000000000 --- a/src/summarizer/summarizer.cpp +++ /dev/null @@ -1,125 +0,0 @@ -/*******************************************************************\ - -Module: Summarizer - -Author: Daniel Kroening, kroening@kroening.com - -\*******************************************************************/ - -#include "../ssa/local_ssa.h" -#include "../ssa/simplify_ssa.h" - -#include "function_signature.h" -#include "summary_db.h" -#include "summarizer.h" - -/*******************************************************************\ - -Function: summarizert::operator() - - Inputs: - - Outputs: - - Purpose: - -\*******************************************************************/ - -void summarizert::operator()(const goto_modelt &goto_model) -{ - // analyze all the functions - forall_goto_functions(f_it, goto_model.goto_functions) - summarize(goto_model, f_it); -} - -/*******************************************************************\ - -Function: summarizert::operator() - - Inputs: - - Outputs: - - Purpose: - -\*******************************************************************/ - -void summarizert::operator()( - const goto_modelt &goto_model, - const irep_idt &id) -{ - // analyze the given function only - - goto_functionst::function_mapt::const_iterator f_it= - goto_model.goto_functions.function_map.find(id); - - if(f_it==goto_model.goto_functions.function_map.end()) - throw "function not found"; - - summarize(goto_model, f_it); -} - -/*******************************************************************\ - -Function: summarizert::summarize - - Inputs: - - Outputs: - - Purpose: - -\*******************************************************************/ - -void summarizert::summarize( - const goto_modelt &goto_model, - const goto_functionst::function_mapt::const_iterator f_it) -{ - status() << "** Analyzing " << f_it->first << messaget::eom; - - summary_dbt summary_db; - - summary_db.set_message_handler(get_message_handler()); - summary_db.read(id2string(f_it->first)); - - const namespacet ns(goto_model.symbol_table); - - // build SSA - progress() << "Building SSA" << messaget::eom; - local_SSAt SSA(f_it->second, ns); - - // simplify, if requested - if(simplify) - { - progress() << "Simplifying" << messaget::eom; - ::simplify(SSA, ns); - } - - - // fixed-point for loops - #if 0 - progress() << "Fixed-point" << messaget::eom; - ssa_fixed_point(SSA); - #endif - - update_function_signature(SSA, summary_db.summary); - - summary_db.write(); -} - -/*******************************************************************\ - -Function: summarizert::report_statistics() - - Inputs: - - Outputs: - - Purpose: - -\*******************************************************************/ - -void summarizert::report_statistics() -{ -} - diff --git a/src/summarizer/summarizer.h b/src/summarizer/summarizer.h deleted file mode 100644 index 2979357e3..000000000 --- a/src/summarizer/summarizer.h +++ /dev/null @@ -1,45 +0,0 @@ -/*******************************************************************\ - -Module: Summarizer - -Author: Daniel Kroening, kroening@kroening.com - -\*******************************************************************/ - -#ifndef CPROVER_SUMMARIZER_H -#define CPROVER_SUMMARIZER_H - -#include -#include - -#include - -#include "../ssa/local_ssa.h" - -class summarizert:public messaget -{ -public: - inline summarizert(): - simplify(false), - fixed_point(false) - { - } - - bool simplify, fixed_point; - - void operator()(const goto_modelt &); - void operator()(const goto_modelt &, const irep_idt &); - - // statistics - absolute_timet start_time; - time_periodt sat_time; - -protected: - void report_statistics(); - - void summarize( - const goto_modelt &, - const goto_functionst::function_mapt::const_iterator); -}; - -#endif diff --git a/src/summarizer/summarizer_fw_contexts.cpp b/src/summarizer/summarizer_fw_contexts.cpp deleted file mode 100644 index 8fc94e943..000000000 --- a/src/summarizer/summarizer_fw_contexts.cpp +++ /dev/null @@ -1,174 +0,0 @@ -/*******************************************************************\ - -Module: Summarizer for Forward Analysis with Calling Context output - -Author: Peter Schrammel - -\*******************************************************************/ - -#include - -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "summarizer_fw_contexts.h" -#include "summary_db.h" - -#include "../domains/ssa_analyzer.h" -#include "../domains/template_generator_summary.h" -#include "../domains/template_generator_callingcontext.h" - -#include "../ssa/local_ssa.h" -#include "../ssa/simplify_ssa.h" - -/*******************************************************************\ - -Function: summarizer_fw_contextst::summarize() - - Inputs: - - Outputs: - - Purpose: - -\*******************************************************************/ - -void summarizer_fw_contextst::summarize() -{ - exprt precondition=true_exprt(); // initial calling context - for(functionst::const_iterator it=ssa_db.functions().begin(); - it!=ssa_db.functions().end(); it++) - { - if(excluded_functions.find(it->first)!=excluded_functions.end()) - continue; - status() << "\nSummarizing function " << it->first << eom; - if(!summary_db.exists(it->first) || - summary_db.get(it->first).mark_recompute) - compute_summary_rec(it->first, precondition, false); - else status() << "Summary for function " << it->first << - " exists already" << eom; - } -} - -/*******************************************************************\ - -Function: summarizer_fw_contextst::inline_summaries() - - Inputs: - - Outputs: - - Purpose: - -\*******************************************************************/ - -void summarizer_fw_contextst::inline_summaries( - const function_namet &function_name, - local_SSAt &SSA, const exprt &precondition, - bool context_sensitive) -{ - for(local_SSAt::nodest::const_iterator n_it=SSA.nodes.begin(); - n_it!=SSA.nodes.end(); n_it++) - { - for(local_SSAt::nodet::function_callst::const_iterator f_it= - n_it->function_calls.begin(); - f_it!=n_it->function_calls.end(); f_it++) - { - assert(f_it->function().id()==ID_symbol); // no function pointers - if(!check_call_reachable(function_name, SSA, n_it, f_it, precondition, true)) - { - continue; - } - - irep_idt fname=to_symbol_expr(f_it->function()).get_identifier(); - - if(excluded_functions.find(fname)!=excluded_functions.end()) - { - exprt precondition_call=compute_calling_context( - function_name, SSA, n_it, f_it, precondition, true); - - // output calling context - switch(ui) - { - case ui_message_handlert::PLAIN: - break; - - case ui_message_handlert::XML_UI: - { - xmlt xml_cc("calling-context"); - xml_cc.set_attribute("function", id2string(fname)); - xml_cc.set_attribute("goto_location", - i2string(n_it->location->location_number)); - - // location - const source_locationt &source_location= - n_it->location->source_location; - xmlt xml_location; - if(source_location.is_not_nil() && source_location.get_file()!="") - xml_location=xml(source_location); - if(xml_location.name!="") - xml_cc.new_element().swap(xml_location); - - // argument ranges - xmlt xml_args("argument-ranges"); - assert(precondition_call.operands().size()%2==0); - for(unsigned i=0;i -#include -#include - -#include "summarizer_fw.h" - -#include "../ssa/ssa_inliner.h" -#include "../ssa/ssa_unwinder.h" -#include "../ssa/local_ssa.h" -#include "ssa_db.h" - -#include - -class summarizer_fw_contextst : public summarizer_fwt -{ - public: - explicit summarizer_fw_contextst(optionst &_options, - summary_dbt &_summary_db, - ssa_dbt &_ssa_db, - ssa_unwindert &_ssa_unwinder, - ssa_inlinert &_ssa_inliner) : - summarizer_fwt(_options, _summary_db, _ssa_db, _ssa_unwinder, _ssa_inliner), - ui(ui_message_handlert::PLAIN) - { - if(_options.get_bool_option("xml-ui")) - ui=ui_message_handlert::XML_UI; - - optionst::value_listt _excluded_functions= - _options.get_list_option("do-not-analyze-functions"); - excluded_functions.insert(_excluded_functions.begin(), - _excluded_functions.end()); - - } - - virtual void summarize(); - - protected: - language_uit::uit ui; // use gui format - std::set excluded_functions; - - virtual void inline_summaries(const function_namet &function_name, - local_SSAt &SSA, - const exprt &precondition, - bool context_sensitive); -}; - - -#endif diff --git a/src/summarizer/summarizer_parse_options.cpp b/src/summarizer/summarizer_parse_options.cpp deleted file mode 100644 index d44fac004..000000000 --- a/src/summarizer/summarizer_parse_options.cpp +++ /dev/null @@ -1,1593 +0,0 @@ -/*******************************************************************\ - -Module: Summarizer Command Line Options Processing - -Author: Daniel Kroening, kroening@kroening.com - -\*******************************************************************/ - -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "array_abstraction.h" - -#include - -#include - -#include -#include "version.h" - -#include "../ssa/malloc_ssa.h" - -#include "summarizer_parse_options.h" -#include "summary_db.h" -#include "summary_checker_ai.h" -#include "summary_checker_bmc.h" -#include "summary_checker_kind.h" -#include "../ssa/split_loopheads.h" -#include "show.h" -#include "horn_encoding.h" - -#define UNWIND_GOTO_INTO_LOOP 0 -#define REMOVE_MULTIPLE_DEREFERENCES 1 - -/*******************************************************************\ - -Function: summarizer_parse_optionst::summarizer_parse_optionst - - Inputs: - - Outputs: - - Purpose: - -\*******************************************************************/ - -summarizer_parse_optionst::summarizer_parse_optionst(int argc, const char **argv): -parse_options_baset(SUMMARIZER_OPTIONS, argc, argv), - language_uit(cmdline, ui_message_handler), - ui_message_handler(cmdline, "2LS " SUMMARIZER_VERSION) -{ -} - -/*******************************************************************\ - -Function: summarizer_parse_optionst::eval_verbosity - - Inputs: - - Outputs: - - Purpose: - -\*******************************************************************/ - -void summarizer_parse_optionst::eval_verbosity() -{ - // this is our default verbosity - int v=messaget::M_STATISTICS; - - if(cmdline.isset("verbosity")) - { - v=unsafe_string2int(cmdline.get_value("verbosity")); - if(v<0) - v=0; - else if(v>10) - v=10; - } - - ui_message_handler.set_verbosity(v); -} - -/*******************************************************************\ - -Function: summarizer_parse_optionst::get_command_line_options - - Inputs: - - Outputs: - - Purpose: - -\*******************************************************************/ - -void summarizer_parse_optionst::get_command_line_options(optionst &options) -{ - if(config.set(cmdline)) - { - usage_error(); - exit(1); - } - - if(cmdline.isset("xml-ui")) - options.set_option("xml-ui", true); - - if(cmdline.isset("debug-level")) - options.set_option("debug-level", cmdline.get_value("debug-level")); - - if(cmdline.isset("unwindset")) - options.set_option("unwindset", cmdline.get_value("unwindset")); - - if(cmdline.isset("unwind")) - options.set_option("unwind", cmdline.get_value("unwind")); - - if(cmdline.isset("inline-partial")) - options.set_option("inline-partial", cmdline.get_value("inline-partial")); - - if(cmdline.isset("inline")) - options.set_option("inline", true); - - if(cmdline.isset("spurious-check")) - options.set_option("spurious-check", cmdline.get_value("spurious-check")); - else - options.set_option("spurious-check", "all"); - - if(cmdline.isset("slice") && cmdline.isset("inline")) - options.set_option("slice", true); - else - options.set_option("slice", false); - - // check array bounds - if(cmdline.isset("bounds-check")) - options.set_option("bounds-check", true); - else - options.set_option("bounds-check", false); - - // check division by zero - if(cmdline.isset("div-by-zero-check")) - options.set_option("div-by-zero-check", true); - else - options.set_option("div-by-zero-check", false); - - // check overflow/underflow - if(cmdline.isset("signed-overflow-check")) - options.set_option("signed-overflow-check", true); - else - options.set_option("signed-overflow-check", false); - - // check overflow/underflow - if(cmdline.isset("unsigned-overflow-check")) - options.set_option("unsigned-overflow-check", true); - else - options.set_option("unsigned-overflow-check", false); - - // check overflow on floats - if(cmdline.isset("float-overflow-check")) - options.set_option("float-overflow-check", true); - else - options.set_option("float-overflow-check", false); - - // check for NaN (not a number) - if(cmdline.isset("nan-check")) - options.set_option("nan-check", true); - else - options.set_option("nan-check", false); - - // check pointers - if(cmdline.isset("pointer-check")) - options.set_option("pointer-check", true); - else - options.set_option("pointer-check", false); - - // check for memory leaks - if(cmdline.isset("memory-leak-check")) - options.set_option("memory-leak-check", true); - else - options.set_option("memory-leak-check", false); - - // check assertions - if(cmdline.isset("no-assertions")) - options.set_option("assertions", false); - else - options.set_option("assertions", true); - - // SSA equality propagation - if(cmdline.isset("ssa-propagation")) - options.set_option("ssa-propagation", true); - else - options.set_option("ssa-propagation", false); - - // use assumptions - if(cmdline.isset("no-assumptions")) - options.set_option("assumptions", false); - else - options.set_option("assumptions", true); - - // use arithmetic refinements - if(cmdline.isset("refine")) - options.set_option("refine", true); - else - options.set_option("refine", false); - - if(cmdline.isset("unit-check")) - options.set_option("unit-check", true); - else - options.set_option("unit-check", false); - - // compute standard invariants (include value at loop entry) - if(cmdline.isset("std-invariants")) - options.set_option("std-invariants", true); - else - options.set_option("std-invariants", false); - - // magic error label - if(cmdline.isset("error-label")) - options.set_option("error-label", cmdline.get_value("error-label")); - - if(cmdline.isset("havoc")) - options.set_option("havoc", true); - else if(cmdline.isset("equalities")) - { - options.set_option("equalities", true); - options.set_option("std-invariants", true); - } - else - { - if(cmdline.isset("zones")) - options.set_option("zones", true); - else if(cmdline.isset("qzones")) - options.set_option("qzones", true); - else if(cmdline.isset("octagons")) - options.set_option("octagons", true); - else // if(cmdline.isset("intervals")) // default - options.set_option("intervals", true); - - if(cmdline.isset("enum-solver")) - options.set_option("enum-solver", true); - else // if(cmdline.isset("binsearch-solver")) // default - options.set_option("binsearch-solver", true); - } - - // use incremental assertion checks - if(cmdline.isset("non-incremental")) - options.set_option("incremental", false); - else - options.set_option("incremental", true); - - // compute preconditions - if(cmdline.isset("preconditions")) - options.set_option("preconditions", true); - - // compute necessary/sufficient preconditions - if(cmdline.isset("sufficient")) - options.set_option("sufficient", true); - - // compute ranking functions - if(cmdline.isset("termination")) - { - options.set_option("termination", true); - options.set_option("sufficient", true); - options.set_option("std-invariants", true); - } - - if(cmdline.isset("monolithic-ranking-function")) - { - options.set_option("monolithic-ranking-function", true); - } - else options.set_option("monolithic-ranking-function", false); - - if(cmdline.isset("lexicographic-ranking-function")) - { - options.set_option("lexicographic-ranking-function", - cmdline.get_value("lexicographic-ranking-function")); - } - else options.set_option("lexicographic-ranking-function", 3); - - if(cmdline.isset("max-inner-ranking-iterations")) - { - options.set_option("max-inner-ranking-iterations", - cmdline.get_value("max-inner-ranking-iterations")); - } - else options.set_option("max-inner-ranking-iterations", 20); - - // do k-induction refinement - if(cmdline.isset("k-induction")) - { - options.set_option("std-invariants", true); - options.set_option("k-induction", true); -// options.set_option("inline", true); - if(!cmdline.isset("unwind")) - options.set_option("unwind", UINT_MAX); - } - - // do incremental bmc - if(cmdline.isset("incremental-bmc")) - { - options.set_option("incremental-bmc", true); -// options.set_option("inline", true); - options.set_option("havoc", true); - if(!cmdline.isset("unwind")) - options.set_option("unwind", UINT_MAX); - } - - // check for spuriousness of assertion failures - if(cmdline.isset("no-spurious-check")) - options.set_option("spurious-check", false); - else - options.set_option("spurious-check", true); - - // all properties (default) - if(cmdline.isset("no-all-properties")) - options.set_option("all-properties", false); - else - options.set_option("all-properties", true); - - // no all functions (default) - if(cmdline.isset("all-functions")) - options.set_option("all-functions", true); - else - options.set_option("all-functions", false); - - // competition mode - if(cmdline.isset("competition-mode")) - { - options.set_option("competition-mode", true); - options.set_option("all-properties", false); - } - - // instrumentation / output - if(cmdline.isset("instrument-output")) - options.set_option("instrument-output", - cmdline.get_value("instrument-output")); - - -#ifdef SHOW_CALLING_CONTEXTS - if(cmdline.isset("show-calling-contexts")) - { - if(!options.get_bool_option("intervals")) - throw "--show-calling-contexts only possible with --intervals"; - options.set_option("show-calling-contexts", true); - options.set_option("do-not-analyze-functions", - cmdline.get_value("show-calling-contexts")); - } -#endif - - if(cmdline.isset("show-trace")) - options.set_option("show-trace", true); - if(cmdline.isset("graphml-cex")) - options.set_option("graphml-cex", cmdline.get_value("graphml-cex")); - if(cmdline.isset("json-cex")) - options.set_option("json-cex", cmdline.get_value("json-cex")); -} - -/*******************************************************************\ - -Function: summarizer_parse_optionst::doit - - Inputs: - - Outputs: - - Purpose: invoke main modules - -\*******************************************************************/ - -int summarizer_parse_optionst::doit() -{ - if(cmdline.isset("version")) - { - std::cout << SUMMARIZER_VERSION " (based on CBMC " CBMC_VERSION ")" << std::endl; - return 0; - } - - // - // command line options - // - - optionst options; - get_command_line_options(options); - - eval_verbosity(); - - // - // Print a banner - // -(??) status() << "2LS version " SUMMARIZER_VERSION " (based on CBMC " CBMC_VERSION ")" << eom; -(??) -(??) register_language(new_ansi_c_language); -(??) register_language(new_cpp_language); -(??) - goto_modelt goto_model; - - register_languages(); - - if(get_goto_program(options, goto_model)) - return 6; - - if(cmdline.isset("show-stats")) - { - show_stats(goto_model, std::cout); - return 7; - } - - // options for various debug outputs - - if(cmdline.isset("show-ssa")) - { - bool simplify=!cmdline.isset("no-simplify"); - irep_idt function=cmdline.get_value("function"); - show_ssa(goto_model, function, simplify, std::cout, ui_message_handler); - return 7; - } - - if(cmdline.isset("show-fixed-points")) - { - bool simplify=!cmdline.isset("no-simplify"); - irep_idt function=cmdline.get_value("function"); - show_fixed_points(goto_model, function, simplify, std::cout, ui_message_handler); - return 7; - } - - if(cmdline.isset("show-defs")) - { - irep_idt function=cmdline.get_value("function"); - show_defs(goto_model, function, std::cout, ui_message_handler); - return 7; - } - - if(cmdline.isset("show-assignments")) - { - irep_idt function=cmdline.get_value("function"); - show_assignments(goto_model, function, std::cout, ui_message_handler); - return 7; - } - - if(cmdline.isset("show-guards")) - { - irep_idt function=cmdline.get_value("function"); - show_guards(goto_model, function, std::cout, ui_message_handler); - return 7; - } - - if(cmdline.isset("show-value-sets")) - { - irep_idt function=cmdline.get_value("function"); - show_value_sets(goto_model, function, std::cout, ui_message_handler); - return 7; - } - - if(cmdline.isset("show-invariants")) - { - options.set_option("show-invariants", true); - } - - if(cmdline.isset("context-sensitive")) - { - options.set_option("context-sensitive", true); - status() << "Context-sensitive analysis from " << - goto_model.goto_functions.entry_point() << eom; - } - - if(cmdline.isset("arrays")) - { - options.set_option("arrays", true); - status() << "Do not ignore array contents" << eom; - } - - // TODO: check option inconsistencies, ignored options etc - if(options.get_bool_option("havoc")) - status() << "Havocking loops and function calls" << eom; - else if(options.get_bool_option("equalities")) - status() << "Using (dis)equalities domain" << eom; - else - { - if(options.get_bool_option("intervals")) - status() << "Using intervals domain"; - else if(options.get_bool_option("zones")) - status() << "Using zones domain"; - else if(options.get_bool_option("octagons")) - status() << "Using octagons domain"; - else assert(false); - if(options.get_bool_option("enum-solver")) - status() << " with enumeration solver"; - else if(options.get_bool_option("binsearch-solver")) - status() << " with binary search solver"; - else assert(false); - status() << eom; - } - - try - { - summary_checker_baset *summary_checker=NULL; - if(!options.get_bool_option("k-induction") && - !options.get_bool_option("incremental-bmc")) - summary_checker=new summary_checker_ait(options); - if(options.get_bool_option("k-induction") && - !options.get_bool_option("incremental-bmc")) - summary_checker=new summary_checker_kindt(options); - if(!options.get_bool_option("k-induction") && - options.get_bool_option("incremental-bmc")) - summary_checker=new summary_checker_bmct(options); - - summary_checker->set_message_handler(get_message_handler()); - summary_checker->simplify=!cmdline.isset("no-simplify"); - summary_checker->fixed_point=!cmdline.isset("no-fixed-point"); - - int retval; - if(cmdline.isset("show-vcc")) - { - std::cout << "VERIFICATION CONDITIONS:\n\n"; - summary_checker->show_vcc=true; - (*summary_checker)(goto_model); - delete summary_checker; - return 0; - } - - if(cmdline.isset("horn-encoding")) - { - status() << "Horn-clause encoding" << eom; - namespacet ns(symbol_table); - - std::string out_file=cmdline.get_value("horn-encoding"); - - if(out_file=="-") - { - horn_encoding(goto_model, std::cout); - } - else - { -#ifdef _MSC_VER - std::ofstream out(widen(out_file).c_str()); -#else - std::ofstream out(out_file.c_str()); -#endif - - if(!out) - { - error() << "Failed to open output file " - << out_file << eom; - delete summary_checker; - return 1; - } - - horn_encoding(goto_model, out); - } - - delete summary_checker; - return 0; - } - - bool report_assertions= - !options.get_bool_option("preconditions") && - !options.get_bool_option("termination"); - // do actual analysis - switch((*summary_checker)(goto_model)) - { - case property_checkert::PASS: - if(report_assertions) - report_properties(options, goto_model, summary_checker->property_map); - report_success(); - retval=0; - break; - - case property_checkert::FAIL: - if(report_assertions) - report_properties(options, goto_model, summary_checker->property_map); - report_failure(); - retval=10; - break; - - case property_checkert::UNKNOWN: - if(report_assertions) - report_properties(options, goto_model, summary_checker->property_map); - retval=5; - if(options.get_bool_option("preconditions")) - goto clean_up; - report_properties(goto_model, summary_checker->property_map); - report_unknown(); - break; - - default: - assert(false); - } - - if(cmdline.isset("instrument-output")) - { - summary_checker->instrument_and_output(goto_model); - } - - clean_up: - delete summary_checker; - return retval; - } - - catch(const std::string error_msg) - { - error() << error_msg << messaget::eom; - return 8; - } - - catch(const char *error_msg) - { - error() << error_msg << messaget::eom; - return 8; - } - -#if 0 - // let's log some more statistics - debug() << "Memory consumption:" << messaget::endl; - memory_info(debug()); - debug() << eom; -#endif -} - - - -void summarizer_parse_optionst::type_stats_rec( - const typet &type, - expr_statst &stats, - const namespacet &ns) -{ - - if(type.id()==ID_symbol) - type_stats_rec(ns.follow(type), stats, ns); - - if(type.id()==ID_pointer || type.id()==ID_array) - { - stats.has_array=true; - - const typet &subtype=ns.follow(type.subtype()); - - if(subtype.id()==ID_signedbv || - subtype.id()==ID_unsignedbv) - { - stats.has_string=(to_bitvector_type(subtype).get_width()==config.ansi_c.char_width); - } - } - - if(type.has_subtypes()) - { - forall_subtypes(it, type) - { - type_stats_rec(*it, stats, ns); - } - } -} - - -/*******************************************************************\ - -Function: summarizer_parse_optionst::expr_stats_rec - - Inputs: - - Outputs: - - Purpose: - -\*******************************************************************/ - - -void summarizer_parse_optionst::expr_stats_rec( - const exprt &expr, - expr_statst &stats) -{ - - if(expr.id()==ID_side_effect) - { - const side_effect_exprt &side_effect_expr=to_side_effect_expr(expr); - const irep_idt &statement=side_effect_expr.get_statement(); - - if(statement==ID_malloc) - { - stats.has_malloc=true; - } - else if(statement==ID_nondet) - { - // done in statet:instantiate_rec - } - } - - if(expr.id()==ID_symbol ) - { - - } - - if(expr.has_operands()) - { - forall_operands(it, expr) - { - expr_stats_rec(*it, stats); - } - } -} - - -/*******************************************************************\ - -Function: summarizer_parse_optionst::show_stats - - Inputs: - - Outputs: - - Purpose: - -\*******************************************************************/ - -void summarizer_parse_optionst::show_stats(const goto_modelt &goto_model, - std::ostream &out) -{ - - const namespacet ns(goto_model.symbol_table); - - expr_statst stats; - - unsigned nr_instructions=0; - unsigned nr_functions=0; - unsigned nr_loops=0; - - // analyze all the functions - forall_goto_functions(f_it, goto_model.goto_functions) - { - if(!f_it->second.body_available()) continue; - - ++nr_functions; - - const goto_programt &goto_program=f_it->second.body; - -#if 0 - statistics() << "function size of " << f_it->first << ": " - << goto_program.instructions.size() << eom; -#endif - - for(goto_programt::instructionst::const_iterator - i_it=goto_program.instructions.begin(); - i_it!=goto_program.instructions.end(); - i_it++) - { - nr_instructions++; - const goto_programt::instructiont &instruction=*i_it; - - if(i_it->is_backwards_goto()) nr_loops++; - - switch(instruction.type) - { - case ASSIGN: - { - const code_assignt &assign=to_code_assign(instruction.code); - expr_stats_rec(assign.lhs(), stats); - expr_stats_rec(assign.rhs(), stats); - } - break; - case ASSUME: - expr_stats_rec(instruction.guard, stats); - break; - case ASSERT: - expr_stats_rec(instruction.guard, stats); - break; - case GOTO: - expr_stats_rec(instruction.guard, stats); - break; - - case DECL: - // someone declaring an array - type_stats_rec(to_code_decl(instruction.code).symbol().type(), stats, ns); - - break; - - default: - // skip - break; - } // switch - } // forall instructions - } // forall functions - - out << "=============== STATS=============== " << std::endl; - out << " nr of instructions: " << nr_instructions << std::endl; - out << " nr of functions: " << nr_functions << std::endl; - out << " nr of loops: " << nr_loops << std::endl; - out << " malloc: " << (stats.has_malloc ? "YES" : "NO") << std::endl; - out << " arrays: " << (stats.has_array ? "YES" : "NO") << std::endl; - out << " strings: " << (stats.has_string ? "YES" : "NO") << std::endl; -} - - -/*******************************************************************\ - -Function: summarizer_parse_optionst::set_properties - - Inputs: - - Outputs: - - Purpose: - -\*******************************************************************/ - -bool summarizer_parse_optionst::set_properties(goto_modelt &goto_model) -{ - try - { - if(cmdline.isset("property")) - ::set_properties(goto_model, cmdline.get_values("property")); - } - - catch(const char *e) - { - error() << e << eom; - return true; - } - - catch(const std::string e) - { - error() << e << eom; - return true; - } - - catch(int) - { - return true; - } - - return false; -} - -/*******************************************************************\ - -Function: summarizer_parse_optionst::require_entry - - Inputs: - - Outputs: - - Purpose: - -\*******************************************************************/ - -void summarizer_parse_optionst::require_entry( - const goto_modelt &goto_model) -{ - irep_idt entry_point=goto_model.goto_functions.entry_point(); - - if(goto_model.symbol_table.symbols.find(entry_point)==symbol_table.symbols.end()) - throw "The program has no entry point; please complete linking"; -} - -/*******************************************************************\ - -Function: summarizer_parse_optionst::get_goto_program - - Inputs: - - Outputs: - - Purpose: - -\*******************************************************************/ - -bool summarizer_parse_optionst::get_goto_program( - const optionst &options, - goto_modelt &goto_model) -{ - if(cmdline.args.size()==0) - { - error() << "Please provide a program to verify" << eom; - return true; - } - - try - { - if(cmdline.args.size()==1 && - is_goto_binary(cmdline.args[0])) - { - status() << "Reading GOTO program from file" << eom; - - if(read_goto_binary(cmdline.args[0], - goto_model, get_message_handler())) - return true; - - config.set_from_symbol_table(goto_model.symbol_table); - - if(cmdline.isset("show-symbol-table")) - { - show_symbol_table(); - return true; - } - - irep_idt entry_point=goto_model.goto_functions.entry_point(); - - if(goto_model.symbol_table.symbols.find(entry_point)==symbol_table.symbols.end()) - { - error() << "The goto binary has no entry point; please complete linking" << eom; - return true; - } - } - else if(cmdline.isset("show-parse-tree")) - { - if(cmdline.args.size()!=1) - { - error() << "Please give one source file only" << eom; - return true; - } - - std::string filename=cmdline.args[0]; - -#ifdef _MSC_VER - std::ifstream infile(widen(filename).c_str()); -#else - std::ifstream infile(filename.c_str()); -#endif - - if(!infile) - { - error() << "failed to open input file `" << filename << "'" << eom; - return true; - } - - languaget *language=get_language_from_filename(filename); - - if(language==NULL) - { - error() << "failed to figure out type of file `" << filename << "'" << eom; - return true; - } - - language->set_message_handler(get_message_handler()); - - status("Parsing", filename); - - if(language->parse(infile, filename)) - { - error() << "PARSING ERROR" << eom; - return true; - } - - language->show_parse(std::cout); - return true; - } - else - { - - if(parse()) return true; - if(typecheck()) return true; - if(final()) return true; - - // we no longer need any parse trees or language files - clear_parse(); - - if(cmdline.isset("show-symbol-table")) - { - show_symbol_table(); - return true; - } - -#if 0 - irep_idt entry_point=goto_model.goto_functions.entry_point(); - - if(symbol_table.symbols.find(entry_point)==symbol_table.symbols.end()) - { - error() << "No entry point; please provide a main function" << eom; - return true; - } -#endif - - status() << "Generating GOTO Program" << eom; - - goto_convert(symbol_table, goto_model, ui_message_handler); - } - - // finally add the library - status() << "Adding CPROVER library" << eom; - link_to_library(goto_model, ui_message_handler); - - if(process_goto_program(options, goto_model)) - return true; - } - - catch(const char *e) - { - error() << e << eom; - return true; - } - - catch(const std::string e) - { - error() << e << eom; - return true; - } - - catch(int) - { - return true; - } - - catch(std::bad_alloc) - { - error() << "Out of memory" << eom; - return true; - } - - return false; -} - -/*******************************************************************\ - -Function: summarizer_parse_optionst::process_goto_program - - Inputs: - - Outputs: - - Purpose: - -\*******************************************************************/ - -bool summarizer_parse_optionst::process_goto_program( - const optionst &options, - goto_modelt &goto_model) -{ - try - { - // do partial inlining - if(options.get_bool_option("inline-partial")) - { - unsigned limit=options.get_unsigned_int_option("inline-partial"); - status() << "Performing partial inlining (" << limit << ")" << eom; - goto_partial_inline(goto_model, ui_message_handler, limit/2); - // TODO: where is limit multiplied by 2??? - - // remove inlined functions - Forall_goto_functions(f_it, goto_model.goto_functions) - if(f_it->first!=ID__start && - f_it->second.body.instructions.size()<=2*(limit/2)) - { - f_it->second.body.clear(); - } - } - - // add generic checks - status() << "Generic Property Instrumentation" << eom; - goto_check(options, goto_model); - - status() << "Function Pointer Removal" << eom; - remove_function_pointers( - goto_model, cmdline.isset("pointer-check")); - - // remove returns (must be done after function pointer removal) - remove_returns(goto_model); - - -#if UNWIND_GOTO_INTO_LOOP - unwind_goto_into_loop(goto_model, 2); -#endif - - remove_skip(goto_model.goto_functions); - goto_model.goto_functions.update(); - - // now do full inlining, if requested - if(options.get_bool_option("inline")) - { - status() << "Performing full inlining" << eom; - if(goto_inline(goto_model, ui_message_handler)) - { - report_unknown(); - return 5; - } - } - - // preprocessing to improve the structure of the SSA for the unwinder - split_loopheads(goto_model); - - // explicitly initialize all local variables - nondet_locals(goto_model); - -#if 1 - // TODO: find a better place for that - replace_malloc(goto_model, ""); -#endif - -#if REMOVE_MULTIPLE_DEREFERENCES - remove_multiple_dereferences(goto_model); -#endif - - // recalculate numbers, etc. - goto_model.goto_functions.update(); - - // add loop ids - goto_model.goto_functions.compute_loop_numbers(); - - // inline __CPROVER_initialize and main - if(cmdline.isset("inline-main")) - { - inline_main(goto_model); - } - - if(!cmdline.isset("no-propagation")) - { - status() << "Constant Propagation" << eom; - propagate_constants(goto_model); - } - - // if we aim to cover, replace - // all assertions by false to prevent simplification - if(cmdline.isset("cover-assertions")) - make_assertions_false(goto_model); - - // show it? - if(cmdline.isset("show-loops")) - { - show_loop_ids(get_ui(), goto_model); - return true; - } - - // do array abstraction - if(cmdline.isset("array-abstraction")) - { - status() << "Performing array abstraction" << eom; - array_abstraction(goto_model.symbol_table, ui_message_handler, - goto_model.goto_functions); - } - - label_properties(goto_model); - - if(cmdline.isset("show-properties")) - { - show_properties(goto_model, get_ui()); - return true; - } - - if(set_properties(goto_model)) - return true; - - // show it? - if(cmdline.isset("show-goto-functions")) - { - const namespacet ns(goto_model.symbol_table); - goto_model.goto_functions.output(ns, std::cout); - return true; - } - } - - catch(const char *e) - { - error() << e << eom; - return true; - } - - catch(const std::string e) - { - error() << e << eom; - return true; - } - - catch(int) - { - return true; - } - - catch(std::bad_alloc) - { - error() << "Out of memory" << eom; - return true; - } - - return false; -} - -/*******************************************************************\ - -Function: summarizer_parse_optionst::report_properties - - Inputs: - - Outputs: - - Purpose: - -\*******************************************************************/ - -void summarizer_parse_optionst::report_properties( - const optionst &options, - const goto_modelt &goto_model, - const property_checkert::property_mapt &property_map) -{ - for(property_checkert::property_mapt::const_iterator - it=property_map.begin(); - it!=property_map.end(); - it++) - { - if(it->first=="") // TODO: some properties do not show up in initialize_property_map - continue; - - if(get_ui()==ui_message_handlert::XML_UI) - { - xmlt xml_result("result"); - xml_result.set_attribute("property", id2string(it->first)); - xml_result.set_attribute("status", property_checkert::as_string(it->second.result)); - std::cout << xml_result << "\n"; - } - else - { - status() << "[" << it->first << "] " - << it->second.location->source_location.get_comment() - << ": " - << property_checkert::as_string(it->second.result) - << eom; - } - - if(cmdline.isset("show-trace") && - it->second.result==property_checkert::FAIL) - show_counterexample(goto_model, it->second.error_trace); - if(cmdline.isset("graphml-cex") && - it->second.result==property_checkert::FAIL) - output_graphml_cex(options, goto_model, it->second.error_trace); - if(cmdline.isset("json-cex") && - it->second.result==property_checkert::FAIL) - output_json_cex(options, - goto_model, it->second.error_trace, - id2string(it->first)); - } - - if(!cmdline.isset("property")) - { - status() << eom; - - unsigned failed=0; - unsigned unknown=0; - - for(property_checkert::property_mapt::const_iterator - it=property_map.begin(); - it!=property_map.end(); - it++) - { - if(it->second.result==property_checkert::UNKNOWN) - unknown++; - if(it->second.result==property_checkert::FAIL) - failed++; - } - - status() << "** " << unknown - << " of " << property_map.size() << " unknown" - << eom; - status() << "** " << failed - << " of " << property_map.size() << " failed" - << eom; - } -} - -/*******************************************************************\ - -Function: summarizer_parse_optionst::report_success - - Inputs: - - Outputs: - - Purpose: - -\*******************************************************************/ - -void summarizer_parse_optionst::report_success() -{ - result() << "VERIFICATION SUCCESSFUL" << eom; - - switch(get_ui()) - { - case ui_message_handlert::PLAIN: - break; - - case ui_message_handlert::XML_UI: - { - xmlt xml("cprover-status"); - xml.data="SUCCESS"; - std::cout << xml; - std::cout << std::endl; - } - break; - - default: - assert(false); - } -} - -/*******************************************************************\ - -Function: summarizer_parse_optionst::show_counterexample - - Inputs: - - Outputs: - - Purpose: - -\*******************************************************************/ - -void summarizer_parse_optionst::show_counterexample( - const goto_modelt &goto_model, - const goto_tracet &error_trace) -{ - const namespacet ns(goto_model.symbol_table); - - switch(get_ui()) - { - case ui_message_handlert::PLAIN: - std::cout << std::endl << "Counterexample:" << std::endl; - show_goto_trace(std::cout, ns, error_trace); - break; - - case ui_message_handlert::XML_UI: - { - xmlt xml; - convert(ns, error_trace, xml); - std::cout << xml << std::endl; - } - break; - - default: - assert(false); - } -} - -/*******************************************************************\ - -Function: summarizer_parse_optionst::output_graphml_cex - - Inputs: - - Outputs: - - Purpose: - -\*******************************************************************/ - -void summarizer_parse_optionst::output_graphml_cex( - const optionst &options, - const goto_modelt &goto_model, - const goto_tracet &error_trace) -{ - const namespacet ns(goto_model.symbol_table); - const std::string graphml=options.get_option("graphml-cex"); - if(!graphml.empty()) - { - graphmlt cex_graph; - convert(ns, error_trace, cex_graph); - - if(graphml=="-") - write_graphml(cex_graph, std::cout); - else - { - std::ofstream out(graphml.c_str()); - write_graphml(cex_graph, out); - } - } -} - -/*******************************************************************\ - -Function: summarizer_parse_optionst::output_json_cex - - Inputs: - - Outputs: - - Purpose: - -\*******************************************************************/ - -void summarizer_parse_optionst::output_json_cex( - const optionst &options, - const goto_modelt &goto_model, - const goto_tracet &error_trace, - const std::string &property_id) -{ - if(options.get_option("json-cex")!="") - { - const namespacet ns(goto_model.symbol_table); - jsont json_trace; - convert(ns, error_trace, json_trace); - - if(options.get_option("json-cex")=="-") - { - std::cout << json_trace; - } - else - { - std::ofstream out((options.get_option("json-cex")+"-"+property_id+".json").c_str()); - out << json_trace << '\n'; - } - } -} - -/*******************************************************************\ - -Function: summarizer_parse_optionst::report_failure - - Inputs: - - Outputs: - - Purpose: - -\*******************************************************************/ - -void summarizer_parse_optionst::report_failure() -{ - result() << "VERIFICATION FAILED" << eom; - - switch(get_ui()) - { - case ui_message_handlert::PLAIN: - break; - - case ui_message_handlert::XML_UI: - { - xmlt xml("cprover-status"); - xml.data="FAILURE"; - std::cout << xml; - std::cout << std::endl; - } - break; - - default: - assert(false); - } -} - -/*******************************************************************\ - -Function: summarizer_parse_optionst::report_unknown - - Inputs: - - Outputs: - - Purpose: - -\*******************************************************************/ - -void summarizer_parse_optionst::report_unknown() -{ - result() << "VERIFICATION INCONCLUSIVE" << eom; - - switch(get_ui()) - { - case ui_message_handlert::PLAIN: - break; - - case ui_message_handlert::XML_UI: - { - xmlt xml("cprover-status"); - xml.data="UNKNOWN"; - std::cout << xml; - std::cout << std::endl; - } - break; - - default: - assert(false); - } -} - -/*******************************************************************\ - -Function: summarizer_parse_optionst::help - - Inputs: - - Outputs: - - Purpose: display command line help - -\*******************************************************************/ - -void summarizer_parse_optionst::help() -{ - std::cout << - "\n" - "* * Summarizer " SUMMARIZER_VERSION "-Copyright (C) 2014 * *\n" - "* * (based on CBMC " CBMC_VERSION " "; - - std::cout << "(" << (sizeof(void *)*8) << "-bit version))"; - - std::cout << " * *\n"; - - std::cout << - "* * Daniel Kroening * *\n" - "* * University of Oxford * *\n" - "* * kroening@kroening.com * *\n" - "\n" - "Usage: Purpose:\n" - "\n" - " summarizer [-?] [-h] [--help] show help\n" - " summarizer file.c ... source file names\n" - "\n" - "Frontend options:\n" - " -I path set include path (C/C++)\n" - " -D macro define preprocessor macro (C/C++)\n" - " --preprocess stop after preprocessing\n" - " --16, --32, --64 set width of int\n" - " --LP64, --ILP64, --LLP64, \n" - " --ILP32, --LP32 set width of int, long and pointers\n" - " --little-endian allow little-endian word-byte conversions\n" - " --big-endian allow big-endian word-byte conversions\n" - " --unsigned-char make \"char\" unsigned by default\n" - " --show-stats show statistics about program\n" - " --show-parse-tree show parse tree\n" - " --show-symbol-table show symbol table\n" - " --show-goto-functions show goto program\n" - " --arch set architecture (default: " - << configt::this_architecture() << ")\n" - " --os set operating system (default: " - << configt::this_operating_system() << ")\n" -#ifdef _WIN32 - " --gcc use GCC as preprocessor\n" -#endif - " --no-arch don't set up an architecture\n" - " --no-library disable built-in abstract C library\n" - " --round-to-nearest IEEE floating point rounding mode (default)\n" - " --round-to-plus-inf IEEE floating point rounding mode\n" - " --round-to-minus-inf IEEE floating point rounding mode\n" - " --round-to-zero IEEE floating point rounding mode\n" - "\n" - "Program instrumentation options:\n" - " --bounds-check enable array bounds checks\n" - " --pointer-check enable pointer checks\n" - " --array-abstraction use array and string abstraction for bounds checks\n" - " --div-by-zero-check enable division by zero checks\n" - " --memory-leak-check enable memory leak checks\n" - " --signed-overflow-check enable arithmetic over- and underflow checks\n" - " --unsigned-overflow-check enable arithmetic over- and underflow checks\n" - " --nan-check check floating-point for NaN\n" - " --error-label label check that label is unreachable\n" - " --show-properties show the properties\n" - " --no-assertions ignore user assertions\n" - " --no-assumptions ignore user assumptions\n" - " --inline inline all functions into main\n" - " --inline-partial nr inline functions smaller than the given nr of instructions\n" - " --instrument-output f output inferred information in goto-binary f\n" - "\n" - "Backend options:\n" - " --all-functions check each function as entry point\n" - " --no-all-properties stop on first failing assertion\n" - " --context-sensitive context-sensitive analysis from entry point\n" - " --termination compute ranking functions to prove termination\n" - " --k-induction use k-induction\n" - " --unit-check check each function (similar to a unit test)\n" - " --incremental-bmc use incremental-bmc\n" - " --preconditions compute preconditions\n" - " --sufficient sufficient preconditions (default: necessary)\n" - " --context-sensitive context-sensitive analysis from entry point\n" - " --havoc havoc loops and function calls\n" - " --intervals use interval domain\n" - " --equalities use equalities and disequalities domain\n" - " --zones use zone domain\n" - " --octagons use octagon domain\n" - " --enum-solver use solver based on model enumeration\n" - " --binsearch-solver use solver based on binary search\n" - " --arrays do not ignore array contents\n" - " --lexicographic-ranking-function n (default n=3)\n" - " --monolithic-ranking-function\n" - " --max-inner-ranking-iterations n (default n=20)\n" - "\n" - "Other options:\n" - " --version show version and exit\n" - " --xml-ui use XML-formatted output\n" - "\n"; -} diff --git a/src/summarizer/summarizer_parse_options.h b/src/summarizer/summarizer_parse_options.h deleted file mode 100644 index 802d99ceb..000000000 --- a/src/summarizer/summarizer_parse_options.h +++ /dev/null @@ -1,145 +0,0 @@ -/*******************************************************************\ - -Module: Command Line Parsing - -Author: Daniel Kroening, kroening@kroening.com - -\*******************************************************************/ - -#ifndef CPROVER_SUMMARIZER_PARSE_OPTIONS_H -#define CPROVER_SUMMARIZER_PARSE_OPTIONS_H - -#include -#include - -#include - -#include - -class goto_modelt; -class optionst; - -#include "summary_checker_base.h" - -#define SUMMARIZER_OPTIONS \ - "(xml-ui)" \ - "(function):" \ - "D:I:" \ - "(depth):(context-bound):(unwind):" \ - "(bounds-check)(pointer-check)(div-by-zero-check)(memory-leak-check)" \ - "(signed-overflow-check)(unsigned-overflow-check)" \ - "(float-overflow-check)(nan-check)" \ - "(array-abstraction)(refine)" \ - "(non-incremental)" \ - "(no-assertions)(no-assumptions)" \ - "(16)(32)(64)(LP64)(ILP64)(LLP64)(ILP32)(LP32)" \ - "(little-endian)(big-endian)" \ - "(error-label):(verbosity):(no-library)" \ - "(version)" \ - "(i386-linux)(i386-macos)(i386-win32)(win32)(winx64)(gcc)" \ - "(ppc-macos)(unsigned-char)" \ - "(havoc)(intervals)(zones)(octagons)(equalities)(qzones)"\ - "(enum-solver)(binsearch-solver)(arrays)"\ - "(string-abstraction)(no-arch)(arch):(floatbv)(fixedbv)" \ - "(round-to-nearest)(round-to-plus-inf)(round-to-minus-inf)(round-to-zero)" \ - "(inline)(inline-main)(inline-partial):" \ - "(context-sensitive)" \ - "(preconditions)(sufficient)" \ - "(instrument-output):" \ - "(show-locs)(show-vcc)(show-properties)(show-trace)(show-fixed-points)(show-stats)" \ - "(show-goto-functions)(show-guards)(show-defs)(show-ssa)(show-assignments)(show-dep-graphs)" \ - "(show-value-sets)" \ - "(show-invariants)(std-invariants)" \ - "(show-calling-contexts):" \ - "(property):(all-properties)(k-induction)(incremental-bmc)" \ - "(no-simplify)(no-fixed-point)" \ - "(no-spurious-check)(no-all-properties)(unit-check)" \ - "(spurious-check):" \ - "(competition-mode)(slice)" \ - "(no-unwinding-assertions)(no-propagation)(ssa-propagation)" - // the last line is for CBMC-regression testing only - -class summarizer_parse_optionst: - public parse_options_baset, - public language_uit -{ -public: - virtual int doit(); - virtual void help(); - - summarizer_parse_optionst(int argc, const char **argv); - summarizer_parse_optionst( - int argc, - const char **argv, - const std::string &extra_options); - -protected: - ui_message_handlert ui_message_handler; - virtual void register_languages(); - - void get_command_line_options(optionst &options); - - bool get_goto_program( - const optionst &options, - goto_modelt &goto_model); - - bool process_goto_program( - const optionst &options, - goto_modelt &goto_model); - - bool set_properties(goto_modelt &); - - void report_success(); - void report_failure(); - - void report_properties( - const goto_modelt &, - const summary_checker_baset::property_mapt &); - - void show_counterexample( - const goto_modelt &, - const class goto_tracet &); - - struct expr_statst { - bool has_malloc; - bool has_string; - bool has_array; - bool has_pointer; - - expr_statst() - : has_malloc(false) - , has_string(false) - , has_array(false) - , has_pointer(false) - {} - }; - - void type_stats_rec( - const typet &type, - expr_statst &stats, - const namespacet &ns); - - void expr_stats_rec( - const exprt &expr, - expr_statst &stats); - - void show_stats( - const goto_modelt &, - std::ostream &); - - void eval_verbosity(); - void report_unknown(); - - // diverse preprocessing - void inline_main(goto_modelt &goto_model); - void propagate_constants(goto_modelt &goto_model); - void nondet_locals(goto_modelt &goto_model); - void unwind_goto_into_loop(goto_modelt &goto_model, unsigned k); - void replace_types_rec(const replace_symbolt &replace_const, exprt &expr); - exprt evaluate_casts_in_constants(const exprt &expr, const typet& parent_type, - bool &valid); - void remove_multiple_dereferences(goto_modelt &goto_model); - void remove_multiple_dereferences(goto_modelt &goto_model, goto_programt &body, goto_programt::targett t, exprt &expr, unsigned &var_counter, bool deref_seen); -}; - -#endif diff --git a/src/summarizer/summary_checker_ai.cpp b/src/summarizer/summary_checker_ai.cpp deleted file mode 100644 index 1777d986c..000000000 --- a/src/summarizer/summary_checker_ai.cpp +++ /dev/null @@ -1,217 +0,0 @@ -/*******************************************************************\ - -Module: Summary Checker for AI - -Author: Peter Schrammel - -\*******************************************************************/ - -#include - -#include "summary_checker_ai.h" - -/*******************************************************************\ - -Function: summary_checker_ait::operator() - - Inputs: - - Outputs: - - Purpose: - -\*******************************************************************/ - -property_checkert::resultt summary_checker_ait::operator()( - const goto_modelt &goto_model) -{ - const namespacet ns(goto_model.symbol_table); - - SSA_functions(goto_model, ns); - - ssa_unwinder.init(false, false); - - unsigned unwind=options.get_unsigned_int_option("unwind"); - if(unwind>0) - { - status() << "Unwinding" << messaget::eom; - - ssa_unwinder.init_localunwinders(); - - ssa_unwinder.unwind_all(unwind+1); - ssa_unwinder.output(debug()); debug() < 0){ - forall_goto_functions(f_it, goto_model.goto_functions){ - if(!f_it->second.body_available()) continue; - if(has_prefix(id2string(f_it->first), TEMPLATE_DECL)) continue; - local_SSAt &SSA=ssa_db.get(f_it->first); - std::cout << "==>> Output SSA for function: " << f_it->first << "\n"; - SSA.output(std::cout); - } - } - else{ - ssa_unwinder.init_localunwinders(); // possibly required; - - // iterate over the SSA to unwind loops - forall_goto_functions(f_it, goto_model.goto_functions){ - - if(!f_it->second.body_available()) continue; - if(has_prefix(id2string(f_it->first), TEMPLATE_DECL)) continue; - - local_SSAt &SSA=ssa_db.get(f_it->first); - for(local_SSAt::nodest::const_iterator n_it=SSA.nodes.begin(); - n_it!=SSA.nodes.end(); n_it++){ - if(n_it->loophead!=SSA.nodes.end()){ - std::cout << "==>> unwinding loop with location number: " - << n_it->loophead->location->location_number << "\n"; - ssa_unwinder.unwind_loop_alone(f_it->first, - n_it->loophead->location->location_number, 1); - } - } - } - - forall_goto_functions(f_it, goto_model.goto_functions){ - if(!f_it->second.body_available()) continue; - if(has_prefix(id2string(f_it->first), TEMPLATE_DECL)) continue; - local_SSAt &SSA=ssa_db.get(f_it->first); - std::cout << "==>> Output SSA for function: " << f_it->first << "\n"; - SSA.output(std::cout); - } - - } - /**/ - /*********************************************************************************/ -#endif - - irep_idt entry_function=goto_model.goto_functions.entry_point(); - if(options.get_bool_option("unit-check")) - entry_function=""; - - if(!(options.get_bool_option("inline"))) - { - if((options.get_option("spurious-check")!="concrete") && - (options.get_option("spurious-check")!="abstract")) - { - SSA_dependency_graphs(goto_model, ns); - } - } - - // properties - initialize_property_map(goto_model.goto_functions); - - bool preconditions=options.get_bool_option("preconditions"); - bool termination=options.get_bool_option("termination"); - if(!options.get_bool_option("havoc")) - { - // forward analysis - summarize(goto_model, true, termination); - } - if(!options.get_bool_option("havoc") && preconditions) - { - // backward analysis - summarize(goto_model, false, termination); - } - - if(preconditions) - { - report_statistics(); - report_preconditions(); - return property_checkert::UNKNOWN; - } - - if(termination) - { - report_statistics(); - return report_termination(); - } - -#ifdef SHOW_CALLINGCONTEXTS - if(options.get_bool_option("show-calling-contexts")) - return property_checkert::UNKNOWN; -#endif - -/* - irep_idt entry_function=goto_model.goto_functions.entry_point(); - if(options.get_bool_option("unit-check")) - entry_function=""; -*/ - - std::set seen_function_calls; - property_checkert::resultt result= check_properties(entry_function, entry_function, seen_function_calls, false); - report_statistics(); - return result; -} - - -/*******************************************************************\ - -Function: summary_checker_ait::report_preconditions - - Inputs: - - Outputs: - - Purpose: - -\*******************************************************************/ - -void summary_checker_ait::report_preconditions() -{ - result() << eom; - result() << "** " << (options.get_bool_option("sufficient") ? - "Sufficient" : "Necessary") - << " preconditions: " << eom; - ssa_dbt::functionst &functions=ssa_db.functions(); - for(ssa_dbt::functionst::iterator it=functions.begin(); - it!=functions.end(); it++) - { - exprt precondition; - bool computed=summary_db.exists(it->first); - if(computed) precondition=summary_db.get(it->first).bw_precondition; - if(precondition.is_nil()) computed=false; - result() << eom << "[" << it->first << "]: " - << (!computed ? "not computed" : - from_expr(it->second->ns, "", precondition)) << eom; - } -} - -/*******************************************************************\ - -Function: summary_checker_ait::report_termination - - Inputs: - - Outputs: - - Purpose: - -\*******************************************************************/ - -property_checkert::resultt summary_checker_ait::report_termination() -{ - result() << eom; - result() << "** Termination: " << eom; - bool all_terminate=true; - bool one_nonterminate=false; - ssa_dbt::functionst &functions=ssa_db.functions(); - for(ssa_dbt::functionst::iterator it=functions.begin(); - it!=functions.end(); it++) - { - threevalt terminates=YES; - bool computed=summary_db.exists(it->first); - if(computed) terminates=summary_db.get(it->first).terminates; - all_terminate=all_terminate && (terminates==YES); - one_nonterminate=one_nonterminate || (terminates==NO); - result() << "[" << it->first << "]: " - << (!computed ? "not computed" : threeval2string(terminates)) << eom; - } - if(all_terminate) return property_checkert::PASS; - if(one_nonterminate) return property_checkert::FAIL; - return property_checkert::UNKNOWN; -} diff --git a/src/summarizer/summary_checker_ai.h b/src/summarizer/summary_checker_ai.h deleted file mode 100644 index 2a9bc7eb5..000000000 --- a/src/summarizer/summary_checker_ai.h +++ /dev/null @@ -1,29 +0,0 @@ -/*******************************************************************\ - -Module: Summary Checker for AI - -Author: Peter Schrammel - -\*******************************************************************/ - -#ifndef CPROVER_SUMMARY_CHECKER_AI_H -#define CPROVER_SUMMARY_CHECKER_AI_H - -#include "summary_checker_base.h" - -class summary_checker_ait:public summary_checker_baset -{ -public: - inline summary_checker_ait(optionst &_options): - summary_checker_baset(_options) - { - } - - virtual resultt operator()(const goto_modelt &); - -protected: - void report_preconditions(); - -}; - -#endif diff --git a/src/summarizer/summary_checker_base.cpp b/src/summarizer/summary_checker_base.cpp deleted file mode 100644 index 6e10ab1bf..000000000 --- a/src/summarizer/summary_checker_base.cpp +++ /dev/null @@ -1,690 +0,0 @@ -/*******************************************************************\ - -Module: Summarizer Checker Base - -Author: Peter Schrammel - -\*******************************************************************/ - -#include - -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "../ssa/local_ssa.h" -#include "../ssa/simplify_ssa.h" -#include "../ssa/ssa_build_goto_trace.h" -#include "../domains/ssa_analyzer.h" -#include "../ssa/ssa_unwinder.h" -#include "../ssa/ssa_const_propagator.h" -#include - -#include "show.h" -#include "instrument_goto.h" - -#include "summary_checker_base.h" -#include "summarizer_bw_cex.h" -#include "summarizer_bw_cex_concrete.h" -#include "summarizer_bw_cex_ai.h" -#include "summarizer_bw_cex_complete.h" -#include "summarizer_bw_cex_wp.h" -#include "summarizer_bw_cex_all.h" - -#include "summarizer_fw.h" -#include "summarizer_fw_term.h" -#include "summarizer_bw.h" -#include "summarizer_bw_term.h" - -#ifdef SHOW_CALLING_CONTEXTS -#include "summarizer_fw_contexts.h" -#endif - - -/*******************************************************************\ - -Function: summary_checker_baset::SSA_dependency_graphs - - Inputs: - - Outputs: - - Purpose: - -\*******************************************************************/ - -void summary_checker_baset::SSA_dependency_graphs( - const goto_modelt &goto_model, - const namespacet &ns) -{ - // compute dependency graph for all the functions - forall_goto_functions(f_it, goto_model.goto_functions) - { - if(!f_it->second.body_available()) continue; - if(has_prefix(id2string(f_it->first), TEMPLATE_DECL)) continue; - - status() << "Computing dependency graph of " << f_it->first << messaget::eom; - - // ssa_db.depgraph_create(f_it->first, ns, ssa_inliner); - - if(entry_function==f_it->first) - ssa_db.depgraph_create(f_it->first, ns, ssa_inliner, true); - else - ssa_db.depgraph_create(f_it->first, ns, ssa_inliner, false); // change to true if all functions are to be treated equal - -#if 0 - ssa_dependency_grapht &ssa_depgraph=ssa_db.get_depgraph(f_it->first); - ssa_depgraph.output(debug()); debug() << eom; - std::cout << "output SSA for function: " << f_it->first << "\n"; - ssa_db.get(f_it->first).output_verbose(std::cout); -#endif - } -} - -/*******************************************************************\ - -Function: summary_checker_baset::SSA_functions - - Inputs: - - Outputs: - - Purpose: - -\*******************************************************************/ - -void summary_checker_baset::SSA_functions(const goto_modelt &goto_model, const namespacet &ns) -{ - entry_function=goto_model.goto_functions.entry_point(); - - // compute SSA for all the functions - forall_goto_functions(f_it, goto_model.goto_functions) - { - if(!f_it->second.body_available()) continue; - if(has_prefix(id2string(f_it->first), TEMPLATE_DECL)) continue; - status() << "Computing SSA of " << f_it->first << messaget::eom; - - ssa_db.create(f_it->first, f_it->second, ns); - local_SSAt &SSA=ssa_db.get(f_it->first); - - // simplify, if requested - if(simplify) - { - status() << "Simplifying" << messaget::eom; - ::simplify(SSA, ns); - } - - // SSA.output_verbose(std::cout); - - // SSA.output(debug()); debug() << eom; - } - - // properties - initialize_property_map(goto_model.goto_functions); -} - -/*******************************************************************\ - -Function: summary_checker_baset::summarize - - Inputs: - - Outputs: - - Purpose: - -\*******************************************************************/ - -void summary_checker_baset::summarize(const goto_modelt &goto_model, - bool forward, - bool termination) -{ - summarizer_baset *summarizer=NULL; - -#ifdef SHOW_CALLING_CONTEXTS - if(options.get_bool_option("show-calling-contexts")) - summarizer=new summarizer_fw_contextst( - options, summary_db, ssa_db, ssa_unwinder, ssa_inliner); - else -#endif - { - if(forward && !termination) - summarizer=new summarizer_fwt( - options, summary_db, ssa_db, ssa_unwinder, ssa_inliner); - if(forward && termination) - summarizer=new summarizer_fw_termt( - options, summary_db, ssa_db, ssa_unwinder, ssa_inliner); - if(!forward && !termination) - summarizer=new summarizer_bwt( - options, summary_db, ssa_db, ssa_unwinder, ssa_inliner); - if(!forward && termination) - summarizer=new summarizer_bw_termt( - options, summary_db, ssa_db, ssa_unwinder, ssa_inliner); - } - assert(summarizer!=NULL); - - summarizer->set_message_handler(get_message_handler()); - - if(!options.get_bool_option("context-sensitive")) - summarizer->summarize(); - else - summarizer->summarize(entry_function); - - // statistics - solver_instances+=summarizer->get_number_of_solver_instances(); - solver_calls+=summarizer->get_number_of_solver_calls(); - summaries_used+=summarizer->get_number_of_summaries_used(); - - delete summarizer; -} - -/*******************************************************************\ - -Function: summary_checker_baset::check_properties - - Inputs: function_name!=nil - checks all functions in the call graph from the entry point - else - checks all functions - - Outputs: - - Purpose: - -\*******************************************************************/ -summary_checker_baset::resultt summary_checker_baset::check_properties() -{ - std::set seen_function_calls; - return check_properties("", "", seen_function_calls, false); -} - -summary_checker_baset::resultt summary_checker_baset::check_properties( - irep_idt function_name, - irep_idt entry_function, - std::set seen_function_calls, - bool is_inlined) -{ - if(function_name!="") - { - ssa_dbt::functionst::const_iterator f_it= - ssa_db.functions().find(function_name); - assert(f_it!=ssa_db.functions().end()); - local_SSAt &SSA=*f_it->second; - - // call recursively for all function calls first - for(local_SSAt::nodest::const_iterator n_it=SSA.nodes.begin(); - n_it!=SSA.nodes.end(); ++n_it) - { - for(local_SSAt::nodet::function_callst::const_iterator ff_it= - n_it->function_calls.begin(); - ff_it!=n_it->function_calls.end(); ff_it++) - { - assert(ff_it->function().id()==ID_symbol); // no function pointers - irep_idt fname=to_symbol_expr(ff_it->function()).get_identifier(); - - // ENHANCE?: can the return value be exploited? - if(ssa_db.functions().find(fname)!=ssa_db.functions().end() && - (!summary_db.exists(fname) || - summary_db.get(fname).bw_transformer.is_nil())) - { -#if 0 - debug() << "Checking call " << fname << messaget::eom; -#endif - if(seen_function_calls.find(fname)==seen_function_calls.end()){ - seen_function_calls.insert(fname); - check_properties(fname, entry_function, seen_function_calls, - n_it->function_calls_inlined); - } - } - } - } - - if(!is_inlined) - { - // now check function itself - status() << "Checking properties of " << f_it->first << messaget::eom; - check_properties(f_it, entry_function); - } - } - else // check all the functions - { - for(ssa_dbt::functionst::const_iterator f_it=ssa_db.functions().begin(); - f_it!=ssa_db.functions().end(); f_it++) - { - status() << "Checking properties of " << f_it->first << messaget::eom; - -#if 0 - // for debugging - show_ssa_symbols(*f_it->second, std::cerr); -#endif - - check_properties(f_it); - - if(options.get_bool_option("show-invariants")) - { - if(!summary_db.exists(f_it->first)) continue; - show_invariants(*(f_it->second), summary_db.get(f_it->first), result()); - result() << eom; - } - } - } - - summary_checker_baset::resultt result=property_checkert::PASS; - if(function_name=="" || function_name==entry_function) - { - // determine overall status - for(property_mapt::const_iterator - p_it=property_map.begin(); p_it!=property_map.end(); p_it++) - { - if(p_it->second.result==FAIL) - return property_checkert::FAIL; - if(p_it->second.result==UNKNOWN) - result=property_checkert::UNKNOWN; - } - } - - return result; -} - -/*******************************************************************\ - -Function: summary_checker_baset::check_properties - - Inputs: - - Outputs: - - Purpose: - -\*******************************************************************/ - -void summary_checker_baset::check_properties( - const ssa_dbt::functionst::const_iterator f_it, - irep_idt entry_function) -{ - unwindable_local_SSAt &SSA=*f_it->second; - - // check whether function has assertions - if(!has_assertion(f_it->first)) - return; - - bool all_properties=options.get_bool_option("all-properties"); - bool build_error_trace=options.get_bool_option("show-trace"); - - SSA.output(debug()); debug() << eom; - - // incremental version - - // solver - incremental_solvert &solver=ssa_db.get_solver(f_it->first); - solver.set_message_handler(get_message_handler()); - -#if 0 - // TEST ssa_const_propagation - if(options.get_bool_option("ssa-propagation")) - { - ssa_const_propagatort ssa_const_propagator; - std::list c; - ssa_const_propagator(c, SSA); - solver << c; - debug() << "SSA const propagation: " << eom; - for(std::list::iterator it=c.begin(); - it!=c.end(); it++) - debug() << " " << from_expr(SSA.ns, "", *it) << eom; - } -#endif - - // give SSA to solver - solver << SSA; - SSA.mark_nodes(); - - solver.new_context(); - - exprt enabling_expr=SSA.get_enabling_exprs(); - solver << enabling_expr; - - // invariant, calling contexts - if(summary_db.exists(f_it->first)) - { - const summaryt &summary=summary_db.get(f_it->first); - if(!summary.fw_invariant.is_nil()) - solver << summary.fw_invariant; - if(!summary.fw_precondition.is_nil()) - solver << summary.fw_precondition; - } - - // callee summaries and inlined functions - ssa_inlinert::assertion_mapt assertion_map; - solver << ssa_inliner.get_summaries(SSA, assertion_map); - - // spuriousness checkers - summarizer_bw_cex_baset *summarizer_bw_cex=NULL; - incremental_solvert* cex_complete_solver= - incremental_solvert::allocate(SSA.ns, - options.get_bool_option("refine")); -#if 1 - cex_complete_solver->set_message_handler(get_message_handler()); -#endif - if(options.get_bool_option("inline") || - options.get_option("spurious-check")=="concrete") - { - summarizer_bw_cex=new summarizer_bw_cex_concretet( - options, summary_db, ssa_db, - ssa_unwinder, ssa_inliner, - entry_function, f_it->first); - } - else if(options.get_option("spurious-check")=="abstract") - { - summarizer_bw_cex=new summarizer_bw_cex_ait( - options, summary_db, ssa_db, - ssa_unwinder, ssa_inliner, - entry_function, f_it->first); - } - else if(options.get_option("spurious-check")=="complete") - { - summarizer_bw_cex=new summarizer_bw_cex_completet( - options, summary_db, ssa_db, - ssa_unwinder, ssa_inliner, *cex_complete_solver, - entry_function, f_it->first); - } - else if(options.get_option("spurious-check")=="wp") - { - summarizer_bw_cex=new summarizer_bw_cex_wpt( - options, summary_db, ssa_db, - ssa_unwinder, ssa_inliner, *cex_complete_solver, - entry_function, f_it->first); - } - else if(options.get_option("spurious-check")=="all") - { - summarizer_bw_cex=new summarizer_bw_cex_allt( - options, summary_db, ssa_db, - ssa_unwinder, ssa_inliner, *cex_complete_solver, - entry_function, f_it->first); - } - assert(summarizer_bw_cex!=NULL); - summarizer_bw_cex->set_message_handler(get_message_handler()); - - cover_goals_extt cover_goals( - SSA, solver, property_map, - all_properties, build_error_trace, - *summarizer_bw_cex); - - for(ssa_inlinert::assertion_mapt::const_iterator - aa_it=assertion_map.begin(); - aa_it!=assertion_map.end(); - aa_it++) - { - irep_idt property_id=aa_it->first->source_location.get_property_id(); - - // do not recheck properties that have already been decided - if(property_map[property_id].result!=UNKNOWN) - continue; - -#if 0 - if(property_id=="") // TODO: some properties do not show up in initialize_property_map - continue; -#endif - - for(exprt::operandst::const_iterator - a_it=aa_it->second.begin(); - a_it!=aa_it->second.end(); - a_it++) - { - exprt property=*a_it; - - if(simplify) - property=::simplify_expr(property, SSA.ns); - -#if 1 - debug() << "property: " << from_expr(SSA.ns, "", property) << eom; -#endif - - property_map[property_id].location=aa_it->first; - cover_goals.goal_map[property_id].conjuncts.push_back(property); - } - } - - - for(cover_goals_extt::goal_mapt::const_iterator - it=cover_goals.goal_map.begin(); - it!=cover_goals.goal_map.end(); - it++) - { - // Our goal is to falsify a property. - // The following is TRUE if the conjunction is empty. - // literalt p=!solver.convert(conjunction(it->second.conjuncts)); - // cover_goals.add(p); - cover_goals.add(not_exprt(conjunction(it->second.conjuncts))); - } - - status() << "Running " << solver.solver->decision_procedure_text() << eom; - - cover_goals(); - /* - std::cout << "Output Verbose: " << entry_function << "\n"; - (ssa_db.get(entry_function)).output_verbose(std::cout); - assert(false); - */ - // set all non-covered goals to PASS except if we do not try - // to cover all goals and we have found a FAIL - if(all_properties || cover_goals.number_covered()==0) - { - std::list::const_iterator g_it= - cover_goals.goals.begin(); - for(cover_goals_extt::goal_mapt::const_iterator - it=cover_goals.goal_map.begin(); - it!=cover_goals.goal_map.end(); - it++, g_it++) - { - if(!g_it->covered) property_map[it->first].result=PASS; - } - } - - solver.pop_context(); - - summarizer_bw_cex->get_reason(reason); - - debug() << "** " << cover_goals.number_covered() - << " of " << cover_goals.size() << " failed (" - << cover_goals.iterations() << " iterations)" << eom; - - delete summarizer_bw_cex; - delete cex_complete_solver; -} - -/*******************************************************************\ - -Function: summary_checker_baset::report_statistics() - - Inputs: - - Outputs: - - Purpose: - -\*******************************************************************/ - -void summary_checker_baset::report_statistics() -{ - for(ssa_dbt::functionst::const_iterator f_it=ssa_db.functions().begin(); - f_it!=ssa_db.functions().end(); f_it++) - { - incremental_solvert &solver=ssa_db.get_solver(f_it->first); - unsigned calls=solver.get_number_of_solver_calls(); - if(calls>0) solver_instances++; - solver_calls+=calls; - } - statistics() << "** statistics: " << eom; - statistics() << " number of solver instances: " << solver_instances << eom; - statistics() << " number of solver calls: " << solver_calls << eom; - statistics() << " number of summaries used: " - << summaries_used << eom; - statistics() << eom; -} - -/*******************************************************************\ - -Function: summary_checker_baset::do_show_vcc - - Inputs: - - Outputs: - - Purpose: - -\*******************************************************************/ - -void summary_checker_baset::do_show_vcc( - const local_SSAt &SSA, - const goto_programt::const_targett i_it, - const local_SSAt::nodet::assertionst::const_iterator &a_it) -{ - std::cout << i_it->source_location << "\n"; - std::cout << i_it->source_location.get_comment() << "\n"; - - std::list ssa_constraints; - ssa_constraints << SSA; - - unsigned i=1; - for(std::list::const_iterator c_it=ssa_constraints.begin(); - c_it!=ssa_constraints.end(); - c_it++, i++) - std::cout << "{-" << i << "} " << from_expr(SSA.ns, "", *c_it) << "\n"; - - std::cout << "|--------------------------\n"; - - std::cout << "{1} " << from_expr(SSA.ns, "", *a_it) << "\n"; - - std::cout << "\n"; -(??)} -(??) -(??) -(??)/*******************************************************************\ -(??) -(??)Function: summary_checker_baset::is_spurious -(??) -(??) Inputs: -(??) -(??) Outputs: -(??) -(??) Purpose: checks whether a countermodel is spurious -(??) -(??)\*******************************************************************/ -(??) -(??)bool summary_checker_baset::is_spurious(const exprt::operandst &loophead_selects, -(??) incremental_solvert &solver) -(??){ -(??) // check loop head choices in model -(??) bool invariants_involved=false; -(??) for(exprt::operandst::const_iterator l_it=loophead_selects.begin(); -(??) l_it!=loophead_selects.end(); l_it++) -(??) { -(??) if(solver.get(l_it->op0()).is_true()) -(??) { -(??) invariants_involved=true; -(??) break; -(??) } -(??) } -(??) if(!invariants_involved) return false; -(??) -(??) // force avoiding paths going through invariants -(??) solver << conjunction(loophead_selects); -(??) -(??) solver_calls++; // statistics -(??) -(??) switch(solver()) -(??) { -(??) case decision_proceduret::D_SATISFIABLE: -(??) return false; -(??) break; -(??) -(??) case decision_proceduret::D_UNSATISFIABLE: -(??) return true; -(??) break; -(??) -(??) case decision_proceduret::D_ERROR: -(??) default: -(??) throw "error from decision procedure"; -(??) } -} - -/*******************************************************************\ - -Function: summary_checker_baset::instrument_and_output - - Inputs: - - Outputs: - - Purpose: instruments the code with the inferred information - and outputs it to a goto-binary - -\*******************************************************************/ - -void summary_checker_baset::instrument_and_output(goto_modelt &goto_model) -{ - instrument_gotot instrument_goto(options, ssa_db, summary_db); - instrument_goto(goto_model); - std::string filename=options.get_option("instrument-output"); - status() << "Writing instrumented goto-binary " << filename << eom; - write_goto_binary(filename, - goto_model.symbol_table, - goto_model.goto_functions, get_message_handler()); -} - -/*******************************************************************\ - -Function: summary_checker_baset::has_assertion - - Inputs: - - Outputs: - - Purpose: searches recursively for assertions in inlined functions - -\*******************************************************************/ - -bool summary_checker_baset::has_assertion(irep_idt function_name) -{ - // SSA.goto_function.body.has_assertion() has become too semantic - bool _has_assertion=false; - const local_SSAt &SSA=ssa_db.get(function_name); - - for(local_SSAt::nodest::const_iterator - n_it=SSA.nodes.begin(); n_it!=SSA.nodes.end(); ++n_it) - { - for(local_SSAt::nodet::assertionst::const_iterator - a_it=n_it->assertions.begin(); a_it!=n_it->assertions.end(); ++a_it) - { - irep_idt property_id=n_it->location->source_location.get_property_id(); - - if(n_it->location->guard.is_true()) - property_map[property_id].result=PASS; - else - _has_assertion=true; - } - if(!n_it->function_calls_inlined) - continue; - - for(local_SSAt::nodet::function_callst::const_iterator - f_it=n_it->function_calls.begin(); - f_it!=n_it->function_calls.end(); ++f_it) - { - irep_idt fname=to_symbol_expr(f_it->function()).get_identifier(); - if(ssa_db.functions().find(fname)==ssa_db.functions().end()) - continue; - - bool new_has_assertion=has_assertion(fname); // recurse - _has_assertion=_has_assertion || new_has_assertion; - } - } - - return _has_assertion; -} diff --git a/src/summarizer/summary_checker_base.h b/src/summarizer/summary_checker_base.h deleted file mode 100644 index 339f3ae01..000000000 --- a/src/summarizer/summary_checker_base.h +++ /dev/null @@ -1,97 +0,0 @@ -/*******************************************************************\ - -Module: Summary Checker Base - -Author: Peter Schrammel - -\*******************************************************************/ - -#ifndef CPROVER_SUMMARY_CHECKER_BASE_H -#define CPROVER_SUMMARY_CHECKER_BASE_H - -#include - -#include -#include - -#include "cover_goals_ext.h" -#include "../ssa/local_ssa.h" -#include "../ssa/ssa_unwinder.h" -#include "../ssa/ssa_inliner.h" -#include "../domains/incremental_solver.h" -#include "ssa_db.h" -#include "summary_db.h" -#include "summarizer_bw_cex.h" - -class summary_checker_baset:public property_checkert -{ -public: - inline summary_checker_baset(optionst &_options): - show_vcc(false), - simplify(false), - fixed_point(false), - options(_options), - ssa_db(_options), summary_db(), - ssa_unwinder(ssa_db), - ssa_inliner(summary_db, ssa_db), - solver_instances(0), - solver_calls(0), - summaries_used(0) - { - ssa_inliner.set_message_handler(get_message_handler()); - } - - bool show_vcc, simplify, fixed_point; - irep_idt function_to_check; - - virtual resultt operator()(const goto_modelt &) { assert(false); } - - void instrument_and_output(goto_modelt &goto_model); - - // statistics - absolute_timet start_time; - time_periodt sat_time; - -protected: - optionst &options; - - ssa_dbt ssa_db; - summary_dbt summary_db; - ssa_unwindert ssa_unwinder; - ssa_inlinert ssa_inliner; - - irep_idt entry_function; - - summarizer_bw_cex_baset::reasont reason; - - unsigned solver_instances; - unsigned solver_calls; - unsigned summaries_used; - void report_statistics(); - - void do_show_vcc( - const local_SSAt &, - const goto_programt::const_targett, - const local_SSAt::nodet::assertionst::const_iterator &); - - void SSA_functions(const goto_modelt &, const namespacet &ns); - void SSA_dependency_graphs(const goto_modelt &, const namespacet &ns); - - void summarize(const goto_modelt &, - bool forward=true, bool termination=false); - - property_checkert::resultt check_properties(); - property_checkert::resultt check_properties( - irep_idt function_name, - irep_idt entry_function, - std::set seen_function_calls, - bool is_inlined); - void check_properties( - const ssa_dbt::functionst::const_iterator f_it, - irep_idt entry_function=""); - - bool has_assertion(irep_idt function_name); - -}; - -#endif diff --git a/src/summarizer/summary_checker_bmc.cpp b/src/summarizer/summary_checker_bmc.cpp deleted file mode 100644 index 7c6b21c71..000000000 --- a/src/summarizer/summary_checker_bmc.cpp +++ /dev/null @@ -1,92 +0,0 @@ -/*******************************************************************\ - -Module: Summarizer Checker for BMC - -Author: Peter Schrammel - -\*******************************************************************/ - -#include "summary_checker_bmc.h" - -#include "../ssa/ssa_refiner.h" -#include "../ssa/ssa_refiner_monolithic.h" -#include "../ssa/ssa_refiner_selective.h" - - -/*******************************************************************\ - -Function: summary_checker_bmct::operator() - - Inputs: - - Outputs: - - Purpose: - -\*******************************************************************/ - -property_checkert::resultt summary_checker_bmct::operator()( - const goto_modelt &goto_model) -{ - const namespacet ns(goto_model.symbol_table); - irep_idt entry_function=goto_model.goto_functions.entry_point(); - if(options.get_bool_option("unit-check")) - entry_function=""; - - SSA_functions(goto_model, ns); - - ssa_unwinder.init(false, true); - - property_checkert::resultt result=property_checkert::UNKNOWN; - unsigned max_unwind=options.get_unsigned_int_option("unwind"); - status() << "Max-unwind is " << max_unwind << eom; - ssa_unwinder.init_localunwinders(); - - ssa_refinert *ssa_refiner; - if((options.get_bool_option("inline"))) - ssa_refiner=new ssa_refiner_monolithict(summary_db, ssa_unwinder, - max_unwind); - else - ssa_refiner=new ssa_refiner_selectivet(ssa_db, ssa_unwinder, - max_unwind, ssa_inliner, reason); - ssa_refiner->set_message_handler(get_message_handler()); - - // while can refine - while((*ssa_refiner)()) - { - status() << "Unwinding (k=" << unwind << ")" << messaget::eom; - summary_db.mark_recompute_all(); - ssa_unwinder.unwind_all(unwind+1); - - // dependency graphs - if(!(options.get_bool_option("inline"))) - { - if((options.get_option("spurious-check")!="concrete") && - (options.get_option("spurious-check")!="abstract")) - { - SSA_dependency_graphs(goto_model, ns); - } - } - - // check - std::set seen_function_calls; - result= check_properties(entry_function, entry_function, - seen_function_calls, false); - - // result - if(result==property_checkert::PASS) - { - status() << "incremental BMC proof found after " - << unwind << " unwinding(s)" << messaget::eom; - break; - } - else if(result==property_checkert::FAIL) - { - status() << "incremental BMC counterexample found after " - << unwind << " unwinding(s)" << messaget::eom; - break; - } - } - report_statistics(); - return result; -} diff --git a/src/summarizer/summary_checker_bmc.h b/src/summarizer/summary_checker_bmc.h deleted file mode 100644 index ab8294099..000000000 --- a/src/summarizer/summary_checker_bmc.h +++ /dev/null @@ -1,26 +0,0 @@ -/*******************************************************************\ - -Module: Summary Checker for BMC - -Author: Peter Schrammel - -\*******************************************************************/ - -#ifndef CPROVER_SUMMARY_CHECKER_BMC_H -#define CPROVER_SUMMARY_CHECKER_BMC_H - -#include "summary_checker_base.h" - -class summary_checker_bmct:public summary_checker_baset -{ -public: - inline summary_checker_bmct(optionst &_options): - summary_checker_baset(_options) - { - } - - virtual resultt operator()(const goto_modelt &); - -}; - -#endif diff --git a/src/summarizer/summary_checker_kind.cpp b/src/summarizer/summary_checker_kind.cpp deleted file mode 100644 index 04059b699..000000000 --- a/src/summarizer/summary_checker_kind.cpp +++ /dev/null @@ -1,105 +0,0 @@ -/*******************************************************************\ - -Module: Summary Checker for k-induction - -Author: Peter Schrammel - -\*******************************************************************/ - -#include "summary_checker_kind.h" -#include "../ssa/ssa_refiner.h" -#include "../ssa/ssa_refiner_monolithic.h" -#include "../ssa/ssa_refiner_selective.h" - -#define GIVE_UP_INVARIANTS 7 - -/*******************************************************************\ - -Function: summary_checker_kindt::operator() - - Inputs: - - Outputs: - - Purpose: - -\*******************************************************************/ - -property_checkert::resultt summary_checker_kindt::operator()( - const goto_modelt &goto_model) -{ - const namespacet ns(goto_model.symbol_table); - irep_idt entry_function=goto_model.goto_functions.entry_point(); - if(options.get_bool_option("unit-check")) - entry_function=""; - - SSA_functions(goto_model, ns); - - ssa_unwinder.init(true, false); - - property_checkert::resultt result=property_checkert::UNKNOWN; - unsigned max_unwind=options.get_unsigned_int_option("unwind"); - status() << "Max-unwind is " << max_unwind << eom; - ssa_unwinder.init_localunwinders(); - - ssa_refinert *ssa_refiner; - if((options.get_bool_option("inline"))) - ssa_refiner=new ssa_refiner_monolithict(summary_db, ssa_unwinder, - max_unwind); - else - ssa_refiner=new ssa_refiner_selectivet(ssa_db, ssa_unwinder, - max_unwind, ssa_inliner, reason); - ssa_refiner->set_message_handler(get_message_handler()); - - // while can refine - while((*ssa_refiner)()) - { - unsigned unwind=ssa_refiner->get_unwind(); - - // dependency graphs - if(!(options.get_bool_option("inline"))) - { - if((options.get_option("spurious-check")!="concrete") && - (options.get_option("spurious-check")!="abstract")) - { - // TODO: update only those that were refined by unwinding - SSA_dependency_graphs(goto_model, ns); - } - } - - // check - std::set seen_function_calls; - result= check_properties(entry_function, entry_function, - seen_function_calls, false); - - // do static analysis and check again - if(result==property_checkert::UNKNOWN && - !options.get_bool_option("havoc") && - (unwind seen_function_calls; - result= check_properties(entry_function, entry_function, - seen_function_calls, false); - } - - // result - if(result==property_checkert::PASS) - { - status() << "k-induction proof found after " - << unwind << " unwinding(s)" << eom; - break; - } - else if(result==property_checkert::FAIL) - { - status() << "k-induction counterexample found after " - << unwind << " unwinding(s)" << eom; - break; - } - } - delete ssa_refiner; - report_statistics(); - return result; -} - diff --git a/src/summarizer/summary_checker_kind.h b/src/summarizer/summary_checker_kind.h deleted file mode 100644 index 792347485..000000000 --- a/src/summarizer/summary_checker_kind.h +++ /dev/null @@ -1,26 +0,0 @@ -/*******************************************************************\ - -Module: Summary Checker for k-induction - -Author: Peter Schrammel - -\*******************************************************************/ - -#ifndef CPROVER_SUMMARY_CHECKER_KIND_H -#define CPROVER_SUMMARY_CHECKER_KIND_H - -#include "summary_checker_base.h" - -class summary_checker_kindt:public summary_checker_baset -{ -public: - inline summary_checker_kindt(optionst &_options): - summary_checker_baset(_options) - { - } - - virtual resultt operator()(const goto_modelt &); - -}; - -#endif From 9175a615765ec651655f2ed15d765f6459069779 Mon Sep 17 00:00:00 2001 From: Peter Schrammel Date: Fri, 2 Jun 2017 09:27:53 +0100 Subject: [PATCH 76/82] Spurious checker needs entry point function and goals need expression --- src/2ls/cover_goals_ext.h | 6 ------ src/2ls/summary_checker_base.cpp | 5 ++--- 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/src/2ls/cover_goals_ext.h b/src/2ls/cover_goals_ext.h index 7cd3f9360..cb05ecdae 100644 --- a/src/2ls/cover_goals_ext.h +++ b/src/2ls/cover_goals_ext.h @@ -106,12 +106,6 @@ class cover_goals_extt:public messaget // managing the goals - inline void add(const literalt condition) - { - goals.push_back(cover_goalt()); - goals.back().condition=condition; - } - inline void add(const exprt cond_expression) { goals.push_back(cover_goalt()); diff --git a/src/2ls/summary_checker_base.cpp b/src/2ls/summary_checker_base.cpp index 786150630..0ee76081b 100644 --- a/src/2ls/summary_checker_base.cpp +++ b/src/2ls/summary_checker_base.cpp @@ -230,7 +230,7 @@ summary_checker_baset::resultt summary_checker_baset::check_properties( show_ssa_symbols(*f_it->second, std::cerr); #endif - check_properties(f_it); + check_properties(f_it, f_it->first); if(options.get_bool_option("show-invariants")) { @@ -464,8 +464,7 @@ void summary_checker_baset::check_properties( { // Our goal is to falsify a property. // The following is TRUE if the conjunction is empty. - literalt p=!solver.convert(conjunction(it->second.conjuncts)); - cover_goals.add(p); + cover_goals.add(conjunction(it->second.conjuncts)); } status() << "Running " << solver.solver->decision_procedure_text() << eom; From 0e17dbcfeaaa84adeabd0622d73e4c89a6940d11 Mon Sep 17 00:00:00 2001 From: Ranadeep Biswas Date: Wed, 7 Jun 2017 18:02:29 +0530 Subject: [PATCH 77/82] Runtime error fixes --- src/2ls/summary_checker_base.cpp | 6 ++++-- src/ssa/local_ssa.cpp | 3 +++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/2ls/summary_checker_base.cpp b/src/2ls/summary_checker_base.cpp index 0ee76081b..ed379c319 100644 --- a/src/2ls/summary_checker_base.cpp +++ b/src/2ls/summary_checker_base.cpp @@ -307,8 +307,10 @@ void summary_checker_baset::check_properties( // invariant, calling contexts if(summary_db.exists(f_it->first)) { - solver << summary_db.get(f_it->first).fw_invariant; - solver << summary_db.get(f_it->first).fw_precondition; + if(!summary_db.get(f_it->first).fw_invariant.is_nil()) + solver << summary_db.get(f_it->first).fw_invariant; + if(!summary_db.get(f_it->first).fw_precondition.is_nil()) + solver << summary_db.get(f_it->first).fw_precondition; } // callee summaries diff --git a/src/ssa/local_ssa.cpp b/src/ssa/local_ssa.cpp index af3727737..e997d27d3 100644 --- a/src/ssa/local_ssa.cpp +++ b/src/ssa/local_ssa.cpp @@ -218,8 +218,11 @@ void local_SSAt::get_globals( { // workaround for the problem that // rhs() for a return value is always the "input" return value + #if 0 // --loc may be invalid const exprt &expr=is_return ? read_lhs(it->get_expr(), --loc) : read_rhs(it->get_expr(), loc); + #endif + const exprt &expr=read_rhs(it->get_expr(), loc); globals.insert(to_symbol_expr(expr)); } else From 739537f0361c708c915660229bef93de83d8e797 Mon Sep 17 00:00:00 2001 From: Ranadeep Biswas Date: Wed, 7 Jun 2017 18:37:10 +0530 Subject: [PATCH 78/82] Fix to check only entry_point --- src/2ls/summary_checker_ai.cpp | 5 ++++- src/2ls/summary_checker_base.cpp | 6 ++++++ src/2ls/summary_checker_base.h | 1 + 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/2ls/summary_checker_ai.cpp b/src/2ls/summary_checker_ai.cpp index 6cda09787..65259c40c 100644 --- a/src/2ls/summary_checker_ai.cpp +++ b/src/2ls/summary_checker_ai.cpp @@ -77,7 +77,10 @@ property_checkert::resultt summary_checker_ait::operator()( return property_checkert::UNKNOWN; #endif - property_checkert::resultt result=check_properties(); + property_checkert::resultt result= + options.get_bool_option("all-functions")? + check_properties(): + check_properties(goto_model.goto_functions.entry_point()); report_statistics(); return result; } diff --git a/src/2ls/summary_checker_base.cpp b/src/2ls/summary_checker_base.cpp index ed379c319..57f5e8581 100644 --- a/src/2ls/summary_checker_base.cpp +++ b/src/2ls/summary_checker_base.cpp @@ -166,6 +166,12 @@ summary_checker_baset::resultt summary_checker_baset::check_properties() return check_properties("", "", seen_function_calls, false); } +summary_checker_baset::resultt summary_checker_baset::check_properties(irep_idt entry_function) +{ + std::set seen_function_calls; + return check_properties(entry_function, entry_function, seen_function_calls, false); +} + summary_checker_baset::resultt summary_checker_baset::check_properties( irep_idt function_name, irep_idt entry_function, diff --git a/src/2ls/summary_checker_base.h b/src/2ls/summary_checker_base.h index bf97dbabf..c758f4ed9 100644 --- a/src/2ls/summary_checker_base.h +++ b/src/2ls/summary_checker_base.h @@ -81,6 +81,7 @@ class summary_checker_baset:public property_checkert bool termination=false); property_checkert::resultt check_properties(); + property_checkert::resultt check_properties(irep_idt entry_function); property_checkert::resultt check_properties( irep_idt function_name, irep_idt entry_function, From 2108cf43535c4e97b29f5035bb60d455f8c61bae Mon Sep 17 00:00:00 2001 From: Peter Schrammel Date: Thu, 8 Jun 2017 22:24:18 +0100 Subject: [PATCH 79/82] Negation moved into cover_goals_ext which resulted in a wrong double negation --- src/2ls/cover_goals_ext.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/2ls/cover_goals_ext.h b/src/2ls/cover_goals_ext.h index cb05ecdae..9a40f4693 100644 --- a/src/2ls/cover_goals_ext.h +++ b/src/2ls/cover_goals_ext.h @@ -109,7 +109,7 @@ class cover_goals_extt:public messaget inline void add(const exprt cond_expression) { goals.push_back(cover_goalt()); - goals.back().condition=!solver.convert(not_exprt(cond_expression)); + goals.back().condition=!solver.convert(cond_expression); goals.back().cond_expression=cond_expression; } From 459ed5dc63f294b5ce7a1d3897d4efd234790614 Mon Sep 17 00:00:00 2001 From: Peter Schrammel Date: Thu, 8 Jun 2017 22:29:48 +0100 Subject: [PATCH 80/82] Deactivate assume after assert --- src/2ls/2ls_parse_options.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/2ls/2ls_parse_options.cpp b/src/2ls/2ls_parse_options.cpp index cc8646bcf..c67380dc5 100644 --- a/src/2ls/2ls_parse_options.cpp +++ b/src/2ls/2ls_parse_options.cpp @@ -60,6 +60,8 @@ Author: Daniel Kroening, Peter Schrammel #define IGNORE_THREADS 1 #define EXPLICIT_NONDET_LOCALS 0 #define FILTER_ASSERTIONS 1 +#define ASSUME_AFTER_ASSERT 0 + /*******************************************************************\ @@ -1094,10 +1096,12 @@ bool twols_parse_optionst::process_goto_program( inline_main(goto_model); } +#ifdef ASSUME_AFTER_ASSERT if(!cmdline.isset("independent-properties")) { add_assumptions_after_assertions(goto_model); } +#endif #ifdef FILTER_ASSERTIONS filter_assertions(goto_model); From baaf462941d912438718c5ff7d47576f34ff3a8e Mon Sep 17 00:00:00 2001 From: Ranadeep Biswas Date: Sun, 11 Jun 2017 00:31:21 +0530 Subject: [PATCH 81/82] Fixed incorrect result from summarizer_bw_cex_concrete --- src/solver/summarizer_bw_cex_concrete.cpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/solver/summarizer_bw_cex_concrete.cpp b/src/solver/summarizer_bw_cex_concrete.cpp index 9f5882334..0e08832bf 100644 --- a/src/solver/summarizer_bw_cex_concrete.cpp +++ b/src/solver/summarizer_bw_cex_concrete.cpp @@ -91,18 +91,18 @@ Function: summarizer_bw_cex_concretet::check() property_checkert::resultt summarizer_bw_cex_concretet::check() { - property_checkert::resultt result=property_checkert::FAIL; - if(!summary_db.exists(entry_function)) - { - result=property_checkert::UNKNOWN; - } - else + property_checkert::resultt result=property_checkert::UNKNOWN; + if(summary_db.exists(entry_function)) { const summaryt &summary=summary_db.get(entry_function); - if(summary.error_summaries.empty() || - summary.error_summaries.begin()->second.is_nil() || - summary.error_summaries.begin()->second.is_true()) - result=property_checkert::UNKNOWN; + if(!summary.error_summaries.empty() && + !summary.error_summaries.begin()->second.is_nil()) + { + if(summary.error_summaries.begin()->second.is_false()) + result=property_checkert::PASS; + else + result=property_checkert::FAIL; + } } // we are only complete if everything was inlined From 50f067c2d0efc9630882424c424b9fd53f47f906 Mon Sep 17 00:00:00 2001 From: Kumar Madhukar Date: Wed, 28 Jun 2017 20:52:08 +0530 Subject: [PATCH 82/82] fixed spurious-check options --- src/2ls/2ls_parse_options.cpp | 7 +++++++ src/2ls/2ls_parse_options.h | 1 + 2 files changed, 8 insertions(+) diff --git a/src/2ls/2ls_parse_options.cpp b/src/2ls/2ls_parse_options.cpp index c67380dc5..046249b2e 100644 --- a/src/2ls/2ls_parse_options.cpp +++ b/src/2ls/2ls_parse_options.cpp @@ -279,10 +279,17 @@ void twols_parse_optionst::get_command_line_options(optionst &options) } // check for spuriousness of assertion failures + /* if(cmdline.isset("no-spurious-check")) options.set_option("spurious-check", false); else options.set_option("spurious-check", true); + */ + + if(cmdline.isset("spurious-check")) + options.set_option("spurious-check", cmdline.get_value("spurious-check")); + else + options.set_option("spurious-check", "all"); // all properties (default) if(cmdline.isset("stop-on-fail")) diff --git a/src/2ls/2ls_parse_options.h b/src/2ls/2ls_parse_options.h index d564b1279..1a2037028 100644 --- a/src/2ls/2ls_parse_options.h +++ b/src/2ls/2ls_parse_options.h @@ -53,6 +53,7 @@ class optionst; "(no-simplify)(no-fixed-point)" \ "(graphml-witness):(json-cex):" \ "(no-spurious-check)(stop-on-fail)" \ + "(spurious-check):" \ "(competition-mode)(slice)(no-propagation)(independent-properties)" \ "(no-unwinding-assertions)" // the last line is for CBMC-regression testing only