diff --git a/src/de/inetsoftware/jwebassembly/binary/BinaryModuleWriter.java b/src/de/inetsoftware/jwebassembly/binary/BinaryModuleWriter.java index d1bbf8a..5e905aa 100644 --- a/src/de/inetsoftware/jwebassembly/binary/BinaryModuleWriter.java +++ b/src/de/inetsoftware/jwebassembly/binary/BinaryModuleWriter.java @@ -93,16 +93,16 @@ public class BinaryModuleWriter extends ModuleWriter implements InstructionOpcod WasmOutputStream stream = new WasmOutputStream(); stream.writeVaruint32( count ); for( FunctionType type : functionTypes ) { - stream.writeVarint32( ValueType.func.getCode() ); + stream.writeVarint( ValueType.func.getCode() ); stream.writeVaruint32( type.params.size() ); for( ValueType valueType : type.params ) { - stream.writeVarint32( valueType.getCode() ); + stream.writeVarint( valueType.getCode() ); } if( type.result == null ) { stream.writeVaruint32( 0 ); } else { stream.writeVaruint32( 1 ); - stream.writeVarint32( type.result.getCode() ); + stream.writeVarint( type.result.getCode() ); } } wasm.writeSection( SectionType.Type, stream, null ); @@ -217,7 +217,7 @@ public class BinaryModuleWriter extends ModuleWriter implements InstructionOpcod localsStream.writeVaruint32( locals.size() ); for( ValueType valueType : locals ) { localsStream.writeVaruint32( 1 ); // TODO optimize, write the count of same types. - localsStream.writeVarint32( valueType.getCode() ); + localsStream.writeVarint( valueType.getCode() ); } functionsStream.writeVaruint32( localsStream.size() + codeStream.size() + 1 ); localsStream.writeTo( functionsStream ); @@ -231,7 +231,16 @@ public class BinaryModuleWriter extends ModuleWriter implements InstructionOpcod @Override protected void writeConstInt( int value ) throws IOException { codeStream.write( I32_CONST ); - codeStream.writeVarint32( value ); + codeStream.writeVarint( value ); + } + + /** + * {@inheritDoc} + */ + @Override + protected void writeConstLong( long value ) throws IOException { + codeStream.write( I64_CONST ); + codeStream.writeVarint( value ); } /** diff --git a/src/de/inetsoftware/jwebassembly/binary/WasmOutputStream.java b/src/de/inetsoftware/jwebassembly/binary/WasmOutputStream.java index ecf82dc..36772fa 100644 --- a/src/de/inetsoftware/jwebassembly/binary/WasmOutputStream.java +++ b/src/de/inetsoftware/jwebassembly/binary/WasmOutputStream.java @@ -1,166 +1,166 @@ -/* - * Copyright 2017 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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package de.inetsoftware.jwebassembly.binary; - -import java.io.ByteArrayOutputStream; -import java.io.FilterOutputStream; -import java.io.IOException; -import java.io.OutputStream; -import java.nio.charset.StandardCharsets; - -import javax.annotation.Nonnegative; - -/** - * @author Volker Berlin - */ -class WasmOutputStream extends FilterOutputStream { - - /** - * Create a in memory stream. - */ - WasmOutputStream() { - super( new ByteArrayOutputStream() ); - } - - /** - * Create a wrapped stream. - * - * @param output - * the target of data - */ - WasmOutputStream( OutputStream output ) { - super( output ); - } - - /** - * Write a integer little endian (ever 4 bytes) - * - * @param value - * the value - * @throws IOException - * if an I/O error occurs. - */ - void writeInt32( int value ) throws IOException { - write( (value >>> 0) & 0xFF ); - write( (value >>> 8) & 0xFF ); - write( (value >>> 16) & 0xFF ); - write( (value >>> 24) & 0xFF ); - } - - /** - * Write an unsigned integer. - * - * @param value - * the value - * @throws IOException - * if an I/O error occurs. - */ - void writeVaruint32( @Nonnegative int value ) throws IOException { - if( value < 0 ) { - throw new IOException( "Invalid negative value" ); - } - do { - int b = value & 0x7F; // low 7 bits - value >>= 7; - if( value != 0 ) { /* more bytes to come */ - b |= 0x80; - } - write( b ); - } while( value != 0 ); - } - - /** - * Write an integer value. - * - * @param value - * the value - * @throws IOException - * if an I/O error occurs. - */ - void writeVarint32( int value ) throws IOException { - while( true ) { - int b = value & 0x7F; - value >>= 7; - - /* sign bit of byte is second high order bit (0x40) */ - if( (value == 0 && (b & 0x40) == 0) || (value == -1 && (b & 0x40) != 0) ) { - write( b ); - return; - } else { - write( b | 0x80 ); - } - } - } - - /** - * Write a section with header and data. - * - * @param type - * the name of the section - * @param data - * the data of the section - * @param name - * the name, must be set if the id == 0 - * @throws IOException - * if any I/O error occur - */ - void writeSection( SectionType type, WasmOutputStream data, String name ) throws IOException { - ByteArrayOutputStream baos = (ByteArrayOutputStream)data.out; - int size = baos.size(); - if( size == 0 ) { - return; - } - writeVaruint32( type.ordinal() ); - writeVaruint32( size ); - if( type == SectionType.Custom ) { - byte[] bytes = name.getBytes( StandardCharsets.ISO_8859_1 ); - writeVaruint32( bytes.length ); - write( bytes ); - } - baos.writeTo( this ); - } - - /** - * Write the data of this stream to the output. Work only for in memory stream. - * - * @param output - * the target - * @throws IOException - * if any I/O error occur - */ - void writeTo( OutputStream output ) throws IOException { - ByteArrayOutputStream baos = (ByteArrayOutputStream)out; - baos.writeTo( output ); - } - - /** - * The count of bytes in the stream. Work only for in memory stream. - * - * @return the data size - */ - int size() { - ByteArrayOutputStream baos = (ByteArrayOutputStream)out; - return baos.size(); - } - - /** - * Reset the stream. Work only for in memory stream. - */ - void reset() { - ByteArrayOutputStream baos = (ByteArrayOutputStream)out; - baos.reset(); - } -} +/* + * Copyright 2017 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package de.inetsoftware.jwebassembly.binary; + +import java.io.ByteArrayOutputStream; +import java.io.FilterOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.nio.charset.StandardCharsets; + +import javax.annotation.Nonnegative; + +/** + * @author Volker Berlin + */ +class WasmOutputStream extends FilterOutputStream { + + /** + * Create a in memory stream. + */ + WasmOutputStream() { + super( new ByteArrayOutputStream() ); + } + + /** + * Create a wrapped stream. + * + * @param output + * the target of data + */ + WasmOutputStream( OutputStream output ) { + super( output ); + } + + /** + * Write a integer little endian (ever 4 bytes) + * + * @param value + * the value + * @throws IOException + * if an I/O error occurs. + */ + void writeInt32( int value ) throws IOException { + write( (value >>> 0) & 0xFF ); + write( (value >>> 8) & 0xFF ); + write( (value >>> 16) & 0xFF ); + write( (value >>> 24) & 0xFF ); + } + + /** + * Write an unsigned integer. + * + * @param value + * the value + * @throws IOException + * if an I/O error occurs. + */ + void writeVaruint32( @Nonnegative int value ) throws IOException { + if( value < 0 ) { + throw new IOException( "Invalid negative value" ); + } + do { + int b = value & 0x7F; // low 7 bits + value >>= 7; + if( value != 0 ) { /* more bytes to come */ + b |= 0x80; + } + write( b ); + } while( value != 0 ); + } + + /** + * Write an integer value. + * + * @param value + * the value + * @throws IOException + * if an I/O error occurs. + */ + void writeVarint( long value ) throws IOException { + while( true ) { + int b = (int)value & 0x7F; + value >>= 7; + + /* sign bit of byte is second high order bit (0x40) */ + if( (value == 0 && (b & 0x40) == 0) || (value == -1 && (b & 0x40) != 0) ) { + write( b ); + return; + } else { + write( b | 0x80 ); + } + } + } + + /** + * Write a section with header and data. + * + * @param type + * the name of the section + * @param data + * the data of the section + * @param name + * the name, must be set if the id == 0 + * @throws IOException + * if any I/O error occur + */ + void writeSection( SectionType type, WasmOutputStream data, String name ) throws IOException { + ByteArrayOutputStream baos = (ByteArrayOutputStream)data.out; + int size = baos.size(); + if( size == 0 ) { + return; + } + writeVaruint32( type.ordinal() ); + writeVaruint32( size ); + if( type == SectionType.Custom ) { + byte[] bytes = name.getBytes( StandardCharsets.ISO_8859_1 ); + writeVaruint32( bytes.length ); + write( bytes ); + } + baos.writeTo( this ); + } + + /** + * Write the data of this stream to the output. Work only for in memory stream. + * + * @param output + * the target + * @throws IOException + * if any I/O error occur + */ + void writeTo( OutputStream output ) throws IOException { + ByteArrayOutputStream baos = (ByteArrayOutputStream)out; + baos.writeTo( output ); + } + + /** + * The count of bytes in the stream. Work only for in memory stream. + * + * @return the data size + */ + int size() { + ByteArrayOutputStream baos = (ByteArrayOutputStream)out; + return baos.size(); + } + + /** + * Reset the stream. Work only for in memory stream. + */ + void reset() { + ByteArrayOutputStream baos = (ByteArrayOutputStream)out; + baos.reset(); + } +} diff --git a/src/de/inetsoftware/jwebassembly/module/ModuleWriter.java b/src/de/inetsoftware/jwebassembly/module/ModuleWriter.java index 88b3db0..af2248d 100644 --- a/src/de/inetsoftware/jwebassembly/module/ModuleWriter.java +++ b/src/de/inetsoftware/jwebassembly/module/ModuleWriter.java @@ -28,6 +28,7 @@ import de.inetsoftware.classparser.Annotations; import de.inetsoftware.classparser.ClassFile; import de.inetsoftware.classparser.Code; import de.inetsoftware.classparser.CodeInputStream; +import de.inetsoftware.classparser.ConstantPool; import de.inetsoftware.classparser.LineNumberTable; import de.inetsoftware.classparser.MethodInfo; import de.inetsoftware.jwebassembly.WasmException; @@ -93,11 +94,11 @@ public abstract class ModuleWriter implements Closeable { i + 1 == lineNumberTable.size() ? code.getCodeSize() : lineNumberTable.getStartOffset( i + 1 ); CodeInputStream byteCode = code.getByteCode( offset, nextOffset - offset ); - writeCodeChunk( byteCode, lineNumber ); + writeCodeChunk( byteCode, lineNumber, method.getConstantPool() ); } } else { CodeInputStream byteCode = code.getByteCode(); - writeCodeChunk( byteCode, -1 ); + writeCodeChunk( byteCode, -1, method.getConstantPool() ); } for( int i = Math.min( paramCount, locals.size() ); i > 0; i-- ) { locals.remove( 0 ); @@ -237,7 +238,7 @@ public abstract class ModuleWriter implements Closeable { * @throws WasmException * if some Java code can't converted */ - private void writeCodeChunk( CodeInputStream byteCode, int lineNumber ) throws WasmException { + private void writeCodeChunk( CodeInputStream byteCode, int lineNumber, ConstantPool constantPool ) throws WasmException { try { while( byteCode.available() > 0 ) { int op = byteCode.readUnsignedByte(); @@ -248,6 +249,9 @@ public abstract class ModuleWriter implements Closeable { case 16: //bipush writeConstInt( byteCode.readByte() ); break; + case 20: //ldc2_w + writeConstLong( (Long)constantPool.get( byteCode.readUnsignedShort() ) ); + break; case 26: // iload_0 case 27: // iload_1 case 28: // iload_2 @@ -264,6 +268,7 @@ public abstract class ModuleWriter implements Closeable { writeAddInt(); break; case 172: // ireturn + case 173: // lreturn case 177: // return void writeReturn(); break; @@ -286,6 +291,30 @@ public abstract class ModuleWriter implements Closeable { */ protected abstract void writeConstInt( int value ) throws IOException; + /** + * Write a constant long value + * + * @param value + * the value + * @throws IOException + * if any I/O error occur + */ + protected abstract void writeConstLong( long value ) throws IOException; + + /** + * Write or Load a local variable. + * + * @param load + * true: if load + * @param valueType + * the type of the variable + * @param idx + * the idx of the variable + * @throws WasmException + * occur a if a variable was used for a different type + * @throws IOException + * if any I/O error occur + */ private void writeLoadStore( boolean load, @Nonnull ValueType valueType, @Nonnegative int idx ) throws WasmException, IOException { while( locals.size() <= idx ) { locals.add( null ); diff --git a/src/de/inetsoftware/jwebassembly/text/TextModuleWriter.java b/src/de/inetsoftware/jwebassembly/text/TextModuleWriter.java index 151bc45..a273468 100644 --- a/src/de/inetsoftware/jwebassembly/text/TextModuleWriter.java +++ b/src/de/inetsoftware/jwebassembly/text/TextModuleWriter.java @@ -111,6 +111,15 @@ public class TextModuleWriter extends ModuleWriter { methodOutput.append( "i32.const " ).append( Integer.toString( value ) ); } + /** + * {@inheritDoc} + */ + @Override + protected void writeConstLong( long value ) throws IOException { + newline( methodOutput ); + methodOutput.append( "i64.const " ).append( Long.toString( value ) ); + } + /** * {@inheritDoc} */