Advertisement
Guest User

Untitled

a guest
May 5th, 2015
226
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Scala 9.18 KB | None | 0 0
  1. package tip.analysis
  2.  
  3. import tip.ast
  4. import tip.ast._
  5. import tip.lattices._
  6. import tip.graph._
  7. import tip.solvers._
  8. import tip.graph.NodeOps._
  9.  
  10. object SignAnalysisCommons {
  11.   val returnId = AIdentifier(s"#result", Loc(0, 0))()
  12. }
  13.  
  14. /**
  15.  * Transfer functions for sign analysis (intraprocedural only).
  16.  */
  17. trait IntraprocSignAnalysisTransferFunctions {
  18.  
  19.   type Sign = SignLattice.SignElement.Value
  20.  
  21.   import SignLattice.SignElement._
  22.  
  23.   val domain: Set[GNode[AstNode]]
  24.  
  25.   val declaredVars = domain.map {_.declaredIdsIncludingParams}.flatten
  26.  
  27.   val statelattice = new MapLattice(declaredVars, SignLattice)
  28.  
  29.   /**
  30.    * The transfer functions.
  31.    */
  32.   def transfer(n: GNode[AstNode], s: statelattice.Element): statelattice.Element = {
  33.     NoPointer.checkCfgNodeLanguageRestriction(n)
  34.     import NoPointer._
  35.     n match {
  36.       case r: GRealNode[AstNode] =>
  37.         r.data match {
  38.          
  39.           // var declarations
  40.           case varr: AVarStmt =>
  41.             varr.declIds.foldLeft(s)( (acc, id) => acc + (id -> Top) )
  42.            
  43.           // assignments
  44.           case ass: AAssignStmt =>
  45.             val id = ass.leftId
  46.             val vdef = id.meta.definition match {
  47.               case Some(x: AIdentifier) => x
  48.               case Some(y) => unsupportedError(y)
  49.               case _ => throw new IllegalArgumentException(s"No definition found for $id")
  50.             }
  51.             try {
  52.               s + (vdef -> statelattice.l.eval(ass.right, s))
  53.             }
  54.             catch {
  55.               case e: Exception => unsupportedError(ass)
  56.             }
  57.            
  58.           // all others: like no-ops
  59.           case _ => s
  60.         }
  61.       case _ => s
  62.     }
  63.   }
  64.  
  65.   private def unsupportedError(x: Any) = throw new IllegalArgumentException(s"Sign analysis meant to be run on programs without $x")
  66. }
  67.  
  68. /**
  69.  * Variant of [[tip.analysis.ForwardDependencies]] that includes call and return edges.
  70.  */
  71. trait SimpleInterproceduralDependencies extends Dependencies[GNode[AstNode]] {
  72.  
  73.   val cfg: ProgramCFG
  74.  
  75.   import cfg._
  76.  
  77.   override def dep(n: GNode[AstNode]) = n.succ.toSet ++ n.called ++ n.callersAfterCall
  78.  
  79.   override def invdep(n: GNode[AstNode]) = n.pred.toSet ++ n.calledExits ++ n.callers
  80. }
  81.  
  82. /**
  83.  * Common functionality for interprocedural analysis.
  84.  */
  85. trait InterprocSignAnalysisMisc {
  86.  
  87.   val lattice: MapLattice[GNode[AstNode], LiftLattice[MapLattice[AIdentifier, SignLattice.type]]]
  88.  
  89.   val cfg: ProgramCFG
  90.  
  91.   NormalisedCallsLanguageRestrictions.checkCfgLanguageRestriction(cfg)
  92.   NoPointer.checkCfgLanguageRestriction(cfg)
  93.  
  94.   def evalArgs(formalParams: Seq[AIdentifier], actualParams: Seq[AExpr], state: lattice.l.l.Element): lattice.l.l.Element = {
  95.     formalParams.zip(actualParams).foldLeft(lattice.l.l.bottom) { case (acc, (id, exp)) =>
  96.       acc + (id -> lattice.l.l.l.eval(exp, state))
  97.     }
  98.   }
  99. }
  100.  
  101. /**
  102.  * Transfer functions for sign analysis (including interprocedural).
  103.  * This version is for the basic worklist algorithm.
  104.  */
  105. trait InterprocSignAnalysisTransferFunctions extends MapLiftLatticeTransfer[GNode[AstNode]] with InterprocSignAnalysisMisc {
  106.  
  107.   override def transfer(n: GNode[AstNode], s: lattice.l.Element, o: lattice.Element): lattice.l.Element = {
  108.     import cfg._
  109.     import NormalisedCallsLanguageRestrictions._
  110.     import lattice.l._
  111.  
  112.     n match {
  113.      
  114.       // call nodes (like no-ops here)
  115.       case call: CallNode[AstNode] => join(n, s, o)
  116.  
  117.       // function entry nodes
  118.       case funentry: FunEntry[AstNode] => {
  119.         val fun = funentry.data.asInstanceOf[AFunDeclaration]
  120.         val callSites = funentry.callers
  121.         callSites.foldRight(s)((x, a) =>
  122.           lattice.l.l.lub(a, evalArgs(fun.args, x.invocation.args, a))
  123.         )
  124.       }
  125.  
  126.       // function exit nodes (like no-ops here)
  127.       case funexit: FunExit[AstNode] => join(n, s, o)
  128.  
  129.       // after-call nodes
  130.       case aftercall: AfterCallNode[AstNode] => {
  131.         val id = aftercall.assignment.leftId
  132.         val idDef = id.meta.definition.get.asInstanceOf[AIdentifier]
  133.         val vprime = o(aftercall.pred.head)
  134.         val w = o(aftercall.calledExits.get)
  135.         vprime + (idDef -> w(SignAnalysisCommons.returnId))
  136.       }
  137.  
  138.       case GRealNode(_, _,_ , ret: AReturnStmt) => {
  139.         val j = join(n, s, o)
  140.         j + (SignAnalysisCommons.returnId -> lattice.l.l.l.eval(ret.value, j))
  141.       }
  142.  
  143.       case _ => super.transfer(n, s, o)
  144.     }
  145.   }
  146. }
  147.  
  148. /**
  149.  * Transfer functions for sign analysis (including interprocedural), propagation style.
  150.  * This is a variant of [[InterprocSignAnalysisTransferFunctions]] for use with [[tip.solvers.PropagationStrategy]].
  151.  */
  152. trait InterprocSignAnalysisTransferFunctionsWithPropagation extends MapLiftLatticeTransfer[GNode[AstNode]]
  153.   with PropagationStrategy[GNode[AstNode]] with InterprocSignAnalysisMisc {
  154.  
  155.   override def transfer(n: GNode[AstNode], s: lattice.l.Element, o: lattice.Element): lattice.l.Element = {
  156.     import cfg._
  157.     import NormalisedCallsLanguageRestrictions._
  158.     import lattice.l._
  159.    
  160.     // helper function that propagates dataflow from a function exit node to an after-call node
  161.     def returnflow(funexit: FunExit[AstNode], aftercall: AfterCallNode[AstNode]) {
  162.       val id = aftercall.assignment().leftId()
  163.       propagate(o(aftercall.pred.head) + (id.meta.definition.get.asInstanceOf[AIdentifier] -> s(SignAnalysisCommons.returnId)), aftercall)
  164.     }
  165.  
  166.     n match {
  167.  
  168.       // call nodes
  169.       case call: CallNode[AstNode] => {
  170.         val calledFun = call.called.get.data.asInstanceOf[AFunDeclaration]
  171.         propagate(evalArgs(calledFun.args, call.invocation.args, s), call.called.head)
  172.         returnflow(call.succ.head.calledExits.head, call.succ.head.asInstanceOf[AfterCallNode[AstNode]]) // make sure existing return flow gets propagated
  173.         lattice.l.bottom // no flow directly to the after-call node
  174.       }
  175.  
  176.       // function entry nodes (like no-op here)
  177.       case funentry: FunEntry[AstNode] => s
  178.      
  179.       // function exit nodes
  180.       case funexit: FunExit[AstNode] => {
  181.         for (aftercall <- funexit.callersAfterCall) returnflow(funexit, aftercall)
  182.         lattice.l.bottom // no successors for this kind of node, but we have to return something
  183.       }
  184.      
  185.       // after-call nodes (like no-op here)
  186.       case aftercall: AfterCallNode[AstNode] => s
  187.  
  188.       case GRealNode(_, _,_ , ret: AReturnStmt) => {
  189.         s + (SignAnalysisCommons.returnId -> lattice.l.l.l.eval(ret.value, s))
  190.       }
  191.  
  192.       case _ => super.transfer(n, s, o)
  193.     }
  194.   }
  195. }
  196.  
  197. /**
  198.  * Base class for intra-procedural sign analysis.
  199.  */
  200. abstract class IntraprocSignAnalysis(cfg: ControlFlowGraph[AstNode]) extends FlowSensitiveAnalysis(cfg)
  201.   with IntraprocSignAnalysisTransferFunctions with MapLiftLatticeTransfer[GNode[AstNode]] with ForwardDependencies {
  202.  
  203.   /**
  204.    * The lattice for the analysis, which is the lattice of maps associating with
  205.    * each node a state, where the state is a map associating with each declared variable
  206.    * an element of the sign lattice.
  207.    */
  208.   val lattice = new MapLattice(cfg.nodes, new LiftLattice(statelattice))
  209. }
  210.  
  211. /**
  212.  * Intraprocedural sign analysis that uses [[tip.solvers.SimpleFixpointSolver]].
  213.  */
  214. class IntraprocSignAnalysisSimpleSolver(cfg: ControlFlowGraph[AstNode])
  215.   extends IntraprocSignAnalysis(cfg) with SimpleFixpointSolver with MapLatticeTransfer[GNode[AstNode]]
  216.  
  217. /**
  218.  * Intraprocedural sign analysis that uses [[tip.solvers.WorklistFixpointSolver]].
  219.  */
  220. class IntraprocSignAnalysisWorklistSolver(cfg: ControlFlowGraph[AstNode])
  221.   extends IntraprocSignAnalysis(cfg) with WorklistFixpointSolver[GNode[AstNode]]
  222.  
  223. /**
  224.  * Intraprocedural sign analysis that uses [[tip.solvers.WorklistFixpointSolverWithInit]].
  225.  */
  226. class IntraprocSignAnalysisWorklistSolverWithInit(cfg: ControlFlowGraph[AstNode])
  227.   extends IntraprocSignAnalysisWorklistSolver(cfg) with WorklistFixpointSolverWithInit[GNode[AstNode]] {
  228.  
  229.   val first = cfg.entries.values.toSet
  230. }
  231.  
  232. /**
  233.  * Intraprocedural sign analysis that uses [[tip.solvers.WorklistFixpointSolverWithInit]] with [[tip.solvers.PropagationStrategy]].
  234.  */
  235. class IntraprocSignAnalysisWorklistSolverWithInitAndPropagation(cfg: ControlFlowGraph[AstNode])
  236.   extends IntraprocSignAnalysisWorklistSolverWithInit(cfg) with PropagationStrategy[GNode[AstNode]] {
  237.  
  238.   override val init = lattice.l.Lift(lattice.l.l.bottom)
  239. }
  240.  
  241. /**
  242.  * Interprocedural sign analysis that uses [[tip.solvers.WorklistFixpointSolverWithInit]] with the basic worklist algorithm.
  243.  */
  244. class InterprocSignAnalysisWorklistSolverWithInit(override val cfg: ProgramCFG)
  245.   extends IntraprocSignAnalysisWorklistSolverWithInit(cfg) with InterprocSignAnalysisTransferFunctions
  246.   with SimpleInterproceduralDependencies {
  247.  
  248.   override val first = Set(cfg.programEntry)
  249. }
  250.  
  251. /**
  252.  * Interprocedural sign analysis that uses [[tip.solvers.WorklistFixpointSolverWithInit]] with [[tip.solvers.PropagationStrategy]].
  253.  */
  254. class InterprocSignAnalysisWorklistSolverWithInitAndPropagation(override val cfg: ProgramCFG)
  255.   extends IntraprocSignAnalysisWorklistSolverWithInitAndPropagation(cfg)
  256.   with InterprocSignAnalysisTransferFunctionsWithPropagation with ForwardDependencies {
  257.  
  258.   override val first = Set(cfg.programEntry)
  259. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement