Merge "Add @NeverMerge annotation for testing"
diff --git a/src/main/java/com/android/tools/r8/ir/code/ConstMethodType.java b/src/main/java/com/android/tools/r8/ir/code/ConstMethodType.java
index d258839..fa43dea 100644
--- a/src/main/java/com/android/tools/r8/ir/code/ConstMethodType.java
+++ b/src/main/java/com/android/tools/r8/ir/code/ConstMethodType.java
@@ -80,7 +80,7 @@
}
@Override
- public boolean isConstString() {
+ public boolean isConstMethodType() {
return true;
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/Dup.java b/src/main/java/com/android/tools/r8/ir/code/Dup.java
index 1f2e418..640d24c 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Dup.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Dup.java
@@ -27,7 +27,7 @@
@Override
public void buildCf(CfBuilder builder) {
- if (this.inValues.get(0).type == ValueType.LONG_OR_DOUBLE) {
+ if (this.inValues.get(0).type.isWide()) {
builder.add(new CfStackInstruction(Opcode.Dup2));
} else {
builder.add(new CfStackInstruction(Opcode.Dup));
@@ -36,12 +36,12 @@
@Override
public boolean identicalNonValueNonPositionParts(Instruction other) {
- return false;
+ throw new Unreachable();
}
@Override
public int compareNonValueParts(Instruction other) {
- return 0;
+ throw new Unreachable();
}
@Override
@@ -61,10 +61,22 @@
}
@Override
- public void insertLoadAndStores(InstructionListIterator it, LoadStoreHelper helper) {}
+ public void insertLoadAndStores(InstructionListIterator it, LoadStoreHelper helper) {
+ // Intentionally empty. Dup is a stack operation.
+ }
@Override
public boolean hasInvariantOutType() {
return false;
}
+
+ @Override
+ public boolean isDup() {
+ return true;
+ }
+
+ @Override
+ public Dup asDup() {
+ return this;
+ }
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/Instruction.java b/src/main/java/com/android/tools/r8/ir/code/Instruction.java
index 44a7a8e..90e8a6a 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Instruction.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Instruction.java
@@ -621,6 +621,14 @@
return null;
}
+ public boolean isDup() {
+ return false;
+ }
+
+ public Dup asDup() {
+ return null;
+ }
+
public boolean isJumpInstruction() {
return false;
}
@@ -1052,6 +1060,14 @@
return null;
}
+ public boolean isSwap() {
+ return false;
+ }
+
+ public Swap asSwap() {
+ return null;
+ }
+
public boolean isLoad() {
return false;
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/StackValue.java b/src/main/java/com/android/tools/r8/ir/code/StackValue.java
index d9dabef..fdff15e 100644
--- a/src/main/java/com/android/tools/r8/ir/code/StackValue.java
+++ b/src/main/java/com/android/tools/r8/ir/code/StackValue.java
@@ -38,6 +38,10 @@
return objectType;
}
+ public StackValue duplicate(int height) {
+ return new StackValue(this.objectType, this.type.toTypeLattice(), height);
+ }
+
@Override
public boolean needsRegister() {
return false;
diff --git a/src/main/java/com/android/tools/r8/ir/code/Swap.java b/src/main/java/com/android/tools/r8/ir/code/Swap.java
new file mode 100644
index 0000000..494fbab
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/ir/code/Swap.java
@@ -0,0 +1,91 @@
+// Copyright (c) 2018, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.ir.code;
+
+import com.android.tools.r8.cf.LoadStoreHelper;
+import com.android.tools.r8.cf.code.CfStackInstruction;
+import com.android.tools.r8.cf.code.CfStackInstruction.Opcode;
+import com.android.tools.r8.errors.Unreachable;
+import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.ir.conversion.CfBuilder;
+import com.android.tools.r8.ir.conversion.DexBuilder;
+import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
+import com.android.tools.r8.ir.optimize.InliningConstraints;
+import java.util.Arrays;
+
+public class Swap extends Instruction {
+
+ public Swap(StackValues dest, StackValues src) {
+ super(dest, src.getStackValues());
+ assert src.getStackValues().size() == 2;
+ assert !(this.inValues.get(0).type.isWide() ^ this.inValues.get(1).type.isWide());
+ }
+
+ public Swap(StackValues dest, StackValue src1, StackValue src2) {
+ super(dest, Arrays.asList(src1, src2));
+ assert !(this.inValues.get(0).type.isWide() ^ !this.inValues.get(1).type.isWide());
+ }
+
+ @Override
+ public void buildDex(DexBuilder builder) {
+ throw new Unreachable("This classfile-specific IR should not be inserted in the Dex backend.");
+ }
+
+ @Override
+ public void buildCf(CfBuilder builder) {
+ if (this.inValues.get(0).type.isWide()) {
+ builder.add(new CfStackInstruction(Opcode.Dup2X2));
+ builder.add(new CfStackInstruction(Opcode.Pop2));
+ } else {
+ builder.add(new CfStackInstruction(Opcode.Swap));
+ }
+ }
+
+ @Override
+ public boolean identicalNonValueNonPositionParts(Instruction other) {
+ throw new Unreachable();
+ }
+
+ @Override
+ public int compareNonValueParts(Instruction other) {
+ throw new Unreachable();
+ }
+
+ @Override
+ public int maxInValueRegister() {
+ return 0;
+ }
+
+ @Override
+ public int maxOutValueRegister() {
+ throw new Unreachable();
+ }
+
+ @Override
+ public ConstraintWithTarget inliningConstraint(
+ InliningConstraints inliningConstraints, DexType invocationContext) {
+ return inliningConstraints.forSwap();
+ }
+
+ @Override
+ public void insertLoadAndStores(InstructionListIterator it, LoadStoreHelper helper) {
+ // Intentionally empty. Swap is a stack operation.
+ }
+
+ @Override
+ public boolean hasInvariantOutType() {
+ return false;
+ }
+
+ @Override
+ public boolean isSwap() {
+ return true;
+ }
+
+ @Override
+ public Swap asSwap() {
+ return this;
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/InliningConstraints.java b/src/main/java/com/android/tools/r8/ir/optimize/InliningConstraints.java
index 7130516..cc85e39 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/InliningConstraints.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/InliningConstraints.java
@@ -237,6 +237,10 @@
return ConstraintWithTarget.ALWAYS;
}
+ public ConstraintWithTarget forSwap() {
+ return ConstraintWithTarget.ALWAYS;
+ }
+
public ConstraintWithTarget forThrow() {
return ConstraintWithTarget.ALWAYS;
}
diff --git a/src/test/java/com/android/tools/r8/D8TestBuilder.java b/src/test/java/com/android/tools/r8/D8TestBuilder.java
index 21a5e0e..4897701 100644
--- a/src/test/java/com/android/tools/r8/D8TestBuilder.java
+++ b/src/test/java/com/android/tools/r8/D8TestBuilder.java
@@ -5,19 +5,19 @@
import com.android.tools.r8.D8Command.Builder;
import com.android.tools.r8.TestBase.Backend;
+import com.android.tools.r8.utils.AndroidApp;
import com.android.tools.r8.utils.InternalOptions;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.Collection;
import java.util.function.Consumer;
+import java.util.function.Supplier;
-public class D8TestBuilder extends TestCompilerBuilder<D8Command, Builder, D8TestBuilder> {
+public class D8TestBuilder
+ extends TestCompilerBuilder<D8Command, Builder, D8TestCompileResult, D8TestBuilder> {
- private final D8Command.Builder builder;
-
- private D8TestBuilder(TestState state, D8Command.Builder builder) {
+ private D8TestBuilder(TestState state, Builder builder) {
super(state, builder, Backend.DEX);
- this.builder = builder;
}
public static D8TestBuilder create(TestState state) {
@@ -30,9 +30,11 @@
}
@Override
- void internalCompile(Builder builder, Consumer<InternalOptions> optionsConsumer)
+ D8TestCompileResult internalCompile(
+ Builder builder, Consumer<InternalOptions> optionsConsumer, Supplier<AndroidApp> app)
throws CompilationFailedException {
ToolHelper.runD8(builder, optionsConsumer);
+ return new D8TestCompileResult(getState(), app.get());
}
public D8TestBuilder addClasspathClasses(Class<?>... classes) {
diff --git a/src/test/java/com/android/tools/r8/D8TestCompileResult.java b/src/test/java/com/android/tools/r8/D8TestCompileResult.java
new file mode 100644
index 0000000..482a611
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/D8TestCompileResult.java
@@ -0,0 +1,18 @@
+// Copyright (c) 2018, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+package com.android.tools.r8;
+
+import com.android.tools.r8.TestBase.Backend;
+import com.android.tools.r8.utils.AndroidApp;
+
+public class D8TestCompileResult extends TestCompileResult {
+ D8TestCompileResult(TestState state, AndroidApp app) {
+ super(state, app);
+ }
+
+ @Override
+ public Backend getBackend() {
+ return Backend.DEX;
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/R8TestBuilder.java b/src/test/java/com/android/tools/r8/R8TestBuilder.java
index 74b40b0..3b01a71 100644
--- a/src/test/java/com/android/tools/r8/R8TestBuilder.java
+++ b/src/test/java/com/android/tools/r8/R8TestBuilder.java
@@ -6,6 +6,7 @@
import com.android.tools.r8.R8Command.Builder;
import com.android.tools.r8.TestBase.Backend;
import com.android.tools.r8.origin.Origin;
+import com.android.tools.r8.utils.AndroidApp;
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.StringUtils;
import java.util.ArrayList;
@@ -13,14 +14,13 @@
import java.util.Collection;
import java.util.List;
import java.util.function.Consumer;
+import java.util.function.Supplier;
-public class R8TestBuilder extends TestCompilerBuilder<R8Command, Builder, R8TestBuilder> {
-
- private final R8Command.Builder builder;
+public class R8TestBuilder
+ extends TestCompilerBuilder<R8Command, Builder, R8TestCompileResult, R8TestBuilder> {
private R8TestBuilder(TestState state, Builder builder, Backend backend) {
super(state, builder, backend);
- this.builder = builder;
}
public static R8TestBuilder create(TestState state, Backend backend) {
@@ -35,12 +35,16 @@
}
@Override
- void internalCompile(Builder builder, Consumer<InternalOptions> optionsConsumer)
+ R8TestCompileResult internalCompile(
+ Builder builder, Consumer<InternalOptions> optionsConsumer, Supplier<AndroidApp> app)
throws CompilationFailedException {
if (enableInliningAnnotations) {
ToolHelper.allowTestProguardOptions(builder);
}
+ StringBuilder proguardMapBuilder = new StringBuilder();
+ builder.setProguardMapConsumer((string, ignore) -> proguardMapBuilder.append(string));
ToolHelper.runR8WithoutResult(builder.build(), optionsConsumer);
+ return new R8TestCompileResult(getState(), backend, app.get(), proguardMapBuilder.toString());
}
public R8TestBuilder addDataResources(List<DataEntryResource> resources) {
diff --git a/src/test/java/com/android/tools/r8/R8TestCompileResult.java b/src/test/java/com/android/tools/r8/R8TestCompileResult.java
new file mode 100644
index 0000000..45fb31c
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/R8TestCompileResult.java
@@ -0,0 +1,32 @@
+// Copyright (c) 2018, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+package com.android.tools.r8;
+
+import com.android.tools.r8.TestBase.Backend;
+import com.android.tools.r8.utils.AndroidApp;
+import com.android.tools.r8.utils.codeinspector.CodeInspector;
+import java.io.IOException;
+import java.util.concurrent.ExecutionException;
+
+public class R8TestCompileResult extends TestCompileResult {
+
+ private final Backend backend;
+ private final String proguardMap;
+
+ R8TestCompileResult(TestState state, Backend backend, AndroidApp app, String proguardMap) {
+ super(state, app);
+ this.backend = backend;
+ this.proguardMap = proguardMap;
+ }
+
+ @Override
+ public Backend getBackend() {
+ return backend;
+ }
+
+ @Override
+ public CodeInspector inspector() throws IOException, ExecutionException {
+ return new CodeInspector(app, proguardMap);
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/TestCompileResult.java b/src/test/java/com/android/tools/r8/TestCompileResult.java
index 4e7cf37..7505a83 100644
--- a/src/test/java/com/android/tools/r8/TestCompileResult.java
+++ b/src/test/java/com/android/tools/r8/TestCompileResult.java
@@ -12,19 +12,23 @@
import java.nio.file.Path;
import java.util.concurrent.ExecutionException;
-public class TestCompileResult {
- private final TestState state;
- private final Backend backend;
- private final AndroidApp app;
+public abstract class TestCompileResult {
+ final TestState state;
+ final AndroidApp app;
- public TestCompileResult(TestState state, Backend backend, AndroidApp app) {
+ TestCompileResult(TestState state, AndroidApp app) {
this.state = state;
- this.backend = backend;
this.app = app;
}
+ public abstract Backend getBackend();
+
+ public TestRunResult run(Class<?> mainClass) throws IOException {
+ return run(mainClass.getTypeName());
+ }
+
public TestRunResult run(String mainClass) throws IOException {
- switch (backend) {
+ switch (getBackend()) {
case DEX:
return runArt(mainClass);
case CF:
@@ -34,6 +38,12 @@
}
}
+ public TestCompileResult writeToZip(Path file) throws IOException {
+ app.writeToZip(
+ file, getBackend() == Backend.DEX ? OutputMode.DexIndexed : OutputMode.ClassFile);
+ return this;
+ }
+
public CodeInspector inspector() throws IOException, ExecutionException {
return new CodeInspector(app);
}
diff --git a/src/test/java/com/android/tools/r8/TestCompilerBuilder.java b/src/test/java/com/android/tools/r8/TestCompilerBuilder.java
index db25352..4706125 100644
--- a/src/test/java/com/android/tools/r8/TestCompilerBuilder.java
+++ b/src/test/java/com/android/tools/r8/TestCompilerBuilder.java
@@ -5,17 +5,21 @@
import com.android.tools.r8.TestBase.Backend;
import com.android.tools.r8.utils.AndroidApiLevel;
+import com.android.tools.r8.utils.AndroidApp;
import com.android.tools.r8.utils.AndroidAppConsumers;
import com.android.tools.r8.utils.InternalOptions;
+import com.google.common.base.Suppliers;
import java.io.IOException;
import java.nio.file.Path;
import java.util.Collection;
import java.util.function.Consumer;
+import java.util.function.Supplier;
public abstract class TestCompilerBuilder<
C extends BaseCompilerCommand,
B extends BaseCompilerCommand.Builder<C, B>,
- T extends TestCompilerBuilder<C, B, T>>
+ R extends TestCompileResult,
+ T extends TestCompilerBuilder<C, B, R, T>>
extends TestBuilder<T> {
public static final Consumer<InternalOptions> DEFAULT_OPTIONS =
@@ -24,8 +28,8 @@
public void accept(InternalOptions options) {}
};
- private final B builder;
- private final Backend backend;
+ final B builder;
+ final Backend backend;
// Default initialized setup. Can be overwritten if needed.
private Path defaultLibrary;
@@ -43,7 +47,8 @@
abstract T self();
- abstract void internalCompile(B builder, Consumer<InternalOptions> optionsConsumer)
+ abstract R internalCompile(
+ B builder, Consumer<InternalOptions> optionsConsumer, Supplier<AndroidApp> app)
throws CompilationFailedException;
public T addOptionsModification(Consumer<InternalOptions> optionsConsumer) {
@@ -51,7 +56,7 @@
return self();
}
- public TestCompileResult compile() throws CompilationFailedException {
+ public R compile() throws CompilationFailedException {
AndroidAppConsumers sink = new AndroidAppConsumers();
builder.setProgramConsumer(sink.wrapProgramConsumer(programConsumer));
if (defaultLibrary != null) {
@@ -60,8 +65,7 @@
if (backend == Backend.DEX && defaultMinApiLevel != null) {
builder.setMinApiLevel(defaultMinApiLevel.getLevel());
}
- internalCompile(builder, optionsConsumer);
- return new TestCompileResult(getState(), backend, sink.build());
+ return internalCompile(builder, optionsConsumer, Suppliers.memoize(sink::build));
}
@Override
diff --git a/src/test/java/com/android/tools/r8/cf/BootstrapCurrentEqualityTest.java b/src/test/java/com/android/tools/r8/cf/BootstrapCurrentEqualityTest.java
index 7202914..d2d434a 100644
--- a/src/test/java/com/android/tools/r8/cf/BootstrapCurrentEqualityTest.java
+++ b/src/test/java/com/android/tools/r8/cf/BootstrapCurrentEqualityTest.java
@@ -36,8 +36,8 @@
import org.junit.rules.TemporaryFolder;
/**
- * This test relies on a freshly built from builds/libs/r8lib_with_deps.jar. If this test fails
- * rebuild r8lib_with_deps by calling test.py or gradle r8libWithdeps.
+ * This test relies on a freshly built builds/libs/r8lib_with_deps.jar. If this test fails
+ * remove build directory and rebuild r8lib_with_deps by calling test.py or gradle r8libWithdeps.
*/
public class BootstrapCurrentEqualityTest extends TestBase {
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/CodeInspector.java b/src/test/java/com/android/tools/r8/utils/codeinspector/CodeInspector.java
index 28404f0..660156a 100644
--- a/src/test/java/com/android/tools/r8/utils/codeinspector/CodeInspector.java
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/CodeInspector.java
@@ -26,6 +26,7 @@
import com.android.tools.r8.naming.MemberNaming.MethodSignature;
import com.android.tools.r8.naming.signature.GenericSignatureAction;
import com.android.tools.r8.naming.signature.GenericSignatureParser;
+import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.utils.AndroidApp;
import com.android.tools.r8.utils.DescriptorUtils;
import com.android.tools.r8.utils.InternalOptions;
@@ -111,10 +112,18 @@
return internalOptions;
}
- public CodeInspector(AndroidApp app, Path proguardMap) throws IOException, ExecutionException {
+ public CodeInspector(AndroidApp app, Path proguardMapFile)
+ throws IOException, ExecutionException {
this(
new ApplicationReader(app, runOptionsConsumer(null), new Timing("CodeInspector"))
- .read(StringResource.fromFile(proguardMap)));
+ .read(StringResource.fromFile(proguardMapFile)));
+ }
+
+ public CodeInspector(AndroidApp app, String proguardMapContent)
+ throws IOException, ExecutionException {
+ this(
+ new ApplicationReader(app, runOptionsConsumer(null), new Timing("CodeInspector"))
+ .read(StringResource.fromString(proguardMapContent, Origin.unknown())));
}
public CodeInspector(DexApplication application) {
diff --git a/tools/test.py b/tools/test.py
index cd9b70f..f1543f1 100755
--- a/tools/test.py
+++ b/tools/test.py
@@ -103,6 +103,9 @@
if 'BUILDBOT_BUILDERNAME' in os.environ:
gradle.RunGradle(['clean'])
+ # Build R8lib with dependencies for bootstrapping tests before adding test sources
+ gradle.RunGradle(['r8libwithdeps'])
+
gradle_args = ['--stacktrace']
# Set all necessary Gradle properties and options first.
if options.verbose:
@@ -156,8 +159,6 @@
gradle_args.append('-PHEAD_sha1=' + utils.get_HEAD_sha1())
# Add Gradle tasks
gradle_args.append('cleanTest')
- # Build R8lib with dependencies for bootstrapping tests.
- gradle_args.append('r8libWithDeps')
gradle_args.append('test')
# Test filtering. Must always follow the 'test' task.
for testFilter in args: