write methods with Export annotation as exported.

This commit is contained in:
Volker Berlin 2017-03-31 20:43:57 +02:00
parent ec93b799b9
commit 7add526da1
3 changed files with 769 additions and 688 deletions

View File

@ -17,6 +17,7 @@ package de.inetsoftware.jwebassembly.binary;
import java.io.IOException; import java.io.IOException;
import java.io.OutputStream; import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
@ -46,6 +47,8 @@ public class BinaryModuleWriter extends ModuleWriter implements InstructionOpcod
private Map<String, Function> functions = new LinkedHashMap<>(); private Map<String, Function> functions = new LinkedHashMap<>();
private Map<String, String> exports = new LinkedHashMap<>();
private Function function; private Function function;
private FunctionType functionType; private FunctionType functionType;
@ -72,6 +75,7 @@ public class BinaryModuleWriter extends ModuleWriter implements InstructionOpcod
writeTypeSection(); writeTypeSection();
writeFunctionSection(); writeFunctionSection();
writeExportSection();
writeCodeSection(); writeCodeSection();
wasm.close(); wasm.close();
@ -123,6 +127,30 @@ public class BinaryModuleWriter extends ModuleWriter implements InstructionOpcod
} }
} }
/**
* Write the export section to the output. This section contains a mapping from the external index to the type signature index.
*
* @throws IOException
* if any I/O error occur
*/
private void writeExportSection() throws IOException {
int count = exports.size();
if( count > 0 ) {
WasmOutputStream stream = new WasmOutputStream();
stream.writeVaruint32( count );
for( Map.Entry<String,String> entry : exports.entrySet() ) {
String exportName = entry.getKey();
byte[] bytes = exportName.getBytes( StandardCharsets.UTF_8 );
stream.writeVaruint32( bytes.length );
stream.write( bytes );
stream.writeVaruint32( ExternalKind.Function.ordinal() );
int id = functions.get( entry.getValue() ).id;
stream.writeVaruint32( id );
}
wasm.writeSection( SectionType.Export, stream, null );
}
}
/** /**
* Write the code section to the output. This section contains the byte code. * Write the code section to the output. This section contains the byte code.
* *
@ -140,6 +168,14 @@ public class BinaryModuleWriter extends ModuleWriter implements InstructionOpcod
wasm.writeSection( SectionType.Code, stream, null ); wasm.writeSection( SectionType.Code, stream, null );
} }
/**
* {@inheritDoc}
*/
@Override
protected void writeExport( String methodName, String exportName ) throws IOException {
exports.put( exportName, methodName );
}
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */

View File

@ -19,10 +19,12 @@ import java.io.Closeable;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map;
import javax.annotation.Nonnegative; import javax.annotation.Nonnegative;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import de.inetsoftware.classparser.Annotations;
import de.inetsoftware.classparser.ClassFile; import de.inetsoftware.classparser.ClassFile;
import de.inetsoftware.classparser.Code; import de.inetsoftware.classparser.Code;
import de.inetsoftware.classparser.CodeInputStream; import de.inetsoftware.classparser.CodeInputStream;
@ -76,7 +78,9 @@ public abstract class ModuleWriter implements Closeable {
private void writeMethod( MethodInfo method ) throws IOException, WasmException { private void writeMethod( MethodInfo method ) throws IOException, WasmException {
Code code = method.getCode(); Code code = method.getCode();
if( code != null ) { // abstract methods and interface methods does not have code if( code != null ) { // abstract methods and interface methods does not have code
writeMethodStart( method.getName() ); String methodName = method.getName(); // TODO naming conversion rule
writeExport( methodName, method );
writeMethodStart( methodName );
writeMethodSignature( method ); writeMethodSignature( method );
locals.clear(); locals.clear();
LineNumberTable lineNumberTable = code.getLineNumberTable(); LineNumberTable lineNumberTable = code.getLineNumberTable();
@ -102,6 +106,38 @@ public abstract class ModuleWriter implements Closeable {
} }
} }
/**
* Look for a Export annotation and if there write an export directive.
* @param methodName
* @param method
* @throws IOException
*/
private void writeExport( 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;
}
writeExport( methodName, exportName );
}
}
}
/**
* Write an export directive
*
* @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;
/** /**
* Write the method header. * Write the method header.
* *

View File

@ -59,6 +59,15 @@ public class TextModuleWriter extends ModuleWriter {
output.append( ')' ); output.append( ')' );
} }
/**
* {@inheritDoc}
*/
@Override
protected void writeExport( String methodName, String exportName ) throws IOException {
newline( output );
output.append( "(export \"" ).append( exportName ).append( "\" (func $" ).append( methodName ).append( "))" );
}
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */