diff --git a/src/de/inetsoftware/jwebassembly/binary/BinaryModuleWriter.java b/src/de/inetsoftware/jwebassembly/binary/BinaryModuleWriter.java index 5fac4f0..0f1f434 100644 --- a/src/de/inetsoftware/jwebassembly/binary/BinaryModuleWriter.java +++ b/src/de/inetsoftware/jwebassembly/binary/BinaryModuleWriter.java @@ -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 ); + } } diff --git a/src/de/inetsoftware/jwebassembly/binary/InstructionOpcodes.java b/src/de/inetsoftware/jwebassembly/binary/InstructionOpcodes.java index c24fbb4..571a13a 100644 --- a/src/de/inetsoftware/jwebassembly/binary/InstructionOpcodes.java +++ b/src/de/inetsoftware/jwebassembly/binary/InstructionOpcodes.java @@ -37,6 +37,8 @@ interface InstructionOpcodes { static final int RETURN = 0x0F; + static final int CALL = 0x10; + // === Variable access =========== static final int GET_LOCAL = 0x20; diff --git a/src/de/inetsoftware/jwebassembly/module/ModuleWriter.java b/src/de/inetsoftware/jwebassembly/module/ModuleWriter.java index f5bdcb8..cdbee2b 100644 --- a/src/de/inetsoftware/jwebassembly/module/ModuleWriter.java +++ b/src/de/inetsoftware/jwebassembly/module/ModuleWriter.java @@ -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 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; } diff --git a/src/de/inetsoftware/jwebassembly/text/TextModuleWriter.java b/src/de/inetsoftware/jwebassembly/text/TextModuleWriter.java index 2825e6d..28a25f2 100644 --- a/src/de/inetsoftware/jwebassembly/text/TextModuleWriter.java +++ b/src/de/inetsoftware/jwebassembly/text/TextModuleWriter.java @@ -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 ); + } } diff --git a/test/de/inetsoftware/jwebassembly/samples/FunctionParameters.java b/test/de/inetsoftware/jwebassembly/samples/FunctionParameters.java index cd6b1e2..18cb067 100644 --- a/test/de/inetsoftware/jwebassembly/samples/FunctionParameters.java +++ b/test/de/inetsoftware/jwebassembly/samples/FunctionParameters.java @@ -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; + } +} diff --git a/test/de/inetsoftware/jwebassembly/samples/FunctionParameters.wat b/test/de/inetsoftware/jwebassembly/samples/FunctionParameters.wat index ec0f0ff..3b7fc49 100644 --- a/test/de/inetsoftware/jwebassembly/samples/FunctionParameters.wat +++ b/test/de/inetsoftware/jwebassembly/samples/FunctionParameters.wat @@ -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 ) ) \ No newline at end of file