mirror of
https://github.com/i-net-software/JWebAssembly.git
synced 2025-03-15 18:44:47 +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 boolean callIndirect;
|
||||
|
||||
/**
|
||||
* Create new instance.
|
||||
*
|
||||
@ -123,10 +125,12 @@ public class BinaryModuleWriter extends ModuleWriter implements InstructionOpcod
|
||||
writeSection( SectionType.Type, functionTypes );
|
||||
writeSection( SectionType.Import, imports.values() );
|
||||
writeSection( SectionType.Function, functions.values() );
|
||||
writeTableSection();
|
||||
writeMemorySection();
|
||||
writeSection( SectionType.Global, globals.values() );
|
||||
writeEventSection();
|
||||
writeExportSection();
|
||||
writeElementSection();
|
||||
writeCodeSection();
|
||||
writeDataSection();
|
||||
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.
|
||||
*
|
||||
@ -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.
|
||||
*
|
||||
@ -941,6 +997,18 @@ public class BinaryModuleWriter extends ModuleWriter implements InstructionOpcod
|
||||
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.
|
||||
*
|
||||
|
@ -224,6 +224,16 @@ public abstract class ModuleWriter implements Closeable {
|
||||
*/
|
||||
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
|
||||
*
|
||||
|
@ -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.
|
||||
*/
|
||||
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;
|
||||
|
@ -67,6 +67,12 @@ public class TextModuleWriter extends ModuleWriter {
|
||||
|
||||
private boolean useExceptions;
|
||||
|
||||
private int importCount;
|
||||
|
||||
private int functionCount;
|
||||
|
||||
private boolean callIndirect;
|
||||
|
||||
/**
|
||||
* Create a new instance.
|
||||
*
|
||||
@ -94,6 +100,18 @@ public class TextModuleWriter extends ModuleWriter {
|
||||
public void close() throws IOException {
|
||||
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();
|
||||
if( dataSize > 0 ) {
|
||||
int pages = (dataSize + 0xFFFF) / 0x10000;
|
||||
@ -166,6 +184,7 @@ public class TextModuleWriter extends ModuleWriter {
|
||||
newline( methodOutput );
|
||||
methodOutput.append( "(import \"" ).append( importModule ).append( "\" \"" ).append( importName ).append( "\" (func $" ).append( normalizeName( name ) );
|
||||
isImport = true;
|
||||
importCount++;
|
||||
}
|
||||
}
|
||||
|
||||
@ -215,6 +234,7 @@ public class TextModuleWriter extends ModuleWriter {
|
||||
methodOutput.append( normalizeName( name ) );
|
||||
inset++;
|
||||
methodParamNames.clear();
|
||||
functionCount++;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -504,6 +524,16 @@ public class TextModuleWriter extends ModuleWriter {
|
||||
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}
|
||||
*/
|
||||
|
Loading…
x
Reference in New Issue
Block a user