// $Id: OMPrewriteExpr.java,v 1.7 2000/10/11 10:33:32 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.object.*;
import exc.block.*;

//
// pass2: check and write variables
//
public class OMPrewriteExpr {
  BasicBlockExprIterator iter;
  OMPfileEnv env;

  public void run(FuncDefBlock def,OMPfileEnv env){
    if(OMP.debugFlag) System.out.println("pass2:");
    this.env = env;
    Block fblock = def.getBlock();
    iter = new BasicBlockExprIterator(fblock);
    for(iter.init(); !iter.end(); iter.next()){
      Xobject x = iter.getExpr();
      if(x == null) continue;
      iter.setExpr(rewriteExpr(x));
    }
  }

  // find data attribute in current enviroment
  OMPvar checkOMPvar(String name){
    return OMPinfo.refOMPvar(iter.getBasicBlock().getParent(),name);
  }

  void checkReductionExpr(OMPvar v,Xobject x,Xobject parent){
    x.setProp(OMP.prop,v);	/* mark it */
    if(parent == null) return;
    switch(parent.Opcode()){
    case Xcode.POST_INCR_EXPR:
    case Xcode.POST_DECR_EXPR:
      /* this must be ok */
      parent.setOperand(v.Ref());
      break;
    case Xcode.ASG_PLUS_EXPR:
    case Xcode.ASG_MUL_EXPR:
    case Xcode.ASG_MINUS_EXPR:
    case Xcode.ASG_BIT_AND_EXPR:
    case Xcode.ASG_BIT_OR_EXPR:
    case Xcode.ASG_BIT_XOR_EXPR:
      /* left must be x */
      if(parent.left() == x) parent.setLeft(v.Ref());
      break;
    case Xcode.ASSIGN_EXPR:
      /* left must be x */
      if(parent.left() != x) break;
      Xobject rv = parent.right();
      switch(rv.Opcode()){
      case Xcode.PLUS_EXPR:
      case Xcode.MUL_EXPR:
      case Xcode.BIT_AND_EXPR:
      case Xcode.BIT_OR_EXPR:
      case Xcode.BIT_XOR_EXPR:
      case Xcode.LOG_AND_EXPR:
      case Xcode.LOG_OR_EXPR:
	if(((OMPvar)rv.right().getProp(OMP.prop)) == v){
	  parent.setLeft(v.Ref());
	  rv.setRight(v.Ref());
	  break;
	}
      case Xcode.MINUS_EXPR:
	if(((OMPvar)rv.left().getProp(OMP.prop)) == v){
	  parent.setLeft(v.Ref());
	  rv.setLeft(v.Ref());
	  break;
	}
      }
    }
  }

  // pass2:
  // 	 check and rewrite variable reference 
  public Xobject rewriteExpr(Xobject x){
    OMPvar v;
    if(x == null) return null;
    XobjectIterator i = new bottomupXobjectIterator(x);
    for(i.init(); !i.end(); i.next()){
      Xobject xx = i.getXobject();
      if(OMP.debugFlag) System.out.println("expr1="+xx);
      if(xx == null) continue;

      if(xx.isFCOMM()){
	Xobject comm = xx.getFCOMM();
	if(comm.Opcode() == Xcode.IDENT){
	  Ident comm_id = env.getFile().findIdent(comm.getName());
	  if(comm_id != null && env.isThreadPrivate(comm_id) &&
	     (v = checkOMPvar(comm.getName())) != null){
	    xx.setFCOMM(v.Ref());
	    continue;
	  }
	}
      }

      if(xx.isVariable()){
	if((v = checkOMPvar(xx.getName())) == null) continue;
	if(v.is_reduction)
	  checkReductionExpr(v,xx,i.getParent());
	else i.setXobject(v.Ref());
      } else if(xx.isVarAddr()){
	if((v = checkOMPvar(xx.getName())) == null) continue;
	if(v != null) i.setXobject(v.getAddr());
	if(v.is_reduction){
	  OMP.warning(iter.getLineNo(),
		      "may be bad reference for reduction variable,'"+
		      xx.getName()+"'");
	}
      } else if(xx.isArrayAddr()){
	if((v = checkOMPvar(xx.getName())) == null) continue;
	if(v != null) i.setXobject(v.getAddr());
      } else if(xx.Opcode() == Xcode.ASSIGN_EXPR &&
		(v = ((OMPvar)xx.left().getProp(OMP.prop))) != null){
	checkReductionExpr(v,xx.left(),xx);
      }
    }

    /* check remaining reduction variable */
    for(i.init(); !i.end(); i.next()){
      Xobject xx = i.getXobject();
      if(OMP.debugFlag) System.out.println("expr2="+xx);
      if(xx == null) continue;
      if(xx.isVariable() && (v = ((OMPvar)xx.getProp(OMP.prop))) != null){
	if(i.getParent() != null && 
	   i.getParent().Opcode() == Xcode.ASSIGN_EXPR &&
	   i.getParent().left() == xx &&
	   !Xtype.isFComplex(xx.Type()) &&
	   v.reduction_op != OMP.DATA_REDUCTION_MIN &&
	   v.reduction_op != OMP.DATA_REDUCTION_MAX)
	  OMP.warning(iter.getLineNo(),
		      "may be bad reference for reduction variable,'"+
		      xx.getName()+"'");
	i.setXobject(v.Ref());
      }
    }
    return i.topXobject();
  }
}  

