diff --git a/teavm-core/src/main/java/org/teavm/javascript/MethodDecompiler.java b/teavm-core/src/main/java/org/teavm/javascript/MethodDecompiler.java index db526a544..c36e60030 100644 --- a/teavm-core/src/main/java/org/teavm/javascript/MethodDecompiler.java +++ b/teavm-core/src/main/java/org/teavm/javascript/MethodDecompiler.java @@ -87,6 +87,7 @@ public class MethodDecompiler { generator.program = program; generator.blockMap = blockMap; generator.indexer = indexer; + generator.outgoings = getPhiOutgoings(program); parentNode = codeTree.getRoot(); currentNode = parentNode.getFirstChild(); for (int i = 0; i < this.graph.size(); ++i) { @@ -128,6 +129,26 @@ public class MethodDecompiler { return renderable; } + private Incoming[][] getPhiOutgoings(Program program) { + List> outgoings = new ArrayList<>(); + for (int i = 0; i < program.basicBlockCount(); ++i) { + outgoings.add(new ArrayList()); + } + for (int i = 0; i < program.basicBlockCount(); ++i) { + BasicBlock basicBlock = program.basicBlockAt(i); + for (Phi phi : basicBlock.getPhis()) { + for (Incoming incoming : phi.getIncomings()) { + outgoings.get(incoming.getSource().getIndex()).add(incoming); + } + } + } + Incoming[][] result = new Incoming[outgoings.size()][]; + for (int i = 0; i < outgoings.size(); ++i) { + result[i] = outgoings.get(i).toArray(new Incoming[0]); + } + return result; + } + private List createBlocks(int start) { List result = new ArrayList<>(); while (currentNode != null && currentNode.getStart() == start) { diff --git a/teavm-core/src/main/java/org/teavm/javascript/StatementGenerator.java b/teavm-core/src/main/java/org/teavm/javascript/StatementGenerator.java index 87754cb95..077b9d35b 100644 --- a/teavm-core/src/main/java/org/teavm/javascript/StatementGenerator.java +++ b/teavm-core/src/main/java/org/teavm/javascript/StatementGenerator.java @@ -21,6 +21,7 @@ public class StatementGenerator implements InstructionVisitor { MethodDecompiler.Block[] blockMap; Program program; ClassHolderSource classSource; + Incoming[][] outgoings; @Override public void visit(EmptyInstruction insn) { @@ -527,7 +528,7 @@ public class StatementGenerator implements InstructionVisitor { assign(castToInteger(Expr.binary(op, Expr.var(first), Expr.var(second))), result); } - private Statement generateJumpStatement(BasicBlock target) { + private Statement generateJumpStatementWithoutPhis(BasicBlock target) { if (nextBlock == target) { return null; } @@ -543,8 +544,24 @@ public class StatementGenerator implements InstructionVisitor { } } - private Statement generateJumpStatement(SwitchStatement stmt, int target) { - Statement body = generateJumpStatement(program.basicBlockAt(target)); + private Statement wrapWithPhis(Statement rawJump) { + SequentialStatement seq = new SequentialStatement(); + for (Incoming outgoing : outgoings[currentBlock.getIndex()]) { + seq.getSequence().add(Statement.assign(Expr.var(outgoing.getPhi().getReceiver().getIndex()), + Expr.var(outgoing.getValue().getIndex()))); + } + if (rawJump != null) { + seq.getSequence().add(rawJump); + } + return !seq.getSequence().isEmpty() ? seq : null; + } + + private Statement generateJumpStatement(BasicBlock target) { + return wrapWithPhis(generateJumpStatementWithoutPhis(target)); + } + + private Statement generateJumpStatementWithoutPhis(SwitchStatement stmt, int target) { + Statement body = generateJumpStatementWithoutPhis(program.basicBlockAt(target)); if (body == null) { BreakStatement breakStmt = new BreakStatement(); breakStmt.setTarget(stmt); @@ -553,6 +570,10 @@ public class StatementGenerator implements InstructionVisitor { return body; } + private Statement generateJumpStatement(SwitchStatement stmt, int target) { + return wrapWithPhis(generateJumpStatementWithoutPhis(stmt, target)); + } + private void branch(Expr condition, BasicBlock consequentBlock, BasicBlock alternativeBlock) { Statement consequent = generateJumpStatement(consequentBlock); Statement alternative = generateJumpStatement(alternativeBlock);