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; }
// Replace functions marked as simple assignments with a bulk copy // (PRIM_ASSIGN) operation. In the generated code, PRIM_ASSIGN on a type that // is represented by a C struct will be rendered as a struct assignment, which // the C compiler can implement as a memcpy. static void replaceSimpleAssignment(FnSymbol* fn) { SET_LINENO(fn); SymExpr* lhs = new SymExpr(fn->getFormal(1)); SymExpr* rhs = new SymExpr(fn->getFormal(2)); BlockStmt* block = new BlockStmt(); block->insertAtTail(new CallExpr(PRIM_ASSIGN, lhs, rhs)); block->insertAtTail(new CallExpr(PRIM_RETURN, gVoid)); fn->body->replace(block); }
BlockStmt* ForLoop::buildForLoop(Expr* indices, Expr* iteratorExpr, BlockStmt* body, bool coforall, bool zippered) { VarSymbol* index = newTemp("_indexOfInterest"); VarSymbol* iterator = newTemp("_iterator"); CallExpr* iterInit = 0; CallExpr* iterMove = 0; ForLoop* loop = new ForLoop(index, iterator, body, zippered); LabelSymbol* continueLabel = new LabelSymbol("_continueLabel"); LabelSymbol* breakLabel = new LabelSymbol("_breakLabel"); BlockStmt* retval = new BlockStmt(); iterator->addFlag(FLAG_EXPR_TEMP); // Unzippered loop, treat all objects (including tuples) the same if (zippered == false) iterInit = new CallExpr(PRIM_MOVE, iterator, new CallExpr("_getIterator", iteratorExpr)); // Expand tuple to a tuple containing appropriate iterators for each value. else iterInit = new CallExpr(PRIM_MOVE, iterator, new CallExpr("_getIteratorZip", iteratorExpr)); // try to optimize anonymous range iteration, replaces iterExpr in place optimizeAnonymousRangeIteration(iteratorExpr, zippered); index->addFlag(FLAG_INDEX_OF_INTEREST); iterMove = new CallExpr(PRIM_MOVE, index, new CallExpr("iteratorIndex", iterator)); if (indices == 0) indices = new UnresolvedSymExpr("chpl__elidedIdx"); checkIndices(indices); destructureIndices(loop, indices, new SymExpr(index), coforall); if (coforall) index->addFlag(FLAG_COFORALL_INDEX_VAR); loop->mContinueLabel = continueLabel; loop->mBreakLabel = breakLabel; loop->insertAtTail(new DefExpr(continueLabel)); retval->insertAtTail(new DefExpr(index)); retval->insertAtTail(new DefExpr(iterator)); retval->insertAtTail(iterInit); retval->insertAtTail(new BlockStmt(iterMove, BLOCK_TYPE)); retval->insertAtTail(loop); retval->insertAtTail(new DefExpr(breakLabel)); retval->insertAtTail(new CallExpr("_freeIterator", iterator)); return retval; }
BlockStmt* ForLoop::copyBody(SymbolMap* map) { BlockStmt* retval = new BlockStmt(); retval->astloc = astloc; retval->blockTag = blockTag; for_alist(expr, body) retval->insertAtTail(expr->copy(map, true)); update_symbols(retval, map); return retval; }
BlockStmt* ForLoop::buildForLoop(Expr* indices, Expr* iteratorExpr, BlockStmt* body, bool coforall, bool zippered) { VarSymbol* index = newTemp("_indexOfInterest"); VarSymbol* iterator = newTemp("_iterator"); CallExpr* iterInit = 0; CallExpr* iterMove = 0; ForLoop* loop = new ForLoop(index, iterator, body, zippered); LabelSymbol* continueLabel = new LabelSymbol("_continueLabel"); LabelSymbol* breakLabel = new LabelSymbol("_breakLabel"); BlockStmt* retval = new BlockStmt(); iterator->addFlag(FLAG_EXPR_TEMP); // Unzippered loop, treat all objects (including tuples) the same if (zippered == false) { iterInit = new CallExpr(PRIM_MOVE, iterator, new CallExpr("_getIterator", iteratorExpr)); // try to optimize anonymous range iteration tryToReplaceWithDirectRangeIterator(iteratorExpr); } // Zippered loop: Expand args to a tuple with an iterator for each element. else { CallExpr* zipExpr = toCallExpr(iteratorExpr); if (zipExpr && zipExpr->isPrimitive(PRIM_ZIP)) { // The PRIM_ZIP indicates this is a new-style zip() AST. // Expand arguments to a tuple with appropriate iterators for each value. // // Specifically, change: // zip(a, b, c, ...) // into the tuple: // (_getIterator(a), _getIterator(b), _getIterator(c), ...) // // (ultimately, we will probably want to make this style of // rewrite into a utility function for the other get*Zip // functions as we convert parallel loops over to use PRIM_ZIP). // zipExpr->primitive = NULL; // remove the primitive // If there's just one argument... if (zipExpr->argList.length == 1) { Expr* zipArg = zipExpr->argList.only(); CallExpr* zipArgCall = toCallExpr(zipArg); // ...and it is a tuple expansion '(...t)' then remove the // tuple expansion primitive and simply pass the tuple itself // to _getIteratorZip(). This will not require any more // tuples than the user introduced themselves. // if (zipArgCall && zipArgCall->isPrimitive(PRIM_TUPLE_EXPAND)) { zipExpr->baseExpr = new UnresolvedSymExpr("_getIteratorZip"); Expr* tupleArg = zipArgCall->argList.only(); tupleArg->remove(); zipArgCall->replace(tupleArg); } else { // ...otherwise, make the expression into a _getIterator() // call zipExpr->baseExpr = new UnresolvedSymExpr("_getIterator"); // try to optimize anonymous range iteration tryToReplaceWithDirectRangeIterator(zipArg); } } else { // // Otherwise, if there's more than one argument, build up the // tuple by applying _getIterator() to each element. // zipExpr->baseExpr = new UnresolvedSymExpr("_build_tuple"); Expr* arg = zipExpr->argList.first(); while (arg) { Expr* next = arg->next; Expr* argCopy = arg->copy(); arg->replace(new CallExpr("_getIterator", argCopy)); // try to optimize anonymous range iteration tryToReplaceWithDirectRangeIterator(argCopy); arg = next; } } iterInit = new CallExpr(PRIM_MOVE, iterator, zipExpr); assert(zipExpr == iteratorExpr); } else { // // This is an old-style zippered loop so handle it in the old style // iterInit = new CallExpr(PRIM_MOVE, iterator, new CallExpr("_getIteratorZip", iteratorExpr)); // try to optimize anonymous range iteration if (CallExpr* call = toCallExpr(iteratorExpr)) if (call->isNamed("_build_tuple")) for_actuals(actual, call) tryToReplaceWithDirectRangeIterator(actual); } } index->addFlag(FLAG_INDEX_OF_INTEREST); iterMove = new CallExpr(PRIM_MOVE, index, new CallExpr("iteratorIndex", iterator)); if (indices == 0) indices = new UnresolvedSymExpr("chpl__elidedIdx"); checkIndices(indices); destructureIndices(loop, indices, new SymExpr(index), coforall); if (coforall) index->addFlag(FLAG_COFORALL_INDEX_VAR); loop->mContinueLabel = continueLabel; loop->mBreakLabel = breakLabel; loop->insertAtTail(new DefExpr(continueLabel)); retval->insertAtTail(new DefExpr(index)); retval->insertAtTail(new DefExpr(iterator)); retval->insertAtTail(iterInit); retval->insertAtTail(new BlockStmt(iterMove, BLOCK_TYPE)); retval->insertAtTail(loop); retval->insertAtTail(new DefExpr(breakLabel)); retval->insertAtTail(new CallExpr("_freeIterator", iterator)); return retval; }
BlockStmt* ParamForLoop::buildParamForLoop(VarSymbol* indexVar, Expr* range, BlockStmt* stmts) { VarSymbol* lowVar = newParamVar(); VarSymbol* highVar = newParamVar(); VarSymbol* strideVar = newParamVar(); LabelSymbol* breakLabel = new LabelSymbol("_breakLabel"); LabelSymbol* continueLabel = new LabelSymbol("_unused_continueLabel"); CallExpr* call = toCallExpr(range); Expr* low = NULL; Expr* high = NULL; Expr* stride = NULL; BlockStmt* outer = new BlockStmt(); if (call && call->isNamed("chpl_by")) { stride = call->get(2)->remove(); call = toCallExpr(call->get(1)); } else { stride = new SymExpr(new_IntSymbol(1)); } if (call && call->isNamed("chpl_build_bounded_range")) { low = call->get(1)->remove(); high = call->get(1)->remove(); } else { USR_FATAL(range, "iterators for param-for-loops must be bounded literal ranges"); } outer->insertAtTail(new DefExpr(indexVar, new_IntSymbol((int64_t) 0))); outer->insertAtTail(new DefExpr(lowVar)); outer->insertAtTail(new CallExpr(PRIM_MOVE, lowVar, low)); outer->insertAtTail(new DefExpr(highVar)); outer->insertAtTail(new CallExpr(PRIM_MOVE, highVar, high)); outer->insertAtTail(new DefExpr(strideVar)); outer->insertAtTail(new CallExpr(PRIM_MOVE, strideVar, stride)); outer->insertAtTail(new ParamForLoop(indexVar, lowVar, highVar, strideVar, continueLabel, breakLabel, stmts)); // this continueLabel will be replaced by a per-iteration one. outer->insertAtTail(new DefExpr(continueLabel)); outer->insertAtTail(new DefExpr(breakLabel)); return buildChapelStmt(outer); }