Simplify the try/catch structure

This commit is contained in:
Volker Berlin 2020-04-18 13:09:11 +02:00
parent 5a665b7c11
commit 87359fb497
10 changed files with 184 additions and 75 deletions

View File

@ -66,7 +66,7 @@ public class BinaryModuleWriter extends ModuleWriter implements InstructionOpcod
private final boolean createSourceMap; private final boolean createSourceMap;
private WasmOutputStream codeStream = new WasmOutputStream(); private WasmOutputStream codeStream = new WasmOutputStream( options );
private List<TypeEntry> functionTypes = new ArrayList<>(); private List<TypeEntry> functionTypes = new ArrayList<>();
@ -116,7 +116,7 @@ public class BinaryModuleWriter extends ModuleWriter implements InstructionOpcod
*/ */
@Override @Override
public void close() throws IOException { public void close() throws IOException {
wasm = new WasmOutputStream( target.getWasmOutput() ); wasm = new WasmOutputStream( options, target.getWasmOutput() );
wasm.write( WASM_BINARY_MAGIC ); wasm.write( WASM_BINARY_MAGIC );
wasm.writeInt32( WASM_BINARY_VERSION ); wasm.writeInt32( WASM_BINARY_VERSION );
@ -152,7 +152,7 @@ public class BinaryModuleWriter extends ModuleWriter implements InstructionOpcod
private void writeSection( SectionType type, Collection<? extends SectionEntry> entries ) throws IOException { private void writeSection( SectionType type, Collection<? extends SectionEntry> entries ) throws IOException {
int count = entries.size(); int count = entries.size();
if( count > 0 ) { if( count > 0 ) {
WasmOutputStream stream = new WasmOutputStream(); WasmOutputStream stream = new WasmOutputStream( options );
stream.writeVaruint32( count ); stream.writeVaruint32( count );
for( SectionEntry entry : entries ) { for( SectionEntry entry : entries ) {
entry.writeSectionEntry( stream ); entry.writeSectionEntry( stream );
@ -174,7 +174,7 @@ public class BinaryModuleWriter extends ModuleWriter implements InstructionOpcod
return; return;
} }
WasmOutputStream stream = new WasmOutputStream(); WasmOutputStream stream = new WasmOutputStream( options );
int count = 1; int count = 1;
if( stringCount > 0 ) { if( stringCount > 0 ) {
count++; count++;
@ -217,7 +217,7 @@ public class BinaryModuleWriter extends ModuleWriter implements InstructionOpcod
private void writeMemorySection() throws IOException { private void writeMemorySection() throws IOException {
int dataSize = dataStream.size(); int dataSize = dataStream.size();
if( dataSize > 0 ) { if( dataSize > 0 ) {
WasmOutputStream stream = new WasmOutputStream(); WasmOutputStream stream = new WasmOutputStream( options );
int pages = (dataSize + 0xFFFF) / 0x10000; // a page is defined with a size of 64KiB int pages = (dataSize + 0xFFFF) / 0x10000; // a page is defined with a size of 64KiB
int count = 1; int count = 1;
stream.writeVaruint32( count ); stream.writeVaruint32( count );
@ -238,7 +238,7 @@ public class BinaryModuleWriter extends ModuleWriter implements InstructionOpcod
*/ */
private void writeEventSection() throws IOException { private void writeEventSection() throws IOException {
if( exceptionSignatureIndex >= 0 ) { if( exceptionSignatureIndex >= 0 ) {
WasmOutputStream stream = new WasmOutputStream(); WasmOutputStream stream = new WasmOutputStream( options );
stream.writeVaruint32( 1 ); stream.writeVaruint32( 1 );
// event declaration // event declaration
@ -260,7 +260,7 @@ public class BinaryModuleWriter extends ModuleWriter implements InstructionOpcod
return; return;
} }
int id = getFunction( startFunction ).id; int id = getFunction( startFunction ).id;
WasmOutputStream stream = new WasmOutputStream(); WasmOutputStream stream = new WasmOutputStream( options );
stream.writeVaruint32( id ); stream.writeVaruint32( id );
wasm.writeSection( SectionType.Start, stream ); wasm.writeSection( SectionType.Start, stream );
} }
@ -277,7 +277,7 @@ public class BinaryModuleWriter extends ModuleWriter implements InstructionOpcod
} }
int elemCount = imports.size() + functions.size(); int elemCount = imports.size() + functions.size();
WasmOutputStream stream = new WasmOutputStream(); WasmOutputStream stream = new WasmOutputStream( options );
stream.writeVaruint32( 1 ); // count of element segments to follow stream.writeVaruint32( 1 ); // count of element segments to follow
// element_segment // element_segment
@ -305,7 +305,7 @@ public class BinaryModuleWriter extends ModuleWriter implements InstructionOpcod
} }
int start = wasm.size(); int start = wasm.size();
WasmOutputStream stream = new WasmOutputStream(); WasmOutputStream stream = new WasmOutputStream( options );
stream.writeVaruint32( size ); stream.writeVaruint32( size );
for( Entry<String, Function> entry : functions.entrySet() ) { for( Entry<String, Function> entry : functions.entrySet() ) {
try { try {
@ -345,7 +345,7 @@ public class BinaryModuleWriter extends ModuleWriter implements InstructionOpcod
return; return;
} }
WasmOutputStream stream = new WasmOutputStream(); WasmOutputStream stream = new WasmOutputStream( options );
stream.writeVaruint32( 1 ); // count, we use one large segment stream.writeVaruint32( 1 ); // count, we use one large segment
// one data segment // one data segment
@ -368,12 +368,12 @@ public class BinaryModuleWriter extends ModuleWriter implements InstructionOpcod
if( !options.debugNames() ) { if( !options.debugNames() ) {
return; return;
} }
WasmOutputStream stream = new WasmOutputStream(); WasmOutputStream stream = new WasmOutputStream( options );
stream.writeString( "name" ); // Custom Section name "name", content is part of the section length stream.writeString( "name" ); // Custom Section name "name", content is part of the section length
// write function names // write function names
stream.write( 1 ); // 1 - Function name stream.write( 1 ); // 1 - Function name
WasmOutputStream section = new WasmOutputStream(); WasmOutputStream section = new WasmOutputStream( options );
section.writeVaruint32( imports.size() + functions.size() ); section.writeVaruint32( imports.size() + functions.size() );
writeDebugFunctionNames( imports.entrySet(), section ); writeDebugFunctionNames( imports.entrySet(), section );
writeDebugFunctionNames( functions.entrySet(), section ); writeDebugFunctionNames( functions.entrySet(), section );
@ -449,7 +449,7 @@ public class BinaryModuleWriter extends ModuleWriter implements InstructionOpcod
if( url == null ) { if( url == null ) {
return; return;
} }
WasmOutputStream stream = new WasmOutputStream(); WasmOutputStream stream = new WasmOutputStream( options );
stream.writeString( "sourceMappingURL" ); // Custom Section name "sourceMappingURL", content is part of the section length stream.writeString( "sourceMappingURL" ); // Custom Section name "sourceMappingURL", content is part of the section length
stream.writeString( url ); stream.writeString( url );
wasm.writeSection( SectionType.Custom, stream ); wasm.writeSection( SectionType.Custom, stream );
@ -465,7 +465,7 @@ public class BinaryModuleWriter extends ModuleWriter implements InstructionOpcod
Package pack = getClass().getPackage(); Package pack = getClass().getPackage();
String version = pack == null ? null : pack.getImplementationVersion(); String version = pack == null ? null : pack.getImplementationVersion();
WasmOutputStream stream = new WasmOutputStream(); WasmOutputStream stream = new WasmOutputStream( options );
stream.writeString( "producers" ); // Custom Section name "producers", content is part of the section length stream.writeString( "producers" ); // Custom Section name "producers", content is part of the section length
stream.writeVaruint32( 2 ); // field_count; number of fields that follow (language and processed-by) stream.writeVaruint32( 2 ); // field_count; number of fields that follow (language and processed-by)
@ -511,13 +511,20 @@ public class BinaryModuleWriter extends ModuleWriter implements InstructionOpcod
@Override @Override
protected void writeException() throws IOException { protected void writeException() throws IOException {
if( exceptionSignatureIndex <= 0 ) { if( exceptionSignatureIndex <= 0 ) {
FunctionTypeEntry exceptionType = new FunctionTypeEntry(); FunctionTypeEntry type = new FunctionTypeEntry();
exceptionType.params.add( ValueType.anyref ); type.params.add( ValueType.anyref );
exceptionSignatureIndex = functionTypes.indexOf( exceptionType ); exceptionSignatureIndex = functionTypes.indexOf( type );
if( exceptionSignatureIndex < 0 ) { if( exceptionSignatureIndex < 0 ) {
exceptionSignatureIndex = functionTypes.size(); exceptionSignatureIndex = functionTypes.size();
functionTypes.add( exceptionType ); functionTypes.add( type );
} }
// result type of catch block for unboxing
type = new FunctionTypeEntry();
type.params.add( ValueType.exnref );
type.results.add( ValueType.anyref );
options.setCatchType( functionTypes.size() );
functionTypes.add( type );
} }
} }
@ -639,7 +646,7 @@ public class BinaryModuleWriter extends ModuleWriter implements InstructionOpcod
@Override @Override
protected void writeMethodFinish() throws IOException { protected void writeMethodFinish() throws IOException {
@SuppressWarnings( "resource" ) @SuppressWarnings( "resource" )
WasmOutputStream localsTypeStream = new WasmOutputStream(); WasmOutputStream localsTypeStream = new WasmOutputStream( options );
int localEntryCount = 0; // number of local entries in output int localEntryCount = 0; // number of local entries in output
int varCount = locals.size(); int varCount = locals.size();
for( int i = 0; i < varCount; ) { for( int i = 0; i < varCount; ) {
@ -655,10 +662,10 @@ public class BinaryModuleWriter extends ModuleWriter implements InstructionOpcod
} }
@SuppressWarnings( "resource" ) @SuppressWarnings( "resource" )
WasmOutputStream localsStream = new WasmOutputStream(); WasmOutputStream localsStream = new WasmOutputStream( options );
localsStream.writeVaruint32( localEntryCount ); localsStream.writeVaruint32( localEntryCount );
WasmOutputStream functionsStream = function.functionsStream = new WasmOutputStream(); WasmOutputStream functionsStream = function.functionsStream = new WasmOutputStream( options );
functionsStream.writeVaruint32( localsStream.size() + localsTypeStream.size() + codeStream.size() + 1 ); functionsStream.writeVaruint32( localsStream.size() + localsTypeStream.size() + codeStream.size() + 1 );
localsStream.writeTo( functionsStream ); localsStream.writeTo( functionsStream );
localsTypeStream.writeTo( functionsStream ); localsTypeStream.writeTo( functionsStream );

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2017 - 2019 Volker Berlin (i-net software) * Copyright 2017 - 2020 Volker Berlin (i-net software)
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -24,6 +24,7 @@ import javax.annotation.Nonnegative;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import de.inetsoftware.jwebassembly.WasmException; import de.inetsoftware.jwebassembly.WasmException;
import de.inetsoftware.jwebassembly.module.WasmOptions;
import de.inetsoftware.jwebassembly.wasm.AnyType; import de.inetsoftware.jwebassembly.wasm.AnyType;
import de.inetsoftware.jwebassembly.wasm.LittleEndianOutputStream; import de.inetsoftware.jwebassembly.wasm.LittleEndianOutputStream;
import de.inetsoftware.jwebassembly.wasm.ValueType; import de.inetsoftware.jwebassembly.wasm.ValueType;
@ -33,11 +34,17 @@ import de.inetsoftware.jwebassembly.wasm.ValueType;
*/ */
class WasmOutputStream extends LittleEndianOutputStream { class WasmOutputStream extends LittleEndianOutputStream {
private final WasmOptions options;
/** /**
* Create a in memory stream. * Create a in memory stream.
*
* @param options
* compiler properties
*/ */
WasmOutputStream() { WasmOutputStream( WasmOptions options ) {
super(); super();
this.options = options;
} }
/** /**
@ -45,9 +52,12 @@ class WasmOutputStream extends LittleEndianOutputStream {
* *
* @param output * @param output
* the target of data * the target of data
* @param options
* compiler properties
*/ */
WasmOutputStream( OutputStream output ) { WasmOutputStream( WasmOptions options, OutputStream output ) {
super( output ); super( output );
this.options = options;
} }
/** /**
@ -86,8 +96,12 @@ class WasmOutputStream extends LittleEndianOutputStream {
* if an I/O error occurs. * if an I/O error occurs.
*/ */
public void writeRefValueType( AnyType type ) throws IOException { public void writeRefValueType( AnyType type ) throws IOException {
if( type.getCode() >= 0 ) { if( type.isRefType() ) {
writeValueType( ValueType.ref_type ); if( options.useGC() ) {
writeValueType( ValueType.ref_type );
} else {
type = ValueType.anyref;
}
} }
writeValueType( type ); writeValueType( type );
} }
@ -192,7 +206,7 @@ class WasmOutputStream extends LittleEndianOutputStream {
* if an I/O error occurs. * if an I/O error occurs.
*/ */
void writeDouble( double value ) throws IOException { void writeDouble( double value ) throws IOException {
long l = Double.doubleToLongBits(value); long l = Double.doubleToLongBits( value );
writeInt32( (int)l ); writeInt32( (int)l );
writeInt32( (int)(l >>> 32) ); writeInt32( (int)(l >>> 32) );
} }

View File

@ -860,17 +860,21 @@ class BranchManger {
* Should be converted to the follow Wasm code for try/catch: * Should be converted to the follow Wasm code for try/catch:
* *
* <pre> * <pre>
* block * try
* block (result anyref) * code1
* try * catch
* code1 * block (param exnref)(result anyref)
* catch * br_on_exn 0 0
* br_on_exn 1 0 * rethrow
* rethrow * end
* end * local.tee $ex
* br 1 * i32.const classIndex(Exception)
* call $.instanceof
* i32.eqz
* if
* local.get $ex
* throw 0
* end * end
* local.set x
* code2 * code2
* end * end
* code3 * code3
@ -910,25 +914,24 @@ class BranchManger {
} }
int startPos = tryBlock.startPosition; int startPos = tryBlock.startPosition;
int catchPos = tryCatch.getHandler(); int catchPos = tryCatch.getHandler();
BranchNode outerBlock = new BranchNode( startPos, endPos, WasmBlockOperator.BLOCK, WasmBlockOperator.END );
parent.add( outerBlock );
BranchNode innerBlock = new BranchNode( startPos, catchPos, WasmBlockOperator.BLOCK, WasmBlockOperator.END, ValueType.anyref );
outerBlock.add( innerBlock );
BranchNode tryNode = new BranchNode( startPos, catchPos, WasmBlockOperator.TRY, null ); BranchNode tryNode = new BranchNode( startPos, catchPos, WasmBlockOperator.TRY, null );
innerBlock.add( tryNode ); parent.add( tryNode );
calculate( tryNode, parsedOperations.subList( 0, idx ) ); calculate( tryNode, parsedOperations.subList( 0, idx ) );
BranchNode catchNode = new BranchNode( catchPos, catchPos, WasmBlockOperator.CATCH, WasmBlockOperator.END ); BranchNode catchNode = new BranchNode( catchPos, endPos, WasmBlockOperator.CATCH, WasmBlockOperator.END );
innerBlock.add( catchNode ); parent.add( catchNode );
if( tryCatch.isFinally() ) { if( tryCatch.isFinally() ) {
catchNode.add( new BranchNode( catchPos, catchPos, WasmBlockOperator.DROP, null ) ); catchNode.add( new BranchNode( catchPos, catchPos, WasmBlockOperator.DROP, null ) );
} else { } else {
// unboxing the exnref on the stack to a reference of the exception
BranchNode unBoxing = new BranchNode( catchPos, catchPos, WasmBlockOperator.BLOCK, WasmBlockOperator.END, options.getCatchType() );
catchNode.add( unBoxing );
//TODO localVariables.getTempVariable( ValueType.exnref, catchPos, endPos ); https://github.com/WebAssembly/wabt/issues/1388 //TODO localVariables.getTempVariable( ValueType.exnref, catchPos, endPos ); https://github.com/WebAssembly/wabt/issues/1388
catchNode.add( new BranchNode( catchPos, catchPos, WasmBlockOperator.BR_ON_EXN, null, 1 ) ); unBoxing.add( new BranchNode( catchPos, catchPos, WasmBlockOperator.BR_ON_EXN, null, 0 ) );
catchNode.add( new BranchNode( catchPos, catchPos, WasmBlockOperator.RETHROW, null ) ); unBoxing.add( new BranchNode( catchPos, catchPos, WasmBlockOperator.RETHROW, null ) );
// add a "if $exception instanceof type" check to the WASM code // add a "if $exception instanceof type" check to the WASM code
StructType type = options.types.valueOf( tryCatch.getType().getName() ); StructType type = options.types.valueOf( tryCatch.getType().getName() );
@ -946,8 +949,6 @@ class BranchManger {
instructions.add( ++instrPos, new WasmBlockInstruction( WasmBlockOperator.THROW, null, catchPos, lineNumber ) ); instructions.add( ++instrPos, new WasmBlockInstruction( WasmBlockOperator.THROW, null, catchPos, lineNumber ) );
instructions.add( ++instrPos, new WasmBlockInstruction( WasmBlockOperator.END, null, catchPos, lineNumber ) ); instructions.add( ++instrPos, new WasmBlockInstruction( WasmBlockOperator.END, null, catchPos, lineNumber ) );
} }
innerBlock.add( new BranchNode( catchPos, catchPos, WasmBlockOperator.BR, null, 1 ) );
} }
/** /**

View File

@ -506,6 +506,14 @@ public class TypeManager {
return code; return code;
} }
/**
* {@inheritDoc}
*/
@Override
public boolean isRefType() {
return true;
}
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */

View File

@ -21,11 +21,7 @@ import javax.annotation.Nonnull;
import de.inetsoftware.jwebassembly.JWebAssembly; import de.inetsoftware.jwebassembly.JWebAssembly;
import de.inetsoftware.jwebassembly.javascript.JavaScriptSyntheticFunctionName; import de.inetsoftware.jwebassembly.javascript.JavaScriptSyntheticFunctionName;
import de.inetsoftware.jwebassembly.module.CodeOptimizer; import de.inetsoftware.jwebassembly.wasm.AnyType;
import de.inetsoftware.jwebassembly.module.FunctionManager;
import de.inetsoftware.jwebassembly.module.FunctionName;
import de.inetsoftware.jwebassembly.module.StringManager;
import de.inetsoftware.jwebassembly.module.TypeManager;
import de.inetsoftware.jwebassembly.wasm.ValueType; import de.inetsoftware.jwebassembly.wasm.ValueType;
/** /**
@ -65,6 +61,30 @@ public class WasmOptions {
private FunctionName cast; private FunctionName cast;
private int catchTypeCode;
private AnyType catchType = new AnyType() {
@Override
public int getCode() {
return catchTypeCode;
}
@Override
public boolean isRefType() {
return false;
}
@Override
public boolean isSubTypeOf( AnyType type ) {
return type == this;
}
@Override
public String toString() {
return "(param exnref)(result anyref)";
}
};
/** /**
* Create a new instance of options * Create a new instance of options
* *
@ -184,4 +204,23 @@ public class WasmOptions {
} }
return name; return name;
} }
/**
* The type for a catch block to unboxing the exnref into a anyref
*
* @return the type
*/
public AnyType getCatchType() {
return catchType;
}
/**
* Set the dynamic type id for the catch type
*
* @param catchTypeCode
* the positive id
*/
public void setCatchType( int catchTypeCode ) {
this.catchTypeCode = catchTypeCode;
}
} }

View File

@ -232,6 +232,9 @@ public class TextModuleWriter extends ModuleWriter {
newline( output ); newline( output );
output.append( "(event (param anyref))" ); output.append( "(event (param anyref))" );
inset = oldInset; inset = oldInset;
options.setCatchType( types.size() );
types.add( options.getCatchType().toString() );
} }
} }
@ -310,7 +313,7 @@ public class TextModuleWriter extends ModuleWriter {
* if any I/O error occur * if any I/O error occur
*/ */
private void writeTypeName( Appendable output, AnyType type ) throws IOException { private void writeTypeName( Appendable output, AnyType type ) throws IOException {
if( type instanceof ValueType ) { if( !type.isRefType() ) {
output.append( type.toString() ); output.append( type.toString() );
} else if( options.useGC() ) { } else if( options.useGC() ) {
output.append( "(optref " ).append( normalizeName( type.toString() ) ).append( ')' ); output.append( "(optref " ).append( normalizeName( type.toString() ) ).append( ')' );
@ -714,14 +717,7 @@ public class TextModuleWriter extends ModuleWriter {
name = "return"; name = "return";
break; break;
case IF: case IF:
if( data == ValueType.empty ) { name = blockWithResult( "if", (AnyType)data );
name = "if";
} else {
StringBuilder builder = new StringBuilder("if (result ");
writeTypeName( builder, (AnyType)data );
builder.append( ")" );
name = builder;
}
insetAfter++; insetAfter++;
break; break;
case ELSE: case ELSE:
@ -737,14 +733,7 @@ public class TextModuleWriter extends ModuleWriter {
name = "drop"; name = "drop";
break; break;
case BLOCK: case BLOCK:
if( data == null ) { name = blockWithResult( "block", (AnyType)data );
name = "block";
} else {
StringBuilder builder = new StringBuilder("block (result ");
writeTypeName( builder, (AnyType)data );
builder.append( ")" );
name = builder;
}
insetAfter++; insetAfter++;
break; break;
case BR: case BR:
@ -797,6 +786,34 @@ public class TextModuleWriter extends ModuleWriter {
inset += insetAfter; inset += insetAfter;
} }
/**
* Create a the result type for a block instruction
*
* @param blockName
* the name of the block for example "if" or "block"
* @param result
* the result type of the block
* @return the block with result type
* @throws IOException
* if any I/O error occur
*/
@Nonnull
private CharSequence blockWithResult( String blockName, AnyType result ) throws IOException {
if( result == null || result == ValueType.empty ) {
return blockName;
} else {
StringBuilder builder = new StringBuilder( blockName );
if( result.toString().contains( "(" ) ) {
builder.append( result );
} else {
builder.append( "(result " );
writeTypeName( builder, result );
builder.append( ")" );
}
return builder;
}
}
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2018 - 2019 Volker Berlin (i-net software) * Copyright 2018 - 2020 Volker Berlin (i-net software)
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -39,6 +39,13 @@ public interface AnyType {
*/ */
public int getCode(); public int getCode();
/**
* If the type is a reference type. A GC reference to the heap.
*
* @return true, is GC type
*/
public boolean isRefType();
/** /**
* Check if this is a sub type of given type. * Check if this is a sub type of given type.
* *

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2019 Volker Berlin (i-net software) * Copyright 2019 - 2020 Volker Berlin (i-net software)
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -50,6 +50,14 @@ public class ArrayType implements AnyType {
return ValueType.anyref.getCode(); return ValueType.anyref.getCode();
} }
/**
* {@inheritDoc}
*/
@Override
public boolean isRefType() {
return true;
}
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2017 - 2019 Volker Berlin (i-net software) * Copyright 2017 - 2020 Volker Berlin (i-net software)
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -58,6 +58,14 @@ public enum ValueType implements AnyType {
return code; return code;
} }
/**
* {@inheritDoc}
*/
@Override
public boolean isRefType() {
return false;
}
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */

View File

@ -336,7 +336,7 @@ public class WatParserTest {
@Test @Test
public void ifElseEndI32() throws IOException { public void ifElseEndI32() throws IOException {
test( "if (result i32) else end" ); test( "if(result i32) else end" );
} }
@Test @Test