WASM: add support of 0x0D binary version

This commit is contained in:
Alexey Andreev 2016-11-20 21:57:40 +03:00
parent 24efd1f49c
commit 9364ad943a
7 changed files with 704 additions and 147 deletions

View File

@ -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<String, Integer> 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) {

View File

@ -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());
}

View File

@ -17,5 +17,6 @@ package org.teavm.backend.wasm.render;
public enum WasmBinaryVersion {
V_0xB,
V_0xC
V_0xC,
V_0xD
}

View File

@ -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;
}
}

View File

@ -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);

View File

@ -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;

View File

@ -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() {