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

Conversation

mateusluizfb
Copy link
Contributor

This is a direct implementation of Cytron's Single Static Assignment Form. The code also uses some ideas and algorithms presented by the SSA book.

The implementation ignores two types of instructions:

  • invokeStmt
  • assign(fieldRef(_, _), _)

The code is composed into five main modules:

  • lang::jimple::toolkit::ssa::Generator is responsible to call all the other modules to perform a complete SSA transformation, also validates if the ignored instructions are present;
  • lang::jimple::toolkit::ssa::DominanceFrontier is responsible to create the graph's dominance frontier;
  • lang::jimple::toolkit::ssa::DominanceTree is responsible to create the graph's dominance tree;
  • lang::jimple::toolkit::ssa::PhiFunctionInsertion it inserts the phi functions in the graph;
  • lang::jimple::toolkit::ssa::VariableRenaming it renames all the variables for different versions;

Comment on lines 19 to 22
map[&T, set[&T]] dominanceTree = createDominanceTree(flowGraph);
map[&T, set[&T]] dominanceFrontier = createDominanceFrontier(flowGraph, dominanceTree);
FlowGraph phiFunctionFlowGraph = insertPhiFunctions(flowGraph, dominanceFrontier);
result = applyVariableRenaming(phiFunctionFlowGraph);
Copy link
Contributor Author

@mateusluizfb mateusluizfb Mar 23, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Applies each SSA's stages

Comment on lines 14 to 49
public FlowGraph insertPhiFunctions(FlowGraph flowGraph, map[&T, set[&T]] dominanceFrontier) {
newFlowGraph = { <origin, destination> | <origin, destination> <- flowGraph };
variableList = { getStmtVariable(graphNode) | <graphNode, _> <- flowGraph, isVariable(graphNode) };

for(Variable variable <- variableList) {
F = {}; // set of basic blocks where φ is added
W = {}; // set of basic blocks that contain definitions of v

for(variableNode <- blocksWithVariable(flowGraph, variable)) { // d ∈ Defs(v)
B = variableNode;
W = W + {B};
};

while(size(W) != 0) {
// remove a basic block X from W
tuple[Node, set[Node]] elements = takeOneFrom(W);
X = elements[0];
W = elements[1];

if(X in dominanceFrontier) { // Avoids NoSuchKey error
frontierNodes = dominanceFrontier[X];
for(Y <- frontierNodes) { // Y : basic block ∈ DF(X )
if(size({Y} & F) == 0 && isJoinNode(flowGraph, Y)) { // Y \notin F && Y is a join node
newFlowGraph = insertPhiFunction(newFlowGraph, Y, variable); // add v←φ(...) at entry of Y
F = F + {Y}; // F ← F ∪ {Y}
if(size([Y] & blocksWithVariable(flowGraph, variable)) == 0) { // Y \notin Defs(v)
W = W + {Y}; // W ←W ∪{Y}
};
};
};
};
};
};

return newFlowGraph;
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Screen Shot 2021-03-23 at 20 08 47

Comment on lines 26 to 101
public FlowGraph applyVariableRenaming(FlowGraph flowGraph) {
VARIABLE_VERSION_STACK = (); // Stack for each variable that holds the next variable to ve replaced
VARIABLE_ASSIGNMENT_COUNT = (); // Counts how many assingments have been processed for a given variable
REPLACED_NODES = {}; // Keep tracking of all nodes replaced in one execution
LAST_VERSION_REPLACED = (); // Keep tracking of the new version of a given node

ADJACENCIES_MATRIX = createAdjacenciesMatrix(flowGraph); // Mainly used to rebuild the renamed flow graph
IDOM_TREE = createIdomTree(createDominanceTree(flowGraph)); // Used to traverse the flow graph

map[Node, list[Node]] newBlockTree = replace(entryNode()); // Start algorithm

// Rebuild renamed flowGraph
FlowGraph newFlowGraph = {};
for(fatherNode <- newBlockTree) {
newFlowGraph = newFlowGraph + { <fatherNode, nodeChild> | nodeChild <- ADJACENCIES_MATRIX[fatherNode]};
};

return newFlowGraph;
}

public map[Node, list[Node]] replace(Node X) {
if((X == exitNode())) return ADJACENCIES_MATRIX;

Node oldNode = X;

// Deal with all nodes that aren't assigments bug uses a variable in some way
if(isNonAssignmentStatementToRename(X)) {
stmtNode(statement) = X;
Node renamedStatement = stmtNode(replaceImmediateUse(statement));
renameNodeOcurrecies(X, renamedStatement);
X = renamedStatement;
};

// Deal will all nodes that are an assigment and are not renamed
if(isOrdinaryAssignment(X) && !isRenamed(X)) {

// Replace right hand side variables
list[Immediate] rightHandNodeImmediates = getRightHandSideImmediates(X);
for(rightHandSideImmediate <- rightHandNodeImmediates) {
newAssignStmt = replaceRightVariableVersion(ADJACENCIES_MATRIX, rightHandSideImmediate, X);

renameNodeOcurrecies(X, newAssignStmt);

X = newAssignStmt;
};

// Replace left hand side variables
if(isLeftHandSideVariable(X)) {
Variable V = getStmtVariable(X);
Immediate localVariableImmediate = local(V[0]);

int assingmentQuantity = returnAssignmentQuantity(localVariableImmediate);
newAssignStmt = replaceLeftVariableVersion(ADJACENCIES_MATRIX, X, assingmentQuantity);

renameNodeOcurrecies(X, newAssignStmt);

stackVariableVersion(localVariableImmediate, assingmentQuantity);
iterateAssignmentQuantity(localVariableImmediate);
findAndAddPhiFunctionArgs(oldNode, newAssignStmt); // Search variable uses of replaced variable in phi-function and rename it

X = newAssignStmt;
};
}

for(child <- IDOM_TREE[X]) {
// We need to check the last version replaced because the renamed version was not beign reflected in the current `for` statement iteration,
// so we need to check the last version replaced
nodeToRename = LAST_VERSION_REPLACED[child]? ? LAST_VERSION_REPLACED[child] : child;
replace(nodeToRename);
};

if(!ignoreNode(oldNode) && isVariable(oldNode) && !isRenamed(X))
popOldNode(oldNode);

return ADJACENCIES_MATRIX;
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the largest module and the most messy one, but try to mimic the Cytron's algorithm:

Screen Shot 2021-03-23 at 20 08 26

@mateusluizfb mateusluizfb force-pushed the feature/variable-renaming branch 2 times, most recently from 3329eef to 0d3eebb Compare June 13, 2021 14:03
@mateusluizfb mateusluizfb force-pushed the feature/variable-renaming branch 6 times, most recently from b7d7a04 to 45f0cf6 Compare June 13, 2021 19:43
@mateusluizfb mateusluizfb force-pushed the feature/variable-renaming branch from 45f0cf6 to e8a8731 Compare June 13, 2021 20:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant