mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 08:14:09 -08:00
wasm: support instructions that were recently implemented in generator
This commit is contained in:
parent
5572d4b5d7
commit
75bead66b3
|
@ -21,12 +21,12 @@ import java.util.List;
|
|||
import org.teavm.backend.wasm.debug.info.ControlFlowInfo;
|
||||
import org.teavm.backend.wasm.debug.info.FunctionControlFlow;
|
||||
import org.teavm.backend.wasm.debug.info.FunctionControlFlowBuilder;
|
||||
import org.teavm.backend.wasm.model.WasmType;
|
||||
import org.teavm.backend.wasm.parser.AddressListener;
|
||||
import org.teavm.backend.wasm.parser.BranchOpcode;
|
||||
import org.teavm.backend.wasm.parser.CodeListener;
|
||||
import org.teavm.backend.wasm.parser.CodeSectionListener;
|
||||
import org.teavm.backend.wasm.parser.Opcode;
|
||||
import org.teavm.backend.wasm.parser.WasmHollowType;
|
||||
|
||||
public class ControlFlowParser implements CodeSectionListener, CodeListener, AddressListener {
|
||||
private int previousAddress;
|
||||
|
@ -60,12 +60,12 @@ public class ControlFlowParser implements CodeSectionListener, CodeListener, Add
|
|||
}
|
||||
|
||||
@Override
|
||||
public int startBlock(boolean loop, WasmType type) {
|
||||
public int startBlock(boolean loop, WasmHollowType type) {
|
||||
return startBlock(loop);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int startConditionalBlock(WasmType type) {
|
||||
public int startConditionalBlock(WasmHollowType type) {
|
||||
return startBlock(false);
|
||||
}
|
||||
|
||||
|
|
|
@ -21,7 +21,6 @@ import java.io.PrintWriter;
|
|||
import java.nio.file.Files;
|
||||
import java.util.function.Consumer;
|
||||
import org.teavm.backend.wasm.model.WasmNumType;
|
||||
import org.teavm.backend.wasm.model.WasmType;
|
||||
import org.teavm.backend.wasm.model.expression.WasmFloatBinaryOperation;
|
||||
import org.teavm.backend.wasm.model.expression.WasmFloatType;
|
||||
import org.teavm.backend.wasm.model.expression.WasmFloatUnaryOperation;
|
||||
|
@ -30,6 +29,7 @@ import org.teavm.backend.wasm.model.expression.WasmInt64Subtype;
|
|||
import org.teavm.backend.wasm.model.expression.WasmIntBinaryOperation;
|
||||
import org.teavm.backend.wasm.model.expression.WasmIntType;
|
||||
import org.teavm.backend.wasm.model.expression.WasmIntUnaryOperation;
|
||||
import org.teavm.backend.wasm.model.expression.WasmSignedType;
|
||||
import org.teavm.backend.wasm.parser.AddressListener;
|
||||
import org.teavm.backend.wasm.parser.BranchOpcode;
|
||||
import org.teavm.backend.wasm.parser.CodeListener;
|
||||
|
@ -38,20 +38,26 @@ import org.teavm.backend.wasm.parser.CodeSectionParser;
|
|||
import org.teavm.backend.wasm.parser.LocalOpcode;
|
||||
import org.teavm.backend.wasm.parser.ModuleParser;
|
||||
import org.teavm.backend.wasm.parser.Opcode;
|
||||
import org.teavm.backend.wasm.parser.WasmHollowType;
|
||||
import org.teavm.common.ByteArrayAsyncInputStream;
|
||||
|
||||
public class DisassemblyCodeSectionListener implements AddressListener, CodeSectionListener, CodeListener {
|
||||
private DisassemblyWriter writer;
|
||||
private int address;
|
||||
private int addressOffset;
|
||||
private int blockIdGen;
|
||||
|
||||
public DisassemblyCodeSectionListener(DisassemblyWriter writer) {
|
||||
this.writer = writer;
|
||||
}
|
||||
|
||||
public void setAddressOffset(int addressOffset) {
|
||||
this.addressOffset = addressOffset;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void address(int address) {
|
||||
this.address = address;
|
||||
this.address = address + addressOffset;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -61,7 +67,7 @@ public class DisassemblyCodeSectionListener implements AddressListener, CodeSect
|
|||
|
||||
@Override
|
||||
public boolean functionStart(int index, int size) {
|
||||
writer.address(address).write("(func $fun_" + index).indent().eol();
|
||||
writer.address(address).write("(func (; " + index + " ;)").indent().eol();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -71,10 +77,10 @@ public class DisassemblyCodeSectionListener implements AddressListener, CodeSect
|
|||
}
|
||||
|
||||
@Override
|
||||
public void local(int start, int count, WasmType type) {
|
||||
public void local(int start, int count, WasmHollowType type) {
|
||||
writer.address(address);
|
||||
for (int i = 0; i < count; ++i) {
|
||||
writer.write("(local $loc_" + (i + start) + " " + typeToString(type) + ")").eol();
|
||||
writer.write("(local (; " + (i + start) + " ;) " + typeToString(type) + ")").eol();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -94,7 +100,7 @@ public class DisassemblyCodeSectionListener implements AddressListener, CodeSect
|
|||
writer.outdent().write(")").eol();
|
||||
}
|
||||
|
||||
private String blockTypeToString(WasmType type) {
|
||||
private String blockTypeToString(WasmHollowType type) {
|
||||
if (type == null) {
|
||||
return "";
|
||||
} else {
|
||||
|
@ -102,10 +108,10 @@ public class DisassemblyCodeSectionListener implements AddressListener, CodeSect
|
|||
}
|
||||
}
|
||||
|
||||
private String typeToString(WasmType type) {
|
||||
private String typeToString(WasmHollowType type) {
|
||||
if (type != null) {
|
||||
if (type instanceof WasmType.Number) {
|
||||
switch (((WasmType.Number) type).number) {
|
||||
if (type instanceof WasmHollowType.Number) {
|
||||
switch (((WasmHollowType.Number) type).number) {
|
||||
case INT32:
|
||||
return "i32";
|
||||
case INT64:
|
||||
|
@ -117,8 +123,23 @@ public class DisassemblyCodeSectionListener implements AddressListener, CodeSect
|
|||
default:
|
||||
break;
|
||||
}
|
||||
} else if (type instanceof WasmType.Reference) {
|
||||
return "ref";
|
||||
} else if (type instanceof WasmHollowType.SpecialReference) {
|
||||
switch (((WasmHollowType.SpecialReference) type).kind) {
|
||||
case ANY:
|
||||
return "any";
|
||||
case FUNC:
|
||||
return "func";
|
||||
case ARRAY:
|
||||
return "array";
|
||||
case EXTERN:
|
||||
return "extern";
|
||||
case STRUCT:
|
||||
return "struct";
|
||||
default:
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
} else if (type instanceof WasmHollowType.CompositeReference) {
|
||||
return String.valueOf(((WasmHollowType.CompositeReference) type).index);
|
||||
}
|
||||
}
|
||||
return "unknown";
|
||||
|
@ -134,7 +155,7 @@ public class DisassemblyCodeSectionListener implements AddressListener, CodeSect
|
|||
}
|
||||
|
||||
@Override
|
||||
public int startBlock(boolean loop, WasmType type) {
|
||||
public int startBlock(boolean loop, WasmHollowType type) {
|
||||
writer.address(address);
|
||||
var label = blockIdGen++;
|
||||
writer.write(loop ? "loop" : "block").write(" $label_" + label).write(blockTypeToString(type))
|
||||
|
@ -143,7 +164,7 @@ public class DisassemblyCodeSectionListener implements AddressListener, CodeSect
|
|||
}
|
||||
|
||||
@Override
|
||||
public int startConditionalBlock(WasmType type) {
|
||||
public int startConditionalBlock(WasmHollowType type) {
|
||||
writer.address(address);
|
||||
var label = blockIdGen++;
|
||||
writer.write("if ").write(" $label_" + label).write(blockTypeToString(type)).indent().eol();
|
||||
|
@ -156,6 +177,20 @@ public class DisassemblyCodeSectionListener implements AddressListener, CodeSect
|
|||
writer.outdent().write("else (; $label_" + token + " ;)").indent().eol();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int startTry(WasmHollowType type) {
|
||||
writer.address(address);
|
||||
var label = blockIdGen++;
|
||||
writer.write("try ").write(" $label_" + label).write(blockTypeToString(type)).indent().eol();
|
||||
return label;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startCatch(int tagIndex) {
|
||||
writer.outdent().address(address);
|
||||
writer.write("catch ").write(String.valueOf(tagIndex)).indent().eol();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endBlock(int token, boolean loop) {
|
||||
writer.address(address).outdent().write("end (; $label_" + token + " ;)").eol();
|
||||
|
@ -185,6 +220,12 @@ public class DisassemblyCodeSectionListener implements AddressListener, CodeSect
|
|||
writer.write(" $label_" + defaultTarget).eol();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void throwInstruction(int tagIndex) {
|
||||
writer.address(address);
|
||||
writer.write("throw ").write(String.valueOf(tagIndex)).eol();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void opcode(Opcode opcode) {
|
||||
writer.address(address);
|
||||
|
@ -201,6 +242,12 @@ public class DisassemblyCodeSectionListener implements AddressListener, CodeSect
|
|||
case DROP:
|
||||
writer.write("drop");
|
||||
break;
|
||||
case REF_EQ:
|
||||
writer.write("ref.eq");
|
||||
break;
|
||||
case ARRAY_LENGTH:
|
||||
writer.write("array.length");
|
||||
break;
|
||||
}
|
||||
writer.eol();
|
||||
}
|
||||
|
@ -216,20 +263,35 @@ public class DisassemblyCodeSectionListener implements AddressListener, CodeSect
|
|||
writer.write("local.set");
|
||||
break;
|
||||
}
|
||||
writer.write(" $loc_" + index).eol();
|
||||
writer.write(" " + index).eol();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getGlobal(int globalIndex) {
|
||||
writer.address(address).write("global.get ").write(Integer.toString(globalIndex)).eol();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setGlobal(int globalIndex) {
|
||||
writer.address(address).write("global.set ").write(Integer.toString(globalIndex)).eol();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void call(int functionIndex) {
|
||||
writer.address(address);
|
||||
writer.write("call $fun_" + functionIndex).eol();
|
||||
writer.write("call " + functionIndex).eol();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void indirectCall(int typeIndex, int tableIndex) {
|
||||
writer.address(address);
|
||||
//TODO: type signature must be printed
|
||||
writer.write("call_indirect $table_" + tableIndex + " $type_" + typeIndex).eol();
|
||||
writer.write("call_indirect " + tableIndex + " " + typeIndex).eol();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void callReference(int typeIndex) {
|
||||
writer.address(address);
|
||||
writer.write("call_ref " + typeIndex).eol();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -429,6 +491,9 @@ public class DisassemblyCodeSectionListener implements AddressListener, CodeSect
|
|||
case CTZ:
|
||||
writer.write("ctz");
|
||||
break;
|
||||
case EQZ:
|
||||
writer.write("eqz");
|
||||
break;
|
||||
case POPCNT:
|
||||
writer.write("popcnt");
|
||||
break;
|
||||
|
@ -758,6 +823,73 @@ public class DisassemblyCodeSectionListener implements AddressListener, CodeSect
|
|||
writer.address(address).write("f64.const " + Double.toHexString(value)).eol();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void nullConstant(WasmHollowType.Reference type) {
|
||||
writer.address(address).write("ref.null ").write(typeToString(type)).eol();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cast(WasmHollowType.Reference type) {
|
||||
writer.address(address).write("ref.cast ").write(typeToString(type)).eol();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void structNew(int typeIndex) {
|
||||
writer.address(address).write("struct.new ").write(Integer.toString(typeIndex)).eol();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void structNewDefault(int typeIndex) {
|
||||
writer.address(address).write("struct.new_default ").write(Integer.toString(typeIndex)).eol();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void structGet(WasmSignedType signedType, int typeIndex, int fieldIndex) {
|
||||
writer.address(address);
|
||||
if (signedType == null) {
|
||||
writer.write("struct.get");
|
||||
} else if (signedType == WasmSignedType.SIGNED) {
|
||||
writer.write("struct.get_s");
|
||||
} else {
|
||||
writer.write("struct.get_u");
|
||||
}
|
||||
writer.write(" ").write(Integer.toString(typeIndex)).write(" ").write(Integer.toString(fieldIndex)).eol();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void structSet(int typeIndex, int fieldIndex) {
|
||||
writer.address(address).write("struct.set ").write(Integer.toString(typeIndex)).write(" ")
|
||||
.write(Integer.toString(fieldIndex)).eol();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void arrayNewDefault(int typeIndex) {
|
||||
writer.address(address).write("array.new_default ").write(Integer.toString(typeIndex)).eol();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void arrayGet(WasmSignedType signedType, int typeIndex) {
|
||||
writer.address(address);
|
||||
if (signedType == null) {
|
||||
writer.write("array.get");
|
||||
} else if (signedType == WasmSignedType.SIGNED) {
|
||||
writer.write("array.get_s");
|
||||
} else {
|
||||
writer.write("array.get_u");
|
||||
}
|
||||
writer.write(" ").write(Integer.toString(typeIndex)).eol();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void arraySet(int typeIndex) {
|
||||
writer.address(address).write("array.set ").write(Integer.toString(typeIndex)).eol();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void functionReference(int functionIndex) {
|
||||
writer.address(address).write("ref.func ").write(Integer.toString(functionIndex)).eol();
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws IOException {
|
||||
var file = new File(args[0]);
|
||||
var bytes = Files.readAllBytes(file.toPath());
|
||||
|
@ -770,6 +902,7 @@ public class DisassemblyCodeSectionListener implements AddressListener, CodeSect
|
|||
var out = new PrintWriter(System.out);
|
||||
var writer = new DisassemblyWriter(out, true);
|
||||
var disassembler = new DisassemblyCodeSectionListener(writer);
|
||||
disassembler.setAddressOffset(pos);
|
||||
var sectionParser = new CodeSectionParser(disassembler, disassembler);
|
||||
sectionParser.parse(bytes);
|
||||
out.flush();
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
package org.teavm.backend.wasm.parser;
|
||||
|
||||
import org.teavm.backend.wasm.model.WasmNumType;
|
||||
import org.teavm.backend.wasm.model.WasmType;
|
||||
import org.teavm.backend.wasm.model.expression.WasmFloatBinaryOperation;
|
||||
import org.teavm.backend.wasm.model.expression.WasmFloatType;
|
||||
import org.teavm.backend.wasm.model.expression.WasmFloatUnaryOperation;
|
||||
|
@ -25,22 +24,30 @@ import org.teavm.backend.wasm.model.expression.WasmInt64Subtype;
|
|||
import org.teavm.backend.wasm.model.expression.WasmIntBinaryOperation;
|
||||
import org.teavm.backend.wasm.model.expression.WasmIntType;
|
||||
import org.teavm.backend.wasm.model.expression.WasmIntUnaryOperation;
|
||||
import org.teavm.backend.wasm.model.expression.WasmSignedType;
|
||||
|
||||
public interface CodeListener {
|
||||
default void error(int depth) {
|
||||
}
|
||||
|
||||
default int startBlock(boolean loop, WasmType type) {
|
||||
default int startBlock(boolean loop, WasmHollowType type) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
default int startConditionalBlock(WasmType type) {
|
||||
default int startConditionalBlock(WasmHollowType type) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
default void startElseSection(int token) {
|
||||
}
|
||||
|
||||
default int startTry(WasmHollowType type) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
default void startCatch(int tagIndex) {
|
||||
}
|
||||
|
||||
default void endBlock(int token, boolean loop) {
|
||||
}
|
||||
|
||||
|
@ -50,6 +57,9 @@ public interface CodeListener {
|
|||
default void tableBranch(int[] depths, int[] targets, int defaultDepth, int defaultTarget) {
|
||||
}
|
||||
|
||||
default void throwInstruction(int tagIndex) {
|
||||
}
|
||||
|
||||
default void opcode(Opcode opcode) {
|
||||
}
|
||||
|
||||
|
@ -121,4 +131,43 @@ public interface CodeListener {
|
|||
|
||||
default void float64Constant(double value) {
|
||||
}
|
||||
|
||||
default void nullConstant(WasmHollowType.Reference type) {
|
||||
}
|
||||
|
||||
default void cast(WasmHollowType.Reference type) {
|
||||
}
|
||||
|
||||
default void structNew(int typeIndex) {
|
||||
}
|
||||
|
||||
default void structNewDefault(int typeIndex) {
|
||||
}
|
||||
|
||||
default void structGet(WasmSignedType signedType, int typeIndex, int fieldIndex) {
|
||||
}
|
||||
|
||||
default void structSet(int typeIndex, int fieldIndex) {
|
||||
}
|
||||
|
||||
default void arrayNewDefault(int typeIndex) {
|
||||
}
|
||||
|
||||
default void arrayGet(WasmSignedType signedType, int typeIndex) {
|
||||
}
|
||||
|
||||
default void arraySet(int typeIndex) {
|
||||
}
|
||||
|
||||
default void getGlobal(int globalIndex) {
|
||||
}
|
||||
|
||||
default void setGlobal(int globalIndex) {
|
||||
}
|
||||
|
||||
default void callReference(int typeIndex) {
|
||||
}
|
||||
|
||||
default void functionReference(int functionIndex) {
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,8 +15,6 @@
|
|||
*/
|
||||
package org.teavm.backend.wasm.parser;
|
||||
|
||||
import org.teavm.backend.wasm.model.WasmType;
|
||||
|
||||
public interface CodeSectionListener {
|
||||
default void sectionStart(int functionCount) {
|
||||
}
|
||||
|
@ -28,7 +26,7 @@ public interface CodeSectionListener {
|
|||
default void localsStart(int count) {
|
||||
}
|
||||
|
||||
default void local(int start, int count, WasmType type) {
|
||||
default void local(int start, int count, WasmHollowType type) {
|
||||
}
|
||||
|
||||
default CodeListener code() {
|
||||
|
|
|
@ -18,7 +18,6 @@ package org.teavm.backend.wasm.parser;
|
|||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.teavm.backend.wasm.model.WasmNumType;
|
||||
import org.teavm.backend.wasm.model.WasmType;
|
||||
import org.teavm.backend.wasm.model.expression.WasmFloatBinaryOperation;
|
||||
import org.teavm.backend.wasm.model.expression.WasmFloatType;
|
||||
import org.teavm.backend.wasm.model.expression.WasmFloatUnaryOperation;
|
||||
|
@ -27,6 +26,7 @@ import org.teavm.backend.wasm.model.expression.WasmInt64Subtype;
|
|||
import org.teavm.backend.wasm.model.expression.WasmIntBinaryOperation;
|
||||
import org.teavm.backend.wasm.model.expression.WasmIntType;
|
||||
import org.teavm.backend.wasm.model.expression.WasmIntUnaryOperation;
|
||||
import org.teavm.backend.wasm.model.expression.WasmSignedType;
|
||||
|
||||
public class CodeSectionParser {
|
||||
private AddressListener addressListener;
|
||||
|
@ -125,6 +125,11 @@ public class CodeSectionParser {
|
|||
return parseBlock(true);
|
||||
case 0x04:
|
||||
return parseConditional();
|
||||
case 0x06:
|
||||
return parseTryCatch();
|
||||
case 0x8:
|
||||
codeListener.throwInstruction(readLEB());
|
||||
break;
|
||||
case 0x0C:
|
||||
parseBranch(BranchOpcode.BR);
|
||||
break;
|
||||
|
@ -143,6 +148,9 @@ public class CodeSectionParser {
|
|||
case 0x11:
|
||||
codeListener.indirectCall(readLEB(), readLEB());
|
||||
break;
|
||||
case 0x14:
|
||||
codeListener.callReference(readLEB());
|
||||
break;
|
||||
|
||||
case 0x1A:
|
||||
codeListener.opcode(Opcode.DROP);
|
||||
|
@ -155,6 +163,13 @@ public class CodeSectionParser {
|
|||
codeListener.local(LocalOpcode.SET, readLEB());
|
||||
break;
|
||||
|
||||
case 0x23:
|
||||
codeListener.getGlobal(readLEB());
|
||||
break;
|
||||
case 0x24:
|
||||
codeListener.setGlobal(readLEB());
|
||||
break;
|
||||
|
||||
case 0x28:
|
||||
codeListener.loadInt32(WasmInt32Subtype.INT32, 1 << readLEB(), readLEB());
|
||||
break;
|
||||
|
@ -617,6 +632,20 @@ public class CodeSectionParser {
|
|||
codeListener.convert(WasmNumType.INT64, WasmNumType.FLOAT64, false, true);
|
||||
break;
|
||||
|
||||
case 0xD0:
|
||||
codeListener.nullConstant(readHeapType());
|
||||
break;
|
||||
|
||||
case 0xD2:
|
||||
codeListener.functionReference(readLEB());
|
||||
break;
|
||||
|
||||
case 0xD3:
|
||||
codeListener.opcode(Opcode.REF_EQ);
|
||||
break;
|
||||
|
||||
case 0xFB:
|
||||
return parseExtExpr2();
|
||||
case 0xFC:
|
||||
return parseExtExpr();
|
||||
|
||||
|
@ -648,6 +677,61 @@ public class CodeSectionParser {
|
|||
}
|
||||
}
|
||||
|
||||
private boolean parseExtExpr2() {
|
||||
switch (readLEB()) {
|
||||
case 0:
|
||||
codeListener.structNew(readLEB());
|
||||
return true;
|
||||
|
||||
case 1:
|
||||
codeListener.structNewDefault(readLEB());
|
||||
return true;
|
||||
|
||||
case 2:
|
||||
codeListener.structGet(null, readLEB(), readLEB());
|
||||
return true;
|
||||
case 3:
|
||||
codeListener.structGet(WasmSignedType.SIGNED, readLEB(), readLEB());
|
||||
return true;
|
||||
case 4:
|
||||
codeListener.structGet(WasmSignedType.UNSIGNED, readLEB(), readLEB());
|
||||
return true;
|
||||
|
||||
case 5:
|
||||
codeListener.structSet(readLEB(), readLEB());
|
||||
return true;
|
||||
|
||||
case 7:
|
||||
codeListener.arrayNewDefault(readLEB());
|
||||
return true;
|
||||
|
||||
case 11:
|
||||
codeListener.arrayGet(null, readLEB());
|
||||
return true;
|
||||
case 12:
|
||||
codeListener.arrayGet(WasmSignedType.SIGNED, readLEB());
|
||||
return true;
|
||||
case 13:
|
||||
codeListener.arrayGet(WasmSignedType.UNSIGNED, readLEB());
|
||||
return true;
|
||||
|
||||
case 14:
|
||||
codeListener.arraySet(readLEB());
|
||||
return true;
|
||||
|
||||
case 15:
|
||||
codeListener.opcode(Opcode.ARRAY_LENGTH);
|
||||
return true;
|
||||
|
||||
case 23:
|
||||
codeListener.cast(readHeapType());
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean parseBlock(boolean isLoop) {
|
||||
var type = readType();
|
||||
var token = codeListener.startBlock(isLoop, type);
|
||||
|
@ -693,6 +777,35 @@ public class CodeSectionParser {
|
|||
return true;
|
||||
}
|
||||
|
||||
private boolean parseTryCatch() {
|
||||
var type = readType();
|
||||
var token = codeListener.startTry(type);
|
||||
blockStack.add(new Block(token));
|
||||
loop: while (true) {
|
||||
switch (data[ptr]) {
|
||||
case 0x0B:
|
||||
break loop;
|
||||
case 0x07: {
|
||||
reportAddress();
|
||||
var tagIndex = readLEB();
|
||||
++ptr;
|
||||
codeListener.startCatch(tagIndex);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
if (!parseExpr()) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
blockStack.remove(blockStack.size() - 1);
|
||||
reportAddress();
|
||||
codeListener.endBlock(token, false);
|
||||
++ptr;
|
||||
return true;
|
||||
}
|
||||
|
||||
private void parseBranch(BranchOpcode opcode) {
|
||||
var depth = readLEB();
|
||||
var target = blockStack.get(blockStack.size() - depth - 1);
|
||||
|
@ -713,19 +826,50 @@ public class CodeSectionParser {
|
|||
codeListener.tableBranch(depths, targets, defaultDepth, defaultTarget);
|
||||
}
|
||||
|
||||
private WasmType readType() {
|
||||
private WasmHollowType readType() {
|
||||
var typeId = data[ptr++];
|
||||
switch (typeId) {
|
||||
case 0x7F:
|
||||
return WasmType.INT32;
|
||||
return WasmHollowType.INT32;
|
||||
case 0x7E:
|
||||
return WasmType.INT64;
|
||||
return WasmHollowType.INT64;
|
||||
case 0x7D:
|
||||
return WasmType.FLOAT32;
|
||||
return WasmHollowType.FLOAT32;
|
||||
case 0x7C:
|
||||
return WasmType.FLOAT64;
|
||||
default:
|
||||
return WasmHollowType.FLOAT64;
|
||||
case 0x63:
|
||||
return readHeapType();
|
||||
case 0x40:
|
||||
return null;
|
||||
default:
|
||||
return readAbsHeapType(typeId);
|
||||
}
|
||||
}
|
||||
|
||||
private WasmHollowType.Reference readHeapType() {
|
||||
var typeId = data[ptr];
|
||||
if ((typeId & 0xC0) == 0x40) {
|
||||
var result = readAbsHeapType(typeId);
|
||||
++ptr;
|
||||
return result;
|
||||
}
|
||||
return new WasmHollowType.CompositeReference(readLEB());
|
||||
}
|
||||
|
||||
private WasmHollowType.SpecialReference readAbsHeapType(int typeId) {
|
||||
switch (typeId) {
|
||||
case 0x70:
|
||||
return WasmHollowType.Reference.FUNC;
|
||||
case 0x6F:
|
||||
return WasmHollowType.Reference.EXTERN;
|
||||
case 0x6E:
|
||||
return WasmHollowType.Reference.ANY;
|
||||
case 0x6B:
|
||||
return WasmHollowType.Reference.STRUCT;
|
||||
case 0x6A:
|
||||
return WasmHollowType.Reference.ARRAY;
|
||||
default:
|
||||
throw new ParseException("Unknown type", ptr);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -19,5 +19,7 @@ public enum Opcode {
|
|||
UNREACHABLE,
|
||||
NOP,
|
||||
RETURN,
|
||||
DROP
|
||||
DROP,
|
||||
REF_EQ,
|
||||
ARRAY_LENGTH
|
||||
}
|
||||
|
|
|
@ -0,0 +1,98 @@
|
|||
/*
|
||||
* Copyright 2024 konsoletyper.
|
||||
*
|
||||
* 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.backend.wasm.parser;
|
||||
|
||||
import java.util.Objects;
|
||||
import org.teavm.backend.wasm.model.WasmNumType;
|
||||
import org.teavm.backend.wasm.model.WasmStorageType;
|
||||
import org.teavm.backend.wasm.model.WasmType;
|
||||
|
||||
public class WasmHollowType {
|
||||
public static final Number INT32 = new Number(WasmNumType.INT32);
|
||||
public static final Number INT64 = new Number(WasmNumType.INT64);
|
||||
public static final Number FLOAT32 = new Number(WasmNumType.FLOAT32);
|
||||
public static final Number FLOAT64 = new Number(WasmNumType.FLOAT64);
|
||||
|
||||
private WasmStorageType.Regular storageType;
|
||||
|
||||
private WasmHollowType() {
|
||||
}
|
||||
|
||||
public static Number num(WasmNumType number) {
|
||||
switch (number) {
|
||||
case INT32:
|
||||
return INT32;
|
||||
case INT64:
|
||||
return INT64;
|
||||
case FLOAT32:
|
||||
return FLOAT32;
|
||||
case FLOAT64:
|
||||
return FLOAT64;
|
||||
default:
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
}
|
||||
|
||||
public static final class Number extends WasmHollowType {
|
||||
public final WasmNumType number;
|
||||
|
||||
private Number(WasmNumType number) {
|
||||
this.number = number;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static abstract class Reference extends WasmHollowType {
|
||||
public static final SpecialReference FUNC = new SpecialReference(WasmType.SpecialReferenceKind.FUNC);
|
||||
public static final SpecialReference ANY = new SpecialReference(WasmType.SpecialReferenceKind.ANY);
|
||||
public static final SpecialReference EXTERN = new SpecialReference(WasmType.SpecialReferenceKind.EXTERN);
|
||||
public static final SpecialReference STRUCT = new SpecialReference(WasmType.SpecialReferenceKind.STRUCT);
|
||||
public static final SpecialReference ARRAY = new SpecialReference(WasmType.SpecialReferenceKind.ARRAY);
|
||||
}
|
||||
|
||||
public static final class CompositeReference extends WasmHollowType.Reference {
|
||||
public final int index;
|
||||
|
||||
public CompositeReference(int index) {
|
||||
this.index = index;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (!(o instanceof CompositeReference)) {
|
||||
return false;
|
||||
}
|
||||
CompositeReference that = (CompositeReference) o;
|
||||
return index == that.index;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hashCode(index);
|
||||
}
|
||||
}
|
||||
|
||||
public static final class SpecialReference extends WasmHollowType.Reference {
|
||||
public final WasmType.SpecialReferenceKind kind;
|
||||
|
||||
SpecialReference(WasmType.SpecialReferenceKind kind) {
|
||||
this.kind = kind;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user