diff --git a/src/de/inetsoftware/jwebassembly/binary/BinaryModuleWriter.java b/src/de/inetsoftware/jwebassembly/binary/BinaryModuleWriter.java index df15c7e..c5c9d4b 100644 --- a/src/de/inetsoftware/jwebassembly/binary/BinaryModuleWriter.java +++ b/src/de/inetsoftware/jwebassembly/binary/BinaryModuleWriter.java @@ -28,7 +28,6 @@ import java.util.Map.Entry; import javax.annotation.Nonnull; import javax.annotation.Nullable; -import de.inetsoftware.classparser.Member; import de.inetsoftware.jwebassembly.JWebAssembly; import de.inetsoftware.jwebassembly.module.FunctionName; import de.inetsoftware.jwebassembly.module.ModuleWriter; @@ -509,12 +508,12 @@ public class BinaryModuleWriter extends ModuleWriter implements InstructionOpcod * {@inheritDoc} */ @Override - protected void writeGlobalAccess( boolean load, FunctionName name, Member ref ) throws IOException { + protected void writeGlobalAccess( boolean load, FunctionName name, AnyType type ) throws IOException { Global var = globals.get( name.fullName ); if( var == null ) { // if not declared then create a definition in the global section var = new Global(); var.id = globals.size(); - var.type = ValueType.getValueType( ref.getType() ); + var.type = type; var.mutability = true; globals.put( name.fullName, var ); } @@ -523,6 +522,14 @@ public class BinaryModuleWriter extends ModuleWriter implements InstructionOpcod codeStream.writeVaruint32( var.id ); } + /** + * {@inheritDoc} + */ + @Override + protected void writeDefaultValue( AnyType type ) throws IOException { + codeStream.writeDefaultValue( type ); + } + /** * {@inheritDoc} */ diff --git a/src/de/inetsoftware/jwebassembly/binary/Global.java b/src/de/inetsoftware/jwebassembly/binary/Global.java index 40db471..a64f2d5 100644 --- a/src/de/inetsoftware/jwebassembly/binary/Global.java +++ b/src/de/inetsoftware/jwebassembly/binary/Global.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. @@ -17,7 +17,7 @@ package de.inetsoftware.jwebassembly.binary; import java.io.IOException; -import de.inetsoftware.jwebassembly.wasm.ValueType; +import de.inetsoftware.jwebassembly.wasm.AnyType; /** * An entry in the global section of the WebAssembly. @@ -28,7 +28,7 @@ class Global extends SectionEntry { int id; - ValueType type; + AnyType type; boolean mutability; @@ -37,9 +37,9 @@ class Global extends SectionEntry { */ @Override void writeSectionEntry( WasmOutputStream stream ) throws IOException { - stream.writeValueType( this.type ); + stream.writeRefValueType( this.type ); stream.write( this.mutability ? 1 : 0 ); - stream.writeConst( 0, this.type ); + stream.writeDefaultValue( this.type ); stream.writeOpCode( InstructionOpcodes.END ); } } diff --git a/src/de/inetsoftware/jwebassembly/binary/WasmOutputStream.java b/src/de/inetsoftware/jwebassembly/binary/WasmOutputStream.java index 39f5817..c245431 100644 --- a/src/de/inetsoftware/jwebassembly/binary/WasmOutputStream.java +++ b/src/de/inetsoftware/jwebassembly/binary/WasmOutputStream.java @@ -24,6 +24,7 @@ import java.nio.charset.StandardCharsets; import javax.annotation.Nonnegative; import javax.annotation.Nonnull; +import de.inetsoftware.jwebassembly.WasmException; import de.inetsoftware.jwebassembly.wasm.AnyType; import de.inetsoftware.jwebassembly.wasm.ValueType; @@ -111,6 +112,39 @@ class WasmOutputStream extends FilterOutputStream { writeValueType( type ); } + /** + * Write the default/initial value for a type. + * + * @param type + * the type + * @throws IOException + * if an I/O error occurs. + */ + public void writeDefaultValue( AnyType type ) throws IOException { + if( type.getCode() < 0 ) { + ValueType valueType = (ValueType)type; + switch( valueType ) { + case i32: + case i64: + case f32: + case f64: + writeConst( 0, valueType ); + break; + case i8: + case i16: + writeConst( 0, ValueType.i32 ); + break; + case anyref: + writeOpCode( InstructionOpcodes.REF_NULL ); + break; + default: + throw new WasmException( "Not supported storage type: " + type, -1 ); + } + } else { + writeOpCode( InstructionOpcodes.REF_NULL ); + } + } + /** * Write a integer little endian (ever 4 bytes) * diff --git a/src/de/inetsoftware/jwebassembly/module/ModuleGenerator.java b/src/de/inetsoftware/jwebassembly/module/ModuleGenerator.java index 0be54e8..63b7374 100644 --- a/src/de/inetsoftware/jwebassembly/module/ModuleGenerator.java +++ b/src/de/inetsoftware/jwebassembly/module/ModuleGenerator.java @@ -415,28 +415,7 @@ public class ModuleGenerator { if( instr.getOperator() == StructOperator.NEW_DEFAULT ) { List list = instr.getStructType().getFields(); for( NamedStorageType storageType : list ) { - if( storageType.getType().getCode() < 0 ) { - ValueType type = (ValueType)storageType.getType(); - switch( type ) { - case i32: - case i64: - case f32: - case f64: - writer.writeConst( 0, type ); - break; - case i8: - case i16: - writer.writeConst( 0, ValueType.i32 ); - break; - case anyref: - writer.writeStructOperator( StructOperator.NULL, null, null, -1 ); - break; - default: - throw new WasmException( "Not supported storage type: " + type, instruction.getLineNumber() ); - } - } else { - writer.writeStructOperator( StructOperator.NULL, null, null, -1 ); - } + writer.writeDefaultValue( storageType.getType() ); } } break; diff --git a/src/de/inetsoftware/jwebassembly/module/ModuleWriter.java b/src/de/inetsoftware/jwebassembly/module/ModuleWriter.java index 4061fa1..da2da4e 100644 --- a/src/de/inetsoftware/jwebassembly/module/ModuleWriter.java +++ b/src/de/inetsoftware/jwebassembly/module/ModuleWriter.java @@ -22,7 +22,6 @@ import java.util.List; import javax.annotation.Nonnull; import javax.annotation.Nullable; -import de.inetsoftware.classparser.Member; import de.inetsoftware.jwebassembly.wasm.AnyType; import de.inetsoftware.jwebassembly.wasm.ArrayOperator; import de.inetsoftware.jwebassembly.wasm.NamedStorageType; @@ -174,14 +173,23 @@ public abstract class ModuleWriter implements Closeable { * true: if load or GET * @param name * the variable name - * @param ref - * the definition of the variable + * @param type + * the type of the variable * * @throws IOException * if any I/O error occur */ - protected abstract void writeGlobalAccess( boolean load, FunctionName name, Member ref ) throws IOException; + protected abstract void writeGlobalAccess( boolean load, FunctionName name, AnyType type ) throws IOException; + /** + * Write the default/initial value for a type. + * + * @param type + * the type + * @throws IOException + * if an I/O error occurs. + */ + protected abstract void writeDefaultValue( AnyType type ) throws IOException; /** * Write a add operator diff --git a/src/de/inetsoftware/jwebassembly/module/WasmCodeBuilder.java b/src/de/inetsoftware/jwebassembly/module/WasmCodeBuilder.java index 0c4ee27..6deb603 100644 --- a/src/de/inetsoftware/jwebassembly/module/WasmCodeBuilder.java +++ b/src/de/inetsoftware/jwebassembly/module/WasmCodeBuilder.java @@ -32,6 +32,7 @@ import de.inetsoftware.jwebassembly.wasm.NamedStorageType; import de.inetsoftware.jwebassembly.wasm.NumericOperator; import de.inetsoftware.jwebassembly.wasm.StructOperator; import de.inetsoftware.jwebassembly.wasm.ValueType; +import de.inetsoftware.jwebassembly.wasm.ValueTypeParser; import de.inetsoftware.jwebassembly.wasm.WasmBlockOperator; /** @@ -193,7 +194,9 @@ public abstract class WasmCodeBuilder { * the line number in the Java source code */ protected void addGlobalInstruction( boolean load, Member ref, int javaCodePos, int lineNumber ) { - instructions.add( new WasmGlobalInstruction( load, ref, javaCodePos, lineNumber ) ); + FunctionName name = new FunctionName( ref ); + AnyType type = new ValueTypeParser( ref.getType(), types ).next(); + instructions.add( new WasmGlobalInstruction( load, name, type, javaCodePos, lineNumber ) ); } /** diff --git a/src/de/inetsoftware/jwebassembly/module/WasmGlobalInstruction.java b/src/de/inetsoftware/jwebassembly/module/WasmGlobalInstruction.java index 5876dfc..749137b 100644 --- a/src/de/inetsoftware/jwebassembly/module/WasmGlobalInstruction.java +++ b/src/de/inetsoftware/jwebassembly/module/WasmGlobalInstruction.java @@ -34,24 +34,29 @@ class WasmGlobalInstruction extends WasmInstruction { private boolean load; - private Member ref; + private FunctionName name; + + private AnyType type; /** * Create an instance of a load/store instruction * * @param load * true: if load or GET - * @param ref - * reference to a static field + * @param name + * the name of the static field + * @param type + * the type of the static field * @param javaCodePos * the code position/offset in the Java method * @param lineNumber * the line number in the Java source code */ - WasmGlobalInstruction( boolean load, Member ref, int javaCodePos, int lineNumber ) { + WasmGlobalInstruction( boolean load, FunctionName name, AnyType type, int javaCodePos, int lineNumber ) { super( javaCodePos, lineNumber ); this.load = load; - this.ref = ref; + this.name = name; + this.type = type; } /** @@ -66,15 +71,14 @@ class WasmGlobalInstruction extends WasmInstruction { * {@inheritDoc} */ public void writeTo( @Nonnull ModuleWriter writer ) throws IOException { - FunctionName name = new FunctionName( ref ); - writer.writeGlobalAccess( load, name, ref ); + writer.writeGlobalAccess( load, name, type ); } /** * {@inheritDoc} */ AnyType getPushValueType() { - return load ? ValueType.getValueType( ref.getType() ) : null; + return load ? type : null; } /** diff --git a/src/de/inetsoftware/jwebassembly/text/TextModuleWriter.java b/src/de/inetsoftware/jwebassembly/text/TextModuleWriter.java index 465da3c..bb3f29e 100644 --- a/src/de/inetsoftware/jwebassembly/text/TextModuleWriter.java +++ b/src/de/inetsoftware/jwebassembly/text/TextModuleWriter.java @@ -24,8 +24,8 @@ import java.util.List; import javax.annotation.Nonnull; import javax.annotation.Nullable; -import de.inetsoftware.classparser.Member; import de.inetsoftware.jwebassembly.JWebAssembly; +import de.inetsoftware.jwebassembly.WasmException; import de.inetsoftware.jwebassembly.module.FunctionName; import de.inetsoftware.jwebassembly.module.ModuleWriter; import de.inetsoftware.jwebassembly.module.ValueTypeConvertion; @@ -113,12 +113,7 @@ public class TextModuleWriter extends ModuleWriter { output.append( " $" ).append( typeName ).append( '.' ).append( field.getName() ); } output.append( " (mut " ); - AnyType type = field.getType(); - if( type.getCode() < 0 ) { - output.append( type.toString() ); - } else { - output.append( "(ref " ).append( normalizeName( type.toString() ) ).append( ')' ); - } + writeTypeName( output, field.getType() ); output.append( "))" ); } inset--; @@ -203,6 +198,24 @@ public class TextModuleWriter extends ModuleWriter { methodParamNames.clear(); } + /** + * Write the name of a type. + * + * @param output + * the target + * @param type + * the type + * @throws IOException + * if any I/O error occur + */ + private void writeTypeName( Appendable output, AnyType type ) throws IOException { + if( type.getCode() < 0 ) { + output.append( type.toString() ); + } else { + output.append( "(ref " ).append( normalizeName( type.toString() ) ).append( ')' ); + } + } + /** * {@inheritDoc} */ @@ -218,11 +231,7 @@ public class TextModuleWriter extends ModuleWriter { } } methodOutput.append( ' ' ); - if( valueType.getCode() < 0 ) { - methodOutput.append( valueType ); - } else { - methodOutput.append( "(ref " ).append( normalizeName( valueType.toString() ) ).append( ')' ); - } + writeTypeName( methodOutput, valueType ); methodOutput.append( ')' ); } @@ -294,19 +303,66 @@ public class TextModuleWriter extends ModuleWriter { * {@inheritDoc} */ @Override - protected void writeGlobalAccess( boolean load, FunctionName name, Member ref ) throws IOException { + protected void writeGlobalAccess( boolean load, FunctionName name, AnyType type ) throws IOException { String fullName = normalizeName( name ); if( !globals.contains( fullName ) ) { // declare global variable if not already declared. output.append( "\n " ); - String type = ValueType.getValueType( ref.getType() ).toString(); - output.append( "(global $" ).append( fullName ).append( " (mut " ).append( type ).append( ") (" ).append( type ).append( ".const 0))" ); + output.append( "(global $" ).append( fullName ).append( " (mut " ); + writeTypeName( output, type ); + output.append( ')' ); + writeDefaultValue( output, type ); + output.append( ')' ); globals.add( fullName ); } newline( methodOutput ); methodOutput.append( load ? "global.get $" : "global.set $" ).append( fullName ); } + /** + * {@inheritDoc} + */ + @Override + protected void writeDefaultValue( AnyType type ) throws IOException { + newline( methodOutput ); + writeDefaultValue( methodOutput, type ); + } + + /** + * Write the default/initial value for type. + * + * @param output + * the target + * @param type + * the type + * @throws IOException + * if an I/O error occurs. + */ + private static void writeDefaultValue( Appendable output, AnyType type ) throws IOException { + if( type.getCode() < 0 ) { + ValueType valueType = (ValueType)type; + switch( valueType ) { + case i32: + case i64: + case f32: + case f64: + output.append( " (" ).append( type.toString() ).append( ".const 0)" ); + break; + case i8: + case i16: + writeDefaultValue( output, ValueType.i32 ); + break; + case anyref: + output.append( "(ref.null)" ); + break; + default: + throw new WasmException( "Not supported storage type: " + type, -1 ); + } + } else { + output.append( "(ref.null)" ); + } + } + /** * {@inheritDoc} */