diff --git a/core/src/main/java/org/teavm/backend/wasm/render/WasmBinaryRenderer.java b/core/src/main/java/org/teavm/backend/wasm/render/WasmBinaryRenderer.java index ebc356848..317dd5731 100644 --- a/core/src/main/java/org/teavm/backend/wasm/render/WasmBinaryRenderer.java +++ b/core/src/main/java/org/teavm/backend/wasm/render/WasmBinaryRenderer.java @@ -63,6 +63,9 @@ public class WasmBinaryRenderer { case V_0xC: output.writeInt32(0xC); break; + case V_0xD: + output.writeInt32(0xD); + break; } renderSignatures(module); @@ -91,14 +94,14 @@ public class WasmBinaryRenderer { section.writeLEB(signatures.size()); for (WasmSignature signature : signatures) { - section.writeByte(0x40); + section.writeByte(version == WasmBinaryVersion.V_0xD ? 0x60 : 0x40); section.writeLEB(signature.types.length - 1); for (int i = 1; i < signature.types.length; ++i) { - section.writeType(signature.types[i]); + section.writeType(signature.types[i], version); } if (signature.types[0] != null) { section.writeByte(1); - section.writeType(signature.types[0]); + section.writeType(signature.types[0], version); } else { section.writeByte(0); } @@ -143,7 +146,7 @@ public class WasmBinaryRenderer { section.writeAsciiString(function.getImportName()); - if (version == WasmBinaryVersion.V_0xC) { + if (version != WasmBinaryVersion.V_0xB) { section.writeByte(EXTERNAL_KIND_FUNCTION); section.writeLEB(signatureIndex); } @@ -185,7 +188,11 @@ public class WasmBinaryRenderer { } } else { section.writeByte(1); - section.writeByte(0x20); + if (version == WasmBinaryVersion.V_0xD) { + section.writeByte(0x70); + } else { + section.writeByte(0x20); + } section.writeByte(0); section.writeLEB(functionIndexes.size()); } @@ -195,7 +202,7 @@ public class WasmBinaryRenderer { private void renderMemory(WasmModule module) { WasmBinaryWriter section = new WasmBinaryWriter(); - if (version == WasmBinaryVersion.V_0xC) { + if (version != WasmBinaryVersion.V_0xB) { section.writeByte(1); section.writeByte(1); } @@ -227,7 +234,7 @@ public class WasmBinaryRenderer { section.writeAsciiString(function.getExportName()); - if (version == WasmBinaryVersion.V_0xC) { + if (version != WasmBinaryVersion.V_0xB) { section.writeByte(EXTERNAL_KIND_FUNCTION); section.writeLEB(functionIndex); } @@ -248,7 +255,7 @@ public class WasmBinaryRenderer { } private void renderElement(WasmModule module) { - if (module.getFunctionTable().isEmpty() || version != WasmBinaryVersion.V_0xC) { + if (module.getFunctionTable().isEmpty() || version == WasmBinaryVersion.V_0xB) { return; } @@ -256,9 +263,7 @@ public class WasmBinaryRenderer { section.writeLEB(1); section.writeLEB(0); - section.writeByte(0x10); - section.writeLEB(0); - section.writeByte(0x0F); + renderInitializer(section, 0); section.writeLEB(module.getFunctionTable().size()); for (WasmFunction function : module.getFunctionTable()) { @@ -309,12 +314,12 @@ public class WasmBinaryRenderer { code.writeLEB(localEntries.size()); for (LocalEntry entry : localEntries) { code.writeLEB(entry.count); - code.writeType(entry.type); + code.writeType(entry.type, version); } } Map importIndexes = this.importIndexes; - if (version == WasmBinaryVersion.V_0xC) { + if (version != WasmBinaryVersion.V_0xB) { importIndexes = this.functionIndexes; } WasmBinaryRenderingVisitor visitor = new WasmBinaryRenderingVisitor(code, version, functionIndexes, @@ -324,11 +329,25 @@ public class WasmBinaryRenderer { } if (version == WasmBinaryVersion.V_0xC) { code.writeByte(0x0F); + } else if (version == WasmBinaryVersion.V_0xD) { + code.writeByte(0x0B); } return code.getData(); } + private void renderInitializer(WasmBinaryWriter output, int value) { + if (version == WasmBinaryVersion.V_0xC) { + output.writeByte(0x10); + output.writeLEB(value); + output.writeByte(0x0F); + } else { + output.writeByte(0x41); + output.writeLEB(value); + output.writeByte(0x0B); + } + } + private void renderData(WasmModule module) { if (module.getSegments().isEmpty()) { return; @@ -342,9 +361,7 @@ public class WasmBinaryRenderer { section.writeLEB(segment.getOffset()); } else { section.writeByte(0); - section.writeByte(0x10); - section.writeLEB(segment.getOffset()); - section.writeByte(0xF); + renderInitializer(section, segment.getOffset()); } section.writeLEB(segment.getLength()); @@ -393,7 +410,7 @@ public class WasmBinaryRenderer { } private void writeSection(int id, String name, byte[] data) { - if (version == WasmBinaryVersion.V_0xC) { + if (version != WasmBinaryVersion.V_0xB) { output.writeByte(id); int length = data.length; if (id == 0) { diff --git a/core/src/main/java/org/teavm/backend/wasm/render/WasmBinaryRenderingVisitor.java b/core/src/main/java/org/teavm/backend/wasm/render/WasmBinaryRenderingVisitor.java index 6b1aee78e..c8cb5c3db 100644 --- a/core/src/main/java/org/teavm/backend/wasm/render/WasmBinaryRenderingVisitor.java +++ b/core/src/main/java/org/teavm/backend/wasm/render/WasmBinaryRenderingVisitor.java @@ -70,22 +70,26 @@ class WasmBinaryRenderingVisitor implements WasmExpressionVisitor { @Override public void visit(WasmBlock expression) { - int blockDepth = expression.isLoop() & version == WasmBinaryVersion.V_0xB ? 2 : 1; + int blockDepth = expression.isLoop() && version == WasmBinaryVersion.V_0xB ? 2 : 1; depth += blockDepth; blockDepths.put(expression, depth); - writer.writeByte(expression.isLoop() ? 0x02 : 0x01); + if (version == WasmBinaryVersion.V_0xD) { + writer.writeByte(expression.isLoop() ? 0x03 : 0x02); + } else { + writer.writeByte(expression.isLoop() ? 0x02 : 0x01); + } writeBlockType(expression.getType()); for (WasmExpression part : expression.getBody()) { part.acceptVisitor(this); } - writer.writeByte(0x0F); + writer.writeByte(version == WasmBinaryVersion.V_0xD ? 0x0B : 0x0F); blockDepths.remove(expression); depth -= blockDepth; } private void writeBlockType(WasmType type) { - if (version == WasmBinaryVersion.V_0xC) { - writer.writeType(type); + if (version != WasmBinaryVersion.V_0xB) { + writer.writeType(type, version); } } @@ -95,7 +99,9 @@ class WasmBinaryRenderingVisitor implements WasmExpressionVisitor { expression.getResult().acceptVisitor(this); } expression.getCondition().acceptVisitor(this); - writer.writeByte(0x07); + + writer.writeByte(version == WasmBinaryVersion.V_0xD ? 0x0D : 0x07); + if (version == WasmBinaryVersion.V_0xB) { writer.writeByte(expression.getResult() != null ? 1 : 0); } @@ -107,7 +113,9 @@ class WasmBinaryRenderingVisitor implements WasmExpressionVisitor { if (expression.getResult() != null) { expression.getResult().acceptVisitor(this); } - writer.writeByte(0x06); + + writer.writeByte(version == WasmBinaryVersion.V_0xD ? 0x0C : 0x06); + if (version == WasmBinaryVersion.V_0xB) { writer.writeByte(expression.getResult() != null ? 1 : 0); } @@ -117,23 +125,27 @@ class WasmBinaryRenderingVisitor implements WasmExpressionVisitor { @Override public void visit(WasmSwitch expression) { expression.getSelector().acceptVisitor(this); - writer.writeByte(0x08); + + writer.writeByte(version == WasmBinaryVersion.V_0xD ? 0x0E : 0x08); + if (version == WasmBinaryVersion.V_0xB) { writer.writeByte(0); } + writer.writeLEB(expression.getTargets().size()); for (WasmBlock target : expression.getTargets()) { int targetDepth = blockDepths.get(target); int relativeDepth = depth - targetDepth; - if (version == WasmBinaryVersion.V_0xC) { + if (version != WasmBinaryVersion.V_0xB) { writer.writeLEB(relativeDepth); } else { writer.writeFixed(relativeDepth); } } + int defaultDepth = blockDepths.get(expression.getDefaultTarget()); int relativeDepth = depth - defaultDepth; - if (version == WasmBinaryVersion.V_0xC) { + if (version != WasmBinaryVersion.V_0xB) { writer.writeLEB(relativeDepth); } else { writer.writeFixed(relativeDepth); @@ -143,7 +155,7 @@ class WasmBinaryRenderingVisitor implements WasmExpressionVisitor { @Override public void visit(WasmConditional expression) { expression.getCondition().acceptVisitor(this); - writer.writeByte(0x03); + writer.writeByte(version == WasmBinaryVersion.V_0xD ? 0x04 : 0x03); writeBlockType(expression.getType()); ++depth; @@ -154,7 +166,7 @@ class WasmBinaryRenderingVisitor implements WasmExpressionVisitor { blockDepths.remove(expression.getThenBlock()); if (!expression.getElseBlock().getBody().isEmpty()) { - writer.writeByte(0x04); + writer.writeByte(version == WasmBinaryVersion.V_0xD ? 0x05 : 0x04); blockDepths.put(expression.getElseBlock(), depth); for (WasmExpression part : expression.getElseBlock().getBody()) { part.acceptVisitor(this); @@ -163,7 +175,7 @@ class WasmBinaryRenderingVisitor implements WasmExpressionVisitor { } --depth; - writer.writeByte(0x0F); + writer.writeByte(version == WasmBinaryVersion.V_0xD ? 0x0B : 0x0F); } @Override @@ -171,7 +183,7 @@ class WasmBinaryRenderingVisitor implements WasmExpressionVisitor { if (expression.getValue() != null) { expression.getValue().acceptVisitor(this); } - writer.writeByte(0x09); + writer.writeByte(version == WasmBinaryVersion.V_0xD ? 0x0F : 0x09); if (version == WasmBinaryVersion.V_0xB) { writer.writeByte(expression.getValue() != null ? 1 : 0); } @@ -188,38 +200,38 @@ class WasmBinaryRenderingVisitor implements WasmExpressionVisitor { @Override public void visit(WasmInt32Constant expression) { - writer.writeByte(0x10); + writer.writeByte(version == WasmBinaryVersion.V_0xD ? 0x41 : 0x10); writer.writeSignedLEB(expression.getValue()); } @Override public void visit(WasmInt64Constant expression) { - writer.writeByte(0x11); + writer.writeByte(version == WasmBinaryVersion.V_0xD ? 0x42 : 0x11); writer.writeSignedLEB(expression.getValue()); } @Override public void visit(WasmFloat32Constant expression) { - writer.writeByte(0x13); + writer.writeByte(version == WasmBinaryVersion.V_0xD ? 0x43 : 0x13); writer.writeFixed(Float.floatToRawIntBits(expression.getValue())); } @Override public void visit(WasmFloat64Constant expression) { - writer.writeByte(0x12); + writer.writeByte(version == WasmBinaryVersion.V_0xD ? 0x44 : 0x12); writer.writeFixed(Double.doubleToRawLongBits(expression.getValue())); } @Override public void visit(WasmGetLocal expression) { - writer.writeByte(0x14); + writer.writeByte(version == WasmBinaryVersion.V_0xD ? 0x20 : 0x14); writer.writeLEB(expression.getLocal().getIndex()); } @Override public void visit(WasmSetLocal expression) { expression.getValue().acceptVisitor(this); - writer.writeByte(0x15); + writer.writeByte(version == WasmBinaryVersion.V_0xD ? 0x21 : 0x15); writer.writeLEB(expression.getLocal().getIndex()); } @@ -227,6 +239,177 @@ class WasmBinaryRenderingVisitor implements WasmExpressionVisitor { public void visit(WasmIntBinary expression) { expression.getFirst().acceptVisitor(this); expression.getSecond().acceptVisitor(this); + if (version == WasmBinaryVersion.V_0xD) { + render0xD(expression); + } else { + renderOld(expression); + } + } + + private void render0xD(WasmIntBinary expression) { + switch (expression.getType()) { + case INT32: + switch (expression.getOperation()) { + case ADD: + writer.writeByte(0x6A); + break; + case SUB: + writer.writeByte(0x6B); + break; + case MUL: + writer.writeByte(0x6C); + break; + case DIV_SIGNED: + writer.writeByte(0x6D); + break; + case DIV_UNSIGNED: + writer.writeByte(0x6E); + break; + case REM_SIGNED: + writer.writeByte(0x6F); + break; + case REM_UNSIGNED: + writer.writeByte(0x70); + break; + case AND: + writer.writeByte(0x71); + break; + case OR: + writer.writeByte(0x72); + break; + case XOR: + writer.writeByte(0x73); + break; + case SHL: + writer.writeByte(0x74); + break; + case SHR_UNSIGNED: + writer.writeByte(0x75); + break; + case SHR_SIGNED: + writer.writeByte(0x76); + break; + case ROTR: + writer.writeByte(0x77); + break; + case ROTL: + writer.writeByte(0x78); + break; + case EQ: + writer.writeByte(0x46); + break; + case NE: + writer.writeByte(0x47); + break; + case LT_SIGNED: + writer.writeByte(0x48); + break; + case LT_UNSIGNED: + writer.writeByte(0x49); + break; + case GT_SIGNED: + writer.writeByte(0x4A); + break; + case GT_UNSIGNED: + writer.writeByte(0x4B); + break; + case LE_SIGNED: + writer.writeByte(0x4C); + break; + case LE_UNSIGNED: + writer.writeByte(0x4D); + break; + case GE_SIGNED: + writer.writeByte(0x4E); + break; + case GE_UNSIGNED: + writer.writeByte(0x4F); + break; + } + break; + case INT64: + switch (expression.getOperation()) { + case ADD: + writer.writeByte(0x7C); + break; + case SUB: + writer.writeByte(0x7D); + break; + case MUL: + writer.writeByte(0x7E); + break; + case DIV_SIGNED: + writer.writeByte(0x7F); + break; + case DIV_UNSIGNED: + writer.writeByte(0x80); + break; + case REM_SIGNED: + writer.writeByte(0x81); + break; + case REM_UNSIGNED: + writer.writeByte(0x82); + break; + case AND: + writer.writeByte(0x83); + break; + case OR: + writer.writeByte(0x84); + break; + case XOR: + writer.writeByte(0x85); + break; + case SHL: + writer.writeByte(0x86); + break; + case SHR_UNSIGNED: + writer.writeByte(0x87); + break; + case SHR_SIGNED: + writer.writeByte(0x88); + break; + case ROTR: + writer.writeByte(0x89); + break; + case ROTL: + writer.writeByte(0x8A); + break; + case EQ: + writer.writeByte(0x51); + break; + case NE: + writer.writeByte(0x52); + break; + case LT_SIGNED: + writer.writeByte(0x53); + break; + case LT_UNSIGNED: + writer.writeByte(0x54); + break; + case GT_SIGNED: + writer.writeByte(0x55); + break; + case GT_UNSIGNED: + writer.writeByte(0x56); + break; + case LE_SIGNED: + writer.writeByte(0x57); + break; + case LE_UNSIGNED: + writer.writeByte(0x58); + break; + case GE_SIGNED: + writer.writeByte(0x59); + break; + case GE_UNSIGNED: + writer.writeByte(0x5A); + break; + } + break; + } + } + + private void renderOld(WasmIntBinary expression) { switch (expression.getType()) { case INT32: switch (expression.getOperation()) { @@ -393,6 +576,99 @@ class WasmBinaryRenderingVisitor implements WasmExpressionVisitor { public void visit(WasmFloatBinary expression) { expression.getFirst().acceptVisitor(this); expression.getSecond().acceptVisitor(this); + if (version == WasmBinaryVersion.V_0xD) { + render0xD(expression); + } else { + renderOld(expression); + } + } + + private void render0xD(WasmFloatBinary expression) { + switch (expression.getType()) { + case FLOAT32: + switch (expression.getOperation()) { + case ADD: + writer.writeByte(0x92); + break; + case SUB: + writer.writeByte(0x93); + break; + case MUL: + writer.writeByte(0x94); + break; + case DIV: + writer.writeByte(0x95); + break; + case MIN: + writer.writeByte(0x96); + break; + case MAX: + writer.writeByte(0x97); + break; + case EQ: + writer.writeByte(0x5B); + break; + case NE: + writer.writeByte(0x5C); + break; + case LT: + writer.writeByte(0x5D); + break; + case GT: + writer.writeByte(0x5E); + break; + case LE: + writer.writeByte(0x5F); + break; + case GE: + writer.writeByte(0x60); + break; + } + break; + case FLOAT64: + switch (expression.getOperation()) { + case ADD: + writer.writeByte(0xA0); + break; + case SUB: + writer.writeByte(0xA1); + break; + case MUL: + writer.writeByte(0xA2); + break; + case DIV: + writer.writeByte(0xA3); + break; + case MIN: + writer.writeByte(0xA4); + break; + case MAX: + writer.writeByte(0xA5); + break; + case EQ: + writer.writeByte(0x61); + break; + case NE: + writer.writeByte(0x62); + break; + case LT: + writer.writeByte(0x63); + break; + case GT: + writer.writeByte(0x64); + break; + case LE: + writer.writeByte(0x65); + break; + case GE: + writer.writeByte(0x66); + break; + } + break; + } + } + + private void renderOld(WasmFloatBinary expression) { switch (expression.getType()) { case FLOAT32: switch (expression.getOperation()) { @@ -480,39 +756,139 @@ class WasmBinaryRenderingVisitor implements WasmExpressionVisitor { @Override public void visit(WasmIntUnary expression) { expression.getOperand().acceptVisitor(this); - switch (expression.getType()) { - case INT32: - switch (expression.getOperation()) { - case CLZ: - writer.writeByte(0x57); - break; - case CTZ: - writer.writeByte(0x58); - break; - case POPCNT: - writer.writeByte(0x59); - break; - } - break; - case INT64: - switch (expression.getOperation()) { - case CLZ: - writer.writeByte(0x72); - break; - case CTZ: - writer.writeByte(0x73); - break; - case POPCNT: - writer.writeByte(0x74); - break; - } - break; + if (version == WasmBinaryVersion.V_0xD) { + switch (expression.getType()) { + case INT32: + switch (expression.getOperation()) { + case CLZ: + writer.writeByte(0x67); + break; + case CTZ: + writer.writeByte(0x68); + break; + case POPCNT: + writer.writeByte(0x69); + break; + } + break; + case INT64: + switch (expression.getOperation()) { + case CLZ: + writer.writeByte(0x79); + break; + case CTZ: + writer.writeByte(0x7A); + break; + case POPCNT: + writer.writeByte(0x7B); + break; + } + break; + } + } else { + switch (expression.getType()) { + case INT32: + switch (expression.getOperation()) { + case CLZ: + writer.writeByte(0x57); + break; + case CTZ: + writer.writeByte(0x58); + break; + case POPCNT: + writer.writeByte(0x59); + break; + } + break; + case INT64: + switch (expression.getOperation()) { + case CLZ: + writer.writeByte(0x72); + break; + case CTZ: + writer.writeByte(0x73); + break; + case POPCNT: + writer.writeByte(0x74); + break; + } + break; + } } } @Override public void visit(WasmFloatUnary expression) { expression.getOperand().acceptVisitor(this); + if (version == WasmBinaryVersion.V_0xD) { + render0xD(expression); + } else { + renderOld(expression); + } + } + + private void render0xD(WasmFloatUnary expression) { + switch (expression.getType()) { + case FLOAT32: + switch (expression.getOperation()) { + case ABS: + writer.writeByte(0x8B); + break; + case NEG: + writer.writeByte(0x8C); + break; + case CEIL: + writer.writeByte(0x8D); + break; + case FLOOR: + writer.writeByte(0x8E); + break; + case TRUNC: + writer.writeByte(0x8F); + break; + case NEAREST: + writer.writeByte(0x90); + break; + case SQRT: + writer.writeByte(0x91); + break; + case COPYSIGN: + writer.writeByte(0x98); + break; + } + break; + case FLOAT64: + switch (expression.getOperation()) { + case ABS: + writer.writeByte(0x99); + break; + case NEG: + writer.writeByte(0x9A); + break; + case CEIL: + writer.writeByte(0x9B); + break; + case FLOOR: + writer.writeByte(0x9C); + break; + case TRUNC: + writer.writeByte(0x9D); + break; + case NEAREST: + writer.writeByte(0x9E); + break; + case SQRT: + writer.writeByte(0x9F); + break; + case COPYSIGN: + writer.writeByte(0xA6); + break; + } + break; + } + } + + private void renderOld(WasmFloatUnary expression) { switch (expression.getType()) { case FLOAT32: switch (expression.getOperation()) { @@ -576,7 +952,79 @@ class WasmBinaryRenderingVisitor implements WasmExpressionVisitor { @Override public void visit(WasmConversion expression) { expression.getOperand().acceptVisitor(this); + if (version == WasmBinaryVersion.V_0xD) { + render0xD(expression); + } else { + renderOld(expression); + } + } + private void render0xD(WasmConversion expression) { + switch (expression.getSourceType()) { + case INT32: + switch (expression.getTargetType()) { + case INT32: + break; + case INT64: + writer.writeByte(expression.isSigned() ? 0xAC : 0xAD); + break; + case FLOAT32: + writer.writeByte(expression.isSigned() ? 0xB2 : 0xB3); + break; + case FLOAT64: + writer.writeByte(expression.isSigned() ? 0xB7 : 0xB8); + break; + } + break; + case INT64: + switch (expression.getTargetType()) { + case INT32: + writer.writeByte(0xA7); + break; + case INT64: + break; + case FLOAT32: + writer.writeByte(expression.isSigned() ? 0xB4 : 0xB5); + break; + case FLOAT64: + writer.writeByte(expression.isSigned() ? 0xB9 : 0xBA); + break; + } + break; + case FLOAT32: + switch (expression.getTargetType()) { + case INT32: + writer.writeByte(expression.isSigned() ? 0xA8 : 0xA9); + break; + case INT64: + writer.writeByte(expression.isSigned() ? 0xAE : 0xAF); + break; + case FLOAT32: + break; + case FLOAT64: + writer.writeByte(0xBB); + break; + } + break; + case FLOAT64: + switch (expression.getTargetType()) { + case INT32: + writer.writeByte(expression.isSigned() ? 0xAA : 0xAB); + break; + case INT64: + writer.writeByte(expression.isSigned() ? 0xB0 : 0xB1); + break; + case FLOAT32: + writer.writeByte(0xB6); + break; + case FLOAT64: + break; + } + break; + } + } + + private void renderOld(WasmConversion expression) { switch (expression.getSourceType()) { case INT32: switch (expression.getTargetType()) { @@ -658,7 +1106,7 @@ class WasmBinaryRenderingVisitor implements WasmExpressionVisitor { writer.writeByte(!expression.isImported() ? 0x16 : 0x18); writer.writeLEB(expression.getArguments().size()); } else { - writer.writeByte(0x16); + writer.writeByte(version == WasmBinaryVersion.V_0xD ? 0x10 : 0x16); } writer.writeLEB(functionIndex); } @@ -671,10 +1119,10 @@ class WasmBinaryRenderingVisitor implements WasmExpressionVisitor { for (WasmExpression argument : expression.getArguments()) { argument.acceptVisitor(this); } - if (version == WasmBinaryVersion.V_0xC) { + if (version != WasmBinaryVersion.V_0xB) { expression.getSelector().acceptVisitor(this); } - writer.writeByte(0x17); + writer.writeByte(version == WasmBinaryVersion.V_0xD ? 0x11 : 0x17); if (version == WasmBinaryVersion.V_0xB) { writer.writeLEB(expression.getArguments().size()); } @@ -685,6 +1133,10 @@ class WasmBinaryRenderingVisitor implements WasmExpressionVisitor { signatureTypes[i + 1] = expression.getParameterTypes().get(i); } writer.writeLEB(signatureIndexes.get(new WasmSignature(signatureTypes))); + + if (version == WasmBinaryVersion.V_0xD) { + writer.writeByte(0); + } } @Override @@ -692,28 +1144,50 @@ class WasmBinaryRenderingVisitor implements WasmExpressionVisitor { expression.getOperand().acceptVisitor(this); if (version == WasmBinaryVersion.V_0xC) { writer.writeByte(0x0B); + } else if (version == WasmBinaryVersion.V_0xD) { + writer.writeByte(0x1A); } } @Override public void visit(WasmLoadInt32 expression) { expression.getIndex().acceptVisitor(this); - switch (expression.getConvertFrom()) { - case INT8: - writer.writeByte(0x20); - break; - case UINT8: - writer.writeByte(0x21); - break; - case INT16: - writer.writeByte(0x22); - break; - case UINT16: - writer.writeByte(0x23); - break; - case INT32: - writer.writeByte(0x2A); - break; + if (version == WasmBinaryVersion.V_0xD) { + switch (expression.getConvertFrom()) { + case INT8: + writer.writeByte(0x2C); + break; + case UINT8: + writer.writeByte(0x2D); + break; + case INT16: + writer.writeByte(0x2E); + break; + case UINT16: + writer.writeByte(0x2F); + break; + case INT32: + writer.writeByte(0x28); + break; + } + } else { + switch (expression.getConvertFrom()) { + case INT8: + writer.writeByte(0x20); + break; + case UINT8: + writer.writeByte(0x21); + break; + case INT16: + writer.writeByte(0x22); + break; + case UINT16: + writer.writeByte(0x23); + break; + case INT32: + writer.writeByte(0x2A); + break; + } } writer.writeByte(alignment(expression.getAlignment())); writer.writeLEB(expression.getOffset()); @@ -722,28 +1196,54 @@ class WasmBinaryRenderingVisitor implements WasmExpressionVisitor { @Override public void visit(WasmLoadInt64 expression) { expression.getIndex().acceptVisitor(this); - switch (expression.getConvertFrom()) { - case INT8: - writer.writeByte(0x24); - break; - case UINT8: - writer.writeByte(0x25); - break; - case INT16: - writer.writeByte(0x26); - break; - case UINT16: - writer.writeByte(0x27); - break; - case INT32: - writer.writeByte(0x28); - break; - case UINT32: - writer.writeByte(0x29); - break; - case INT64: - writer.writeByte(0x2B); - break; + if (version == WasmBinaryVersion.V_0xD) { + switch (expression.getConvertFrom()) { + case INT8: + writer.writeByte(0x30); + break; + case UINT8: + writer.writeByte(0x31); + break; + case INT16: + writer.writeByte(0x32); + break; + case UINT16: + writer.writeByte(0x33); + break; + case INT32: + writer.writeByte(0x34); + break; + case UINT32: + writer.writeByte(0x25); + break; + case INT64: + writer.writeByte(0x29); + break; + } + } else { + switch (expression.getConvertFrom()) { + case INT8: + writer.writeByte(0x24); + break; + case UINT8: + writer.writeByte(0x25); + break; + case INT16: + writer.writeByte(0x26); + break; + case UINT16: + writer.writeByte(0x27); + break; + case INT32: + writer.writeByte(0x28); + break; + case UINT32: + writer.writeByte(0x29); + break; + case INT64: + writer.writeByte(0x2B); + break; + } } writer.writeByte(alignment(expression.getAlignment())); writer.writeLEB(expression.getOffset()); @@ -752,7 +1252,7 @@ class WasmBinaryRenderingVisitor implements WasmExpressionVisitor { @Override public void visit(WasmLoadFloat32 expression) { expression.getIndex().acceptVisitor(this); - writer.writeByte(0x2C); + writer.writeByte(version == WasmBinaryVersion.V_0xD ? 0x2A : 0x2C); writer.writeByte(alignment(expression.getAlignment())); writer.writeLEB(expression.getOffset()); } @@ -760,7 +1260,7 @@ class WasmBinaryRenderingVisitor implements WasmExpressionVisitor { @Override public void visit(WasmLoadFloat64 expression) { expression.getIndex().acceptVisitor(this); - writer.writeByte(0x2D); + writer.writeByte(version == WasmBinaryVersion.V_0xD ? 0x2B : 0x2D); writer.writeByte(alignment(expression.getAlignment())); writer.writeLEB(expression.getOffset()); } @@ -769,18 +1269,34 @@ class WasmBinaryRenderingVisitor implements WasmExpressionVisitor { public void visit(WasmStoreInt32 expression) { expression.getIndex().acceptVisitor(this); expression.getValue().acceptVisitor(this); - switch (expression.getConvertTo()) { - case INT8: - case UINT8: - writer.writeByte(0x2E); - break; - case INT16: - case UINT16: - writer.writeByte(0x2F); - break; - case INT32: - writer.writeByte(0x33); - break; + if (version == WasmBinaryVersion.V_0xD) { + switch (expression.getConvertTo()) { + case INT8: + case UINT8: + writer.writeByte(0x3A); + break; + case INT16: + case UINT16: + writer.writeByte(0x3B); + break; + case INT32: + writer.writeByte(0x36); + break; + } + } else { + switch (expression.getConvertTo()) { + case INT8: + case UINT8: + writer.writeByte(0x2E); + break; + case INT16: + case UINT16: + writer.writeByte(0x2F); + break; + case INT32: + writer.writeByte(0x33); + break; + } } writer.writeByte(alignment(expression.getAlignment())); writer.writeLEB(expression.getOffset()); @@ -790,22 +1306,42 @@ class WasmBinaryRenderingVisitor implements WasmExpressionVisitor { public void visit(WasmStoreInt64 expression) { expression.getIndex().acceptVisitor(this); expression.getValue().acceptVisitor(this); - switch (expression.getConvertTo()) { - case INT8: - case UINT8: - writer.writeByte(0x30); - break; - case INT16: - case UINT16: - writer.writeByte(0x31); - break; - case INT32: - case UINT32: - writer.writeByte(0x32); - break; - case INT64: - writer.writeByte(0x34); - break; + if (version == WasmBinaryVersion.V_0xD) { + switch (expression.getConvertTo()) { + case INT8: + case UINT8: + writer.writeByte(0x3C); + break; + case INT16: + case UINT16: + writer.writeByte(0x3D); + break; + case INT32: + case UINT32: + writer.writeByte(0x3E); + break; + case INT64: + writer.writeByte(0x37); + break; + } + } else { + switch (expression.getConvertTo()) { + case INT8: + case UINT8: + writer.writeByte(0x30); + break; + case INT16: + case UINT16: + writer.writeByte(0x31); + break; + case INT32: + case UINT32: + writer.writeByte(0x32); + break; + case INT64: + writer.writeByte(0x34); + break; + } } writer.writeByte(alignment(expression.getAlignment())); writer.writeLEB(expression.getOffset()); @@ -815,7 +1351,7 @@ class WasmBinaryRenderingVisitor implements WasmExpressionVisitor { public void visit(WasmStoreFloat32 expression) { expression.getIndex().acceptVisitor(this); expression.getValue().acceptVisitor(this); - writer.writeByte(0x35); + writer.writeByte(version == WasmBinaryVersion.V_0xD ? 0x38 : 0x35); writer.writeByte(alignment(expression.getAlignment())); writer.writeLEB(expression.getOffset()); } @@ -824,7 +1360,7 @@ class WasmBinaryRenderingVisitor implements WasmExpressionVisitor { public void visit(WasmStoreFloat64 expression) { expression.getIndex().acceptVisitor(this); expression.getValue().acceptVisitor(this); - writer.writeByte(0x36); + writer.writeByte(version == WasmBinaryVersion.V_0xD ? 0x39 : 0x36); writer.writeByte(alignment(expression.getAlignment())); writer.writeLEB(expression.getOffset()); } diff --git a/core/src/main/java/org/teavm/backend/wasm/render/WasmBinaryVersion.java b/core/src/main/java/org/teavm/backend/wasm/render/WasmBinaryVersion.java index 43058cada..2644ababa 100644 --- a/core/src/main/java/org/teavm/backend/wasm/render/WasmBinaryVersion.java +++ b/core/src/main/java/org/teavm/backend/wasm/render/WasmBinaryVersion.java @@ -17,5 +17,6 @@ package org.teavm.backend.wasm.render; public enum WasmBinaryVersion { V_0xB, - V_0xC + V_0xC, + V_0xD } diff --git a/core/src/main/java/org/teavm/backend/wasm/render/WasmBinaryWriter.java b/core/src/main/java/org/teavm/backend/wasm/render/WasmBinaryWriter.java index 6decb28dd..234fee8cb 100644 --- a/core/src/main/java/org/teavm/backend/wasm/render/WasmBinaryWriter.java +++ b/core/src/main/java/org/teavm/backend/wasm/render/WasmBinaryWriter.java @@ -27,23 +27,23 @@ public class WasmBinaryWriter { data[pointer++] = (byte) v; } - public void writeType(WasmType type) { + public void writeType(WasmType type, WasmBinaryVersion version) { if (type == null) { - writeByte(0); + writeByte(version == WasmBinaryVersion.V_0xD ? 0x40 : 0); return; } switch (type) { case INT32: - writeByte(1); + writeByte(version == WasmBinaryVersion.V_0xD ? 0x7F : 1); break; case INT64: - writeByte(2); + writeByte(version == WasmBinaryVersion.V_0xD ? 0x7E : 2); break; case FLOAT32: - writeByte(3); + writeByte(version == WasmBinaryVersion.V_0xD ? 0x7D : 3); break; case FLOAT64: - writeByte(4); + writeByte(version == WasmBinaryVersion.V_0xD ? 0x7C : 4); break; } } diff --git a/tools/cli/src/main/java/org/teavm/cli/TeaVMRunner.java b/tools/cli/src/main/java/org/teavm/cli/TeaVMRunner.java index 54430c049..388a4b72d 100644 --- a/tools/cli/src/main/java/org/teavm/cli/TeaVMRunner.java +++ b/tools/cli/src/main/java/org/teavm/cli/TeaVMRunner.java @@ -110,7 +110,7 @@ public final class TeaVMRunner { .withLongOpt("wasm-version") .withArgName("version") .hasArg() - .withDescription("WebAssembly binary version (11, 12)") + .withDescription("WebAssembly binary version (11, 12, 13)") .create()); if (args.length == 0) { @@ -296,6 +296,9 @@ public final class TeaVMRunner { case 12: tool.setWasmVersion(WasmBinaryVersion.V_0xC); break; + case 13: + tool.setWasmVersion(WasmBinaryVersion.V_0xD); + break; default: System.err.print("Wrong version value"); printUsage(options); diff --git a/tools/core/src/main/java/org/teavm/tooling/TeaVMTool.java b/tools/core/src/main/java/org/teavm/tooling/TeaVMTool.java index 0ecaaf992..899cc2558 100644 --- a/tools/core/src/main/java/org/teavm/tooling/TeaVMTool.java +++ b/tools/core/src/main/java/org/teavm/tooling/TeaVMTool.java @@ -99,7 +99,7 @@ public class TeaVMTool implements BaseTeaVMTool { private DebugInformationBuilder debugEmitter; private JavaScriptTarget javaScriptTarget; private WasmTarget webAssemblyTarget; - private WasmBinaryVersion wasmVersion = WasmBinaryVersion.V_0xC; + private WasmBinaryVersion wasmVersion = WasmBinaryVersion.V_0xD; public File getTargetDirectory() { return targetDirectory; diff --git a/tools/maven/plugin/src/main/java/org/teavm/maven/TeaVMCompileMojo.java b/tools/maven/plugin/src/main/java/org/teavm/maven/TeaVMCompileMojo.java index 28633023c..f6d0f67ea 100644 --- a/tools/maven/plugin/src/main/java/org/teavm/maven/TeaVMCompileMojo.java +++ b/tools/maven/plugin/src/main/java/org/teavm/maven/TeaVMCompileMojo.java @@ -78,7 +78,7 @@ public class TeaVMCompileMojo extends AbstractTeaVMMojo { private TeaVMTool tool = new TeaVMTool(); @Parameter - private WasmBinaryVersion wasmVersion = WasmBinaryVersion.V_0xC; + private WasmBinaryVersion wasmVersion = WasmBinaryVersion.V_0xD; @Override protected File getTargetDirectory() {