/*
* $Id$
*
* Copyright (C) 2003-2015 JNode.org
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; If not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
package org.jnode.vm.compiler.ir;
import java.util.List;
import org.jnode.vm.compiler.ir.quad.BranchQuad;
import org.jnode.vm.compiler.ir.quad.PhiAssignQuad;
import org.jnode.vm.compiler.ir.quad.Quad;
import org.jnode.vm.objects.BootableArrayList;
/**
* @author Madhu Siddalingaiah
*/
public class IRBasicBlock<T> {
private boolean startOfExceptionHandler;
private int endPC;
private int startPC;
private Variable<T>[] variables;
private static int blockIndex = 1;
private static int postOrderCounter = 1;
private String name;
/**
* This blocks immediate dominator (up the dom tree)
*/
private IRBasicBlock<T> idominator;
/**
* The blocks immediately dominated (down the dom tree)
*/
private List<IRBasicBlock<T>> dominatedBlocks;
/**
* The blocks in the dominance frontier of this block
*/
private List<IRBasicBlock<T>> dominanceFrontier;
/**
* The immediate successors of this block
*/
private List<IRBasicBlock<T>> successors;
/**
* The immediate predecessors of this block
*/
private List<IRBasicBlock<T>> predecessors;
/**
* Depth from the root (root = 0, next lower = 1 etc., unknown = -1)
*/
private int postOrderNumber;
/**
* The quads in this block
*/
private List<Quad<T>> quads;
private BootableArrayList<Operand> defList;
// The stack offset at the beginning of this block
// In some cases, e.g. terniary operators, this is important
private int stackOffset;
/**
* @param startPC
* @param endPC
* @param startOfExceptionHandler
*/
public IRBasicBlock(
int startPC,
int endPC,
boolean startOfExceptionHandler) {
this.startPC = startPC;
this.endPC = endPC;
this.startOfExceptionHandler = startOfExceptionHandler;
this.stackOffset = -1; // We'll check to make sure this is set
this.name = "B" + startPC;
predecessors = new BootableArrayList<IRBasicBlock<T>>();
successors = new BootableArrayList<IRBasicBlock<T>>();
dominatedBlocks = new BootableArrayList<IRBasicBlock<T>>();
postOrderNumber = -1;
dominanceFrontier = new BootableArrayList<IRBasicBlock<T>>();
quads = new BootableArrayList<Quad<T>>();
defList = new BootableArrayList<Operand>();
}
/**
* @param address
*/
public IRBasicBlock(int address) {
this(address, -1, false);
}
private void addPredecessor(IRBasicBlock<T> p) {
if (!predecessors.contains(p)) {
predecessors.add(p);
}
}
public void addDominatedBlock(IRBasicBlock<T> db) {
if (!dominatedBlocks.contains(db)) {
dominatedBlocks.add(db);
}
}
/**
* @return the variables for the basic block
*/
public Variable<T>[] getVariables() {
if (variables == null) {
variables = idominator.getVariables();
}
if (variables == null) {
throw new AssertionError("variables are null!");
}
return variables;
}
/**
* @param variables new variables for the basic block
*/
public void setVariables(Variable<T>[] variables) {
this.variables = variables;
}
/**
* @return the stack offset for the basic block
*/
public int getStackOffset() {
if (stackOffset < 0) {
stackOffset = idominator.getStackOffset();
}
if (stackOffset < 0) {
throw new AssertionError("stack offset is invalid!");
}
return stackOffset;
}
/**
* @param initialOffset
*/
public void setStackOffset(int initialOffset) {
stackOffset = initialOffset;
}
/**
* @param q a quad
*/
public void add(Quad<T> q) {
addDef(q);
int n = quads.size();
if (n < 1 || q instanceof BranchQuad || !(quads.get(n - 1) instanceof BranchQuad)) {
quads.add(q);
} else {
quads.add(n - 1, q);
}
}
public void add(PhiAssignQuad<T> paq) {
if (!quads.contains(paq)) {
addDef(paq);
quads.add(0, paq);
}
}
private void addDef(Quad<T> q) {
Operand<T> def = q.getDefinedOp();
if (def instanceof Variable &&
!defList.contains(def)) {
defList.add(def);
}
}
/**
* @return the successors
*/
public List<IRBasicBlock<T>> getSuccessors() {
return successors;
}
/**
* @return the idominator
*/
public IRBasicBlock<T> getIDominator() {
return idominator;
}
/**
* @return the block name
*/
public String getName() {
return name;
}
/**
* @return the predecessors
*/
public List<IRBasicBlock<T>> getPredecessors() {
return predecessors;
}
/**
* @param block
*/
public void addSuccessor(IRBasicBlock<T> block) {
if (!successors.contains(block)) {
successors.add(block);
block.addPredecessor(this);
}
}
/**
* @param block
*/
public void setIDominator(IRBasicBlock<T> block) {
idominator = block;
if (block != null) {
block.addDominatedBlock(this);
}
}
/**
* @param string
*/
public void setName(String string) {
name = string;
}
/**
* @return the post-order number
*/
public int getPostOrderNumber() {
return postOrderNumber;
}
/**
* @param i
*/
public void setPostOrderNumber(int i) {
postOrderNumber = i;
}
public void computePostOrder(List<IRBasicBlock<T>> list) {
setPostOrderNumber(0);
for (IRBasicBlock<T> b : successors) {
if (b.getPostOrderNumber() < 0) {
b.computePostOrder(list);
}
}
setPostOrderNumber(postOrderCounter++);
list.add(this);
}
public void printDomTree() {
System.out.print(getName() + " doms:");
IRBasicBlock<T> d = getIDominator();
while (d != null) {
System.out.print(' ' + d.getName());
d = d.getIDominator();
}
System.out.println();
}
public void printPredecessors() {
System.out.print(getName() + " preds:");
for (IRBasicBlock b : predecessors) {
System.out.print(' ' + b.getName());
}
System.out.println();
}
/**
* @param b
*/
public void addDominanceFrontier(IRBasicBlock<T> b) {
if (!dominanceFrontier.contains(b)) {
dominanceFrontier.add(b);
}
}
/**
* @return the dominance frontier
*/
public List<IRBasicBlock<T>> getDominanceFrontier() {
return dominanceFrontier;
}
/**
* @return the dominated blocks
*/
public List<IRBasicBlock<T>> getDominatedBlocks() {
return dominatedBlocks;
}
/**
* @return the quads
*/
public List<Quad<T>> getQuads() {
return quads;
}
/**
* @return the def list
*/
public List<Operand> getDefList() {
return defList;
}
/**
* @return the end PC
*/
public int getEndPC() {
return endPC;
}
/**
* @return the start PC
*/
public int getStartPC() {
return startPC;
}
/**
* @param i
*/
public void setEndPC(int i) {
endPC = i;
}
/**
* @param i
*/
public void setStartPC(int i) {
startPC = i;
}
/**
* @return {@code true} if this block is the start of an exception handler,
* otherwise {@code false}
*/
public boolean isStartOfExceptionHandler() {
return startOfExceptionHandler;
}
/**
* @param b
*/
public void setStartOfExceptionHandler(boolean b) {
startOfExceptionHandler = b;
}
/**
* @param pc a PC value
* @return {@code true} if the basic block contains the given PC
*/
public boolean contains(int pc) {
return ((pc >= startPC) && (pc < endPC));
}
public String toString() {
return name;
}
}