[LIR] Add support for item-based const string.
Also migrates legacy example tests regalloc, returns and staticfield.
Bug: b/225838009
Bug: b/167145686
Change-Id: If1a173572d003d7ad760b93aaffc74fd732113d5
diff --git a/src/main/java/com/android/tools/r8/ir/code/DexItemBasedConstString.java b/src/main/java/com/android/tools/r8/ir/code/DexItemBasedConstString.java
index 3a5623d..51182ac 100644
--- a/src/main/java/com/android/tools/r8/ir/code/DexItemBasedConstString.java
+++ b/src/main/java/com/android/tools/r8/ir/code/DexItemBasedConstString.java
@@ -22,6 +22,7 @@
import com.android.tools.r8.ir.optimize.DeadCodeRemover.DeadInstructionResult;
import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
import com.android.tools.r8.ir.optimize.InliningConstraints;
+import com.android.tools.r8.lightir.LirBuilder;
import com.android.tools.r8.naming.dexitembasedstring.NameComputationInfo;
public class DexItemBasedConstString extends ConstInstruction {
@@ -89,6 +90,11 @@
}
@Override
+ public void buildLir(LirBuilder<Value, ?> builder) {
+ builder.addDexItemBasedConstString(item, nameComputationInfo);
+ }
+
+ @Override
public boolean identicalNonValueNonPositionParts(Instruction other) {
return other.isDexItemBasedConstString()
&& other.asDexItemBasedConstString().item == item
diff --git a/src/main/java/com/android/tools/r8/lightir/Lir2IRConverter.java b/src/main/java/com/android/tools/r8/lightir/Lir2IRConverter.java
index d2a3038..abccb80 100644
--- a/src/main/java/com/android/tools/r8/lightir/Lir2IRConverter.java
+++ b/src/main/java/com/android/tools/r8/lightir/Lir2IRConverter.java
@@ -8,6 +8,7 @@
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexField;
import com.android.tools.r8.graph.DexMethod;
+import com.android.tools.r8.graph.DexReference;
import com.android.tools.r8.graph.DexString;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.ProgramMethod;
@@ -29,6 +30,7 @@
import com.android.tools.r8.ir.code.ConstString;
import com.android.tools.r8.ir.code.DebugLocalWrite;
import com.android.tools.r8.ir.code.DebugPosition;
+import com.android.tools.r8.ir.code.DexItemBasedConstString;
import com.android.tools.r8.ir.code.Div;
import com.android.tools.r8.ir.code.Goto;
import com.android.tools.r8.ir.code.IRCode;
@@ -72,6 +74,7 @@
import com.android.tools.r8.ir.conversion.MethodConversionOptions.MutableMethodConversionOptions;
import com.android.tools.r8.lightir.LirBuilder.IntSwitchPayload;
import com.android.tools.r8.lightir.LirCode.PositionEntry;
+import com.android.tools.r8.naming.dexitembasedstring.NameComputationInfo;
import com.android.tools.r8.utils.ListUtils;
import com.google.common.collect.ImmutableList;
import it.unimi.dsi.fastutil.ints.Int2IntMap;
@@ -426,11 +429,22 @@
@Override
public void onConstString(DexString string) {
- Value dest = getOutValueForNextInstruction(TypeElement.stringClassType(appView));
+ Value dest =
+ getOutValueForNextInstruction(
+ TypeElement.stringClassType(appView, Nullability.definitelyNotNull()));
addInstruction(new ConstString(dest, string));
}
@Override
+ public void onDexItemBasedConstString(
+ DexReference item, NameComputationInfo<?> nameComputationInfo) {
+ Value dest =
+ getOutValueForNextInstruction(
+ TypeElement.stringClassType(appView, Nullability.definitelyNotNull()));
+ addInstruction(new DexItemBasedConstString(dest, item, nameComputationInfo));
+ }
+
+ @Override
public void onConstClass(DexType type) {
Value dest =
getOutValueForNextInstruction(
diff --git a/src/main/java/com/android/tools/r8/lightir/LirBuilder.java b/src/main/java/com/android/tools/r8/lightir/LirBuilder.java
index dd33679..b0334c9 100644
--- a/src/main/java/com/android/tools/r8/lightir/LirBuilder.java
+++ b/src/main/java/com/android/tools/r8/lightir/LirBuilder.java
@@ -15,6 +15,7 @@
import com.android.tools.r8.graph.DexItem;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexMethod;
+import com.android.tools.r8.graph.DexReference;
import com.android.tools.r8.graph.DexString;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.ir.analysis.type.TypeElement;
@@ -33,6 +34,7 @@
import com.android.tools.r8.lightir.LirCode.DebugLocalInfoTable;
import com.android.tools.r8.lightir.LirCode.PositionEntry;
import com.android.tools.r8.lightir.LirCode.TryCatchTable;
+import com.android.tools.r8.naming.dexitembasedstring.NameComputationInfo;
import com.android.tools.r8.utils.ListUtils;
import com.google.common.collect.ImmutableList;
import it.unimi.dsi.fastutil.ints.Int2ReferenceMap;
@@ -125,6 +127,14 @@
}
}
+ public static class NameComputationPayload extends InstructionPayload {
+ public final NameComputationInfo<?> nameComputationInfo;
+
+ public NameComputationPayload(NameComputationInfo<?> nameComputationInfo) {
+ this.nameComputationInfo = nameComputationInfo;
+ }
+ }
+
public LirBuilder(DexMethod method, LirEncodingStrategy<V, EV> strategy, DexItemFactory factory) {
this.factory = factory;
constants = new Reference2IntOpenHashMap<>();
@@ -772,4 +782,11 @@
return addInstructionTemplate(
opcode, Collections.emptyList(), ImmutableList.of(array, index, value));
}
+
+ public LirBuilder<V, EV> addDexItemBasedConstString(
+ DexReference item, NameComputationInfo<?> nameComputationInfo) {
+ NameComputationPayload payload = new NameComputationPayload(nameComputationInfo);
+ return addInstructionTemplate(
+ LirOpcodes.ITEMBASEDCONSTSTRING, ImmutableList.of(item, payload), Collections.emptyList());
+ }
}
diff --git a/src/main/java/com/android/tools/r8/lightir/LirOpcodes.java b/src/main/java/com/android/tools/r8/lightir/LirOpcodes.java
index c4f2076..e4111ff 100644
--- a/src/main/java/com/android/tools/r8/lightir/LirOpcodes.java
+++ b/src/main/java/com/android/tools/r8/lightir/LirOpcodes.java
@@ -196,6 +196,7 @@
int DEBUGLOCALWRITE = 213;
int INVOKENEWARRAY = 214;
int NEWARRAYFILLEDDATA = 215;
+ int ITEMBASEDCONSTSTRING = 216;
static String toString(int opcode) {
switch (opcode) {
@@ -512,6 +513,8 @@
return "INVOKENEWARRAY";
case NEWARRAYFILLEDDATA:
return "NEWARRAYFILLEDDATA";
+ case ITEMBASEDCONSTSTRING:
+ return "ITEMBASEDCONSTSTRING";
default:
throw new Unreachable("Unexpected LIR opcode: " + opcode);
diff --git a/src/main/java/com/android/tools/r8/lightir/LirParsedInstructionCallback.java b/src/main/java/com/android/tools/r8/lightir/LirParsedInstructionCallback.java
index e7733fc..8277988 100644
--- a/src/main/java/com/android/tools/r8/lightir/LirParsedInstructionCallback.java
+++ b/src/main/java/com/android/tools/r8/lightir/LirParsedInstructionCallback.java
@@ -9,6 +9,7 @@
import com.android.tools.r8.graph.DexField;
import com.android.tools.r8.graph.DexItem;
import com.android.tools.r8.graph.DexMethod;
+import com.android.tools.r8.graph.DexReference;
import com.android.tools.r8.graph.DexString;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.ir.code.IfType;
@@ -16,6 +17,8 @@
import com.android.tools.r8.ir.code.NumericType;
import com.android.tools.r8.lightir.LirBuilder.FillArrayPayload;
import com.android.tools.r8.lightir.LirBuilder.IntSwitchPayload;
+import com.android.tools.r8.lightir.LirBuilder.NameComputationPayload;
+import com.android.tools.r8.naming.dexitembasedstring.NameComputationInfo;
import java.util.ArrayList;
import java.util.List;
@@ -87,6 +90,11 @@
onInstruction();
}
+ public void onDexItemBasedConstString(
+ DexReference item, NameComputationInfo<?> nameComputationInfo) {
+ onInstruction();
+ }
+
public void onConstClass(DexType type) {
onInstruction();
}
@@ -1043,6 +1051,14 @@
onCmpInstruction(opcode, leftValue, rightValue);
return;
}
+ case LirOpcodes.ITEMBASEDCONSTSTRING:
+ {
+ DexReference item = (DexReference) getConstantItem(view.getNextConstantOperand());
+ NameComputationPayload payload =
+ (NameComputationPayload) getConstantItem(view.getNextConstantOperand());
+ onDexItemBasedConstString(item, payload.nameComputationInfo);
+ return;
+ }
default:
throw new Unimplemented("No dispatch for opcode " + LirOpcodes.toString(opcode));
}
diff --git a/src/main/java/com/android/tools/r8/lightir/LirPrinter.java b/src/main/java/com/android/tools/r8/lightir/LirPrinter.java
index d30288b..7aaf668 100644
--- a/src/main/java/com/android/tools/r8/lightir/LirPrinter.java
+++ b/src/main/java/com/android/tools/r8/lightir/LirPrinter.java
@@ -6,12 +6,14 @@
import com.android.tools.r8.errors.Unimplemented;
import com.android.tools.r8.graph.DexField;
import com.android.tools.r8.graph.DexMethod;
+import com.android.tools.r8.graph.DexReference;
import com.android.tools.r8.graph.DexString;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.ir.code.IfType;
import com.android.tools.r8.ir.code.MemberType;
import com.android.tools.r8.ir.code.NumericType;
import com.android.tools.r8.lightir.LirBuilder.IntSwitchPayload;
+import com.android.tools.r8.naming.dexitembasedstring.NameComputationInfo;
import com.android.tools.r8.utils.StringUtils;
import java.util.Arrays;
import java.util.List;
@@ -151,6 +153,12 @@
}
@Override
+ public void onDexItemBasedConstString(
+ DexReference item, NameComputationInfo<?> nameComputationInfo) {
+ appendOutValue().append("item(").append(item).append(")");
+ }
+
+ @Override
public void onConstClass(DexType type) {
appendOutValue().append("class(").append(type).append(")");
}
diff --git a/src/test/java/com/android/tools/r8/R8RunExamplesTest.java b/src/test/java/com/android/tools/r8/R8RunExamplesTest.java
index 44bf2f7..a303b8c 100644
--- a/src/test/java/com/android/tools/r8/R8RunExamplesTest.java
+++ b/src/test/java/com/android/tools/r8/R8RunExamplesTest.java
@@ -27,9 +27,6 @@
String[] tests = {
"arithmetic.Arithmetic",
"inlining.Inlining",
- "regalloc.RegAlloc",
- "returns.Returns",
- "staticfield.StaticField",
"stringbuilding.StringBuilding",
"switches.Switches",
"sync.Sync",
diff --git a/src/test/java/com/android/tools/r8/debug/ExamplesDebugTest.java b/src/test/java/com/android/tools/r8/debug/ExamplesDebugTest.java
index 3e2ae80..c870a8e 100644
--- a/src/test/java/com/android/tools/r8/debug/ExamplesDebugTest.java
+++ b/src/test/java/com/android/tools/r8/debug/ExamplesDebugTest.java
@@ -60,22 +60,6 @@
}
@Test
- public void testRegAlloc() throws Exception {
- testDebugging("regalloc", "RegAlloc");
- }
-
- @Test
- public void testReturns() throws Exception {
- testDebugging("returns", "Returns");
- }
-
- @Test
- public void testStaticField() throws Exception {
- // TODO(b/79671093): D8 has different line number info during stepping.
- testDebuggingJvmOnly("staticfield", "StaticField");
- }
-
- @Test
public void testStringBuilding() throws Exception {
testDebugging("stringbuilding", "StringBuilding");
}
diff --git a/src/test/examples/regalloc/RegAlloc.java b/src/test/java/com/android/tools/r8/examples/regalloc/RegAlloc.java
similarity index 99%
rename from src/test/examples/regalloc/RegAlloc.java
rename to src/test/java/com/android/tools/r8/examples/regalloc/RegAlloc.java
index 68ad054..0b7474c 100644
--- a/src/test/examples/regalloc/RegAlloc.java
+++ b/src/test/java/com/android/tools/r8/examples/regalloc/RegAlloc.java
@@ -5,7 +5,7 @@
// This code is not run directly. It needs to be compiled to dex code.
// 'regalloc.dex' is what is run.
-package regalloc;
+package com.android.tools.r8.examples.regalloc;
// Various test cases that are challenging for the register allocator.
public class RegAlloc {
diff --git a/src/test/java/com/android/tools/r8/examples/regalloc/RegAllocTestRunner.java b/src/test/java/com/android/tools/r8/examples/regalloc/RegAllocTestRunner.java
new file mode 100644
index 0000000..df0c295
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/examples/regalloc/RegAllocTestRunner.java
@@ -0,0 +1,65 @@
+// Copyright (c) 2023, 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.examples.regalloc;
+
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.examples.ExamplesTestBase;
+import com.android.tools.r8.examples.regalloc.RegAlloc.BoxedInteger;
+import com.android.tools.r8.utils.StringUtils;
+import com.google.common.collect.ImmutableList;
+import java.util.List;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class RegAllocTestRunner extends ExamplesTestBase {
+
+ @Parameterized.Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withAllRuntimesAndApiLevels().enableApiLevelsForCf().build();
+ }
+
+ public RegAllocTestRunner(TestParameters parameters) {
+ super(parameters);
+ }
+
+ @Override
+ public Class<?> getMainClass() {
+ return RegAlloc.class;
+ }
+
+ @Override
+ public List<Class<?>> getTestClasses() throws Exception {
+ return ImmutableList.of(getMainClass(), BoxedInteger.class);
+ }
+
+ @Override
+ public String getExpected() {
+ return StringUtils.lines(
+ "binaryOpUsingHighRegistersArguments: 17016 257 507",
+ "binaryDoubleOpUsingHighRegistersArguments: 251.0 125.0",
+ "binaryOpUsingHighRegistersLocals 518",
+ "instance get many registers42",
+ "sum: 33670",
+ "binaryOpUsingHighRegistersLocals 518.0",
+ "sum: 33670.0");
+ }
+
+ @Test
+ public void testDesugaring() throws Exception {
+ runTestDesugaring();
+ }
+
+ @Test
+ public void testR8() throws Exception {
+ runTestR8();
+ }
+
+ @Test
+ public void testDebug() throws Exception {
+ runTestDebugComparator();
+ }
+}
diff --git a/src/test/examples/returns/Returns.java b/src/test/java/com/android/tools/r8/examples/returns/Returns.java
similarity index 92%
rename from src/test/examples/returns/Returns.java
rename to src/test/java/com/android/tools/r8/examples/returns/Returns.java
index c496ce5..f3955df 100644
--- a/src/test/examples/returns/Returns.java
+++ b/src/test/java/com/android/tools/r8/examples/returns/Returns.java
@@ -2,7 +2,7 @@
// 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 returns;
+package com.android.tools.r8.examples.returns;
public class Returns {
public static void main(String[] args) {
diff --git a/src/test/java/com/android/tools/r8/examples/returns/ReturnsTestRunner.java b/src/test/java/com/android/tools/r8/examples/returns/ReturnsTestRunner.java
new file mode 100644
index 0000000..1a18ae6
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/examples/returns/ReturnsTestRunner.java
@@ -0,0 +1,49 @@
+// Copyright (c) 2023, 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.examples.returns;
+
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.examples.ExamplesTestBase;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class ReturnsTestRunner extends ExamplesTestBase {
+
+ @Parameterized.Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withAllRuntimesAndApiLevels().enableApiLevelsForCf().build();
+ }
+
+ public ReturnsTestRunner(TestParameters parameters) {
+ super(parameters);
+ }
+
+ @Override
+ public Class<?> getMainClass() {
+ return Returns.class;
+ }
+
+ @Override
+ public String getExpected() {
+ return "";
+ }
+
+ @Test
+ public void testDesugaring() throws Exception {
+ runTestDesugaring();
+ }
+
+ @Test
+ public void testR8() throws Exception {
+ runTestR8();
+ }
+
+ @Test
+ public void testDebug() throws Exception {
+ runTestDebugComparator();
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/examples/returns/StaticFieldTestRunner.java b/src/test/java/com/android/tools/r8/examples/returns/StaticFieldTestRunner.java
new file mode 100644
index 0000000..81ca334
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/examples/returns/StaticFieldTestRunner.java
@@ -0,0 +1,54 @@
+// Copyright (c) 2023, 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.examples.returns;
+
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.examples.ExamplesTestBase;
+import com.android.tools.r8.examples.staticfield.StaticField;
+import com.android.tools.r8.utils.StringUtils;
+import org.junit.Assume;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class StaticFieldTestRunner extends ExamplesTestBase {
+
+ @Parameterized.Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withAllRuntimesAndApiLevels().enableApiLevelsForCf().build();
+ }
+
+ public StaticFieldTestRunner(TestParameters parameters) {
+ super(parameters);
+ }
+
+ @Override
+ public Class<?> getMainClass() {
+ return StaticField.class;
+ }
+
+ @Override
+ public String getExpected() {
+ return StringUtils.lines("101010", "101010", "ABC", "ABC");
+ }
+
+ @Test
+ public void testDesugaring() throws Exception {
+ runTestDesugaring();
+ }
+
+ @Test
+ public void testR8() throws Exception {
+ runTestR8();
+ }
+
+ @Test
+ public void testDebug() throws Exception {
+ // TODO(b/79671093): DEX has different line number info during stepping.
+ Assume.assumeTrue(parameters.isCfRuntime());
+ runTestDebugComparator();
+ }
+}
diff --git a/src/test/examples/staticfield/StaticField.java b/src/test/java/com/android/tools/r8/examples/staticfield/StaticField.java
similarity index 95%
rename from src/test/examples/staticfield/StaticField.java
rename to src/test/java/com/android/tools/r8/examples/staticfield/StaticField.java
index f4d5854..5c48a2e 100644
--- a/src/test/examples/staticfield/StaticField.java
+++ b/src/test/java/com/android/tools/r8/examples/staticfield/StaticField.java
@@ -2,7 +2,7 @@
// 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 staticfield;
+package com.android.tools.r8.examples.staticfield;
public class StaticField {