GenRet BlockStmt::codegen() { GenInfo* info = gGenInfo; FILE* outfile = info->cfile; GenRet ret; codegenStmt(this); if( outfile ) { if (blockInfo) { if (blockInfo->isPrimitive(PRIM_BLOCK_WHILEDO_LOOP)) { std::string hdr = "while (" + codegenValue(blockInfo->get(1)).c + ") "; info->cStatements.push_back(hdr); } else if (blockInfo->isPrimitive(PRIM_BLOCK_DOWHILE_LOOP)) { info->cStatements.push_back("do "); } else if (blockInfo->isPrimitive(PRIM_BLOCK_FOR_LOOP)) { std::string hdr = "for (;" + codegenValue(blockInfo->get(1)).c + ";) "; info->cStatements.push_back(hdr); } else if (blockInfo->isPrimitive(PRIM_BLOCK_XMT_PRAGMA_FORALL_I_IN_N)) { std::string hdr = "_Pragma(\"mta for all streams "; hdr += codegenValue(blockInfo->get(1)).c; hdr += " of "; hdr += codegenValue(blockInfo->get(2)).c; hdr += "\")\n"; info->cStatements.push_back(hdr); } } if (this != getFunction()->body) info->cStatements.push_back("{\n"); if (!(fNoRepositionDefExpr)) { Vec<BaseAST*> asts; collect_top_asts(this, asts); forv_Vec(BaseAST, ast, asts) { if (DefExpr* def = toDefExpr(ast)) { if (def->parentExpr == this) { if (!toTypeSymbol(def->sym)) { if (fGenIDS && isVarSymbol(def->sym)) info->cStatements.push_back("/* " + numToString(def->sym->id) + " */ "); def->sym->codegenDef(); } } } } } body.codegen(""); if (blockInfo && blockInfo->isPrimitive(PRIM_BLOCK_DOWHILE_LOOP)) { std::string ftr = "} while (" + codegenValue(blockInfo->get(1)).c + ");\n"; info->cStatements.push_back(ftr); } else if (this != getFunction()->body) { std::string end = "}"; CondStmt* cond = toCondStmt(parentExpr); if (!cond || !(cond->thenStmt == this && cond->elseStmt)) end += "\n"; info->cStatements.push_back(end); } } else {
GenRet BlockStmt::codegen() { GenInfo* info = gGenInfo; FILE* outfile = info->cfile; GenRet ret; codegenStmt(this); if (outfile) { if (this != getFunction()->body) { if (this->blockInfoGet()) { if (this->blockInfoGet()->isPrimitive(PRIM_BLOCK_LOCAL)) { info->cStatements.push_back("/* local block */\n"); } } info->cStatements.push_back("{\n"); } body.codegen(""); if (this != getFunction()->body) { std::string end = "}"; CondStmt* cond = toCondStmt(parentExpr); if (!cond || !(cond->thenStmt == this && cond->elseStmt)) end += "\n"; info->cStatements.push_back(end); } } else { #ifdef HAVE_LLVM llvm::Function* func = info->builder->GetInsertBlock()->getParent(); llvm::BasicBlock* blockStmtBody = NULL; getFunction()->codegenUniqueNum++; blockStmtBody = llvm::BasicBlock::Create(info->module->getContext(), FNAME("blk_body")); info->builder->CreateBr(blockStmtBody); // Now add the body. func->getBasicBlockList().push_back(blockStmtBody); info->builder->SetInsertPoint(blockStmtBody); info->lvt->addLayer(); body.codegen(""); info->lvt->removeLayer(); INT_ASSERT(blockStmtBody->getParent() == func); #endif } return ret; }
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 list_line(Expr* expr, BaseAST* parentAst) { if (expr->isStmt()) return !*block_explanation(expr, parentAst); if (CondStmt* cond = toCondStmt(parentAst)) { if (cond->condExpr == expr) return false; } if (Expr* pExpr = toExpr(parentAst)) if (pExpr->isStmt()) return true; if (isSymbol(parentAst)) return true; return false; }
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; }