Ejemplo n.º 1
0
  private void buildCDG() {
    if (this.procSet == null) {
      procSet = cfgMap.keySet();
    }
    for (Procedure proc : procSet) {
      System.out.println(
          "Building Control Dependence Graph for Proc: "
              + proc.getSymbolName()
              + ", time: "
              + (new Date()).toString());
      CFGraph cfg = cfgMap.get(proc);
      // reverse the control flow graph
      DFAGraph reversedCFG = SlicingTools.reverseCFGraph(cfg);
      // add additional start node for connecting multiple return node
      // single return node works fine with this.
      DFANode dummyEntryNode = new DFANode();
      List<DFANode> entryList = reversedCFG.getEntryNodes();
      reversedCFG.addNode(dummyEntryNode);
      for (DFANode entry : entryList) {
        dummyEntryNode.addSucc(entry);
        reversedCFG.addEdge(dummyEntryNode, entry);
      }
      //
      ArrayList<DFANode> nodeList = new ArrayList<DFANode>();

      // extract dominator
      BitSet[] dominator = SlicingTools.getDominators(reversedCFG, nodeList);
      int nodeSize = nodeList.size();
      DFANode[] nodeArray = new DFANode[nodeSize];
      nodeList.toArray(nodeArray);
      Set<Integer> entryIdxSet = SlicingTools.getEntryIdxSet(reversedCFG, nodeList);
      List<DFANode> entryNodeList = reversedCFG.getEntryNodes();

      // print dominator
      //            SlicingTools.printDominator(dominator, nodeArray, proc);

      // extract immediate dominator
      BitSet[] immediateDom =
          SlicingTools.getImmediateDominator(dominator, entryIdxSet, entryNodeList, nodeArray);

      // print immediate dominator
      //            SlicingTools.printDominator(immediateDom, nodeArray, proc);

      // build Post Dominance Tree
      if (PrintTools.getVerbosity() > 1)
        System.out.println(
            "############# build Post Dominace Tree (Graph) for "
                + proc.getSymbolName()
                + " ###########");
      DFAGraph postDomTree =
          SlicingTools.buildImmediateDominanceTree(reversedCFG, immediateDom, nodeArray, nodeList);

      // print post dominance tree
      //            SlicingTools.printDominanceTree(postDomTree, proc);

      // extract edges m --> n such that n does not postdominate(dominate in reversed) m
      // CFGEdge's head and tail are on reversed cfg.
      // can get PDTree node by getData("pdtNode")
      Set<CFGEdge> nonPDEdgeSet = extractNonPostdominatingEdges(reversedCFG, postDomTree, proc);

      List<DFANode> pdtNodeList = new ArrayList<DFANode>();
      Iterator<DFANode> pdtIter = postDomTree.iterator();
      int idx = 0;
      while (pdtIter.hasNext()) {
        DFANode node = pdtIter.next();
        pdtNodeList.add(node);
        //            	System.out.println("[" + idx++ + "]" +
        // ((DFANode)((DFANode)node.getData("revNode")).getData("cfgNode")).getData("ir"));
      }
      for (CFGEdge edge : nonPDEdgeSet) {
        // find lowest common ancestor of m and n (result: l)
        DFANode commonAncestor = getLowestCommonAncestor(edge, postDomTree, pdtNodeList);

        // all nodes in N on the path from l to n in the postdominance tree except l
        // are control dependent on m
        Set<DFANode> cdSet = getControlDependentSet(edge, commonAncestor);
        DFANode controllingNode = edge.tail.getData("cfgNode");
        // TODO: handled some corner cases this way but should be fixed later
        // Some wrong controlling nodes are inserted, maybe due to the problem of control flow graph
        if ((controllingNode.getData("ir") instanceof Expression) == false
            && (controllingNode.getData("ir") instanceof SwitchStatement) == false) {
          // filter if a statement is a controlling node (wrong)
          continue;
          // throw new RuntimeException("controllingNode is not expression: " +
          // controllingNode.getData("ir"));
        } else {
          if (controllingNode.getData("ir") instanceof Expression) {
            // filter a stepping expression in the for loop is a controlling node (wrong)
            Expression exp = controllingNode.getData("ir");
            Traversable parent = exp.getParent();
            if (parent instanceof ForLoop) {
              ForLoop fLoop = (ForLoop) parent;
              if (exp.equals(fLoop.getStep())) {
                continue;
              }
            }
          } else if (controllingNode.getData("ir") instanceof SwitchStatement) {

          } else {
            throw new RuntimeException(
                "controllingNode is unexpected type: " + controllingNode.getData("ir"));
          }
        }
        //
        for (DFANode node : cdSet) {
          DFANode revNode = node.getData("revNode");
          if (revNode == null) {
            continue;
          }
          DFANode controlledNode = revNode.getData("cfgNode");
          controlledNode.putData("controlNode", controllingNode);
          if (PrintTools.getVerbosity() > 1)
            System.out.println(
                "[Node]"
                    + controlledNode.getData("ir")
                    + " == control dependent on == [Node]"
                    + controllingNode.getData("ir"));
        }
      }
      // check inter-dependent node
      // remove the controlling node for coming first node toward coming later node
      Iterator<DFANode> cfgIter = cfg.iterator();
      while (cfgIter.hasNext()) {
        DFANode n = cfgIter.next();
        DFANode cdNode = n.getData("controlNode");
        if (cdNode == null) {
          continue;
        }
        DFANode cdCDNode = cdNode.getData("controlNode");
        if (n.equals(cdCDNode)) {
          n.removeData("controlNode");
          //            		throw new RuntimeException("My contol node is dependent on me. my: " + n +
          // ",\n cd: " + cdNode);
        }
      }
      // check a cyclic dependent node and remove it
      cfgIter = cfg.iterator();
      while (cfgIter.hasNext()) {
        DFANode n = cfgIter.next();
        DFANode cdNode = n.getData("controlNode");
        while (cdNode != null) {
          if (cdNode.equals(n)) {
            cdNode.removeData("controlNode");
            break;
            //            			throw new RuntimeException("Cyclic dependency was found!!");
          } else {
            cdNode = cdNode.getData("controlNode");
          }
        }
      }
    }
  }