Add support for i32.load to the wat parser and some small bug fixes

This commit is contained in:
Volker Berlin 2019-11-18 21:32:35 +01:00
parent 86d239986e
commit 947f66502b
5 changed files with 107 additions and 7 deletions

View File

@ -33,6 +33,7 @@ import de.inetsoftware.jwebassembly.javascript.NonGC;
import de.inetsoftware.jwebassembly.module.WasmInstruction.Type;
import de.inetsoftware.jwebassembly.wasm.AnyType;
import de.inetsoftware.jwebassembly.wasm.ArrayOperator;
import de.inetsoftware.jwebassembly.wasm.MemoryOperator;
import de.inetsoftware.jwebassembly.wasm.NamedStorageType;
import de.inetsoftware.jwebassembly.wasm.NumericOperator;
import de.inetsoftware.jwebassembly.wasm.StructOperator;
@ -356,7 +357,20 @@ public abstract class WasmCodeBuilder {
if( id == null ) {
strings.put( (String)value, id = strings.size() );
}
FunctionName name = getNonGC( "stringConstant", lineNumber );
String wat = "local.get 0 " + //
"table.get 1 " + // strings table
"local.tee 1 " + //
"ref.is_null " + //
"if " + //
"local.get 0 " + //
"i32.const 4 " + //
"i32.mul " + //
"i32.load offset=0 " + //
"drop " + //
"end " + //
"local.get 1 " + //
"return";
FunctionName name = new WatCodeSyntheticFunctionName( "stringConstant", wat, ValueType.i32, null, ValueType.anyref );
instructions.add( new WasmConstInstruction( id, ValueType.i32, javaCodePos, lineNumber ) );
addCallInstruction( name, javaCodePos, lineNumber );
} else {
@ -586,4 +600,24 @@ public abstract class WasmCodeBuilder {
}
}
}
/**
* Create an instance of a load/store to the linear memory instruction
*
* @param op
* the operation
* @param type
* the type of the static field
* @param offset
* the base offset which will be added to the offset value on the stack
* @param alignment
* the alignment of the value on the linear memory (0: 8 Bit; 1: 16 Bit; 2: 32 Bit)
* @param javaCodePos
* the code position/offset in the Java method
* @param lineNumber
* the line number in the Java source code
*/
protected void addMemoryInstruction( MemoryOperator op, ValueType type, int offset, int alignment, int javaCodePos, int lineNumber ) {
instructions.add( new WasmMemoryInstruction( op, type, offset, alignment, javaCodePos, lineNumber ) );
}
}

View File

@ -38,10 +38,10 @@ class WasmMemoryInstruction extends WasmInstruction {
private int offset;
private int aligment;
private int alignment;
/**
* Create an instance of a load/store instruction
* Create an instance of a load/store to the linear memory instruction
*
* @param op
* the operation
@ -56,12 +56,12 @@ class WasmMemoryInstruction extends WasmInstruction {
* @param lineNumber
* the line number in the Java source code
*/
WasmMemoryInstruction( MemoryOperator op, ValueType type, int offset, int aligment, int javaCodePos, int lineNumber ) {
WasmMemoryInstruction( MemoryOperator op, ValueType type, int offset, int alignment, int javaCodePos, int lineNumber ) {
super( javaCodePos, lineNumber );
this.op = op;
this.type = type;
this.offset = offset;
this.aligment = aligment;
this.alignment = alignment;
}
/**
@ -77,7 +77,7 @@ class WasmMemoryInstruction extends WasmInstruction {
*/
@Override
public void writeTo( @Nonnull ModuleWriter writer ) throws IOException {
writer.writeMemoryOperator( op, type, offset, aligment );
writer.writeMemoryOperator( op, type, offset, alignment );
}
/**

View File

@ -149,8 +149,10 @@ public class TextModuleWriter extends ModuleWriter {
if( stringCount > 0 ) {
if( !callIndirect ) {
// we need to create a placeholder table with index 0 if not exists
newline( output );
output.append( "(table 0 funcref)" );
}
newline( output );
output.append( "(table " ).append( Integer.toString( stringCount ) ).append( " anyref)" );
}
@ -843,6 +845,6 @@ public class TextModuleWriter extends ModuleWriter {
newline( methodOutput );
methodOutput.append( valueType ).append( '.' ).append( memOp )
.append( " offset=" ).append( offset )
.append( " align=" ).append( alignment );
.append( " align=" ).append( 1 << alignment );
}
}

View File

@ -27,6 +27,7 @@ import de.inetsoftware.classparser.MethodInfo;
import de.inetsoftware.jwebassembly.WasmException;
import de.inetsoftware.jwebassembly.module.ValueTypeConvertion;
import de.inetsoftware.jwebassembly.module.WasmCodeBuilder;
import de.inetsoftware.jwebassembly.wasm.MemoryOperator;
import de.inetsoftware.jwebassembly.wasm.NumericOperator;
import de.inetsoftware.jwebassembly.wasm.ValueType;
import de.inetsoftware.jwebassembly.wasm.VariableOperator;
@ -220,6 +221,12 @@ public class WatParser extends WasmCodeBuilder {
case "end":
addBlockInstruction( WasmBlockOperator.END, null, javaCodePos, lineNumber );
break;
case "drop":
addBlockInstruction( WasmBlockOperator.DROP, null, javaCodePos, lineNumber );
break;
case "i32.load":
i = addMemoryInstruction( MemoryOperator.load, ValueType.i32, tokens, i, lineNumber );
break;
default:
throw new WasmException( "Unknown WASM token: " + tok, lineNumber );
}
@ -301,4 +308,51 @@ public class WatParser extends WasmCodeBuilder {
}
return tokens;
}
/**
* Parse the optional tokens of a load memory instruction and add it.
*
* @param op
* the operation
* @param type
* the type of the static field
* @param tokens
* the token list
* @param i
* the position in the tokens
* @param lineNumber
* the line number in the Java source code
* @return the current index to the tokens
*/
private int addMemoryInstruction( MemoryOperator op, ValueType type, List<String> tokens, int i, int lineNumber ) {
int offset = 0;
int alignment = 0;
if( i < tokens.size() ) {
String str = tokens.get( i + 1 );
if( str.startsWith( "offset=" ) ) {
offset = Integer.parseInt( str.substring( 7 ) );
i++;
}
str = tokens.get( i + 1 );
if( str.startsWith( "align=" ) ) {
int align = Integer.parseInt( str.substring( 6 ) );
switch( align ) {
case 1:
alignment = 0;
break;
case 2:
alignment = 1;
break;
case 4:
alignment = 2;
break;
default:
throw new WasmException( "alignment must be power-of-two", lineNumber );
}
i++;
}
}
addMemoryInstruction( op, type, offset, alignment, i, lineNumber );
return i;
}
}

View File

@ -315,6 +315,11 @@ public class WatParserTest {
test( "if (result i32) else end" );
}
@Test
public void drop() throws IOException {
test( "drop" );
}
@Test
public void table_get() throws IOException {
test( "table.get 1" );
@ -326,6 +331,11 @@ public class WatParserTest {
}
@Test
public void i32_load() throws IOException {
test( "i32.load offset=2 align=1" );
}
@Test
public void errorMissingToken() throws IOException {
testError( "i32.const", "Missing Token in wasm text format after token: i32.const" );
}