// 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; }
/* * 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; } } } } } }
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)) {