changes to PDG seems to be working for if, while and for added some stuff for arrays but havent tested yet
This commit is contained in:
202
src/pdg/PDG.java
202
src/pdg/PDG.java
@@ -32,22 +32,35 @@ public class PDG {
|
|||||||
private void computeControlDependencies() {
|
private void computeControlDependencies() {
|
||||||
System.out.println("\tComputing control dependencies...");
|
System.out.println("\tComputing control dependencies...");
|
||||||
|
|
||||||
for (Node node : cfg.nodes()) {
|
boolean changed = true;
|
||||||
Set<String> deps = new HashSet<>();
|
|
||||||
|
|
||||||
for (Edge inEdge : node.inEdges()) {
|
while (changed) {
|
||||||
Node pred = inEdge.source();
|
changed = false;
|
||||||
|
|
||||||
if (pred.outEdges().size() > 1) {
|
for (Node node : cfg.nodes()) {
|
||||||
deps.add(pred.label());
|
Set<String> deps = new HashSet<>();
|
||||||
|
|
||||||
|
for (Edge inEdge : node.inEdges()) {
|
||||||
|
Node pred = inEdge.source();
|
||||||
|
|
||||||
|
// get all deps from
|
||||||
if (controlDeps.containsKey(pred.label())) {
|
if (controlDeps.containsKey(pred.label())) {
|
||||||
deps.addAll(controlDeps.get(pred.label()));
|
deps.addAll(controlDeps.get(pred.label()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// update deps if pred is a branching node liek if and while
|
||||||
|
if (pred.outEdges().size() > 1) {
|
||||||
|
deps.add(pred.label());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// compare prev iteration to current if we found changes in depns update control
|
||||||
|
// deps. else exit loop
|
||||||
|
Set<String> oldDeps = controlDeps.get(node.label());
|
||||||
|
if (oldDeps == null || !oldDeps.equals(deps)) {
|
||||||
|
controlDeps.put(node.label(), deps);
|
||||||
|
changed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
controlDeps.put(node.label(), deps);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
System.out.println("\t\tFound " + countDependencies(controlDeps) + " control dependencies");
|
System.out.println("\t\tFound " + countDependencies(controlDeps) + " control dependencies");
|
||||||
@@ -97,51 +110,68 @@ public class PDG {
|
|||||||
*/
|
*/
|
||||||
private Set<String> extractDefs(String statement) {
|
private Set<String> extractDefs(String statement) {
|
||||||
Set<String> vars = new HashSet<>();
|
Set<String> vars = new HashSet<>();
|
||||||
// Skip special nodes
|
// exclude comments
|
||||||
if (statement.startsWith("*"))
|
if (statement.startsWith("*") || statement.startsWith("/"))
|
||||||
return vars;
|
return vars;
|
||||||
|
|
||||||
if (statement.contains("=") && !statement.contains("==")) {
|
// used for normal assignments exclude anything else
|
||||||
String[] parts = statement.split("=");
|
boolean isDef = statement.contains("=") &&
|
||||||
// Debug proper variabel naem selection:
|
!statement.contains("==") &&
|
||||||
// System.out.printf("Statement: %s", statement);
|
!statement.contains("<=") &&
|
||||||
// print anything before "="
|
!statement.contains(">=") &&
|
||||||
// System.out.println(parts[0]);
|
!statement.contains("!=");
|
||||||
|
|
||||||
// retrieve teh first "word" before equals
|
if (isDef) {
|
||||||
Pattern p = Pattern.compile("(\\w+)\\s*$");
|
String lhs = statement.substring(0, statement.indexOf('=')).trim();
|
||||||
Matcher m = p.matcher(parts[0]);
|
|
||||||
String varLabel = "-1";
|
|
||||||
|
|
||||||
if (m.find()) {
|
// remove left over operators after getting teh substring
|
||||||
varLabel = m.group(1);
|
if (lhs.endsWith("+") || lhs.endsWith("-") || lhs.endsWith("*") || lhs.endsWith("/") || lhs.endsWith("%")
|
||||||
}
|
|| lhs.endsWith("&") || lhs.endsWith("|") || lhs.endsWith("^")) {
|
||||||
if ((!varLabel.isEmpty() || varLabel == "-1") && Character.isJavaIdentifierStart(varLabel.charAt(0))) {
|
lhs = lhs.substring(0, lhs.length() - 1).trim();
|
||||||
// print variable to be assigned
|
|
||||||
// System.out.println(varLabel);
|
|
||||||
vars.add(varLabel);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// for possible arrays
|
||||||
|
if (lhs.contains("[")) {
|
||||||
|
lhs = lhs.substring(0, lhs.indexOf('[')).trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
// get last "word" splits by whitespace
|
||||||
|
String[] tokens = lhs.split("\\s+");
|
||||||
|
if (tokens.length > 0) {
|
||||||
|
String var = tokens[tokens.length - 1];
|
||||||
|
if (!var.isEmpty() && Character.isJavaIdentifierStart(var.charAt(0))) {
|
||||||
|
vars.add(var);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Handle For Loops
|
||||||
if (statement.contains("for") && statement.contains("(")) {
|
if (statement.contains("for") && statement.contains("(")) {
|
||||||
String forPart = statement.substring(statement.indexOf("("));
|
String inside = statement.substring(statement.indexOf("(") + 1);
|
||||||
String[] forParts = forPart.split(";");
|
if (inside.contains(";")) {
|
||||||
if (forParts.length >= 3) {
|
String[] parts = inside.split(";");
|
||||||
if (forParts[0].contains("=")) {
|
|
||||||
String[] initParts = forParts[0].split("=");
|
// Init def: "int i = 0"
|
||||||
if (initParts.length > 0) {
|
if (parts.length > 0 && parts[0].contains("=")) {
|
||||||
String var = initParts[0].trim().replaceAll("[^a-zA-Z0-9_]", "");
|
String part = parts[0].substring(0, parts[0].indexOf('=')).trim();
|
||||||
|
String[] tokens = part.split("\\s+");
|
||||||
|
if (tokens.length > 0) {
|
||||||
|
// retrieve last element
|
||||||
|
String var = tokens[tokens.length - 1];
|
||||||
|
vars.add(var);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update def for: "i++", "i--", "++i"
|
||||||
|
if (parts.length >= 3) {
|
||||||
|
String update = parts[parts.length - 1];
|
||||||
|
update = update.replaceAll("\\)", ""); // remove closing paren if present
|
||||||
|
if (update.contains("++") || update.contains("--")) {
|
||||||
|
String var = update;
|
||||||
if (!var.isEmpty())
|
if (!var.isEmpty())
|
||||||
vars.add(var);
|
vars.add(var);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
String update = forParts[forParts.length - 1];
|
|
||||||
if (update.contains("++") || update.contains("--")) {
|
|
||||||
String var = update.replaceAll("[^a-zA-Z0-9_]", "");
|
|
||||||
if (!var.isEmpty())
|
|
||||||
vars.add(var);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -153,26 +183,53 @@ public class PDG {
|
|||||||
*/
|
*/
|
||||||
private Set<String> extractUses(String statement) {
|
private Set<String> extractUses(String statement) {
|
||||||
Set<String> vars = new HashSet<>();
|
Set<String> vars = new HashSet<>();
|
||||||
System.out.printf("Uses Statement: %s \n", statement);
|
|
||||||
// make sure we only work on the rhs
|
|
||||||
int eq = statement.indexOf('=');
|
|
||||||
if (eq != -1) {
|
|
||||||
statement = statement.substring(eq + 1);
|
|
||||||
}
|
|
||||||
// Split on any non-identifier character (keeps letters/digits/_ together)
|
|
||||||
String[] tokens = statement.split("[^a-zA-Z0-9_]+");
|
|
||||||
|
|
||||||
for (String token : tokens) {
|
// check for normal definition
|
||||||
if (!token.isEmpty()
|
boolean isDef = statement.contains("=") &&
|
||||||
&& Character.isJavaIdentifierStart(token.charAt(0))
|
!statement.contains("==") &&
|
||||||
&& !isKeyword(token)
|
!statement.contains("<=") &&
|
||||||
&& !token.matches("\\d+")) {
|
!statement.contains(">=") &&
|
||||||
System.out.println("Token to add:");
|
!statement.contains("!=");
|
||||||
System.out.println(token);
|
|
||||||
vars.add(token);
|
String searchArea = statement;
|
||||||
|
|
||||||
|
// Two cases: 1. normal def only RHS matters 2. compound def both LHS and RHS
|
||||||
|
// matter
|
||||||
|
if (isDef) {
|
||||||
|
int eqIndex = statement.indexOf('=');
|
||||||
|
// check for += -= etc. if it exists we found a compound def
|
||||||
|
boolean isCompound = eqIndex > 0 && "+-*/%&|^".indexOf(statement.charAt(eqIndex - 1)) != -1;
|
||||||
|
|
||||||
|
if (isCompound) {
|
||||||
|
// both RHS & LHS
|
||||||
|
searchArea = statement;
|
||||||
|
} else {
|
||||||
|
// only RHS
|
||||||
|
searchArea = statement.substring(eqIndex + 1); // skip anything before =
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Tokenize and filter
|
||||||
|
// fancy split on non-identifier characters to extract all variables used
|
||||||
|
String[] tokens = searchArea.split("[^a-zA-Z0-9_]+");
|
||||||
|
|
||||||
|
for (int i = 0; i < tokens.length; i++) {
|
||||||
|
String token = tokens[i];
|
||||||
|
if (token.isEmpty())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Basic validity checks
|
||||||
|
if (Character.isJavaIdentifierStart(token.charAt(0))
|
||||||
|
&& !isKeyword(token)
|
||||||
|
&& !token.matches("\\d+")) {
|
||||||
|
// skip if its a method
|
||||||
|
boolean isMethodCall = statement.matches(".*\\b" + token + "\\s*\\(.*");
|
||||||
|
|
||||||
|
if (!isMethodCall) {
|
||||||
|
vars.add(token);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return vars;
|
return vars;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -200,10 +257,8 @@ public class PDG {
|
|||||||
reaching.put(node.label(), new HashMap<>());
|
reaching.put(node.label(), new HashMap<>());
|
||||||
}
|
}
|
||||||
boolean changed = true;
|
boolean changed = true;
|
||||||
int iterations = 0;
|
while (changed) {
|
||||||
while (changed && iterations < 100) {
|
|
||||||
changed = false;
|
changed = false;
|
||||||
iterations++;
|
|
||||||
|
|
||||||
for (Node node : cfg.nodes()) {
|
for (Node node : cfg.nodes()) {
|
||||||
String label = node.label();
|
String label = node.label();
|
||||||
@@ -212,24 +267,37 @@ public class PDG {
|
|||||||
for (Edge inEdge : node.inEdges()) {
|
for (Edge inEdge : node.inEdges()) {
|
||||||
Node pred = inEdge.source();
|
Node pred = inEdge.source();
|
||||||
String predLabel = pred.label();
|
String predLabel = pred.label();
|
||||||
|
|
||||||
|
Map<String, Set<String>> predOut = new HashMap<>();
|
||||||
|
|
||||||
|
// In predecesor def
|
||||||
if (reaching.containsKey(predLabel)) {
|
if (reaching.containsKey(predLabel)) {
|
||||||
for (Map.Entry<String, Set<String>> entry : reaching.get(predLabel).entrySet()) {
|
for (Map.Entry<String, Set<String>> entry : reaching.get(predLabel).entrySet()) {
|
||||||
String var = entry.getKey();
|
// create a copy of the set
|
||||||
newReaching.putIfAbsent(var, new HashSet<>());
|
predOut.put(entry.getKey(), new HashSet<>(entry.getValue()));
|
||||||
newReaching.get(var).addAll(entry.getValue());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add predecessor's definitions
|
// kill & gen
|
||||||
for (String var : defs.get(predLabel)) {
|
if (defs.containsKey(predLabel)) {
|
||||||
|
for (String var : defs.get(predLabel)) {
|
||||||
|
// since new def, we update definition of x to new definition
|
||||||
|
Set<String> newDef = new HashSet<>();
|
||||||
|
newDef.add(predLabel);
|
||||||
|
predOut.put(var, newDef);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// merge
|
||||||
|
for (Map.Entry<String, Set<String>> entry : predOut.entrySet()) {
|
||||||
|
String var = entry.getKey();
|
||||||
newReaching.putIfAbsent(var, new HashSet<>());
|
newReaching.putIfAbsent(var, new HashSet<>());
|
||||||
newReaching.get(var).clear();
|
newReaching.get(var).addAll(entry.getValue());
|
||||||
newReaching.get(var).add(predLabel);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
reaching.put(label, newReaching);
|
reaching.put(label, newReaching);
|
||||||
|
// nothing changed then exit
|
||||||
if (!mapsEqual(oldReaching, newReaching)) {
|
if (!mapsEqual(oldReaching, newReaching)) {
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user