mirror of
https://github.com/i-net-software/JWebAssembly.git
synced 2025-03-25 07:27:52 +01:00
prepare the using of call_indirect
This commit is contained in:
parent
8e439eb83e
commit
4e98efeb5d
@ -87,6 +87,8 @@ public class BinaryModuleWriter extends ModuleWriter implements InstructionOpcod
|
|||||||
|
|
||||||
private String javaSourceFile;
|
private String javaSourceFile;
|
||||||
|
|
||||||
|
private boolean callIndirect;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create new instance.
|
* Create new instance.
|
||||||
*
|
*
|
||||||
@ -123,10 +125,12 @@ public class BinaryModuleWriter extends ModuleWriter implements InstructionOpcod
|
|||||||
writeSection( SectionType.Type, functionTypes );
|
writeSection( SectionType.Type, functionTypes );
|
||||||
writeSection( SectionType.Import, imports.values() );
|
writeSection( SectionType.Import, imports.values() );
|
||||||
writeSection( SectionType.Function, functions.values() );
|
writeSection( SectionType.Function, functions.values() );
|
||||||
|
writeTableSection();
|
||||||
writeMemorySection();
|
writeMemorySection();
|
||||||
writeSection( SectionType.Global, globals.values() );
|
writeSection( SectionType.Global, globals.values() );
|
||||||
writeEventSection();
|
writeEventSection();
|
||||||
writeExportSection();
|
writeExportSection();
|
||||||
|
writeElementSection();
|
||||||
writeCodeSection();
|
writeCodeSection();
|
||||||
writeDataSection();
|
writeDataSection();
|
||||||
writeDebugNames();
|
writeDebugNames();
|
||||||
@ -158,6 +162,31 @@ public class BinaryModuleWriter extends ModuleWriter implements InstructionOpcod
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write the table section. It declare the space for the element section.
|
||||||
|
*
|
||||||
|
* @throws IOException
|
||||||
|
* if any I/O error occur
|
||||||
|
*/
|
||||||
|
private void writeTableSection() throws IOException {
|
||||||
|
if( !callIndirect ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int elemCount = imports.size() + functions.size();
|
||||||
|
WasmOutputStream stream = new WasmOutputStream();
|
||||||
|
int count = 1;
|
||||||
|
stream.writeVaruint32( count ); // count of tables
|
||||||
|
for( int i = 0; i < count; i++ ) {
|
||||||
|
stream.writeValueType( ValueType.anyfunc ); // the type of elements
|
||||||
|
stream.writeVaruint32( 1 ); // flags; 1-maximum is available, 0-no maximum value available
|
||||||
|
stream.writeVaruint32( elemCount ); // initial length
|
||||||
|
stream.writeVaruint32( elemCount ); // maximum length
|
||||||
|
}
|
||||||
|
|
||||||
|
wasm.writeSection( SectionType.Table, stream );
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Write the memory section.
|
* Write the memory section.
|
||||||
*
|
*
|
||||||
@ -220,6 +249,33 @@ public class BinaryModuleWriter extends ModuleWriter implements InstructionOpcod
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write element section. This section create a matching between direct and indirect function call IDs.
|
||||||
|
*
|
||||||
|
* @throws IOException
|
||||||
|
* if any I/O error occur
|
||||||
|
*/
|
||||||
|
private void writeElementSection() throws IOException {
|
||||||
|
if( !callIndirect ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int elemCount = imports.size() + functions.size();
|
||||||
|
WasmOutputStream stream = new WasmOutputStream();
|
||||||
|
stream.writeVaruint32( 1 ); // count of element segments to follow
|
||||||
|
|
||||||
|
// element_segment
|
||||||
|
stream.writeVaruint32( 0 ); // the table index (0 in the MVP)
|
||||||
|
stream.writeConst( 0, ValueType.i32 ); // the offset on which the elements start
|
||||||
|
stream.writeOpCode( END ); // end of offset instruction
|
||||||
|
stream.writeVaruint32( elemCount );
|
||||||
|
for( int i = 0; i < elemCount; i++ ) {
|
||||||
|
stream.writeVaruint32( i ); // we use a 1:1 matching between direct function call numbers and indrect function numbers because the most functions will be indirect
|
||||||
|
}
|
||||||
|
|
||||||
|
wasm.writeSection( SectionType.Element, stream );
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Write the code section to the output. This section contains the byte code.
|
* Write the code section to the output. This section contains the byte code.
|
||||||
*
|
*
|
||||||
@ -941,6 +997,18 @@ public class BinaryModuleWriter extends ModuleWriter implements InstructionOpcod
|
|||||||
codeStream.writeVaruint32( func.id );
|
codeStream.writeVaruint32( func.id );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected void writeFunctionCallIndirect( FunctionName name ) throws IOException {
|
||||||
|
callIndirect = true;
|
||||||
|
Function func = getFunction( name );
|
||||||
|
codeStream.writeOpCode( CALL_INDIRECT );
|
||||||
|
codeStream.writeVaruint32( func.typeId );
|
||||||
|
codeStream.writeVaruint32( 0 ); // table 0
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the function object for the name. If not exists then it will be created.
|
* Get the function object for the name. If not exists then it will be created.
|
||||||
*
|
*
|
||||||
|
@ -224,6 +224,16 @@ public abstract class ModuleWriter implements Closeable {
|
|||||||
*/
|
*/
|
||||||
protected abstract void writeFunctionCall( FunctionName name ) throws IOException;
|
protected abstract void writeFunctionCall( FunctionName name ) throws IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write a call indirect to a function.
|
||||||
|
*
|
||||||
|
* @param name
|
||||||
|
* the function name
|
||||||
|
* @throws IOException
|
||||||
|
* if any I/O error occur
|
||||||
|
*/
|
||||||
|
protected abstract void writeFunctionCallIndirect( FunctionName name ) throws IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Write a block/branch code
|
* Write a block/branch code
|
||||||
*
|
*
|
||||||
|
@ -0,0 +1,115 @@
|
|||||||
|
/*
|
||||||
|
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 java.util.Iterator;
|
||||||
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
|
|
||||||
|
import de.inetsoftware.jwebassembly.wasm.AnyType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* WasmInstruction for a function call.
|
||||||
|
*
|
||||||
|
* @author Volker Berlin
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
class WasmCallIndirectInstruction extends WasmInstruction {
|
||||||
|
|
||||||
|
private AnyType valueType;
|
||||||
|
|
||||||
|
private final FunctionName name;
|
||||||
|
|
||||||
|
private int paramCount = -1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create an instance of a function call instruction
|
||||||
|
*
|
||||||
|
* @param name
|
||||||
|
* the function name that should be called
|
||||||
|
* @param javaCodePos
|
||||||
|
* the code position/offset in the Java method
|
||||||
|
* @param lineNumber
|
||||||
|
* the line number in the Java source code
|
||||||
|
*/
|
||||||
|
WasmCallIndirectInstruction( FunctionName name, int javaCodePos, int lineNumber ) {
|
||||||
|
super( javaCodePos, lineNumber );
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
Type getType() {
|
||||||
|
return Type.CallIndirect;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the function name that should be called
|
||||||
|
*
|
||||||
|
* @return the name
|
||||||
|
*/
|
||||||
|
@Nonnull
|
||||||
|
FunctionName getFunctionName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public void writeTo( @Nonnull ModuleWriter writer ) throws IOException {
|
||||||
|
writer.writeFunctionCallIndirect( name );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
AnyType getPushValueType() {
|
||||||
|
countParams();
|
||||||
|
return valueType;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
int getPopCount() {
|
||||||
|
countParams();
|
||||||
|
return paramCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Count the parameters in the signature
|
||||||
|
*/
|
||||||
|
private void countParams() {
|
||||||
|
if( paramCount >= 0 ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Iterator<AnyType> parser = name.getSignature();
|
||||||
|
paramCount = 1;
|
||||||
|
while( parser.next() != null ) {
|
||||||
|
paramCount++;
|
||||||
|
}
|
||||||
|
valueType = parser.next();
|
||||||
|
while( parser.hasNext() ) {
|
||||||
|
valueType = parser.next();
|
||||||
|
paramCount--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -35,7 +35,7 @@ abstract class WasmInstruction {
|
|||||||
* Type of instruction to faster differ as with instanceof.
|
* Type of instruction to faster differ as with instanceof.
|
||||||
*/
|
*/
|
||||||
static enum Type {
|
static enum Type {
|
||||||
Const, Convert, Local, Global, Block, Numeric, Nop, Call, Array, Struct;
|
Const, Convert, Local, Global, Block, Numeric, Nop, Call, CallIndirect, Array, Struct;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int javaCodePos;
|
private int javaCodePos;
|
||||||
|
@ -67,6 +67,12 @@ public class TextModuleWriter extends ModuleWriter {
|
|||||||
|
|
||||||
private boolean useExceptions;
|
private boolean useExceptions;
|
||||||
|
|
||||||
|
private int importCount;
|
||||||
|
|
||||||
|
private int functionCount;
|
||||||
|
|
||||||
|
private boolean callIndirect;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new instance.
|
* Create a new instance.
|
||||||
*
|
*
|
||||||
@ -94,6 +100,18 @@ public class TextModuleWriter extends ModuleWriter {
|
|||||||
public void close() throws IOException {
|
public void close() throws IOException {
|
||||||
output.append( methodOutput );
|
output.append( methodOutput );
|
||||||
|
|
||||||
|
if( callIndirect ) {
|
||||||
|
int count = importCount + functionCount;
|
||||||
|
String countStr = Integer.toString( count );
|
||||||
|
output.append( "(table " ).append( countStr ).append( ' ' ).append( countStr ).append( " anyfunc)" );
|
||||||
|
newline( output );
|
||||||
|
output.append( "(elem (i32.const 0) " );
|
||||||
|
for( int i = 0; i < count; i++ ) {
|
||||||
|
output.append( Integer.toString( i ) ).append( ' ' );
|
||||||
|
}
|
||||||
|
output.append( ')' );
|
||||||
|
}
|
||||||
|
|
||||||
int dataSize = dataStream.size();
|
int dataSize = dataStream.size();
|
||||||
if( dataSize > 0 ) {
|
if( dataSize > 0 ) {
|
||||||
int pages = (dataSize + 0xFFFF) / 0x10000;
|
int pages = (dataSize + 0xFFFF) / 0x10000;
|
||||||
@ -166,6 +184,7 @@ public class TextModuleWriter extends ModuleWriter {
|
|||||||
newline( methodOutput );
|
newline( methodOutput );
|
||||||
methodOutput.append( "(import \"" ).append( importModule ).append( "\" \"" ).append( importName ).append( "\" (func $" ).append( normalizeName( name ) );
|
methodOutput.append( "(import \"" ).append( importModule ).append( "\" \"" ).append( importName ).append( "\" (func $" ).append( normalizeName( name ) );
|
||||||
isImport = true;
|
isImport = true;
|
||||||
|
importCount++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -215,6 +234,7 @@ public class TextModuleWriter extends ModuleWriter {
|
|||||||
methodOutput.append( normalizeName( name ) );
|
methodOutput.append( normalizeName( name ) );
|
||||||
inset++;
|
inset++;
|
||||||
methodParamNames.clear();
|
methodParamNames.clear();
|
||||||
|
functionCount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -504,6 +524,16 @@ public class TextModuleWriter extends ModuleWriter {
|
|||||||
methodOutput.append( "call $" ).append( normalizeName( name ) );
|
methodOutput.append( "call $" ).append( normalizeName( name ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected void writeFunctionCallIndirect( FunctionName name ) throws IOException {
|
||||||
|
callIndirect = true;
|
||||||
|
newline( methodOutput );
|
||||||
|
methodOutput.append( "call_indirect $" ).append( normalizeName( name ) );
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
|
Loading…
x
Reference in New Issue
Block a user