mirror of
https://github.com/i-net-software/JWebAssembly.git
synced 2025-03-25 23:47:51 +01:00
Write locals to binary format.
This commit is contained in:
parent
a5eee6aa7d
commit
92dc727962
@ -32,20 +32,23 @@ import de.inetsoftware.jwebassembly.module.ValueType;
|
|||||||
*/
|
*/
|
||||||
public class BinaryModuleWriter extends ModuleWriter implements InstructionOpcodes {
|
public class BinaryModuleWriter extends ModuleWriter implements InstructionOpcodes {
|
||||||
|
|
||||||
private static final byte[] WASM_BINARY_MAGIC = { 0, 'a', 's', 'm' };
|
private static final byte[] WASM_BINARY_MAGIC = { 0, 'a', 's', 'm' };
|
||||||
|
|
||||||
private static final int WASM_BINARY_VERSION = 1;
|
private static final int WASM_BINARY_VERSION = 1;
|
||||||
|
|
||||||
private WasmOutputStream wasm;
|
private WasmOutputStream wasm;
|
||||||
|
|
||||||
private WasmOutputStream codeStream = new WasmOutputStream();
|
private WasmOutputStream codeStream = new WasmOutputStream();
|
||||||
|
|
||||||
private List<FunctionType> functionTypes = new ArrayList<>();
|
private WasmOutputStream functionsStream = new WasmOutputStream();
|
||||||
|
|
||||||
private Map<String,Function> functions = new LinkedHashMap<>();
|
private List<FunctionType> functionTypes = new ArrayList<>();
|
||||||
|
|
||||||
private Function function;
|
private Map<String, Function> functions = new LinkedHashMap<>();
|
||||||
private FunctionType functionType;
|
|
||||||
|
private Function function;
|
||||||
|
|
||||||
|
private FunctionType functionType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create new instance.
|
* Create new instance.
|
||||||
@ -74,6 +77,12 @@ public class BinaryModuleWriter extends ModuleWriter implements InstructionOpcod
|
|||||||
wasm.close();
|
wasm.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write the type section to the output. This section contains the signatures of the functions.
|
||||||
|
*
|
||||||
|
* @throws IOException
|
||||||
|
* if any I/O error occur
|
||||||
|
*/
|
||||||
private void writeTypeSection() throws IOException {
|
private void writeTypeSection() throws IOException {
|
||||||
int count = functionTypes.size();
|
int count = functionTypes.size();
|
||||||
if( count > 0 ) {
|
if( count > 0 ) {
|
||||||
@ -96,6 +105,12 @@ public class BinaryModuleWriter extends ModuleWriter implements InstructionOpcod
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write the function section to the output. This section contains a mapping from the function index to the type signature index.
|
||||||
|
*
|
||||||
|
* @throws IOException
|
||||||
|
* if any I/O error occur
|
||||||
|
*/
|
||||||
private void writeFunctionSection() throws IOException {
|
private void writeFunctionSection() throws IOException {
|
||||||
int count = functions.size();
|
int count = functions.size();
|
||||||
if( count > 0 ) {
|
if( count > 0 ) {
|
||||||
@ -108,10 +123,20 @@ public class BinaryModuleWriter extends ModuleWriter implements InstructionOpcod
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write the code section to the output. This section contains the byte code.
|
||||||
|
*
|
||||||
|
* @throws IOException
|
||||||
|
* if any I/O error occur
|
||||||
|
*/
|
||||||
private void writeCodeSection() throws IOException {
|
private void writeCodeSection() throws IOException {
|
||||||
|
int size = functions.size();
|
||||||
|
if( size == 0 ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
WasmOutputStream stream = new WasmOutputStream();
|
WasmOutputStream stream = new WasmOutputStream();
|
||||||
stream.writeVaruint32( functions.size() );
|
stream.writeVaruint32( size );
|
||||||
codeStream.writeTo( stream );
|
functionsStream.writeTo( stream );
|
||||||
wasm.writeSection( SectionType.Code, stream, null );
|
wasm.writeSection( SectionType.Code, stream, null );
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -124,6 +149,7 @@ public class BinaryModuleWriter extends ModuleWriter implements InstructionOpcod
|
|||||||
function.id = functions.size();
|
function.id = functions.size();
|
||||||
functions.put( name, function );
|
functions.put( name, function );
|
||||||
functionType = new FunctionType();
|
functionType = new FunctionType();
|
||||||
|
codeStream.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -145,11 +171,22 @@ public class BinaryModuleWriter extends ModuleWriter implements InstructionOpcod
|
|||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
protected void writeMethodFinish() throws IOException {
|
protected void writeMethodFinish( List<ValueType> locals ) throws IOException {
|
||||||
// TODO optimize and search for duplicates
|
// TODO optimize and search for duplicates
|
||||||
function.typeId = functionTypes.size();
|
function.typeId = functionTypes.size();
|
||||||
functionTypes.add( functionType );
|
functionTypes.add( functionType );
|
||||||
codeStream.write( END );
|
|
||||||
|
|
||||||
|
WasmOutputStream localsStream = new WasmOutputStream();
|
||||||
|
localsStream.writeVaruint32( locals.size() );
|
||||||
|
for( ValueType valueType : locals ) {
|
||||||
|
localsStream.writeVaruint32( 1 ); // TODO optimize, write the count of same types.
|
||||||
|
localsStream.writeVarint32( valueType.getCode() );
|
||||||
|
}
|
||||||
|
functionsStream.writeVaruint32( localsStream.size() + codeStream.size() + 1 );
|
||||||
|
localsStream.writeTo( functionsStream );
|
||||||
|
codeStream.writeTo( functionsStream );
|
||||||
|
functionsStream.write( END );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -165,7 +202,7 @@ public class BinaryModuleWriter extends ModuleWriter implements InstructionOpcod
|
|||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
protected void writeLoadInt( int idx ) throws IOException {
|
protected void writeLoad( int idx ) throws IOException {
|
||||||
codeStream.write( GET_LOCAL );
|
codeStream.write( GET_LOCAL );
|
||||||
codeStream.writeVaruint32( idx );
|
codeStream.writeVaruint32( idx );
|
||||||
}
|
}
|
||||||
@ -174,7 +211,7 @@ public class BinaryModuleWriter extends ModuleWriter implements InstructionOpcod
|
|||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
protected void writeStoreInt( int idx ) throws IOException {
|
protected void writeStore( int idx ) throws IOException {
|
||||||
codeStream.write( SET_LOCAL );
|
codeStream.write( SET_LOCAL );
|
||||||
codeStream.writeVaruint32( idx );
|
codeStream.writeVaruint32( idx );
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,11 @@ package de.inetsoftware.jwebassembly.module;
|
|||||||
|
|
||||||
import java.io.Closeable;
|
import java.io.Closeable;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.annotation.Nonnegative;
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
|
|
||||||
import de.inetsoftware.classparser.ClassFile;
|
import de.inetsoftware.classparser.ClassFile;
|
||||||
import de.inetsoftware.classparser.Code;
|
import de.inetsoftware.classparser.Code;
|
||||||
@ -32,6 +37,10 @@ import de.inetsoftware.jwebassembly.WasmException;
|
|||||||
*/
|
*/
|
||||||
public abstract class ModuleWriter implements Closeable {
|
public abstract class ModuleWriter implements Closeable {
|
||||||
|
|
||||||
|
private int paramCount;
|
||||||
|
|
||||||
|
private ArrayList<ValueType> locals = new ArrayList<>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Write the content of the class to the
|
* Write the content of the class to the
|
||||||
*
|
*
|
||||||
@ -65,10 +74,11 @@ public abstract class ModuleWriter implements Closeable {
|
|||||||
* if some Java code can't converted
|
* if some Java code can't converted
|
||||||
*/
|
*/
|
||||||
private void writeMethod( MethodInfo method ) throws IOException, WasmException {
|
private void writeMethod( MethodInfo method ) throws IOException, WasmException {
|
||||||
writeMethodStart( method.getName() );
|
|
||||||
writeMethodSignature( method );
|
|
||||||
Code code = method.getCode();
|
Code code = method.getCode();
|
||||||
if( code != null ) {
|
if( code != null ) { // abstract methods and interface methods does not have code
|
||||||
|
writeMethodStart( method.getName() );
|
||||||
|
writeMethodSignature( method );
|
||||||
|
locals.clear();
|
||||||
LineNumberTable lineNumberTable = code.getLineNumberTable();
|
LineNumberTable lineNumberTable = code.getLineNumberTable();
|
||||||
if( lineNumberTable != null ) {
|
if( lineNumberTable != null ) {
|
||||||
int lineNumber;
|
int lineNumber;
|
||||||
@ -85,8 +95,11 @@ public abstract class ModuleWriter implements Closeable {
|
|||||||
CodeInputStream byteCode = code.getByteCode();
|
CodeInputStream byteCode = code.getByteCode();
|
||||||
writeCodeChunk( byteCode, -1 );
|
writeCodeChunk( byteCode, -1 );
|
||||||
}
|
}
|
||||||
|
for( int i = 0; i < paramCount; i++ ) {
|
||||||
|
locals.remove( 0 );
|
||||||
|
}
|
||||||
|
writeMethodFinish( locals );
|
||||||
}
|
}
|
||||||
writeMethodFinish();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -112,7 +125,9 @@ public abstract class ModuleWriter implements Closeable {
|
|||||||
private void writeMethodSignature( MethodInfo method ) throws IOException, WasmException {
|
private void writeMethodSignature( MethodInfo method ) throws IOException, WasmException {
|
||||||
String signature = method.getDescription();
|
String signature = method.getDescription();
|
||||||
String kind = "param";
|
String kind = "param";
|
||||||
|
int paramCount = 0;
|
||||||
for( int i = 1; i < signature.length(); i++ ) {
|
for( int i = 1; i < signature.length(); i++ ) {
|
||||||
|
paramCount++;
|
||||||
String javaType;
|
String javaType;
|
||||||
switch( signature.charAt( i ) ) {
|
switch( signature.charAt( i ) ) {
|
||||||
case '[': // array
|
case '[': // array
|
||||||
@ -142,13 +157,13 @@ public abstract class ModuleWriter implements Closeable {
|
|||||||
case 'V': // void
|
case 'V': // void
|
||||||
continue;
|
continue;
|
||||||
case ')':
|
case ')':
|
||||||
|
this.paramCount = paramCount - 1;
|
||||||
kind = "return";
|
kind = "return";
|
||||||
continue;
|
continue;
|
||||||
default:
|
default:
|
||||||
javaType = signature.substring( i, i + 1 );
|
javaType = signature.substring( i, i + 1 );
|
||||||
}
|
}
|
||||||
Code code = method.getCode();
|
int lineNumber = method.getCode().getFirstLineNr();
|
||||||
int lineNumber = code == null ? -1 : code.getFirstLineNr();
|
|
||||||
throw new WasmException( "Not supported Java data type in method signature: " + javaType, lineNumber );
|
throw new WasmException( "Not supported Java data type in method signature: " + javaType, lineNumber );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -168,10 +183,13 @@ public abstract class ModuleWriter implements Closeable {
|
|||||||
/**
|
/**
|
||||||
* Complete the method
|
* Complete the method
|
||||||
*
|
*
|
||||||
|
* @param locals
|
||||||
|
* a list with types of local variables
|
||||||
|
*
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
* if any I/O error occur
|
* if any I/O error occur
|
||||||
*/
|
*/
|
||||||
protected abstract void writeMethodFinish() throws IOException;
|
protected abstract void writeMethodFinish( List<ValueType> locals ) throws IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Write a chunk of byte code.
|
* Write a chunk of byte code.
|
||||||
@ -192,10 +210,16 @@ public abstract class ModuleWriter implements Closeable {
|
|||||||
writeConstInt( 1 );
|
writeConstInt( 1 );
|
||||||
break;
|
break;
|
||||||
case 26: // iload_0
|
case 26: // iload_0
|
||||||
writeLoadInt( 0 );
|
case 27: // iload_1
|
||||||
|
case 28: // iload_2
|
||||||
|
case 29: // iload_3
|
||||||
|
writeLoadStore( true, ValueType.i32, op - 26 );
|
||||||
break;
|
break;
|
||||||
|
case 59: // istore_0
|
||||||
case 60: // istore_1
|
case 60: // istore_1
|
||||||
writeStoreInt( 1 );
|
case 61: // istore_2
|
||||||
|
case 62: // istore_3
|
||||||
|
writeLoadStore( false, ValueType.i32, op - 59 );
|
||||||
break;
|
break;
|
||||||
case 96: // iadd
|
case 96: // iadd
|
||||||
writeAddInt();
|
writeAddInt();
|
||||||
@ -213,7 +237,7 @@ public abstract class ModuleWriter implements Closeable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Write a const integer value
|
* Write a constant integer value
|
||||||
*
|
*
|
||||||
* @param value
|
* @param value
|
||||||
* the value
|
* the value
|
||||||
@ -222,25 +246,41 @@ public abstract class ModuleWriter implements Closeable {
|
|||||||
*/
|
*/
|
||||||
protected abstract void writeConstInt( int value ) throws IOException;
|
protected abstract void writeConstInt( int value ) throws IOException;
|
||||||
|
|
||||||
/**
|
private void writeLoadStore( boolean load, @Nonnull ValueType valueType, @Nonnegative int idx ) throws WasmException, IOException {
|
||||||
* Write a load integer
|
while( locals.size() <= idx ) {
|
||||||
*
|
locals.add( null );
|
||||||
* @param idx
|
}
|
||||||
* the index of the parameter variable
|
ValueType oldType = locals.get( idx );
|
||||||
* @throws IOException
|
if( oldType != null && oldType != valueType ) {
|
||||||
* if any I/O error occur
|
throw new WasmException( "Redefine local variable type from " + oldType + " to " + valueType, -1 );
|
||||||
*/
|
}
|
||||||
protected abstract void writeLoadInt( int idx ) throws IOException;
|
locals.set( idx, valueType );
|
||||||
|
if( load ) {
|
||||||
|
writeLoad( idx );
|
||||||
|
} else {
|
||||||
|
writeStore( idx );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Write a store integer.
|
* Write a variable load.
|
||||||
*
|
*
|
||||||
* @param idx
|
* @param idx
|
||||||
* the index of the parameter variable
|
* the index of the parameter variable
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
* if any I/O error occur
|
* if any I/O error occur
|
||||||
*/
|
*/
|
||||||
protected abstract void writeStoreInt( int idx ) throws IOException;
|
protected abstract void writeLoad( int idx ) throws IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write a variable store.
|
||||||
|
*
|
||||||
|
* @param idx
|
||||||
|
* the index of the parameter variable
|
||||||
|
* @throws IOException
|
||||||
|
* if any I/O error occur
|
||||||
|
*/
|
||||||
|
protected abstract void writeStore( int idx ) throws IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Write a add operator
|
* Write a add operator
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
package de.inetsoftware.jwebassembly.text;
|
package de.inetsoftware.jwebassembly.text;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import de.inetsoftware.jwebassembly.module.ModuleWriter;
|
import de.inetsoftware.jwebassembly.module.ModuleWriter;
|
||||||
import de.inetsoftware.jwebassembly.module.ValueType;
|
import de.inetsoftware.jwebassembly.module.ValueType;
|
||||||
@ -79,7 +80,7 @@ public class TextModuleWriter extends ModuleWriter {
|
|||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
protected void writeMethodFinish() throws IOException {
|
protected void writeMethodFinish( List<ValueType> locals ) throws IOException {
|
||||||
inset--;
|
inset--;
|
||||||
newline();
|
newline();
|
||||||
output.append( ')' );
|
output.append( ')' );
|
||||||
@ -91,14 +92,14 @@ public class TextModuleWriter extends ModuleWriter {
|
|||||||
@Override
|
@Override
|
||||||
protected void writeConstInt( int value ) throws IOException {
|
protected void writeConstInt( int value ) throws IOException {
|
||||||
newline();
|
newline();
|
||||||
output.append( "i32.const " ).append( Integer.toString( value ));
|
output.append( "i32.const " ).append( Integer.toString( value ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
protected void writeLoadInt( int idx ) throws IOException {
|
protected void writeLoad( int idx ) throws IOException {
|
||||||
newline();
|
newline();
|
||||||
output.append( "get_local " ).append( Integer.toString( idx ) );
|
output.append( "get_local " ).append( Integer.toString( idx ) );
|
||||||
}
|
}
|
||||||
@ -107,7 +108,7 @@ public class TextModuleWriter extends ModuleWriter {
|
|||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
protected void writeStoreInt( int idx ) throws IOException {
|
protected void writeStore( int idx ) throws IOException {
|
||||||
newline();
|
newline();
|
||||||
output.append( "set_local " ).append( Integer.toString( idx ) );
|
output.append( "set_local " ).append( Integer.toString( idx ) );
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user