diff --git a/core/src/main/java/org/teavm/wasm/decompile/DecompilationVisitor.java b/core/src/main/java/org/teavm/wasm/decompile/DecompilationVisitor.java new file mode 100644 index 000000000..b689cadb3 --- /dev/null +++ b/core/src/main/java/org/teavm/wasm/decompile/DecompilationVisitor.java @@ -0,0 +1,240 @@ +/* + * Copyright 2016 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.wasm.decompile; + +import org.teavm.model.InvokeDynamicInstruction; +import org.teavm.model.instructions.ArrayLengthInstruction; +import org.teavm.model.instructions.AssignInstruction; +import org.teavm.model.instructions.BinaryBranchingInstruction; +import org.teavm.model.instructions.BinaryInstruction; +import org.teavm.model.instructions.BranchingInstruction; +import org.teavm.model.instructions.CastInstruction; +import org.teavm.model.instructions.CastIntegerInstruction; +import org.teavm.model.instructions.CastNumberInstruction; +import org.teavm.model.instructions.ClassConstantInstruction; +import org.teavm.model.instructions.CloneArrayInstruction; +import org.teavm.model.instructions.ConstructArrayInstruction; +import org.teavm.model.instructions.ConstructInstruction; +import org.teavm.model.instructions.ConstructMultiArrayInstruction; +import org.teavm.model.instructions.DoubleConstantInstruction; +import org.teavm.model.instructions.EmptyInstruction; +import org.teavm.model.instructions.ExitInstruction; +import org.teavm.model.instructions.FloatConstantInstruction; +import org.teavm.model.instructions.GetElementInstruction; +import org.teavm.model.instructions.GetFieldInstruction; +import org.teavm.model.instructions.InitClassInstruction; +import org.teavm.model.instructions.InstructionVisitor; +import org.teavm.model.instructions.IntegerConstantInstruction; +import org.teavm.model.instructions.InvokeInstruction; +import org.teavm.model.instructions.IsInstanceInstruction; +import org.teavm.model.instructions.JumpInstruction; +import org.teavm.model.instructions.LongConstantInstruction; +import org.teavm.model.instructions.MonitorEnterInstruction; +import org.teavm.model.instructions.MonitorExitInstruction; +import org.teavm.model.instructions.NegateInstruction; +import org.teavm.model.instructions.NullCheckInstruction; +import org.teavm.model.instructions.NullConstantInstruction; +import org.teavm.model.instructions.PutElementInstruction; +import org.teavm.model.instructions.PutFieldInstruction; +import org.teavm.model.instructions.RaiseInstruction; +import org.teavm.model.instructions.StringConstantInstruction; +import org.teavm.model.instructions.SwitchInstruction; +import org.teavm.model.instructions.UnwrapArrayInstruction; + +public class DecompilationVisitor implements InstructionVisitor { + @Override + public void visit(EmptyInstruction insn) { + + } + + @Override + public void visit(ClassConstantInstruction insn) { + + } + + @Override + public void visit(NullConstantInstruction insn) { + + } + + @Override + public void visit(IntegerConstantInstruction insn) { + + } + + @Override + public void visit(LongConstantInstruction insn) { + + } + + @Override + public void visit(FloatConstantInstruction insn) { + + } + + @Override + public void visit(DoubleConstantInstruction insn) { + + } + + @Override + public void visit(StringConstantInstruction insn) { + + } + + @Override + public void visit(BinaryInstruction insn) { + + } + + @Override + public void visit(NegateInstruction insn) { + + } + + @Override + public void visit(AssignInstruction insn) { + + } + + @Override + public void visit(CastInstruction insn) { + + } + + @Override + public void visit(CastNumberInstruction insn) { + + } + + @Override + public void visit(CastIntegerInstruction insn) { + + } + + @Override + public void visit(BranchingInstruction insn) { + + } + + @Override + public void visit(BinaryBranchingInstruction insn) { + + } + + @Override + public void visit(JumpInstruction insn) { + + } + + @Override + public void visit(SwitchInstruction insn) { + + } + + @Override + public void visit(ExitInstruction insn) { + + } + + @Override + public void visit(RaiseInstruction insn) { + + } + + @Override + public void visit(ConstructArrayInstruction insn) { + + } + + @Override + public void visit(ConstructInstruction insn) { + + } + + @Override + public void visit(ConstructMultiArrayInstruction insn) { + + } + + @Override + public void visit(GetFieldInstruction insn) { + + } + + @Override + public void visit(PutFieldInstruction insn) { + + } + + @Override + public void visit(ArrayLengthInstruction insn) { + + } + + @Override + public void visit(CloneArrayInstruction insn) { + + } + + @Override + public void visit(UnwrapArrayInstruction insn) { + + } + + @Override + public void visit(GetElementInstruction insn) { + + } + + @Override + public void visit(PutElementInstruction insn) { + + } + + @Override + public void visit(InvokeInstruction insn) { + + } + + @Override + public void visit(InvokeDynamicInstruction insn) { + + } + + @Override + public void visit(IsInstanceInstruction insn) { + + } + + @Override + public void visit(InitClassInstruction insn) { + + } + + @Override + public void visit(NullCheckInstruction insn) { + + } + + @Override + public void visit(MonitorEnterInstruction insn) { + } + + @Override + public void visit(MonitorExitInstruction insn) { + } +} diff --git a/core/src/main/java/org/teavm/wasm/decompile/WasmDecompiler.java b/core/src/main/java/org/teavm/wasm/decompile/WasmDecompiler.java new file mode 100644 index 000000000..59fa058ef --- /dev/null +++ b/core/src/main/java/org/teavm/wasm/decompile/WasmDecompiler.java @@ -0,0 +1,135 @@ +/* + * Copyright 2016 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.wasm.decompile; + +import org.teavm.common.DominatorTree; +import org.teavm.common.Graph; +import org.teavm.common.GraphUtils; +import org.teavm.common.Loop; +import org.teavm.common.LoopGraph; +import org.teavm.model.Program; +import org.teavm.model.util.ProgramUtils; +import org.teavm.wasm.model.expression.WasmBlock; +import org.teavm.wasm.model.expression.WasmExpression; + +public class WasmDecompiler { + private Program program; + private LoopGraph cfg; + private DominatorTree dom; + private Graph domGraph; + private Label[] labels; + private WasmExpression[] blockExpressions; + private Step[] stack; + private int stackTop; + + public void decompile(Program program) { + this.program = program; + prepare(); + push(new EnterStep(0)); + run(); + } + + private void prepare() { + cfg = new LoopGraph(ProgramUtils.buildControlFlowGraph(program)); + dom = GraphUtils.buildDominatorTree(cfg); + domGraph = GraphUtils.buildDominatorGraph(dom, cfg.size()); + labels = new Label[cfg.size()]; + blockExpressions = new WasmExpression[cfg.size()]; + stack = new Step[cfg.size() * 4]; + } + + private void run() { + while (stackTop > 0) { + stack[stackTop--].perform(); + } + } + + private void push(Step step) { + stack[stackTop++] = step; + } + + private class EnterStep implements Step { + private int index; + + public EnterStep(int index) { + this.index = index; + } + + @Override + public void perform() { + Loop loop = cfg.loopAt(index); + if (loop != null && loop.getHead() == index) { + enterLoop(); + } else if (cfg.outgoingEdgesCount(index) == 1) { + enterOrdinaryBlock(); + } else { + enterBranching(); + } + } + + private void enterLoop() { + + } + + private void enterOrdinaryBlock() { + + } + + private void enterBranching() { + + } + } + + private class LoopContinueLabel implements Label { + private int index; + private WasmBlock wrapper; + + public LoopContinueLabel(int index) { + this.index = index; + } + + @Override + public WasmBlock getTarget() { + if (wrapper == null) { + wrapper = new WasmBlock(false); + wrapper.getBody().add(blockExpressions[index]); + blockExpressions[index] = wrapper; + } + return wrapper; + } + } + + private class BreakLabel implements Label { + private WasmBlock target; + + public BreakLabel(WasmBlock target) { + this.target = target; + } + + @Override + public WasmBlock getTarget() { + return null; + } + } + + private interface Step { + void perform(); + } + + private interface Label { + WasmBlock getTarget(); + } +} diff --git a/core/src/main/java/org/teavm/wasm/model/WasmModule.java b/core/src/main/java/org/teavm/wasm/model/WasmModule.java index 90eb52351..3c6435567 100644 --- a/core/src/main/java/org/teavm/wasm/model/WasmModule.java +++ b/core/src/main/java/org/teavm/wasm/model/WasmModule.java @@ -15,11 +15,14 @@ */ package org.teavm.wasm.model; +import java.util.ArrayList; import java.util.LinkedHashMap; +import java.util.List; import java.util.Map; public class WasmModule { private Map functions = new LinkedHashMap<>(); + private List functionTable = new ArrayList<>(); public void add(WasmFunction function) { if (functions.containsKey(function.getName())) { @@ -31,4 +34,8 @@ public class WasmModule { functions.put(function.getName(), function); function.module = this; } + + public List getFunctionTable() { + return functionTable; + } }