Encode SSA value references using relative index.
Bug: b//225838009
Change-Id: I6fa7c9042bd9bf8ab376477dcb311116357c5a6f
diff --git a/src/main/java/com/android/tools/r8/lightir/ByteUtils.java b/src/main/java/com/android/tools/r8/lightir/ByteUtils.java
index 5c51959..f719f11 100644
--- a/src/main/java/com/android/tools/r8/lightir/ByteUtils.java
+++ b/src/main/java/com/android/tools/r8/lightir/ByteUtils.java
@@ -40,10 +40,10 @@
public static int readEncodedInt(ByteIterator iterator) {
assert 4 == intEncodingSize(0);
- int value = ensureU1(iterator.nextByte()) << 24;
- value |= ensureU1(iterator.nextByte()) << 16;
- value |= ensureU1(iterator.nextByte()) << 8;
- value |= ensureU1(iterator.nextByte());
+ int value = truncateToU1(iterator.nextByte()) << 24;
+ value |= truncateToU1(iterator.nextByte()) << 16;
+ value |= truncateToU1(iterator.nextByte()) << 8;
+ value |= truncateToU1(iterator.nextByte());
return value;
}
diff --git a/src/main/java/com/android/tools/r8/lightir/IR2LIRConverter.java b/src/main/java/com/android/tools/r8/lightir/IR2LIRConverter.java
index 9bdc15a..b1ad627 100644
--- a/src/main/java/com/android/tools/r8/lightir/IR2LIRConverter.java
+++ b/src/main/java/com/android/tools/r8/lightir/IR2LIRConverter.java
@@ -65,7 +65,9 @@
}
private void computeInstructions() {
- int currentInstructionIndex = 0;
+ // The IR instruction index corresponds to the LIR value index which includes arguments and
+ // all instructions.
+ int currentValueIndex = 0;
BasicBlockIterator blockIt = irCode.listIterator();
while (blockIt.hasNext()) {
BasicBlock block = blockIt.next();
@@ -77,7 +79,7 @@
for (Phi phi : block.getPhis()) {
permuteOperands(phi.getOperands(), permutation, operands);
builder.addPhi(phi.getType(), Arrays.asList(operands));
- currentInstructionIndex++;
+ currentValueIndex++;
}
}
if (block.hasCatchHandlers()) {
@@ -89,25 +91,27 @@
}
InstructionIterator it = block.iterator();
while (it.hasNext()) {
+ assert builder.verifyCurrentValueIndex(currentValueIndex);
Instruction instruction = it.next();
assert !instruction.hasOutValue()
- || currentInstructionIndex == values.getInt(instruction.outValue());
+ || currentValueIndex == values.getInt(instruction.outValue());
builder.setCurrentPosition(instruction.getPosition());
if (!instruction.getDebugValues().isEmpty()) {
- builder.setDebugLocalEnds(currentInstructionIndex, instruction.getDebugValues());
+ builder.setDebugLocalEnds(currentValueIndex, instruction.getDebugValues());
}
if (instruction.isGoto()) {
BasicBlock nextBlock = blockIt.peekNext();
if (instruction.asGoto().getTarget() == nextBlock) {
builder.addFallthrough();
- currentInstructionIndex++;
+ currentValueIndex++;
continue;
}
}
instruction.buildLIR(builder);
- currentInstructionIndex++;
+ currentValueIndex++;
}
+ assert builder.verifyCurrentValueIndex(currentValueIndex);
}
}
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 28547c0..56fb836 100644
--- a/src/main/java/com/android/tools/r8/lightir/LIR2IRConverter.java
+++ b/src/main/java/com/android/tools/r8/lightir/LIR2IRConverter.java
@@ -93,6 +93,11 @@
currentPosition = SyntheticPosition.builder().setLine(0).setMethod(method).build();
}
+ @Override
+ public int getCurrentValueIndex() {
+ return nextInstructionIndex + code.getArgumentCount();
+ }
+
private void closeCurrentBlock() {
currentBlock = null;
}
@@ -154,6 +159,9 @@
block.setFilled();
blockList.add(block);
}
+ for (int i = 0; i < peekNextInstructionIndex(); ++i) {
+ valueNumberGenerator.next();
+ }
return new IRCode(
appView.options(),
method,
@@ -179,7 +187,7 @@
public Value getValue(int index) {
Value value = values[index];
if (value == null) {
- value = new Value(valueNumberGenerator.next(), TypeElement.getBottom(), null);
+ value = new Value(index, TypeElement.getBottom(), null);
values[index] = value;
}
return value;
@@ -206,7 +214,7 @@
DebugLocalInfo localInfo = code.getDebugLocalInfo(valueIndex);
Value value = values[valueIndex];
if (value == null) {
- value = new Value(valueNumberGenerator.next(), type, localInfo);
+ value = new Value(valueIndex, type, localInfo);
values[valueIndex] = value;
} else {
value.setType(type);
@@ -225,9 +233,7 @@
// uniform with instructions.
advanceInstructionState();
// Creating the phi implicitly adds it to currentBlock.
- Phi phi =
- new Phi(
- valueNumberGenerator.next(), currentBlock, type, localInfo, RegisterReadType.NORMAL);
+ Phi phi = new Phi(valueIndex, currentBlock, type, localInfo, RegisterReadType.NORMAL);
Value value = values[valueIndex];
if (value != null) {
// A fake ssa value has already been created, replace the users by the actual phi.
@@ -269,12 +275,11 @@
private Argument addArgument(DexType type, int index) {
// Arguments are not included in the "instructions" so this does not call "addInstruction"
// which would otherwise advance the state.
- Value dest = getValue(index);
- dest.setType(type.toTypeElement(appView));
+ TypeElement typeElement = type.toTypeElement(appView);
DebugLocalInfo localInfo = code.getDebugLocalInfo(index);
- if (localInfo != null) {
- dest.setLocalInfo(localInfo);
- }
+ Value dest = new Value(index, typeElement, localInfo);
+ assert values[index] == null;
+ values[index] = dest;
Argument argument = new Argument(dest, index, type.isBooleanType());
assert currentBlock != null;
assert currentPosition.isSyntheticPosition();
@@ -370,9 +375,9 @@
}
@Override
- public void onArrayLength(int arrayIndex) {
+ public void onArrayLength(int arrayValueIndex) {
Value dest = getOutValueForNextInstruction(TypeElement.getInt());
- Value arrayValue = getValue(arrayIndex);
+ Value arrayValue = getValue(arrayValueIndex);
addInstruction(new ArrayLength(dest, arrayValue));
}
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 4f3a62e..9095c8b 100644
--- a/src/main/java/com/android/tools/r8/lightir/LIRBuilder.java
+++ b/src/main/java/com/android/tools/r8/lightir/LIRBuilder.java
@@ -96,6 +96,11 @@
flushedPosition = currentPosition;
}
+ public boolean verifyCurrentValueIndex(int valueIndex) {
+ assert instructionCount + argumentCount == valueIndex;
+ return true;
+ }
+
public DexType toDexType(TypeElement typeElement) {
if (typeElement.isPrimitiveType()) {
return typeElement.asPrimitiveType().toDexType(factory);
@@ -143,12 +148,16 @@
return valueIndexGetter.getValueIndex(value);
}
- private int valueIndexSize(int index) {
- return ByteUtils.intEncodingSize(index);
+ private int valueIndexSize(int valueIndex, int referencingInstructionIndex) {
+ int referencingValueIndex = referencingInstructionIndex + argumentCount;
+ int encodedValueIndex = LIRUtils.encodeValueIndex(valueIndex, referencingValueIndex);
+ return ByteUtils.intEncodingSize(encodedValueIndex);
}
- private void writeValueIndex(int index) {
- ByteUtils.writeEncodedInt(index, writer::writeOperand);
+ private void writeValueIndex(int valueIndex, int referencingInstructionIndex) {
+ int referencingValueIndex = referencingInstructionIndex + argumentCount;
+ int encodedValueIndex = LIRUtils.encodeValueIndex(valueIndex, referencingValueIndex);
+ ByteUtils.writeEncodedInt(encodedValueIndex, writer::writeOperand);
}
private int getBlockIndex(B block) {
@@ -174,14 +183,14 @@
return this;
}
- public LIRBuilder<V, B> setDebugLocalEnds(int instructionIndex, Set<V> endValues) {
+ public LIRBuilder<V, B> setDebugLocalEnds(int instructionValueIndex, Set<V> endValues) {
int size = endValues.size();
int[] indices = new int[size];
Iterator<V> iterator = endValues.iterator();
for (int i = 0; i < size; i++) {
indices[i] = getValueIndex(iterator.next());
}
- debugLocalEnds.put(instructionIndex, indices);
+ debugLocalEnds.put(instructionValueIndex, indices);
return this;
}
@@ -192,12 +201,12 @@
return this;
}
- private void advanceInstructionState() {
+ private int advanceInstructionState() {
if (!currentPosition.equals(flushedPosition)) {
setPositionIndex(instructionCount, currentPosition);
flushedPosition = currentPosition;
}
- ++instructionCount;
+ return instructionCount++;
}
private LIRBuilder<V, B> addNoOperandInstruction(int opcode) {
@@ -217,7 +226,7 @@
private LIRBuilder<V, B> addInstructionTemplate(int opcode, List<DexItem> items, List<V> values) {
assert values.size() < MAX_VALUE_COUNT;
- advanceInstructionState();
+ int instructionIndex = advanceInstructionState();
int operandSize = 0;
for (DexItem item : items) {
operandSize += constantIndexSize(item);
@@ -225,7 +234,7 @@
for (int i = 0; i < values.size(); i++) {
V value = values.get(i);
int valueIndex = getValueIndex(value);
- operandSize += valueIndexSize(valueIndex);
+ operandSize += valueIndexSize(valueIndex, instructionIndex);
valueIndexBuffer[i] = valueIndex;
}
writer.writeInstruction(opcode, operandSize);
@@ -233,7 +242,7 @@
writeConstantIndex(item);
}
for (int i = 0; i < values.size(); i++) {
- writeValueIndex(valueIndexBuffer[i]);
+ writeValueIndex(valueIndexBuffer[i], instructionIndex);
}
return this;
}
@@ -243,7 +252,7 @@
}
public LIRBuilder<V, B> addConstInt(int value) {
- if (0 <= value && value <= 5) {
+ if (-1 <= value && value <= 5) {
addNoOperandInstruction(LIROpcodes.ICONST_0 + value);
} else {
advanceInstructionState();
@@ -258,18 +267,7 @@
case OBJECT:
return addConstNull();
case INT:
- {
- int intValue = (int) value;
- if (-1 <= intValue && intValue <= 5) {
- int opcode = LIROpcodes.ICONST_0 + intValue;
- return addNoOperandInstruction(opcode);
- }
- int opcode = LIROpcodes.ICONST;
- int size = ByteUtils.intEncodingSize(intValue);
- writer.writeInstruction(opcode, size);
- ByteUtils.writeEncodedInt(intValue, writer::writeOperand);
- return this;
- }
+ return addConstInt((int) value);
case FLOAT:
case LONG:
case DOUBLE:
@@ -372,11 +370,11 @@
}
int targetIndex = getBlockIndex(trueTarget);
int valueIndex = getValueIndex(value);
- int operandSize = blockIndexSize(targetIndex) + valueIndexSize(valueIndex);
- advanceInstructionState();
+ int operandSize = blockIndexSize(targetIndex) + valueIndexSize(valueIndex, instructionCount);
+ int instructionIndex = advanceInstructionState();
writer.writeInstruction(opcode, operandSize);
writeBlockIndex(targetIndex);
- writeValueIndex(valueIndex);
+ writeValueIndex(valueIndex, instructionIndex);
return this;
}
@@ -405,16 +403,18 @@
default:
throw new Unreachable("Unexpected if kind " + ifKind);
}
+ int instructionIndex = advanceInstructionState();
int targetIndex = getBlockIndex(trueTarget);
int valueOneIndex = getValueIndex(inValues.get(0));
int valueTwoIndex = getValueIndex(inValues.get(1));
int operandSize =
- blockIndexSize(targetIndex) + valueIndexSize(valueOneIndex) + valueIndexSize(valueTwoIndex);
- advanceInstructionState();
+ blockIndexSize(targetIndex)
+ + valueIndexSize(valueOneIndex, instructionIndex)
+ + valueIndexSize(valueTwoIndex, instructionIndex);
writer.writeInstruction(opcode, operandSize);
writeBlockIndex(targetIndex);
- writeValueIndex(valueOneIndex);
- writeValueIndex(valueTwoIndex);
+ writeValueIndex(valueOneIndex, instructionIndex);
+ writeValueIndex(valueTwoIndex, instructionIndex);
return this;
}
diff --git a/src/main/java/com/android/tools/r8/lightir/LIRCode.java b/src/main/java/com/android/tools/r8/lightir/LIRCode.java
index 09619f4..e39820a 100644
--- a/src/main/java/com/android/tools/r8/lightir/LIRCode.java
+++ b/src/main/java/com/android/tools/r8/lightir/LIRCode.java
@@ -12,10 +12,7 @@
import com.android.tools.r8.ir.code.Position;
import com.android.tools.r8.lightir.LIRBuilder.BlockIndexGetter;
import com.android.tools.r8.lightir.LIRBuilder.ValueIndexGetter;
-import com.android.tools.r8.utils.StringUtils;
-import com.android.tools.r8.utils.StringUtils.BraceType;
import it.unimi.dsi.fastutil.ints.Int2ReferenceMap;
-import java.util.Arrays;
public class LIRCode implements Iterable<LIRInstructionView> {
@@ -141,10 +138,10 @@
return debugLocalInfoTable == null ? null : debugLocalInfoTable.valueToLocalMap.get(valueIndex);
}
- public int[] getDebugLocalEnds(int instructionIndex) {
+ public int[] getDebugLocalEnds(int instructionValueIndex) {
return debugLocalInfoTable == null
? null
- : debugLocalInfoTable.instructionToEndUseMap.get(instructionIndex);
+ : debugLocalInfoTable.instructionToEndUseMap.get(instructionValueIndex);
}
@Override
@@ -154,29 +151,6 @@
@Override
public String toString() {
- StringBuilder builder = new StringBuilder("LIRCode{");
- builder
- .append("args:")
- .append(argumentCount)
- .append(", insn(num:")
- .append(instructionCount)
- .append(", size:")
- .append(instructions.length)
- .append("):{");
- int index = 0;
- for (LIRInstructionView view : this) {
- builder.append(index).append(':');
- builder.append(LIROpcodes.toString(view.getOpcode()));
- if (view.getRemainingOperandSizeInBytes() > 0) {
- builder.append("(size:").append(1 + view.getRemainingOperandSizeInBytes()).append(")");
- }
- if (++index < instructionCount) {
- builder.append(", ");
- }
- }
- builder.append("}, pool(size:").append(constants.length).append("):");
- StringUtils.append(builder, Arrays.asList(constants), ", ", BraceType.TUBORG);
- builder.append("}");
- return builder.toString();
+ return new LIRPrinter(this).prettyPrint();
}
}
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 f0bc3f3..40395bb 100644
--- a/src/main/java/com/android/tools/r8/lightir/LIRParsedInstructionCallback.java
+++ b/src/main/java/com/android/tools/r8/lightir/LIRParsedInstructionCallback.java
@@ -25,7 +25,7 @@
* <p>Due to the parsing of the individual instructions, this parser has a higher overhead than
* using the basic {@code LIRInstructionView}.
*/
-public class LIRParsedInstructionCallback implements LIRInstructionCallback {
+public abstract class LIRParsedInstructionCallback implements LIRInstructionCallback {
private final LIRCode code;
@@ -33,33 +33,70 @@
this.code = code;
}
- public void onConstNull() {}
+ /** Returns the index for the value associated with the current argument/instruction. */
+ public abstract int getCurrentValueIndex();
- public void onConstNumber(NumericType type, long value) {}
+ public final int getCurrentInstructionIndex() {
+ return getCurrentValueIndex() - code.getArgumentCount();
+ }
+
+ private int getActualValueIndex(int relativeValueIndex) {
+ return LIRUtils.decodeValueIndex(relativeValueIndex, getCurrentValueIndex());
+ }
+
+ private int getNextValueOperand(LIRInstructionView view) {
+ return getActualValueIndex(view.getNextValueOperand());
+ }
+
+ public void onInstruction() {}
+
+ public void onConstNull() {
+ onInstruction();
+ }
+
+ public void onConstNumber(NumericType type, long value) {
+ onInstruction();
+ }
public void onConstInt(int value) {
onConstNumber(NumericType.INT, value);
}
- public void onConstString(DexString string) {}
+ public void onConstString(DexString string) {
+ onInstruction();
+ }
- public void onDiv(NumericType type, int leftValueIndex, int rightValueIndex) {}
+ public void onDiv(NumericType type, int leftValueIndex, int rightValueIndex) {
+ onInstruction();
+ }
public void onDivInt(int leftValueIndex, int rightValueIndex) {
onDiv(NumericType.INT, leftValueIndex, rightValueIndex);
}
- public void onIf(If.Type ifKind, int blockIndex, int valueIndex) {}
+ public void onIf(If.Type ifKind, int blockIndex, int valueIndex) {
+ onInstruction();
+ }
- public void onGoto(int blockIndex) {}
+ public void onGoto(int blockIndex) {
+ onInstruction();
+ }
- public void onFallthrough() {}
+ public void onFallthrough() {
+ onInstruction();
+ }
- public void onMoveException(DexType exceptionType) {}
+ public void onMoveException(DexType exceptionType) {
+ onInstruction();
+ }
- public void onDebugLocalWrite(int srcIndex) {}
+ public void onDebugLocalWrite(int srcIndex) {
+ onInstruction();
+ }
- public void onInvokeMethodInstruction(DexMethod method, IntList arguments) {}
+ public void onInvokeMethodInstruction(DexMethod method, IntList arguments) {
+ onInstruction();
+ }
public void onInvokeDirect(DexMethod method, IntList arguments) {
onInvokeMethodInstruction(method, arguments);
@@ -70,27 +107,35 @@
}
public void onFieldInstruction(DexField field) {
- onFieldInstruction(field);
+ onInstruction();
}
public void onStaticGet(DexField field) {
onFieldInstruction(field);
}
- public void onReturnVoid() {}
+ public void onReturnVoid() {
+ onInstruction();
+ }
- public void onArrayLength(int arrayIndex) {}
+ public void onArrayLength(int arrayValueIndex) {
+ onInstruction();
+ }
- public void onDebugPosition() {}
+ public void onDebugPosition() {
+ onInstruction();
+ }
- public void onPhi(DexType type, IntList operands) {}
+ public void onPhi(DexType type, IntList operands) {
+ onInstruction();
+ }
private DexItem getConstantItem(int index) {
return code.getConstantItem(index);
}
@Override
- public final void onInstructionView(LIRInstructionView view) {
+ public void onInstructionView(LIRInstructionView view) {
int opcode = view.getOpcode();
switch (opcode) {
case LIROpcodes.ACONST_NULL:
@@ -127,15 +172,15 @@
}
case LIROpcodes.IDIV:
{
- int leftValueIndex = view.getNextValueOperand();
- int rightValueIndex = view.getNextValueOperand();
+ int leftValueIndex = getNextValueOperand(view);
+ int rightValueIndex = getNextValueOperand(view);
onDivInt(leftValueIndex, rightValueIndex);
return;
}
case LIROpcodes.IFNE:
{
int blockIndex = view.getNextBlockOperand();
- int valueIndex = view.getNextValueOperand();
+ int valueIndex = getNextValueOperand(view);
onIf(If.Type.NE, blockIndex, valueIndex);
return;
}
@@ -172,7 +217,7 @@
}
case LIROpcodes.ARRAYLENGTH:
{
- onArrayLength(view.getNextValueOperand());
+ onArrayLength(getNextValueOperand(view));
return;
}
case LIROpcodes.DEBUGPOS:
@@ -185,7 +230,7 @@
DexType type = (DexType) getConstantItem(view.getNextConstantOperand());
IntList operands = new IntArrayList();
while (view.hasMoreOperands()) {
- operands.add(view.getNextValueOperand());
+ operands.add(getNextValueOperand(view));
}
onPhi(type, operands);
return;
@@ -203,7 +248,7 @@
}
case LIROpcodes.DEBUGLOCALWRITE:
{
- int srcIndex = view.getNextValueOperand();
+ int srcIndex = getNextValueOperand(view);
onDebugLocalWrite(srcIndex);
return;
}
@@ -219,7 +264,7 @@
private IntList getInvokeInstructionArguments(LIRInstructionView view) {
IntList arguments = new IntArrayList();
while (view.hasMoreOperands()) {
- arguments.add(view.getNextValueOperand());
+ arguments.add(getNextValueOperand(view));
}
return arguments;
}
diff --git a/src/main/java/com/android/tools/r8/lightir/LIRPrinter.java b/src/main/java/com/android/tools/r8/lightir/LIRPrinter.java
new file mode 100644
index 0000000..c8af439
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/lightir/LIRPrinter.java
@@ -0,0 +1,202 @@
+// Copyright (c) 2022, 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.lightir;
+
+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.DexString;
+import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.ir.code.If.Type;
+import com.android.tools.r8.ir.code.NumericType;
+import com.android.tools.r8.utils.StringUtils;
+import it.unimi.dsi.fastutil.ints.IntList;
+
+public class LIRPrinter extends LIRParsedInstructionCallback {
+
+ private static final String SEPERATOR = "\n";
+ private final LIRCode code;
+ private final StringBuilder builder = new StringBuilder();
+
+ private final int instructionIndexPadding;
+ private final int instructionNamePadding;
+
+ private int valueIndex = 0;
+ private LIRInstructionView view;
+
+ public LIRPrinter(LIRCode code) {
+ super(code);
+ this.code = code;
+ instructionIndexPadding =
+ Math.max(
+ fmtInsnIndex(-code.getArgumentCount()).length(),
+ fmtInsnIndex(code.getInstructionCount() - 1).length());
+ int maxNameLength = 0;
+ for (LIRInstructionView view : code) {
+ maxNameLength = Math.max(maxNameLength, LIROpcodes.toString(view.getOpcode()).length());
+ }
+ instructionNamePadding = maxNameLength;
+ }
+
+ @Override
+ public int getCurrentValueIndex() {
+ return valueIndex;
+ }
+
+ private void advanceToNextValueIndex() {
+ valueIndex++;
+ }
+
+ private String fmtValueIndex(int valueIndex) {
+ return "v" + valueIndex;
+ }
+
+ private String fmtInsnIndex(int instructionIndex) {
+ return instructionIndex < 0 ? "--" : ("" + instructionIndex);
+ }
+
+ private void appendValueArguments(IntList arguments) {
+ for (int i = 0; i < arguments.size(); i++) {
+ builder.append(fmtValueIndex(arguments.getInt(i))).append(' ');
+ }
+ }
+
+ public String prettyPrint() {
+ for (int i = 0; i < code.getArgumentCount(); i++) {
+ addInstructionHeader("ARG", 0);
+ appendOutValue();
+ advanceToNextValueIndex();
+ }
+ code.forEach(this::onInstructionView);
+ return builder.toString();
+ }
+
+ @Override
+ public void onInstructionView(LIRInstructionView view) {
+ this.view = view;
+ assert view.getInstructionIndex() == getCurrentInstructionIndex();
+ int operandSizeInBytes = view.getRemainingOperandSizeInBytes();
+ int instructionSizeInBytes = operandSizeInBytes == 0 ? 1 : 2 + operandSizeInBytes;
+ String opcode = LIROpcodes.toString(view.getOpcode());
+ addInstructionHeader(opcode, instructionSizeInBytes);
+ super.onInstructionView(view);
+ advanceToNextValueIndex();
+ }
+
+ private void addInstructionHeader(String opcode, int instructionSize) {
+ if (getCurrentValueIndex() > 0) {
+ builder.append(SEPERATOR);
+ }
+ StringUtils.appendLeftPadded(
+ builder, fmtInsnIndex(getCurrentInstructionIndex()), instructionIndexPadding);
+ builder.append(':');
+ StringUtils.appendLeftPadded(
+ builder, Integer.toString(instructionSize), instructionIndexPadding);
+ builder.append(": ");
+ StringUtils.appendRightPadded(builder, opcode, instructionNamePadding);
+ builder.append(' ');
+ }
+
+ @Override
+ public void onInstruction() {
+ throw new Unimplemented(
+ "Printing of instruction missing: " + LIROpcodes.toString(view.getOpcode()));
+ }
+
+ private StringBuilder appendOutValue() {
+ return builder.append(fmtValueIndex(getCurrentValueIndex())).append(" <- ");
+ }
+
+ @Override
+ public void onConstNull() {
+ appendOutValue().append("null");
+ }
+
+ @Override
+ public void onConstInt(int value) {
+ appendOutValue().append(value);
+ }
+
+ @Override
+ public void onConstString(DexString string) {
+ appendOutValue().append("str(").append(string).append(")");
+ }
+
+ @Override
+ public void onDiv(NumericType type, int leftValueIndex, int rightValueIndex) {
+ appendOutValue()
+ .append(fmtValueIndex(leftValueIndex))
+ .append(' ')
+ .append(fmtValueIndex(rightValueIndex))
+ .append(' ')
+ .append(type);
+ }
+
+ @Override
+ public void onIf(Type ifKind, int blockIndex, int valueIndex) {
+ builder.append(fmtValueIndex(valueIndex)).append(' ').append(fmtInsnIndex(blockIndex));
+ }
+
+ @Override
+ public void onGoto(int blockIndex) {
+ builder.append(fmtInsnIndex(blockIndex));
+ }
+
+ @Override
+ public void onFallthrough() {
+ // Nothing to append.
+ }
+
+ @Override
+ public void onMoveException(DexType exceptionType) {
+ appendOutValue().append(exceptionType);
+ }
+
+ @Override
+ public void onDebugLocalWrite(int srcIndex) {
+ appendOutValue().append(fmtValueIndex(srcIndex));
+ }
+
+ @Override
+ public void onInvokeMethodInstruction(DexMethod method, IntList arguments) {
+ if (!method.getReturnType().isVoidType()) {
+ appendOutValue();
+ }
+ appendValueArguments(arguments);
+ builder.append(method);
+ }
+
+ @Override
+ public void onFieldInstruction(DexField field) {
+ builder.append(field);
+ }
+
+ @Override
+ public void onStaticGet(DexField field) {
+ appendOutValue();
+ super.onStaticGet(field);
+ }
+
+ @Override
+ public void onReturnVoid() {
+ // Nothing to append.
+ }
+
+ @Override
+ public void onArrayLength(int arrayValueIndex) {
+ appendOutValue().append(fmtValueIndex(arrayValueIndex));
+ }
+
+ @Override
+ public void onDebugPosition() {
+ // Nothing to append.
+ }
+
+ @Override
+ public void onPhi(DexType type, IntList operands) {
+ appendOutValue();
+ appendValueArguments(operands);
+ builder.append(type);
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/lightir/LIRUtils.java b/src/main/java/com/android/tools/r8/lightir/LIRUtils.java
new file mode 100644
index 0000000..09dcd81
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/lightir/LIRUtils.java
@@ -0,0 +1,17 @@
+// Copyright (c) 2022, 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.lightir;
+
+public class LIRUtils {
+
+ private LIRUtils() {}
+
+ public static int encodeValueIndex(int absoluteValueIndex, int referencingValueContext) {
+ return referencingValueContext - absoluteValueIndex;
+ }
+
+ public static int decodeValueIndex(int encodedValueIndex, int referencingValueContext) {
+ return referencingValueContext - encodedValueIndex;
+ }
+}