[LIR] Add new-instance, invoke and cmp instructions.
Bug: b/225838009
Change-Id: I00cbfa596e09f653ac3d552f360d6cb5e817711b
diff --git a/src/main/java/com/android/tools/r8/ir/code/Cmp.java b/src/main/java/com/android/tools/r8/ir/code/Cmp.java
index a03637e..bc4cf73 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Cmp.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Cmp.java
@@ -19,6 +19,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 com.android.tools.r8.utils.LongInterval;
import com.android.tools.r8.utils.StringUtils;
import com.android.tools.r8.utils.StringUtils.BraceType;
@@ -236,6 +237,11 @@
}
@Override
+ public void buildLir(LirBuilder<Value, ?> builder) {
+ builder.addCmp(type, bias, leftValue(), rightValue());
+ }
+
+ @Override
public TypeElement evaluate(AppView<?> appView) {
return TypeElement.getInt();
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/InvokeInterface.java b/src/main/java/com/android/tools/r8/ir/code/InvokeInterface.java
index 94ba6c4..2936292 100644
--- a/src/main/java/com/android/tools/r8/ir/code/InvokeInterface.java
+++ b/src/main/java/com/android/tools/r8/ir/code/InvokeInterface.java
@@ -26,6 +26,7 @@
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 com.android.tools.r8.lightir.LirBuilder;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
import java.util.List;
@@ -165,4 +166,9 @@
void internalRegisterUse(UseRegistry<?> registry, DexClassAndMethod context) {
registry.registerInvokeInterface(getInvokedMethod());
}
+
+ @Override
+ public void buildLir(LirBuilder<Value, ?> builder) {
+ builder.addInvokeInterface(getInvokedMethod(), arguments());
+ }
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/InvokeStatic.java b/src/main/java/com/android/tools/r8/ir/code/InvokeStatic.java
index c84568c..3acd5fc 100644
--- a/src/main/java/com/android/tools/r8/ir/code/InvokeStatic.java
+++ b/src/main/java/com/android/tools/r8/ir/code/InvokeStatic.java
@@ -29,6 +29,7 @@
import com.android.tools.r8.ir.optimize.Inliner.Reason;
import com.android.tools.r8.ir.optimize.InliningConstraints;
import com.android.tools.r8.ir.optimize.inliner.WhyAreYouNotInliningReporter;
+import com.android.tools.r8.lightir.LirBuilder;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
import java.util.List;
@@ -244,6 +245,11 @@
registry.registerInvokeStatic(getInvokedMethod());
}
+ @Override
+ public void buildLir(LirBuilder<Value, ?> builder) {
+ builder.addInvokeStatic(getInvokedMethod(), arguments());
+ }
+
public static class Builder extends InvokeMethod.Builder<Builder, InvokeStatic> {
@Override
diff --git a/src/main/java/com/android/tools/r8/ir/code/NewInstance.java b/src/main/java/com/android/tools/r8/ir/code/NewInstance.java
index 40e7d5d..0fa2583 100644
--- a/src/main/java/com/android/tools/r8/ir/code/NewInstance.java
+++ b/src/main/java/com/android/tools/r8/ir/code/NewInstance.java
@@ -29,6 +29,7 @@
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 com.android.tools.r8.lightir.LirBuilder;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
public class NewInstance extends Instruction {
@@ -239,6 +240,11 @@
registry.registerNewInstance(clazz);
}
+ @Override
+ public void buildLir(LirBuilder<Value, ?> builder) {
+ builder.addNewInstance(clazz);
+ }
+
public static class Builder extends BuilderBase<Builder, NewInstance> {
private DexType type;
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 e09e9f5..95591f5 100644
--- a/src/main/java/com/android/tools/r8/lightir/Lir2IRConverter.java
+++ b/src/main/java/com/android/tools/r8/lightir/Lir2IRConverter.java
@@ -3,17 +3,21 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.lightir;
+import com.android.tools.r8.errors.Unreachable;
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.DexString;
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.TypeElement;
import com.android.tools.r8.ir.code.Argument;
import com.android.tools.r8.ir.code.ArrayLength;
import com.android.tools.r8.ir.code.BasicBlock;
import com.android.tools.r8.ir.code.CatchHandlers;
+import com.android.tools.r8.ir.code.Cmp;
+import com.android.tools.r8.ir.code.Cmp.Bias;
import com.android.tools.r8.ir.code.ConstNumber;
import com.android.tools.r8.ir.code.ConstString;
import com.android.tools.r8.ir.code.DebugLocalWrite;
@@ -25,8 +29,11 @@
import com.android.tools.r8.ir.code.IfType;
import com.android.tools.r8.ir.code.Instruction;
import com.android.tools.r8.ir.code.InvokeDirect;
+import com.android.tools.r8.ir.code.InvokeInterface;
+import com.android.tools.r8.ir.code.InvokeStatic;
import com.android.tools.r8.ir.code.InvokeVirtual;
import com.android.tools.r8.ir.code.MoveException;
+import com.android.tools.r8.ir.code.NewInstance;
import com.android.tools.r8.ir.code.NumberGenerator;
import com.android.tools.r8.ir.code.NumericType;
import com.android.tools.r8.ir.code.Phi;
@@ -91,8 +98,6 @@
AppView<?> appView,
LirDecodingStrategy<Value, EV> strategy) {
super(code);
- assert code.getPositionTable().length > 0;
- assert code.getPositionTable()[0].fromInstructionIndex == 0;
this.appView = appView;
this.code = code;
this.strategy = strategy;
@@ -370,6 +375,23 @@
addInstruction(instruction);
}
+ @Override
+ public void onInvokeStatic(DexMethod target, List<EV> arguments) {
+ // TODO(b/225838009): Maintain is-interface bit.
+ Value dest = getInvokeInstructionOutputValue(target);
+ List<Value> ssaArgumentValues = getValues(arguments);
+ InvokeStatic instruction = new InvokeStatic(target, dest, ssaArgumentValues);
+ addInstruction(instruction);
+ }
+
+ @Override
+ public void onInvokeInterface(DexMethod target, List<EV> arguments) {
+ Value dest = getInvokeInstructionOutputValue(target);
+ List<Value> ssaArgumentValues = getValues(arguments);
+ InvokeInterface instruction = new InvokeInterface(target, dest, ssaArgumentValues);
+ addInstruction(instruction);
+ }
+
private Value getInvokeInstructionOutputValue(DexMethod target) {
return target.getReturnType().isVoidType()
? null
@@ -377,6 +399,13 @@
}
@Override
+ public void onNewInstance(DexType clazz) {
+ TypeElement type = TypeElement.fromDexType(clazz, Nullability.definitelyNotNull(), appView);
+ Value dest = getOutValueForNextInstruction(type);
+ addInstruction(new NewInstance(clazz, dest));
+ }
+
+ @Override
public void onStaticGet(DexField field) {
Value dest = getOutValueForNextInstruction(field.getTypeElement(appView));
addInstruction(new StaticGet(dest, field));
@@ -425,5 +454,39 @@
dest.setType(type);
addInstruction(new DebugLocalWrite(dest, src));
}
+
+ @Override
+ public void onCmpInstruction(int opcode, EV leftIndex, EV rightIndex) {
+ NumericType type;
+ Bias bias;
+ switch (opcode) {
+ case LirOpcodes.LCMP:
+ type = NumericType.LONG;
+ bias = Bias.NONE;
+ break;
+ case LirOpcodes.FCMPL:
+ type = NumericType.FLOAT;
+ bias = Bias.LT;
+ break;
+ case LirOpcodes.FCMPG:
+ type = NumericType.FLOAT;
+ bias = Bias.GT;
+ break;
+ case LirOpcodes.DCMPL:
+ type = NumericType.DOUBLE;
+ bias = Bias.LT;
+ break;
+ case LirOpcodes.DCMPG:
+ type = NumericType.DOUBLE;
+ bias = Bias.GT;
+ break;
+ default:
+ throw new Unreachable("Unexpected cmp opcode: " + opcode);
+ }
+ Value leftValue = getValue(leftIndex);
+ Value rightValue = getValue(rightIndex);
+ Value dest = getOutValueForNextInstruction(TypeElement.getInt());
+ addInstruction(new Cmp(type, bias, dest, leftValue, rightValue));
+ }
}
}
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 fd4113a..7730e8f 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,8 @@
import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.code.BasicBlock;
import com.android.tools.r8.ir.code.CatchHandlers;
+import com.android.tools.r8.ir.code.Cmp;
+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.NumericType;
@@ -208,6 +210,11 @@
opcode, Collections.emptyList(), Collections.singletonList(value));
}
+ private LirBuilder<V, EV> addTwoValueInstruction(int opcode, V leftValue, V rightValue) {
+ return addInstructionTemplate(
+ opcode, Collections.emptyList(), ImmutableList.of(leftValue, rightValue));
+ }
+
private LirBuilder<V, EV> addInstructionTemplate(
int opcode, List<DexItem> items, List<V> values) {
assert values.size() < MAX_VALUE_COUNT;
@@ -303,6 +310,18 @@
return addInvokeInstruction(LirOpcodes.INVOKEVIRTUAL, method, arguments);
}
+ public LirBuilder<V, EV> addInvokeStatic(DexMethod method, List<V> arguments) {
+ return addInvokeInstruction(LirOpcodes.INVOKESTATIC, method, arguments);
+ }
+
+ public LirBuilder<V, EV> addInvokeInterface(DexMethod method, List<V> arguments) {
+ return addInvokeInstruction(LirOpcodes.INVOKEINTERFACE, method, arguments);
+ }
+
+ public LirBuilder<V, EV> addNewInstance(DexType clazz) {
+ return addOneItemInstruction(LirOpcodes.NEW, clazz);
+ }
+
public LirBuilder<V, EV> addReturn(V value) {
throw new Unimplemented();
}
@@ -435,4 +454,21 @@
debugTable,
strategy.getStrategyInfo());
}
+
+ private int getCmpOpcode(NumericType type, Cmp.Bias bias) {
+ switch (type) {
+ case LONG:
+ return LirOpcodes.LCMP;
+ case FLOAT:
+ return bias == Cmp.Bias.LT ? LirOpcodes.FCMPL : LirOpcodes.FCMPG;
+ case DOUBLE:
+ return bias == Cmp.Bias.LT ? LirOpcodes.DCMPL : LirOpcodes.DCMPG;
+ default:
+ throw new Unreachable("Cmp has unknown type " + type);
+ }
+ }
+
+ public LirBuilder<V, EV> addCmp(NumericType type, Bias bias, V leftValue, V rightValue) {
+ return addTwoValueInstruction(getCmpOpcode(type, bias), leftValue, rightValue);
+ }
}
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 ed94301..77b9422 100644
--- a/src/main/java/com/android/tools/r8/lightir/LirParsedInstructionCallback.java
+++ b/src/main/java/com/android/tools/r8/lightir/LirParsedInstructionCallback.java
@@ -106,6 +106,18 @@
onInvokeMethodInstruction(method, arguments);
}
+ public void onInvokeStatic(DexMethod method, List<EV> arguments) {
+ onInvokeMethodInstruction(method, arguments);
+ }
+
+ public void onInvokeInterface(DexMethod method, List<EV> arguments) {
+ onInvokeMethodInstruction(method, arguments);
+ }
+
+ public void onNewInstance(DexType clazz) {
+ onInstruction();
+ }
+
public void onFieldInstruction(DexField field) {
onInstruction();
}
@@ -130,6 +142,11 @@
onInstruction();
}
+ public void onCmpInstruction(int opcode, EV leftValue, EV rightValue) {
+ assert LirOpcodes.LCMP <= opcode && opcode <= LirOpcodes.DCMPG;
+ onInstruction();
+ }
+
private DexItem getConstantItem(int index) {
return code.getConstantItem(index);
}
@@ -204,6 +221,29 @@
onInvokeVirtual(target, arguments);
return;
}
+ case LirOpcodes.INVOKESTATIC:
+ {
+ DexMethod target = getInvokeInstructionTarget(view);
+ List<EV> arguments = getInvokeInstructionArguments(view);
+ onInvokeStatic(target, arguments);
+ return;
+ }
+ case LirOpcodes.INVOKEINTERFACE:
+ {
+ DexMethod target = getInvokeInstructionTarget(view);
+ List<EV> arguments = getInvokeInstructionArguments(view);
+ onInvokeInterface(target, arguments);
+ return;
+ }
+ case LirOpcodes.NEW:
+ {
+ DexItem item = getConstantItem(view.getNextConstantOperand());
+ if (item instanceof DexType) {
+ onNewInstance((DexType) item);
+ return;
+ }
+ throw new Unimplemented();
+ }
case LirOpcodes.GETSTATIC:
{
DexField field = (DexField) getConstantItem(view.getNextConstantOperand());
@@ -252,6 +292,17 @@
onDebugLocalWrite(srcIndex);
return;
}
+ case LirOpcodes.LCMP:
+ case LirOpcodes.FCMPL:
+ case LirOpcodes.FCMPG:
+ case LirOpcodes.DCMPL:
+ case LirOpcodes.DCMPG:
+ {
+ EV leftValue = getNextValueOperand(view);
+ EV rightValue = getNextValueOperand(view);
+ onCmpInstruction(opcode, leftValue, rightValue);
+ 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 f4a840b..a705fd2 100644
--- a/src/main/java/com/android/tools/r8/lightir/LirPrinter.java
+++ b/src/main/java/com/android/tools/r8/lightir/LirPrinter.java
@@ -11,6 +11,7 @@
import com.android.tools.r8.ir.code.IfType;
import com.android.tools.r8.ir.code.NumericType;
import com.android.tools.r8.utils.StringUtils;
+import java.util.Arrays;
import java.util.List;
public class LirPrinter<EV> extends LirParsedInstructionCallback<EV> {
@@ -60,6 +61,11 @@
return instructionIndex < 0 ? "--" : ("" + instructionIndex);
}
+ @SafeVarargs
+ private void appendValueArguments(EV... arguments) {
+ appendValueArguments(Arrays.asList(arguments));
+ }
+
private void appendValueArguments(List<EV> arguments) {
for (int i = 0; i < arguments.size(); i++) {
builder.append(fmtValueIndex(arguments.get(i))).append(' ');
@@ -203,4 +209,10 @@
appendValueArguments(operands);
builder.append(type);
}
+
+ @Override
+ public void onCmpInstruction(int opcode, EV leftValue, EV rightValue) {
+ appendOutValue();
+ appendValueArguments(leftValue, rightValue);
+ }
}