blob: 357ff337078481363fb33509363c0b8694b40bb4 [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.ir.analysis.framework.intraprocedural.cf;
import com.android.tools.r8.cf.code.CfInstruction;
import com.android.tools.r8.graph.CfCode;
import com.android.tools.r8.utils.SetUtils;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
/** A basic block for {@link com.android.tools.r8.graph.CfCode}. */
public class CfBlock {
// The CfCode instruction index of the block's first instruction.
int firstInstructionIndex = -1;
// The CfCode instruction index of the block's last instruction.
int lastInstructionIndex = -1;
// The predecessors of the block. These are stored explicitly (unlike the successors) since they
// cannot efficiently be computed from the block.
final Set<CfBlock> predecessors = new LinkedHashSet<>();
// The exceptional predecessors of the block.
final List<CfBlock> exceptionalPredecessors = new ArrayList<>();
// The exceptional successors of the block (i.e., the catch handlers of the block).
final List<CfBlock> exceptionalSuccessors = new ArrayList<>();
public CfInstruction getFallthroughInstruction(CfCode code) {
int fallthroughInstructionIndex = getLastInstructionIndex() + 1;
return fallthroughInstructionIndex < code.getInstructions().size()
? code.getInstructions().get(fallthroughInstructionIndex)
: null;
}
public int getFirstInstructionIndex() {
return firstInstructionIndex;
}
public CfInstruction getLastInstruction(CfCode code) {
return code.getInstructions().get(lastInstructionIndex);
}
public int getLastInstructionIndex() {
return lastInstructionIndex;
}
public Collection<CfBlock> getPredecessors() {
return predecessors;
}
// TODO(b/214496607): This currently only encodes the graph, but we likely need to include the
// guard types here.
public List<CfBlock> getExceptionalPredecessors() {
return exceptionalPredecessors;
}
// TODO(b/214496607): This currently only encodes the graph, but we likely need to include the
// guard types here.
public List<CfBlock> getExceptionalSuccessors() {
return exceptionalSuccessors;
}
// A mutable interface for block construction.
static class MutableCfBlock extends CfBlock {
void addPredecessor(CfBlock block) {
predecessors.add(block);
}
void addExceptionalPredecessor(CfBlock block) {
exceptionalPredecessors.add(block);
}
void addExceptionalSuccessor(CfBlock block) {
exceptionalSuccessors.add(block);
}
void setFirstInstructionIndex(int firstInstructionIndex) {
this.firstInstructionIndex = firstInstructionIndex;
}
void setLastInstructionIndex(int lastInstructionIndex) {
this.lastInstructionIndex = lastInstructionIndex;
}
boolean validate() {
assert 0 <= firstInstructionIndex;
assert firstInstructionIndex <= lastInstructionIndex;
assert SetUtils.newIdentityHashSet(predecessors).size() == predecessors.size();
return true;
}
}
}