Program Listing for File VariableStateTransfer.h

Program Listing for File VariableStateTransfer.h#

Return to documentation for file (src/midend/programAnalysis/genericDataflow/simpleAnalyses/VariableStateTransfer.h)

#include <featureTests.h>
#ifdef ROSE_ENABLE_SOURCE_ANALYSIS

#ifndef _VARIABLESTATETRANSFER_H
#define _VARIABLESTATETRANSFER_H

#include "dataflow.h"
#include "latticeFull.h"
#include "liveDeadVarAnalysis.h"

#include <vector>

template <class LatticeType>
class VariableStateTransfer : public IntraDFTransferVisitor
{
protected:
  bool modified;
  void updateModified(bool latModified) { modified = latModified || modified; }

  const int debugLevel;

  FiniteVarsExprsProductLattice* prodLat;

  LatticeType *getLattice(const SgExpression *sgn) {
    return sgn ? getLattice(SgExpr2Var(sgn)) : NULL;
  }
  LatticeType *getLattice(varID var) {
    return dynamic_cast<LatticeType *>(prodLat->getVarLattice(var));
  }

  bool getLattices(const SgBinaryOp *sgn, LatticeType* &arg1Lat, LatticeType* &arg2Lat, LatticeType* &resLat) {
    arg1Lat = getLattice(sgn->get_lhs_operand());
    arg2Lat = getLattice(sgn->get_rhs_operand());
    resLat = getLattice(sgn);

    if(isSgCompoundAssignOp(sgn)) {
      if(resLat==NULL && arg1Lat != NULL)
        resLat = arg1Lat;
    }
    //Dbg::dbg << "transfer B, resLat="<<resLat<<"\n";

    return (arg1Lat && arg2Lat && resLat);
  }

  bool getLattices(const SgUnaryOp *sgn,  LatticeType* &arg1Lat, LatticeType* &arg2Lat, LatticeType* &resLat) {
    arg1Lat = getLattice(sgn->get_operand());
    resLat = getLattice(sgn);

    // Unary Update
    if(isSgMinusMinusOp(sgn) || isSgPlusPlusOp(sgn)) {
      arg2Lat = new LatticeType(1);
    }
    //Dbg::dbg << "res="<<res.str()<<" arg1="<<arg1.str()<<" arg1Lat="<<arg1Lat<<", arg2Lat="<<arg2Lat<<"\n";
    //Dbg::dbg << "transfer B, resLat="<<resLat<<"\n";

    return (arg1Lat && arg2Lat && resLat);
  }

public:
  VariableStateTransfer(const Function& func, const DataflowNode& n, NodeState& state, const std::vector<Lattice*>& dfInfo, const int &debugLevel_)
    : IntraDFTransferVisitor(func, n, state, dfInfo), modified(false), debugLevel(debugLevel_), prodLat(dynamic_cast<FiniteVarsExprsProductLattice*>(*(dfInfo.begin())))
  {
    //Dbg::dbg << "transfer A prodLat="<<prodLat<<"="<<prodLat->str("    ")<<"\n";
    // Make sure that all the lattices are initialized
    //prodLat->initialize();
    const std::vector<Lattice*>& lattices = prodLat->getLattices();
    for(std::vector<Lattice*>::const_iterator it = lattices.begin(); it!=lattices.end(); it++)
      (dynamic_cast<LatticeType *>(*it))->initialize();
  }

  void visit(SgAssignOp *sgn)
  {
    LatticeType *lhsLat, *rhsLat, *resLat;
    getLattices(sgn, lhsLat, rhsLat, resLat);

    if(debugLevel>=1) {
      if(resLat) Dbg::dbg << "resLat=\n    "<<resLat->str("    ")<<"\n";
      if(lhsLat) Dbg::dbg << "lhsLat=\n    "<<lhsLat->str("    ")<<"\n";
      if(rhsLat) Dbg::dbg << "rhsLat=\n    "<<rhsLat->str("    ")<<"\n";
    }

    // Copy the lattice of the right-hand-side to both the left-hand-side variable and to the assignment expression itself
    if(resLat) // If the left-hand-side contains a live expression or variable
      { resLat->copy(rhsLat); modified = true; }
    if(lhsLat) // If the left-hand-side contains a live expression or variable
      { lhsLat->copy(rhsLat); modified = true; }
  }

  void visit(SgAssignInitializer *sgn)
  {
    LatticeType* asgnLat = getLattice(sgn->get_operand());
    LatticeType* resLat = getLattice(sgn);

    if(debugLevel>=1) {
      if(asgnLat) Dbg::dbg << "asgnLat=    "<<asgnLat->str("    ")<<"\n";
      if(resLat) Dbg::dbg << "resLat=    "<<resLat->str("    ")<<"\n";
    }

    // If the result expression is live
    if(resLat) { resLat->copy(asgnLat); modified = true; }
  }

  // XXX: Right now, we take the meet of all of the elements of the
  // initializer. This could be enhanced with an improved memory
  // abstraction to treat each element individually.
  void visit(SgAggregateInitializer *sgn)
  {
    LatticeType *res = getLattice(sgn);
    SgExpressionPtrList &inits = sgn->get_initializers()->get_expressions();
    if (inits.size() > 0) {
      res->copy(getLattice(inits[0]));
      modified = true;
      for (size_t i = 1; i < inits.size(); ++i)
        res->meetUpdate(getLattice(inits[i]));
    }
  }

  // XXX: This needs to be handled by an inter-procedural analysis
  void visit(SgConstructorInitializer *sgn)
  { }

  // XXX: I don't even know what this is - Phil
  void visit(SgDesignatedInitializer *sgn)
  { }

  void visit(SgInitializedName *initName)
  {
    LatticeType* varLat = getLattice(initName);

    if(varLat) {
      LatticeType* initLat = getLattice(initName->get_initializer());
      // If there was no initializer, leave this in its default 'bottom' state
      if(initLat) {
        varLat->copy(initLat);
        modified = true;
      }
    }
  }

  void visit(SgBinaryOp *sgn) {
    LatticeType *lhs, *rhs, *res;
    getLattices(sgn, lhs, rhs, res);
    if (res) {
      res->copy(lhs);
      res->meetUpdate(rhs);
      modified = true;
    }
  }

  void visit(SgCompoundAssignOp *sgn) {
    LatticeType *lhs, *rhs, *res;
    getLattices(sgn, lhs, rhs, res);
    if (lhs)
      updateModified(lhs->meetUpdate(rhs));
    // Liveness of the result implies liveness of LHS
    if (res) {
      res->copy(lhs);
      modified = true;
    }
  }

  void visit(SgCommaOpExp *sgn)
  {
    LatticeType *lhsLat, *rhsLat, *resLat;
    getLattices(sgn, lhsLat, rhsLat, resLat);

    if (resLat) {
      resLat->copy(rhsLat);
      modified = true;
    }
  }

  void visit(SgConditionalExp *sgn)
  {
    LatticeType *condLat = getLattice(sgn->get_conditional_exp()),
                *trueLat = getLattice(sgn->get_true_exp()),
                *falseLat = getLattice(sgn->get_false_exp()),
                *resLat = getLattice(sgn);

    // Liveness of the result implies liveness of the input expressions
    if (resLat) {
      resLat->copy(condLat);
      resLat->meetUpdate(trueLat);
      resLat->meetUpdate(falseLat);
      modified = true;
    }
  }

  void visit(SgScopeOp *)
  {
    // Documentation says this is no longer used, so explicitly fail if we see it
    ROSE_ABORT();
  }

  void visit(SgBitComplementOp *sgn)
  {
    LatticeType *res = getLattice(sgn);
    if (res) {
      res->copy(getLattice(sgn->get_operand()));
      modified = true;
    }
  }
};

#endif
#endif