Refactor the writing of sections more object oriented.

This commit is contained in:
Volker Berlin 2018-10-07 21:20:14 +02:00
parent c0c24cb2cc
commit df7cb74bcc
6 changed files with 113 additions and 123 deletions

View File

@ -19,6 +19,7 @@ import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
@ -88,10 +89,10 @@ public class BinaryModuleWriter extends ModuleWriter implements InstructionOpcod
wasm.write( WASM_BINARY_MAGIC );
wasm.writeInt32( WASM_BINARY_VERSION );
writeTypeSection();
writeImportSection();
writeFunctionSection();
writeGlobalSection();
writeSection( SectionType.Type, functionTypes );
writeSection( SectionType.Import, imports.values() );
writeSection( SectionType.Function, functions.values() );
writeSection( SectionType.Global, globals.values() );
writeExportSection();
writeCodeSection();
@ -99,94 +100,24 @@ public class BinaryModuleWriter extends ModuleWriter implements InstructionOpcod
}
/**
* Write the type section to the output. This section contains the signatures of the functions.
* Write a section with list format to the output.
*
* @param type
* the type of the section
* @param entries
* the entries of the section
* @throws IOException
* if any I/O error occur
*/
private void writeTypeSection() throws IOException {
int count = functionTypes.size();
private void writeSection( SectionType type, Collection<? extends SectionEntry> entries ) throws IOException {
int count = entries.size();
if( count > 0 ) {
WasmOutputStream stream = new WasmOutputStream();
stream.writeVaruint32( count );
for( FunctionType type : functionTypes ) {
stream.write( ValueType.func.getCode() );
stream.writeVaruint32( type.params.size() );
for( ValueType valueType : type.params ) {
stream.write( valueType.getCode() );
}
if( type.result == null ) {
stream.writeVaruint32( 0 );
} else {
stream.writeVaruint32( 1 );
stream.write( type.result.getCode() );
}
for( SectionEntry entry : entries ) {
entry.writeSectionEntry( stream );
}
wasm.writeSection( SectionType.Type, stream, null );
}
}
/**
* Write the import section to the output. This section declare all imports.
*
* @throws IOException
* if any I/O error occur
*/
private void writeImportSection() throws IOException {
int count = imports.size();
if( count > 0 ) {
WasmOutputStream stream = new WasmOutputStream();
stream.writeVaruint32( count );
for( ImportFunction importFunction : imports.values() ) {
byte[] bytes = importFunction.module.getBytes( StandardCharsets.UTF_8 );
stream.writeVaruint32( bytes.length );
stream.write( bytes );
bytes = importFunction.name.getBytes( StandardCharsets.UTF_8 );
stream.writeVaruint32( bytes.length );
stream.write( bytes );
stream.writeVaruint32( ExternalKind.Function.ordinal() );
stream.writeVaruint32( importFunction.typeId );
}
wasm.writeSection( SectionType.Import, stream, null );
}
}
/**
* 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 {
int count = functions.size();
if( count > 0 ) {
WasmOutputStream stream = new WasmOutputStream();
stream.writeVaruint32( count );
for( Function func : functions.values() ) {
stream.writeVaruint32( func.typeId );
}
wasm.writeSection( SectionType.Function, stream, null );
}
}
/**
* Write the global section to the output. This section contains a declaring of global (static) variables.
*
* @throws IOException
* if any I/O error occur
*/
private void writeGlobalSection() throws IOException {
int count = globals.size();
if( count > 0 ) {
WasmOutputStream stream = new WasmOutputStream();
stream.writeVaruint32( count );
for( Global var : globals.values() ) {
stream.write( var.type.getCode() );
stream.write( var.mutability ? 1 : 0 );
writeConst( stream, 0, var.type );
stream.writeOpCode( END );
}
wasm.writeSection( SectionType.Global, stream, null );
wasm.writeSection( type, stream, null );
}
}
@ -335,42 +266,7 @@ public class BinaryModuleWriter extends ModuleWriter implements InstructionOpcod
*/
@Override
protected void writeConst( Number value, ValueType valueType ) throws IOException {
writeConst( codeStream, value, valueType );
}
/**
* Write a constant number value
*
* @param codeStream
* the target stream
* @param value
* the value
* @param valueType
* the data type of the number
* @throws IOException
* if any I/O error occur
*/
private static void writeConst( WasmOutputStream codeStream, Number value, ValueType valueType ) throws IOException {
switch( valueType ) {
case i32:
codeStream.writeOpCode( I32_CONST );
codeStream.writeVarint( value.intValue() );
break;
case i64:
codeStream.writeOpCode( I64_CONST );
codeStream.writeVarint( value.longValue() );
break;
case f32:
codeStream.writeOpCode( F32_CONST );
codeStream.writeFloat( value.floatValue() );
break;
case f64:
codeStream.writeOpCode( F64_CONST );
codeStream.writeDouble( value.doubleValue() );
break;
default:
throw new Error( valueType + " " + value );
}
codeStream.writeConst( value, valueType );
}
/**

View File

@ -15,15 +15,24 @@
*/
package de.inetsoftware.jwebassembly.binary;
import java.io.IOException;
/**
* An entry in the function section of the WebAssembly.
*
* @author Volker Berlin
*/
class Function {
class Function extends SectionEntry {
int id;
int typeId;
/**
* {@inheritDoc}
*/
@Override
void writeSectionEntry( WasmOutputStream stream ) throws IOException {
stream.writeVaruint32( this.typeId );
}
}

View File

@ -15,6 +15,7 @@
*/
package de.inetsoftware.jwebassembly.binary;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
@ -26,12 +27,30 @@ import de.inetsoftware.jwebassembly.module.ValueType;
*
* @author Volker Berlin
*/
class FunctionType {
class FunctionType extends SectionEntry {
final List<ValueType> params = new ArrayList<>();
ValueType result; // Java has only one return parameter
/**
* {@inheritDoc}
*/
@Override
void writeSectionEntry( WasmOutputStream stream ) throws IOException {
stream.write( ValueType.func.getCode() );
stream.writeVaruint32( this.params.size() );
for( ValueType valueType : this.params ) {
stream.write( valueType.getCode() );
}
if( this.result == null ) {
stream.writeVaruint32( 0 );
} else {
stream.writeVaruint32( 1 );
stream.write( this.result.getCode() );
}
}
/**
* {@inheritDoc}
*/

View File

@ -15,6 +15,8 @@
*/
package de.inetsoftware.jwebassembly.binary;
import java.io.IOException;
import de.inetsoftware.jwebassembly.module.ValueType;
/**
@ -22,11 +24,22 @@ import de.inetsoftware.jwebassembly.module.ValueType;
*
* @author Volker Berlin
*/
class Global {
class Global extends SectionEntry {
int id;
ValueType type;
boolean mutability;
/**
* {@inheritDoc}
*/
@Override
void writeSectionEntry( WasmOutputStream stream ) throws IOException {
stream.write( this.type.getCode() );
stream.write( this.mutability ? 1 : 0 );
stream.writeConst( 0, this.type );
stream.writeOpCode( InstructionOpcodes.END );
}
}

View File

@ -15,6 +15,9 @@
*/
package de.inetsoftware.jwebassembly.binary;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
/**
* An entry in the import section of the WebAssembly.
*
@ -30,4 +33,19 @@ class ImportFunction extends Function {
this.module = module;
this.name = name;
}
/**
* {@inheritDoc}
*/
@Override
void writeSectionEntry( WasmOutputStream stream ) throws IOException {
byte[] bytes = this.module.getBytes( StandardCharsets.UTF_8 );
stream.writeVaruint32( bytes.length );
stream.write( bytes );
bytes = this.name.getBytes( StandardCharsets.UTF_8 );
stream.writeVaruint32( bytes.length );
stream.write( bytes );
stream.writeVaruint32( ExternalKind.Function.ordinal() );
stream.writeVaruint32( this.typeId );
}
}

View File

@ -23,6 +23,8 @@ import java.nio.charset.StandardCharsets;
import javax.annotation.Nonnegative;
import de.inetsoftware.jwebassembly.module.ValueType;
/**
* @author Volker Berlin
*/
@ -147,6 +149,39 @@ class WasmOutputStream extends FilterOutputStream {
writeInt32( (int)(l >>> 32) );
}
/**
* Write a constant number value
*
* @param value
* the value
* @param valueType
* the data type of the number
* @throws IOException
* if any I/O error occur
*/
void writeConst( Number value, ValueType valueType ) throws IOException {
switch( valueType ) {
case i32:
this.writeOpCode( InstructionOpcodes.I32_CONST );
this.writeVarint( value.intValue() );
break;
case i64:
this.writeOpCode( InstructionOpcodes.I64_CONST );
this.writeVarint( value.longValue() );
break;
case f32:
this.writeOpCode( InstructionOpcodes.F32_CONST );
this.writeFloat( value.floatValue() );
break;
case f64:
this.writeOpCode( InstructionOpcodes.F64_CONST );
this.writeDouble( value.doubleValue() );
break;
default:
throw new Error( valueType + " " + value );
}
}
/**
* Write a section with header and data.
*