270 likes | 375 Views
Interprocedural Analysis. Noam Rinetzky Mooly Sagiv http://www.math.tau.ac.il/~sagiv/courses/pa04.html Tel Aviv University 640-6706 Textbook Chapter 2.5. Outline. The trivial solution Why isn’t it adequate Challenges in interprocedural analysis Simplifying assumptions A naive solution
E N D
Interprocedural Analysis NoamRinetzky Mooly Sagiv http://www.math.tau.ac.il/~sagiv/courses/pa04.html Tel Aviv University 640-6706 Textbook Chapter 2.5
Outline • The trivial solution • Why isn’t it adequate • Challenges in interprocedural analysis • Simplifying assumptions • A naive solution • Join over valid paths • The functional approach • A case study linear constant propagation • Context free reachability • The call-string approach • Modularity issues • Other solutions
A Trivial treatment of procedures • Analyze a single procedure • After every call continue with conservative information • Global variables and local variables which “may be modified by the call” are mapped to • Can be easily implemented • Procedures can be written in different languages • Procedure inline can help • Side-effect analysis can help
Disadvantages of the trivial solution • Modular (object oriented and functional) programming encourages small frequently called procedures • Optimization • Modern machines allows the compiler to schedule many instructions in parallel • Need to optimize many instructions • Inline can be a bad solution • Software engineering • Many bugs result from interface misuse • Procedures define partial functions
Challenges in Interprocedural Analysis • Procedure nesting • Respect call-return mechanism • Handling recursion • Local variables • Parameter passing mechanisms: value, value-result, reference, by name • The called procedure is not always known • The source code of the called procedure is not always available • separate compilation • vendor code • ...
Simplifying Assumptions • All the code is available • Simple parameter passing • The called procedure is syntactically known • No nesting • Procedure names are syntactically different from variables • Procedures are uniquely defined • Recursion is supported
Extended Syntax of While P := begin D S end D := proc id(val id*, res id*) isl S endl’ | D D S := [x := a]l | [call p(a, z)]ll’ | [skip]l | S1 ; S2| if [b]l then S1 elseS2 | while [b]ldo S b := true | false | not b | b1 opb b2 | a1 opr a2 a := x | n | a1 opa a2
Fibonacci Example 0 begin proc fib 1 begin proc fib(val z, u, res v) is1 if [z <3]2 then [v := u + 1]3 else ( [call fib(z-1, u, v)]45 [call fib(z-2, v, v)]67 ) end8 [call fib(x, 0, y)]910 end11 2 9 call fib(x, 0, y) if z <3 3 3 v:=u+1 call fib(z-1, u, v) 4 call fib(z-1, u, v) 5 10 call fib(x, 0, y) call fib(z-2, v, v) 6 call fib(z-2, v, v) 7 11 end 8 end
Constant Example begin proc p(val a) is1 if [b]2 then ( [a := a -1]3 [call p(a)]45 [a := a + 1]6 ) [x := -2* a + 5]7 end8 [call p(7)]910 end
A naive Interprocedural solution • Treat procedure calls as gotos • Obtain a conservative solution • Find the least fixed point of the system: • Use Chaotic iterations DFentry(s) = DFentry(v) = {f(e)(DFentry(u) : (u, v) E}
Simple Example begin proc p(val a) is1 [x := a + 1]2 end3 [call p(7)]45 [print x]6 [call p(9)]78 [print x]9 end
Constant Example begin proc p(val a) is1 if [b]2 then ( [a := a -1]3 [call p(a)]45 [a := a + 1]6 ) [x := -2* a + 5]7 end8 [call p(7)]910 end
A More Precise Solution • Only considers matching calls and returns (valid) • Can be defined via context free grammar • Every call is a different letter • Matching calls and returns • The control flow graph can also be defined via context free grammar
Simple Example begin proc p(val a) is1 [x := a + 1]2 end3 [call p(7)]45 [print x]6 [call p(9)]78 [print x]9 end
Constant Example begin proc p(val a) is1 if [b]2 then ( [a := a -1]3 [call p(a)]45 [a := a + 1]6 ) [x := -2* a + 5]7 end8 [call p(7)]910 end
The Join-Over-Valid-Paths (JVP) • For a sequence of labels [l1, l2, …, ln] definef [l1, l2, …, ln]: L L by composing the effects of basic blocks • f[l](s)=s • f[l, p](s) = f[p](fl(s)) • JVPl = {f[l1, l2, …, l]() [l1, l2, …, l] vpaths(l)} • Compute a safe approximation to JVP • In some cases the JVP can be computed • Distributivity of f • Functional representation
The Call String Approach for Approximating JVP • No assumptions • Record at every node a pair (l, c) where l L is the dataflow information and c is a suffix of unmatched calls • Use Chaotic iterations • To guarantee termination limit the size of c (typically 1 or 2) • Emulates inline (but no code growth) • Exponential in C • For a finite lattice there exists a C which leads to join over all valid paths
Simple Example begin proc p(val a) is1 [x := a + 1]2 end3 [call p(7)]45 [print x]6 [call p(9)]78 [print x]9 end
Constant Example begin proc p(val a) is1 if [b]2 then ( [a := a -1]3 [call p(a)]45 [a := a + 1]6 ) [x := -2* a + 5]7 end8 [call p(7)]910 print x end
The Functional Approach • The meaning of a function is mapping from values of actual variables into states • The abstract meaning of a function is function from the abstract values of the numbers to abstract stores • Iterate on the abstract domain of functions from L to L
Motivating Example 0 begin proc p 1 2 call p(7) if … 9 a:=a-1 3 call p(a) 4 call p(7) 5 10 call p(a) 6 a:=a-1 11 print x 7 x:=-2*a+5 8 end end
Motivating Example(2) 0 begin proc p 1 2 call p(7) if … 9 3 a:=a-1 call p(a) 4 call p(7) 5 10 call p(a) 6 a:=a-1 11 print x 7 x:=-2*a+5 8 end end
Issues in Functional Approach • How to guarantee that finite height for functional lattice? • It may happen that L has finite height and yet the lattice of monotonic function from L to L do not • Efficiently represent functions • Functional join • Functional composition • Testing equality • Usually non-trivial • But can be done for distributive functions
Example Linear Constant Propagation • Consider the constant propagation lattice • The value of every variable y at the program exit can be represented by: y = {(axx + bx )| x Var* } c ax ,c Z {, } bx Z • Supports efficient composition and “functional” join • [z := a * y + b] • Computes JVP
Constant Example a=a. (a *1 + 0) begin proc p(val a) is1 if [b]2 then ( [a := a -1]3 [call p(a)]45 [a := a + 1]6 ) [x := -2* a + 5]7 end8 [call p(7)]910 end a. (a -1 + 0) a. (a -1 + 0) a. (a + 0) a. a
Functional Approach via Context Free Reachablity • The problem of computing reachability in a graph restricted by a context free grammar can be solved in cubic time • Can be used to compute JVP in arbitrary finite distributive data flow problems (not just bitvector) • Nodes in the graph correspond to individual facts • Efficient implementations exit (MOPED)
Conclusion • Handling functions is crucial for abstract interpretation • Virtual functions and exceptions complicate thinks • But scalability is an issue • Assume-guarantee helps • But relies on specifications