// $Id: OMPBlock.java,v 1.5 2000/06/12 06:50:52 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.openmp;

import exc.block.*;
import exc.object.*;

import java.util.Vector;
import java.util.Enumeration;
//
// OpenMP Block
//  Forall,ParallelRegion,Sections,
//  Single,Ordered,Master,Critical,Atomic,Flush,Barrier
//
public class OMPBlock extends Block {
  BasicBlock end_bb;
  BlockList body;
  int narg;
  Xobject info; // note: info is not check in flow analysis.

  public OMPBlock(int code){
    super(code,new BasicBlock());
    end_bb = new BasicBlock();
    end_bb.setParent(this);
  }

  public OMPBlock(int code,BasicBlock bblock){
    super(code,bblock);
    end_bb = new BasicBlock();
    end_bb.setParent(this);
  }

  public OMPBlock(int code,BasicBlock bb1,BasicBlock bb2){
    super(code,bb1);
    end_bb = bb2;
    end_bb.setParent(this);
  }

  /* access function */
  public BasicBlock beginBasicBlock(){
    return getBasicBlock();
  }

  public boolean isBeginBasicBlock(BasicBlock b){
    return b == getBasicBlock();
  }

  public BasicBlock endBasicBlock(){
    return end_bb;
  }

  public boolean isEndBasicBlock(BasicBlock b){
    return end_bb == b;
  }

  public BlockList getBody() { return body; }

  public void setBody(BlockList s){
    body = s;
    s.setParent(this);
  }

  public Xobject getInfoExpr(){ return info; }
  public void setInfoExpr(Xobject x) { info = x; }

  public int getNarg() { return narg; }
  public void setNarg(int n) { narg = n; }

  public void visitBasicBlock(BasicBlockVisitor v){
    v.visit(beginBasicBlock());
    v.visit(endBasicBlock());
  }

  /* 
   * static constructor interface
   */
  public static OMPBlock Barrier(){
    return new OMPBlock(Xcode.OMP_BARRIER);
  }
  
  public static OMPBlock Flush(Vector flush_vars){
    OMPBlock b = new OMPBlock(Xcode.OMP_FLUSH);
    if(flush_vars != null){
      /* expand vector to list */
      Xobject l = Xcons.emptyList();
      for(Enumeration e = flush_vars.elements(); e.hasMoreElements();){
	Xobject v = (Xobject)e.nextElement();
	l.add(v);
      }
      b.info = l;
    }
    return b;
  }
 
  public static OMPBlock Master(BlockList body){
    OMPBlock b = new OMPBlock(Xcode.OMP_MASTER);
    b.setBody(body);
    return b;
  }
  
  public static OMPBlock Ordered(BlockList body){
    OMPBlock b = new OMPBlock(Xcode.OMP_ORDERED);
    b.setBody(body);
    return b;
  }
  
  public static OMPBlock Single(BlockList body){
    OMPBlock b = new OMPBlock(Xcode.OMP_SINGLE);
    b.setBody(body);
    return b;
  }

  public static OMPBlock Sections(int n,BlockList body){
    OMPBlock b = new OMPBlock(Xcode.OMP_SECTIONS);
    b.setBody(body);
    b.narg = n;
    return b;
  }

  public static OMPBlock Critical(Xobject name,BlockList body){
    OMPBlock b = new OMPBlock(Xcode.OMP_CRITICAL);
    b.setBody(body);
    b.info = name;
    return b;
  }
  
  public static OMPBlock Atomic(Xobject expr){
    OMPBlock b = new OMPBlock(Xcode.OMP_ATOMIC);
    BlockList body = Bcons.emptyBody();
    body.add(Bcons.Statement(expr));
    b.setBody(body);
    return b;
  }

  public static OMPparallelBlock ParallelRegion(int narg,BasicBlock setup_bb,
			      BlockList body, Xobject cond){
    return new OMPparallelBlock(narg,setup_bb,body,cond);
  }
  
  public static OMPforallBlock Forall(Xobject var,
				      Xobject lb,Xobject ub, Xobject step,
				      int checkOpcode,
				      BlockList body,
				      int sched,Xobject chunk,boolean 
				      ordered){
    return new OMPforallBlock(var,lb,ub,step,checkOpcode,body,
			      sched,chunk,ordered);
  }
}



