Program Listing for File virtualCFG.h

Program Listing for File virtualCFG.h#

↰ Return to documentation for file (src/frontend/SageIII/virtualCFG/virtualCFG.h)

#ifndef VIRTUAL_CFG_H
#define VIRTUAL_CFG_H

#include <string>
#include <vector>
#include <assert.h>
#include "rosedll.h"


class SgNode;
class SgExpression;
class SgInitializedName;
class SgLabelSymbol;
class SgLabelRefExp;
class SgStatement;

#ifndef _MSC_VER
SgStatement* isSgStatement(SgNode* node);
const SgStatement* isSgStatement(const SgNode* node);
SgExpression* isSgExpression(SgNode* node);
const SgExpression* isSgExpression(const SgNode* node);
SgInitializedName* isSgInitializedName(SgNode* node);
const SgInitializedName* isSgInitializedName(const SgNode* node);
#endif

// DQ (9/1/2012): Debugging code to trace haskell_port error.
extern int abcd;

namespace VirtualCFG {

// DQ (9/1/2012): Debugging code to trace haskell_port error.
extern int efgh;

  class CFGEdge;

  enum EdgeConditionKind
  {
    eckUnconditional,
    eckTrue,
    eckFalse,
    eckCaseLabel,
    eckDefault,
    eckDoConditionPassed,
    eckDoConditionFailed,
    eckForallIndicesInRange,
    eckForallIndicesNotInRange,
    eckComputedGotoCaseLabel,
    eckArithmeticIfLess,
    eckArithmeticIfEqual,
    eckArithmeticIfGreater,
    eckInterprocedural,

 // DQ (1/19/2018): Allow an error value to use for debugging.
    eckError
  };

  class ROSE_DLL_API CFGNode {
    SgNode* node; // Must be either a SgStatement, SgExpression, or SgInitializedName (FIXME: change this to just SgLocatedNode if SgInitializedName becomes a subclass of that)

    unsigned int index;

    public:
    CFGNode(): node(0), index(0) {}
    CFGNode(SgNode* node, unsigned int index = 0);

    std::string toString() const;
    std::string toStringForDebugging() const;
    std::string id() const;
    SgNode* getNode() const {return node;}
    unsigned int getIndex() const {return index;}
    std::vector<CFGEdge> outEdges() const;
    std::vector<CFGEdge> inEdges() const;
    bool isInteresting() const;
    bool operator==(const CFGNode& o) const {return node == o.node && index == o.index;}
    bool operator!=(const CFGNode& o) const {return !(*this == o);}
    bool operator<(const CFGNode& o) const {return node < o.node || (node == o.node && index < o.index);}
  }; // end class CFGNode

  class ROSE_DLL_API CFGEdge {
    CFGNode src, tgt;
    public:
    CFGEdge(CFGNode src, CFGNode tgt): src(src), tgt(tgt) { assert(src.getNode() != NULL && tgt.getNode() != NULL); }

    CFGEdge() {}

    std::string toString() const;
    std::string toStringForDebugging() const;
    std::string id() const;
    CFGNode source() const {return src;}
    CFGNode target() const {return tgt;}
    EdgeConditionKind condition() const;
    SgExpression* caseLabel() const;
    unsigned int computedGotoCaseIndex() const;
    SgExpression* conditionBasedOn() const;
    std::vector<SgInitializedName*> scopesBeingExited() const;
    std::vector<SgInitializedName*> scopesBeingEntered() const;
    bool operator==(const CFGEdge& o) const {return src == o.src && tgt == o.tgt;}
    bool operator!=(const CFGEdge& o) const {return src != o.src || tgt != o.tgt;}

    bool operator<(const CFGEdge& o) const {return src < o.src || (src == o.src && tgt < o.tgt);}

  }; // end CFGEdge

  class CFGPath {
    std::vector<CFGEdge> edges;
    public:
 // DQ (8/28/2006): This constructor causes a bug to be brought out in ROSE
 // (in compiling this file using ROSE) see test2006_124.C for a smaller example.
    CFGPath(CFGEdge e): edges(1, e) {}
    // Merge two CFG paths
    CFGPath(const CFGPath& a, const CFGPath& b): edges(a.edges) {
      assert (!a.edges.empty());
      assert (!b.edges.empty());
      assert (a.edges.back().target() == b.edges.front().source());
      edges.insert(edges.end(),b.edges.begin(),b.edges.end());
    }

    //George Vulov 12/1/2010: We need a default constructor
    CFGPath()
    {
    }

    std::string toString() const;
    std::string toStringForDebugging() const;
    std::string id() const;
    // Get the head CFG node of the path
    CFGNode source() const {assert (!edges.empty()); return edges.front().source();}
    // Get the tail CFG node of the path
    CFGNode target() const {assert (!edges.empty()); return edges.back().target();}
    //Return the first non-unconditional edge's condition
    EdgeConditionKind condition() const {
      for (unsigned int i = 0; i < edges.size(); ++i) {
        EdgeConditionKind kind = edges[i].condition();
        if (kind != eckUnconditional) return kind;
      }
      return eckUnconditional;
    }
    // Return the case label of its first edge representing a case
    SgExpression* caseLabel() const {
      for (unsigned int i = 0; i < edges.size(); ++i) {
          SgExpression* label = edges[i].caseLabel();
          if (label != NULL) return label;
        }
      return NULL;
    }
    SgExpression* conditionBasedOn() const {
      for (unsigned int i = 0; i < edges.size(); ++i) {
          SgExpression* base = edges[i].conditionBasedOn();
          if (base != NULL) return base;
      }
      return NULL;
    }
    std::vector<SgInitializedName*> scopesBeingExited() const {
      std::vector<SgInitializedName*> result;
      for (unsigned int i = 0; i < edges.size(); ++i) {
        std::vector<SgInitializedName*> s_i = edges[i].scopesBeingExited();
        result.insert(result.end(), s_i.begin(), s_i.end());
      }
      return result;
    }
    std::vector<SgInitializedName*> scopesBeingEntered() const {
      std::vector<SgInitializedName*> result;
      for (unsigned int i = 0; i < edges.size(); ++i) {
        std::vector<SgInitializedName*> s_i = edges[i].scopesBeingEntered();
        result.insert(result.end(), s_i.begin(), s_i.end());
      }
      return result;
    }
    bool operator==(const CFGPath& o) const {return edges == o.edges;}
    bool operator!=(const CFGPath& o) const {return edges != o.edges;}

    bool operator<(const CFGPath& o) const {
      if (edges.size() != o.edges.size()) {
        return edges.size() < o.edges.size();
      }
      for (unsigned int i = 0; i < edges.size(); ++i) {
        if (edges[i] != o.edges[i]) {
          return edges[i] < o.edges[i];
        }
      }
      return false;
    }

        const std::vector<CFGEdge>& getEdges() const
        {
                return edges;
        }
  }; // end CFGPath

  inline CFGPath mergePaths(const CFGPath& hd, const CFGPath& tl) {
    // Assumes the edges don't do anything too complicated with scopes
    return CFGPath(hd, tl);
  }

  inline CFGPath mergePathsReversed(const CFGPath& tl, const CFGPath& hd) {
    return mergePaths(hd, tl);
  }

  inline CFGNode cfgBeginningOfConstruct(SgNode* c) {
    return CFGNode(c, 0);
  }

  unsigned int cfgIndexForEndWrapper(SgNode* n);

  inline CFGNode cfgEndOfConstruct(SgNode* c) {
    return CFGNode(c, cfgIndexForEndWrapper(c));
  }

  inline CFGNode makeCfg(SgNode* start) {
    return cfgBeginningOfConstruct(start);
  }

  class InterestingEdge;

  class InterestingNode {
    CFGNode n;

    public:
    InterestingNode(CFGNode n): n(n) {}
    std::string toString() const {return n.toString();}
    std::string toStringForDebugging() const {return n.toStringForDebugging();}
    std::string id() const {return n.id();}
    SgNode* getNode() const {return n.getNode();}
    const CFGNode& toNode() const { return n; }
    unsigned int getIndex() const {return n.getIndex();}
    std::vector<InterestingEdge> outEdges() const;
    std::vector<InterestingEdge> inEdges() const;
    bool isInteresting() const {return true;}
    bool operator==(const InterestingNode& o) const {return n == o.n;}
    bool operator!=(const InterestingNode& o) const {return !(*this == o);}
    bool operator<(const InterestingNode& o) const {return n < o.n;}
  };

  class InterestingEdge {
    CFGPath p;

    public:
    InterestingEdge(CFGPath p): p(p) {}
    std::string toString() const {return p.toString();}
    std::string toStringForDebugging() const {return p.toStringForDebugging();}
    std::string id() const {return p.id();}
    InterestingNode source() const {return InterestingNode(p.source());}
    InterestingNode target() const {return InterestingNode(p.target());}
    EdgeConditionKind condition() const {return p.condition();}
    SgExpression* caseLabel() const {return p.caseLabel();}
    SgExpression* conditionBasedOn() const {return p.conditionBasedOn();}
    std::vector<SgInitializedName*> scopesBeingExited() const {return p.scopesBeingExited();}
    std::vector<SgInitializedName*> scopesBeingEntered() const {return p.scopesBeingEntered();}
    bool operator==(const InterestingEdge& o) const {return p == o.p;}
    bool operator!=(const InterestingEdge& o) const {return p != o.p;}
    bool operator<(const InterestingEdge& o) const {return p < o.p;}
  };

  inline InterestingNode makeInterestingCfg(SgNode* start) {
    // Returns CFG node for just before start
    return InterestingNode(cfgBeginningOfConstruct(start));
  }

  CFGNode getCFGTargetOfFortranLabelSymbol(SgLabelSymbol* sym);
  CFGNode getCFGTargetOfFortranLabelRef(SgLabelRefExp* lRef);

  template <class Node1T, class Node2T, class EdgeT>
  void makeEdge(Node1T from, Node2T to, std::vector<EdgeT>& result);

} // end namespace VirtualCFG

#define SGFUNCTIONCALLEXP_INTERPROCEDURAL_INDEX 2
#define SGCONSTRUCTORINITIALIZER_INTERPROCEDURAL_INDEX 1
#define SGFUNCTIONDEFINITION_INTERPROCEDURAL_INDEX 2

#define SGFUNCTIONCALLEXP_INTERPROCEDURAL_INDEX 2
#define SGCONSTRUCTORINITIALIZER_INTERPROCEDURAL_INDEX 1
#define SGFUNCTIONDEFINITION_INTERPROCEDURAL_INDEX 2

template <class NodeT1, class NodeT2, class EdgeT>
void makeEdge(NodeT1 from, NodeT2 to, std::vector<EdgeT>& result);

#endif // VIRTUAL_CFG_H