add support for CAST operation

This commit is contained in:
Volker Berlin 2020-02-28 18:04:28 +01:00
parent dd74a8beae
commit 758f31e79c
5 changed files with 56 additions and 18 deletions

View File

@ -197,6 +197,24 @@ public class TypeManager {
, valueOf( "java/lang/Object" ), ValueType.i32, null, ValueType.i32 ); //
}
/**
* Create the FunctionName for the CAST operation and mark it as used. The function has 2 parameters (THIS,
* classIndex) and returns this if the type match else it throw an exception.
*
* @return the name
*/
WatCodeSyntheticFunctionName createCast() {
return new WatCodeSyntheticFunctionName( //
"cast", "local.get 0 " // THIS
+ "local.get 1 " // the class index that we search
+ "call $.instanceof()V " // the synthetic signature of ArraySyntheticFunctionName
+ "i32.eqz " //
+ "local.get 0 " // THIS
+ "return " //
+ "unreachable " // TODO throw a ClassCastException if exception handling is supported
, valueOf( "java/lang/Object" ), ValueType.i32, null, valueOf( "java/lang/Object" ) );
}
/**
* A reference to a type.
*

View File

@ -634,11 +634,17 @@ public abstract class WasmCodeBuilder {
* the line number in the Java source code
*/
protected void addStructInstruction( StructOperator op, @Nonnull String typeName, @Nullable NamedStorageType fieldName, int javaCodePos, int lineNumber ) {
if( op == StructOperator.INSTANCEOF ) {
instructions.add( new WasmConstInstruction( types.valueOf( typeName ).getClassIndex(), javaCodePos, lineNumber ) );
FunctionName name = options.getInstanceOf();
instructions.add( new WasmCallInstruction( name, javaCodePos, lineNumber, types, false ) );
return;
switch( op ) {
case INSTANCEOF:
instructions.add( new WasmConstInstruction( types.valueOf( typeName ).getClassIndex(), javaCodePos, lineNumber ) );
FunctionName name = options.getInstanceOf();
instructions.add( new WasmCallInstruction( name, javaCodePos, lineNumber, types, false ) );
return;
case CAST:
instructions.add( new WasmConstInstruction( types.valueOf( typeName ).getClassIndex(), javaCodePos, lineNumber ) );
name = options.getCast();
instructions.add( new WasmCallInstruction( name, javaCodePos, lineNumber, types, false ) );
return;
}
WasmStructInstruction structInst = new WasmStructInstruction( op, typeName, fieldName, javaCodePos, lineNumber, types );
instructions.add( structInst );

View File

@ -63,6 +63,8 @@ public class WasmOptions {
private FunctionName instanceOf;
private FunctionName cast;
/**
* Create a new instance of options
*
@ -165,4 +167,21 @@ public class WasmOptions {
}
return name;
}
/**
* Get the FunctionName for a CAST operation and mark it as used. The function has 2 parameters (THIS, classIndex)
* and returns THIS or throw an exception.
*
* @return the name
*/
@Nonnull
FunctionName getCast() {
FunctionName name = cast;
if( name == null ) {
cast = name = types.createCast();
functions.markAsNeeded( name );
getInstanceOf();
}
return name;
}
}

View File

@ -126,19 +126,6 @@ public class RuntimeErrors {
}
}
@Test
public void checkcast() throws IOException {
compileErrorTest( "Unknown operator: CAST", CheckcastMethod.class );
}
static class CheckcastMethod {
@Export
static Integer runnable() {
Object obj = new Integer(0);
return (Integer)obj;
}
}
@Test
public void classConatnt() throws IOException {
compileErrorTest( "Class constants are not supported.", ClassConstant.class );

View File

@ -55,6 +55,7 @@ public class StructsNonGC extends AbstractBaseTest {
addParam( list, script, "instanceof1" );
addParam( list, script, "instanceof2" );
addParam( list, script, "instanceof3" );
addParam( list, script, "cast" );
}
rule.setTestParameters( list );
return list;
@ -166,6 +167,13 @@ public class StructsNonGC extends AbstractBaseTest {
Object obj = new LinkedList();
return obj instanceof List;
}
@Export
static int cast() {
Object obj = new Integer(42);
Integer val = (Integer)obj;
return val.intValue();
}
}
interface TestDefault {