Пример #1
0
/*
  The classical use/def isnt quite enough here. There are two unusual
  issues:
   - the ref/non-ref issue.
     An assignment to a var which is referenced doesnt end its
     lifetime. In fact it could just be a "use" of the var. But it
     also counts as a def.
   - the destructor issue.
     variables which might need to be destroyed later are technically
     alive, but dont interfere with any other variables in the same state.
     They /do/ interfere with any truly "live" variables, however.
     These are "dying".

   So we end up defining, use, kill, def and dying.

  use : a read of the variable, an ordinary assignment if it could
        be referenced

  kill : an unset, a ref assignment, or, for non referenced vars, any assignment

  def : ref or normal assignment

  dying : a variable whose destructor is (partially/locally) anticipated.
*/
void LiveDict::updateAccess(ExpressionPtr e) {
  int cls = e->getExprClass();
  if (cls & Expression::Store) {
    /*
      Handled when we see the lhs
    */
    return;
  }

  int eid = e->getCanonID();
  int context = e->getContext();
  bool unset = false;
  bool store = false;
  if (context & Expression::LValue && context & Expression::UnsetContext) {
    unset = true;
  } else if (context & Expression::AssignmentLHS) {
    store = true;
  }

  if (e->is(Expression::KindOfSimpleVariable)) {
    SimpleVariablePtr sv(static_pointer_cast<SimpleVariable>(e));
    bool use = false, kill = false, def = false;
    Symbol *sym = sv->getSymbol();
    bool isReferenced =
      e->isReferencedValid() ?
        e->isReferenced() :
        sym && sym->isReferenced();
    bool isNeeded =
      e->isNeededValid() ?
        e->isNeeded() :
        sym && sym->isNeeded();
    if (unset) {
      kill = true;
    } else if (store) {
      if (context & Expression::RefAssignmentLHS ||
          (!m_am.hasWildRefs() && !isReferenced)) {
        kill = true;
      }
      def = true;
    } else if ((context & Expression::Declaration) == Expression::Declaration) {
      // a global declaration
      def = kill = true;
    } else if (context & (Expression::LValue|
                          Expression::RefValue|
                          Expression::DeepReference|
                          Expression::UnsetContext|
                          Expression::OprLValue)) {
      use = def = true;
    } else {
      use = true;
    }
    if (kill && (!sym || isNeeded || isReferenced) &&
        !BitOps::get_bit(eid, m_altered) &&
        !BitOps::get_bit(eid, m_available)) {
      BitOps::set_bit(eid, m_dying, true);
    }
    if (use &&
        !BitOps::get_bit(eid, m_altered) &&
        !BitOps::get_bit(eid, m_available)) {
      BitOps::set_bit(eid, m_anticipated, true);
      e->setAnticipated();
    }
    if (kill) {
      BitOps::set_bit(eid, m_altered, true);
      BitOps::set_bit(eid, m_available, def);
    } else if (def) {
      BitOps::set_bit(eid, m_available, true);
    }

    if (!m_am.couldBeAliased(sv)) {
      return;
    }
  } else if (!e->is(Expression::KindOfDynamicVariable) &&
             (unset || (context & Expression::RefAssignmentLHS))) {
    // An unset, or a reference assignment to anything other
    // than a simple or dynamic variable can never affect a simple
    // variable (outside of pseudoMain).
    return;
  }

  if (store || cls & (Expression::Load|Expression::Call)) {
    bool mod =
      store ||
      (cls & Expression::Load &&
       e->getContext() & (Expression::LValue|
                          Expression::RefValue|
                          Expression::UnsetContext|
                          Expression::DeepReference|
                          Expression::OprLValue));

    ExpressionPtr cur = m_refs, prev;
    bool isLoad;
    int depth = 0, effects = 0;
    while (cur) {
      ExpressionPtr next = cur->getCanonLVal();
      int cid = cur->getCanonID();
      if (cid != eid &&
          m_am.checkAnyInterf(e, cur, isLoad, depth, effects) !=
          AliasManager::DisjointAccess) {
        if (mod) {
          BitOps::set_bit(cid, m_available, true);
        }
        if (!BitOps::get_bit(cid, m_altered) &&
            !BitOps::get_bit(cid, m_available)) {
          BitOps::set_bit(cid, m_anticipated, true);
        }
        if (!prev) {
          m_refs = next;
        } else {
          prev->setCanonPtr(next);
        }
      } else {
        prev = cur;
      }
      cur = next;
    }
  }
}
Пример #2
0
void ExprDict::updateAccess(ExpressionPtr e) {
  int cls = e->getExprClass();
  int eid = e->getCanonID();
  e->clearAnticipated();
  e->clearAvailable();

  // bail on non-canonical expressions
  if (!isCanonicalStructure(eid)) {
    // but record we saw a type assertion belonging to this block
    m_avlTypeAsserts.push_back(eid);
    return;
  }

  if (m_anticipated &&
      (cls & Expression::Update ?
       !BitOps::get_bit(eid, m_altered) : !e->getLocalEffects())) {
    /*
      Anticipated can be computed bottom up as we go. But note that we
      only know altered for Load/Store expressions.
    */
    int i = e->getKidCount();
    while (true) {
      if (!i--) {
        e->setAnticipated();
        if (!e->hasContext(Expression::AssignmentLHS)) {
          setStructureOps(eid, m_anticipated, true);
        }
        break;
      }
      if (ExpressionPtr k = e->getNthExpr(i)) {
        if (!isCanonicalStructure(k->getCanonID())) continue;
        if (!k->isAnticipated()) {
          break;
        }
      }
    }
  }

  if (m_available) {
    /*
      Available has to be computed optimistically, because we dont yet
      know what is going to be altered between here and the end of the block
      So keep a list of the potentially-available accesses (avlAccess), and
      for each id, the last potentially-available expression (avlExpr).
      For each modifying expression that we process, we remove expressions
      from avlAccess, and at the end, we build up the available expressions
      bottom up.
    */
    if ((cls & (Expression::Store|Expression::Call)) ||
        (cls & Expression::Load &&
         e->getContext() & (Expression::LValue|
                            Expression::RefValue|
                            Expression::UnsetContext|
                            Expression::DeepReference))) {
      bool isLoad;
      int depth = 0, effects = 0;
      for (int i = 0, n = m_avlAccess.size(); i < n; ) {
        ExpressionRawPtr a = m_avlAccess[i];
        if (m_am.checkAnyInterf(e, a, isLoad, depth, effects) !=
            AliasManager::DisjointAccess) {
          int aid = a->getCanonID();
          assert(isCanonicalStructure(aid));
          if (eid != aid || cls == Expression::Load) {
            BitOps::set_bit(aid, m_altered, true);
          }
          if (!(cls & Expression::Store) ||
              a != e->getStoreVariable()) {
            a->clearAvailable();
            m_avlAccess[i] = m_avlAccess[--n];
            m_avlAccess.resize(n);
            continue;
          }
        }
        i++;
      }
    }
    if (cls & Expression::Update ||
        !e->getContainedEffects()) {
      int i = e->getKidCount();
      while (true) {
        if (!i--) {
          e->setAvailable();
          if (cls & Expression::Update) {
            m_avlAccess.push_back(e);
          }
          m_avlExpr[eid] = e;
          break;
        }
        if (ExpressionPtr k = e->getNthExpr(i)) {
          if (!isCanonicalStructure(k->getCanonID())) continue;
          if (!k->isAvailable()) {
            break;
          }
        }
      }
    }
  }

  if ((cls & (Expression::Store|Expression::Call)) ||
      (cls & Expression::Load &&
       e->getContext() & (Expression::LValue|
                          Expression::RefValue|
                          Expression::UnsetContext|
                          Expression::DeepReference))) {
    ExpressionPtr cur = m_active, prev;
    bool isLoad;
    int depth = 0, effects = 0;
    while (cur) {
      ExpressionPtr next = cur->getCanonLVal();
      int cid = cur->getCanonID();
      assert(isCanonicalStructure(cid));
      if ((cid != eid || cls == Expression::Load) &&
          (BitOps::get_bit(cid, m_altered) ||
           m_am.checkAnyInterf(e, cur, isLoad, depth, effects) !=
           AliasManager::DisjointAccess)) {
        BitOps::set_bit(cid, m_altered, true);
        if (!prev) {
          m_active = next;
        } else {
          prev->setCanonPtr(next);
        }
      } else {
        prev = cur;
      }
      cur = next;
    }
  }
}