diff --git a/src/de/inetsoftware/jwebassembly/binary/BinaryModuleWriter.java b/src/de/inetsoftware/jwebassembly/binary/BinaryModuleWriter.java index 9a7f322..b2f2b4b 100644 --- a/src/de/inetsoftware/jwebassembly/binary/BinaryModuleWriter.java +++ b/src/de/inetsoftware/jwebassembly/binary/BinaryModuleWriter.java @@ -63,7 +63,7 @@ public class BinaryModuleWriter extends ModuleWriter implements InstructionOpcod private Map functions = new LinkedHashMap<>(); - private List locals = new ArrayList<>(); + private List locals = new ArrayList<>(); private Map globals = new LinkedHashMap<>(); @@ -73,7 +73,7 @@ public class BinaryModuleWriter extends ModuleWriter implements InstructionOpcod private Function function; - private FunctionType functionType; + private FunctionTypeEntry functionType; /** * Create new instance. @@ -233,7 +233,7 @@ public class BinaryModuleWriter extends ModuleWriter implements InstructionOpcod @Override protected int writeStruct( String typeName, List fields ) throws IOException { int typeId = functionTypes.size(); - functionTypes.add( new StructType( fields ) ); + functionTypes.add( new StructTypeEntry( fields ) ); return typeId; } @@ -245,7 +245,7 @@ public class BinaryModuleWriter extends ModuleWriter implements InstructionOpcod ImportFunction importFunction; function = importFunction = new ImportFunction(importModule, importName); imports.put( name.signatureName, importFunction ); - functionType = new FunctionType(); + functionType = new FunctionTypeEntry(); } /** @@ -278,7 +278,7 @@ public class BinaryModuleWriter extends ModuleWriter implements InstructionOpcod @Override protected void writeMethodStart( FunctionName name ) throws IOException { function = getFunction( name ); - functionType = new FunctionType(); + functionType = new FunctionTypeEntry(); codeStream.reset(); locals.clear(); } @@ -287,7 +287,7 @@ public class BinaryModuleWriter extends ModuleWriter implements InstructionOpcod * {@inheritDoc} */ @Override - protected void writeMethodParam( String kind, ValueType valueType, @Nullable String name ) throws IOException { + protected void writeMethodParam( String kind, StorageType valueType, @Nullable String name ) throws IOException { switch( kind ) { case "param": functionType.params.add( valueType ); @@ -327,7 +327,7 @@ public class BinaryModuleWriter extends ModuleWriter implements InstructionOpcod protected void writeMethodFinish() throws IOException { WasmOutputStream localsStream = new WasmOutputStream(); localsStream.writeVaruint32( locals.size() ); - for( ValueType valueType : locals ) { + for( StorageType valueType : locals ) { localsStream.writeVaruint32( 1 ); // TODO optimize, write the count of same types. localsStream.writeValueType( valueType ); } diff --git a/src/de/inetsoftware/jwebassembly/binary/FunctionType.java b/src/de/inetsoftware/jwebassembly/binary/FunctionTypeEntry.java similarity index 83% rename from src/de/inetsoftware/jwebassembly/binary/FunctionType.java rename to src/de/inetsoftware/jwebassembly/binary/FunctionTypeEntry.java index bfa8433..0a2fa67 100644 --- a/src/de/inetsoftware/jwebassembly/binary/FunctionType.java +++ b/src/de/inetsoftware/jwebassembly/binary/FunctionTypeEntry.java @@ -19,6 +19,7 @@ import java.io.IOException; import java.util.ArrayList; import java.util.List; +import de.inetsoftware.jwebassembly.wasm.StorageType; import de.inetsoftware.jwebassembly.wasm.ValueType; /** @@ -26,11 +27,11 @@ import de.inetsoftware.jwebassembly.wasm.ValueType; * * @author Volker Berlin */ -class FunctionType extends TypeEntry { +class FunctionTypeEntry extends TypeEntry { - final List params = new ArrayList<>(); + final List params = new ArrayList<>(); - final List results = new ArrayList<>(); + final List results = new ArrayList<>(); /** * {@inheritDoc} @@ -46,11 +47,11 @@ class FunctionType extends TypeEntry { @Override void writeSectionEntryDetails( WasmOutputStream stream ) throws IOException { stream.writeVaruint32( this.params.size() ); - for( ValueType valueType : this.params ) { + for( StorageType valueType : this.params ) { stream.writeValueType( valueType ); } stream.writeVaruint32( this.results.size() ); - for( ValueType valueType : this.results ) { + for( StorageType valueType : this.results ) { stream.writeValueType( valueType ); } } @@ -74,7 +75,7 @@ class FunctionType extends TypeEntry { if( obj == null || obj.getClass() != getClass() ) { return false; } - FunctionType type = (FunctionType)obj; + FunctionTypeEntry type = (FunctionTypeEntry)obj; return params.equals( type.params ) && results.equals( type.results ); } } diff --git a/src/de/inetsoftware/jwebassembly/binary/StructType.java b/src/de/inetsoftware/jwebassembly/binary/StructTypeEntry.java similarity index 93% rename from src/de/inetsoftware/jwebassembly/binary/StructType.java rename to src/de/inetsoftware/jwebassembly/binary/StructTypeEntry.java index 5e80c07..3964d7d 100644 --- a/src/de/inetsoftware/jwebassembly/binary/StructType.java +++ b/src/de/inetsoftware/jwebassembly/binary/StructTypeEntry.java @@ -26,7 +26,7 @@ import de.inetsoftware.jwebassembly.wasm.ValueType; * * @author Volker Berlin */ -class StructType extends TypeEntry { +class StructTypeEntry extends TypeEntry { private final List fields; @@ -36,7 +36,7 @@ class StructType extends TypeEntry { * @param fields * the fields of the struct */ - StructType( List fields ) { + StructTypeEntry( List fields ) { this.fields = fields; } @@ -79,7 +79,7 @@ class StructType extends TypeEntry { if( obj == null || obj.getClass() != getClass() ) { return false; } - StructType type = (StructType)obj; + StructTypeEntry type = (StructTypeEntry)obj; return fields.equals( type.fields ); } } diff --git a/src/de/inetsoftware/jwebassembly/module/ModuleGenerator.java b/src/de/inetsoftware/jwebassembly/module/ModuleGenerator.java index 776dde5..4b9a950 100644 --- a/src/de/inetsoftware/jwebassembly/module/ModuleGenerator.java +++ b/src/de/inetsoftware/jwebassembly/module/ModuleGenerator.java @@ -151,26 +151,43 @@ public class ModuleGenerator { String name = instruction.getTypeName(); if( name != null ) { StructType type = types.valueOf( name ); - if( type.getCode() == Integer.MIN_VALUE ) { - String className = name; - InputStream stream = libraries.getResourceAsStream( className + ".class" ); - if( stream == null ) { - throw new WasmException( "Missing class: " + className, -1 ); - } - ClassFile classFile = new ClassFile( stream ); - ArrayList list = new ArrayList<>(); - FieldInfo[] fields = classFile.getFields(); - for( FieldInfo field : fields ) { - if( field.isStatic() ) { - continue; - } - StorageType fieldtype = new ValueTypeParser( field.getType() ).next(); - list.add( new NamedStorageType( fieldtype, field.getName() ) ); - } - int id = writer.writeStruct( className, list ); - types.useType( type, id ); - } instruction.setType( type ); + if( type.getCode() == Integer.MAX_VALUE ) { + writeStructType( type ); + } + } + } + + /** + * Write the struct type + * + * @param type + * the type + * @throws IOException + * if any I/O error occur + */ + private void writeStructType( StructType type ) throws IOException { + String className = type.getName(); + InputStream stream = libraries.getResourceAsStream( className + ".class" ); + if( stream == null ) { + throw new WasmException( "Missing class: " + className, -1 ); + } + ClassFile classFile = new ClassFile( stream ); + ArrayList list = new ArrayList<>(); + FieldInfo[] fields = classFile.getFields(); + for( FieldInfo field : fields ) { + if( field.isStatic() ) { + continue; + } + StorageType fieldtype = new ValueTypeParser( field.getType(), types ).next(); + list.add( new NamedStorageType( fieldtype, field.getName() ) ); + } + int id = writer.writeStruct( className, list ); + types.useType( type, id ); + for( NamedStorageType namedType : list ) { + if( namedType.type.getCode() == Integer.MAX_VALUE ) { + writeStructType( (StructType)namedType.type ); + } } } @@ -338,7 +355,7 @@ public class ModuleGenerator { writer.writeMethodParam( "param", ValueType.anyref, "this" ); } ValueTypeParser parser = new ValueTypeParser( signature ); - ValueType type; + StorageType type; for( String kind : new String[] {"param","result"}) { while( (type = parser.next()) != null ) { String paramName = null; diff --git a/src/de/inetsoftware/jwebassembly/module/ModuleWriter.java b/src/de/inetsoftware/jwebassembly/module/ModuleWriter.java index 0deb980..2ca6db8 100644 --- a/src/de/inetsoftware/jwebassembly/module/ModuleWriter.java +++ b/src/de/inetsoftware/jwebassembly/module/ModuleWriter.java @@ -107,7 +107,7 @@ public abstract class ModuleWriter implements Closeable { * @throws IOException * if any I/O error occur */ - protected abstract void writeMethodParam( String kind, ValueType valueType, @Nullable String name ) throws IOException; + protected abstract void writeMethodParam( String kind, StorageType valueType, @Nullable String name ) throws IOException; /** * Finish the function parameter. diff --git a/src/de/inetsoftware/jwebassembly/module/TypeManager.java b/src/de/inetsoftware/jwebassembly/module/TypeManager.java index cf25cc5..d7e2990 100644 --- a/src/de/inetsoftware/jwebassembly/module/TypeManager.java +++ b/src/de/inetsoftware/jwebassembly/module/TypeManager.java @@ -29,7 +29,7 @@ import de.inetsoftware.jwebassembly.wasm.StorageType; * * @author Volker Berlin */ -class TypeManager { +public class TypeManager { private final Map map = new LinkedHashMap<>(); @@ -62,10 +62,10 @@ class TypeManager { * the type name * @return the struct type */ - StructType valueOf( String name ) { + public StructType valueOf( String name ) { StructType type = map.get( name ); if( type == null ) { - type = new StructType(); + type = new StructType( name ); map.put( name, type ); } return type; @@ -78,7 +78,19 @@ class TypeManager { */ static class StructType implements StorageType { - private int code = Integer.MIN_VALUE; + private final String name; + + private int code = Integer.MAX_VALUE; + + /** + * Create a reference to type + * + * @param name + * the Java class name + */ + StructType( String name ) { + this.name = name; + } /** * {@inheritDoc} @@ -87,5 +99,21 @@ class TypeManager { public int getCode() { return code; } + + /** + * Get the name of the Java type + * @return the name + */ + public String getName() { + return name; + } + + /** + * {@inheritDoc} + */ + @Override + public String toString() { + return "$" + name; + } } } diff --git a/src/de/inetsoftware/jwebassembly/module/WasmCallInstruction.java b/src/de/inetsoftware/jwebassembly/module/WasmCallInstruction.java index e9783ab..0781c12 100644 --- a/src/de/inetsoftware/jwebassembly/module/WasmCallInstruction.java +++ b/src/de/inetsoftware/jwebassembly/module/WasmCallInstruction.java @@ -1,5 +1,5 @@ /* - Copyright 2018 Volker Berlin (i-net software) + Copyright 2018 - 2019 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. @@ -108,9 +108,9 @@ class WasmCallInstruction extends WasmInstruction { while( parser.next() != null ) { paramCount++; } - valueType = parser.next(); + valueType = (ValueType)parser.next(); ValueType type; - while( (type = parser.next()) != null ) { + while( (type = (ValueType)parser.next()) != null ) { valueType = type; paramCount--; } diff --git a/src/de/inetsoftware/jwebassembly/text/TextModuleWriter.java b/src/de/inetsoftware/jwebassembly/text/TextModuleWriter.java index b6534e4..8d49640 100644 --- a/src/de/inetsoftware/jwebassembly/text/TextModuleWriter.java +++ b/src/de/inetsoftware/jwebassembly/text/TextModuleWriter.java @@ -100,7 +100,14 @@ public class TextModuleWriter extends ModuleWriter { if( debugNames && field.name != null ) { output.append( " $" ).append( field.name ); } - output.append( " (mut " ).append( field.type.toString() ).append( "))" ); + output.append( " (mut " ); + StorageType type = field.type; + if( type.getCode() < 0 ) { + output.append( type.toString() ); + } else { + output.append( "(ref " ).append( type.toString() ).append( ')' ); + } + output.append( "))" ); } inset--; newline( output ); @@ -145,7 +152,7 @@ public class TextModuleWriter extends ModuleWriter { * {@inheritDoc} */ @Override - protected void writeMethodParam( String kind, ValueType valueType, @Nullable String name ) throws IOException { + protected void writeMethodParam( String kind, StorageType valueType, @Nullable String name ) throws IOException { methodOutput.append( " (" ).append( kind ); if( debugNames && name != null ) { methodOutput.append( " $" ).append( name ); diff --git a/src/de/inetsoftware/jwebassembly/wasm/ValueType.java b/src/de/inetsoftware/jwebassembly/wasm/ValueType.java index e0609c6..1b5a398 100644 --- a/src/de/inetsoftware/jwebassembly/wasm/ValueType.java +++ b/src/de/inetsoftware/jwebassembly/wasm/ValueType.java @@ -1,5 +1,5 @@ /* - * Copyright 2017 - 2018 Volker Berlin (i-net software) + * Copyright 2017 - 2019 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. @@ -61,7 +61,7 @@ public enum ValueType implements StorageType { * @return the value type */ public static ValueType getValueType( String javaSignature ) { - return new ValueTypeParser( javaSignature ).next(); + return (ValueType)new ValueTypeParser( javaSignature ).next(); } } diff --git a/src/de/inetsoftware/jwebassembly/wasm/ValueTypeParser.java b/src/de/inetsoftware/jwebassembly/wasm/ValueTypeParser.java index 90455ac..c527f4c 100644 --- a/src/de/inetsoftware/jwebassembly/wasm/ValueTypeParser.java +++ b/src/de/inetsoftware/jwebassembly/wasm/ValueTypeParser.java @@ -1,5 +1,5 @@ /* - * Copyright 2018 Volker Berlin (i-net software) + * Copyright 2018 - 2019 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. @@ -16,6 +16,7 @@ package de.inetsoftware.jwebassembly.wasm; import de.inetsoftware.jwebassembly.WasmException; +import de.inetsoftware.jwebassembly.module.TypeManager; /** * Parser for a Java signature. This can be a method signature or a signature of a field. @@ -27,14 +28,29 @@ public class ValueTypeParser { private int idx; + private TypeManager types; + /** * Create a new parser. * * @param javaSignature - * the Jav signature + * the Java signature */ public ValueTypeParser( String javaSignature ) { - sig = javaSignature; + this( javaSignature, null ); + } + + /** + * Create a new parser. + * + * @param javaSignature + * the Java signature + * @param types + * the optional type manager + */ + public ValueTypeParser( String javaSignature, TypeManager types ) { + this.sig = javaSignature; + this.types = types; if( javaSignature.startsWith( "(" ) ) { idx++; } @@ -45,7 +61,7 @@ public class ValueTypeParser { * * @return next type or null */ - public ValueType next() { + public StorageType next() { if( idx >= sig.length() ) { return null; } @@ -56,8 +72,10 @@ public class ValueTypeParser { next(); return ValueType.anyref; case 'L': - idx = sig.indexOf( ';', idx ) + 1; - return ValueType.anyref; + int idx2 = sig.indexOf( ';', idx ); + String name = sig.substring( idx, idx2 ); + idx = idx2 + 1; + return types == null ? ValueType.anyref : types.valueOf( name ); case 'Z': // boolean case 'B': // byte case 'C': // char