blob: 3f84cdfd372942e87c63e0a543825ae972de24a6 [file] [log] [blame]
// 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.graph.DebugLocalInfo;
import com.android.tools.r8.graph.DexItem;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.ir.code.CatchHandlers;
import com.android.tools.r8.ir.code.IRMetadata;
import com.android.tools.r8.ir.code.Position;
import it.unimi.dsi.fastutil.ints.Int2ReferenceMap;
import java.util.Map;
import java.util.function.BiConsumer;
public class LirCode<EV> implements Iterable<LirInstructionView> {
public static class PositionEntry {
final int fromInstructionIndex;
final Position position;
public PositionEntry(int fromInstructionIndex, Position position) {
this.fromInstructionIndex = fromInstructionIndex;
this.position = position;
}
}
public static class TryCatchTable {
final Int2ReferenceMap<CatchHandlers<Integer>> tryCatchHandlers;
public TryCatchTable(Int2ReferenceMap<CatchHandlers<Integer>> tryCatchHandlers) {
this.tryCatchHandlers = tryCatchHandlers;
}
public CatchHandlers<Integer> getHandlersForBlock(int blockIndex) {
return tryCatchHandlers.get(blockIndex);
}
}
public static class DebugLocalInfoTable<EV> {
private final Map<EV, DebugLocalInfo> valueToLocalMap;
private final Int2ReferenceMap<int[]> instructionToEndUseMap;
public DebugLocalInfoTable(
Map<EV, DebugLocalInfo> valueToLocalMap, Int2ReferenceMap<int[]> instructionToEndUseMap) {
assert !valueToLocalMap.isEmpty();
assert !instructionToEndUseMap.isEmpty();
this.valueToLocalMap = valueToLocalMap;
this.instructionToEndUseMap = instructionToEndUseMap;
}
public void forEachLocalDefinition(BiConsumer<EV, DebugLocalInfo> fn) {
valueToLocalMap.forEach(fn);
}
}
private final LirStrategyInfo<EV> strategyInfo;
private final IRMetadata metadata;
/** Constant pool of items. */
private final DexItem[] constants;
private final PositionEntry[] positionTable;
/** Full number of arguments (including receiver for non-static methods). */
private final int argumentCount;
/** Byte encoding of the instructions (excludes arguments, includes phis). */
private final byte[] instructions;
/** Cached value for the number of logical instructions (excludes arguments, includes phis). */
private final int instructionCount;
/** Table of try-catch handlers for each basic block. */
private final TryCatchTable tryCatchTable;
/** Table of debug local information for each SSA value (if present). */
private final DebugLocalInfoTable<EV> debugLocalInfoTable;
public static <V, EV> LirBuilder<V, EV> builder(
DexMethod method, LirEncodingStrategy<V, EV> strategy, DexItemFactory factory) {
return new LirBuilder<>(method, strategy, factory);
}
/** Should be constructed using {@link LirBuilder}. */
LirCode(
IRMetadata metadata,
DexItem[] constants,
PositionEntry[] positions,
int argumentCount,
byte[] instructions,
int instructionCount,
TryCatchTable tryCatchTable,
DebugLocalInfoTable<EV> debugLocalInfoTable,
LirStrategyInfo<EV> strategyInfo) {
this.metadata = metadata;
this.constants = constants;
this.positionTable = positions;
this.argumentCount = argumentCount;
this.instructions = instructions;
this.instructionCount = instructionCount;
this.tryCatchTable = tryCatchTable;
this.debugLocalInfoTable = debugLocalInfoTable;
this.strategyInfo = strategyInfo;
}
public EV decodeValueIndex(int encodedValueIndex, int currentValueIndex) {
return strategyInfo
.getReferenceStrategy()
.decodeValueIndex(encodedValueIndex, currentValueIndex);
}
public LirStrategyInfo<EV> getStrategyInfo() {
return strategyInfo;
}
public int getArgumentCount() {
return argumentCount;
}
public byte[] getInstructionBytes() {
return instructions;
}
public int getInstructionCount() {
return instructionCount;
}
public IRMetadata getMetadata() {
return metadata;
}
public DexItem getConstantItem(int index) {
return constants[index];
}
public PositionEntry[] getPositionTable() {
return positionTable;
}
public TryCatchTable getTryCatchTable() {
return tryCatchTable;
}
public DebugLocalInfoTable<EV> getDebugLocalInfoTable() {
return debugLocalInfoTable;
}
public DebugLocalInfo getDebugLocalInfo(EV valueIndex) {
return debugLocalInfoTable == null ? null : debugLocalInfoTable.valueToLocalMap.get(valueIndex);
}
public int[] getDebugLocalEnds(int instructionValueIndex) {
return debugLocalInfoTable == null
? null
: debugLocalInfoTable.instructionToEndUseMap.get(instructionValueIndex);
}
@Override
public LirIterator iterator() {
return new LirIterator(new ByteArrayIterator(instructions));
}
@Override
public String toString() {
return new LirPrinter<>(this).prettyPrint();
}
}