From baf7fb9cf0290d7237df5359bd877191cdd1b47e Mon Sep 17 00:00:00 2001 From: Volker Berlin Date: Sun, 3 Nov 2019 19:00:49 +0100 Subject: [PATCH] Add table.set/get --- .../binary/BinaryModuleWriter.java | 11 ++- .../jwebassembly/module/ModuleWriter.java | 15 +++- .../jwebassembly/module/WasmCodeBuilder.java | 20 ++++- .../jwebassembly/module/WasmInstruction.java | 2 +- .../module/WasmTableInstruction.java | 88 +++++++++++++++++++ .../jwebassembly/text/TextModuleWriter.java | 10 +++ .../jwebassembly/watparser/WatParser.java | 6 ++ .../jwebassembly/module/WatParserTest.java | 10 +++ 8 files changed, 158 insertions(+), 4 deletions(-) create mode 100644 src/de/inetsoftware/jwebassembly/module/WasmTableInstruction.java diff --git a/src/de/inetsoftware/jwebassembly/binary/BinaryModuleWriter.java b/src/de/inetsoftware/jwebassembly/binary/BinaryModuleWriter.java index 4a26fa6..cfe8fc3 100644 --- a/src/de/inetsoftware/jwebassembly/binary/BinaryModuleWriter.java +++ b/src/de/inetsoftware/jwebassembly/binary/BinaryModuleWriter.java @@ -16,7 +16,6 @@ package de.inetsoftware.jwebassembly.binary; import java.io.IOException; -import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Collection; import java.util.LinkedHashMap; @@ -24,6 +23,7 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; +import javax.annotation.Nonnegative; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -648,6 +648,15 @@ public class BinaryModuleWriter extends ModuleWriter implements InstructionOpcod codeStream.writeVaruint32( var.id ); } + /** + * {@inheritDoc} + */ + @Override + protected void writeTable( boolean load, @Nonnegative int idx ) throws IOException { + codeStream.writeOpCode( load ? TABLE_GET : TABLE_SET ); + codeStream.writeVaruint32( idx ); + } + /** * {@inheritDoc} */ diff --git a/src/de/inetsoftware/jwebassembly/module/ModuleWriter.java b/src/de/inetsoftware/jwebassembly/module/ModuleWriter.java index d5eb6e4..598cb57 100644 --- a/src/de/inetsoftware/jwebassembly/module/ModuleWriter.java +++ b/src/de/inetsoftware/jwebassembly/module/ModuleWriter.java @@ -18,6 +18,7 @@ package de.inetsoftware.jwebassembly.module; import java.io.Closeable; import java.io.IOException; +import javax.annotation.Nonnegative; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -195,7 +196,7 @@ public abstract class ModuleWriter implements Closeable { protected abstract void writeLocal( VariableOperator op, int idx ) throws IOException; /** - * Write a set_global variable + * Write a global variable operation * @param load * true: if load or GET * @param name @@ -208,6 +209,18 @@ public abstract class ModuleWriter implements Closeable { */ protected abstract void writeGlobalAccess( boolean load, FunctionName name, AnyType type ) throws IOException; + /** + * Write a table operation. + * @param load + * true: if "get" else "set" + * @param idx + * the index of the table + * + * @throws IOException + * if any I/O error occur + */ + protected abstract void writeTable( boolean load, @Nonnegative int idx ) throws IOException; + /** * Write the default/initial value for a type. * diff --git a/src/de/inetsoftware/jwebassembly/module/WasmCodeBuilder.java b/src/de/inetsoftware/jwebassembly/module/WasmCodeBuilder.java index 946292d..7e97e78 100644 --- a/src/de/inetsoftware/jwebassembly/module/WasmCodeBuilder.java +++ b/src/de/inetsoftware/jwebassembly/module/WasmCodeBuilder.java @@ -252,7 +252,7 @@ public abstract class WasmCodeBuilder { } /** - * Create a WasmLoadStoreInstruction get_local/set_local. + * Create a WasmLoadStoreInstruction local.get/local.set. * * @param load * true: if load @@ -286,6 +286,23 @@ public abstract class WasmCodeBuilder { instructions.add( new WasmGlobalInstruction( load, name, type, javaCodePos, lineNumber ) ); } + /** + * Add a WasmTableInstruction table.get/table.set. + * + * @param load + * true: if load + * @param idx + * the index of the table + * @param javaCodePos + * the code position/offset in the Java method + * @param lineNumber + * the line number in the Java source code + */ + @Nonnull + protected void addTableInstruction( boolean load, @Nonnegative int idx, int javaCodePos, int lineNumber ) { + instructions.add( new WasmTableInstruction( load, idx, javaCodePos, lineNumber ) ); + } + /** * Add a constant instruction. * @@ -319,6 +336,7 @@ public abstract class WasmCodeBuilder { strings.put( (String)value, id = strings.size() ); } FunctionName name = getNonGC( "stringConstant", lineNumber ); + instructions.add( new WasmConstInstruction( id, ValueType.i32, javaCodePos, lineNumber ) ); addCallInstruction( name, javaCodePos, lineNumber ); } else { instructions.add( new WasmConstInstruction( (Number)value, javaCodePos, lineNumber ) ); diff --git a/src/de/inetsoftware/jwebassembly/module/WasmInstruction.java b/src/de/inetsoftware/jwebassembly/module/WasmInstruction.java index d406e57..d7a0a94 100644 --- a/src/de/inetsoftware/jwebassembly/module/WasmInstruction.java +++ b/src/de/inetsoftware/jwebassembly/module/WasmInstruction.java @@ -35,7 +35,7 @@ abstract class WasmInstruction { * Type of instruction to faster differ as with instanceof. */ static enum Type { - Const, Convert, Local, Global, Block, Numeric, Nop, Call, CallIndirect, Array, Struct, DupThis; + Const, Convert, Local, Global, Table, Block, Numeric, Nop, Call, CallIndirect, Array, Struct, DupThis; } private int javaCodePos; diff --git a/src/de/inetsoftware/jwebassembly/module/WasmTableInstruction.java b/src/de/inetsoftware/jwebassembly/module/WasmTableInstruction.java new file mode 100644 index 0000000..7938a1d --- /dev/null +++ b/src/de/inetsoftware/jwebassembly/module/WasmTableInstruction.java @@ -0,0 +1,88 @@ +/* + Copyright 2019 Volker Berlin (i-net software) + + 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 de.inetsoftware.jwebassembly.module; + +import java.io.IOException; + +import javax.annotation.Nonnegative; +import javax.annotation.Nonnull; + +import de.inetsoftware.jwebassembly.wasm.AnyType; +import de.inetsoftware.jwebassembly.wasm.ValueType; + +/** + * WasmInstruction for load and store a element in a table. + * + * @author Volker Berlin + * + */ +class WasmTableInstruction extends WasmInstruction { + + private boolean load; + + private int idx; + + /** + * Create an instance of a load/store instruction + * + * @param load + * true: if "get" else "set" + * @param idx + * the index of the table + * @param javaCodePos + * the code position/offset in the Java method + * @param lineNumber + * the line number in the Java source code + */ + WasmTableInstruction( boolean load, @Nonnegative int idx, int javaCodePos, int lineNumber ) { + super( javaCodePos, lineNumber ); + this.load = load; + this.idx = idx; + } + + /** + * {@inheritDoc} + */ + @Override + Type getType() { + return Type.Table; + } + + /** + * {@inheritDoc} + */ + @Override + public void writeTo( @Nonnull ModuleWriter writer ) throws IOException { + writer.writeTable( load, idx ); + } + + /** + * {@inheritDoc} + */ + @Override + AnyType getPushValueType() { + return load ? ValueType.anyref : null; + } + + /** + * {@inheritDoc} + */ + @Override + int getPopCount() { + return load ? 0 : 1; + } +} diff --git a/src/de/inetsoftware/jwebassembly/text/TextModuleWriter.java b/src/de/inetsoftware/jwebassembly/text/TextModuleWriter.java index 0a26fa1..7de964d 100644 --- a/src/de/inetsoftware/jwebassembly/text/TextModuleWriter.java +++ b/src/de/inetsoftware/jwebassembly/text/TextModuleWriter.java @@ -25,6 +25,7 @@ import java.util.Map; import java.util.Map.Entry; import java.util.Set; +import javax.annotation.Nonnegative; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -470,6 +471,15 @@ public class TextModuleWriter extends ModuleWriter { methodOutput.append( load ? "global.get $" : "global.set $" ).append( fullName ); } + /** + * {@inheritDoc} + */ + @Override + protected void writeTable( boolean load, @Nonnegative int idx ) throws IOException { + newline( methodOutput ); + methodOutput.append( load ? "table.get " : "table.set " ).append( idx ); + } + /** * {@inheritDoc} */ diff --git a/src/de/inetsoftware/jwebassembly/watparser/WatParser.java b/src/de/inetsoftware/jwebassembly/watparser/WatParser.java index 0e62287..8b4c029 100644 --- a/src/de/inetsoftware/jwebassembly/watparser/WatParser.java +++ b/src/de/inetsoftware/jwebassembly/watparser/WatParser.java @@ -171,6 +171,12 @@ public class WatParser extends WasmCodeBuilder { case "f64.trunc": addNumericInstruction( NumericOperator.trunc, ValueType.f64, javaCodePos, lineNumber ); break; + case "table.get": + addTableInstruction( true, getInt( tokens, ++i), javaCodePos, lineNumber ); + break; + case "table.set": + addTableInstruction( false, getInt( tokens, ++i), javaCodePos, lineNumber ); + break; // case "call": // addCallInstruction( method, javaCodePos ); // break; diff --git a/test/de/inetsoftware/jwebassembly/module/WatParserTest.java b/test/de/inetsoftware/jwebassembly/module/WatParserTest.java index 9aecdf4..91a1158 100644 --- a/test/de/inetsoftware/jwebassembly/module/WatParserTest.java +++ b/test/de/inetsoftware/jwebassembly/module/WatParserTest.java @@ -279,6 +279,16 @@ public class WatParserTest { test( "if (result i32) else end" ); } + @Test + public void table_get() throws IOException { + test( "table.get 1" ); + } + + @Test + public void table_set() throws IOException { + test( "table.set 2" ); + } + @Test public void errorMissingToken() throws IOException { testError( "i32.const", "Missing Token in wasm text format after token: i32.const" );