Skip to content

Commit

Permalink
Working on graph pattern matcher
Browse files Browse the repository at this point in the history
  • Loading branch information
mirkosertic committed May 3, 2024
1 parent 8b43299 commit a239c97
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 42 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
import de.mirkosertic.bytecoder.core.ir.ControlTokenConsumer;
import de.mirkosertic.bytecoder.core.ir.Graph;
import de.mirkosertic.bytecoder.core.ir.Node;
import de.mirkosertic.bytecoder.core.ir.NodeType;
import de.mirkosertic.bytecoder.core.ir.Projection;

import java.util.ArrayList;
import java.util.HashMap;
Expand All @@ -31,7 +33,6 @@
public class GraphPatternMatcher {

private interface Context {
Node[] outgoingDataFlowsFor(final Node node);
}

private static class Path {
Expand All @@ -46,16 +47,16 @@ private Path(final String path) {
this.path = path;
}

public Path addIncoming(final int i) {
return new Path(path + ".i[" + i + "]");
public Path addIncoming(final int incomingIndex, final NodeType nodeType, final int expectedIndex) {
return new Path(path + ".i[" + incomingIndex + ":" + nodeType + ":" + expectedIndex + "]");
}

public Path addOutgoing(final int i) {
return new Path(path + ".o[" + i + "]");
public Path controlComingFrom(final int nodeIndex, final NodeType nodeType) {
return new Path(path + ".cin[" + nodeIndex + ":" + nodeType + "]");
}

public Path controlComingFrom(final int nodeIndex) {
return new Path(path + ".cin[" + nodeIndex + "]");
public Path controlGoingTo(final Projection projection, final int nodeIndex, final NodeType nodeType) {
return new Path(path + ".cout[" + nodeIndex + ":" + nodeType + ":" + projection + ":" + projection.edgeType() + "]");
}

@Override
Expand All @@ -79,18 +80,19 @@ public Node resolve(final Node root, final Context context) {
if ("R".equals(token)) {
node = root;
} else if (token.startsWith("i[")) {
int index = Integer.parseInt(token.substring(2, token.length() - 1));
final int p = token.indexOf(":");
final int p2 = token.lastIndexOf(":");
final int index = Integer.parseInt(token.substring(2, p));
final NodeType nodeType = NodeType.valueOf(token.substring(p + 1, p2));
final int expectedNodeIndex = Integer.parseInt(token.substring(p2 + 1, token.length() - 1));
final Node[] incoming = node.incomingDataFlows;
if (incoming.length > index) {
node = incoming[index];
} else {
return null;
}
} else if (token.startsWith("o[")) {
int index = Integer.parseInt(token.substring(2, token.length() - 1));
final Node[] outgoing = context.outgoingDataFlowsFor(node);
if (outgoing.length > index) {
node = outgoing[index];
if (node.nodeType != nodeType) {
// Unexpected node type
return null;
}
// TODO: Verify index is the same
} else {
return null;
}
Expand Down Expand Up @@ -183,22 +185,7 @@ private void registerPaths(final Node pivot, final CompiledPattern compiledPatte
for (int i = 0; i < incomingDataFlow.length; i++) {
final Node n = incomingDataFlow[i];
final boolean registered = compiledPattern.registerToIndex(n);
final Path newPath = workingItemPath.addIncoming(i);

final List<Path> paths = compiledPattern.nodeToPaths.computeIfAbsent(n, key -> new ArrayList<>());
if (!paths.contains(newPath)) {
paths.add(newPath);
}

if (registered) {
workingQueue.add(new PathAnalysisState(n, newPath));
}
}
final Node[] outgoing = workingItem.node.outgoingDataFlows();
for (int i = 0; i < outgoing.length; i++) {
final Node n = outgoing[i];
final boolean registered = compiledPattern.registerToIndex(n);
final Path newPath = workingItemPath.addOutgoing(i);
final Path newPath = workingItemPath.addIncoming(i, n.nodeType, compiledPattern.nodeIndexOf(n));

final List<Path> paths = compiledPattern.nodeToPaths.computeIfAbsent(n, key -> new ArrayList<>());
if (!paths.contains(newPath)) {
Expand All @@ -214,7 +201,7 @@ private void registerPaths(final Node pivot, final CompiledPattern compiledPatte
final ControlTokenConsumer control = (ControlTokenConsumer) workingItem.node;
for (final ControlTokenConsumer inc : control.controlComingFrom) {
final boolean registered = compiledPattern.registerToIndex(inc);
final Path newPath = workingItemPath.controlComingFrom(compiledPattern.nodeIndexOf(inc));
final Path newPath = workingItemPath.controlComingFrom(compiledPattern.nodeIndexOf(inc), inc.nodeType);

final List<Path> paths = compiledPattern.nodeToPaths.computeIfAbsent(inc, key -> new ArrayList<>());
if (!paths.contains(newPath)) {
Expand All @@ -225,6 +212,19 @@ private void registerPaths(final Node pivot, final CompiledPattern compiledPatte
workingQueue.add(new PathAnalysisState(inc, newPath));
}
}
for (final Map.Entry<Projection, ControlTokenConsumer> entry : control.controlFlowsTo.entrySet()) {
final ControlTokenConsumer target = entry.getValue();
compiledPattern.registerToIndex(target);

final Path newPath = workingItemPath.controlGoingTo(entry.getKey(), compiledPattern.nodeIndexOf(target), target.nodeType);

final List<Path> paths = compiledPattern.nodeToPaths.computeIfAbsent(target, key -> new ArrayList<>());
if (!paths.contains(newPath)) {
paths.add(newPath);
}

workingQueue.add(new PathAnalysisState(target, newPath));
}
}
}
}
Expand All @@ -241,13 +241,6 @@ public List<Node> findMatches(final Graph source) {
final List<Node> result = new ArrayList<>();

final Context c = new Context() {

private final Map<Node, Node[]> outgoingFlows = new HashMap<>();

@Override
public Node[] outgoingDataFlowsFor(final Node node) {
return outgoingFlows.computeIfAbsent(node, Node::outgoingDataFlows);
}
};

// We search for all analysis candidates in source with the same nodetype as pivot
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,10 @@

public class GraphPatternMatcherTest {

private static final Logger logger = new Slf4JLogger();

@Test
public void testEmpty() {
final Logger logger = new Slf4JLogger();
final Graph source = new Graph(logger);
final Graph pattern = new Graph(logger);
final Node pivot = pattern.newRegion("Test");
Expand All @@ -40,7 +41,6 @@ public void testEmpty() {

@Test
public void testSearchForCopy() {
final Logger logger = new Slf4JLogger();
final Graph source = new Graph(logger);
final Variable st = source.newVariable(Type.INT_TYPE);
final Node sc = source.newCopy();
Expand Down

0 comments on commit a239c97

Please sign in to comment.