From d2eb2e160ffc4248f35692e41c970bb5b49f532d Mon Sep 17 00:00:00 2001 From: Volker Berlin Date: Fri, 14 Apr 2017 16:31:35 +0200 Subject: [PATCH] add support for mul and div --- .../binary/BinaryModuleWriter.java | 43 ++++++++++++++ .../binary/InstructionOpcodes.java | 20 +++++++ .../jwebassembly/module/ModuleWriter.java | 57 +++++++++++++++++++ .../jwebassembly/module/NumericOperator.java | 3 + .../inetsoftware/jwebassembly/WasmRule.java | 26 ++++----- .../jwebassembly/err/RuntimeErrors.java | 25 ++++++++ .../jwebassembly/math/MathOperations.java | 39 +++++++++++++ 7 files changed, 200 insertions(+), 13 deletions(-) diff --git a/src/de/inetsoftware/jwebassembly/binary/BinaryModuleWriter.java b/src/de/inetsoftware/jwebassembly/binary/BinaryModuleWriter.java index 9e7bb7c..ce1ad1a 100644 --- a/src/de/inetsoftware/jwebassembly/binary/BinaryModuleWriter.java +++ b/src/de/inetsoftware/jwebassembly/binary/BinaryModuleWriter.java @@ -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(); diff --git a/src/de/inetsoftware/jwebassembly/binary/InstructionOpcodes.java b/src/de/inetsoftware/jwebassembly/binary/InstructionOpcodes.java index c0f2e30..76fb2a9 100644 --- a/src/de/inetsoftware/jwebassembly/binary/InstructionOpcodes.java +++ b/src/de/inetsoftware/jwebassembly/binary/InstructionOpcodes.java @@ -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; diff --git a/src/de/inetsoftware/jwebassembly/module/ModuleWriter.java b/src/de/inetsoftware/jwebassembly/module/ModuleWriter.java index f712d19..cc5daee 100644 --- a/src/de/inetsoftware/jwebassembly/module/ModuleWriter.java +++ b/src/de/inetsoftware/jwebassembly/module/ModuleWriter.java @@ -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; diff --git a/src/de/inetsoftware/jwebassembly/module/NumericOperator.java b/src/de/inetsoftware/jwebassembly/module/NumericOperator.java index 8600345..1422b1d 100644 --- a/src/de/inetsoftware/jwebassembly/module/NumericOperator.java +++ b/src/de/inetsoftware/jwebassembly/module/NumericOperator.java @@ -21,4 +21,7 @@ package de.inetsoftware.jwebassembly.module; public enum NumericOperator { add, sub, + mul, + div, + rem, } diff --git a/test/de/inetsoftware/jwebassembly/WasmRule.java b/test/de/inetsoftware/jwebassembly/WasmRule.java index 8c2daa2..db83114 100644 --- a/test/de/inetsoftware/jwebassembly/WasmRule.java +++ b/test/de/inetsoftware/jwebassembly/WasmRule.java @@ -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" ); } /** diff --git a/test/de/inetsoftware/jwebassembly/err/RuntimeErrors.java b/test/de/inetsoftware/jwebassembly/err/RuntimeErrors.java index f401bfb..0f24c3c 100644 --- a/test/de/inetsoftware/jwebassembly/err/RuntimeErrors.java +++ b/test/de/inetsoftware/jwebassembly/err/RuntimeErrors.java @@ -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; + } + } } diff --git a/test/de/inetsoftware/jwebassembly/math/MathOperations.java b/test/de/inetsoftware/jwebassembly/math/MathOperations.java index 9d3aba8..42820ef 100644 --- a/test/de/inetsoftware/jwebassembly/math/MathOperations.java +++ b/test/de/inetsoftware/jwebassembly/math/MathOperations.java @@ -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; + } + } }