Write also missing library functions

This commit is contained in:
Volker Berlin 2018-11-25 15:11:42 +01:00
parent c2683f4576
commit e9b7597eda
2 changed files with 79 additions and 16 deletions

View File

@ -17,6 +17,8 @@ package de.inetsoftware.jwebassembly.module;
import java.util.HashSet; import java.util.HashSet;
import javax.annotation.Nullable;
/** /**
* Manage the required function/methods * Manage the required function/methods
* *
@ -50,4 +52,28 @@ public class FunctionManager {
toWriteLater.add( name ); 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 );
}
} }

View File

@ -16,6 +16,7 @@
package de.inetsoftware.jwebassembly.module; package de.inetsoftware.jwebassembly.module;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream;
import java.net.URL; import java.net.URL;
import java.net.URLClassLoader; import java.net.URLClassLoader;
import java.util.List; import java.util.List;
@ -102,9 +103,43 @@ public class ModuleGenerator {
/** /**
* Finish the code generation. * 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<String, Object> 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 impoarModule = (String)annotationValues.get( "module" );
String importName = (String)annotationValues.get( "name" ); String importName = (String)annotationValues.get( "name" );
writer.prepareImport( name, impoarModule, importName ); writer.prepareImport( name, impoarModule, importName );
writeMethodSignature( method.getType(), null, null ); writeMethodSignature( name, null, null );
} else { } else {
writer.prepareFunction( name ); writer.prepareFunction( name );
} }
@ -179,28 +214,29 @@ public class ModuleGenerator {
} }
WasmCodeBuilder codeBuilder; WasmCodeBuilder codeBuilder;
Code code = method.getCode(); Code code = method.getCode();
String signature; FunctionName name;
if( method.getAnnotation( JWebAssembly.TEXTCODE_ANNOTATION ) != null ) { if( method.getAnnotation( JWebAssembly.TEXTCODE_ANNOTATION ) != null ) {
Map<String, Object> wat = method.getAnnotation( JWebAssembly.TEXTCODE_ANNOTATION ); Map<String, Object> wat = method.getAnnotation( JWebAssembly.TEXTCODE_ANNOTATION );
String watCode = (String)wat.get( "value" ); String watCode = (String)wat.get( "value" );
signature = (String)wat.get( "signature" ); String signature = (String)wat.get( "signature" );
if( signature == null ) { if( signature == null ) {
signature = method.getType(); signature = method.getType();
} }
name = new FunctionName( method, signature );
watParser.parse( watCode, code == null ? -1 : code.getFirstLineNr() ); watParser.parse( watCode, code == null ? -1 : code.getFirstLineNr() );
codeBuilder = watParser; codeBuilder = watParser;
} else if( code != null ) { // abstract methods and interface methods does not have code } 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" ) ); javaCodeBuilder.buildCode( code, !method.getType().endsWith( ")V" ) );
codeBuilder = javaCodeBuilder; codeBuilder = javaCodeBuilder;
} else { } else {
return; return;
} }
FunctionName name = new FunctionName( method );
writeExport( name, method ); writeExport( name, method );
writer.writeMethodStart( name ); writer.writeMethodStart( name );
functions.writeFunction( 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() ) { for( WasmInstruction instruction : codeBuilder.getInstructions() ) {
if( instruction instanceof WasmCallInstruction ) { if( instruction instanceof WasmCallInstruction ) {
@ -240,7 +276,7 @@ public class ModuleGenerator {
/** /**
* Write the parameter and return signatures * Write the parameter and return signatures
* *
* @param signature * @param name
* the Java signature, typical method.getType(); * the Java signature, typical method.getType();
* @param variables * @param variables
* Java variable table with names of the variables for debugging * Java variable table with names of the variables for debugging
@ -251,7 +287,8 @@ public class ModuleGenerator {
* @throws WasmException * @throws WasmException
* if some Java code can't converted * 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"; String kind = "param";
int paramCount = 0; int paramCount = 0;
ValueType type = null; ValueType type = null;
@ -260,27 +297,27 @@ public class ModuleGenerator {
kind = "result"; kind = "result";
continue; continue;
} }
String name = null; String paramName = null;
if( kind == "param" ) { if( kind == "param" ) {
if( variables != null ) { if( variables != null ) {
name = variables.getPosition( paramCount ).getName(); paramName = variables.getPosition( paramCount ).getName();
} }
paramCount++; paramCount++;
} }
type = ValueType.getValueType( signature, i ); type = ValueType.getValueType( signature, i );
if( type != null ) { if( type != null ) {
writer.writeMethodParam( kind, type, name ); writer.writeMethodParam( kind, type, paramName );
} }
} }
if( codeBuilder != null ) { if( codeBuilder != null ) {
List<ValueType> localTypes = codeBuilder.getLocalTypes( paramCount ); List<ValueType> localTypes = codeBuilder.getLocalTypes( paramCount );
for( int i = 0; i < localTypes.size(); i++ ) { for( int i = 0; i < localTypes.size(); i++ ) {
type = localTypes.get( i ); type = localTypes.get( i );
String name = null; String paramName = null;
if( variables != 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( ); writer.writeMethodParamFinish( );