blob: e05d521b1e535e1203e5aae96d1860ddd35deb15 [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 it.unimi.dsi.fastutil.bytes.ByteIterator;
import java.util.Iterator;
/**
* Basic iterator over the light IR.
*
* <p>This iterator is internally a zero-allocation parser with the "elements" as a view onto the
* current state.
*/
public class LIRIterator implements Iterator<LIRInstructionView>, LIRInstructionView {
private final ByteIterator iterator;
private int currentByteIndex = 0;
private int currentOpcode = -1;
private int currentOperandSize = 0;
public LIRIterator(ByteIterator iterator) {
this.iterator = iterator;
}
@Override
public boolean hasNext() {
return iterator.hasNext();
}
@Override
public LIRInstructionView next() {
currentOpcode = u1();
if (LIROpcodes.isOneByteInstruction(currentOpcode)) {
currentOperandSize = 0;
} else {
// Any instruction that is not a single byte has a two-byte header. The second byte is the
// size of the variable width operand payload.
currentOperandSize = u1();
skip(currentOperandSize);
}
return this;
}
@Override
public void accept(LIRBasicInstructionCallback eventCallback) {
int operandsOffset = currentByteIndex - currentOperandSize;
eventCallback.onInstruction(currentOpcode, operandsOffset, currentOperandSize);
}
private void skip(int i) {
currentByteIndex += i;
iterator.skip(i);
}
private int u1() {
++currentByteIndex;
return ByteUtils.fromU1(iterator.nextByte());
}
}