Beispiel #1
0
// Find a definition of the condition variable in the body of the loop.
// Returns null if no such expression is found.
SymExpr* WhileStmt::getWhileCondDef(VarSymbol* condSym)
{
  std::vector<SymExpr*> symExprs;
  SymExpr*              condDef = NULL;

  collectSymExprs(this, symExprs);

  for_vector(SymExpr, se, symExprs)
  {
    if (se->symbol() == condSym)
    {
      if (se == mCondExpr)
      {
        // The reference is the condition expression - not interesting.
      }

      else if (condDef)
      {
        // There are >1 references to condSym. Let us notify ourselves
        // so we can adjust the code to handle this case as well.
        // If desired, disable this assert - the only outcome of that may be
        // that the warning will not be issued in some cases.
        INT_ASSERT(false);
      }

      else
      {
        // This is what we are looking for.
        condDef = se;
      }
    }
  }

  return condDef;
}
Beispiel #2
0
/*
 * Returns true if `e` has no side effects. Checked side effects are:
 *  - Read/write to a global
 *  - Is/contains essential primitive
 *  - If it's a call to functions with ref arguments
 *  - If the LHS of a PRIM_MOVE appears in the exprToMove
 *
 * For now, this is a very conservative analysis. A more precise analysis
 * could distinguish between reads and writes to memory and to take into
 * account alias analysis.
 */
bool SafeExprAnalysis::exprHasNoSideEffects(Expr* e, Expr* exprToMove) {
  if(safeExprCache.count(e) > 0) {
    return safeExprCache[e];
  }
  if(CallExpr* ce = toCallExpr(e)) {
    if(!ce->isPrimitive()) {
      FnSymbol* fnSym = ce->theFnSymbol();
      const bool cachedSafeFn = safeFnCache.count(fnSym);
      if(!cachedSafeFn) {
        const bool retval = fnHasNoSideEffects(fnSym);
        safeFnCache[fnSym] = retval;
        return retval;
      }
      return safeFnCache[fnSym];
    }
    else {
      //primitive
      if(! isSafePrimitive(ce)){
        safeExprCache[e] = false;
        return false;
      }
      else if (exprToMove != NULL) {
        //
        // Exposed by AST pattern like this:
        //          |---|------- `exprToMove`
        // (move T (+ A B))
        // (move A B) -------- `ce`
        // (move B T)
        //
        // Without this check could turn into:
        //
        // (move A B)
        // (move B (+ A B))
        //
        // Which is incorrect.
        //
        if (ce->isPrimitive(PRIM_MOVE)) {
          INT_ASSERT(isSymExpr(ce->get(1)));
          std::vector<SymExpr*> syms;
          collectSymExprs(exprToMove, syms);
          for_vector(SymExpr, s, syms) {
            if (s->symbol() == toSymExpr(ce->get(1))->symbol()) {
              safeExprCache[e] = false;
              return false;
            }
          }
        }
      }
    }
  }
Beispiel #3
0
 forv_Vec(FnSymbol, fn, gFnSymbols) {
   if (fn->isIterator()) {
     if (fn->retTag == RET_TYPE)
       USR_FATAL_CONT(fn, "iterators may not yield or return types");
     if (fn->retTag == RET_PARAM)
       USR_FATAL_CONT(fn, "iterators may not yield or return parameters");
   } else if (fn->hasFlag(FLAG_CONSTRUCTOR) &&
              !fn->hasFlag(FLAG_DEFAULT_CONSTRUCTOR)) {
     if (fn->retExprType)
       USR_FATAL_CONT(fn, "constructors may not declare a return type");
     for_formals(formal, fn) {
       std::vector<SymExpr*> symExprs;
       collectSymExprs(formal, symExprs);
       for_vector(SymExpr, se, symExprs) {
         if (se->var == fn->_this) {
           USR_FATAL_CONT(se, "invalid access of class member in constructor header");
           break;
         }
       }
     }
   } else if (fn->hasFlag(FLAG_DESTRUCTOR)) {