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() {
System.out.println("\tComputing control dependencies...");
boolean changed = true;
while (changed) {
changed = false;
for (Node node : cfg.nodes()) {
Set<String> deps = new HashSet<>();
for (Edge inEdge : node.inEdges()) {
Node pred = inEdge.source();
if (pred.outEdges().size() > 1) {
deps.add(pred.label());
// get all deps from
if (controlDeps.containsKey(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;
}
}
}
System.out.println("\t\tFound " + countDependencies(controlDeps) + " control dependencies");
@@ -97,53 +110,70 @@ public class PDG {
*/
private Set<String> extractDefs(String statement) {
Set<String> vars = new HashSet<>();
// Skip special nodes
if (statement.startsWith("*"))
// exclude comments
if (statement.startsWith("*") || statement.startsWith("/"))
return vars;
if (statement.contains("=") && !statement.contains("==")) {
String[] parts = statement.split("=");
// Debug proper variabel naem selection:
// System.out.printf("Statement: %s", statement);
// print anything before "="
// System.out.println(parts[0]);
// used for normal assignments exclude anything else
boolean isDef = statement.contains("=") &&
!statement.contains("==") &&
!statement.contains("<=") &&
!statement.contains(">=") &&
!statement.contains("!=");
// retrieve teh first "word" before equals
Pattern p = Pattern.compile("(\\w+)\\s*$");
Matcher m = p.matcher(parts[0]);
String varLabel = "-1";
if (isDef) {
String lhs = statement.substring(0, statement.indexOf('=')).trim();
if (m.find()) {
varLabel = m.group(1);
}
if ((!varLabel.isEmpty() || varLabel == "-1") && Character.isJavaIdentifierStart(varLabel.charAt(0))) {
// print variable to be assigned
// System.out.println(varLabel);
vars.add(varLabel);
// remove left over operators after getting teh substring
if (lhs.endsWith("+") || lhs.endsWith("-") || lhs.endsWith("*") || lhs.endsWith("/") || lhs.endsWith("%")
|| lhs.endsWith("&") || lhs.endsWith("|") || lhs.endsWith("^")) {
lhs = lhs.substring(0, lhs.length() - 1).trim();
}
// 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("(")) {
String forPart = statement.substring(statement.indexOf("("));
String[] forParts = forPart.split(";");
if (forParts.length >= 3) {
if (forParts[0].contains("=")) {
String[] initParts = forParts[0].split("=");
if (initParts.length > 0) {
String var = initParts[0].trim().replaceAll("[^a-zA-Z0-9_]", "");
if (!var.isEmpty())
String inside = statement.substring(statement.indexOf("(") + 1);
if (inside.contains(";")) {
String[] parts = inside.split(";");
// Init def: "int i = 0"
if (parts.length > 0 && parts[0].contains("=")) {
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);
}
}
String update = forParts[forParts.length - 1];
// 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.replaceAll("[^a-zA-Z0-9_]", "");
String var = update;
if (!var.isEmpty())
vars.add(var);
}
}
}
}
return vars;
}
@@ -153,26 +183,53 @@ public class PDG {
*/
private Set<String> extractUses(String statement) {
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) {
if (!token.isEmpty()
&& Character.isJavaIdentifierStart(token.charAt(0))
// check for normal definition
boolean isDef = statement.contains("=") &&
!statement.contains("==") &&
!statement.contains("<=") &&
!statement.contains(">=") &&
!statement.contains("!=");
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+")) {
System.out.println("Token to add:");
System.out.println(token);
// skip if its a method
boolean isMethodCall = statement.matches(".*\\b" + token + "\\s*\\(.*");
if (!isMethodCall) {
vars.add(token);
}
}
}
return vars;
}
@@ -200,10 +257,8 @@ public class PDG {
reaching.put(node.label(), new HashMap<>());
}
boolean changed = true;
int iterations = 0;
while (changed && iterations < 100) {
while (changed) {
changed = false;
iterations++;
for (Node node : cfg.nodes()) {
String label = node.label();
@@ -212,24 +267,37 @@ public class PDG {
for (Edge inEdge : node.inEdges()) {
Node pred = inEdge.source();
String predLabel = pred.label();
Map<String, Set<String>> predOut = new HashMap<>();
// In predecesor def
if (reaching.containsKey(predLabel)) {
for (Map.Entry<String, Set<String>> entry : reaching.get(predLabel).entrySet()) {
// create a copy of the set
predOut.put(entry.getKey(), new HashSet<>(entry.getValue()));
}
}
// kill & gen
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.get(var).addAll(entry.getValue());
}
}
// Add predecessor's definitions
for (String var : defs.get(predLabel)) {
newReaching.putIfAbsent(var, new HashSet<>());
newReaching.get(var).clear();
newReaching.get(var).add(predLabel);
}
}
reaching.put(label, newReaching);
// nothing changed then exit
if (!mapsEqual(oldReaching, newReaching)) {
changed = true;
}