From e9b7597eda9bfdbf9b38e5c34e259a73c3aa0f23 Mon Sep 17 00:00:00 2001 From: Volker Berlin Date: Sun, 25 Nov 2018 15:11:42 +0100 Subject: [PATCH] Write also missing library functions --- .../jwebassembly/module/FunctionManager.java | 26 +++++++ .../jwebassembly/module/ModuleGenerator.java | 69 ++++++++++++++----- 2 files changed, 79 insertions(+), 16 deletions(-) diff --git a/src/de/inetsoftware/jwebassembly/module/FunctionManager.java b/src/de/inetsoftware/jwebassembly/module/FunctionManager.java index d45c0ee..625beec 100644 --- a/src/de/inetsoftware/jwebassembly/module/FunctionManager.java +++ b/src/de/inetsoftware/jwebassembly/module/FunctionManager.java @@ -17,6 +17,8 @@ package de.inetsoftware.jwebassembly.module; import java.util.HashSet; +import javax.annotation.Nullable; + /** * Manage the required function/methods * @@ -50,4 +52,28 @@ public class FunctionManager { toWriteLater.add( name ); } } + + /** + * Get the first FunctionName that is required but was not written. + * + * @return the FunctionName or null + */ + @Nullable + FunctionName nextWriteLater() { + if( toWriteLater.isEmpty() ) { + return null; + } + return toWriteLater.iterator().next(); + } + + /** + * if the given function is required but was not written. + * + * @param name + * the function name + * @return true, if the function on the to do list + */ + boolean isToWrite( FunctionName name ) { + return toWriteLater.contains( name ); + } } diff --git a/src/de/inetsoftware/jwebassembly/module/ModuleGenerator.java b/src/de/inetsoftware/jwebassembly/module/ModuleGenerator.java index 7f959f0..72de158 100644 --- a/src/de/inetsoftware/jwebassembly/module/ModuleGenerator.java +++ b/src/de/inetsoftware/jwebassembly/module/ModuleGenerator.java @@ -16,6 +16,7 @@ package de.inetsoftware.jwebassembly.module; import java.io.IOException; +import java.io.InputStream; import java.net.URL; import java.net.URLClassLoader; import java.util.List; @@ -102,9 +103,43 @@ public class ModuleGenerator { /** * Finish the code generation. + * + * @throws IOException + * if any I/O error occur */ - public void finish() { - + public void finish() throws IOException { + FunctionName next; + while( (next = functions.nextWriteLater()) != null ) { + InputStream stream = libraries.getResourceAsStream( next.className + ".class" ); + if( stream == null ) { + throw new WasmException( "Missing function: " + next.signatureName, -1 ); + } + ClassFile classFile = new ClassFile( stream ); + iterateMethods( classFile, method -> { + try { + FunctionName name; + Map wat = method.getAnnotation( JWebAssembly.TEXTCODE_ANNOTATION ); + if( wat != null ) { + String signature = (String)wat.get( "signature" ); + if( signature == null ) { + signature = method.getType(); + } + name = new FunctionName( method, signature ); + } else { + name = new FunctionName( method ); + } + if( functions.isToWrite( name ) ) { + writeMethod( method ); + } + } catch (IOException ioex){ + throw WasmException.create( ioex, sourceFile, className, -1 ); + } + } ); + + if( functions.isToWrite( next ) ) { + throw new WasmException( "Missing function: " + next.signatureName, -1 ); + } + } } /** @@ -154,7 +189,7 @@ public class ModuleGenerator { String impoarModule = (String)annotationValues.get( "module" ); String importName = (String)annotationValues.get( "name" ); writer.prepareImport( name, impoarModule, importName ); - writeMethodSignature( method.getType(), null, null ); + writeMethodSignature( name, null, null ); } else { writer.prepareFunction( name ); } @@ -179,28 +214,29 @@ public class ModuleGenerator { } WasmCodeBuilder codeBuilder; Code code = method.getCode(); - String signature; + FunctionName name; if( method.getAnnotation( JWebAssembly.TEXTCODE_ANNOTATION ) != null ) { Map wat = method.getAnnotation( JWebAssembly.TEXTCODE_ANNOTATION ); String watCode = (String)wat.get( "value" ); - signature = (String)wat.get( "signature" ); + String signature = (String)wat.get( "signature" ); if( signature == null ) { signature = method.getType(); } + name = new FunctionName( method, signature ); watParser.parse( watCode, code == null ? -1 : code.getFirstLineNr() ); codeBuilder = watParser; } else if( code != null ) { // abstract methods and interface methods does not have code - signature = method.getType(); + name = new FunctionName( method ); javaCodeBuilder.buildCode( code, !method.getType().endsWith( ")V" ) ); codeBuilder = javaCodeBuilder; } else { return; } - FunctionName name = new FunctionName( method ); writeExport( name, method ); writer.writeMethodStart( name ); functions.writeFunction( name ); - writeMethodSignature( signature, code.getLocalVariableTable(), codeBuilder ); + LocalVariableTable localVariableTable = code == null ? null : code.getLocalVariableTable(); + writeMethodSignature( name, localVariableTable, codeBuilder ); for( WasmInstruction instruction : codeBuilder.getInstructions() ) { if( instruction instanceof WasmCallInstruction ) { @@ -240,7 +276,7 @@ public class ModuleGenerator { /** * Write the parameter and return signatures * - * @param signature + * @param name * the Java signature, typical method.getType(); * @param variables * Java variable table with names of the variables for debugging @@ -251,7 +287,8 @@ public class ModuleGenerator { * @throws WasmException * if some Java code can't converted */ - private void writeMethodSignature( String signature, @Nullable LocalVariableTable variables, WasmCodeBuilder codeBuilder ) throws IOException, WasmException { + private void writeMethodSignature( FunctionName name, @Nullable LocalVariableTable variables, WasmCodeBuilder codeBuilder ) throws IOException, WasmException { + String signature = name.signature; String kind = "param"; int paramCount = 0; ValueType type = null; @@ -260,27 +297,27 @@ public class ModuleGenerator { kind = "result"; continue; } - String name = null; + String paramName = null; if( kind == "param" ) { if( variables != null ) { - name = variables.getPosition( paramCount ).getName(); + paramName = variables.getPosition( paramCount ).getName(); } paramCount++; } type = ValueType.getValueType( signature, i ); if( type != null ) { - writer.writeMethodParam( kind, type, name ); + writer.writeMethodParam( kind, type, paramName ); } } if( codeBuilder != null ) { List localTypes = codeBuilder.getLocalTypes( paramCount ); for( int i = 0; i < localTypes.size(); i++ ) { type = localTypes.get( i ); - String name = null; + String paramName = null; if( variables != null ) { - name = variables.getPosition( paramCount ).getName(); + paramName = variables.getPosition( paramCount ).getName(); } - writer.writeMethodParam( "local", type, name ); + writer.writeMethodParam( "local", type, paramName ); } } writer.writeMethodParamFinish( );