[LIR] Add xor and array get and put instructions.
Bug: b/225838009
Change-Id: I653a6b1ac6724d64d463c08eb5a5419c62917742
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfLogicalBinop.java b/src/main/java/com/android/tools/r8/cf/code/CfLogicalBinop.java
index 32afbc5..a173410 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfLogicalBinop.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfLogicalBinop.java
@@ -106,6 +106,10 @@
}
public int getAsmOpcode() {
+ return getAsmOpcode(opcode, type);
+ }
+
+ public static int getAsmOpcode(Opcode opcode, NumericType type) {
switch (opcode) {
case Shl:
return type.isWide() ? Opcodes.LSHL : Opcodes.ISHL;
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/proto/GeneratedMessageLiteShrinker.java b/src/main/java/com/android/tools/r8/ir/analysis/proto/GeneratedMessageLiteShrinker.java
index 2efe2c3..ca151c5 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/proto/GeneratedMessageLiteShrinker.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/proto/GeneratedMessageLiteShrinker.java
@@ -345,7 +345,7 @@
Instruction materializingInstruction = objects.get(i).buildIR(appView, code);
instructionIterator.add(materializingInstruction);
instructionIterator.add(
- new ArrayPut(
+ ArrayPut.create(
MemberType.OBJECT,
newObjectsValue,
indexValue,
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 2bfd3c3..ab357ed 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
@@ -31,6 +31,7 @@
import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
import com.android.tools.r8.ir.optimize.InliningConstraints;
import com.android.tools.r8.ir.regalloc.RegisterAllocator;
+import com.android.tools.r8.lightir.LirBuilder;
import java.util.Arrays;
import java.util.Set;
@@ -286,4 +287,14 @@
int index = index().getConstInstruction().asConstNumber().getIntValue();
return newArraySize <= 0 || index < 0 || newArraySize <= index;
}
+
+ @Override
+ public void buildLir(LirBuilder<Value, ?> builder) {
+ if (getMemberType().isObject()) {
+ DexType destType = dest().getType().asReferenceType().toDexType(builder.factory());
+ builder.addArrayGetObject(destType, array(), index());
+ } else {
+ builder.addArrayGetPrimitive(getMemberType(), array(), index());
+ }
+ }
}
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 5f07431..eff1adc 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
@@ -27,6 +27,7 @@
import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
import com.android.tools.r8.ir.optimize.InliningConstraints;
import com.android.tools.r8.ir.regalloc.RegisterAllocator;
+import com.android.tools.r8.lightir.LirBuilder;
import java.util.Arrays;
public class ArrayPut extends ArrayAccess {
@@ -36,14 +37,29 @@
private MemberType type;
- public ArrayPut(MemberType type, Value array, Value index, Value value) {
+ public static ArrayPut create(MemberType type, Value array, Value index, Value value) {
+ ArrayPut put = new ArrayPut(type, array, index, value);
+ assert put.verify();
+ return put;
+ }
+
+ public static ArrayPut createWithoutVerification(
+ MemberType type, Value array, Value index, Value value) {
+ return new ArrayPut(type, array, index, value);
+ }
+
+ private ArrayPut(MemberType type, Value array, Value index, Value value) {
super(null, Arrays.asList(array, index, value));
- assert type != null;
- assert array.verifyCompatible(ValueType.OBJECT);
- assert index.verifyCompatible(ValueType.INT);
this.type = type;
}
+ private boolean verify() {
+ assert type != null;
+ assert array().verifyCompatible(ValueType.OBJECT);
+ assert index().verifyCompatible(ValueType.INT);
+ return true;
+ }
+
@Override
public int opcode() {
return Opcodes.ARRAY_PUT;
@@ -251,6 +267,11 @@
@Override
public ArrayAccess withMemberType(MemberType newMemberType) {
- return new ArrayPut(newMemberType, array(), index(), value());
+ return ArrayPut.create(newMemberType, array(), index(), value());
+ }
+
+ @Override
+ public void buildLir(LirBuilder<Value, ?> builder) {
+ builder.addArrayPut(getMemberType(), array(), index(), value());
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/LogicalBinop.java b/src/main/java/com/android/tools/r8/ir/code/LogicalBinop.java
index cfc2ee7..5457a36 100644
--- a/src/main/java/com/android/tools/r8/ir/code/LogicalBinop.java
+++ b/src/main/java/com/android/tools/r8/ir/code/LogicalBinop.java
@@ -12,6 +12,7 @@
import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.conversion.CfBuilder;
import com.android.tools.r8.ir.conversion.DexBuilder;
+import com.android.tools.r8.lightir.LirBuilder;
import java.util.function.Function;
public abstract class LogicalBinop extends Binop {
@@ -143,4 +144,9 @@
public void buildCf(CfBuilder builder) {
builder.add(new CfLogicalBinop(getCfOpcode(), type), this);
}
+
+ @Override
+ public void buildLir(LirBuilder<Value, ?> builder) {
+ builder.addLogicalBinop(getCfOpcode(), type, leftValue(), rightValue());
+ }
}
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 e28dba3..cf7a34f 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
@@ -1158,7 +1158,7 @@
Value inValue = readRegister(value, ValueTypeConstraint.fromMemberType(type));
Value inArray = readRegister(array, ValueTypeConstraint.OBJECT);
Value inIndex = readRegister(index, ValueTypeConstraint.INT);
- ArrayPut instruction = new ArrayPut(type, inArray, inIndex, inValue);
+ ArrayPut instruction = ArrayPut.create(type, inArray, inIndex, inValue);
if (!type.isPrecise()) {
addImpreciseInstruction(instruction);
}
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java b/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
index fc8d1f2..a5417c6 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
@@ -1041,6 +1041,7 @@
OptimizationFeedback feedback,
BytecodeMetadataProvider bytecodeMetadataProvider,
Timing timing) {
+ IRCode oldCode = code;
if (options.testing.roundtripThroughLir) {
code = roundtripThroughLir(code, feedback, bytecodeMetadataProvider, timing);
}
@@ -1075,6 +1076,9 @@
LirCode<EV> lirCode =
IR2LirConverter.translate(code, strategy.getEncodingStrategy(), appView.dexItemFactory());
timing.end();
+ // Check that printing does not fail.
+ String lirString = lirCode.toString();
+ assert !lirString.isEmpty();
timing.begin("LIR->IR (" + name + ")");
IRCode irCode =
Lir2IRConverter.translate(
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/records/RecordFieldValuesRewriter.java b/src/main/java/com/android/tools/r8/ir/desugar/records/RecordFieldValuesRewriter.java
index 0c1c56f..1653ae2 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/records/RecordFieldValuesRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/records/RecordFieldValuesRewriter.java
@@ -112,7 +112,7 @@
intConstantI.setPosition(constantPosition);
iterator.add(intConstantI);
ArrayPut arrayPut =
- new ArrayPut(
+ ArrayPut.create(
MemberType.OBJECT,
newArrayEmpty.outValue(),
intConstantI.outValue(),
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 4eea25d..a3e20e6 100644
--- a/src/main/java/com/android/tools/r8/lightir/Lir2IRConverter.java
+++ b/src/main/java/com/android/tools/r8/lightir/Lir2IRConverter.java
@@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.lightir;
+import com.android.tools.r8.errors.Unimplemented;
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexField;
@@ -11,10 +12,13 @@
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.analysis.type.Nullability;
+import com.android.tools.r8.ir.analysis.type.PrimitiveTypeElement;
import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.code.Add;
import com.android.tools.r8.ir.code.Argument;
+import com.android.tools.r8.ir.code.ArrayGet;
import com.android.tools.r8.ir.code.ArrayLength;
+import com.android.tools.r8.ir.code.ArrayPut;
import com.android.tools.r8.ir.code.BasicBlock;
import com.android.tools.r8.ir.code.CatchHandlers;
import com.android.tools.r8.ir.code.Cmp;
@@ -36,6 +40,7 @@
import com.android.tools.r8.ir.code.InvokeStatic;
import com.android.tools.r8.ir.code.InvokeSuper;
import com.android.tools.r8.ir.code.InvokeVirtual;
+import com.android.tools.r8.ir.code.MemberType;
import com.android.tools.r8.ir.code.Monitor;
import com.android.tools.r8.ir.code.MonitorType;
import com.android.tools.r8.ir.code.MoveException;
@@ -54,9 +59,12 @@
import com.android.tools.r8.ir.code.Sub;
import com.android.tools.r8.ir.code.Throw;
import com.android.tools.r8.ir.code.Value;
+import com.android.tools.r8.ir.code.ValueType;
+import com.android.tools.r8.ir.code.Xor;
import com.android.tools.r8.ir.conversion.MethodConversionOptions.MutableMethodConversionOptions;
import com.android.tools.r8.lightir.LirCode.PositionEntry;
import com.android.tools.r8.utils.ListUtils;
+import com.google.common.collect.ImmutableList;
import it.unimi.dsi.fastutil.ints.Int2ReferenceMap;
import it.unimi.dsi.fastutil.ints.Int2ReferenceOpenHashMap;
import it.unimi.dsi.fastutil.ints.IntArrayList;
@@ -202,8 +210,7 @@
// LIR has no value-user info so after building is done, removed unused values.
for (Instruction instruction : block.getInstructions()) {
if (instruction.hasOutValue()
- && !instruction.isArgument()
- && !instruction.isMoveException()
+ && instruction.isInvoke()
&& instruction.hasUnusedOutValue()) {
instruction.clearOutValue();
}
@@ -330,6 +337,11 @@
}
@Override
+ public void onInstruction() {
+ throw new Unimplemented("Missing IR conversion");
+ }
+
+ @Override
public void onConstNull() {
Value dest = getOutValueForNextInstruction(TypeElement.getNull());
addInstruction(new ConstNumber(dest, 0));
@@ -342,38 +354,66 @@
}
@Override
+ public void onConstFloat(int value) {
+ Value dest = getOutValueForNextInstruction(TypeElement.getFloat());
+ addInstruction(new ConstNumber(dest, value));
+ }
+
+ @Override
+ public void onConstLong(long value) {
+ Value dest = getOutValueForNextInstruction(TypeElement.getLong());
+ addInstruction(new ConstNumber(dest, value));
+ }
+
+ @Override
+ public void onConstDouble(long value) {
+ Value dest = getOutValueForNextInstruction(TypeElement.getDouble());
+ addInstruction(new ConstNumber(dest, value));
+ }
+
+ TypeElement valueTypeElement(NumericType type) {
+ return PrimitiveTypeElement.fromNumericType(type);
+ }
+
+ @Override
public void onAdd(NumericType type, EV leftValueIndex, EV rightValueIndex) {
- Value dest = getOutValueForNextInstruction(TypeElement.getInt());
+ Value dest = getOutValueForNextInstruction(valueTypeElement(type));
addInstruction(
Add.createNonNormalized(type, dest, getValue(leftValueIndex), getValue(rightValueIndex)));
}
@Override
public void onSub(NumericType type, EV leftValueIndex, EV rightValueIndex) {
- Value dest = getOutValueForNextInstruction(TypeElement.getInt());
+ Value dest = getOutValueForNextInstruction(valueTypeElement(type));
addInstruction(new Sub(type, dest, getValue(leftValueIndex), getValue(rightValueIndex)));
}
@Override
public void onMul(NumericType type, EV leftValueIndex, EV rightValueIndex) {
- Value dest = getOutValueForNextInstruction(TypeElement.getInt());
+ Value dest = getOutValueForNextInstruction(valueTypeElement(type));
addInstruction(
Mul.createNonNormalized(type, dest, getValue(leftValueIndex), getValue(rightValueIndex)));
}
@Override
public void onDiv(NumericType type, EV leftValueIndex, EV rightValueIndex) {
- Value dest = getOutValueForNextInstruction(TypeElement.getInt());
+ Value dest = getOutValueForNextInstruction(valueTypeElement(type));
addInstruction(new Div(type, dest, getValue(leftValueIndex), getValue(rightValueIndex)));
}
@Override
public void onRem(NumericType type, EV leftValueIndex, EV rightValueIndex) {
- Value dest = getOutValueForNextInstruction(TypeElement.getInt());
+ Value dest = getOutValueForNextInstruction(valueTypeElement(type));
addInstruction(new Rem(type, dest, getValue(leftValueIndex), getValue(rightValueIndex)));
}
@Override
+ public void onXor(NumericType type, EV left, EV right) {
+ Value dest = getOutValueForNextInstruction(valueTypeElement(type));
+ addInstruction(Xor.createNonNormalized(type, dest, getValue(left), getValue(right)));
+ }
+
+ @Override
public void onConstString(DexString string) {
Value dest = getOutValueForNextInstruction(TypeElement.stringClassType(appView));
addInstruction(new ConstString(dest, string));
@@ -398,6 +438,17 @@
}
@Override
+ public void onIfCmp(IfType ifKind, int blockIndex, EV leftValueIndex, EV rightValueIndex) {
+ BasicBlock targetBlock = getBasicBlock(blockIndex);
+ Value leftValue = getValue(leftValueIndex);
+ Value rightValue = getValue(rightValueIndex);
+ addInstruction(new If(ifKind, ImmutableList.of(leftValue, rightValue)));
+ currentBlock.link(targetBlock);
+ currentBlock.link(getBasicBlock(nextInstructionIndex));
+ closeCurrentBlock();
+ }
+
+ @Override
public void onFallthrough() {
int nextBlockIndex = peekNextInstructionIndex() + 1;
onGoto(nextBlockIndex);
@@ -500,6 +551,12 @@
}
@Override
+ public void onReturn(EV value) {
+ addInstruction(new Return(getValue(value)));
+ closeCurrentBlock();
+ }
+
+ @Override
public void onArrayLength(EV arrayValueIndex) {
Value dest = getOutValueForNextInstruction(TypeElement.getInt());
Value arrayValue = getValue(arrayValueIndex);
@@ -580,5 +637,27 @@
public void onMonitorExit(EV value) {
addInstruction(new Monitor(MonitorType.EXIT, getValue(value)));
}
+
+ @Override
+ public void onArrayGetObject(DexType type, EV array, EV index) {
+ Value dest = getOutValueForNextInstruction(type.toTypeElement(appView));
+ addInstruction(new ArrayGet(MemberType.OBJECT, dest, getValue(array), getValue(index)));
+ }
+
+ @Override
+ public void onArrayGetPrimitive(MemberType type, EV array, EV index) {
+ // Convert the member type to a "stack value type", e.g., byte, char etc to int.
+ ValueType valueType = ValueType.fromMemberType(type);
+ DexType dexType = valueType.toDexType(appView.dexItemFactory());
+ Value dest = getOutValueForNextInstruction(dexType.toTypeElement(appView));
+ addInstruction(new ArrayGet(type, dest, getValue(array), getValue(index)));
+ }
+
+ @Override
+ public void onArrayPut(MemberType type, EV array, EV index, EV value) {
+ addInstruction(
+ ArrayPut.createWithoutVerification(
+ type, getValue(array), getValue(index), getValue(value)));
+ }
}
}
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 91ce188..95624bb 100644
--- a/src/main/java/com/android/tools/r8/lightir/LirBuilder.java
+++ b/src/main/java/com/android/tools/r8/lightir/LirBuilder.java
@@ -5,6 +5,7 @@
import com.android.tools.r8.cf.code.CfArithmeticBinop;
import com.android.tools.r8.cf.code.CfArithmeticBinop.Opcode;
+import com.android.tools.r8.cf.code.CfLogicalBinop;
import com.android.tools.r8.cf.code.CfNumberConversion;
import com.android.tools.r8.errors.Unimplemented;
import com.android.tools.r8.errors.Unreachable;
@@ -22,6 +23,7 @@
import com.android.tools.r8.ir.code.Cmp.Bias;
import com.android.tools.r8.ir.code.IRMetadata;
import com.android.tools.r8.ir.code.IfType;
+import com.android.tools.r8.ir.code.MemberType;
import com.android.tools.r8.ir.code.MonitorType;
import com.android.tools.r8.ir.code.NumericType;
import com.android.tools.r8.ir.code.Position;
@@ -88,6 +90,10 @@
flushedPosition = currentPosition;
}
+ public DexItemFactory factory() {
+ return factory;
+ }
+
public boolean verifyCurrentValueIndex(int valueIndex) {
assert instructionCount + argumentCount == valueIndex;
return true;
@@ -109,7 +115,6 @@
public LirBuilder<V, EV> setCurrentPosition(Position position) {
assert position != null;
- assert position != Position.none();
currentPosition = position;
return this;
}
@@ -566,7 +571,7 @@
}
public LirBuilder<V, EV> addArithmeticBinop(
- Opcode binop, NumericType type, V leftValue, V rightValue) {
+ CfArithmeticBinop.Opcode binop, NumericType type, V leftValue, V rightValue) {
// The LIR and CF opcodes are the same values, check that the two endpoints match.
assert LirOpcodes.IADD == CfArithmeticBinop.getAsmOpcode(Opcode.Add, NumericType.INT);
assert LirOpcodes.DREM == CfArithmeticBinop.getAsmOpcode(Opcode.Rem, NumericType.DOUBLE);
@@ -574,6 +579,17 @@
return addTwoValueInstruction(opcode, leftValue, rightValue);
}
+ public LirBuilder<V, EV> addLogicalBinop(
+ CfLogicalBinop.Opcode binop, NumericType type, V leftValue, V rightValue) {
+ // The LIR and CF opcodes are the same values, check that the two endpoints match.
+ assert LirOpcodes.ISHL
+ == CfLogicalBinop.getAsmOpcode(CfLogicalBinop.Opcode.Shl, NumericType.INT);
+ assert LirOpcodes.LXOR
+ == CfLogicalBinop.getAsmOpcode(CfLogicalBinop.Opcode.Xor, NumericType.LONG);
+ int opcode = CfLogicalBinop.getAsmOpcode(binop, type);
+ return addTwoValueInstruction(opcode, leftValue, rightValue);
+ }
+
public LirBuilder<V, EV> addMonitor(MonitorType type, V value) {
return addOneValueInstruction(
type == MonitorType.ENTER ? LirOpcodes.MONITORENTER : LirOpcodes.MONITOREXIT, value);
@@ -590,4 +606,73 @@
assert opcode <= LirOpcodes.I2S;
return addOneValueInstruction(opcode, value);
}
+
+ public LirBuilder<V, EV> addArrayGetObject(DexType destType, V array, V index) {
+ return addInstructionTemplate(
+ LirOpcodes.AALOAD, Collections.singletonList(destType), ImmutableList.of(array, index));
+ }
+
+ public LirBuilder<V, EV> addArrayGetPrimitive(MemberType memberType, V array, V index) {
+ int opcode;
+ switch (memberType) {
+ case BOOLEAN_OR_BYTE:
+ opcode = LirOpcodes.BALOAD;
+ break;
+ case CHAR:
+ opcode = LirOpcodes.CALOAD;
+ break;
+ case SHORT:
+ opcode = LirOpcodes.SALOAD;
+ break;
+ case INT:
+ opcode = LirOpcodes.IALOAD;
+ break;
+ case FLOAT:
+ opcode = LirOpcodes.FALOAD;
+ break;
+ case LONG:
+ opcode = LirOpcodes.LALOAD;
+ break;
+ case DOUBLE:
+ opcode = LirOpcodes.DALOAD;
+ break;
+ default:
+ throw new Unreachable("Unexpected object or imprecise member type: " + memberType);
+ }
+ return addInstructionTemplate(opcode, Collections.emptyList(), ImmutableList.of(array, index));
+ }
+
+ public LirBuilder<V, EV> addArrayPut(MemberType memberType, V array, V index, V value) {
+ int opcode;
+ switch (memberType) {
+ case BOOLEAN_OR_BYTE:
+ opcode = LirOpcodes.BASTORE;
+ break;
+ case CHAR:
+ opcode = LirOpcodes.CASTORE;
+ break;
+ case SHORT:
+ opcode = LirOpcodes.SASTORE;
+ break;
+ case INT:
+ opcode = LirOpcodes.IASTORE;
+ break;
+ case FLOAT:
+ opcode = LirOpcodes.FASTORE;
+ break;
+ case LONG:
+ opcode = LirOpcodes.LASTORE;
+ break;
+ case DOUBLE:
+ opcode = LirOpcodes.DASTORE;
+ break;
+ case OBJECT:
+ opcode = LirOpcodes.AASTORE;
+ break;
+ default:
+ throw new Unreachable("Unexpected imprecise member type: " + memberType);
+ }
+ return addInstructionTemplate(
+ opcode, Collections.emptyList(), ImmutableList.of(array, index, value));
+ }
}
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 de3a7b4..6af7bb5 100644
--- a/src/main/java/com/android/tools/r8/lightir/LirParsedInstructionCallback.java
+++ b/src/main/java/com/android/tools/r8/lightir/LirParsedInstructionCallback.java
@@ -5,12 +5,14 @@
import com.android.tools.r8.cf.code.CfNumberConversion;
import com.android.tools.r8.errors.Unimplemented;
+import com.android.tools.r8.errors.Unreachable;
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.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 java.util.ArrayList;
import java.util.List;
@@ -79,6 +81,38 @@
onInstruction();
}
+ private void onArrayGetInternal(MemberType type, LirInstructionView view) {
+ if (type.isObject()) {
+ DexType destType = (DexType) getConstantItem(view.getNextConstantOperand());
+ EV array = getNextValueOperand(view);
+ EV index = getNextValueOperand(view);
+ onArrayGetObject(destType, array, index);
+ } else {
+ EV array = getNextValueOperand(view);
+ EV index = getNextValueOperand(view);
+ onArrayGetPrimitive(type, array, index);
+ }
+ }
+
+ public void onArrayGetPrimitive(MemberType type, EV array, EV index) {
+ onInstruction();
+ }
+
+ public void onArrayGetObject(DexType type, EV array, EV index) {
+ onInstruction();
+ }
+
+ private void onArrayPutInternal(MemberType type, LirInstructionView view) {
+ EV array = getNextValueOperand(view);
+ EV index = getNextValueOperand(view);
+ EV value = getNextValueOperand(view);
+ onArrayPut(type, array, index, value);
+ }
+
+ public void onArrayPut(MemberType type, EV array, EV index, EV value) {
+ onInstruction();
+ }
+
public void onAdd(NumericType type, EV leftValueIndex, EV rightValueIndex) {
onInstruction();
}
@@ -179,6 +213,36 @@
onRem(NumericType.DOUBLE, leftValueIndex, rightValueIndex);
}
+ private void onLogicalBinopInternal(int opcode, LirInstructionView view) {
+ EV left = getNextValueOperand(view);
+ EV right = getNextValueOperand(view);
+ switch (opcode) {
+ case LirOpcodes.ISHL:
+ case LirOpcodes.LSHL:
+ case LirOpcodes.ISHR:
+ case LirOpcodes.LSHR:
+ case LirOpcodes.IUSHR:
+ case LirOpcodes.LUSHR:
+ case LirOpcodes.IAND:
+ case LirOpcodes.LAND:
+ case LirOpcodes.IOR:
+ case LirOpcodes.LOR:
+ throw new Unimplemented();
+ case LirOpcodes.IXOR:
+ onXor(NumericType.INT, left, right);
+ return;
+ case LirOpcodes.LXOR:
+ onXor(NumericType.INT, left, right);
+ return;
+ default:
+ throw new Unreachable("Unexpected logical binop: " + opcode);
+ }
+ }
+
+ public void onXor(NumericType type, EV left, EV right) {
+ onInstruction();
+ }
+
public void onNumberConversion(int opcode, EV value) {
assert LirOpcodes.I2L <= opcode;
assert opcode <= LirOpcodes.I2S;
@@ -190,10 +254,27 @@
onInstruction();
}
+ private void onIfInternal(IfType ifKind, LirInstructionView view) {
+ int blockIndex = view.getNextBlockOperand();
+ EV valueIndex = getNextValueOperand(view);
+ onIf(ifKind, blockIndex, valueIndex);
+ }
+
public void onIf(IfType ifKind, int blockIndex, EV valueIndex) {
onInstruction();
}
+ private void onIfCmpInternal(IfType ifKind, LirInstructionView view) {
+ int blockIndex = view.getNextBlockOperand();
+ EV leftValueIndex = getNextValueOperand(view);
+ EV rightValueIndex = getNextValueOperand(view);
+ onIfCmp(ifKind, blockIndex, leftValueIndex, rightValueIndex);
+ }
+
+ public void onIfCmp(IfType ifKind, int blockIndex, EV leftValueIndex, EV rightValueIndex) {
+ onInstruction();
+ }
+
public void onGoto(int blockIndex) {
onInstruction();
}
@@ -258,6 +339,10 @@
onInstruction();
}
+ public void onReturn(EV value) {
+ onInstruction();
+ }
+
public void onArrayLength(EV arrayValueIndex) {
onInstruction();
}
@@ -365,6 +450,92 @@
onConstDouble(value);
return;
}
+ case LirOpcodes.IALOAD:
+ {
+ onArrayGetInternal(MemberType.INT, view);
+ break;
+ }
+ case LirOpcodes.LALOAD:
+ {
+ onArrayGetInternal(MemberType.LONG, view);
+ break;
+ }
+ case LirOpcodes.FALOAD:
+ {
+ onArrayGetInternal(MemberType.FLOAT, view);
+ break;
+ }
+ case LirOpcodes.DALOAD:
+ {
+ onArrayGetInternal(MemberType.DOUBLE, view);
+ break;
+ }
+ case LirOpcodes.AALOAD:
+ {
+ onArrayGetInternal(MemberType.OBJECT, view);
+ break;
+ }
+ case LirOpcodes.BALOAD:
+ {
+ onArrayGetInternal(MemberType.BOOLEAN_OR_BYTE, view);
+ break;
+ }
+ case LirOpcodes.CALOAD:
+ {
+ onArrayGetInternal(MemberType.CHAR, view);
+ break;
+ }
+ case LirOpcodes.SALOAD:
+ {
+ onArrayGetInternal(MemberType.SHORT, view);
+ break;
+ }
+ case LirOpcodes.IASTORE:
+ {
+ onArrayPutInternal(MemberType.INT, view);
+ break;
+ }
+ case LirOpcodes.LASTORE:
+ {
+ onArrayPutInternal(MemberType.LONG, view);
+ break;
+ }
+ case LirOpcodes.FASTORE:
+ {
+ onArrayPutInternal(MemberType.FLOAT, view);
+ break;
+ }
+
+ case LirOpcodes.DASTORE:
+ {
+ onArrayPutInternal(MemberType.DOUBLE, view);
+ break;
+ }
+
+ case LirOpcodes.AASTORE:
+ {
+ onArrayPutInternal(MemberType.OBJECT, view);
+ break;
+ }
+
+ case LirOpcodes.BASTORE:
+ {
+ onArrayPutInternal(MemberType.BOOLEAN_OR_BYTE, view);
+ break;
+ }
+
+ case LirOpcodes.CASTORE:
+ {
+ onArrayPutInternal(MemberType.CHAR, view);
+ break;
+ }
+
+ case LirOpcodes.SASTORE:
+ {
+ onArrayPutInternal(MemberType.SHORT, view);
+ break;
+ }
+
case LirOpcodes.IADD:
{
EV leftValueIndex = getNextValueOperand(view);
@@ -505,6 +676,22 @@
onRemDouble(leftValueIndex, rightValueIndex);
return;
}
+ case LirOpcodes.ISHL:
+ case LirOpcodes.LSHL:
+ case LirOpcodes.ISHR:
+ case LirOpcodes.LSHR:
+ case LirOpcodes.IUSHR:
+ case LirOpcodes.LUSHR:
+ case LirOpcodes.IAND:
+ case LirOpcodes.LAND:
+ case LirOpcodes.IOR:
+ case LirOpcodes.LOR:
+ case LirOpcodes.IXOR:
+ case LirOpcodes.LXOR:
+ {
+ onLogicalBinopInternal(opcode, view);
+ return;
+ }
case LirOpcodes.I2L:
case LirOpcodes.I2F:
case LirOpcodes.I2D:
@@ -525,11 +712,84 @@
onNumberConversion(opcode, value);
return;
}
+ case LirOpcodes.IFEQ:
+ {
+ onIfInternal(IfType.EQ, view);
+ return;
+ }
case LirOpcodes.IFNE:
{
- int blockIndex = view.getNextBlockOperand();
- EV valueIndex = getNextValueOperand(view);
- onIf(IfType.NE, blockIndex, valueIndex);
+ onIfInternal(IfType.NE, view);
+ return;
+ }
+ case LirOpcodes.IFLT:
+ {
+ onIfInternal(IfType.LT, view);
+ return;
+ }
+ case LirOpcodes.IFGE:
+ {
+ onIfInternal(IfType.GE, view);
+ return;
+ }
+ case LirOpcodes.IFGT:
+ {
+ onIfInternal(IfType.GT, view);
+ return;
+ }
+ case LirOpcodes.IFLE:
+ {
+ onIfInternal(IfType.LE, view);
+ return;
+ }
+ case LirOpcodes.IFNULL:
+ {
+ onIfInternal(IfType.EQ, view);
+ return;
+ }
+ case LirOpcodes.IFNONNULL:
+ {
+ onIfInternal(IfType.NE, view);
+ return;
+ }
+ case LirOpcodes.IF_ICMPEQ:
+ {
+ onIfCmpInternal(IfType.EQ, view);
+ return;
+ }
+ case LirOpcodes.IF_ICMPNE:
+ {
+ onIfCmpInternal(IfType.NE, view);
+ return;
+ }
+ case LirOpcodes.IF_ICMPLT:
+ {
+ onIfCmpInternal(IfType.LT, view);
+ return;
+ }
+ case LirOpcodes.IF_ICMPGE:
+ {
+ onIfCmpInternal(IfType.GE, view);
+ return;
+ }
+ case LirOpcodes.IF_ICMPGT:
+ {
+ onIfCmpInternal(IfType.GT, view);
+ return;
+ }
+ case LirOpcodes.IF_ICMPLE:
+ {
+ onIfCmpInternal(IfType.LE, view);
+ return;
+ }
+ case LirOpcodes.IF_ACMPEQ:
+ {
+ onIfCmpInternal(IfType.EQ, view);
+ return;
+ }
+ case LirOpcodes.IF_ACMPNE:
+ {
+ onIfCmpInternal(IfType.NE, view);
return;
}
case LirOpcodes.GOTO:
@@ -624,6 +884,12 @@
onReturnVoid();
return;
}
+ case LirOpcodes.ARETURN:
+ {
+ EV value = getNextValueOperand(view);
+ onReturn(value);
+ return;
+ }
case LirOpcodes.ARRAYLENGTH:
{
onArrayLength(getNextValueOperand(view));
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 19d5350..58a00f6 100644
--- a/src/main/java/com/android/tools/r8/lightir/LirPrinter.java
+++ b/src/main/java/com/android/tools/r8/lightir/LirPrinter.java
@@ -9,6 +9,7 @@
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.utils.StringUtils;
import java.util.Arrays;
@@ -129,18 +130,47 @@
}
@Override
+ public void onConstFloat(int value) {
+ appendOutValue().append(Float.intBitsToFloat(value));
+ }
+
+ @Override
+ public void onConstLong(long value) {
+ appendOutValue().append(value);
+ }
+
+ @Override
+ public void onConstDouble(long value) {
+ appendOutValue().append(Double.longBitsToDouble(value));
+ }
+
+ @Override
public void onConstString(DexString string) {
appendOutValue().append("str(").append(string).append(")");
}
@Override
+ public void onAdd(NumericType type, EV leftValueIndex, EV rightValueIndex) {
+ appendOutValue();
+ appendValueArguments(leftValueIndex, rightValueIndex);
+ }
+
+ @Override
+ public void onSub(NumericType type, EV leftValueIndex, EV rightValueIndex) {
+ appendOutValue();
+ appendValueArguments(leftValueIndex, rightValueIndex);
+ }
+
+ @Override
public void onDiv(NumericType type, EV leftValueIndex, EV rightValueIndex) {
- appendOutValue()
- .append(fmtValueIndex(leftValueIndex))
- .append(' ')
- .append(fmtValueIndex(rightValueIndex))
- .append(' ')
- .append(type);
+ appendOutValue();
+ appendValueArguments(leftValueIndex, rightValueIndex);
+ }
+
+ @Override
+ public void onXor(NumericType type, EV leftValueIndex, EV rightValueIndex) {
+ appendOutValue();
+ appendValueArguments(leftValueIndex, rightValueIndex);
}
@Override
@@ -151,7 +181,14 @@
@Override
public void onIf(IfType ifKind, int blockIndex, EV valueIndex) {
- builder.append(fmtValueIndex(valueIndex)).append(' ').append(fmtInsnIndex(blockIndex));
+ appendValueArguments(valueIndex);
+ builder.append(fmtInsnIndex(blockIndex));
+ }
+
+ @Override
+ public void onIfCmp(IfType ifKind, int blockIndex, EV leftValueIndex, EV rightValueIndex) {
+ appendValueArguments(leftValueIndex, rightValueIndex);
+ builder.append(fmtInsnIndex(blockIndex));
}
@Override
@@ -175,6 +212,12 @@
}
@Override
+ public void onNewInstance(DexType clazz) {
+ appendOutValue();
+ builder.append(clazz);
+ }
+
+ @Override
public void onInvokeMethodInstruction(DexMethod method, List<EV> arguments) {
if (!method.getReturnType().isVoidType()) {
appendOutValue();
@@ -225,11 +268,36 @@
}
@Override
+ public void onReturn(EV value) {
+ appendValueArguments(value);
+ }
+
+ @Override
public void onArrayLength(EV arrayValueIndex) {
appendOutValue().append(fmtValueIndex(arrayValueIndex));
}
@Override
+ public void onArrayGetPrimitive(MemberType type, EV array, EV index) {
+ appendOutValue();
+ appendValueArguments(array, index);
+ builder.append(type);
+ }
+
+ @Override
+ public void onArrayGetObject(DexType type, EV array, EV index) {
+ appendOutValue();
+ appendValueArguments(array, index);
+ builder.append(type);
+ }
+
+ @Override
+ public void onArrayPut(MemberType type, EV array, EV index, EV value) {
+ appendValueArguments(array, index, value);
+ builder.append(type);
+ }
+
+ @Override
public void onDebugPosition() {
// Nothing to append.
}
diff --git a/src/test/java/com/android/tools/r8/examples/ExamplesTestBase.java b/src/test/java/com/android/tools/r8/examples/ExamplesTestBase.java
index 093702c..76af63f 100644
--- a/src/test/java/com/android/tools/r8/examples/ExamplesTestBase.java
+++ b/src/test/java/com/android/tools/r8/examples/ExamplesTestBase.java
@@ -45,6 +45,7 @@
public void runTestR8() throws Exception {
parameters.assumeR8TestParameters();
testForR8(parameters.getBackend())
+ .addOptionsModification(o -> o.testing.roundtripThroughLir = true)
.setMinApi(parameters)
.addProgramClasses(getTestClasses())
.addKeepMainRule(getMainClass())