// $Id: BasicBlock.java,v 1.14 2000/12/12 03:19:31 msato Exp $
// $RWC_Release: Omni-1.6 $
// $RWC_Copyright:
//  Omni Compiler Software Version 1.5-1.6
//  Copyright (C) 2002 PC Cluster Consortium
//  
//  This software is free software; you can redistribute it and/or modify
//  it under the terms of the GNU Lesser General Public License version
//  2.1 published by the Free Software Foundation.
//  
//  Omni Compiler Software Version 1.0-1.4
//  Copyright (C) 1999, 2000, 2001.
//   Tsukuba Research Center, Real World Computing Partnership, Japan.
//  
//  Please check the Copyright and License information in the files named
//  COPYRIGHT and LICENSE under the top  directory of the Omni Compiler
//  Software release kit.
//  
//  
//  $
package exc.block;

import java.util.*;
import exc.object.*;

/**
 * Basic block which contain statements without control flow.
 */
public class BasicBlock extends PropObject {
  protected static int BasicBlockCounter = 0;
  int id;		// id number
  Xobject exp;		// expression at tail for branch
  Block parent;		// enclosed statement block
  Statement head,tail;

  Vector cflow_in;	/* vector of BasicBlock for flow computation */
  Vector cflow_out;	/* vector of BasicBlock for flow computation */
  int depth_first_num;	/* depth first order number */
  BasicBlock top_next; 
  BasicBlock top_prev;
  boolean mark;

  public BasicBlock(){ 
    id = BasicBlockCounter++;	// not used
    cflow_in = new Vector();
    cflow_out = new Vector();
  }

  public BasicBlock(BasicBlock b){
    for(Statement s = b.head; s != null; s = s.getNext())
      this.add(s.getExpr().copy());
    if(b.exp != null) this.exp = b.exp.copy();
  }

  public BasicBlock copy() { return new BasicBlock(this); }

  public int Id() { return id; }
  public void setId(int id) { this.id = id; }
  public Block getParent() { return parent; }
  public void setParent(Block b) { parent = b; }
  public Statement getHead() { return head; }
  public Statement getTail() { return tail; }
  public Xobject getExpr() { return exp; }
  public void setExpr(Xobject x){ exp = x; }

  public StatementIterator statements(){
    return new forwardStatementIterator(getHead());
  }

  public Vector getCflowIn() { return cflow_in; }
  public Vector getCflowOut() { return cflow_out; }

  public BasicBlock getCflowIn(int i) { 
    return (BasicBlock)(cflow_in.elementAt(i));
  }
  public BasicBlock getCflowOut(int i) { 
    return (BasicBlock)(cflow_out.elementAt(i));
  }

  public void addCflowTo(BasicBlock b){
    cflow_out.addElement(b);
    b.cflow_in.addElement(this);
  }

  public void removeCflowTo(BasicBlock b){
    cflow_out.removeElement(b);
    b.cflow_in.removeElement(this);
  }

  public BasicBlock topNext() { return top_next; }
  public BasicBlock topPrev() { return top_prev; }
  public void setTopNext(BasicBlock bb) { top_next = bb; }
  public void setTopPrev(BasicBlock bb) { top_prev = bb; }
    
  public void resetMark() { mark = false; }
  public void setMark() { mark = true; }
  public boolean isMarked() { return mark; }
  public int DFN() { return depth_first_num; }
  public void setDFN(int n) { depth_first_num = n; }

  // add at tail
  public void add(Statement s){
    s.parent = this;
    if(tail == null){
      head = tail = s;
      return;
    }
    tail.next = s;
    s.prev = tail;
    tail = s;
  }

  public void add(Xobject statement){
    add(new Statement(statement));
  }

  public void addStatement(Statement s){
    BasicBlock parent_bb;
    Block block;

    parent_bb = this;
    block = parent_bb.parent;
    if (block instanceof ForBlock) {
      if (block.prev == null) {
	BlockList bl = block.parent;
	Block b = new SimpleBlock(Xcode.EXPR_STATEMENT, new BasicBlock());
	if (bl.head != block) {
	  System.err.println("ForBlock is not first Block in BlockList");
	  System.exit(1);
	}
	bl.head = b;
	b.next = block;
	block.prev = b;
      }
      parent_bb = block.prev.getBasicBlock();
    }
    s.parent = parent_bb;
    if(parent_bb.tail == null){
      parent_bb.head = parent_bb.tail = s;
      return;
    }
    parent_bb.tail.next = s;
    s.prev = parent_bb.tail;
    parent_bb.tail = s;
  }

  public void addStatement(Xobject statement){
    addStatement(new Statement(statement));
  }

  public void insert(Xobject statement){
    insert(new Statement(statement));
  }

  public void insert(Statement s){
    s.parent = this;
    if(tail == null){
      head = tail = s;
      return;
    }
    head.prev = s;
    s.next = head;
    head = s;
  }

  public void insertStatement(Xobject statement){
    insertStatement(new Statement(statement));
  }

  public void insertStatement(Statement s){
    BasicBlock parent_bb;
    Block block;

    parent_bb = this;
    block = parent_bb.parent;
    if (block instanceof ForBlock
	|| block instanceof IfBlock) {
      if (block.parent instanceof BlockList) {
	BlockList bl = block.parent;
	Block b = new SimpleBlock(Xcode.EXPR_STATEMENT,
				  new BasicBlock());
	if (bl.head == block) {
	  bl.head = b;
	  b.next = block;
	  block.prev = b;
	} else if (bl.tail == block) {
	  b.prev = block.prev;
	  block.prev.next = b;
	  b.next = block;
	} else {
	  b.prev = block.prev;
	  block.prev.next = b;
	  b.next = block;
	  block.prev = b;
	}
	parent_bb = b.getBasicBlock();
      }
    }
    s.parent = parent_bb;
    if(parent_bb.tail == null){
      parent_bb.head = parent_bb.tail = s;
      return;
    }
    parent_bb.head.prev = s;
    s.next = parent_bb.head;
    parent_bb.head = s;
  }

  public boolean isEmpty(){
    return exp == null && head == null;
  }

  public boolean isSingle(){
    return exp == null && head != null && head == tail;
  }

  //
  // static member function for constructor
  //
  public static BasicBlock Cond(Xobject x){
    BasicBlock bb = new BasicBlock();
    bb.exp = x;
    return bb;
  }

  public static BasicBlock Statement(Xobject x){
    BasicBlock bb = new BasicBlock();
    // expand a top level of COMMA_EXPR
    if(x == null) return bb;
    if(x.Opcode() == Xcode.COMMA_EXPR){
      for(XobjArgs a = x.getArgs(); a != null; a = a.nextArgs())
	bb.add(a.getArg());
    } else 
      bb.add(x);
    return bb;
  }

  public Xobject toXobject(){
    if(head == null) return exp;
    if(head == tail && exp == null) return head.getExpr();
    Xobject l = new XobjList(Xcode.COMMA_EXPR);
    for(Statement s = head; s != null; s = s.getNext())
      if(s.getExpr() != null) l.add(s.getExpr());
    if(exp != null) l.add(exp);
    return l;
  }

  public String toString(){
    return "BB:"+id;
  }
}

