use of de.mirkosertic.bytecoder.ssa.ExpressionListContainer 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());
}
}
}
}
use of de.mirkosertic.bytecoder.ssa.ExpressionListContainer in project Bytecoder by mirkosertic.
the class InlineFinalNodesOptimizer method inline.
private void inline(Map<BytecodeOpcodeAddress, RegionNode> aFinalNodes, ExpressionList aList) {
for (Expression theExpression : aList.toList()) {
if (theExpression instanceof ExpressionListContainer) {
ExpressionListContainer theContainer = (ExpressionListContainer) theExpression;
for (ExpressionList theList : theContainer.getExpressionLists()) {
inline(aFinalNodes, theList);
}
}
if (theExpression instanceof GotoExpression) {
GotoExpression theGoto = (GotoExpression) theExpression;
RegionNode thePotentialFinal = aFinalNodes.get(theGoto.getJumpTarget());
if (thePotentialFinal != null) {
aList.replace(theExpression, thePotentialFinal.getExpressions());
}
}
}
}
use of de.mirkosertic.bytecoder.ssa.ExpressionListContainer in project Bytecoder by mirkosertic.
the class InlineGotoOptimizer method performNodeInlining.
private boolean performNodeInlining(ControlFlowGraph aGraph, RegionNode aNode, ExpressionList aList, List<BytecodeOpcodeAddress> aJumpTargets) {
for (Expression theExpression : aList.toList()) {
if (theExpression instanceof ExpressionListContainer) {
ExpressionListContainer theContainer = (ExpressionListContainer) theExpression;
for (ExpressionList theList : theContainer.getExpressionLists()) {
if (performNodeInlining(aGraph, aNode, theList, aJumpTargets)) {
return true;
}
}
}
if (theExpression instanceof GotoExpression) {
GotoExpression theGOTO = (GotoExpression) theExpression;
RegionNode theTargetNode = aGraph.nodeStartingAt(theGOTO.getJumpTarget());
if (theTargetNode.isStrictlyDominatedBy(aNode)) {
BytecodeOpcodeAddress theJumpTarget = theGOTO.getJumpTarget();
int theCount = 0;
for (BytecodeOpcodeAddress theEntry : aJumpTargets) {
if (theEntry.equals(theJumpTarget)) {
theCount++;
}
}
if (theCount == 1) {
// Node can be inlined
aGraph.delete(theTargetNode);
aList.replace(theGOTO, theTargetNode.getExpressions());
aNode.inheritSuccessorsOf(theTargetNode);
for (RegionNode theNode : aGraph.getKnownNodes()) {
recomputeGotos(theNode.getExpressions(), theTargetNode.getStartAddress(), aNode.getStartAddress());
}
return true;
}
}
}
}
return false;
}
use of de.mirkosertic.bytecoder.ssa.ExpressionListContainer in project Bytecoder by mirkosertic.
the class InlineGotoOptimizer method recomputeGotos.
private void recomputeGotos(ExpressionList aList, BytecodeOpcodeAddress aOriginal, BytecodeOpcodeAddress aNew) {
for (Expression theExpression : aList.toList()) {
if (theExpression instanceof ExpressionListContainer) {
ExpressionListContainer theContainer = (ExpressionListContainer) theExpression;
for (ExpressionList theList : theContainer.getExpressionLists()) {
recomputeGotos(theList, aOriginal, aNew);
}
}
if (theExpression instanceof GotoExpression) {
GotoExpression theGoto = (GotoExpression) theExpression;
if (Objects.equals(theGoto.getJumpTarget(), aOriginal)) {
GotoExpression theNewGoto = new GotoExpression(aNew);
aList.replace(theGoto, theNewGoto);
}
}
}
}
Aggregations