Merge "[CF] Implement simple store/load elimination and avoid storing constants."
diff --git a/src/main/java/com/android/tools/r8/graph/DexMethod.java b/src/main/java/com/android/tools/r8/graph/DexMethod.java
index cc8e0db..2fe0796 100644
--- a/src/main/java/com/android/tools/r8/graph/DexMethod.java
+++ b/src/main/java/com/android/tools/r8/graph/DexMethod.java
@@ -23,7 +23,8 @@
this.name = name;
if (!name.isValidMethodName()) {
throw new CompilationError(
- "Method name '" + name.toString() + "' cannot be represented in dex format.");
+ "Method name '" + name.toASCIIString() + "' in class '" + holder.toSourceString() +
+ "' cannot be represented in dex format.");
}
}
diff --git a/src/main/java/com/android/tools/r8/graph/DexString.java b/src/main/java/com/android/tools/r8/graph/DexString.java
index 434bad7..4bc9a50 100644
--- a/src/main/java/com/android/tools/r8/graph/DexString.java
+++ b/src/main/java/com/android/tools/r8/graph/DexString.java
@@ -6,6 +6,7 @@
import com.android.tools.r8.dex.Constants;
import com.android.tools.r8.dex.IndexedItemCollection;
import com.android.tools.r8.naming.NamingLens;
+import com.android.tools.r8.utils.StringUtils;
import java.io.UTFDataFormatException;
import java.util.Arrays;
@@ -49,6 +50,23 @@
}
}
+ public String toASCIIString() {
+ try {
+ String s = decode();
+ StringBuilder builder = new StringBuilder();
+ for (char ch : s.toCharArray()) {
+ if (0x1f < ch && ch < 0x7f) { // 0 - 0x1f and 0x7f are control characters.
+ builder.append(ch);
+ } else {
+ builder.append("\\u").append(StringUtils.hexString(ch, 4, false));
+ }
+ }
+ return builder.toString();
+ } catch (UTFDataFormatException e) {
+ throw new RuntimeException("Bad format", e);
+ }
+ }
+
public int numberOfLeadingSquareBrackets() {
int result = 0;
while (content.length > result && content[result] == ((byte) '[')) {
diff --git a/src/main/java/com/android/tools/r8/utils/StringUtils.java b/src/main/java/com/android/tools/r8/utils/StringUtils.java
index 8712b7a..de77dac 100644
--- a/src/main/java/com/android/tools/r8/utils/StringUtils.java
+++ b/src/main/java/com/android/tools/r8/utils/StringUtils.java
@@ -155,26 +155,36 @@
}
public static String hexString(int value, int width) {
+ return hexString(value, width, false);
+ }
+
+ public static String hexString(int value, int width, boolean zeroXPrefix) {
assert(0 <= width && width <= 8);
+ String prefix = zeroXPrefix ? "0x" : "";
String hex = Integer.toHexString(value);
if (value >= 0) {
- return "0x" + zeroPrefixString(hex, width);
+ return prefix + zeroPrefixString(hex, width);
} else {
// Negative ints are always formatted as 8 characters.
assert(hex.length() == 8);
- return "0x" + hex;
+ return prefix + hex;
}
}
public static String hexString(long value, int width) {
+ return hexString(value, width, false);
+ }
+
+ public static String hexString(long value, int width, boolean zeroXPrefix) {
assert(0 <= width && width <= 16);
+ String prefix = zeroXPrefix ? "0x" : "";
String hex = Long.toHexString(value);
if (value >= 0) {
- return "0x" + zeroPrefixString(hex, width);
+ return prefix + zeroPrefixString(hex, width);
} else {
// Negative longs are always formatted as 16 characters.
assert(hex.length() == 16);
- return "0x" + hex;
+ return prefix + hex;
}
}
diff --git a/src/test/java/com/android/tools/r8/dex/DexStringTest.java b/src/test/java/com/android/tools/r8/dex/DexStringTest.java
index fa7f332..b12d876 100644
--- a/src/test/java/com/android/tools/r8/dex/DexStringTest.java
+++ b/src/test/java/com/android/tools/r8/dex/DexStringTest.java
@@ -88,4 +88,21 @@
assertEquals(0, s.content[length - 1]);
assertEquals(encodedLength, length - 1);
}
+
+ @Test
+ public void testToASCIIString() {
+ DexItemFactory factory = new DexItemFactory();
+ assertEquals("\\u0000", factory.createString("\u0000").toASCIIString());
+ assertEquals("\\u0001", factory.createString("\u0001").toASCIIString());
+ assertEquals("\\u001f", factory.createString("\u001f").toASCIIString());
+ assertEquals(" ", factory.createString("\u0020").toASCIIString());
+ assertEquals("~", factory.createString("\u007e").toASCIIString());
+ assertEquals("\\u007f", factory.createString("\u007f").toASCIIString());
+ assertEquals("\\u0080", factory.createString("\u0080").toASCIIString());
+ assertEquals("\\u07ff", factory.createString("\u07ff").toASCIIString());
+ assertEquals("\\u0800", factory.createString("\u0800").toASCIIString());
+ assertEquals("\\uffff", factory.createString("\uffff").toASCIIString());
+ assertEquals("\\ud800\\udc00", factory.createString("\ud800\udc00").toASCIIString());
+ assertEquals("\\udbff\\udfff", factory.createString("\udbff\udfff").toASCIIString());
+ }
}
diff --git a/src/test/java/com/android/tools/r8/jasmin/InvalidMethodNames.java b/src/test/java/com/android/tools/r8/jasmin/InvalidMethodNames.java
index 7b035f6..0aa0f59 100644
--- a/src/test/java/com/android/tools/r8/jasmin/InvalidMethodNames.java
+++ b/src/test/java/com/android/tools/r8/jasmin/InvalidMethodNames.java
@@ -3,12 +3,14 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.jasmin;
-import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.errors.CompilationError;
+import com.android.tools.r8.graph.DexString;
import com.google.common.collect.ImmutableList;
import java.util.Arrays;
import java.util.Collection;
@@ -43,6 +45,8 @@
t.printStackTrace(System.out);
fail("Invalid dex method names should be compilation errors.");
}
+ String asciiString = new DexString(name).toASCIIString();
+ assertTrue(t.getMessage().contains(asciiString));
} catch (Throwable t) {
t.printStackTrace(System.out);
fail("Invalid dex method names should be compilation errors.");