com.android.dx.rop.code.BasicBlock Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of builder Show documentation
Show all versions of builder Show documentation
Library to build Android applications.
/*
* Copyright (C) 2007 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.dx.rop.code;
import com.android.dx.rop.type.TypeList;
import com.android.dx.util.Hex;
import com.android.dx.util.IntList;
import com.android.dx.util.LabeledItem;
/**
* Basic block of register-based instructions.
*/
public final class BasicBlock implements LabeledItem {
/** {@code >= 0;} target label for this block */
private final int label;
/** {@code non-null;} list of instructions in this block */
private final InsnList insns;
/**
* {@code non-null;} full list of successors that this block may
* branch to
*/
private final IntList successors;
/**
* {@code >= -1;} the primary / standard-flow / "default" successor, or
* {@code -1} if this block has no successors (that is, it
* exits the function/method)
*/
private final int primarySuccessor;
/**
* Constructs an instance. The predecessor set is set to {@code null}.
*
* @param label {@code >= 0;} target label for this block
* @param insns {@code non-null;} list of instructions in this block
* @param successors {@code non-null;} full list of successors that this
* block may branch to
* @param primarySuccessor {@code >= -1;} the primary / standard-flow /
* "default" successor, or {@code -1} if this block has no
* successors (that is, it exits the function/method or is an
* unconditional throw)
*/
public BasicBlock(int label, InsnList insns, IntList successors,
int primarySuccessor) {
if (label < 0) {
throw new IllegalArgumentException("label < 0");
}
try {
insns.throwIfMutable();
} catch (NullPointerException ex) {
// Elucidate exception.
throw new NullPointerException("insns == null");
}
int sz = insns.size();
if (sz == 0) {
throw new IllegalArgumentException("insns.size() == 0");
}
for (int i = sz - 2; i >= 0; i--) {
Rop one = insns.get(i).getOpcode();
if (one.getBranchingness() != Rop.BRANCH_NONE) {
throw new IllegalArgumentException("insns[" + i + "] is a " +
"branch or can throw");
}
}
Insn lastInsn = insns.get(sz - 1);
if (lastInsn.getOpcode().getBranchingness() == Rop.BRANCH_NONE) {
throw new IllegalArgumentException("insns does not end with " +
"a branch or throwing " +
"instruction");
}
try {
successors.throwIfMutable();
} catch (NullPointerException ex) {
// Elucidate exception.
throw new NullPointerException("successors == null");
}
if (primarySuccessor < -1) {
throw new IllegalArgumentException("primarySuccessor < -1");
}
if (primarySuccessor >= 0 && !successors.contains(primarySuccessor)) {
throw new IllegalArgumentException(
"primarySuccessor " + primarySuccessor + " not in successors " + successors);
}
this.label = label;
this.insns = insns;
this.successors = successors;
this.primarySuccessor = primarySuccessor;
}
/**
* {@inheritDoc}
*
* Instances of this class compare by identity. That is,
* {@code x.equals(y)} is only true if {@code x == y}.
*/
@Override
public boolean equals(Object other) {
return (this == other);
}
/**
* {@inheritDoc}
*
* Return the identity hashcode of this instance. This is proper,
* since instances of this class compare by identity (see {@link #equals}).
*/
@Override
public int hashCode() {
return System.identityHashCode(this);
}
/**
* Gets the target label of this block.
*
* @return {@code >= 0;} the label
*/
public int getLabel() {
return label;
}
/**
* Gets the list of instructions inside this block.
*
* @return {@code non-null;} the instruction list
*/
public InsnList getInsns() {
return insns;
}
/**
* Gets the list of successors that this block may branch to.
*
* @return {@code non-null;} the successors list
*/
public IntList getSuccessors() {
return successors;
}
/**
* Gets the primary successor of this block.
*
* @return {@code >= -1;} the primary successor, or {@code -1} if this
* block has no successors at all
*/
public int getPrimarySuccessor() {
return primarySuccessor;
}
/**
* Gets the secondary successor of this block. It is only valid to call
* this method on blocks that have exactly two successors.
*
* @return {@code >= 0;} the secondary successor
*/
public int getSecondarySuccessor() {
if (successors.size() != 2) {
throw new UnsupportedOperationException(
"block doesn't have exactly two successors");
}
int succ = successors.get(0);
if (succ == primarySuccessor) {
succ = successors.get(1);
}
return succ;
}
/**
* Gets the first instruction of this block. This is just a
* convenient shorthand for {@code getInsns().get(0)}.
*
* @return {@code non-null;} the first instruction
*/
public Insn getFirstInsn() {
return insns.get(0);
}
/**
* Gets the last instruction of this block. This is just a
* convenient shorthand for {@code getInsns().getLast()}.
*
* @return {@code non-null;} the last instruction
*/
public Insn getLastInsn() {
return insns.getLast();
}
/**
* Returns whether this block might throw an exception. This is
* just a convenient shorthand for {@code getLastInsn().canThrow()}.
*
* @return {@code true} iff this block might throw an
* exception
*/
public boolean canThrow() {
return insns.getLast().canThrow();
}
/**
* Returns whether this block has any associated exception handlers.
* This is just a shorthand for inspecting the last instruction in
* the block to see if it could throw, and if so, whether it in fact
* has any associated handlers.
*
* @return {@code true} iff this block has any associated
* exception handlers
*/
public boolean hasExceptionHandlers() {
Insn lastInsn = insns.getLast();
return lastInsn.getCatches().size() != 0;
}
/**
* Returns the exception handler types associated with this block,
* if any. This is just a shorthand for inspecting the last
* instruction in the block to see if it could throw, and if so,
* grabbing the catch list out of it. If not, this returns an
* empty list (not {@code null}).
*
* @return {@code non-null;} the exception handler types associated with
* this block
*/
public TypeList getExceptionHandlerTypes() {
Insn lastInsn = insns.getLast();
return lastInsn.getCatches();
}
/**
* Returns an instance that is identical to this one, except that
* the registers in each instruction are offset by the given
* amount.
*
* @param delta the amount to offset register numbers by
* @return {@code non-null;} an appropriately-constructed instance
*/
public BasicBlock withRegisterOffset(int delta) {
return new BasicBlock(label, insns.withRegisterOffset(delta),
successors, primarySuccessor);
}
public String toString() {
return '{' + Hex.u2(label) + '}';
}
/**
* BasicBlock visitor interface
*/
public interface Visitor {
/**
* Visits a basic block
* @param b block visited
*/
public void visitBlock (BasicBlock b);
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy