write dead code at a function end if needed to produce well formatted

WASM code.
This commit is contained in:
Volker Berlin 2018-05-20 15:56:24 +02:00
parent 83013cd5f2
commit acb55beabc

View File

@ -44,6 +44,8 @@ public abstract class ModuleWriter implements Closeable {
private int paramCount; private int paramCount;
private ValueType returnType;
private LocaleVariableManager localVariables = new LocaleVariableManager(); private LocaleVariableManager localVariables = new LocaleVariableManager();
private String sourceFile; private String sourceFile;
@ -140,12 +142,33 @@ public abstract class ModuleWriter implements Closeable {
localVariables.calculate(); localVariables.calculate();
CodeInputStream byteCode = null; CodeInputStream byteCode = null;
boolean endWithReturn = false;
Iterator<CodeInputStream> byteCodes = code.getByteCodes().iterator(); Iterator<CodeInputStream> byteCodes = code.getByteCodes().iterator();
while( byteCodes.hasNext() ) { while( byteCodes.hasNext() ) {
byteCode = byteCodes.next(); byteCode = byteCodes.next();
writeCodeChunk( byteCode, lineNumber = byteCode.getLineNumber(), method.getConstantPool() ); writeCodeChunk( byteCode, lineNumber = byteCode.getLineNumber(), method.getConstantPool() );
} }
branchManager.handle( byteCode, this ); // write the last end operators branchManager.handle( byteCode, this ); // write the last end operators
if( !endWithReturn && returnType != null ) {
// if a method ends with a loop without a break then code after the loop is no reachable
// Java does not need a return byte code in this case
// But WebAssembly need the dead code to validate
switch( returnType ) {
case i32:
writeConstInt( 0 );
break;
case i64:
writeConstLong( 0 );
break;
case f32:
writeConstFloat( 0 );
break;
case f64:
writeConstDouble( 0 );
break;
}
writeBlockCode( WasmBlockOperator.RETURN, null );
}
writeMethodFinish( localVariables.getLocalTypes( paramCount ) ); writeMethodFinish( localVariables.getLocalTypes( paramCount ) );
} }
} catch( Exception ioex ) { } catch( Exception ioex ) {
@ -220,9 +243,11 @@ public abstract class ModuleWriter implements Closeable {
String signature = method.getDescription(); String signature = method.getDescription();
String kind = "param"; String kind = "param";
int paramCount = 0; int paramCount = 0;
ValueType type = null;
for( int i = 1; i < signature.length(); i++ ) { for( int i = 1; i < signature.length(); i++ ) {
paramCount++; paramCount++;
String javaType; String javaType = null;
type = null;
switch( signature.charAt( i ) ) { switch( signature.charAt( i ) ) {
case '[': // array case '[': // array
javaType = "array"; javaType = "array";
@ -234,17 +259,17 @@ public abstract class ModuleWriter implements Closeable {
case 'C': // char case 'C': // char
case 'S': // short case 'S': // short
case 'I': // int case 'I': // int
writeMethodParam( kind, ValueType.i32 ); type = ValueType.i32;
continue; break;
case 'D': // double case 'D': // double
writeMethodParam( kind, ValueType.f64 ); type = ValueType.f64;
continue; break;
case 'F': // float case 'F': // float
writeMethodParam( kind, ValueType.f32 ); type = ValueType.f32;
continue; break;
case 'J': // long case 'J': // long
writeMethodParam( kind, ValueType.i64 ); type = ValueType.i64;
continue; break;
case 'V': // void case 'V': // void
continue; continue;
case ')': case ')':
@ -254,10 +279,15 @@ public abstract class ModuleWriter implements Closeable {
default: default:
javaType = signature.substring( i, i + 1 ); javaType = signature.substring( i, i + 1 );
} }
if( type != null ) {
writeMethodParam( kind, type );
} else {
int lineNumber = method.getCode().getFirstLineNr(); int lineNumber = method.getCode().getFirstLineNr();
throw new WasmException( "Not supported Java data type in method signature: " + javaType, sourceFile, lineNumber ); throw new WasmException( "Not supported Java data type in method signature: " + javaType, sourceFile, lineNumber );
} }
} }
this.returnType = type;
}
/** /**
* Write a method parameter. * Write a method parameter.
@ -527,11 +557,14 @@ public abstract class ModuleWriter implements Closeable {
* the constant pool of the the current class * the constant pool of the the current class
* @throws WasmException * @throws WasmException
* if some Java code can't converted * if some Java code can't converted
* @return true, if the last operation was a return
*/ */
private void writeCodeChunk( CodeInputStream byteCode, int lineNumber, ConstantPool constantPool ) throws WasmException { private boolean writeCodeChunk( CodeInputStream byteCode, int lineNumber, ConstantPool constantPool ) throws WasmException {
boolean endWithReturn = false;
try { try {
while( byteCode.available() > 0 ) { while( byteCode.available() > 0 ) {
branchManager.handle( byteCode, this ); branchManager.handle( byteCode, this );
endWithReturn = false;
int op = byteCode.readUnsignedByte(); int op = byteCode.readUnsignedByte();
switch( op ) { switch( op ) {
case 0: // nop case 0: // nop
@ -891,6 +924,7 @@ public abstract class ModuleWriter implements Closeable {
case 175: // dreturn case 175: // dreturn
case 177: // return void case 177: // return void
writeBlockCode( WasmBlockOperator.RETURN, null ); writeBlockCode( WasmBlockOperator.RETURN, null );
endWithReturn = true;
break; break;
case 184: // invokestatic case 184: // invokestatic
idx = byteCode.readUnsignedShort(); idx = byteCode.readUnsignedShort();
@ -906,6 +940,7 @@ public abstract class ModuleWriter implements Closeable {
} catch( Exception ex ) { } catch( Exception ex ) {
throw WasmException.create( ex, sourceFile, lineNumber ); throw WasmException.create( ex, sourceFile, lineNumber );
} }
return endWithReturn;
} }
/** /**