mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2025-01-23 23:04:50 -08:00
Continue developing decompiler
This commit is contained in:
parent
96ba2bbf7d
commit
d672fe068a
|
@ -165,6 +165,36 @@ public final class GraphUtils {
|
||||||
return graph.build();
|
return graph.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static int[] dfs(Graph graph) {
|
||||||
|
int[] result = new int[graph.size()];
|
||||||
|
int[] state = new int[graph.size()];
|
||||||
|
int[] stack = new int[graph.size() * 2];
|
||||||
|
int top = 0;
|
||||||
|
stack[top++] = 0;
|
||||||
|
int index = graph.size();
|
||||||
|
|
||||||
|
while (top > 0) {
|
||||||
|
int node = stack[--top];
|
||||||
|
switch (state[node]) {
|
||||||
|
case 0:
|
||||||
|
state[node] = 1;
|
||||||
|
stack[top++] = node;
|
||||||
|
for (int successor : graph.outgoingEdges(node)) {
|
||||||
|
if (state[successor] == 0) {
|
||||||
|
stack[top++] = node;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
result[node] = --index;
|
||||||
|
state[node] = 2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
public static void splitIrreducibleGraph(Graph graph, int[] weights, GraphSplittingBackend backend) {
|
public static void splitIrreducibleGraph(Graph graph, int[] weights, GraphSplittingBackend backend) {
|
||||||
new IrreducibleGraphConverter().convertToReducible(graph, weights, backend);
|
new IrreducibleGraphConverter().convertToReducible(graph, weights, backend);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,39 +0,0 @@
|
||||||
/*
|
|
||||||
* 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 com.carrotsearch.hppc.IntObjectMap;
|
|
||||||
import com.carrotsearch.hppc.IntObjectOpenHashMap;
|
|
||||||
|
|
||||||
public final class ContextUtils {
|
|
||||||
private ContextUtils() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void withLabels(Context context, IntObjectMap<Label> labels) {
|
|
||||||
IntObjectMap<Label> undo = new IntObjectOpenHashMap<>();
|
|
||||||
for (int node : labels.keys().toArray()) {
|
|
||||||
undo.put(node, context.getLabel(node));
|
|
||||||
}
|
|
||||||
context.push(() -> withLabelsImpl(context, undo));
|
|
||||||
withLabelsImpl(context, labels);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void withLabelsImpl(Context context, IntObjectMap<Label> labels) {
|
|
||||||
for (int node : labels.keys().toArray()) {
|
|
||||||
context.setLabel(node, labels.get(node));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,161 @@
|
||||||
|
/*
|
||||||
|
* 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.instructions.BinaryBranchingInstruction;
|
||||||
|
import org.teavm.model.instructions.BranchingCondition;
|
||||||
|
import org.teavm.model.instructions.BranchingInstruction;
|
||||||
|
import org.teavm.model.util.VariableType;
|
||||||
|
import org.teavm.wasm.model.WasmLocal;
|
||||||
|
import org.teavm.wasm.model.WasmType;
|
||||||
|
import org.teavm.wasm.model.expression.WasmExpression;
|
||||||
|
import org.teavm.wasm.model.expression.WasmFloat32Constant;
|
||||||
|
import org.teavm.wasm.model.expression.WasmFloat64Constant;
|
||||||
|
import org.teavm.wasm.model.expression.WasmFloatBinary;
|
||||||
|
import org.teavm.wasm.model.expression.WasmFloatBinaryOperation;
|
||||||
|
import org.teavm.wasm.model.expression.WasmFloatType;
|
||||||
|
import org.teavm.wasm.model.expression.WasmInt32Constant;
|
||||||
|
import org.teavm.wasm.model.expression.WasmInt64Constant;
|
||||||
|
import org.teavm.wasm.model.expression.WasmIntBinary;
|
||||||
|
import org.teavm.wasm.model.expression.WasmIntBinaryOperation;
|
||||||
|
import org.teavm.wasm.model.expression.WasmIntType;
|
||||||
|
import org.teavm.wasm.model.expression.WasmLocalReference;
|
||||||
|
|
||||||
|
final class DecompileSupport {
|
||||||
|
private DecompileSupport() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static WasmExpression getCondition(BranchingInstruction instruction, WasmLocal local, VariableType type) {
|
||||||
|
WasmExpression operand = new WasmLocalReference(local);
|
||||||
|
|
||||||
|
WasmExpression condition;
|
||||||
|
switch (type) {
|
||||||
|
case FLOAT:
|
||||||
|
condition = new WasmFloatBinary(WasmFloatType.FLOAT32, getFloatCondition(instruction.getCondition()),
|
||||||
|
operand, new WasmFloat32Constant(0));
|
||||||
|
break;
|
||||||
|
case DOUBLE:
|
||||||
|
condition = new WasmFloatBinary(WasmFloatType.FLOAT64, getFloatCondition(instruction.getCondition()),
|
||||||
|
operand, new WasmFloat64Constant(0));
|
||||||
|
break;
|
||||||
|
case INT:
|
||||||
|
condition = new WasmIntBinary(WasmIntType.INT32, getIntCondition(instruction.getCondition()),
|
||||||
|
operand, new WasmInt32Constant(0));
|
||||||
|
break;
|
||||||
|
case LONG:
|
||||||
|
condition = new WasmIntBinary(WasmIntType.INT64, getIntCondition(instruction.getCondition()),
|
||||||
|
operand, new WasmInt64Constant(0));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
condition = new WasmIntBinary(WasmIntType.INT32, getReferenceCondition(instruction.getCondition()),
|
||||||
|
operand, new WasmInt32Constant(0));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return operand;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static WasmExpression getCondition(BinaryBranchingInstruction instruction, WasmLocal first,
|
||||||
|
WasmLocal second) {
|
||||||
|
WasmExpression a = new WasmLocalReference(first);
|
||||||
|
WasmExpression b = new WasmLocalReference(second);
|
||||||
|
|
||||||
|
WasmExpression condition;
|
||||||
|
switch (instruction.getCondition()) {
|
||||||
|
case REFERENCE_EQUAL:
|
||||||
|
case EQUAL:
|
||||||
|
condition = new WasmIntBinary(WasmIntType.INT32, WasmIntBinaryOperation.EQ, a, b);
|
||||||
|
break;
|
||||||
|
case REFERENCE_NOT_EQUAL:
|
||||||
|
case NOT_EQUAL:
|
||||||
|
condition = new WasmIntBinary(WasmIntType.INT32, WasmIntBinaryOperation.NE, a, b);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new IllegalArgumentException(instruction.getCondition().toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
return condition;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static WasmFloatBinaryOperation getFloatCondition(BranchingCondition condition) {
|
||||||
|
switch (condition) {
|
||||||
|
case EQUAL:
|
||||||
|
return WasmFloatBinaryOperation.EQ;
|
||||||
|
case NOT_EQUAL:
|
||||||
|
return WasmFloatBinaryOperation.NE;
|
||||||
|
case GREATER:
|
||||||
|
return WasmFloatBinaryOperation.GT;
|
||||||
|
case GREATER_OR_EQUAL:
|
||||||
|
return WasmFloatBinaryOperation.GE;
|
||||||
|
case LESS:
|
||||||
|
return WasmFloatBinaryOperation.LT;
|
||||||
|
case LESS_OR_EQUAL:
|
||||||
|
return WasmFloatBinaryOperation.LE;
|
||||||
|
case NULL:
|
||||||
|
case NOT_NULL:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
throw new IllegalArgumentException(condition.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static WasmIntBinaryOperation getIntCondition(BranchingCondition condition) {
|
||||||
|
switch (condition) {
|
||||||
|
case EQUAL:
|
||||||
|
return WasmIntBinaryOperation.EQ;
|
||||||
|
case NOT_EQUAL:
|
||||||
|
return WasmIntBinaryOperation.NE;
|
||||||
|
case GREATER:
|
||||||
|
return WasmIntBinaryOperation.GT_SIGNED;
|
||||||
|
case GREATER_OR_EQUAL:
|
||||||
|
return WasmIntBinaryOperation.GE_SIGNED;
|
||||||
|
case LESS:
|
||||||
|
return WasmIntBinaryOperation.LT_SIGNED;
|
||||||
|
case LESS_OR_EQUAL:
|
||||||
|
return WasmIntBinaryOperation.LE_SIGNED;
|
||||||
|
case NULL:
|
||||||
|
case NOT_NULL:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
throw new IllegalArgumentException(condition.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static WasmIntBinaryOperation getReferenceCondition(BranchingCondition condition) {
|
||||||
|
switch (condition) {
|
||||||
|
case NULL:
|
||||||
|
return WasmIntBinaryOperation.EQ;
|
||||||
|
case NOT_NULL:
|
||||||
|
return WasmIntBinaryOperation.NE;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
throw new IllegalArgumentException(condition.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static WasmType mapType(VariableType type) {
|
||||||
|
switch (type) {
|
||||||
|
case INT:
|
||||||
|
return WasmType.INT32;
|
||||||
|
case LONG:
|
||||||
|
return WasmType.INT64;
|
||||||
|
case FLOAT:
|
||||||
|
return WasmType.FLOAT32;
|
||||||
|
case DOUBLE:
|
||||||
|
return WasmType.FLOAT64;
|
||||||
|
default:
|
||||||
|
return WasmType.INT32;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -15,40 +15,81 @@
|
||||||
*/
|
*/
|
||||||
package org.teavm.wasm.decompile;
|
package org.teavm.wasm.decompile;
|
||||||
|
|
||||||
|
import com.carrotsearch.hppc.IntObjectMap;
|
||||||
|
import com.carrotsearch.hppc.IntObjectOpenHashMap;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
import org.teavm.common.DominatorTree;
|
import org.teavm.common.DominatorTree;
|
||||||
import org.teavm.common.Graph;
|
import org.teavm.common.Graph;
|
||||||
import org.teavm.common.GraphUtils;
|
import org.teavm.common.GraphUtils;
|
||||||
|
import org.teavm.common.IntegerArray;
|
||||||
import org.teavm.common.Loop;
|
import org.teavm.common.Loop;
|
||||||
import org.teavm.common.LoopGraph;
|
import org.teavm.common.LoopGraph;
|
||||||
|
import org.teavm.model.BasicBlock;
|
||||||
|
import org.teavm.model.Instruction;
|
||||||
|
import org.teavm.model.MethodReference;
|
||||||
import org.teavm.model.Program;
|
import org.teavm.model.Program;
|
||||||
|
import org.teavm.model.instructions.BinaryBranchingInstruction;
|
||||||
|
import org.teavm.model.instructions.BranchingInstruction;
|
||||||
import org.teavm.model.util.ProgramUtils;
|
import org.teavm.model.util.ProgramUtils;
|
||||||
|
import org.teavm.model.util.TypeInferer;
|
||||||
|
import org.teavm.model.util.VariableType;
|
||||||
|
import org.teavm.wasm.model.WasmFunction;
|
||||||
|
import org.teavm.wasm.model.WasmLocal;
|
||||||
|
import org.teavm.wasm.model.WasmType;
|
||||||
import org.teavm.wasm.model.expression.WasmBlock;
|
import org.teavm.wasm.model.expression.WasmBlock;
|
||||||
|
import org.teavm.wasm.model.expression.WasmConditional;
|
||||||
import org.teavm.wasm.model.expression.WasmExpression;
|
import org.teavm.wasm.model.expression.WasmExpression;
|
||||||
|
import org.teavm.wasm.model.expression.WasmIntBinary;
|
||||||
|
import org.teavm.wasm.model.expression.WasmIntBinaryOperation;
|
||||||
|
import org.teavm.wasm.model.expression.WasmIntType;
|
||||||
|
import org.teavm.wasm.model.expression.WasmLocalReference;
|
||||||
|
|
||||||
public class WasmDecompiler {
|
public class WasmDecompiler {
|
||||||
|
private WasmFunction function;
|
||||||
private Program program;
|
private Program program;
|
||||||
private LoopGraph cfg;
|
private LoopGraph cfg;
|
||||||
private DominatorTree dom;
|
private DominatorTree dom;
|
||||||
private Graph domGraph;
|
private Graph domGraph;
|
||||||
private Label[] labels;
|
private Label[] labels;
|
||||||
private WasmExpression[] blockExpressions;
|
private TypeInferer typeInferer;
|
||||||
private Step[] stack;
|
private Step[] stack;
|
||||||
private int stackTop;
|
private int stackTop;
|
||||||
|
|
||||||
public void decompile(Program program) {
|
public void decompile(Program program, MethodReference methodReference, WasmFunction function) {
|
||||||
|
this.function = function;
|
||||||
this.program = program;
|
this.program = program;
|
||||||
prepare();
|
prepare(methodReference);
|
||||||
push(new EnterStep(0));
|
deferEnter(0, function.getBody());
|
||||||
run();
|
run();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void prepare() {
|
private void prepare(MethodReference methodReference) {
|
||||||
cfg = new LoopGraph(ProgramUtils.buildControlFlowGraph(program));
|
cfg = new LoopGraph(ProgramUtils.buildControlFlowGraph(program));
|
||||||
dom = GraphUtils.buildDominatorTree(cfg);
|
dom = GraphUtils.buildDominatorTree(cfg);
|
||||||
domGraph = GraphUtils.buildDominatorGraph(dom, cfg.size());
|
domGraph = GraphUtils.buildDominatorGraph(dom, cfg.size());
|
||||||
labels = new Label[cfg.size()];
|
labels = new Label[cfg.size()];
|
||||||
blockExpressions = new WasmExpression[cfg.size()];
|
|
||||||
stack = new Step[cfg.size() * 4];
|
stack = new Step[cfg.size() * 4];
|
||||||
|
typeInferer = new TypeInferer();
|
||||||
|
typeInferer.inferTypes(program, methodReference);
|
||||||
|
|
||||||
|
int maxLocal = 0;
|
||||||
|
for (int i = 0; i < program.variableCount(); ++i) {
|
||||||
|
maxLocal = Math.max(maxLocal, program.variableAt(i).getRegister());
|
||||||
|
}
|
||||||
|
|
||||||
|
WasmType[] types = new WasmType[maxLocal];
|
||||||
|
for (int i = 0; i < program.variableCount(); ++i) {
|
||||||
|
int register = program.variableAt(i).getRegister();
|
||||||
|
if (types[register] == null) {
|
||||||
|
types[register] = DecompileSupport.mapType(typeInferer.typeOf(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < maxLocal; ++i) {
|
||||||
|
WasmType type = types[i];
|
||||||
|
function.getLocalVariables().add(new WasmLocal(type != null ? type : WasmType.INT32, null));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void run() {
|
private void run() {
|
||||||
|
@ -61,75 +102,129 @@ public class WasmDecompiler {
|
||||||
stack[stackTop++] = step;
|
stack[stackTop++] = step;
|
||||||
}
|
}
|
||||||
|
|
||||||
private class EnterStep implements Step {
|
private void deferEnter(int node, List<WasmExpression> expressions) {
|
||||||
private int index;
|
push(() -> enter(node, expressions));
|
||||||
|
}
|
||||||
|
|
||||||
public EnterStep(int index) {
|
private void enter(int node, List<WasmExpression> expressions) {
|
||||||
this.index = index;
|
Loop loop = cfg.loopAt(node);
|
||||||
|
if (loop != null && loop.getHead() == node) {
|
||||||
|
expressions = enterLoop(loop, expressions);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
DecompilationVisitor decompilationVisitor = new DecompilationVisitor(expressions, context);
|
||||||
public void perform() {
|
compileInstructions(node, decompilationVisitor);
|
||||||
Loop loop = cfg.loopAt(index);
|
|
||||||
if (loop != null && loop.getHead() == index) {
|
int successors = domGraph.outgoingEdgesCount(node);
|
||||||
enterLoop();
|
if (successors == 1) {
|
||||||
} else if (cfg.outgoingEdgesCount(index) == 1) {
|
deferEnter(domGraph.outgoingEdges(node)[0], expressions);
|
||||||
enterOrdinaryBlock();
|
} else if (successors == 0) {
|
||||||
} else {
|
BasicBlock block = program.basicBlockAt(node);
|
||||||
enterBranching();
|
block.getLastInstruction().acceptVisitor(decompilationVisitor);
|
||||||
|
} else {
|
||||||
|
compileFork(node, expressions);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void compileInstructions(int node, DecompilationVisitor decompilationVisitor) {
|
||||||
|
BasicBlock block = program.basicBlockAt(node);
|
||||||
|
int lastInstructionIndex = block.getInstructions().size() - 1;
|
||||||
|
for (int i = 0; i < lastInstructionIndex; ++i) {
|
||||||
|
block.getInstructions().get(i).acceptVisitor(decompilationVisitor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<WasmExpression> enterLoop(Loop loop, List<WasmExpression> expressions) {
|
||||||
|
WasmBlock wasmLoop = new WasmBlock(true);
|
||||||
|
List<WasmExpression> innerExpressions = wasmLoop.getBody();
|
||||||
|
expressions.add(wasmLoop);
|
||||||
|
LoopExitStep exitStep = new LoopExitStep(expressions, wasmLoop);
|
||||||
|
push(exitStep);
|
||||||
|
|
||||||
|
IntObjectMap<Label> newLabels = new IntObjectOpenHashMap<>();
|
||||||
|
int[] exits = findLoopExits(loop);
|
||||||
|
Label breakLabel = exitStep.createBreakLabel();
|
||||||
|
for (int exit : exits) {
|
||||||
|
newLabels.put(exit, breakLabel);
|
||||||
|
}
|
||||||
|
newLabels.put(loop.getHead(), exitStep.createContinueLabel());
|
||||||
|
withLabels(newLabels);
|
||||||
|
|
||||||
|
return innerExpressions;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int[] findLoopExits(Loop loop) {
|
||||||
|
IntegerArray exits = new IntegerArray(2);
|
||||||
|
for (int i = 0; i < cfg.size(); ++i) {
|
||||||
|
Loop nodeLoop = cfg.loopAt(i);
|
||||||
|
if (nodeLoop != null && nodeLoop.isChildOf(loop)) {
|
||||||
|
for (int successor : cfg.outgoingEdges(i)) {
|
||||||
|
Loop successorLoop = cfg.loopAt(successor);
|
||||||
|
if (successorLoop == null || !successorLoop.isChildOf(loop)) {
|
||||||
|
exits.add(i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return exits.getAll();
|
||||||
|
}
|
||||||
|
|
||||||
private void enterLoop() {
|
private void compileFork(int node, List<WasmExpression> expressions) {
|
||||||
|
Instruction instruction = program.basicBlockAt(node).getLastInstruction();
|
||||||
}
|
if (instruction instanceof BranchingInstruction) {
|
||||||
|
compileFork(node, expressions, (BranchingInstruction) instruction);
|
||||||
private void enterOrdinaryBlock() {
|
} else if (instruction instanceof BinaryBranchingInstruction) {
|
||||||
|
compileFork(node, expressions, (BinaryBranchingInstruction) instruction);
|
||||||
}
|
|
||||||
|
|
||||||
private void enterBranching() {
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class LoopContinueLabel implements Label {
|
private void compileFork(int node, List<WasmExpression> expressions, BranchingInstruction instruction) {
|
||||||
private int index;
|
WasmLocal local = function.getLocalVariables().get(instruction.getOperand().getRegister());
|
||||||
private WasmBlock wrapper;
|
WasmExpression operand = new WasmLocalReference(local);
|
||||||
|
VariableType operandType = typeInferer.typeOf(instruction.getOperand().getIndex());
|
||||||
|
WasmExpression condition = DecompileSupport.getCondition(instruction, local, operandType);
|
||||||
|
compileIf(node, expressions, condition, instruction.getConsequent().getIndex(),
|
||||||
|
instruction.getAlternative().getIndex());
|
||||||
|
}
|
||||||
|
|
||||||
public LoopContinueLabel(int index) {
|
private void compileFork(int node, List<WasmExpression> expressions, BinaryBranchingInstruction instruction) {
|
||||||
this.index = index;
|
WasmLocal a = function.getLocalVariables().get(instruction.getFirstOperand().getIndex());
|
||||||
}
|
WasmLocal b = function.getLocalVariables().get(instruction.getSecondOperand().getIndex());
|
||||||
|
WasmExpression condition = DecompileSupport.getCondition(instruction, a, b);
|
||||||
|
compileIf(node, expressions, condition, instruction.getConsequent().getIndex(),
|
||||||
|
instruction.getAlternative().getIndex());
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
private void compileIf(int node, List<WasmExpression> expressions, WasmExpression condition,
|
||||||
public WasmBlock getTarget() {
|
int thenNode, int elseNode) {
|
||||||
if (wrapper == null) {
|
boolean ownsThen = dom.directlyDominates(node, thenNode);
|
||||||
wrapper = new WasmBlock(false);
|
boolean ownsElse = dom.directlyDominates(node, elseNode);
|
||||||
wrapper.getBody().add(blockExpressions[index]);
|
int[] exits = Arrays.stream(domGraph.outgoingEdges(node))
|
||||||
blockExpressions[index] = wrapper;
|
.filter(n -> n != thenNode && n != elseNode)
|
||||||
}
|
.toArray();
|
||||||
return wrapper;
|
|
||||||
|
if (ownsThen && ownsElse) {
|
||||||
|
WasmConditional conditional = new WasmConditional(condition);
|
||||||
|
expressions.add(conditional);
|
||||||
|
compileBranch(conditional.getElseBlock(), elseNode, exits);
|
||||||
|
compileBranch(conditional.getThenBlock(), thenNode, exits);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class BreakLabel implements Label {
|
|
||||||
private WasmBlock target;
|
|
||||||
|
|
||||||
public BreakLabel(WasmBlock target) {
|
private void withLabels(IntObjectMap<Label> labels) {
|
||||||
this.target = target;
|
IntObjectMap<Label> undo = new IntObjectOpenHashMap<>();
|
||||||
}
|
for (int node : labels.keys().toArray()) {
|
||||||
|
undo.put(node, this.labels[node]);
|
||||||
@Override
|
|
||||||
public WasmBlock getTarget() {
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
push(() -> withLabelsImpl(undo));
|
||||||
|
withLabelsImpl(labels);
|
||||||
}
|
}
|
||||||
|
|
||||||
private interface Step {
|
private void withLabelsImpl(IntObjectMap<Label> labels) {
|
||||||
void perform();
|
for (int node : labels.keys().toArray()) {
|
||||||
}
|
this.labels[node] = labels.get(node);
|
||||||
|
}
|
||||||
private interface Label {
|
|
||||||
WasmBlock getTarget();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user