add support for mul and div

This commit is contained in:
Volker Berlin 2017-04-14 16:31:35 +02:00
parent f5928ab1d4
commit d2eb2e160f
7 changed files with 200 additions and 13 deletions

View File

@ -25,6 +25,7 @@ import java.util.Map;
import javax.annotation.Nullable;
import de.inetsoftware.jwebassembly.WasmException;
import de.inetsoftware.jwebassembly.module.ModuleWriter;
import de.inetsoftware.jwebassembly.module.NumericOperator;
import de.inetsoftware.jwebassembly.module.ValueType;
@ -322,6 +323,48 @@ public class BinaryModuleWriter extends ModuleWriter implements InstructionOpcod
break;
}
break;
case mul:
switch( valueType ) {
case i32:
op = I32_MUL;
break;
case i64:
op = I64_MUL;
break;
case f32:
op = F32_MUL;
break;
case f64:
op = F64_MUL;
break;
}
break;
case div:
switch( valueType ) {
case i32:
op = I32_DIV_S;
break;
case i64:
op = I64_DIV_S;
break;
case f32:
op = F32_DIV;
break;
case f64:
op = F64_DIV;
break;
}
break;
case rem:
switch( valueType ) {
case i32:
op = I32_REM_S;
break;
case i64:
op = I64_REM_S;
break;
}
break;
}
if( op == 0 ) {
throw new Error();

View File

@ -57,18 +57,38 @@ interface InstructionOpcodes {
static final int I32_SUB = 0x6B;
static final int I32_MUL = 0x6C;
static final int I32_DIV_S = 0x6D;
static final int I32_REM_S = 0x6F;
static final int I64_ADD = 0x7C;
static final int I64_SUB = 0x7D;
static final int I64_MUL = 0x7E;
static final int I64_DIV_S = 0x7F;
static final int I64_REM_S = 0x81;
static final int F32_ADD = 0x92;
static final int F32_SUB = 0x93;
static final int F32_MUL = 0x94;
static final int F32_DIV = 0x95;
static final int F64_ADD = 0xA0;
static final int F64_SUB = 0xA1;
static final int F64_MUL = 0xA2;
static final int F64_DIV = 0xA3;
// === data type conversions =====
static final int I32_WRAP_I64 = 0xA7;

View File

@ -269,9 +269,21 @@ public abstract class ModuleWriter implements Closeable {
case 10: // lconst_1
writeConstLong( op - 9 );
break;
case 11: // fconst_0
case 12: // fconst_1
case 13: // fconst_2
writeConstFloat( op - 11 );
break;
case 14: // dconst_0
case 15: // dconst_1
writeConstDouble( op - 14 );
break;
case 16: // bipush
writeConstInt( byteCode.readByte() );
break;
case 17: // sipush
writeConstInt( byteCode.readShort() );
break;
case 18: // ldc
writeConst( constantPool.get( byteCode.readUnsignedByte() ) );
break;
@ -314,6 +326,18 @@ public abstract class ModuleWriter implements Closeable {
case 66: // lstore_3
writeLoadStore( false, ValueType.i64, op - 63 );
break;
case 67: // fstore_0
case 68: // fstore_1
case 69: // fstore_2
case 70: // fstore_3
writeLoadStore( false, ValueType.f32, op - 67 );
break;
case 71: // dstore_0
case 72: // dstore_1
case 73: // dstore_2
case 74: // dstore_3
writeLoadStore( false, ValueType.f64, op - 71 );
break;
case 96: // iadd
writeNumericOperator( NumericOperator.add, ValueType.i32);
break;
@ -338,6 +362,39 @@ public abstract class ModuleWriter implements Closeable {
case 103: // dsub
writeNumericOperator( NumericOperator.sub, ValueType.f64 );
break;
case 104: // imul;
writeNumericOperator( NumericOperator.mul, ValueType.i32 );
break;
case 105: // lmul
writeNumericOperator( NumericOperator.mul, ValueType.i64 );
break;
case 106: // fmul
writeNumericOperator( NumericOperator.mul, ValueType.f32 );
break;
case 107: // dmul
writeNumericOperator( NumericOperator.mul, ValueType.f64 );
break;
case 108: // idiv
writeNumericOperator( NumericOperator.div, ValueType.i32 );
break;
case 109: // ldiv
writeNumericOperator( NumericOperator.div, ValueType.i64 );
break;
case 110: // fdiv
writeNumericOperator( NumericOperator.div, ValueType.f32 );
break;
case 111: // ddiv
writeNumericOperator( NumericOperator.div, ValueType.f64 );
break;
case 112: // irem
writeNumericOperator( NumericOperator.rem, ValueType.i32 );
break;
case 113: // lrem
writeNumericOperator( NumericOperator.rem, ValueType.i64 );
break;
case 114: // frem
case 115: // drem
throw new WasmException( "Modulo/Remainder for floating numbers is not supported in WASM. Use int or long data types." + op, sourceFile, lineNumber );
case 136: // l2i
writeCast( ValueTypeConvertion.l2i );
break;

View File

@ -21,4 +21,7 @@ package de.inetsoftware.jwebassembly.module;
public enum NumericOperator {
add,
sub,
mul,
div,
rem,
}

View File

@ -63,21 +63,21 @@ public class WasmRule extends TemporaryFolder {
*/
@Override
protected void before() throws Throwable {
super.before();
try {
wasmFile = newFile( "test.wasm" );
JWebAssembly wasm = new JWebAssembly();
for( Class<?> clazz : classes ) {
URL url = clazz.getResource( '/' + clazz.getName().replace( '.', '/' ) + ".class" );
wasm.addFile( url );
}
wasm.compileToBinary( wasmFile );
compile();
}
nodeScript = createScript( "nodetest.js" );
spiderMonkeyScript = createScript( "SpiderMonkeyTest.js" );
} catch( Exception ex ) {
throwException( ex );
public void compile() throws IOException, WasmException {
create();
wasmFile = newFile( "test.wasm" );
JWebAssembly wasm = new JWebAssembly();
for( Class<?> clazz : classes ) {
URL url = clazz.getResource( '/' + clazz.getName().replace( '.', '/' ) + ".class" );
wasm.addFile( url );
}
wasm.compileToBinary( wasmFile );
nodeScript = createScript( "nodetest.js" );
spiderMonkeyScript = createScript( "SpiderMonkeyTest.js" );
}
/**

View File

@ -16,7 +16,10 @@
package de.inetsoftware.jwebassembly.err;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.io.IOException;
import java.util.Collection;
import org.junit.ClassRule;
@ -27,6 +30,7 @@ import org.junit.runners.Parameterized.Parameters;
import org.webassembly.annotation.Export;
import de.inetsoftware.jwebassembly.ScriptEngine;
import de.inetsoftware.jwebassembly.WasmException;
import de.inetsoftware.jwebassembly.WasmRule;
/**
@ -61,4 +65,25 @@ public class RuntimeErrors {
return Long.MAX_VALUE;
}
}
@Test
public void floatRem() throws IOException {
WasmRule wasm = new WasmRule( TestModulo.class );
try {
wasm.compile();
fail( "Floating modulo is not supported" );
} catch( WasmException ex ) {
assertTrue( ex.toString(), ex.getMessage().contains( "Modulo/Remainder" ) );
} finally {
wasm.delete();
}
}
static class TestModulo {
@Export
static float longReturn() {
float a = 3.4F;
return a % 2F;
}
}
}

View File

@ -63,6 +63,10 @@ public class MathOperations {
addParam( list, script, "subLong" );
addParam( list, script, "subFloat", 1F, 3.5F );
addParam( list, script, "subDouble", 1.0, 3.5 );
addParam( list, script, "mulDivInt" );
addParam( list, script, "mulDivLong" );
addParam( list, script, "mulDivFloat" );
addParam( list, script, "mulDivDouble" );
}
return list;
}
@ -136,5 +140,40 @@ public class MathOperations {
static double subDouble( double a, double b ) {
return a - b;
}
@Export
static int mulDivInt() {
int a = 420;
a *= 3;
a /= -5;
a %= 37;
return a;
}
@Export
static int mulDivLong() {
long a = -54321;
a *= 3;
a /= -5;
a %= 37;
return (int)a;
}
@Export
static float mulDivFloat() {
float a = -54321F;
a *= 3F;
a /= -8F;
return a;
}
@Export
static double mulDivDouble() {
double a = -54321.0;
a *= 3F;
a /= -5F;
return a;
}
}
}