Loading src/main/java/tfm/exec/PDGLog.java +2 −1 Original line number Diff line number Diff line Loading @@ -31,8 +31,9 @@ public class PDGLog extends GraphLog<PDG> { Logger.log(graph.vertexSet().stream() .sorted(Comparator.comparingInt(GraphNode::getId)) .map(node -> String.format("GraphNode { id: %s, declared: %s, defined: %s, used: %s }", String.format("GraphNode { id: %s, instruction: %s, declared: %s, defined: %s, used: %s }", node.getId(), node.getInstruction(), node.getDeclaredVariables(), node.getDefinedVariables(), node.getUsedVariables()) Loading src/main/java/tfm/graphs/Graph.java +4 −3 Original line number Diff line number Diff line package tfm.graphs; import com.github.javaparser.ast.Node; import org.jgrapht.graph.DefaultDirectedGraph; import org.jgrapht.graph.DirectedPseudograph; import org.jgrapht.io.DOTExporter; import tfm.arcs.Arc; import tfm.nodes.GraphNode; import tfm.nodes.NodeFactory; import tfm.utils.ASTUtils; import java.util.*; import java.util.function.Consumer; Loading @@ -14,7 +15,7 @@ import java.util.stream.Collectors; /** * * */ public abstract class Graph extends DefaultDirectedGraph<GraphNode<?>, Arc> { public abstract class Graph extends DirectedPseudograph<GraphNode<?>, Arc> { protected static final int DEFAULT_VERTEX_START_ID = 0; Loading Loading @@ -74,7 +75,7 @@ public abstract class Graph extends DefaultDirectedGraph<GraphNode<?>, Arc> { @SuppressWarnings("unchecked") public <ASTNode extends Node> Optional<GraphNode<ASTNode>> findNodeByASTNode(ASTNode astNode) { return vertexSet().stream() .filter(node -> Objects.equals(node.getAstNode(), astNode)) .filter(node -> ASTUtils.equalsWithRangeInCU(node.getAstNode(), astNode)) .findFirst() .map(node -> (GraphNode<ASTNode>) node); } Loading src/main/java/tfm/graphs/cfg/CFG.java +3 −3 Original line number Diff line number Diff line Loading @@ -37,10 +37,10 @@ public class CFG extends GraphWithRootNode<MethodDeclaration> { public Set<GraphNode<?>> findLastDefinitionsFrom(GraphNode<?> startNode, String variable) { if (!this.containsVertex(startNode)) throw new NodeNotFoundException(startNode, this); return findLastDefinitionsFrom(new HashSet<>(), startNode, startNode, variable); return findLastDefinitionsFrom(new HashSet<>(), startNode.getId(), startNode, variable); } private Set<GraphNode<?>> findLastDefinitionsFrom(Set<Integer> visited, GraphNode<?> startNode, GraphNode<?> currentNode, String variable) { private Set<GraphNode<?>> findLastDefinitionsFrom(Set<Integer> visited, int startNode, GraphNode<?> currentNode, String variable) { visited.add(currentNode.getId()); Set<GraphNode<?>> res = new HashSet<>(); Loading @@ -50,7 +50,7 @@ public class CFG extends GraphWithRootNode<MethodDeclaration> { continue; GraphNode<?> from = getEdgeSource(arc); if (!Objects.equals(startNode, from) && visited.contains(from.getId())) { if (!Objects.equals(startNode, from.getId()) && visited.contains(from.getId())) { continue; } Loading src/main/java/tfm/graphs/pdg/DataDependencyBuilder.java +11 −56 Original line number Diff line number Diff line package tfm.graphs.pdg; import com.github.javaparser.ast.Node; import com.github.javaparser.ast.stmt.*; import com.github.javaparser.ast.visitor.VoidVisitorAdapter; import tfm.graphs.cfg.CFG; import tfm.graphs.pdg.PDG; import tfm.nodes.GraphNode; import tfm.variables.VariableExtractor; import java.util.Optional; import java.util.Set; class DataDependencyBuilder extends VoidVisitorAdapter<Void> { Loading Loading @@ -43,17 +39,13 @@ class DataDependencyBuilder extends VoidVisitorAdapter<Void> { @Override public void visit(ForStmt forStmt, Void ignored) { GraphNode<ForStmt> forNode = pdg.findNodeByASTNode(forStmt).get(); forStmt.getInitialization().stream() .map(ExpressionStmt::new) .forEach(expressionStmt -> buildDataDependency(forNode, expressionStmt)); forStmt.getInitialization() .forEach(this::buildDataDependency); buildDataDependency(forStmt); // Only for comparison forStmt.getUpdate().stream() .map(ExpressionStmt::new) .forEach(expressionStmt -> buildDataDependency(forNode, expressionStmt)); forStmt.getUpdate() .forEach(this::buildDataDependency); forStmt.getBody().accept(this, null); } Loading @@ -79,51 +71,14 @@ class DataDependencyBuilder extends VoidVisitorAdapter<Void> { switchEntryStmt.getStatements().accept(this, null); } private void buildDataDependency(Statement statement) { buildDataDependency(pdg.findNodeByASTNode(statement).get()); private void buildDataDependency(Node node) { buildDataDependency(pdg.findNodeByASTNode(node).get()); } private void buildDataDependency(GraphNode<?> node) { new VariableExtractor() .setOnVariableUseListener(variable -> { node.addUsedVariable(variable); Optional<? extends GraphNode<?>> nodeOptional = cfg.findNodeByASTNode(node.getAstNode()); if (!nodeOptional.isPresent()) { return; } GraphNode<?> cfgNode = nodeOptional.get(); Set<GraphNode<?>> lastDefinitions = cfg.findLastDefinitionsFrom(cfgNode, variable); for (GraphNode<?> definitionNode : lastDefinitions) { pdg.findNodeByASTNode(definitionNode.getAstNode()) .ifPresent(pdgNode -> pdg.addDataDependencyArc(pdgNode, node, variable)); } }) .setOnVariableDefinitionListener(node::addDefinedVariable) .setOnVariableDeclarationListener(node::addDeclaredVariable) .visit(node.getAstNode()); for (String usedVariable : node.getUsedVariables()) { cfg.findLastDefinitionsFrom(node, usedVariable) .forEach(definitionNode -> pdg.addDataDependencyArc(definitionNode, node, usedVariable)); } // For statement special case private void buildDataDependency(GraphNode<?> forNode, Statement statement) { new VariableExtractor() .setOnVariableUseListener(variable -> { forNode.addUsedVariable(variable); Optional<? extends GraphNode<?>> nodeOptional = cfg.findNodeByASTNode(statement); if (!nodeOptional.isPresent()) { return; } pdg.addDataDependencyArc(forNode, forNode, variable); }) .setOnVariableDefinitionListener(forNode::addDefinedVariable) .setOnVariableDeclarationListener(forNode::addDeclaredVariable) .visit(statement); } } src/main/java/tfm/graphs/pdg/PDGBuilder.java +5 −3 Original line number Diff line number Diff line Loading @@ -5,6 +5,8 @@ import com.github.javaparser.ast.stmt.BlockStmt; import tfm.graphs.cfg.CFG; import tfm.nodes.GraphNode; import java.util.Objects; /** * Populates a {@link PDG}, given a complete {@link CFG}, an empty {@link PDG} and an AST root node. * For now it only accepts {@link MethodDeclaration} as root, as it can only receive a single CFG. Loading Loading @@ -47,9 +49,9 @@ public class PDGBuilder { cfg.build(methodDeclaration); // Copy nodes from CFG to PDG for (GraphNode<?> node : cfg.vertexSet()) if (!node.equals(cfg.getExitNode())) pdg.addVertex(node); cfg.vertexSet().stream() .filter(node -> !Objects.equals(node, cfg.getExitNode())) .forEach(node -> pdg.addVertex(node)); // Build control dependency ControlDependencyBuilder controlDependencyBuilder = new ControlDependencyBuilder(pdg, cfg); Loading Loading
src/main/java/tfm/exec/PDGLog.java +2 −1 Original line number Diff line number Diff line Loading @@ -31,8 +31,9 @@ public class PDGLog extends GraphLog<PDG> { Logger.log(graph.vertexSet().stream() .sorted(Comparator.comparingInt(GraphNode::getId)) .map(node -> String.format("GraphNode { id: %s, declared: %s, defined: %s, used: %s }", String.format("GraphNode { id: %s, instruction: %s, declared: %s, defined: %s, used: %s }", node.getId(), node.getInstruction(), node.getDeclaredVariables(), node.getDefinedVariables(), node.getUsedVariables()) Loading
src/main/java/tfm/graphs/Graph.java +4 −3 Original line number Diff line number Diff line package tfm.graphs; import com.github.javaparser.ast.Node; import org.jgrapht.graph.DefaultDirectedGraph; import org.jgrapht.graph.DirectedPseudograph; import org.jgrapht.io.DOTExporter; import tfm.arcs.Arc; import tfm.nodes.GraphNode; import tfm.nodes.NodeFactory; import tfm.utils.ASTUtils; import java.util.*; import java.util.function.Consumer; Loading @@ -14,7 +15,7 @@ import java.util.stream.Collectors; /** * * */ public abstract class Graph extends DefaultDirectedGraph<GraphNode<?>, Arc> { public abstract class Graph extends DirectedPseudograph<GraphNode<?>, Arc> { protected static final int DEFAULT_VERTEX_START_ID = 0; Loading Loading @@ -74,7 +75,7 @@ public abstract class Graph extends DefaultDirectedGraph<GraphNode<?>, Arc> { @SuppressWarnings("unchecked") public <ASTNode extends Node> Optional<GraphNode<ASTNode>> findNodeByASTNode(ASTNode astNode) { return vertexSet().stream() .filter(node -> Objects.equals(node.getAstNode(), astNode)) .filter(node -> ASTUtils.equalsWithRangeInCU(node.getAstNode(), astNode)) .findFirst() .map(node -> (GraphNode<ASTNode>) node); } Loading
src/main/java/tfm/graphs/cfg/CFG.java +3 −3 Original line number Diff line number Diff line Loading @@ -37,10 +37,10 @@ public class CFG extends GraphWithRootNode<MethodDeclaration> { public Set<GraphNode<?>> findLastDefinitionsFrom(GraphNode<?> startNode, String variable) { if (!this.containsVertex(startNode)) throw new NodeNotFoundException(startNode, this); return findLastDefinitionsFrom(new HashSet<>(), startNode, startNode, variable); return findLastDefinitionsFrom(new HashSet<>(), startNode.getId(), startNode, variable); } private Set<GraphNode<?>> findLastDefinitionsFrom(Set<Integer> visited, GraphNode<?> startNode, GraphNode<?> currentNode, String variable) { private Set<GraphNode<?>> findLastDefinitionsFrom(Set<Integer> visited, int startNode, GraphNode<?> currentNode, String variable) { visited.add(currentNode.getId()); Set<GraphNode<?>> res = new HashSet<>(); Loading @@ -50,7 +50,7 @@ public class CFG extends GraphWithRootNode<MethodDeclaration> { continue; GraphNode<?> from = getEdgeSource(arc); if (!Objects.equals(startNode, from) && visited.contains(from.getId())) { if (!Objects.equals(startNode, from.getId()) && visited.contains(from.getId())) { continue; } Loading
src/main/java/tfm/graphs/pdg/DataDependencyBuilder.java +11 −56 Original line number Diff line number Diff line package tfm.graphs.pdg; import com.github.javaparser.ast.Node; import com.github.javaparser.ast.stmt.*; import com.github.javaparser.ast.visitor.VoidVisitorAdapter; import tfm.graphs.cfg.CFG; import tfm.graphs.pdg.PDG; import tfm.nodes.GraphNode; import tfm.variables.VariableExtractor; import java.util.Optional; import java.util.Set; class DataDependencyBuilder extends VoidVisitorAdapter<Void> { Loading Loading @@ -43,17 +39,13 @@ class DataDependencyBuilder extends VoidVisitorAdapter<Void> { @Override public void visit(ForStmt forStmt, Void ignored) { GraphNode<ForStmt> forNode = pdg.findNodeByASTNode(forStmt).get(); forStmt.getInitialization().stream() .map(ExpressionStmt::new) .forEach(expressionStmt -> buildDataDependency(forNode, expressionStmt)); forStmt.getInitialization() .forEach(this::buildDataDependency); buildDataDependency(forStmt); // Only for comparison forStmt.getUpdate().stream() .map(ExpressionStmt::new) .forEach(expressionStmt -> buildDataDependency(forNode, expressionStmt)); forStmt.getUpdate() .forEach(this::buildDataDependency); forStmt.getBody().accept(this, null); } Loading @@ -79,51 +71,14 @@ class DataDependencyBuilder extends VoidVisitorAdapter<Void> { switchEntryStmt.getStatements().accept(this, null); } private void buildDataDependency(Statement statement) { buildDataDependency(pdg.findNodeByASTNode(statement).get()); private void buildDataDependency(Node node) { buildDataDependency(pdg.findNodeByASTNode(node).get()); } private void buildDataDependency(GraphNode<?> node) { new VariableExtractor() .setOnVariableUseListener(variable -> { node.addUsedVariable(variable); Optional<? extends GraphNode<?>> nodeOptional = cfg.findNodeByASTNode(node.getAstNode()); if (!nodeOptional.isPresent()) { return; } GraphNode<?> cfgNode = nodeOptional.get(); Set<GraphNode<?>> lastDefinitions = cfg.findLastDefinitionsFrom(cfgNode, variable); for (GraphNode<?> definitionNode : lastDefinitions) { pdg.findNodeByASTNode(definitionNode.getAstNode()) .ifPresent(pdgNode -> pdg.addDataDependencyArc(pdgNode, node, variable)); } }) .setOnVariableDefinitionListener(node::addDefinedVariable) .setOnVariableDeclarationListener(node::addDeclaredVariable) .visit(node.getAstNode()); for (String usedVariable : node.getUsedVariables()) { cfg.findLastDefinitionsFrom(node, usedVariable) .forEach(definitionNode -> pdg.addDataDependencyArc(definitionNode, node, usedVariable)); } // For statement special case private void buildDataDependency(GraphNode<?> forNode, Statement statement) { new VariableExtractor() .setOnVariableUseListener(variable -> { forNode.addUsedVariable(variable); Optional<? extends GraphNode<?>> nodeOptional = cfg.findNodeByASTNode(statement); if (!nodeOptional.isPresent()) { return; } pdg.addDataDependencyArc(forNode, forNode, variable); }) .setOnVariableDefinitionListener(forNode::addDefinedVariable) .setOnVariableDeclarationListener(forNode::addDeclaredVariable) .visit(statement); } }
src/main/java/tfm/graphs/pdg/PDGBuilder.java +5 −3 Original line number Diff line number Diff line Loading @@ -5,6 +5,8 @@ import com.github.javaparser.ast.stmt.BlockStmt; import tfm.graphs.cfg.CFG; import tfm.nodes.GraphNode; import java.util.Objects; /** * Populates a {@link PDG}, given a complete {@link CFG}, an empty {@link PDG} and an AST root node. * For now it only accepts {@link MethodDeclaration} as root, as it can only receive a single CFG. Loading Loading @@ -47,9 +49,9 @@ public class PDGBuilder { cfg.build(methodDeclaration); // Copy nodes from CFG to PDG for (GraphNode<?> node : cfg.vertexSet()) if (!node.equals(cfg.getExitNode())) pdg.addVertex(node); cfg.vertexSet().stream() .filter(node -> !Objects.equals(node, cfg.getExitNode())) .forEach(node -> pdg.addVertex(node)); // Build control dependency ControlDependencyBuilder controlDependencyBuilder = new ControlDependencyBuilder(pdg, cfg); Loading