use of de.mirkosertic.bytecoder.ssa.GotoExpression in project Bytecoder by mirkosertic.
the class InlineGotoOptimizerTest method testSimpleFlow.
@Test
public void testSimpleFlow() {
Program theProgram = new Program();
ControlFlowGraph theGraph = theProgram.getControlFlowGraph();
RegionNode theNode = theGraph.createAt(BytecodeOpcodeAddress.START_AT_ZERO, RegionNode.BlockType.NORMAL);
RegionNode theNode2 = theGraph.createAt(new BytecodeOpcodeAddress(20), RegionNode.BlockType.NORMAL);
theNode.getExpressions().add(new GotoExpression(new BytecodeOpcodeAddress(20)));
theNode.addSuccessor(theNode2);
theNode2.getExpressions().add(new ReturnExpression());
theGraph.calculateReachabilityAndMarkBackEdges();
InlineGotoOptimizer theOptimizer = new InlineGotoOptimizer();
theOptimizer.optimize(theGraph, null);
Assert.assertEquals(1, theGraph.getKnownNodes().size(), 0);
Assert.assertEquals(1, theGraph.getDominatedNodes().size(), 0);
Assert.assertTrue(theGraph.getKnownNodes().contains(theNode));
Assert.assertEquals(1, theNode.getExpressions().size(), 0);
Assert.assertTrue(theNode.getExpressions().toList().get(0) instanceof ReturnExpression);
Assert.assertEquals(0, theNode.getSuccessors().size(), 0);
Relooper theRelooper = new Relooper();
Relooper.Block theRoot = theRelooper.reloop(theGraph);
}
use of de.mirkosertic.bytecoder.ssa.GotoExpression in project Bytecoder by mirkosertic.
the class InlineGotoOptimizerTest method testIf.
@Test
public void testIf() {
Program theProgram = new Program();
ControlFlowGraph theGraph = theProgram.getControlFlowGraph();
RegionNode theNode = theGraph.createAt(BytecodeOpcodeAddress.START_AT_ZERO, RegionNode.BlockType.NORMAL);
RegionNode theNode1 = theGraph.createAt(new BytecodeOpcodeAddress(20), RegionNode.BlockType.NORMAL);
RegionNode theNode2 = theGraph.createAt(new BytecodeOpcodeAddress(40), RegionNode.BlockType.NORMAL);
RegionNode theNode3 = theGraph.createAt(new BytecodeOpcodeAddress(60), RegionNode.BlockType.NORMAL);
theNode.addSuccessor(theNode1);
theNode.addSuccessor(theNode2);
ExpressionList theTrueClause = new ExpressionList();
theTrueClause.add(new GotoExpression(new BytecodeOpcodeAddress(20)));
IFExpression theIF = new IFExpression(new BytecodeOpcodeAddress(0), new BytecodeOpcodeAddress(20), new IntegerValue(10), theTrueClause);
theNode.getExpressions().add(theIF);
theNode.getExpressions().add(new GotoExpression(new BytecodeOpcodeAddress(40)));
theNode1.addSuccessor(theNode3);
theNode1.getExpressions().add(new GotoExpression(new BytecodeOpcodeAddress(60)));
theNode2.addSuccessor(theNode3);
theNode2.getExpressions().add(new GotoExpression(new BytecodeOpcodeAddress(60)));
theNode3.getExpressions().add(new ReturnExpression());
theGraph.calculateReachabilityAndMarkBackEdges();
InlineGotoOptimizer theOptimizer = new InlineGotoOptimizer();
theOptimizer.optimize(theGraph, null);
System.out.println(theGraph.toDOT());
}
use of de.mirkosertic.bytecoder.ssa.GotoExpression in project Bytecoder by mirkosertic.
the class RelooperTest method testEndlessLoop.
@Test
public void testEndlessLoop() {
Program theProgram = new Program();
ControlFlowGraph theGraph = new ControlFlowGraph(theProgram);
RegionNode theNode1 = theGraph.createAt(BytecodeOpcodeAddress.START_AT_ZERO, RegionNode.BlockType.NORMAL);
theNode1.getExpressions().add(new GotoExpression(new BytecodeOpcodeAddress(10)));
RegionNode theNode2 = theGraph.createAt(new BytecodeOpcodeAddress(10), RegionNode.BlockType.NORMAL);
theNode2.getExpressions().add(new GotoExpression(new BytecodeOpcodeAddress(20)));
RegionNode theNode3 = theGraph.createAt(new BytecodeOpcodeAddress(20), RegionNode.BlockType.NORMAL);
theNode3.getExpressions().add(new GotoExpression(BytecodeOpcodeAddress.START_AT_ZERO));
theNode1.addSuccessor(theNode2);
theNode2.addSuccessor(theNode3);
theNode3.addSuccessor(theNode1);
theGraph.calculateReachabilityAndMarkBackEdges();
Relooper theRelooper = new Relooper();
Relooper.Block theBlock = theRelooper.reloop(theGraph);
theRelooper.debugPrint(System.out, theBlock);
}
use of de.mirkosertic.bytecoder.ssa.GotoExpression in project Bytecoder by mirkosertic.
the class Relooper method debugPrint.
private void debugPrint(PrintStream aStream, int aInset, ExpressionList aExpressionList) {
for (Expression theExpression : aExpressionList.toList()) {
if (theExpression instanceof BreakExpression) {
BreakExpression theBreak = (BreakExpression) theExpression;
printInset(aStream, aInset);
aStream.println("Break " + theBreak.blockToBreak().name() + " and jump to " + theBreak.jumpTarget().getAddress());
} else if (theExpression instanceof ContinueExpression) {
ContinueExpression theContinue = (ContinueExpression) theExpression;
printInset(aStream, aInset);
aStream.println("Continue at " + theContinue.labelToReturnTo().name());
} else if (theExpression instanceof ReturnExpression) {
printInset(aStream, aInset);
aStream.println("Return");
} else if (theExpression instanceof GotoExpression) {
throw new IllegalStateException("Goto should have been removed!");
}
}
}
use of de.mirkosertic.bytecoder.ssa.GotoExpression in project Bytecoder by mirkosertic.
the class Relooper method replaceGotosIn.
private void replaceGotosIn(Stack<Block> aTraversalStack, SimpleBlock aCurrent, RegionNode aLabel, ExpressionList aList) {
for (Expression theExpression : aList.toList()) {
if (theExpression instanceof ExpressionListContainer) {
ExpressionListContainer theContainer = (ExpressionListContainer) theExpression;
for (ExpressionList theList : theContainer.getExpressionLists()) {
replaceGotosIn(aTraversalStack, aCurrent, aLabel, theList);
}
}
if (theExpression instanceof GotoExpression) {
GotoExpression theGoto = (GotoExpression) theExpression;
boolean theGotoFound = false;
// We search the successor edge
for (Map.Entry<RegionNode.Edge, RegionNode> theSuc : aLabel.getSuccessors().entrySet()) {
if (Objects.equals(theSuc.getValue().getStartAddress(), theGoto.getJumpTarget())) {
theGotoFound = true;
RegionNode theTarget = theSuc.getValue();
// We found the matching edge
if (theSuc.getKey().getType() == RegionNode.EdgeType.NORMAL) {
// We can only branch to the next block
// We search the whole hiararchy to find the right block to break out
boolean theSomethingFound = false;
for (int i = aTraversalStack.size() - 1; i >= 0; i--) {
Block theNestingBlock = aTraversalStack.get(i);
if (theNestingBlock.next() != null && theNestingBlock.next().entries().contains(theTarget)) {
theNestingBlock.requireLabel();
BreakExpression theBreak = new BreakExpression(theNestingBlock.label(), theTarget.getStartAddress());
aList.replace(theGoto, theBreak);
if (theNestingBlock.next() instanceof SimpleBlock && theNestingBlock.next().entries().size() == 1) {
theBreak.noSetRequired();
}
theSomethingFound = true;
break;
} else if (theNestingBlock.entries().contains(theTarget)) {
theNestingBlock.requireLabel();
ContinueExpression theContinue = new ContinueExpression(theNestingBlock.label(), theTarget.getStartAddress());
aList.replace(theGoto, theContinue);
theSomethingFound = true;
break;
}
}
if (!theSomethingFound) {
throw new IllegalStateException("Failed to jump to " + theTarget.getStartAddress().getAddress() + " from " + aCurrent.label().name() + " : no matching entry found!");
}
} else {
// We can only branch back into the known stack of nested blocks
boolean theSomethingFound = false;
for (Block theNestingBlock : aTraversalStack) {
if (theNestingBlock.entries().contains(theTarget)) {
theSomethingFound = true;
// We can return to the target in the hierarchy
theNestingBlock.requireLabel();
ContinueExpression theContinue = new ContinueExpression(theNestingBlock.label(), theTarget.getStartAddress());
aList.replace(theGoto, theContinue);
break;
}
}
if (!theSomethingFound) {
throw new IllegalStateException("No back edge target found for " + theTarget.getStartAddress().getAddress());
}
}
}
}
if (!theGotoFound) {
throw new IllegalStateException("No GOTO possible for " + theGoto.getJumpTarget().getAddress() + " in label " + aCurrent.label().name());
}
}
}
}
Aggregations