Add support for invoke static method calls

This commit is contained in:
Volker Berlin 2018-03-24 12:33:56 +01:00
parent c548779c76
commit 4836024e4e
6 changed files with 123 additions and 51 deletions

View File

@ -25,6 +25,7 @@ import java.util.Map;
import javax.annotation.Nullable;
import de.inetsoftware.classparser.MethodInfo;
import de.inetsoftware.jwebassembly.WasmException;
import de.inetsoftware.jwebassembly.module.ModuleWriter;
import de.inetsoftware.jwebassembly.module.NumericOperator;
@ -176,19 +177,30 @@ public class BinaryModuleWriter extends ModuleWriter implements InstructionOpcod
/**
* {@inheritDoc}
*/
@Override
protected void writeExport( String methodName, String exportName ) throws IOException {
exports.put( exportName, methodName );
protected void prepareMethod( MethodInfo method ) throws WasmException {
String methodName = method.getName();
String className = method.getDeclaringClassFile().getThisClass().getName();
String fullName = className + '.' + methodName;
String signatureName = fullName + method.getDescription();
Function function = new Function();
function.id = functions.size();
functions.put( signatureName, function );
}
/**
* {@inheritDoc}
*/
@Override
protected void writeMethodStart( String name ) throws IOException {
function = new Function();
function.id = functions.size();
functions.put( name, function );
protected void writeExport( String signatureName, String methodName, String exportName ) throws IOException {
exports.put( exportName, signatureName );
}
/**
* {@inheritDoc}
*/
@Override
protected void writeMethodStart( String signatureName, String name ) throws IOException {
function = functions.get( signatureName );
functionType = new FunctionType();
codeStream.reset();
}
@ -458,4 +470,17 @@ public class BinaryModuleWriter extends ModuleWriter implements InstructionOpcod
protected void writeReturn() throws IOException {
codeStream.write( RETURN );
}
/**
* {@inheritDoc}
*/
@Override
protected void writeFunctionCall( String name ) throws IOException {
codeStream.write( CALL );
Function func = functions.get( name );
if( func == null ) {
throw new WasmException( "Call to unknown function: " + name, null, -1 );
}
codeStream.writeVaruint32( func.id );
}
}

View File

@ -37,6 +37,8 @@ interface InstructionOpcodes {
static final int RETURN = 0x0F;
static final int CALL = 0x10;
// === Variable access ===========
static final int GET_LOCAL = 0x20;

View File

@ -105,8 +105,8 @@ public abstract class ModuleWriter implements Closeable {
* @throws WasmException
* if some Java code can't converted
*/
private void prepareMethod( MethodInfo method ) throws WasmException {
protected void prepareMethod( MethodInfo method ) throws WasmException {
// Nothing
}
/**
@ -121,9 +121,12 @@ public abstract class ModuleWriter implements Closeable {
try {
Code code = method.getCode();
if( code != null ) { // abstract methods and interface methods does not have code
String methodName = method.getName(); // TODO naming conversion rule
writeExport( methodName, method );
writeMethodStart( methodName );
String methodName = method.getName();
String className = method.getDeclaringClassFile().getThisClass().getName();
String fullName = className + '.' + methodName;
String signatureName = fullName + method.getDescription();
writeExport( signatureName, fullName, method );
writeMethodStart( signatureName, fullName );
writeMethodSignature( method );
locals.clear();
localTable = code.getLocalVariableTable();
@ -156,48 +159,55 @@ public abstract class ModuleWriter implements Closeable {
/**
* Look for a Export annotation and if there write an export directive.
*
* @param signatureName
* the full name with signature
* @param methodName
* the normalized method name
* @param method
* the moethod
*
* @throws IOException
* if any IOException occur
*/
private void writeExport( String methodName, MethodInfo method ) throws IOException {
private void writeExport( String signatureName, String methodName, MethodInfo method ) throws IOException {
Annotations annotations = method.getRuntimeInvisibleAnnotations();
if( annotations != null ) {
Map<String,Object> export = annotations.get( "org.webassembly.annotation.Export" );
if( export != null ) {
String exportName = (String)export.get( "name" );
if( exportName == null ) {
exportName = methodName;
exportName = method.getName(); // TODO naming conversion rule if no name was set
}
writeExport( methodName, exportName );
writeExport( signatureName, methodName, exportName );
}
}
}
/**
* Write an export directive
*
* @param signatureName
* the full name with signature
* @param methodName
* the method name
* @param exportName
* the export name, if null then the same like the method name
*
* @throws IOException
* if any I/O error occur
*/
protected abstract void writeExport( String methodName, String exportName ) throws IOException;
protected abstract void writeExport( String signatureName, String methodName, String exportName ) throws IOException;
/**
* Write the method header.
*
* @param signatureName
* the full name with signature
* @param name
* the method name
*
* @throws IOException
* if any I/O error occur
*/
protected abstract void writeMethodStart( String name ) throws IOException;
protected abstract void writeMethodStart( String signatureName, String name ) throws IOException;
/**
* Write the parameter and return signatures
@ -490,6 +500,11 @@ public abstract class ModuleWriter implements Closeable {
case 177: // return void
writeReturn();
break;
case 184: // invokestatic
idx = byteCode.readUnsignedShort();
ConstantRef method = (ConstantRef)constantPool.get( idx );
writeFunctionCall( method.getConstantClass().getName() + '.' + method.getName() + method.getType() );
break;
default:
throw new WasmException( "Unimplemented byte code operation: " + op, sourceFile, lineNumber );
}
@ -617,7 +632,9 @@ public abstract class ModuleWriter implements Closeable {
/**
* Write a add operator
* @param numOp TODO
*
* @param numOp
* the numeric operation
* @param valueType
* the type of the parameters
*
@ -643,4 +660,14 @@ public abstract class ModuleWriter implements Closeable {
* if any I/O error occur
*/
protected abstract void writeReturn() throws IOException;
/**
* Write a call to a function.
*
* @param name
* the full qualified method name
* @throws IOException
* if any I/O error occur
*/
protected abstract void writeFunctionCall( String name ) throws IOException;
}

View File

@ -67,7 +67,7 @@ public class TextModuleWriter extends ModuleWriter {
* {@inheritDoc}
*/
@Override
protected void writeExport( String methodName, String exportName ) throws IOException {
protected void writeExport( String signatureName, String methodName, String exportName ) throws IOException {
newline( output );
output.append( "(export \"" ).append( exportName ).append( "\" (func $" ).append( methodName ).append( "))" );
}
@ -76,7 +76,7 @@ public class TextModuleWriter extends ModuleWriter {
* {@inheritDoc}
*/
@Override
protected void writeMethodStart( String name ) throws IOException {
protected void writeMethodStart( String signatureName, String name ) throws IOException {
newline( output );
output.append( "(func $" );
output.append( name );
@ -211,4 +211,14 @@ public class TextModuleWriter extends ModuleWriter {
output.append( ' ' );
}
}
/**
* {@inheritDoc}
*/
@Override
protected void writeFunctionCall( String name ) throws IOException {
newline( methodOutput );
name = name.substring( 0, name.indexOf( '(' ) );
methodOutput.append( "call $" ).append( name );
}
}

View File

@ -1,28 +1,31 @@
/*
* Copyright 2017 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.samples;
/**
*
* @author Volker Berlin
*
*/
public class FunctionParameters {
void singleInt( int a ) {
}
}
/*
* Copyright 2017 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.samples;
import org.webassembly.annotation.Export;
/**
*
* @author Volker Berlin
*
*/
public class FunctionParameters {
@Export(name="abc")
static void singleInt( int a ) {
int b = a + 1;
}
}

View File

@ -1,5 +1,10 @@
(module
(func $singleInt (param i32)
(export "abc" (func $de/inetsoftware/jwebassembly/samples/FunctionParameters.singleInt))
(func $de/inetsoftware/jwebassembly/samples/FunctionParameters.singleInt (param i32) (local i32)
get_local 0
i32.const 1
i32.add
set_local 1
return
)
)