Package it.unive.lisa.program.cfg
Class CFG
- java.lang.Object
-
- it.unive.lisa.util.datastructures.graph.code.CodeGraph<CFG,Statement,Edge>
-
- it.unive.lisa.program.cfg.CFG
-
- All Implemented Interfaces:
CodeMember
,Graph<CFG,Statement,Edge>
- Direct Known Subclasses:
CFGWithAnalysisResults
public class CFG extends CodeGraph<CFG,Statement,Edge> implements CodeMember
-
-
Field Summary
-
Fields inherited from class it.unive.lisa.util.datastructures.graph.code.CodeGraph
entrypoints, list
-
-
Constructor Summary
Constructors Constructor Description CFG(CFG other)
Clones the given control flow graph.CFG(CodeMemberDescriptor descriptor)
Builds the control flow graph.CFG(CodeMemberDescriptor descriptor, java.util.Collection<Statement> entrypoints, NodeList<CFG,Statement,Edge> list)
Builds the control flow graph.
-
Method Summary
All Methods Instance Methods Concrete Methods Modifier and Type Method Description void
addControlFlowStructure(ControlFlowStructure cf)
Adds the givenControlFlowStructure
to the ones contained in this cfg.<A extends AbstractState<A,H,V,T>,H extends HeapDomain<H>,V extends ValueDomain<V>,T extends TypeDomain<T>>
CFGWithAnalysisResults<A,H,V,T>fixpoint(AnalysisState<A,H,V,T> entryState, InterproceduralAnalysis<A,H,V,T> interprocedural, WorkingSet<Statement> ws, int widenAfter)
Computes a fixpoint over this control flow graph.<A extends AbstractState<A,H,V,T>,H extends HeapDomain<H>,V extends ValueDomain<V>,T extends TypeDomain<T>>
CFGWithAnalysisResults<A,H,V,T>fixpoint(AnalysisState<A,H,V,T> singleton, java.util.Map<Statement,AnalysisState<A,H,V,T>> startingPoints, InterproceduralAnalysis<A,H,V,T> interprocedural, WorkingSet<Statement> ws, int widenAfter)
Computes a fixpoint over this control flow graph.<A extends AbstractState<A,H,V,T>,H extends HeapDomain<H>,V extends ValueDomain<V>,T extends TypeDomain<T>>
CFGWithAnalysisResults<A,H,V,T>fixpoint(java.util.Collection<Statement> entrypoints, AnalysisState<A,H,V,T> entryState, InterproceduralAnalysis<A,H,V,T> interprocedural, WorkingSet<Statement> ws, int widenAfter)
Computes a fixpoint over this control flow graph.java.util.Collection<Statement>
getAllExitpoints()
Yields the statements of this control flow graph that are normal exitpoints, that is, that normally ends the execution of this cfg, returning the control to the caller, or throwing an error (i.e., all such statements on which eitherStatement.stopsExecution()
orStatement.throwsError()
hold).java.util.Collection<ControlFlowStructure>
getControlFlowStructures()
Yields the collection ofControlFlowStructure
s contained in this cfg.
Note that if no control flow structures have been provided by frontends, and no attempt at extracting them has been made yet, invoking this method will cause aControlFlowExtractor
to try to extract them.CodeMemberDescriptor
getDescriptor()
Yields the name of this control flow graph.ProgramPoint
getGenericProgramPoint()
Yields a genericProgramPoint
happening inside this cfg.java.util.Collection<Statement>
getGuards(ProgramPoint pp)
Yields the guard of all theControlFlowStructure
s, regardless of their type, containing the given program point.java.util.Collection<Statement>
getIfThenElseGuards(ProgramPoint pp)
Yields the guard of all theIfThenElse
containing the given program point.java.util.Collection<Statement>
getLoopGuards(ProgramPoint pp)
Yields the guard of allLoop
s containing the given program point.Statement
getMostRecentGuard(ProgramPoint pp)
Yields the guard of the most recentControlFlowStructure
, regardless of its type, containing the given program point.Statement
getMostRecentIfThenElseGuard(ProgramPoint pp)
Yields the guard of the most recentIfThenElse
containing the given program point.Statement
getMostRecentLoopGuard(ProgramPoint pp)
Yields the guard of the most recentLoop
containing the given program point.java.util.Collection<Statement>
getNormalExitpoints()
Yields the statements of this control flow graph that are normal exitpoints, that is, that normally ends the execution of this cfg, returning the control to the caller without throwing an error (i.e., all such statements on whichStatement.stopsExecution()
holds butStatement.throwsError()
does not).boolean
isGuarded(ProgramPoint pp)
Yieldstrue
if and only if the given program point is inside the body of aControlFlowStructure
, regardless of its type.
Note that if no control flow structures have been provided by frontends, and no attempt at extracting them has been made yet, invoking this method will cause aControlFlowExtractor
to try to extract them.boolean
isInsideIfThenElse(ProgramPoint pp)
Yieldstrue
if and only if the given program point is inside one of the branches of anIfThenElse
.
Note that if no control flow structures have been provided by frontends, and no attempt at extracting them has been made yet, invoking this method will cause aControlFlowExtractor
to try to extract them.boolean
isInsideLoop(ProgramPoint pp)
Yieldstrue
if and only if the given program point is inside the body of aLoop
.
Note that if no control flow structures have been provided by frontends, and no attempt at extracting them has been made yet, invoking this method will cause aControlFlowExtractor
to try to extract them.void
preSimplify(Statement node)
Callback that is invoked on a node before simplifying it.void
simplify()
Simplifies this cfg, removing allNoOp
s and rewriting the edge set accordingly.SerializableGraph
toSerializableGraph(java.util.function.Function<Statement,SerializableValue> descriptionGenerator)
Yields an instance ofSerializableGraph
built from this one.java.lang.String
toString()
void
validate()
Validates this cfg, ensuring that the code contained in it is well formed.-
Methods inherited from class it.unive.lisa.util.datastructures.graph.code.CodeGraph
addEdge, addNode, addNode, containsEdge, containsNode, followersOf, getEdgeConnecting, getEdges, getEdgesConnecting, getEdgesCount, getEntrypoints, getIngoingEdges, getNodeList, getNodes, getNodesCount, getOutgoingEdges, isEqualTo, predecessorsOf, simplify
-
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
-
Methods inherited from interface it.unive.lisa.util.datastructures.graph.Graph
accept, toSerializableGraph
-
-
-
-
Constructor Detail
-
CFG
public CFG(CodeMemberDescriptor descriptor)
Builds the control flow graph.- Parameters:
descriptor
- the descriptor of this cfg
-
CFG
public CFG(CodeMemberDescriptor descriptor, java.util.Collection<Statement> entrypoints, NodeList<CFG,Statement,Edge> list)
Builds the control flow graph.- Parameters:
descriptor
- the descriptor of this cfgentrypoints
- the statements of this cfg that will be reachable from other cfgslist
- the node list containing all the statements and the edges that will be part of this cfg
-
CFG
public CFG(CFG other)
Clones the given control flow graph.- Parameters:
other
- the original cfg
-
-
Method Detail
-
getDescriptor
public final CodeMemberDescriptor getDescriptor()
Yields the name of this control flow graph.- Specified by:
getDescriptor
in interfaceCodeMember
- Returns:
- the name
-
getNormalExitpoints
public java.util.Collection<Statement> getNormalExitpoints()
Yields the statements of this control flow graph that are normal exitpoints, that is, that normally ends the execution of this cfg, returning the control to the caller without throwing an error (i.e., all such statements on whichStatement.stopsExecution()
holds butStatement.throwsError()
does not).- Returns:
- the normal exitpoints of this cfg.
-
getAllExitpoints
public java.util.Collection<Statement> getAllExitpoints()
Yields the statements of this control flow graph that are normal exitpoints, that is, that normally ends the execution of this cfg, returning the control to the caller, or throwing an error (i.e., all such statements on which eitherStatement.stopsExecution()
orStatement.throwsError()
hold).- Returns:
- the exitpoints of this cfg.
-
addControlFlowStructure
public void addControlFlowStructure(ControlFlowStructure cf)
Adds the givenControlFlowStructure
to the ones contained in this cfg.- Parameters:
cf
- the control flow structure to add- Throws:
java.lang.IllegalArgumentException
- if a control flow structure for the same condition already exists
-
getControlFlowStructures
public java.util.Collection<ControlFlowStructure> getControlFlowStructures()
Yields the collection ofControlFlowStructure
s contained in this cfg.
Note that if no control flow structures have been provided by frontends, and no attempt at extracting them has been made yet, invoking this method will cause aControlFlowExtractor
to try to extract them.- Returns:
- the collection, either provided by frontends or extracted, of the control flow structures of this method
-
toString
public java.lang.String toString()
-
simplify
public void simplify()
Simplifies this cfg, removing allNoOp
s and rewriting the edge set accordingly. This method will throw anUnsupportedOperationException
if one of theNoOp
s has an outgoing edge that is not aSequentialEdge
, since such statement is expected to always be sequential.- Throws:
java.lang.UnsupportedOperationException
- if there exists at least oneNoOp
with an outgoing non-sequential edge.
-
fixpoint
public <A extends AbstractState<A,H,V,T>,H extends HeapDomain<H>,V extends ValueDomain<V>,T extends TypeDomain<T>> CFGWithAnalysisResults<A,H,V,T> fixpoint(AnalysisState<A,H,V,T> entryState, InterproceduralAnalysis<A,H,V,T> interprocedural, WorkingSet<Statement> ws, int widenAfter) throws FixpointException
Computes a fixpoint over this control flow graph. This method returns aCFGWithAnalysisResults
instance mapping eachStatement
to theAnalysisState
computed by this method. The computation usesLattice.lub(Lattice)
to compose results obtained at different iterations, up towidenAfter * predecessors_number
times, wherepredecessors_number
is the number of expressions that are predecessors of the one being processed. After overcoming that threshold,Lattice.widening(Lattice)
is used. The computation starts at the statements returned byCodeGraph.getEntrypoints()
, usingentryState
as entry state for all of them.interprocedural
will be invoked to get the approximation of all invoked cfgs, whilews
is used as working set for the statements to process.- Type Parameters:
A
- the type ofAbstractState
contained into the analysis stateH
- the type ofHeapDomain
contained into the computed abstract stateV
- the type ofValueDomain
contained into the computed abstract stateT
- the type ofTypeDomain
contained into the computed abstract state- Parameters:
entryState
- the entry states to apply to eachStatement
returned byCodeGraph.getEntrypoints()
interprocedural
- the interprocedural analysis that can be queried when a call towards an other cfg is encounteredws
- theWorkingSet
instance to use for this computationwidenAfter
- the number of times after which theLattice.lub(Lattice)
invocation gets replaced by theLattice.widening(Lattice)
call. Use0
to always useLattice.lub(Lattice)
- Returns:
- a
CFGWithAnalysisResults
instance that is equivalent to this control flow graph, and that stores for eachStatement
the result of the fixpoint computation - Throws:
FixpointException
- if an error occurs during the semantic computation of a statement, or if some unknown/invalid statement ends up in the working set
-
fixpoint
public <A extends AbstractState<A,H,V,T>,H extends HeapDomain<H>,V extends ValueDomain<V>,T extends TypeDomain<T>> CFGWithAnalysisResults<A,H,V,T> fixpoint(java.util.Collection<Statement> entrypoints, AnalysisState<A,H,V,T> entryState, InterproceduralAnalysis<A,H,V,T> interprocedural, WorkingSet<Statement> ws, int widenAfter) throws FixpointException
Computes a fixpoint over this control flow graph. This method returns aCFGWithAnalysisResults
instance mapping eachStatement
to theAnalysisState
computed by this method. The computation usesLattice.lub(Lattice)
to compose results obtained at different iterations, up towidenAfter * predecessors_number
times, wherepredecessors_number
is the number of expressions that are predecessors of the one being processed. After overcoming that threshold,Lattice.widening(Lattice)
is used. The computation starts at the statements inentrypoints
, usingentryState
as entry state for all of them.interprocedural
will be invoked to get the approximation of all invoked cfgs, whilews
is used as working set for the statements to process.- Type Parameters:
A
- the type ofAbstractState
contained into the analysis stateH
- the type ofHeapDomain
contained into the computed abstract stateV
- the type ofValueDomain
contained into the computed abstract stateT
- the type ofTypeDomain
contained into the computed abstract state- Parameters:
entrypoints
- the collection ofStatement
s that to use as a starting point of the computation (that must be nodes of this cfg)entryState
- the entry states to apply to eachStatement
inentrypoints
interprocedural
- the callgraph that can be queried when a call towards an other cfg is encounteredws
- theWorkingSet
instance to use for this computationwidenAfter
- the number of times after which theLattice.lub(Lattice)
invocation gets replaced by theLattice.widening(Lattice)
call. Use0
to always useLattice.lub(Lattice)
- Returns:
- a
CFGWithAnalysisResults
instance that is equivalent to this control flow graph, and that stores for eachStatement
the result of the fixpoint computation - Throws:
FixpointException
- if an error occurs during the semantic computation of a statement, or if some unknown/invalid statement ends up in the working set
-
fixpoint
public <A extends AbstractState<A,H,V,T>,H extends HeapDomain<H>,V extends ValueDomain<V>,T extends TypeDomain<T>> CFGWithAnalysisResults<A,H,V,T> fixpoint(AnalysisState<A,H,V,T> singleton, java.util.Map<Statement,AnalysisState<A,H,V,T>> startingPoints, InterproceduralAnalysis<A,H,V,T> interprocedural, WorkingSet<Statement> ws, int widenAfter) throws FixpointException
Computes a fixpoint over this control flow graph. This method returns aCFGWithAnalysisResults
instance mapping eachStatement
to theAnalysisState
computed by this method. The computation usesLattice.lub(Lattice)
to compose results obtained at different iterations, up towidenAfter * predecessors_number
times, wherepredecessors_number
is the number of expressions that are predecessors of the one being processed. After overcoming that threshold,Lattice.widening(Lattice)
is used. The computation starts at the statements instartingPoints
, using as its entry state their respective value.interprocedural
will be invoked to get the approximation of all invoked cfgs, whilews
is used as working set for the statements to process.- Type Parameters:
A
- the type ofAbstractState
contained into the analysis stateH
- the type ofHeapDomain
contained into the computed abstract stateV
- the type ofValueDomain
contained into the computed abstract stateT
- the type ofTypeDomain
contained into the computed abstract state- Parameters:
singleton
- an instance of theAnalysisState
containing the abstract state of the analysis to run, used to retrieve top and bottom valuesstartingPoints
- a map betweenStatement
s that to use as a starting point of the computation (that must be nodes of this cfg) and the entry states to apply on itinterprocedural
- the callgraph that can be queried when a call towards an other cfg is encounteredws
- theWorkingSet
instance to use for this computationwidenAfter
- the number of times after which theLattice.lub(Lattice)
invocation gets replaced by theLattice.widening(Lattice)
call. Use0
to always useLattice.lub(Lattice)
- Returns:
- a
CFGWithAnalysisResults
instance that is equivalent to this control flow graph, and that stores for eachStatement
the result of the fixpoint computation - Throws:
FixpointException
- if an error occurs during the semantic computation of a statement, or if some unknown/invalid statement ends up in the working set
-
toSerializableGraph
public SerializableGraph toSerializableGraph(java.util.function.Function<Statement,SerializableValue> descriptionGenerator)
Description copied from interface:Graph
Yields an instance ofSerializableGraph
built from this one. IfdescriptionGenerator
is notnull
,SerializableNodeDescription
for each node will be generated using it.- Specified by:
toSerializableGraph
in interfaceGraph<CFG,Statement,Edge>
- Overrides:
toSerializableGraph
in classCodeGraph<CFG,Statement,Edge>
- Parameters:
descriptionGenerator
- the function to be used for generating node descriptions, can benull
- Returns:
- a
SerializableGraph
instance
-
preSimplify
public void preSimplify(Statement node)
Description copied from class:CodeGraph
Callback that is invoked on a node before simplifying it.- Overrides:
preSimplify
in classCodeGraph<CFG,Statement,Edge>
- Parameters:
node
- the node about to be simplified
-
getGenericProgramPoint
public ProgramPoint getGenericProgramPoint()
Yields a genericProgramPoint
happening inside this cfg. A generic program point can be used for semantic evaluations of instrumentedStatement
s, that are not tied to any concrete statement.- Returns:
- a generic program point happening in this cfg
-
validate
public void validate() throws ProgramValidationException
Validates this cfg, ensuring that the code contained in it is well formed. This method checks that:- the underlying adjacency matrix is valid, through
AdjacencyMatrix.validate(Collection)
- all
ControlFlowStructure
s of this cfg contains node effectively in the cfg - all
Statement
s that stop the execution (according toStatement.stopsExecution()
) do not have outgoing edges - all
Statement
s that do not have outgoing edges stop the execution (according toStatement.stopsExecution()
) - all entrypoints are effectively part of this cfg
- Specified by:
validate
in interfaceCodeMember
- Throws:
ProgramValidationException
- if one of the aforementioned checks fail
- the underlying adjacency matrix is valid, through
-
isGuarded
public boolean isGuarded(ProgramPoint pp)
Yieldstrue
if and only if the given program point is inside the body of aControlFlowStructure
, regardless of its type.
Note that if no control flow structures have been provided by frontends, and no attempt at extracting them has been made yet, invoking this method will cause aControlFlowExtractor
to try to extract them.- Parameters:
pp
- the program point- Returns:
true
ifpp
is inside a control flow structure
-
isInsideLoop
public boolean isInsideLoop(ProgramPoint pp)
Yieldstrue
if and only if the given program point is inside the body of aLoop
.
Note that if no control flow structures have been provided by frontends, and no attempt at extracting them has been made yet, invoking this method will cause aControlFlowExtractor
to try to extract them.- Parameters:
pp
- the program point- Returns:
true
ifpp
is inside a loop
-
isInsideIfThenElse
public boolean isInsideIfThenElse(ProgramPoint pp)
Yieldstrue
if and only if the given program point is inside one of the branches of anIfThenElse
.
Note that if no control flow structures have been provided by frontends, and no attempt at extracting them has been made yet, invoking this method will cause aControlFlowExtractor
to try to extract them.- Parameters:
pp
- the program point- Returns:
true
ifpp
is inside an if-then-else
-
getGuards
public java.util.Collection<Statement> getGuards(ProgramPoint pp)
Yields the guard of all theControlFlowStructure
s, regardless of their type, containing the given program point. If the program point is not part of the body of a control structure, this method returns an empty collection.
Note that if no control flow structures have been provided by frontends, and no attempt at extracting them has been made yet, invoking this method will cause aControlFlowExtractor
to try to extract them.- Parameters:
pp
- the program point- Returns:
- the collection of the guards of all structures containing
pp
-
getLoopGuards
public java.util.Collection<Statement> getLoopGuards(ProgramPoint pp)
Yields the guard of allLoop
s containing the given program point. If the program point is not part of the body of a loop, this method returns an empty collection.
Note that if no control flow structures have been provided by frontends, and no attempt at extracting them has been made yet, invoking this method will cause aControlFlowExtractor
to try to extract them.- Parameters:
pp
- the program point- Returns:
- the collection of the guards of all loops containing
pp
-
getIfThenElseGuards
public java.util.Collection<Statement> getIfThenElseGuards(ProgramPoint pp)
Yields the guard of all theIfThenElse
containing the given program point. If the program point is not part of a branch of an if-then-else, this method returns an empty collection.
Note that if no control flow structures have been provided by frontends, and no attempt at extracting them has been made yet, invoking this method will cause aControlFlowExtractor
to try to extract them.- Parameters:
pp
- the program point- Returns:
- the collection of the guards of all if-then-elses containing
pp
-
getMostRecentGuard
public Statement getMostRecentGuard(ProgramPoint pp)
Yields the guard of the most recentControlFlowStructure
, regardless of its type, containing the given program point. If the program point is not part of the body of a control structure, this method returnsnull
.
Note that if no control flow structures have been provided by frontends, and no attempt at extracting them has been made yet, invoking this method will cause aControlFlowExtractor
to try to extract them.- Parameters:
pp
- the program point- Returns:
- the most recent if-then-else guard, or
null
-
getMostRecentLoopGuard
public Statement getMostRecentLoopGuard(ProgramPoint pp)
Yields the guard of the most recentLoop
containing the given program point. If the program point is not part of the body of a loop, this method returnsnull
.
Note that if no control flow structures have been provided by frontends, and no attempt at extracting them has been made yet, invoking this method will cause aControlFlowExtractor
to try to extract them.- Parameters:
pp
- the program point- Returns:
- the most recent loop guard, or
null
-
getMostRecentIfThenElseGuard
public Statement getMostRecentIfThenElseGuard(ProgramPoint pp)
Yields the guard of the most recentIfThenElse
containing the given program point. If the program point is not part of a branch of an if-then-else, this method returnsnull
.
Note that if no control flow structures have been provided by frontends, and no attempt at extracting them has been made yet, invoking this method will cause aControlFlowExtractor
to try to extract them.- Parameters:
pp
- the program point- Returns:
- the most recent if-then-else guard, or
null
-
-