Presentation is loading. Please wait.

Presentation is loading. Please wait.

Program Analysis with Set Constraints Ravi Chugh.

Similar presentations


Presentation on theme: "Program Analysis with Set Constraints Ravi Chugh."— Presentation transcript:

1 Program Analysis with Set Constraints Ravi Chugh

2 Set-constraint based analysis Another technique for computing information about program variables Phase 1: constraint generation – Create set variables corresponding to program – Add inclusion constraints between these sets – Usually a local, syntax-directed process (ASTs vs CFGs) Phase 2: constraint resolution – Solve for values of all set variables Extends naturally to inter-procedural analysis

3 Constant propagation int abs(int i) { if (...) { return i; } else { return –i; } } int id(int j) { return j; } void main() { int a = 1, b = 2; int x = abs(a); int y = id(b);... use x...... use y... } Want to determine whether x and y are constant values when they are used We will build a flow- insensitive analysis

4 Set constraints Terms t := c (constant) | X (set variable) | C(t 1,...,t n )(constructed term) Constraints t 1 <= t 2 (set inclusion) Constructors – C(v 1,...,v n ) is an n-arg ctor C with variances v i – v i is either + (covariant) or – (contravariant) – Covariance corresponds to “forwards flow” – Contravariance corresponds to “backwards flow”

5 Set constraints and graph reachability Tight correspondence between set-inclusion constraints and edges in a flow graph

6 Set constraints and graph reachability Tight correspondence between set-inclusion constraints and edges in a flow graph 1 <= X X X 1 1

7 Set constraints and graph reachability Tight correspondence between set-inclusion constraints and edges in a flow graph 1 <= X X <= Y X X 1 1 Y Y

8 Set constraints and graph reachability Tight correspondence between set-inclusion constraints and edges in a flow graph 1 <= X X <= Y Ctor(A,B,C) <= Ctor(D,E,F) where Ctor(+,-,+) X X 1 1 Ctor ( A, B, C ) Ctor ( D, E, F ) Y Y

9 Set constraints and graph reachability Tight correspondence between set-inclusion constraints and edges in a flow graph 1 <= X X <= Y Ctor(A,B,C) <= Ctor(D,E,F) where Ctor(+,-,+) X X 1 1 Ctor ( A, B, C ) Ctor ( D, E, F ) Y Y

10 Constraint resolution System of constraints Con Additional constraints added by following rules 1) Transitivity of sets – Con with x <= y ∧ y <= z  Con ∧ x <= z 2) Constructed terms – Con with C(...,x i,...) <= C(...,y i,...)  Con ∧ i straint i straint i is x i <= y i if C covariant in i straint i is y i <= x i if C contravariant in i 3) Inconsistent terms – Con with C(...) <= D(...)  Inconsistent

11 Fun constructor For simplicity, assume all functions take one arg Define constructor Fun(-,+) Places for function input and output Encoding a function call: int z = id(2); Fun(i, retid) <= Fun(2, z)

12 Fun constructor For simplicity, assume all functions take one arg Define constructor Fun(-,+) Places for function input and output Encoding a function call: int z = id(2); Fun(i, retid) <= Fun(2, z) By contravariance, the actual 2 flows to i By covariance, the return value of id flows to z Fun ( i, retid) Fun ( 2, z )

13 int abs(int i) { if (...) { return i; } else { return –i; } } int id(int j) { return j; } void main() { int a = 1, b = 2; int x = abs(a); int y = id(b);... use x...... use y... }

14 int abs(int i) { if (...) { return i; } else { return –i; } } int id(int j) { return j; } void main() { int a = 1, b = 2; int x = abs(a); int y = id(b);... use x...... use y... } Fun(i,ret1) <= abs Fun (i, ret1) abs

15 int abs(int i) { if (...) { return i; } else { return –i; } } int id(int j) { return j; } void main() { int a = 1, b = 2; int x = abs(a); int y = id(b);... use x...... use y... } Fun(i,ret1) <= abs Fun (i, ret1) abs

16 int abs(int i) { if (...) { return i; } else { return –i; } } int id(int j) { return j; } void main() { int a = 1, b = 2; int x = abs(a); int y = id(b);... use x...... use y... } Fun(i,ret1) <= abs i <= ret1 Fun (i, ret1) abs

17 int abs(int i) { if (...) { return i; } else { return –i; } } int id(int j) { return j; } void main() { int a = 1, b = 2; int x = abs(a); int y = id(b);... use x...... use y... } Fun(i,ret1) <= abs i <= ret1 Fun (i, ret1) abs

18 int abs(int i) { if (...) { return i; } else { return –i; } } int id(int j) { return j; } void main() { int a = 1, b = 2; int x = abs(a); int y = id(b);... use x...... use y... } Fun(i,ret1) <= abs i <= ret1 T <= ret1 Fun (i, ret1) abs T T

19 int abs(int i) { if (...) { return i; } else { return –i; } } int id(int j) { return j; } void main() { int a = 1, b = 2; int x = abs(a); int y = id(b);... use x...... use y... } Fun(i,ret1) <= abs i <= ret1 T <= ret1 Fun (i, ret1) abs T T

20 int abs(int i) { if (...) { return i; } else { return –i; } } int id(int j) { return j; } void main() { int a = 1, b = 2; int x = abs(a); int y = id(b);... use x...... use y... } Fun(i,ret1) <= abs i <= ret1 T <= ret1 Fun(j,ret2) <= id Fun (i, ret1) abs T T Fun (j, ret2) id

21 int abs(int i) { if (...) { return i; } else { return –i; } } int id(int j) { return j; } void main() { int a = 1, b = 2; int x = abs(a); int y = id(b);... use x...... use y... } Fun(i,ret1) <= abs i <= ret1 T <= ret1 Fun(j,ret2) <= id Fun (i, ret1) abs T T Fun (j, ret2) id

22 int abs(int i) { if (...) { return i; } else { return –i; } } int id(int j) { return j; } void main() { int a = 1, b = 2; int x = abs(a); int y = id(b);... use x...... use y... } Fun(i,ret1) <= abs i <= ret1 T <= ret1 Fun(j,ret2) <= id j <= ret2 Fun (i, ret1) abs T T Fun (j, ret2) id

23 int abs(int i) { if (...) { return i; } else { return –i; } } int id(int j) { return j; } void main() { int a = 1, b = 2; int x = abs(a); int y = id(b);... use x...... use y... } Fun(i,ret1) <= abs i <= ret1 T <= ret1 Fun(j,ret2) <= id j <= ret2 Fun (i, ret1) abs T T Fun (j, ret2) id

24 int abs(int i) { if (...) { return i; } else { return –i; } } int id(int j) { return j; } void main() { int a = 1, b = 2; int x = abs(a); int y = id(b);... use x...... use y... } Fun(i,ret1) <= abs i <= ret1 T <= ret1 Fun(j,ret2) <= id j <= ret2 1 <= a 2 <= b Fun (i, ret1) abs T T Fun (j, ret2) id a a 1 1 b b 2 2

25 int abs(int i) { if (...) { return i; } else { return –i; } } int id(int j) { return j; } void main() { int a = 1, b = 2; int x = abs(a); int y = id(b);... use x...... use y... } Fun(i,ret1) <= abs i <= ret1 T <= ret1 Fun(j,ret2) <= id j <= ret2 1 <= a 2 <= b Fun (i, ret1) abs T T Fun (j, ret2) id a a 1 1 b b 2 2

26 int abs(int i) { if (...) { return i; } else { return –i; } } int id(int j) { return j; } void main() { int a = 1, b = 2; int x = abs(a); int y = id(b);... use x...... use y... } Fun(i,ret1) <= abs i <= ret1 T <= ret1 Fun(j,ret2) <= id j <= ret2 1 <= a 2 <= b abs <= Fun(a,x) Fun (i, ret1) abs T T Fun (j, ret2) id a a 1 1 b b 2 2 Fun (, x )

27 int abs(int i) { if (...) { return i; } else { return –i; } } int id(int j) { return j; } void main() { int a = 1, b = 2; int x = abs(a); int y = id(b);... use x...... use y... } Fun(i,ret1) <= abs i <= ret1 T <= ret1 Fun(j,ret2) <= id j <= ret2 1 <= a 2 <= b abs <= Fun(a,x) Fun (i, ret1) abs T T Fun (j, ret2) id a a 1 1 b b 2 2 Fun (, x )

28 int abs(int i) { if (...) { return i; } else { return –i; } } int id(int j) { return j; } void main() { int a = 1, b = 2; int x = abs(a); int y = id(b);... use x...... use y... } Fun(i,ret1) <= abs i <= ret1 T <= ret1 Fun(j,ret2) <= id j <= ret2 1 <= a 2 <= b abs <= Fun(a,x) Fun (i, ret1) abs T T Fun (j, ret2) id a a 1 1 b b 2 2 Fun (, x )

29 int abs(int i) { if (...) { return i; } else { return –i; } } int id(int j) { return j; } void main() { int a = 1, b = 2; int x = abs(a); int y = id(b);... use x...... use y... } Fun(i,ret1) <= abs i <= ret1 T <= ret1 Fun(j,ret2) <= id j <= ret2 1 <= a 2 <= b abs <= Fun(a,x) id <= Fun(b,y) Fun (i, ret1) abs T T Fun (j, ret2) id a a 1 1 b b 2 2 Fun (, x ) Fun (, y )

30 int abs(int i) { if (...) { return i; } else { return –i; } } int id(int j) { return j; } void main() { int a = 1, b = 2; int x = abs(a); int y = id(b);... use x...... use y... } Fun(i,ret1) <= abs i <= ret1 T <= ret1 Fun(j,ret2) <= id j <= ret2 1 <= a 2 <= b abs <= Fun(a,x) id <= Fun(b,y) Fun (i, ret1) abs T T Fun (j, ret2) id a a 1 1 b b 2 2 Fun (, x ) Fun (, y )

31 int abs(int i) { if (...) { return i; } else { return –i; } } int id(int j) { return j; } void main() { int a = 1, b = 2; int x = abs(a); int y = id(b);... use x...... use y... } Fun(i,ret1) <= abs i <= ret1 T <= ret1 Fun(j,ret2) <= id j <= ret2 1 <= a 2 <= b abs <= Fun(a,x) id <= Fun(b,y) Fun (i, ret1) abs T T Fun (j, ret2) id a a 1 1 b b 2 2 Fun (, x ) Fun (, y ) [[x]] = [[y]] =

32 int abs(int i) { if (...) { return i; } else { return –i; } } int id(int j) { return j; } void main() { int a = 1, b = 2; int x = abs(a); int y = id(b);... use x...... use y... } Fun(i,ret1) <= abs i <= ret1 T <= ret1 Fun(j,ret2) <= id j <= ret2 1 <= a 2 <= b abs <= Fun(a,x) id <= Fun(b,y) Fun (i, ret1) abs T T Fun (j, ret2) id a a 1 1 b b 2 2 Fun (, x ) Fun (, y ) [[x]] = {1, T} [[y]] = {2}

33 Pointers Handle pointers with a Ref(-,+) constructor Two args correspond to set and get operations int i = 1; int *p = &i; *p = 2; int j = *p;

34 Pointers Handle pointers with a Ref(-,+) constructor Two args correspond to set and get operations int i = 1; int *p = &i; *p = 2; int j = *p; i i 1 1

35 Pointers Handle pointers with a Ref(-,+) constructor Two args correspond to set and get operations int i = 1; int *p = &i; *p = 2; int j = *p; 1 1 i i

36 Pointers Handle pointers with a Ref(-,+) constructor Two args correspond to set and get operations int i = 1; int *p = &i; *p = 2; int j = *p; Ref (seti, i) 1 1

37 Pointers Handle pointers with a Ref(-,+) constructor Two args correspond to set and get operations int i = 1; int *p = &i; *p = 2; int j = *p; Ref (seti, i) 1 1

38 Pointers Handle pointers with a Ref(-,+) constructor Two args correspond to set and get operations int i = 1; int *p = &i; *p = 2; int j = *p; Ref (seti, i) 1 1 p p

39 Pointers Handle pointers with a Ref(-,+) constructor Two args correspond to set and get operations int i = 1; int *p = &i; *p = 2; int j = *p; Ref (seti, i) 1 1 p p

40 Pointers Handle pointers with a Ref(-,+) constructor Two args correspond to set and get operations int i = 1; int *p = &i; *p = 2; int j = *p; Ref (seti, i) 1 1 p p Ref ( 2, _)

41 Pointers Handle pointers with a Ref(-,+) constructor Two args correspond to set and get operations int i = 1; int *p = &i; *p = 2; int j = *p; Ref (seti, i) 1 1 p p Ref ( 2, _)

42 Pointers Handle pointers with a Ref(-,+) constructor Two args correspond to set and get operations int i = 1; int *p = &i; *p = 2; int j = *p; Ref (seti, i) 1 1 p p Ref ( 2, _)

43 Pointers Handle pointers with a Ref(-,+) constructor Two args correspond to set and get operations int i = 1; int *p = &i; *p = 2; int j = *p; Ref (seti, i) 1 1 p p Ref ( 2, _) Ref ( _, j)

44 Pointers Handle pointers with a Ref(-,+) constructor Two args correspond to set and get operations int i = 1; int *p = &i; *p = 2; int j = *p; Ref (seti, i) 1 1 p p Ref ( 2, _) Ref ( _, j)

45 Pointers Handle pointers with a Ref(-,+) constructor Two args correspond to set and get operations int i = 1; int *p = &i; *p = 2; int j = *p; Ref (seti, i) 1 1 p p Ref ( 2, _) Ref ( _, j) [[j]] =

46 Pointers Handle pointers with a Ref(-,+) constructor Two args correspond to set and get operations int i = 1; int *p = &i; *p = 2; int j = *p; Ref (seti, i) 1 1 p p Ref ( 2, _) Ref ( _, j) [[j]] = {1, 2}

47 More on functions Our encoding supports higher-order functions – Passing around Fun terms just like constants Function pointers also just work int (*funcPtr)(int); int foo(int i) { return i }; funcPtr = &foo; int x = (*funcPtr)(0);

48 More on functions Our encoding supports higher-order functions – Passing around Fun terms just like constants Function pointers also just work int (*funcPtr)(int); int foo(int i) { return i }; funcPtr = &foo; int x = (*funcPtr)(0); funcPtr

49 More on functions Our encoding supports higher-order functions – Passing around Fun terms just like constants Function pointers also just work int (*funcPtr)(int); int foo(int i) { return i }; funcPtr = &foo; int x = (*funcPtr)(0); funcPtr

50 More on functions Our encoding supports higher-order functions – Passing around Fun terms just like constants Function pointers also just work int (*funcPtr)(int); int foo(int i) { return i }; funcPtr = &foo; int x = (*funcPtr)(0); funcPtr Fun (i, ret) foo

51 More on functions Our encoding supports higher-order functions – Passing around Fun terms just like constants Function pointers also just work int (*funcPtr)(int); int foo(int i) { return i }; funcPtr = &foo; int x = (*funcPtr)(0); funcPtr Fun (i, ret) foo

52 More on functions Our encoding supports higher-order functions – Passing around Fun terms just like constants Function pointers also just work int (*funcPtr)(int); int foo(int i) { return i }; funcPtr = &foo; int x = (*funcPtr)(0); funcPtr Fun (i, ret) Ref (setF, foo)

53 More on functions Our encoding supports higher-order functions – Passing around Fun terms just like constants Function pointers also just work int (*funcPtr)(int); int foo(int i) { return i }; funcPtr = &foo; int x = (*funcPtr)(0); Fun (i, ret) Ref (setF, foo) funcPtr

54 More on functions Our encoding supports higher-order functions – Passing around Fun terms just like constants Function pointers also just work int (*funcPtr)(int); int foo(int i) { return i }; funcPtr = &foo; int x = (*funcPtr)(0); funcPtr Fun (i, ret) Ref (setF, foo)

55 More on functions Our encoding supports higher-order functions – Passing around Fun terms just like constants Function pointers also just work int (*funcPtr)(int); int foo(int i) { return i }; funcPtr = &foo; int x = (*funcPtr)(0); funcPtr Fun (i, ret) Ref (setF, foo)

56 More on functions Our encoding supports higher-order functions – Passing around Fun terms just like constants Function pointers also just work int (*funcPtr)(int); int foo(int i) { return i }; funcPtr = &foo; int x = (*funcPtr)(0); funcPtr Fun (i, ret) Ref (setF, foo) Ref ( _, Fun (0, x )

57 More on functions Our encoding supports higher-order functions – Passing around Fun terms just like constants Function pointers also just work int (*funcPtr)(int); int foo(int i) { return i }; funcPtr = &foo; int x = (*funcPtr)(0); funcPtr Fun (i, ret) Ref (setF, foo) Ref ( _, Fun (0, x )

58 More on functions Our encoding supports higher-order functions – Passing around Fun terms just like constants Function pointers also just work int (*funcPtr)(int); int foo(int i) { return i }; funcPtr = &foo; int x = (*funcPtr)(0); funcPtr Fun (i, ret) Ref (setF, foo) Ref ( _, Fun (0, x )

59 Context sensitivity Smearing call sites int x = id(1); int y = id(2); Fun (j, r) id Fun (1, x) Fun (2, y) [[x]] = {1, 2} [[y]] = {1, 2}

60 Context sensitivity Smearing call sites int x = id(1); int y = id(2); Option 1: Specialization Each call id i gets a new copy of id Eliminates smearing, but graph size increases Fun (j, r) id Fun (1, x) Fun (2, y) Fun (j, r) id 1 Fun (1, x) Fun (j, r) id 2 Fun (2, y) [[x]] = {1, 2} [[y]] = {1, 2}

61 Context sensitivity Option 2: Unique labeled edges for each call site Not using Fun constructor There is flow only if there is a path that spells a substring of a well-bracketed string – [ a [ b ] b ] a and [ a ] a [ b are valid; [ a [ b ] a ] b is not For both options, if there are higher-order functions or function pointers, need a first pass to compute pointer targets j j r r 1 1 x x 2 2 y y [1[1 ]1]1 [2[2 ]2]2

62 Field sensitivity For each field f, define Fld f (-,+) constructor int readG(obj p) { return p.g; } obj o; o.f = 3; o.g = 4; int w = id(o.f); int z = readG(o); Fun (j, ret2) id

63 Field sensitivity int readG(obj p) { return p.g; } obj o; o.f = 3; o.g = 4; int w = id(o.f); int z = readG(o); Fun (j, ret2) id For each field f, define Fld f (-,+) constructor

64 Field sensitivity int readG(obj p) { return p.g; } obj o; o.f = 3; o.g = 4; int w = id(o.f); int z = readG(o); Fun (j, ret2) id For each field f, define Fld f (-,+) constructor Fun (p, ret3) readG Fld g (_, )

65 Field sensitivity int readG(obj p) { return p.g; } obj o; o.f = 3; o.g = 4; int w = id(o.f); int z = readG(o); Fun (j, ret2) id For each field f, define Fld f (-,+) constructor Fun (p, ret3) readG Fld g (_, )

66 Field sensitivity int readG(obj p) { return p.g; } obj o; o.f = 3; o.g = 4; int w = id(o.f); int z = readG(o); Fun (j, ret2) id For each field f, define Fld f (-,+) constructor Fun (p, ret3) readG Fld g (_, ) o o Fld g (_, og) Fld f (_, of)

67 Field sensitivity int readG(obj p) { return p.g; } obj o; o.f = 3; o.g = 4; int w = id(o.f); int z = readG(o); Fun (j, ret2) id For each field f, define Fld f (-,+) constructor Fun (p, ret3) readG Fld g (_, ) o o Fld g (_, og) Fld f (_, of)

68 Field sensitivity int readG(obj p) { return p.g; } obj o; o.f = 3; o.g = 4; int w = id(o.f); int z = readG(o); Fun (j, ret2) id For each field f, define Fld f (-,+) constructor Fun (p, ret3) readG Fld g (_, ) o o Fld g (_, og) Fld f (_, of) Fld f (3, _) Fld g (4, _)

69 Field sensitivity int readG(obj p) { return p.g; } obj o; o.f = 3; o.g = 4; int w = id(o.f); int z = readG(o); Fun (j, ret2) id For each field f, define Fld f (-,+) constructor Fun (p, ret3) readG Fld g (_, ) o o Fld g (_, og) Fld f (_, of) Fld f (3, _) Fld g (4, _)

70 Field sensitivity int readG(obj p) { return p.g; } obj o; o.f = 3; o.g = 4; int w = id(o.f); int z = readG(o); Fun (j, ret2) id For each field f, define Fld f (-,+) constructor Fun (p, ret3) readG Fld g (_, ) o o Fld g (_, og) Fld f (_, of) Fun (, w ) Fld f (_, ) Fld f (3, _) Fld g (4, _)

71 Field sensitivity int readG(obj p) { return p.g; } obj o; o.f = 3; o.g = 4; int w = id(o.f); int z = readG(o); Fun (j, ret2) id For each field f, define Fld f (-,+) constructor Fun (p, ret3) readG Fld g (_, ) o o Fld g (_, og) Fld f (_, of) Fun (, w ) Fld f (_, ) Fld f (3, _) Fld g (4, _)

72 Field sensitivity int readG(obj p) { return p.g; } obj o; o.f = 3; o.g = 4; int w = id(o.f); int z = readG(o); Fun (j, ret2) id For each field f, define Fld f (-,+) constructor Fun (p, ret3) readG Fld g (_, ) o o Fld g (_, og) Fld f (_, of) Fun (, z ) Fun (, w ) Fld f (_, ) Fld f (3, _) Fld g (4, _)

73 Scalability Constraint graph for entire program is in memory Even for flow-insensitive analyses, this can become a bottleneck Even worse for flow-sensitive analyses Techniques for analyzing parts of program in isolation and storing summaries of their observable effects

74 Summary Set constraints are often natural for expressing various program analyses – Constant propagation, pointer analysis – Closure analysis – Receiver class analysis – Information flow Rich literature on solving systems of constraints Non-trivial to extend to flow-sensitive or summary-based analyses Interference between functions and references


Download ppt "Program Analysis with Set Constraints Ravi Chugh."

Similar presentations


Ads by Google