From 758f31e79c769fec02a2ba9695307ec7f6f32f27 Mon Sep 17 00:00:00 2001 From: Volker Berlin Date: Fri, 28 Feb 2020 18:04:28 +0100 Subject: [PATCH] add support for CAST operation --- .../jwebassembly/module/TypeManager.java | 18 ++++++++++++++++++ .../jwebassembly/module/WasmCodeBuilder.java | 16 +++++++++++----- .../jwebassembly/module/WasmOptions.java | 19 +++++++++++++++++++ .../jwebassembly/runtime/RuntimeErrors.java | 13 ------------- .../jwebassembly/runtime/StructsNonGC.java | 8 ++++++++ 5 files changed, 56 insertions(+), 18 deletions(-) diff --git a/src/de/inetsoftware/jwebassembly/module/TypeManager.java b/src/de/inetsoftware/jwebassembly/module/TypeManager.java index 7199322..085a136 100644 --- a/src/de/inetsoftware/jwebassembly/module/TypeManager.java +++ b/src/de/inetsoftware/jwebassembly/module/TypeManager.java @@ -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. * diff --git a/src/de/inetsoftware/jwebassembly/module/WasmCodeBuilder.java b/src/de/inetsoftware/jwebassembly/module/WasmCodeBuilder.java index ee8c21c..a36742e 100644 --- a/src/de/inetsoftware/jwebassembly/module/WasmCodeBuilder.java +++ b/src/de/inetsoftware/jwebassembly/module/WasmCodeBuilder.java @@ -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 ); diff --git a/src/de/inetsoftware/jwebassembly/module/WasmOptions.java b/src/de/inetsoftware/jwebassembly/module/WasmOptions.java index aefcaae..0335ac7 100644 --- a/src/de/inetsoftware/jwebassembly/module/WasmOptions.java +++ b/src/de/inetsoftware/jwebassembly/module/WasmOptions.java @@ -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; + } } diff --git a/test/de/inetsoftware/jwebassembly/runtime/RuntimeErrors.java b/test/de/inetsoftware/jwebassembly/runtime/RuntimeErrors.java index a3afda9..4462fec 100644 --- a/test/de/inetsoftware/jwebassembly/runtime/RuntimeErrors.java +++ b/test/de/inetsoftware/jwebassembly/runtime/RuntimeErrors.java @@ -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 ); diff --git a/test/de/inetsoftware/jwebassembly/runtime/StructsNonGC.java b/test/de/inetsoftware/jwebassembly/runtime/StructsNonGC.java index 5243829..574c932 100644 --- a/test/de/inetsoftware/jwebassembly/runtime/StructsNonGC.java +++ b/test/de/inetsoftware/jwebassembly/runtime/StructsNonGC.java @@ -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 {