Remove the boolean and byte distinction from array member types.
This CL also ensures that field member types are not conflated with those of
array instructions.
Bug: 109788783
Change-Id: I238d6b225d753c6f30db8a127017afb214c93bd2
diff --git a/src/main/java/com/android/tools/r8/cf/CfPrinter.java b/src/main/java/com/android/tools/r8/cf/CfPrinter.java
index 4378118..3866f5f 100644
--- a/src/main/java/com/android/tools/r8/cf/CfPrinter.java
+++ b/src/main/java/com/android/tools/r8/cf/CfPrinter.java
@@ -605,8 +605,7 @@
switch (type) {
case OBJECT:
return 'a';
- case BOOLEAN:
- case BYTE:
+ case BOOLEAN_OR_BYTE:
return 'b';
case CHAR:
return 'c';
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfArrayLoad.java b/src/main/java/com/android/tools/r8/cf/code/CfArrayLoad.java
index e77a59e..17dcff2 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfArrayLoad.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfArrayLoad.java
@@ -32,8 +32,7 @@
switch (type) {
case OBJECT:
return Opcodes.AALOAD;
- case BYTE:
- case BOOLEAN:
+ case BOOLEAN_OR_BYTE:
return Opcodes.BALOAD;
case CHAR:
return Opcodes.CALOAD;
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfArrayStore.java b/src/main/java/com/android/tools/r8/cf/code/CfArrayStore.java
index ff76777..463d697 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfArrayStore.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfArrayStore.java
@@ -30,8 +30,7 @@
switch (type) {
case OBJECT:
return Opcodes.AASTORE;
- case BYTE:
- case BOOLEAN:
+ case BOOLEAN_OR_BYTE:
return Opcodes.BASTORE;
case CHAR:
return Opcodes.CASTORE;
diff --git a/src/main/java/com/android/tools/r8/code/AgetBoolean.java b/src/main/java/com/android/tools/r8/code/AgetBoolean.java
index c671af1..fc05007 100644
--- a/src/main/java/com/android/tools/r8/code/AgetBoolean.java
+++ b/src/main/java/com/android/tools/r8/code/AgetBoolean.java
@@ -37,7 +37,7 @@
@Override
public void buildIR(IRBuilder builder) {
- builder.addArrayGet(MemberType.BOOLEAN, AA, BB, CC);
+ builder.addArrayGet(MemberType.BOOLEAN_OR_BYTE, AA, BB, CC);
}
@Override
diff --git a/src/main/java/com/android/tools/r8/code/AgetByte.java b/src/main/java/com/android/tools/r8/code/AgetByte.java
index abe1ac6..f7bc165 100644
--- a/src/main/java/com/android/tools/r8/code/AgetByte.java
+++ b/src/main/java/com/android/tools/r8/code/AgetByte.java
@@ -37,7 +37,7 @@
@Override
public void buildIR(IRBuilder builder) {
- builder.addArrayGet(MemberType.BYTE, AA, BB, CC);
+ builder.addArrayGet(MemberType.BOOLEAN_OR_BYTE, AA, BB, CC);
}
@Override
diff --git a/src/main/java/com/android/tools/r8/code/AputBoolean.java b/src/main/java/com/android/tools/r8/code/AputBoolean.java
index f59bd90..ac64012 100644
--- a/src/main/java/com/android/tools/r8/code/AputBoolean.java
+++ b/src/main/java/com/android/tools/r8/code/AputBoolean.java
@@ -37,7 +37,7 @@
@Override
public void buildIR(IRBuilder builder) {
- builder.addArrayPut(MemberType.BOOLEAN, AA, BB, CC);
+ builder.addArrayPut(MemberType.BOOLEAN_OR_BYTE, AA, BB, CC);
}
@Override
diff --git a/src/main/java/com/android/tools/r8/code/AputByte.java b/src/main/java/com/android/tools/r8/code/AputByte.java
index 5d522e0..1d439c6 100644
--- a/src/main/java/com/android/tools/r8/code/AputByte.java
+++ b/src/main/java/com/android/tools/r8/code/AputByte.java
@@ -37,7 +37,7 @@
@Override
public void buildIR(IRBuilder builder) {
- builder.addArrayPut(MemberType.BYTE, AA, BB, CC);
+ builder.addArrayPut(MemberType.BOOLEAN_OR_BYTE, AA, BB, CC);
}
@Override
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 5918964..2a10b2d 100644
--- a/src/main/java/com/android/tools/r8/graph/LazyCfCode.java
+++ b/src/main/java/com/android/tools/r8/graph/LazyCfCode.java
@@ -527,8 +527,7 @@
return MemberType.OBJECT;
case Opcodes.BALOAD:
case Opcodes.BASTORE:
- // TODO(b/109788783): Distinguish byte and boolean.
- return MemberType.BOOLEAN;
+ return MemberType.BOOLEAN_OR_BYTE;
case Opcodes.CALOAD:
case Opcodes.CASTORE:
return MemberType.CHAR;
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/type/ArrayTypeLatticeElement.java b/src/main/java/com/android/tools/r8/ir/analysis/type/ArrayTypeLatticeElement.java
index c631e11..5e16020 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/type/ArrayTypeLatticeElement.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/type/ArrayTypeLatticeElement.java
@@ -57,7 +57,7 @@
return nesting;
}
- TypeLatticeElement getArrayMemberTypeAsMemberType() {
+ public TypeLatticeElement getArrayMemberTypeAsMemberType() {
return memberTypeLattice;
}
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/type/TypeLatticeElement.java b/src/main/java/com/android/tools/r8/ir/analysis/type/TypeLatticeElement.java
index 94cd5e1..2dff5a9 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/type/TypeLatticeElement.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/type/TypeLatticeElement.java
@@ -17,8 +17,8 @@
public abstract class TypeLatticeElement {
public static final BottomTypeLatticeElement BOTTOM = BottomTypeLatticeElement.getInstance();
public static final TopTypeLatticeElement TOP = TopTypeLatticeElement.getInstance();
- static final BooleanTypeLatticeElement BOOLEAN = BooleanTypeLatticeElement.getInstance();
- static final ByteTypeLatticeElement BYTE = ByteTypeLatticeElement.getInstance();
+ public static final BooleanTypeLatticeElement BOOLEAN = BooleanTypeLatticeElement.getInstance();
+ public static final ByteTypeLatticeElement BYTE = ByteTypeLatticeElement.getInstance();
static final ShortTypeLatticeElement SHORT = ShortTypeLatticeElement.getInstance();
static final CharTypeLatticeElement CHAR = CharTypeLatticeElement.getInstance();
public static final IntTypeLatticeElement INT = IntTypeLatticeElement.getInstance();
diff --git a/src/main/java/com/android/tools/r8/ir/code/ArrayGet.java b/src/main/java/com/android/tools/r8/ir/code/ArrayGet.java
index e082dcd..cf9994f 100644
--- a/src/main/java/com/android/tools/r8/ir/code/ArrayGet.java
+++ b/src/main/java/com/android/tools/r8/ir/code/ArrayGet.java
@@ -80,11 +80,16 @@
case OBJECT:
instruction = new AgetObject(dest, array, index);
break;
- case BOOLEAN:
- instruction = new AgetBoolean(dest, array, index);
- break;
- case BYTE:
- instruction = new AgetByte(dest, array, index);
+ case BOOLEAN_OR_BYTE:
+ ArrayTypeLatticeElement arrayType = array().getTypeLattice().asArrayTypeLatticeElement();
+ if (arrayType != null
+ && arrayType.getArrayMemberTypeAsMemberType() == TypeLatticeElement.BOOLEAN) {
+ instruction = new AgetBoolean(dest, array, index);
+ } else {
+ assert array().getTypeLattice().isDefinitelyNull()
+ || arrayType.getArrayMemberTypeAsMemberType() == TypeLatticeElement.BYTE;
+ instruction = new AgetByte(dest, array, index);
+ }
break;
case CHAR:
instruction = new AgetChar(dest, array, index);
@@ -190,8 +195,7 @@
: arrayTypeLattice.getArrayMemberTypeAsValueType();
assert valueType.isReference();
return valueType;
- case BOOLEAN:
- case BYTE:
+ case BOOLEAN_OR_BYTE:
case CHAR:
case SHORT:
case INT:
diff --git a/src/main/java/com/android/tools/r8/ir/code/ArrayPut.java b/src/main/java/com/android/tools/r8/ir/code/ArrayPut.java
index 82e65e5..b2b2f10 100644
--- a/src/main/java/com/android/tools/r8/ir/code/ArrayPut.java
+++ b/src/main/java/com/android/tools/r8/ir/code/ArrayPut.java
@@ -17,6 +17,8 @@
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.ir.analysis.type.ArrayTypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
import com.android.tools.r8.ir.conversion.CfBuilder;
import com.android.tools.r8.ir.conversion.DexBuilder;
import com.android.tools.r8.ir.conversion.TypeConstraintResolver;
@@ -82,11 +84,16 @@
case OBJECT:
instruction = new AputObject(value, array, index);
break;
- case BOOLEAN:
- instruction = new AputBoolean(value, array, index);
- break;
- case BYTE:
- instruction = new AputByte(value, array, index);
+ case BOOLEAN_OR_BYTE:
+ ArrayTypeLatticeElement arrayType = array().getTypeLattice().asArrayTypeLatticeElement();
+ if (arrayType != null
+ && arrayType.getArrayMemberTypeAsMemberType() == TypeLatticeElement.BOOLEAN) {
+ instruction = new AputBoolean(value, array, index);
+ } else {
+ assert array().getTypeLattice().isDefinitelyNull()
+ || arrayType.getArrayMemberTypeAsMemberType() == TypeLatticeElement.BYTE;
+ instruction = new AputByte(value, array, index);
+ }
break;
case CHAR:
instruction = new AputChar(value, array, index);
diff --git a/src/main/java/com/android/tools/r8/ir/code/FieldInstruction.java b/src/main/java/com/android/tools/r8/ir/code/FieldInstruction.java
index fe5dac4..4810054 100644
--- a/src/main/java/com/android/tools/r8/ir/code/FieldInstruction.java
+++ b/src/main/java/com/android/tools/r8/ir/code/FieldInstruction.java
@@ -16,7 +16,6 @@
public abstract class FieldInstruction extends Instruction {
- private MemberType type;
private final DexField field;
protected FieldInstruction(DexField field, Value dest, Value value) {
@@ -27,11 +26,10 @@
super(dest, inValues);
assert field != null;
this.field = field;
- this.type = MemberType.fromDexType(field.type);
}
- public MemberType getType() {
- return type;
+ public FieldMemberType getType() {
+ return FieldMemberType.fromDexType(field.type);
}
public DexField getField() {
diff --git a/src/main/java/com/android/tools/r8/ir/code/FieldMemberType.java b/src/main/java/com/android/tools/r8/ir/code/FieldMemberType.java
new file mode 100644
index 0000000..3d2f9b0
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/ir/code/FieldMemberType.java
@@ -0,0 +1,53 @@
+// Copyright (c) 2019, 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.errors.InternalCompilerError;
+import com.android.tools.r8.errors.Unreachable;
+import com.android.tools.r8.graph.DexType;
+
+public enum FieldMemberType {
+ OBJECT,
+ BOOLEAN,
+ BYTE,
+ CHAR,
+ SHORT,
+ INT,
+ FLOAT,
+ LONG,
+ DOUBLE;
+
+ public static FieldMemberType fromTypeDescriptorChar(char descriptor) {
+ switch (descriptor) {
+ case 'L':
+ case '[':
+ return FieldMemberType.OBJECT;
+ case 'Z':
+ return FieldMemberType.BOOLEAN;
+ case 'B':
+ return FieldMemberType.BYTE;
+ case 'S':
+ return FieldMemberType.SHORT;
+ case 'C':
+ return FieldMemberType.CHAR;
+ case 'I':
+ return FieldMemberType.INT;
+ case 'F':
+ return FieldMemberType.FLOAT;
+ case 'J':
+ return FieldMemberType.LONG;
+ case 'D':
+ return FieldMemberType.DOUBLE;
+ case 'V':
+ throw new InternalCompilerError("No member type for void type.");
+ default:
+ throw new Unreachable("Invalid descriptor char '" + descriptor + "'");
+ }
+ }
+
+ public static FieldMemberType fromDexType(DexType type) {
+ return fromTypeDescriptorChar((char) type.descriptor.content[0]);
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/ir/code/InstanceGet.java b/src/main/java/com/android/tools/r8/ir/code/InstanceGet.java
index ca8cbfa..046aba5 100644
--- a/src/main/java/com/android/tools/r8/ir/code/InstanceGet.java
+++ b/src/main/java/com/android/tools/r8/ir/code/InstanceGet.java
@@ -86,9 +86,6 @@
case SHORT:
instruction = new IgetShort(destRegister, objectRegister, field);
break;
- case INT_OR_FLOAT:
- case LONG_OR_DOUBLE:
- throw new Unreachable("Unexpected imprecise type: " + getType());
default:
throw new Unreachable("Unexpected type: " + getType());
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/InstancePut.java b/src/main/java/com/android/tools/r8/ir/code/InstancePut.java
index 9cea0c0..fca35ba 100644
--- a/src/main/java/com/android/tools/r8/ir/code/InstancePut.java
+++ b/src/main/java/com/android/tools/r8/ir/code/InstancePut.java
@@ -83,9 +83,6 @@
case SHORT:
instruction = new IputShort(valueRegister, objectRegister, field);
break;
- case INT_OR_FLOAT:
- case LONG_OR_DOUBLE:
- throw new Unreachable("Unexpected imprecise type: " + getType());
default:
throw new Unreachable("Unexpected type: " + getType());
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/MemberType.java b/src/main/java/com/android/tools/r8/ir/code/MemberType.java
index a21a4e7..fe1048a 100644
--- a/src/main/java/com/android/tools/r8/ir/code/MemberType.java
+++ b/src/main/java/com/android/tools/r8/ir/code/MemberType.java
@@ -10,8 +10,7 @@
public enum MemberType {
OBJECT,
- BOOLEAN,
- BYTE,
+ BOOLEAN_OR_BYTE,
CHAR,
SHORT,
INT,
@@ -79,9 +78,8 @@
case '[':
return MemberType.OBJECT;
case 'Z':
- return MemberType.BOOLEAN;
case 'B':
- return MemberType.BYTE;
+ return MemberType.BOOLEAN_OR_BYTE;
case 'S':
return MemberType.SHORT;
case 'C':
diff --git a/src/main/java/com/android/tools/r8/ir/code/StaticGet.java b/src/main/java/com/android/tools/r8/ir/code/StaticGet.java
index 6dbf723..4f8191f 100644
--- a/src/main/java/com/android/tools/r8/ir/code/StaticGet.java
+++ b/src/main/java/com/android/tools/r8/ir/code/StaticGet.java
@@ -78,9 +78,6 @@
case SHORT:
instruction = new SgetShort(dest, field);
break;
- case INT_OR_FLOAT:
- case LONG_OR_DOUBLE:
- throw new Unreachable("Unexpected imprecise type: " + getType());
default:
throw new Unreachable("Unexpected type: " + getType());
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/StaticPut.java b/src/main/java/com/android/tools/r8/ir/code/StaticPut.java
index d8df7f1..a609206 100644
--- a/src/main/java/com/android/tools/r8/ir/code/StaticPut.java
+++ b/src/main/java/com/android/tools/r8/ir/code/StaticPut.java
@@ -75,9 +75,6 @@
case SHORT:
instruction = new SputShort(src, field);
break;
- case INT_OR_FLOAT:
- case LONG_OR_DOUBLE:
- throw new Unreachable("Unexpected imprecise type: " + getType());
default:
throw new Unreachable("Unexpected type: " + getType());
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/ValueType.java b/src/main/java/com/android/tools/r8/ir/code/ValueType.java
index e9e89aa..e3926c5 100644
--- a/src/main/java/com/android/tools/r8/ir/code/ValueType.java
+++ b/src/main/java/com/android/tools/r8/ir/code/ValueType.java
@@ -35,8 +35,7 @@
public static ValueType fromMemberType(MemberType type) {
switch (type) {
- case BOOLEAN:
- case BYTE:
+ case BOOLEAN_OR_BYTE:
case CHAR:
case SHORT:
case INT:
diff --git a/src/main/java/com/android/tools/r8/ir/code/ValueTypeConstraint.java b/src/main/java/com/android/tools/r8/ir/code/ValueTypeConstraint.java
index 9c376fb..9ee7b0f 100644
--- a/src/main/java/com/android/tools/r8/ir/code/ValueTypeConstraint.java
+++ b/src/main/java/com/android/tools/r8/ir/code/ValueTypeConstraint.java
@@ -61,8 +61,7 @@
public static ValueTypeConstraint fromMemberType(MemberType type) {
switch (type) {
- case BOOLEAN:
- case BYTE:
+ case BOOLEAN_OR_BYTE:
case CHAR:
case SHORT:
case INT:
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/IRBuilder.java b/src/main/java/com/android/tools/r8/ir/conversion/IRBuilder.java
index bd7d27e..59d7a55 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/IRBuilder.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/IRBuilder.java
@@ -145,8 +145,7 @@
private static TypeLatticeElement fromMemberType(MemberType type) {
switch (type) {
- case BOOLEAN:
- case BYTE:
+ case BOOLEAN_OR_BYTE:
case CHAR:
case SHORT:
case INT:
@@ -1005,7 +1004,6 @@
Value in2 = readRegister(index, ValueTypeConstraint.INT);
TypeLatticeElement typeLattice = fromMemberType(type);
Value out = writeRegister(dest, typeLattice, ThrowingInfo.CAN_THROW);
- out.setKnownToBeBoolean(type == MemberType.BOOLEAN);
ArrayGet instruction = new ArrayGet(type, out, in1, in2);
assert instruction.instructionTypeCanThrow();
if (!type.isPrecise()) {
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/JarSourceCode.java b/src/main/java/com/android/tools/r8/ir/conversion/JarSourceCode.java
index d7a55b7..591adeb 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/JarSourceCode.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/JarSourceCode.java
@@ -954,9 +954,8 @@
case Type.OBJECT:
return MemberType.OBJECT;
case Type.BOOLEAN:
- return MemberType.BOOLEAN;
case Type.BYTE:
- return MemberType.BYTE;
+ return MemberType.BOOLEAN_OR_BYTE;
case Type.SHORT:
return MemberType.SHORT;
case Type.CHAR:
@@ -976,10 +975,6 @@
}
}
- private MemberType memberType(String fieldDesc) {
- return memberType(application.getAsmType(fieldDesc));
- }
-
private static NumericType numericType(Type type) {
switch (type.getSort()) {
case Type.BYTE:
diff --git a/src/test/java/com/android/tools/r8/R8RunExamplesTest.java b/src/test/java/com/android/tools/r8/R8RunExamplesTest.java
index 793df27..c9485e3 100644
--- a/src/test/java/com/android/tools/r8/R8RunExamplesTest.java
+++ b/src/test/java/com/android/tools/r8/R8RunExamplesTest.java
@@ -156,10 +156,6 @@
@Override
protected Set<String> getFailingRunCfToDex() {
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();
}