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:
Nicolas Amaya
2025-12-15 20:03:43 -07:00
parent 046634109c
commit 4c7002c263

View File

@@ -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;
} }