BlockStmt* DoWhileStmt::build(Expr* cond, BlockStmt* body) { VarSymbol* condVar = newTemp(); CallExpr* condTest = new CallExpr("_cond_test", cond); LabelSymbol* continueLabel = new LabelSymbol("_continueLabel"); LabelSymbol* breakLabel = new LabelSymbol("_breakLabel"); DoWhileStmt* loop = 0; BlockStmt* retval = new BlockStmt(); // make variables declared in the scope of the body visible to // expressions in the condition of a do..while block if (body->length() == 1 && toBlockStmt(body->body.only())) { body = toBlockStmt(body->body.only()); body->remove(); } body->insertAtTail(new DefExpr(continueLabel)); body->insertAtTail(new CallExpr(PRIM_MOVE, condVar, condTest->copy())); loop = new DoWhileStmt(condVar, body); loop->mContinueLabel = continueLabel; loop->mBreakLabel = breakLabel; retval->insertAtTail(new DefExpr(condVar)); retval->insertAtTail(loop); retval->insertAtTail(new DefExpr(breakLabel)); return retval; }
// Is 'sym' an index var in the coforall loop // for which the 'fn' was created? static bool isCorrespCoforallIndex(FnSymbol* fn, Symbol* sym) { if (!sym->hasFlag(FLAG_COFORALL_INDEX_VAR)) return false; // If 'sym' is for the loop that 'call' belongs to, // they both come from the same BlockStmt. BlockStmt* block = toBlockStmt(fn->defPoint->parentExpr); INT_ASSERT(block); // I conjecture that if 'sym' comes from a different block, // it ain't going to be from that loop. if (sym->defPoint->parentExpr != block) return false; // FYI: presently, for a 'coforall', the enclosing block is a for loop. INT_ASSERT(block->isForLoop()); // We could verify that 'sym' is defined via a 'move' // from the _indexOfInterest variable referenced by the SymExpr // block->blockInfoGet()->get(1). (It's a move from a tuple component // of _indexOfInterest, for zippered coforall loops.) // return true; }
static bool inLocalBlock(CallExpr *call) { for (Expr* parent = call->parentExpr; parent; parent = parent->parentExpr) { if (BlockStmt* blk = toBlockStmt(parent)) { if (blk->blockInfo && blk->blockInfo->isPrimitive(PRIM_BLOCK_LOCAL)) return true; } } return false; }
void Expr::prettyPrint(std::ostream *o) { if (BlockStmt *stmt = toBlockStmt(this)) printf("blockstmt %s", stmt->userLabel); else if (CondStmt *stmt = toCondStmt(this)) printf("condstmt %s", stmt->condExpr->parentSymbol->name); else if (GotoStmt *stmt = toGotoStmt(this)) printf("gotostmt %s", stmt->label->parentSymbol->name); printf("Oh no! This method hasn't been defined for this class!\n"); }
static bool inLocalBlock(CallExpr *call) { for (Expr* parent = call->parentExpr; parent; parent = parent->parentExpr) { if (BlockStmt* blk = toBlockStmt(parent)) { // NOAKES 2014/11/25 Transitional. Do not trip over blockInfoGet for a Loop if (blk->isLoopStmt() == true) ; else if (blk->blockInfoGet() && blk->blockInfoGet()->isPrimitive(PRIM_BLOCK_LOCAL)) return true; } } return false; }
// It is probably an error if there is no such BlockStmt. // Currently return NULL. Consider throwing an internal error in the future. BlockStmt* Expr::getScopeBlock() { Expr* expr = this->parentExpr; BlockStmt* retval = NULL; while (expr != NULL && retval == NULL) { BlockStmt* block = toBlockStmt(expr); if (block != NULL && (block->blockTag & BLOCK_SCOPELESS) == 0) retval = block; else expr = expr->parentExpr; } return retval; }
// Find the block stmt that encloses the target of this gotoStmt static BlockStmt* findBlockForTarget(GotoStmt* stmt) { BlockStmt* retval = NULL; if (stmt != NULL && stmt->isGotoReturn() == false) { SymExpr* labelSymExpr = toSymExpr(stmt->label); Expr* ptr = labelSymExpr->symbol()->defPoint; while (ptr != NULL && isBlockStmt(ptr) == false) { ptr = ptr->parentExpr; } retval = toBlockStmt(ptr); INT_ASSERT(retval); } return retval; }
bool Expr::isModuleDefinition() { bool retval = false; #if 1 // MDN 2014/07/02 // Leaving the old definition here until the scope-less BlockStmt // change is stable. if (BlockStmt* block = toBlockStmt(this)) if (block->length() == 1) if (DefExpr* def = toDefExpr(block->body.only())) if (isModuleSymbol(def->sym)) retval = true; #endif if (DefExpr* def = toDefExpr(this)) if (isModuleSymbol(def->sym)) retval = true; return retval; }
// Read one statement Expr* IpeReader::readStmt() { int lexerStatus = 100; int parserStatus = YYPUSH_MORE; Expr* retval = 0; mContext.latestComment = NULL; while (lexerStatus != 0 && parserStatus == YYPUSH_MORE && retval == 0) { YYSTYPE yylval; mContext.generatedStmt = NULL; lexerStatus = yylex(&yylval, &mYYlloc, mContext.scanner); if (lexerStatus >= 0) parserStatus = yypush_parse(mParser, lexerStatus, &yylval, &mYYlloc, &mContext); else if (lexerStatus == YYLEX_BLOCK_COMMENT) mContext.latestComment = yylval.pch; if (mContext.generatedStmt != 0) { if (BlockStmt* bs = toBlockStmt(mContext.generatedStmt)) { if (Expr* expr = bs->body.last()) retval = expr; } } } if (retval != 0) insert_help(retval, NULL, NULL); return retval; }
static void list_ast(BaseAST* ast, BaseAST* parentAst = NULL, int indent = 0) { bool do_list_line = false; bool is_C_loop = false; const char* block_explain = NULL; if (Expr* expr = toExpr(ast)) { do_list_line = !parentAst || list_line(expr, parentAst); if (do_list_line) { printf("%-7d ", expr->id); for (int i = 0; i < indent; i++) printf(" "); } if (GotoStmt* e = toGotoStmt(ast)) { printf("goto "); if (SymExpr* label = toSymExpr(e->label)) { if (label->var != gNil) { list_ast(e->label, ast, indent+1); } } else { list_ast(e->label, ast, indent+1); } } else if (toBlockStmt(ast)) { block_explain = block_explanation(ast, parentAst); printf("%s{\n", block_explain); } else if (toCondStmt(ast)) { printf("if "); } else if (CallExpr* e = toCallExpr(expr)) { if (e->isPrimitive(PRIM_BLOCK_C_FOR_LOOP)) is_C_loop = true; if (e->primitive) printf("%s( ", e->primitive->name); else printf("call( "); } else if (NamedExpr* e = toNamedExpr(expr)) { printf("%s = ", e->name); } else if (toDefExpr(expr)) { printf("def "); } else if (SymExpr* e = toSymExpr(expr)) { list_sym(e->var, false); } else if (UnresolvedSymExpr* e = toUnresolvedSymExpr(expr)) { printf("%s ", e->unresolved); } } if (Symbol* sym = toSymbol(ast)) list_sym(sym); bool early_newline = toFnSymbol(ast) || toModuleSymbol(ast); if (early_newline || is_C_loop) printf("\n"); int new_indent = indent; if (isExpr(ast)) if (do_list_line) new_indent = indent+2; AST_CHILDREN_CALL(ast, list_ast, ast, new_indent); if (Expr* expr = toExpr(ast)) { CallExpr* parent_C_loop = NULL; if (CallExpr* call = toCallExpr(parentAst)) if (call->isPrimitive(PRIM_BLOCK_C_FOR_LOOP)) parent_C_loop = call; if (toCallExpr(expr)) { printf(") "); } if (toBlockStmt(ast)) { printf("%-7d ", expr->id); if (*block_explain) indent -= 2; for (int i = 0; i < indent; i++) printf(" "); if ((parent_C_loop && parent_C_loop->get(3) == expr) || *block_explain) printf("} "); else printf("}\n"); } else if (CondStmt* cond = toCondStmt(parentAst)) { if (cond->condExpr == expr) printf("\n"); } else if (!toCondStmt(expr) && do_list_line) { DefExpr* def = toDefExpr(expr); if (!(def && early_newline)) if (!parent_C_loop) printf("\n"); } } }
// Returns max local frame space to evaluate this expr int locationExpr(Expr* expr, IpeEnv* env) { int retval = 0; if (DefExpr* defExpr = toDefExpr(expr)) { VarSymbol* var = toVarSymbol(defExpr->sym); int delta = 8; // NOAKES Size of every type is currently 8 INT_ASSERT(var); env->locationSet(var); retval = delta; } else if (isCallExpr(expr) == true) retval = 0; else if (CondStmt* stmt = toCondStmt(expr)) { if (stmt->elseStmt == NULL) { retval = locationExpr(stmt->thenStmt, env); } else { int thenSize = locationExpr(stmt->thenStmt, env); int elseSize = locationExpr(stmt->elseStmt, env); retval = (thenSize > elseSize) ? thenSize : elseSize; } } else if (WhileDoStmt* stmt = toWhileDoStmt(expr)) { Expr* body = stmt->body.get(1); INT_ASSERT(stmt->body.length == 1); INT_ASSERT(isBlockStmt(body)); retval = locationExpr(body, env); } else if (BlockStmt* stmt = toBlockStmt(expr)) { IpeBlockStmt* ipeStmt = (IpeBlockStmt*) stmt; int maxFrame = 0; IpeEnv env(ipeStmt->scopeGet()); for (int i = 1; i <= ipeStmt->body.length; i++) { int localSize = locationExpr(ipeStmt->body.get(i), &env); if (localSize > maxFrame) maxFrame = localSize; } retval = maxFrame; } else { AstDumpToNode logger(stdout, 3); printf(" locationExpr(Expr*, IpeEnv* env) unsupported\n"); printf(" "); expr->accept(&logger); printf("\n\n"); env->describe(3); printf("\n\n"); INT_ASSERT(false); } return retval; }
static void list_ast(BaseAST* ast, BaseAST* parentAst = NULL, int indent = 0) { bool do_list_line = false; bool is_C_loop = false; const char* block_explain = NULL; if (Expr* expr = toExpr(ast)) { if (ForallStmt* pfs = toForallStmt(parentAst)) { if (expr == pfs->fRecIterIRdef) { printf("fRecIterIRdef"); } else if (expr == pfs->loopBody()) { if (pfs->numShadowVars() == 0) print_on_its_own_line(indent, "with() do\n"); else print_on_its_own_line(indent, "do\n", false); indent -= 2; } } do_list_line = !parentAst || list_line(expr, parentAst); if (do_list_line) { printf("%-7d ", expr->id); print_indent(indent); } if (const char* expl = forall_explanation_start(ast, parentAst)) printf("%s", expl); if (GotoStmt* e = toGotoStmt(ast)) { printf("goto "); if (SymExpr* label = toSymExpr(e->label)) { if (label->symbol() != gNil) { list_ast(e->label, ast, indent+1); } } else { list_ast(e->label, ast, indent+1); } } else if (toBlockStmt(ast)) { block_explain = block_explanation(ast, parentAst); const char* block_kind = ast->astTagAsString(); if (!strcmp(block_kind, "BlockStmt")) block_kind = ""; printf("%s{%s\n", block_explain, block_kind); } else if (toCondStmt(ast)) { printf("if "); } else if (toIfExpr(ast)) { printf("IfExpr "); } else if (toForallStmt(ast)) { printf("forall\n"); } else if (CallExpr* e = toCallExpr(expr)) { if (e->isPrimitive(PRIM_BLOCK_C_FOR_LOOP)) is_C_loop = true; if (e->primitive) printf("%s( ", e->primitive->name); else printf("call( "); } else if (ForallExpr* e = toForallExpr(expr)) { if (e->zippered) printf("zip "); printf("forall( "); } else if (NamedExpr* e = toNamedExpr(expr)) { printf("%s = ", e->name); } else if (toDefExpr(expr)) { Symbol* sym = toDefExpr(expr)->sym; if (sym->type != NULL) { printf("def %s ", sym->qualType().qualStr()); } else { printf("def "); } } else if (SymExpr* e = toSymExpr(expr)) { list_sym(e->symbol(), false); } else if (UnresolvedSymExpr* e = toUnresolvedSymExpr(expr)) { printf("%s ", e->unresolved); } else if (isUseStmt(expr)) { printf("use "); } } if (Symbol* sym = toSymbol(ast)) list_sym(sym); bool early_newline = toFnSymbol(ast) || toModuleSymbol(ast); if (early_newline || is_C_loop) printf("\n"); int new_indent = indent; if (isExpr(ast)) if (do_list_line) new_indent = indent+2; AST_CHILDREN_CALL(ast, list_ast, ast, new_indent); if (Expr* expr = toExpr(ast)) { CallExpr* parent_C_loop = NULL; if (CallExpr* call = toCallExpr(parentAst)) if (call->isPrimitive(PRIM_BLOCK_C_FOR_LOOP)) parent_C_loop = call; if (toCallExpr(expr)) { printf(") "); } if (toBlockStmt(ast)) { printf("%-7d ", expr->id); if (*block_explain) indent -= 2; print_indent(indent); if ((parent_C_loop && parent_C_loop->get(3) == expr) || *block_explain) printf("} "); else if (isDeferStmt(parentAst)) printf("}"); // newline is coming else printf("}\n"); if (isForallLoopBody(expr) && parentAst != NULL) { print_indent(indent); printf(" end forall %d", parentAst->id); } } else if (ForallExpr* e = toForallExpr(expr)) { if (e->cond) printf(") "); else printf("} "); } else if (UseStmt* use = toUseStmt(expr)) { if (!use->isPlainUse()) { if (use->hasExceptList()) { printf("except "); } else { printf("only "); } bool first = true; for_vector(const char, str, use->named) { if (first) { first = false; } else { printf(", "); } printf("%s", str); } for (std::map<const char*, const char*>::iterator it = use->renamed.begin(); it != use->renamed.end(); ++it) { if (first) { first = false; } else { printf(", "); } printf("%s as %s", it->second, it->first); } printf("\n"); } } else if (CondStmt* cond = toCondStmt(parentAst)) {
// Returns true if the symbol is read in the containing expression, // false otherwise. If the operand is used as an address, // that does not count as a 'read', so false is returned in that case. static bool isUse(SymExpr* se) { if (toGotoStmt(se->parentExpr)) return false; if (toCondStmt(se->parentExpr)) return true; if (toBlockStmt(se->parentExpr)) return true; if (isDefExpr(se->parentExpr)) return false; CallExpr* call = toCallExpr(se->parentExpr); if (FnSymbol* fn = call->resolvedFunction()) { // Skip the "base" symbol. if (se->symbol() == fn) return false; // A "normal" call. ArgSymbol* arg = actual_to_formal(se); if (arg->intent == INTENT_OUT || (arg->intent & INTENT_FLAG_REF)) return false; } else { INT_ASSERT(call->primitive); const bool isFirstActual = call->get(1) == se; switch(call->primitive->tag) { default: return true; case PRIM_MOVE: case PRIM_ASSIGN: case PRIM_ADD_ASSIGN: case PRIM_SUBTRACT_ASSIGN: case PRIM_MULT_ASSIGN: case PRIM_DIV_ASSIGN: case PRIM_MOD_ASSIGN: case PRIM_LSH_ASSIGN: case PRIM_RSH_ASSIGN: case PRIM_AND_ASSIGN: case PRIM_OR_ASSIGN: case PRIM_XOR_ASSIGN: if (isFirstActual) { return false; } return true; case PRIM_ADDR_OF: case PRIM_SET_REFERENCE: return false; // See Note #2. case PRIM_PRIVATE_BROADCAST: // The operand is used by name (it must be a manifest constant). // Thus it acts more like an address than a value. return false; case PRIM_CHPL_COMM_GET: case PRIM_CHPL_COMM_PUT: case PRIM_CHPL_COMM_ARRAY_GET: case PRIM_CHPL_COMM_ARRAY_PUT: case PRIM_CHPL_COMM_GET_STRD: case PRIM_CHPL_COMM_PUT_STRD: // ('comm_get/put' locAddr locale widePtr len) // The first and third operands are treated as addresses. // The second and fourth are values if (se == call->get(2) || se == call->get(4)) { return true; } return false; case PRIM_CHPL_COMM_REMOTE_PREFETCH: // comm prefetch locale widePtr len // second argument is an address // first and third are values. if (isFirstActual || se == call->get(3)) { return true; } return false; case PRIM_SET_MEMBER: // The first operand works like a reference, and the second is a field // name. Only the third is a replaceable use. if (se == call->get(3)) { return true; } return false; case PRIM_GET_MEMBER: case PRIM_GET_MEMBER_VALUE: if (isFirstActual) { return false; } return true; case PRIM_ARRAY_SET: case PRIM_ARRAY_SET_FIRST: case PRIM_ARRAY_GET: case PRIM_ARRAY_GET_VALUE: // The first operand is treated like a reference. if (isFirstActual) { return false; } return true; case PRIM_SET_UNION_ID: // The first operand is treated like a reference. if (isFirstActual) { return false; } return true; } } return true; }
// This routine returns true if the value of the given symbol may have changed // due to execution of the containing expression. // If the symbol is a reference, this means that the address to which the // symbol points will be changed, not the value contained in that address. See // isRefUse() for that case. // To be conservative, the routine should return true by default and then // select the cases where we are sure nothing has changed. static bool needsKilling(SymExpr* se, std::set<Symbol*>& liveRefs) { INT_ASSERT(se->isRef() == false); if (toGotoStmt(se->parentExpr)) { return false; } if (toCondStmt(se->parentExpr)) { return false; } if (toBlockStmt(se->parentExpr)) { return false; } if (isDefExpr(se->parentExpr)) { return false; } CallExpr* call = toCallExpr(se->parentExpr); if (FnSymbol* fn = call->resolvedFunction()) { // Skip the "base" symbol. if (se->symbol() == fn) { return false; } ArgSymbol* arg = actual_to_formal(se); if (arg->intent == INTENT_OUT || arg->intent == INTENT_INOUT || arg->intent == INTENT_REF || arg->hasFlag(FLAG_ARG_THIS)) // Todo: replace with arg intent check? { liveRefs.insert(se->symbol()); return true; } if (isRecordWrappedType(arg->type)) { return true; } return false; } else { const bool isFirstActual = call->get(1) == se; if ((call->isPrimitive(PRIM_MOVE) || call->isPrimitive(PRIM_ASSIGN)) && isFirstActual) { return true; } if (isOpEqualPrim(call) && isFirstActual) { return true; } if (call->isPrimitive(PRIM_SET_MEMBER) && isFirstActual) { return true; } if (call->isPrimitive(PRIM_ARRAY_SET) || call->isPrimitive(PRIM_ARRAY_SET_FIRST)) { if (isFirstActual) { return true; } return false; } if (call->isPrimitive(PRIM_GET_MEMBER)) { // This creates an alias to a portion of the first arg. // We could track this as a reference and invalidate a pair containing // this symbol when the ref is dereferenced. But for now, we want to // preserve the mapping ref = &value in the RefMap, so having a (ref, // value) pair also possibly mean ref = &(value.subfield) does not quite // fit. // We could keep the ability to do (deref ref) <- value substitution by // keeping a separate map for "true" references, or by performing those // substitutions in a separate pass. // For now, we treat subfield extraction as evidence of a future change // to the symbol itself, and use that fact to remove it from // consideration in copy propagation. if (isFirstActual) { // We select just the case where the referent is passed by value, // because in the other case, the address of the object is not // returned, so that means that the address (i.e. the value of the // reference variable) does not change. return true; } return false; } if (call->isPrimitive(PRIM_ADDR_OF) || call->isPrimitive(PRIM_SET_REFERENCE)) { liveRefs.insert(se->symbol()); return true; } return false; } INT_ASSERT(0); // Should never get here. return true; }
void CatchStmt::replaceChild(Expr* old_ast, Expr* new_ast) { if (_body == old_ast) { _body = toBlockStmt(new_ast); } }
BlockStmt* CatchStmt::body() const { return toBlockStmt(_body->body.last()); }