Skip to content
PDGVisitor.java 10.7 KiB
Newer Older
Javier Costa's avatar
Javier Costa committed
package tfm.visitors;
Javier Costa's avatar
Javier Costa committed

import com.github.javaparser.ast.expr.Expression;
Javier Costa's avatar
Javier Costa committed
import com.github.javaparser.ast.stmt.ExpressionStmt;
import com.github.javaparser.ast.stmt.ForEachStmt;
import com.github.javaparser.ast.stmt.IfStmt;
import com.github.javaparser.ast.stmt.WhileStmt;
Javier Costa's avatar
Javier Costa committed
import com.github.javaparser.ast.visitor.VoidVisitorAdapter;
Javier Costa's avatar
Javier Costa committed
import tfm.graphs.PDGGraph;
Javier Costa's avatar
Javier Costa committed
import tfm.nodes.PDGNode;
Javier Costa's avatar
Javier Costa committed
import tfm.scopes.IfElseScope;
import tfm.scopes.Scope;
Javier Costa's avatar
Javier Costa committed
import tfm.scopes.ScopeHolder;
import tfm.scopes.VariableScope;
import tfm.utils.Logger;
Javier Costa's avatar
Javier Costa committed
import tfm.variables.VariableExtractor;
Javier Costa's avatar
Javier Costa committed
import tfm.variables.actions.VariableDefinition;
import tfm.variables.actions.VariableUse;
Javier Costa's avatar
Javier Costa committed

Javier Costa's avatar
Javier Costa committed
import java.util.HashSet;
Javier Costa's avatar
Javier Costa committed
import java.util.List;
import java.util.Set;

public class PDGVisitor extends VoidVisitorAdapter<ScopeHolder<PDGNode>> {

//    private VariableSet variableSet;
Javier Costa's avatar
Javier Costa committed

Javier Costa's avatar
Javier Costa committed
    protected PDGGraph graph;
    protected ScopeHolder<PDGNode> globalScope;
Javier Costa's avatar
Javier Costa committed

Javier Costa's avatar
Javier Costa committed
    public PDGVisitor(PDGGraph graph, ScopeHolder<PDGNode> scopeHolder) {
Javier Costa's avatar
Javier Costa committed
        this.graph = graph;
Javier Costa's avatar
Javier Costa committed
        this.globalScope = scopeHolder;
Javier Costa's avatar
Javier Costa committed
    }

    @Override
Javier Costa's avatar
Javier Costa committed
    public void visit(ExpressionStmt n, ScopeHolder<PDGNode> scope) {
Javier Costa's avatar
Javier Costa committed
        Expression expression = n.getExpression();
Javier Costa's avatar
Javier Costa committed

Javier Costa's avatar
Javier Costa committed
        PDGNode expressionNode = graph.addNode(expression.toString(), n);
Javier Costa's avatar
Javier Costa committed

Javier Costa's avatar
Javier Costa committed
        graph.addControlDependencyArc(scope.getRoot(), expressionNode);

        VariableScope<PDGNode> expressionScope = new VariableScope<>(expressionNode);
Javier Costa's avatar
Javier Costa committed
        new VariableExtractor()
                .setOnVariableDeclarationListener(variable ->
Javier Costa's avatar
Javier Costa committed
                        expressionScope.addVariableDeclaration(variable, expressionNode)
Javier Costa's avatar
Javier Costa committed
                ).setOnVariableDefinitionListener(variable ->
Javier Costa's avatar
Javier Costa committed
                        expressionScope.addVariableDefinition(variable, expressionNode)
Javier Costa's avatar
Javier Costa committed
                ).setOnVariableUseListener(variable -> {
Javier Costa's avatar
Javier Costa committed
                        expressionScope.addVariableUse(variable, expressionNode);
Javier Costa's avatar
Javier Costa committed

                        Scope<PDGNode> searchScope = scope.isVariableDefined(variable) ? scope : globalScope;

                        searchScope.getLastDefinitions(variable)
Javier Costa's avatar
Javier Costa committed
                            .forEach(variableDefinition -> graph.addDataDependencyArc(
                                    variableDefinition.getNode(),
                                    expressionNode,
                                    variable
                            ));
Javier Costa's avatar
Javier Costa committed
                })
                .visit(expression);
Javier Costa's avatar
Javier Costa committed

        scope.addSubscope(expressionScope);
Javier Costa's avatar
Javier Costa committed
    public void visit(IfStmt ifStmt, ScopeHolder<PDGNode> scope) {
Javier Costa's avatar
Javier Costa committed
        PDGNode ifNode = graph.addNode(
                String.format("if (%s)", ifStmt.getCondition().toString()),
Javier Costa's avatar
Javier Costa committed
                ifStmt
Javier Costa's avatar
Javier Costa committed
        );
Javier Costa's avatar
Javier Costa committed
        graph.addControlDependencyArc(scope.getRoot(), ifNode);

Javier Costa's avatar
Javier Costa committed
        ScopeHolder<PDGNode> ifScope = ifStmt.hasElseBranch() ? new IfElseScope<>(ifNode) : new ScopeHolder<>(ifNode);
Javier Costa's avatar
Javier Costa committed
        new VariableExtractor()
                .setOnVariableUseListener(variable -> {
Javier Costa's avatar
Javier Costa committed
                    ifScope.addVariableUse(variable, ifNode);
Javier Costa's avatar
Javier Costa committed

                    Scope<PDGNode> searchScope = scope.isVariableDefined(variable) ? scope : globalScope;

                    searchScope.getLastDefinitions(variable)
Javier Costa's avatar
Javier Costa committed
                            .forEach(variableDefinition ->
                                    graph.addDataDependencyArc(
                                        variableDefinition.getNode(),
                                        ifNode,
                                        variable
                                    )
                            );
Javier Costa's avatar
Javier Costa committed
                })
                .visit(ifStmt.getCondition());
Javier Costa's avatar
Javier Costa committed

Javier Costa's avatar
Javier Costa committed
        if (!ifStmt.hasElseBranch()) {
            ifStmt.getThenStmt().accept(this, ifScope);
        } else {
            @SuppressWarnings("unchecked")
            IfElseScope<PDGNode> ifElseScope = (IfElseScope<PDGNode>) ifScope;
Javier Costa's avatar
Javier Costa committed

Javier Costa's avatar
Javier Costa committed
            ifStmt.getThenStmt().accept(this, ifElseScope.getThenScope());
            ifStmt.getElseStmt().get().accept(this, ifElseScope.getElseScope());
        }
Javier Costa's avatar
Javier Costa committed

        scope.addSubscope(ifScope);
Javier Costa's avatar
Javier Costa committed
    public void visit(WhileStmt whileStmt, ScopeHolder<PDGNode> scope) {
Javier Costa's avatar
Javier Costa committed
        // assert whileStmt.getBegin().isPresent();

        PDGNode whileNode = graph.addNode(
                String.format("while (%s)", whileStmt.getCondition().toString()),
Javier Costa's avatar
Javier Costa committed
                whileStmt
Javier Costa's avatar
Javier Costa committed
        );
Javier Costa's avatar
Javier Costa committed
        graph.addControlDependencyArc(scope.getRoot(), whileNode);

        ScopeHolder<PDGNode> whileScope = new ScopeHolder<>(whileNode);
Javier Costa's avatar
Javier Costa committed
        new VariableExtractor()
                .setOnVariableUseListener(variable -> {
Javier Costa's avatar
Javier Costa committed
                    whileScope.addVariableUse(variable, whileNode);
Javier Costa's avatar
Javier Costa committed

                    Scope<PDGNode> searchScope = scope.isVariableDefined(variable) ? scope : globalScope;

                    searchScope.getLastDefinitions(variable)
Javier Costa's avatar
Javier Costa committed
                            .forEach(variableDefinition -> graph.addDataDependencyArc(
                                    variableDefinition.getNode(),
Javier Costa's avatar
Javier Costa committed
                                    whileNode,
                                    variable
                            ));
                })
                .visit(whileStmt.getCondition());
Javier Costa's avatar
Javier Costa committed
        whileStmt.getBody().accept(this, whileScope);

        buildLoopDataDependencies(whileScope);

        scope.addSubscope(whileScope);
    }

    private void buildLoopDataDependencies(ScopeHolder<PDGNode> scope) {
        scope.getDefinedVariables()
Javier Costa's avatar
Javier Costa committed
                .forEach(variable -> {
                    List<VariableDefinition<PDGNode>> firstDef = scope.getFirstDefinitions(variable);
                    List<VariableDefinition<PDGNode>> lastDef = scope.getLastDefinitions(variable);
Javier Costa's avatar
Javier Costa committed

                    Set<Integer> usesFromLastDef = new HashSet<>();
Javier Costa's avatar
Javier Costa committed

                    firstDef.forEach(variableDefinition -> {
                        scope.getVariableUsesBeforeNode(variable, variableDefinition.getNode())
                                .forEach(use -> {
                                    if (!usesFromLastDef.contains(use.getNode().getId())) {
                                        lastDef.forEach(def -> graph.addDataDependencyArc(
                                                def.getNode(),
                                                use.getNode(),
                                                variable)
                                        );

                                        usesFromLastDef.add(use.getNode().getId());
                                    }
                                });
Javier Costa's avatar
Javier Costa committed
                    });
        });
Javier Costa's avatar
Javier Costa committed

Javier Costa's avatar
Javier Costa committed
//    @Override
Javier Costa's avatar
Javier Costa committed
//    public void visit(ForStmt forStmt, PDGNode node) {
Javier Costa's avatar
Javier Costa committed
//        // Add initialization nodes
//        forStmt.getInitialization().stream()
//                .map(expression -> graph.addNode(expression.toString()))
//                .forEach(pdgVertex -> graph.addControlDependencyArc(parent, pdgVertex));
//
//        // Add condition node
//        Expression condition = forStmt.getCompare().orElse(new BooleanLiteralExpr(true));
//        PDGNode conditionNode = graph.addNode(condition.toString());
//
//        graph.addControlDependencyArc(parent, conditionNode);
//
//        // Visit for
//        super.visit(forStmt, conditionNode);
//
//        // Add update vertex
//        forStmt.getUpdate().stream()
//                .map(expression -> graph.addNode(expression.toString()))
//                .forEach(pdgVertex -> graph.addControlDependencyArc(conditionNode, pdgVertex));
//    }

Javier Costa's avatar
Javier Costa committed
    @Override
Javier Costa's avatar
Javier Costa committed
    public void visit(ForEachStmt forEachStmt, ScopeHolder<PDGNode> scope) {
Javier Costa's avatar
Javier Costa committed
//        // Initializer
//        VariableDeclarationExpr iterator = new VariableDeclarationExpr(
//                new VariableDeclarator(
//                        JavaParser.parseClassOrInterfaceType("Iterator"),
//                        "iterator",
//                        new ConditionalExpr(
//                                new MethodCallExpr(
//                                        new MethodCallExpr(
//                                            forEachStmt.getIterable(),
//                                            "getClass"
//                                        ),
//                                        "isArray"
//                                ),
//                                new MethodCallExpr(
//                                        new NameExpr("Arrays"),
//                                        "asList",
//                                        new NodeList<>(
//                                                forEachStmt.getIterable()
//                                        )
//                                ),
//                                new CastExpr(
//                                        JavaParser.parseClassOrInterfaceType("Iterable"),
//                                        new CastExpr(
//                                                JavaParser.parseClassOrInterfaceType("Object"),
//                                                forEachStmt.getIterable()
//                                        )
//                                )
//                        )
//                )
//        );
//
//        // Compare
//        MethodCallExpr iteratorHasNext = new MethodCallExpr(
//                new NameExpr("iterator"),
//                "hasNext"
//        );
//
//        // Body
//        Type variableType = forEachStmt.getVariable().getCommonType();
//        String variableName = forEachStmt.getVariable().getVariables().get(0).getNameAsString();
//
//        BlockStmt foreachBody = Utils.blockWrapper(forEachStmt.getBody());
//        foreachBody.getStatements().addFirst(
//                new ExpressionStmt(
//                    new VariableDeclarationExpr(
//                            new VariableDeclarator(
//                                    variableType,
//                                    variableName,
//                                    new CastExpr(
//                                            variableType,
//                                            new MethodCallExpr(
//                                                    new NameExpr("iterator"),
//                                                    "next"
//                                            )
//                                    )
//                            )
//                    )
//                )
//        );
//
//        new ForStmt(new NodeList<>(iterator), iteratorHasNext, new NodeList<>(), foreachBody)
//            .accept(this, parent);
Javier Costa's avatar
Javier Costa committed

//    @Override
Javier Costa's avatar
Javier Costa committed
//    public void visit(SwitchStmt switchStmt, PDGNode node) {
Javier Costa's avatar
Javier Costa committed
//        PDGNode switchNode = graph.addNode(switchStmt.toString());
//
//        graph.addControlDependencyArc(parent, switchNode);
//
//        switchStmt.getSelector().accept(this, parent);
//        switchStmt.getEntries()
//                .forEach(switchEntryStmt -> switchEntryStmt.accept(this, switchNode));
//    }
Javier Costa's avatar
Javier Costa committed
}