Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/variable renaming #38

Open
wants to merge 81 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
81 commits
Select commit Hold shift + click to select a range
b3973dc
Implement dominance tree
mateusluizfb Oct 31, 2020
5811942
Implement dominance frontier
mateusluizfb Oct 31, 2020
4a01850
Fix some paths
mateusluizfb Oct 31, 2020
f163807
Implement a first version of the phi-function insertion
mateusluizfb Nov 9, 2020
6d0da73
Some fixes in the phi insertion
mateusluizfb Nov 12, 2020
17b8862
Refactor phi function insertion
mateusluizfb Nov 12, 2020
0cfca0e
Create variable renaming module
mateusluizfb Nov 20, 2020
2006b29
Remove phi function extracted code
mateusluizfb Nov 24, 2020
d51d120
Add Stack implementation code
mateusluizfb Nov 24, 2020
56e18d5
Import stack in the variable renaming code
mateusluizfb Nov 24, 2020
ad0e7fa
Remove Util code and leave in the modules
mateusluizfb Nov 30, 2020
5939bfb
Rename stack's empty() to emptyStack()
mateusluizfb Dec 2, 2020
5a17d79
Implement first part of the variable renaming
mateusluizfb Dec 2, 2020
74f80c0
Fix some mehods arguments
mateusluizfb Jan 5, 2021
22245ce
Creating a new variable version
mateusluizfb Jan 7, 2021
6f5480b
Fix stack peeek for int value
mateusluizfb Jan 7, 2021
b4ff2af
Correctly verify right hand side variables
mateusluizfb Jan 11, 2021
1848186
Change right hand side list iteration
mateusluizfb Jan 12, 2021
37f4e88
Fix right hand side iteration
mateusluizfb Jan 17, 2021
0bcad7c
Only insert phi functions in join nodes
mateusluizfb Jan 17, 2021
f48f3d2
Replace a simple right hand side variable
mateusluizfb Jan 17, 2021
767f49b
Fix left variable replacement
mateusluizfb Jan 21, 2021
6733177
Usign block by block DFS instead the common variable iteration
mateusluizfb Jan 21, 2021
9e9753a
Beginning to phi function renaming
mateusluizfb Jan 21, 2021
fee15d2
Change the block iteration strategy
mateusluizfb Jan 28, 2021
0c7ee20
Adjust left and right hand side renaming
mateusluizfb Jan 28, 2021
2bd3ae2
Adjust tests setup
mateusluizfb Jan 28, 2021
25dc1f1
Pop queue in the end of each execution
mateusluizfb Feb 1, 2021
684f585
Starting to rename another variable in deeper immediates
mateusluizfb Feb 2, 2021
6135298
Refact Variable Renaming
mateusluizfb Feb 2, 2021
2ea8a77
Refactor variable renaming
mateusluizfb Feb 3, 2021
fb3ff82
Adding and moving ssa tests
mateusluizfb Feb 6, 2021
f90cb73
Remove unused test from VariableRenaming
mateusluizfb Feb 6, 2021
ff486fd
Merge branch 'master' into feature/variable-renaming
mateusluizfb Feb 8, 2021
1fc6056
Fix ssa tests namespace
mateusluizfb Feb 8, 2021
488fa1e
Update phi function insertion
mateusluizfb Feb 8, 2021
5063f8e
Chante test classfile
mateusluizfb Feb 10, 2021
394a082
Update java 8 test file
mateusluizfb Feb 10, 2021
55863c2
Rename left hand side of a phiFunction
mateusluizfb Feb 15, 2021
6e3c843
Test a simple exception case
mateusluizfb Feb 15, 2021
2b9645c
Refactor stack of variable version access
mateusluizfb Feb 19, 2021
03d6a00
Refactor variable version stacks access
mateusluizfb Feb 19, 2021
3f069ce
Use string as key in the variable version stack
mateusluizfb Feb 19, 2021
f523e55
Match only local immediates with name
mateusluizfb Feb 19, 2021
43737be
Fix assignment check without args case
mateusluizfb Feb 19, 2021
7561cd0
DFS through an idom tree instead the CFG
mateusluizfb Feb 20, 2021
98c04df
Create a module to run the SSA transformation
mateusluizfb Feb 22, 2021
f79e8db
Add some tests to the SSA generator
mateusluizfb Feb 22, 2021
62df263
Rename invoke args
mateusluizfb Feb 23, 2021
6020750
Match method invoke with the right matchs
mateusluizfb Feb 25, 2021
b05df0f
Unsupport invokeStmt operators when applying SSA transformation
mateusluizfb Feb 25, 2021
40c72e5
Adding some comments
mateusluizfb Feb 25, 2021
a366970
Rename rhs expressions
mateusluizfb Feb 26, 2021
f5fee38
Fix phiFunction renaming by looking up via DFS
mateusluizfb Feb 26, 2021
ccc7921
Adding support for left hand side array
mateusluizfb Feb 27, 2021
453ddf2
Support right hand side array
mateusluizfb Feb 27, 2021
140555e
Test soot example code
mateusluizfb Feb 27, 2021
de2ad22
Organazing some tests
mateusluizfb Mar 8, 2021
0c08d53
Refacto SSA integration tests
mateusluizfb Mar 10, 2021
e34d1af
Add new test samples
mateusluizfb Mar 10, 2021
a08c8ef
Add test for all math problems
mateusluizfb Mar 11, 2021
1628f80
Add comment to test
mateusluizfb Mar 23, 2021
5cf7d66
Rename variable renaming stacks
mateusluizfb Mar 23, 2021
8330998
Refactor phi-function insertion module
mateusluizfb Mar 24, 2021
5da3143
Revert pom.xml
mateusluizfb Jun 8, 2021
35477ef
Merge branch 'master' into feature/variable-renaming
mateusluizfb Jun 8, 2021
960c69a
Extracting helper methods to another file
mateusluizfb Jun 13, 2021
e8a8731
Fix CI build issues
mateusluizfb Jun 13, 2021
1b6f132
Fix tests
mateusluizfb Jun 14, 2021
02452bf
Rewrite phi-function insertion algorithm
mateusluizfb Jun 16, 2021
9d0c4e1
Rewrite dominance-frontier creation algorithm
mateusluizfb Jun 16, 2021
66f2e5d
Minor fixes in the phi-function insertion
mateusluizfb Jun 16, 2021
d8a7384
Refactor dominance tree creation
mateusluizfb Jun 17, 2021
6267bbc
Simpler dom frontier implementation
mateusluizfb Jun 17, 2021
44b6cf2
Revert "Simpler dom frontier implementation"
mateusluizfb Jun 17, 2021
d457b36
Implement the more efficient way compute dom frontier
mateusluizfb Jun 17, 2021
2fdcf78
Fix dominance frontier test
mateusluizfb Jun 18, 2021
f230dc5
Fix tests and run phi insertion for join nodes only
mateusluizfb Jun 20, 2021
8fc6e15
Fixing some tests
mateusluizfb Jun 20, 2021
ad31c15
Simplify again the dominance frontier algorithm
mateusluizfb Jun 20, 2021
493ce83
Fix some tests
mateusluizfb Jun 21, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion src/main/java/lang/jimple/util/Pair.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package lang.jimple.util;

import lang.jimple.internal.generated.Type;
import lang.jimple.internal.generated.Value;

import lombok.AllArgsConstructor;
import lombok.Data;

Expand All @@ -9,5 +12,4 @@ public class Pair<First, Second> {

First first;
Second second;

}
1 change: 1 addition & 0 deletions src/main/rascal/lang/jimple/core/Syntax.rsc
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ data Expression
| lengthOf(Immediate immediate)
| neg(Immediate immediate)
| immediate(Immediate immediate)
| phiFunction(Variable variable, list[Variable] definitions)
;

data ArrayDescriptor
Expand Down
2 changes: 1 addition & 1 deletion src/main/rascal/lang/jimple/decompiler/Decompiler.rsc
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import Exception;

@javaClass{lang.jimple.internal.Decompiler}
@reflect{for stdout}
java ClassOrInterfaceDeclaration decompile(loc classFile) throws IO;
java ClassOrInterfaceDeclaration decompile(loc classFile) throws IO;



24 changes: 24 additions & 0 deletions src/main/rascal/lang/jimple/toolkit/ssa/DominanceFrontier.rsc
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
module lang::jimple::toolkit::ssa::DominanceFrontier

import analysis::graphs::Graph;
import lang::jimple::toolkit::FlowGraph;
import lang::jimple::toolkit::ssa::DominanceTree;

public map[Node, set[Node]] createDominanceFrontier(FlowGraph flowGraph, map[&T, set[&T]] dominanceTree) {
allNodes = { origin | <origin, _> <- flowGraph } + { destination | <_, destination> <- flowGraph };

dominanceFrontiers = ();

for(graphNode <- allNodes) {
for(predecessor <- predecessors(flowGraph, graphNode)) {
tempPredecessor = predecessor;
while(tempPredecessor != findIdom(dominanceTree, graphNode)) {
dominanceFrontiers[tempPredecessor] = tempPredecessor in dominanceFrontiers ? dominanceFrontiers[tempPredecessor] : {};
dominanceFrontiers[tempPredecessor] = dominanceFrontiers[tempPredecessor] + {graphNode};
tempPredecessor = findIdom(dominanceTree, tempPredecessor);
};
};
};

return dominanceFrontiers;
}
56 changes: 47 additions & 9 deletions src/main/rascal/lang/jimple/toolkit/ssa/DominanceTree.rsc
Original file line number Diff line number Diff line change
@@ -1,16 +1,54 @@
module lang::jimple::toolkit::ssa::DominanceTree

import demo::Dominators;
import Set;
import lang::jimple::toolkit::FlowGraph;
import analysis::graphs::Graph;
import demo::Dominators;

import List;
public map[&T, set[&T]] createDominanceTree(Graph[&T] graph) {
rel[&T, set[&T]] dominanceTreeRelations = dominators(graph, entryNode());
return ( father: childs | <father, childs> <- dominanceTreeRelations );
}

public map[Node, list[Node]] createAdjacenciesMatrix(FlowGraph flowGraph) {
blockTree = ( origin: [] | <origin, _> <- flowGraph);

for(<origin, destination> <- flowGraph) {
blockTree[origin] = blockTree[origin] + [destination];
};

return blockTree;
}

public map[Node, list[Node]] createIdomTree(map[&T, set[&T]] dominanceTree) {
blockTree = ( treeKey: [] | treeKey <- dominanceTree);

for(treeKey <- dominanceTree) {
idom = findIdom(dominanceTree, treeKey);

if(treeKey != entryNode())
blockTree[idom] = blockTree[idom] + [treeKey];
};

public map[Node, Node] createDominanceTree(FlowGraph flowGraph) {
result = (computeDominator(flowGraph, a): a | <a, _> <- flowGraph);
return result;
return blockTree;
}

public Node computeDominator(FlowGraph flowGraph, Node currentNode) {
predecessorNodeList = [a | <a, b> <- flowGraph, b == currentNode];
result = if(isEmpty(predecessorNodeList) == true) currentNode; else head(predecessorNodeList);
return result;
}
public Graph[&T] removeNodeFromGraph(Graph[&T] graph, &T nodeToRemove) {
return { <father, graphChild> | <father, graphChild> <- graph, nodeToRemove != father || nodeToRemove == entryNode() };
}


public Node findIdom(map[&T, set[&T]] dominanceTree, Node child) {
idom = entryNode();

possibleIdoms = [ father | father <- dominanceTree, child in dominanceTree[father] ];

for(possibleIdom <- possibleIdoms) {
if(size(dominanceTree[possibleIdom]) < size(dominanceTree[idom])) {
idom = possibleIdom;
};
};

return idom;
}
39 changes: 39 additions & 0 deletions src/main/rascal/lang/jimple/toolkit/ssa/Generator.rsc
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
module lang::jimple::toolkit::ssa::Generator

import List;

import lang::jimple::toolkit::FlowGraph;
import lang::jimple::core::Syntax;

import lang::jimple::toolkit::ssa::DominanceTree;
import lang::jimple::toolkit::ssa::PhiFunctionInsertion;
import lang::jimple::toolkit::ssa::DominanceFrontier;
import lang::jimple::toolkit::ssa::VariableRenaming;

public FlowGraph applySSATransformation(MethodBody methodBody) {
FlowGraph flowGraph = forwardFlowGraph(methodBody);

if(hasUnsupportedInstruction(flowGraph)) // Doest not support invokeStmt and fieldRef rename
return {};

map[&T, set[&T]] dominanceTree = createDominanceTree(flowGraph);
map[&T, set[&T]] dominanceFrontier = createDominanceFrontier(flowGraph, dominanceTree);
FlowGraph phiFunctionFlowGraph = insertPhiFunctions(flowGraph, dominanceFrontier);
result = applyVariableRenaming(phiFunctionFlowGraph);

return result;
}

public bool hasUnsupportedInstruction(FlowGraph flowGraph) {
unsupportedList = [ <origin, destination> | <origin, destination> <- flowGraph, unspportedStatement(origin) || unspportedStatement(destination)];

return size(unsupportedList) != 0;
}

public bool unspportedStatement(Node nodeStatement) {
switch(nodeStatement) {
case stmtNode(invokeStmt(_)): return true;
case stmtNode(assign(fieldRef(_, _), _)): return true;
default: return false;
}
}
115 changes: 115 additions & 0 deletions src/main/rascal/lang/jimple/toolkit/ssa/Helpers.rsc
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
module lang::jimple::toolkit::ssa::Helpers

import Node;
import Type;
import List;

import lang::jimple::toolkit::FlowGraph;
import lang::jimple::core::Syntax;

public Variable returnStmtVariable(Node graphNode) {
assignStatement = returnStmtNodeBody(graphNode);
variableArg = assignStatement[0];

switch(variableArg) {
case Variable variable: return variable;
}
}

public Statement returnStmtNodeBody(Node stmtNode) {
switch(stmtNode) {
case stmtNode(stmtBody): return stmtBody;
}
}

public Variable returnPhiFunctionLeftHandSide(Expression phiFunctionExpr) {
switch(phiFunctionExpr) {
case phiFunction(leftHandSide, _): return leftHandSide;
}
}

public list[Variable] returnPhiFunctionRightHandSide(Expression phiFunctionExpr) {
switch(phiFunctionExpr) {
case phiFunction(_, rightHandSide): return rightHandSide;
}
}

public Variable returnLeftHandSideVariable(Node stmtNode) {
switch(stmtNode) {
case stmtNode(assign(leftHandSide, _)): return leftHandSide;
}
}

public Expression returnRightHandSideExpression(Node stmtNode) {
switch(stmtNode) {
case stmtNode(assign(_, rightHandSide)): return rightHandSide;
}
}

public String returnVariableImmediateName(Immediate immediate) {
switch(immediate) {
case local(String localName): return localName;
default: return "";
}
}

public String returnImmediateName(Immediate immediate) {
switch(immediate[0]) {
case String immediateName: return immediateName;
}
}

public list[Immediate] returnRightHandSideImmediates(Node variableNode) {
rightHandSide = returnRightHandSideExpression(variableNode);
typeOfVariableArg = typeOf(rightHandSide);

if(typeOfVariableArg.name != "Expression") return [];

list[Immediate] immediates = returnExpressionImmediates(rightHandSide);
list[Immediate] localVariableImmediates = [ immediate | immediate <- immediates, returnVariableImmediateName(immediate) != ""];
int variablesCount = size(localVariableImmediates);

if(variablesCount != 0) return localVariableImmediates;

return [];
}

public list[Immediate] returnExpressionImmediates(Expression expression) {
switch(expression) {
case newInstance(Type instanceType): return [];
case newArray(Type baseType, list[ArrayDescriptor] dims): return [];
case cast(Type toType, local(name)): return [];
case instanceOf(Type baseType, local(name)): return [local(name)];
case invokeExp(_): return [];
case arraySubscript(Name arrayName, _): return [local(arrayName)];
case stringSubscript(String stringName, local(name)): return [local(stringName)];
case localFieldRef(Name local, Name className, Type fieldType, Name fieldName): return [];
case fieldRef(Name className, Type fieldType, Name fieldName): return [];
case and(lhs, rhs): return [lhs, rhs];
case or(lhs, rhs): return [lhs, rhs];
case xor(lhs, rhs): return [lhs, rhs];
case reminder(lhs, rhs): return [lhs, rhs];
case isNull(variable): return [variable];
case isNotNull(variable): return [variable];
case cmp(lhs, rhs): return [lhs, rhs];
case cmpg(lhs, rhs): return [lhs, rhs];
case cmpl(lhs, rhs): return [lhs, rhs];
case cmpeq(lhs, rhs): return [lhs, rhs];
case cmpne(lhs, rhs): return [lhs, rhs];
case cmpgt(lhs, rhs): return [lhs, rhs];
case cmpge(lhs, rhs): return [lhs, rhs];
case cmplt(lhs, rhs): return [lhs, rhs];
case cmple(lhs, rhs): return [lhs, rhs];
case shl(lhs, rhs): return [lhs, rhs];
case shr(lhs, rhs): return [lhs, rhs];
case ushr(lhs, rhs): return [lhs, rhs];
case plus(lhs, rhs): return [lhs, rhs];
case minus(lhs, rhs): return [lhs, rhs];
case mult(lhs, rhs): return [lhs, rhs];
case div(lhs, rhs): return [lhs, rhs];
case lengthOf(local(name)): return [local(name)];
case neg(local(name)): return [local(name)];
case immediate(local(name)): return [local(name)];
default: return [];
}
}
103 changes: 103 additions & 0 deletions src/main/rascal/lang/jimple/toolkit/ssa/PhiFunctionInsertion.rsc
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
module lang::jimple::toolkit::ssa::PhiFunctionInsertion

import demo::Dominators;
import Set;
import Relation;
import Type;
import IO;
import Node;
import List;

import analysis::graphs::Graph;
import lang::jimple::toolkit::FlowGraph;
import lang::jimple::core::Syntax;
import lang::jimple::toolkit::ssa::Helpers;

public FlowGraph insertPhiFunctions(FlowGraph flowGraph, map[&T, set[&T]] dominanceFrontier) {
variableList = { getStmtVariable(graphNode) | <graphNode, _> <- flowGraph, isVariable(graphNode) };

for(V <- variableList) {
DomFromPlus = ();
Work = ();
W = {};

for(X <- blocksWithVariable(flowGraph, V)) {
Work[X] = 1;
W = W + {X};
};

while(W != {}) {
<X, newSet> = takeOneFrom(W);
W = newSet;

if(X in dominanceFrontier) {
for(Y <- dominanceFrontier[X]) {
if(!(Y in DomFromPlus)) {
flowGraph = insertPhiFunction(flowGraph, Y, V); // add v←φ(...) at entry of Y
DomFromPlus[Y] = 1;
if(!(Y in DomFromPlus)) {
Work(Y) = 1;
W = W + {Y};
};
};
};
};
};
};

return flowGraph;

}

public list[Node] blocksWithVariable(FlowGraph flowGraph, Variable variable) {
return [graphNode | <graphNode, _> <- flowGraph, isSameVariable(graphNode, variable)];;
}

public bool isVariable(Node graphNode) {
if (size(graphNode[..]) == 0) return false;

assignStatement = returnStmtNodeBody(graphNode);
if (size(assignStatement[..]) == 0) return false;

variableArg = assignStatement[0];
typeOfVariableArg = typeOf(variableArg);

if (size(typeOfVariableArg[..]) == 0) return false;

return typeOfVariableArg.name == "Variable";
}

public &T getStmtVariable(Node graphNode) {
assignStatement = returnStmtNodeBody(graphNode);
variableArg = assignStatement[0];

return variableArg;
}

public bool isSameVariable(Node graphNode, Variable variable) {
if (size(graphNode[..]) == 0) return false;

assignStatement = returnStmtNodeBody(graphNode);
if (size(assignStatement[..]) == 0) return false;

variableArg = assignStatement[0];
typeOfVariableArg = typeOf(variableArg);

if (size(typeOfVariableArg[..]) == 0) return false;

return variableArg == variable;
}

public FlowGraph insertPhiFunction(FlowGraph flowGraph, Node childNode, Variable variable) {
if (childNode == exitNode()) return flowGraph;

fatherNodes = predecessors(flowGraph, childNode);
phiFunctionStmt = stmtNode(assign(variable, phiFunction(variable, [])));

phiFunctionRelations = { <fatherNode, phiFunctionStmt> | fatherNode <- fatherNodes };
filteredFlowGraph = { <origin, destination> | <origin, destination> <- flowGraph, !(origin in fatherNodes) || !(childNode == destination) };

flowGraphWithPhiFunction = phiFunctionRelations + filteredFlowGraph + {<phiFunctionStmt, childNode>};

return flowGraphWithPhiFunction;
}
Loading