Download presentation
Presentation is loading. Please wait.
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
Similar presentations
© 2024 SlidePlayer.com. Inc.
All rights reserved.