// $Id: FuncDefBlock.java,v 1.10 2000/04/24 07:08:27 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.io.*;
import exc.object.*;

public class FuncDefBlock {
  protected XobjectDef def;
  protected Block fblock;
  String funcBlockProp = "funcBlock";

  public FuncDefBlock(XobjectDef def){
    this.def = def;
    fblock = (Block)def.getProp(funcBlockProp); // check cache
    if(fblock == null){
      def.setDef(canonicalizeExpr(def.getDef()));
      fblock = Bcons.buildFunctionBlock(def);
      def.setProp(funcBlockProp,fblock);
    } 
  }

  // make clone
  public FuncDefBlock(FuncDefBlock fd){ 
    this.def = fd.def;
    this.fblock = fd.fblock;
  }

  public FuncDefBlock(String name,Xobject id_list,
		      Xobject decls, BlockList body, XobjectFile env){
    // make dummy XobjectDef 
    this.def = XobjectDef.Func(name,id_list,decls,body.toXobject()); 
    def.setProp(funcBlockProp,
		new FunctionBlock(name,id_list,decls,
				  Bcons.COMPOUND(body),env));
  }

  public Block getBlock() { return fblock; }
  public XobjectDef getDef() { return def; }
  public XobjectFile getFile() { return def.getFile(); }

  public void Finalize(){
    // System.out.println("-- Finalize:"); print();
    def.setDef(fblock.toXobject());
    def.remProp(funcBlockProp);		// flush cache
  }

  public void removeDeclInit(){
    BlockIterator i = new topdownBlockIterator(fblock);
    for(i.init(); !i.end(); i.next()){
      BlockList body = i.getBlock().getBody();
      if(body != null) body.removeDeclInit();
    }
  }

  /* rewrite VarAddr -> (ADDR_OF Var) */
  Xobject canonicalizeExpr(Xobject e){
    Xobject s;
    XobjectIterator i = new bottomupXobjectIterator(e);
    for(i.init(); !i.end(); i.next()){
      Xobject x = i.getXobject();
      if(x == null) continue;
      // if type is null, don't care 
      if(x.isVarAddr() && x.Type() != null){
	i.setXobject(Xcons.AddrOf(Xcons.PointerRef(x)));
      } else if(x.Opcode() == Xcode.POINTER_REF &&
	      x.left().Opcode() == Xcode.ADDR_OF)
	i.setXobject(x.left().left());
    }
    return i.topXobject();
  }

  /* for debug */
  public void print(){  print(System.out); }

  public void print(OutputStream out){
     BlockPrintWriter debug_out = new BlockPrintWriter(out);
     debug_out.print(fblock); debug_out.flush();
  }

  public void print(Writer out){
     BlockPrintWriter debug_out = new BlockPrintWriter(out);
     debug_out.print(fblock); debug_out.flush();
  }
}


