Run test examples in CF-to-DEX mode
Add getFailingCompileCfToDex() and getFailingRunCfToDex() to mark tests
that currently fail when running with the CF frontend for testing and
the DEX backend because of b/109788783 (byte/boolean distinction),
b/109789539 (multianewarray), b/109789541 (synchronized methods).
* Add references to tracking bugs for missing implementations.
* CfMultiANewArray.buildIR(): Throw Unimplemented when running with the
DEX backend.
* barray example: Add loads and stores to non-null arrays.
Bug: 109788783, 109789539, 109789541
Change-Id: If80113549b050be533f506bf9b3d7a9e6ec36b8d
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfMultiANewArray.java b/src/main/java/com/android/tools/r8/cf/code/CfMultiANewArray.java
index 015b8a3..0eed4a6 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfMultiANewArray.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfMultiANewArray.java
@@ -4,6 +4,7 @@
package com.android.tools.r8.cf.code;
import com.android.tools.r8.cf.CfPrinter;
+import com.android.tools.r8.errors.Unimplemented;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.UseRegistry;
import com.android.tools.r8.ir.conversion.CfSourceCode;
@@ -52,6 +53,10 @@
@Override
public void buildIR(IRBuilder builder, CfState state, CfSourceCode code) {
+ if (!builder.isGeneratingClassFiles()) {
+ // TODO(b/109789539): Implement this case (see JarSourceCode.buildPrelude()/buildPostlude()).
+ throw new Unimplemented("CfMultiANewArray to DEX backend");
+ }
int[] dimensions = state.popReverse(this.dimensions);
builder.addMultiNewArray(type, state.push(type).register, dimensions);
}
diff --git a/src/main/java/com/android/tools/r8/graph/CfCode.java b/src/main/java/com/android/tools/r8/graph/CfCode.java
index ffa34d1..b8e0bd8 100644
--- a/src/main/java/com/android/tools/r8/graph/CfCode.java
+++ b/src/main/java/com/android/tools/r8/graph/CfCode.java
@@ -225,8 +225,11 @@
ValueNumberGenerator generator,
Position callerPosition,
Origin origin) {
- assert !options.isGeneratingDex() || !encodedMethod.accessFlags.isSynchronized()
- : "Converting CfCode to IR not supported for DEX output of synchronized methods.";
+ // TODO(b/109789541): Implement CF->IR->DEX for synchronized methods.
+ if (options.isGeneratingDex() && encodedMethod.accessFlags.isSynchronized()) {
+ throw new Unimplemented(
+ "Converting CfCode to IR not supported for DEX output of synchronized methods.");
+ }
CfSourceCode source = new CfSourceCode(this, encodedMethod, callerPosition, origin);
IRBuilder builder =
(generator == null)
diff --git a/src/main/java/com/android/tools/r8/graph/LazyCfCode.java b/src/main/java/com/android/tools/r8/graph/LazyCfCode.java
index 454ed29..afc2969 100644
--- a/src/main/java/com/android/tools/r8/graph/LazyCfCode.java
+++ b/src/main/java/com/android/tools/r8/graph/LazyCfCode.java
@@ -533,7 +533,8 @@
return MemberType.OBJECT;
case Opcodes.BALOAD:
case Opcodes.BASTORE:
- return MemberType.BOOLEAN; // TODO: Distinguish byte and boolean.
+ // TODO(b/109788783): Distinguish byte and boolean.
+ return MemberType.BOOLEAN;
case Opcodes.CALOAD:
case Opcodes.CASTORE:
return MemberType.CHAR;
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/CfSourceCode.java b/src/main/java/com/android/tools/r8/ir/conversion/CfSourceCode.java
index e68e3d5..ca79b0f 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/CfSourceCode.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/CfSourceCode.java
@@ -324,7 +324,7 @@
buildArgumentInstructions(builder);
recordStateForTarget(0, state.getSnapshot());
// TODO: addDebugLocalUninitialized + addDebugLocalStart for non-argument locals live at 0
- // TODO: Generate method synchronization
+ // TODO(b/109789541): Generate method synchronization for DEX backend.
inPrelude = false;
}
@@ -353,7 +353,7 @@
@Override
public void buildPostlude(IRBuilder builder) {
- // Since we're generating classfiles, we never need to synthesize monitor enter/exit.
+ // TODO(b/109789541): Generate method synchronization for DEX backend.
}
@Override
diff --git a/src/test/examples/barray/BArray.java b/src/test/examples/barray/BArray.java
index 0ca6505..26ac5f8 100644
--- a/src/test/examples/barray/BArray.java
+++ b/src/test/examples/barray/BArray.java
@@ -6,20 +6,59 @@
public class BArray {
public static void main(String[] args) {
+ System.out.println("null boolean: " + readNullBooleanArray());
+ System.out.println("null byte: " + readNullByteArray());
+ System.out.println("boolean: " + readBooleanArray(writeBooleanArray(args)));
+ System.out.println("byte: " + readByteArray(writeByteArray(args)));
+ }
+
+ public static boolean readNullBooleanArray() {
boolean[] boolArray = null;
+ try {
+ return boolArray[0] || boolArray[1];
+ } catch (Throwable e) {
+ return true;
+ }
+ }
+
+ public static byte readNullByteArray() {
byte[] byteArray = null;
- boolean bool;
- byte bits;
try {
- bool = boolArray[0] || boolArray[1];
+ return byteArray[0];
} catch (Throwable e) {
- bool = true;
+ return 42;
}
+ }
+
+ public static boolean[] writeBooleanArray(String[] args) {
+ boolean[] array = new boolean[args.length];
+ for (int i = 0; i < args.length; i++) {
+ array[i] = args[i].length() == 42;
+ }
+ return array;
+ }
+
+ public static byte[] writeByteArray(String[] args) {
+ byte[] array = new byte[args.length];
+ for (int i = 0; i < args.length; i++) {
+ array[i] = (byte) args[i].length();
+ }
+ return array;
+ }
+
+ public static boolean readBooleanArray(boolean[] boolArray) {
try {
- bits = byteArray[0];
+ return boolArray[0] || boolArray[1];
} catch (Throwable e) {
- bits = 42;
+ return true;
}
- System.out.println("bits " + bits + " and bool " + bool);
+ }
+
+ public static byte readByteArray(byte[] byteArray) {
+ try {
+ return byteArray[0];
+ } catch (Throwable e) {
+ return 42;
+ }
}
}
diff --git a/src/test/java/com/android/tools/r8/R8RunExamplesCommon.java b/src/test/java/com/android/tools/r8/R8RunExamplesCommon.java
index fe5ae72..4afd0c2 100644
--- a/src/test/java/com/android/tools/r8/R8RunExamplesCommon.java
+++ b/src/test/java/com/android/tools/r8/R8RunExamplesCommon.java
@@ -148,6 +148,11 @@
if (output == Output.CF && getFailingCompileCf().contains(mainClass)) {
thrown.expect(Throwable.class);
}
+ if (frontend == Frontend.CF
+ && output == Output.DEX
+ && getFailingCompileCfToDex().contains(mainClass)) {
+ thrown.expect(Throwable.class);
+ }
OutputMode outputMode = output == Output.CF ? OutputMode.ClassFile : OutputMode.DexIndexed;
switch (compiler) {
case D8: {
@@ -215,6 +220,12 @@
thrown = ExpectedException.none();
}
+ if (frontend == Frontend.CF
+ && output == Output.DEX
+ && getFailingRunCfToDex().contains(mainClass)) {
+ thrown.expect(Throwable.class);
+ }
+
if (output == Output.CF) {
ToolHelper.ProcessResult result = ToolHelper.runJava(generated, mainClass);
if (result.exitCode != 0) {
@@ -257,6 +268,11 @@
protected abstract Map<String, TestCondition> getFailingRunCf();
+ protected abstract Set<String> getFailingCompileCfToDex();
+
+ // TODO(mathiasr): Add CompilerSet for CfToDex so we can fold this into getFailingRun().
+ protected abstract Set<String> getFailingRunCfToDex();
+
protected abstract Set<String> getFailingCompileCf();
protected abstract Set<String> getFailingOutputCf();
diff --git a/src/test/java/com/android/tools/r8/R8RunExamplesKotlinTest.java b/src/test/java/com/android/tools/r8/R8RunExamplesKotlinTest.java
index 97c8624..dc94a71 100644
--- a/src/test/java/com/android/tools/r8/R8RunExamplesKotlinTest.java
+++ b/src/test/java/com/android/tools/r8/R8RunExamplesKotlinTest.java
@@ -49,6 +49,16 @@
}
@Override
+ protected Set<String> getFailingCompileCfToDex() {
+ return Collections.emptySet();
+ }
+
+ @Override
+ protected Set<String> getFailingRunCfToDex() {
+ return Collections.emptySet();
+ }
+
+ @Override
protected Set<String> getFailingCompileCf() {
return Collections.emptySet();
}
diff --git a/src/test/java/com/android/tools/r8/R8RunExamplesTest.java b/src/test/java/com/android/tools/r8/R8RunExamplesTest.java
index d8b886c..4ee928b 100644
--- a/src/test/java/com/android/tools/r8/R8RunExamplesTest.java
+++ b/src/test/java/com/android/tools/r8/R8RunExamplesTest.java
@@ -109,6 +109,14 @@
test,
Frontend.CF,
Output.CF));
+ fullTestList.add(
+ makeTest(
+ Input.JAVAC_ALL,
+ CompilerUnderTest.R8,
+ CompilationMode.RELEASE,
+ test,
+ Frontend.CF,
+ Output.DEX));
}
return fullTestList;
}
@@ -143,6 +151,29 @@
}
@Override
+ protected Set<String> getFailingCompileCfToDex() {
+ return new ImmutableSet.Builder<String>()
+ // TODO(b/109788783): Implement byte/boolean distinction for array load/store.
+ .add("arrayaccess.ArrayAccess")
+ .add("barray.BArray")
+ .add("filledarray.FilledArray")
+ .build();
+ }
+
+ @Override
+ protected Set<String> getFailingRunCfToDex() {
+ return new ImmutableSet.Builder<String>()
+ // TODO(b/109789541): Implement method synchronization for DEX backend.
+ .add("sync.Sync")
+ // TODO(b/109789539): Implement CfMultiANewArray.buildIR() for DEX backend.
+ .add("newarray.NewArray")
+ .add("trycatch.TryCatch")
+ .add("regress_70737019.Test")
+ .add("regress_72361252.Test")
+ .build();
+ }
+
+ @Override
protected Set<String> getFailingCompileCf() {
return new ImmutableSet.Builder<String>()
.build();