package edg; import java.util.List; import java.util.Set; import java.util.function.Predicate; import edg.config.Config; import edg.constraint.*; import edg.edge.*; import edg.graph.Node; import edg.graph.EDG; import edg.graph.Edge; import edg.graph.LAST; public class EDGFactory { private final LAST last; private EDG edg; private final boolean interproceduralGraph; public EDGFactory(LAST last) { this(last, true); } public EDGFactory(LAST last, boolean interprocedural) { this.last = last; this.interproceduralGraph = interprocedural; } // Required Configuration Parameters (Questions made to the users in order to decide the dependencies built on the graph) private static boolean isOOLanguage = false; public EDG createEDG() { initializeEDG(); if (isOOLanguage) { // Only For OOPrograms With Inheritance and Types // LASTBuilder.addInheritanceInformation(edg); // LASTBuilder.completeFieldAccessTypes(edg); // new DynamicTypesGenerator(edg).generate(); } transformExpressionNodes(); generateDependencies(); return edg; } private void initializeEDG() { edg = new EDG(last); } private void transformExpressionNodes() { final List expressionNodes = edg.getNodes(node -> node.getInfo() != null && node.getInfo().isExpression()); for (Node expression : expressionNodes) createNodeResultStructures(expression); // TODO : When structural false edges are implemented, move this to LASTBuilder edg.vertexSet().stream() .filter(EDGFactory::isCallNode) .forEach(node -> { final Node parent = edg.getParent(node); edg.removeEDGEdge(parent, node, Edge.Type.Structural); edg.setRemovableEdge(parent, node, Edge.Type.Structural); }); } public static boolean isCallNode(Node node) { switch(node.getType()) { case Scope: case Name: case Arguments: case ArgumentIn: return true; default: return false; } } private void generateDependencies() { long initialControl = System.nanoTime(); new ControlEdgeGenerator(edg).generate(); long finalControl = System.nanoTime(); edg.getGenerationTime().setControlTime((finalControl-initialControl) / 1000000.0); // WE ARE NOT GENERATING INTERPROCEDURAL EDGES if (isOOLanguage) new InterproceduralEdgeGenerator(edg).generate(); // Specially Generated for OOPrograms else { long initialInputOutput = System.nanoTime(); if (interproceduralGraph) new InterproceduralEdgeGenerator(edg).generateErlang(); // long finalInputOutput = System.nanoTime(); edg.getGenerationTime().setInterproceduralTime((finalInputOutput-initialInputOutput) / 1000000.0); } long initialFlow = System.nanoTime(); new FlowEdgeGenerator(edg).generate(); long finalFlow = System.nanoTime(); edg.getGenerationTime().setFlowTime((finalFlow-initialFlow) / 1000000.0); // WE ARE NOT GENERATING SUMMARIES if (Config.summaries) new SummaryEdgeGenerator(edg).generate(); else //new SummaryEdgeGenerator(edg).generateAsExternal(); new SummaryEdgeGenerator(edg).generateOnlyExternal(); // new ExceptionEdgeGenerator(edg).generate(); } private void createNodeResultStructures(Node node) { // Conversion of 1 to 2 nodes & structural change final LDASTNodeInfo nodeInfo = node.getInfo(); final LDASTNodeInfo ldNodeInfo = new LDASTNodeInfo(nodeInfo.getFile(), nodeInfo.getClassName(), nodeInfo.getLine(), nodeInfo.getConstruction()); // Result Node final Node result = new Node("result", edg.getNextFictitiousId(), node.getSDGId(), Node.Type.Result, "", ldNodeInfo); final Node parent = last.getParent(node); edg.addVertex(result); edg.registerNodeResPair(node, result); // Remove the Structural edges if the parent is an expression -> The hidden structural edges inside nodes remain in the graph if (!parent.getType().isFictitious() && parent.getInfo().isExpression()) { // THIS IS AN EXCEPTION IN ORDER TO INCLUDE ROUTINES IN THE SLICE // WHEN CFG IS FINISHED THEY WILL BE INCLUDED BY CONTROL if (parent.getType() != Node.Type.Routine) { edg.removeEDGEdge(parent, node, Edge.Type.Structural); edg.setRemovableEdge(parent, node, Edge.Type.Structural); } } // Add the structural edge parent -> result to perform tree traversal (not considered for slicing) edg.addStructuralEdge(parent, result); // Modify Value Arcs if (node.getType() == Node.Type.DataConstructor && !edg.isPatternZone(node)) treatDataConstructorExpressions(node, result); else treatCommonNodes(node, result); // Value arcs between initial node and its result edg.addEdge(node, result, Edge.Type.Value); Set specialResultTypes = Set.of(Node.Type.Routine, Node.Type.Clause); if (specialResultTypes.contains(node.getType())) { createNodeResultStructuresSpecial(node, result); return; } // Modify CFG Arcs to add Results to the CFG final Set outgoingCFGEdges = edg.outgoingEdgesOf(node); outgoingCFGEdges.removeIf(Predicate.not(Edge::isControlFlowEdge)); if (!outgoingCFGEdges.isEmpty()) edg.addEdge(node, result, Edge.Type.ControlFlow); for (Edge cfgEdge : outgoingCFGEdges) { final Node to = edg.getEdgeTarget(cfgEdge); edg.removeEdge(cfgEdge); edg.addEdge(result, to, cfgEdge.getType()); } } private void createNodeResultStructuresSpecial(Node node, Node result) { switch(node.getType()) { case Routine: final Set incomingCFGEdges = edg.incomingEdgesOf(node); incomingCFGEdges.removeIf(Predicate.not(Edge::isControlFlowEdge)); for (Edge cfgEdge : incomingCFGEdges) { final Node from = edg.getEdgeSource(cfgEdge); edg.removeEdge(cfgEdge); edg.addEdge(from,result, cfgEdge.getType()); } break; case Clause: final Set incomingClauseCFGEdges = edg.incomingEdgesOf(node); incomingClauseCFGEdges.removeIf(Predicate.not(Edge::isControlFlowEdge)); for (Edge cfgEdge : incomingClauseCFGEdges) { final Node from = edg.getEdgeSource(cfgEdge); // ParameterOut type must be always connected to clause's result if (from.getType() == Node.Type.ParameterOut) { edg.removeEdge(cfgEdge); edg.addEdge(from, result, cfgEdge.getType()); } } final Set outgoingClauseCFGEdges = edg.outgoingEdgesOf(node); outgoingClauseCFGEdges.removeIf(Predicate.not(Edge::isControlFlowEdge)); for (Edge cfgEdge : outgoingClauseCFGEdges) { final Node finalToDestination = edg.getEdgeTarget(cfgEdge); Node to = finalToDestination; if (to.getType() == Node.Type.Result) to = edg.getNodeFromRes(to); if (to.getType() == Node.Type.Routine) { edg.removeEdge(cfgEdge); edg.addEdge(result, finalToDestination, cfgEdge.getType()); } } break; default: throw new IllegalArgumentException("The node has not an allowed type: " +node.getType()); } } private void treatCommonNodes(Node node, Node result) { final Set outgoingEdges = edg.outgoingEdgesOf(node); outgoingEdges.removeIf(edge -> edge.getType() != Edge.Type.Value); for (Edge valueEdge : outgoingEdges) { final Node to = edg.getEdgeTarget(valueEdge); final EdgeConstraint edgeConstraint = valueEdge.getConstraint(); edg.removeEdge(valueEdge); final Edge e = new Edge(Edge.Type.Value, edgeConstraint); edg.addEdge(result, to, e); } final Set incomingEdges = edg.incomingEdgesOf(node); incomingEdges.removeIf(edge -> edge.getType() != Edge.Type.Value); for (Edge valueEdge : incomingEdges) { final Node from = edg.getEdgeSource(valueEdge); final EdgeConstraint edgeConstraint = valueEdge.getConstraint(); if (node.getType() != Node.Type.Clause || !(edgeConstraint instanceof LiteralConstraint)) edg.removeEdge(valueEdge); final Edge e = new Edge(Edge.Type.Value, edgeConstraint); edg.addEdge(from, result, e); } } private void treatDataConstructorExpressions(Node dataConstructor, Node result) { deleteIncomingValueArcs(dataConstructor); modifyDataConstructorArcs(dataConstructor, result); } private void deleteIncomingValueArcs(Node dataConstructor) { for (Edge edge : edg.incomingEdgesOf(dataConstructor)) if (edge.getType() == Edge.Type.Value) edg.removeEdge(edge); } private void modifyDataConstructorArcs(Node dataConstructor, Node result) { final List dataConstructorChildren = edg.getChildrenNonResult(dataConstructor); final int dataConstructorChildrenCount = dataConstructorChildren.size(); for (int childIndex = 0; childIndex < dataConstructorChildrenCount; childIndex++) { final Node dataConstructorChild = edg.getResFromNode(dataConstructorChildren.get(childIndex)); final DataConstructorConstraint constraint = new DataConstructorConstraint( AccessConstraint.Operation.Remove, childIndex + "/" + (dataConstructorChildrenCount-1)); edg.addEdge(dataConstructorChild, result, new Edge(Edge.Type.Value, constraint)); } final Set outgoingEdges = edg.outgoingEdgesOf(dataConstructor); outgoingEdges.removeIf(edge -> edge.getType() != Edge.Type.Value); for (Edge valueEdge : outgoingEdges) { final Node from = edg.getEdgeSource(valueEdge); final Node to = edg.getEdgeTarget(valueEdge); final EdgeConstraint edgeConstraint = valueEdge.getConstraint(); edg.removeEdge(valueEdge); final Edge e = new Edge(Edge.Type.Value, edgeConstraint); edg.addEdge(result, to, e); } } }