Пример #1
0
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;
}
Пример #2
0
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;
}
Пример #3
0
SymbolTableEntry* Parser::parseExpressionPrime(SymbolTableEntry* prevEntry){
	SymbolTableEntry* result = prevEntry;
	if(isNext(tc_RELOP)){
		OpType t = m_currentToken->getOpType();
		match(tc_RELOP);
		SymbolTableEntry* exp = parseSimpleExpression();
		result = newTemp();
		SymbolTableEntry* tr = newLabel();
		SymbolTableEntry* end = newLabel();
		if(t == op_LT){
			m_code->generate(cd_LT, prevEntry, exp, tr);
		}
		else if(t == op_LE){
			m_code->generate(cd_LE, prevEntry, exp, tr);
		}
		else if(t == op_GT){
			m_code->generate(cd_GT, prevEntry, exp, tr);
		}
		else if(t == op_GE){
			m_code->generate(cd_GE, prevEntry, exp, tr);
		}
		else if(t == op_EQ){
			m_code->generate(cd_EQ, prevEntry, exp, tr);
		}
		else{
			m_code->generate(cd_NE, prevEntry, exp, tr);
		}
		m_code->generate(cd_ASSIGN, m_symbolTable->lookup(CodeFalse), NULL, result);
		m_code->generate(cd_GOTO, NULL, NULL, end);
		m_code->generate(cd_LABEL, NULL, NULL, tr);
		m_code->generate(cd_ASSIGN, m_symbolTable->lookup(CodeTrue), NULL, result);
		m_code->generate(cd_LABEL, NULL, NULL, end);
	}
	return result;
}
Пример #4
0
 // tag iterators and replace delete statements with calls to ~chpl_destroy
 forv_Vec(CallExpr, call, gCallExprs) {
   if (call->isPrimitive(PRIM_YIELD)) {
     FnSymbol* fn = toFnSymbol(call->parentSymbol);
     // violations should have caused USR_FATAL in semanticChecks.cpp
     INT_ASSERT(fn && fn->hasFlag(FLAG_ITERATOR_FN));
   }
   if (call->isPrimitive(PRIM_DELETE)) {
     SET_LINENO(call);
     VarSymbol* tmp = newTemp("delete_tmp");
     call->insertBefore(new DefExpr(tmp));
     call->insertBefore(new CallExpr(PRIM_MOVE, tmp, call->get(1)->remove()));
     call->insertBefore(new CallExpr("~chpl_destroy", gMethodToken, tmp));
     CallExpr* freeExpr = callChplHereFree(tmp);
     if (fLocal) {
       call->insertBefore(freeExpr);
     } else {
       //
       // if compiling for multiple locales, we need to be sure that the
       // delete is executed on the locale on which the object lives for
       // correctness sake.
       //
       BlockStmt* onStmt = buildOnStmt(new SymExpr(tmp), freeExpr);
       call->insertBefore(onStmt);
     }
     call->remove();
   }
 }
Пример #5
0
SymbolTableEntry* Parser::parseTermPrime(SymbolTableEntry* prevEntry){
	if(isNext(tc_MULOP)){
		OpType t = m_currentToken->getOpType();
		match(tc_MULOP);
		SymbolTableEntry* factor = parseFactor();
		SymbolTableEntry* temp = newTemp();
		if(t == op_MULT){
			m_code->generate(cd_MULT, prevEntry, factor, temp);
		}
		else if(t == op_DIVIDE){
			m_code->generate(cd_DIVIDE, prevEntry, factor, temp);
		}
		else if(t == op_DIV){
			m_code->generate(cd_DIV, prevEntry, factor, temp);
		}
		else if(t == op_MOD){
			m_code->generate(cd_MOD, prevEntry, factor, temp);
		}
		else{
			m_code->generate(cd_AND, prevEntry, factor, temp);
		}
		prevEntry = parseTermPrime(temp);
	}
	return prevEntry;
}
Пример #6
0
TAC* binaryOp_tac(tacType_t type, TAC** children)
{
	linkedList_t* temp1 = children[0]->destination;
	linkedList_t* temp2 = children[1]->destination;
	
	return append(append(children[0], children[1]), tac(type, newTemp(), temp1, temp2));
}
Пример #7
0
VarSymbol* ParamForLoop::newParamVar()
{
  VarSymbol* retval = newTemp();

  retval->addFlag(FLAG_MAYBE_PARAM);

  return retval;
}
Пример #8
0
/*
To implement task reduce intents, we follow the steps in
propagateExtraLeaderArgs() and setupOneReduceIntent()

I.e. add the following to the AST:

* before 'call'
    def globalOp = new reduceType(origSym.type);

* pass globalOp to call();
  corresponding formal in 'fn': parentOp

* inside 'fn'
    def currOp = parentOp.clone()
    def symReplace = currOp.identify;
    ...
    currOp.accumulate(symReplace);
    parentOp.combine(currOp);
    delete currOp;

* after 'call' and its _waitEndCount()
    origSym = parentOp.generate();
    delete parentOp;

Put in a different way, a coforall like this:

    var x: int;
    coforall ITER with (OP reduce x) {
      BODY(x);      // will typically include:  x OP= something;
    }

with its corresponding task-function representation:

    var x: int;
    proc coforall_fn() {
      BODY(x);
    }
    call coforall_fn();

is transformed into

    var x: int;
    var globalOp = new OP_SCAN_REDUCE_CLASS(x.type);

    proc coforall_fn(parentOp) {
      var currOp = parentOp.clone()
      var symReplace = currOp.identify;

      BODY(symReplace);

      currOp.accumulate(symReplace);
      parentOp.combine(currOp);
      delete currOp;
    }

    call coforall_fn(globalOp);
    // wait for endCount - not shown
    x = globalOp.generate();
    delete globalOp;

Todo: to support cobegin constructs, need to share 'globalOp'
across all fn+call pairs for the same construct.
*/
static void addReduceIntentSupport(FnSymbol* fn, CallExpr* call,
                                   TypeSymbol* reduceType, Symbol* origSym,
                                   ArgSymbol*& newFormal, Symbol*& newActual,
                                   Symbol*& symReplace, bool isCoforall,
                                   Expr*& redRef1, Expr*& redRef2)
{
  setupRedRefs(fn, true, redRef1, redRef2);
  VarSymbol* globalOp = new VarSymbol("reduceGlobal");
  globalOp->addFlag(FLAG_NO_CAPTURE_FOR_TASKING);
  newActual = globalOp;

  VarSymbol* eltType = newTemp("redEltType");
  eltType->addFlag(FLAG_MAYBE_TYPE);

  Expr* headAnchor = call;
  if (isCoforall) headAnchor = headAnchor->parentExpr;
  headAnchor->insertBefore(new DefExpr(eltType));
  headAnchor->insertBefore("'move'(%S, 'typeof'(%S))", eltType, origSym);
  headAnchor->insertBefore(new DefExpr(globalOp));

  AggregateType* reduceAt = toAggregateType(reduceType->type);
  INT_ASSERT(reduceAt);

  CallExpr* newOp = new CallExpr(reduceAt->defaultInitializer->name,
                                 new NamedExpr("eltType", new SymExpr(eltType)));
  headAnchor->insertBefore(new CallExpr(PRIM_MOVE, globalOp, newOp));

  Expr* tailAnchor = findTailInsertionPoint(call, isCoforall);
  // Doing insertAfter() calls in reverse order.
  // Can't insertBefore() on tailAnchor->next - that can be NULL.
  tailAnchor->insertAfter("'delete'(%S)",
                         globalOp);
  tailAnchor->insertAfter("'='(%S, generate(%S,%S))",
                         origSym, gMethodToken, globalOp);

  ArgSymbol* parentOp = new ArgSymbol(INTENT_BLANK, "reduceParent", dtUnknown);
  newFormal = parentOp;

  VarSymbol* currOp = new VarSymbol("reduceCurr");
  VarSymbol* svar  = new VarSymbol(origSym->name, origSym->type);
  symReplace = svar;

  redRef1->insertBefore(new DefExpr(currOp));
  redRef1->insertBefore("'move'(%S, clone(%S,%S))", // init
                        currOp, gMethodToken, parentOp);
  redRef1->insertBefore(new DefExpr(svar));
  redRef1->insertBefore("'move'(%S, identity(%S,%S))", // init
                        svar, gMethodToken, currOp);

  redRef2->insertBefore(new CallExpr("accumulate",
                                     gMethodToken, currOp, svar));
  redRef2->insertBefore(new CallExpr("chpl__reduceCombine",
                                     parentOp, currOp));
  redRef2->insertBefore(new CallExpr("chpl__cleanupLocalOp",
                                     parentOp, currOp));
}
void TransformLogicalShortCircuit::exitCallExpr(CallExpr* call)
{
  if (call->primitive == 0)
  {
    if (UnresolvedSymExpr* expr = toUnresolvedSymExpr(call->baseExpr))
    {
      bool isLogicalAnd = strcmp(expr->unresolved, "&&") == 0;
      bool isLogicalOr  = strcmp(expr->unresolved, "||") == 0;

      if (isLogicalAnd || isLogicalOr)
      {
        SET_LINENO(call);

        if (call->getStmtExpr() == mInsertionPoint)
        {
          Expr*      left  = call->get(1);
          Expr*      right = call->get(2);
          VarSymbol* lvar  = newTemp();

          VarSymbol* eMsg  = NULL;
          FnSymbol*  ifFn  = NULL;

          left->remove();
          right->remove();

          lvar->addFlag(FLAG_MAYBE_PARAM);

          if (isLogicalAnd)
          {
            eMsg = new_StringSymbol("cannot promote short-circuiting && operator");
            ifFn = buildIfExpr(new CallExpr("isTrue", lvar),
                               new CallExpr("isTrue", right),
                               new SymExpr(gFalse));
          }
          else
          {
            eMsg = new_StringSymbol("cannot promote short-circuiting || operator");
            ifFn = buildIfExpr(new CallExpr("isTrue", lvar),
                               new SymExpr(gTrue),
                               new CallExpr("isTrue", right));
          }

          ifFn->insertAtHead(new CondStmt(new CallExpr("_cond_invalid", lvar),
                                          new CallExpr("compilerError", eMsg)));
          ifFn->insertAtHead(new CallExpr(PRIM_MOVE, lvar, left));
          ifFn->insertAtHead(new DefExpr(lvar));

          call->baseExpr->replace(new UnresolvedSymExpr(ifFn->name));

          mInsertionPoint->insertBefore(new DefExpr(ifFn));
        }
      }
    }
  }
}
Пример #10
0
void localizeGlobals() {
  if (fNoGlobalConstOpt) return;
  forv_Vec(FnSymbol, fn, gFnSymbols) {
    Map<Symbol*,VarSymbol*> globals;
    std::vector<BaseAST*> asts;
    collect_asts(fn->body, asts);
    for_vector(BaseAST, ast, asts) {
      if (SymExpr* se = toSymExpr(ast)) {
        Symbol* var = se->symbol();
        ModuleSymbol* parentmod = toModuleSymbol(var->defPoint->parentSymbol);
        CallExpr* parentExpr = toCallExpr(se->parentExpr);
        bool inAddrOf = parentExpr && parentExpr->isPrimitive(PRIM_ADDR_OF);
        bool lhsOfMove = parentExpr && isMoveOrAssign(parentExpr) && (parentExpr->get(1) == se);

        // Is var a global constant?
        // Don't replace the var name in its init function since that's
        //      where we're setting the value. Similarly, dont replace them
        //      inside initStringLiterals
        // If the parentSymbol is the rootModule, the var is 'void,'
        //      'false,' '0,' ...
        // Also don't replace it when it's in an addr of primitive.
        if (parentmod &&
            fn != parentmod->initFn &&
            fn != initStringLiterals &&
            !inAddrOf &&
            !lhsOfMove &&
            var->hasFlag(FLAG_CONST) &&
            var->defPoint->parentSymbol != rootModule) {
          VarSymbol* local_global = globals.get(var);
          SET_LINENO(se); // Set the se line number for output
          if (!local_global) {
            const char * newname = astr("local_", var->cname);
            local_global = newTemp(newname, var->type);
            fn->insertAtHead(new CallExpr(PRIM_MOVE, local_global, var));
            fn->insertAtHead(new DefExpr(local_global));

            // Copy string immediates to localized strings so that
            // we can show the string value in comments next to uses.
            if (!llvmCodegen)
              if (VarSymbol* localVarSym = toVarSymbol(var))
                if (Immediate* immediate = localVarSym->immediate)
                  if (immediate->const_kind == CONST_KIND_STRING)
                    local_global->immediate =
                      new Immediate(immediate->v_string, immediate->string_kind);

            globals.put(var, local_global);
          }
          se->replace(new SymExpr(toSymbol(local_global)));
        }
      }
    }
  }
Пример #11
0
//
// The argument expr is a use of a wide reference. Insert a check to ensure
// that it is on the current locale, then drop its wideness by moving the
// addr field into a non-wide of otherwise the same type. Then, replace its
// use with the non-wide version.
//
static void insertLocalTemp(Expr* expr) {
  SymExpr* se = toSymExpr(expr);
  Expr* stmt = expr->getStmtExpr();
  INT_ASSERT(se && stmt);
  SET_LINENO(se);
  VarSymbol* var = newTemp(astr("local_", se->var->name),
                           se->var->type->getField("addr")->type);
  if (!fNoLocalChecks) {
    stmt->insertBefore(new CallExpr(PRIM_LOCAL_CHECK, se->copy()));
  }
  stmt->insertBefore(new DefExpr(var));
  stmt->insertBefore(new CallExpr(PRIM_MOVE, var, se->copy()));
  se->replace(new SymExpr(var));
}
Пример #12
0
string AssignmentStatement::GenerateCode(){
	stringstream varCode;

	ResultValue lvalue_r = lvalue->GenerateCode();
	ResultValue rvalue_r = expr->GenerateCode();
	LValueExpression* n = (LValueExpression*)lvalue;
	cout << " 1: " << lvalue_r.code << "        2: " << rvalue_r.code << endl;
	if (!ExistVarGlobal(n->variable_name) && !ExistVarTemp(n->variable_name)){
				cout << "("<<line<<","<<column<<"): Variable \'" << n->variable_name << "\' no ha sido declarada."<<endl;
	}
	else if (lvalue_r.type == rvalue_r.type){
					if (ExistVarGlobal(n->variable_name)){
							if (rvalue_r.isConstant){
									string p = newTemp();
									varCode << rvalue_r.code;
									varCode << "	li " << p << ", " << rvalue_r.value.int_value << endl; // VALIDAR los demas tipos (bool, string)
									varCode << "	sw " << p << ", " << n->variable_name << endl;
									releaseTemp(p);
							}
							else {
									string p = newTemp();
									varCode << rvalue_r.code;
									varCode << "	sw " << rvalue_r.place << ", " << n->variable_name << endl;
									releaseTemp(p);
							}
					}
					if (ExistVarTemp(n->variable_name)){
							if (rvalue_r.isConstant)
									varCode << "	li " << varsTemp[n->variable_name].place << ", " << rvalue_r.value.int_value << endl;
							else
									varCode << "	move " << varsTemp[n->variable_name].place << ", " << rvalue_r.place << endl;
					}
			 }
			else
					cout << " ERROR en Statement ("<<line<<","<<column<<"): Variable \'"<< n->variable_name << "\' No se puede convertir \'" << TypeToString(rvalue_r.type) << "\' a \'" << TypeToString(lvalue_r.type) << "\'"<<endl;
	return varCode.str();
}
Пример #13
0
SymbolTableEntry* Parser::parseSimpleExpression(){
	int sign = false;
	if(isNext(tc_ADDOP)){
		if(m_currentToken->getOpType() == op_MINUS){
			sign = true;
		}
		parseSign();
	}
	SymbolTableEntry* entry = parseTerm();
	entry = parseSimpleExpressionPrime(entry);
	SymbolTableEntry* result = entry;
	if(sign){
		result = newTemp();
		m_code->generate(cd_UMINUS, entry, NULL, result);
	}
	return result;
}
Пример #14
0
  forv_Vec(CallExpr, call, gCallExprs) {
    if (call->isPrimitive(PRIM_CHECK_ERROR)) {
      SET_LINENO(call);

      SymExpr* errSe   = toSymExpr(call->get(1));
      Symbol*  errorVar= errSe->symbol();

      VarSymbol* errorExistsVar = newTemp("errorExists", dtBool);
      DefExpr*   def            = new DefExpr(errorExistsVar);
      CallExpr*  errorExists    = new CallExpr(PRIM_NOTEQUAL, errorVar, gNil);
      CallExpr*  move = new CallExpr(PRIM_MOVE, errorExistsVar, errorExists);

      Expr* stmt = call->getStmtExpr();
      stmt->insertBefore(def);
      def->insertAfter(move);
      call->replace(new SymExpr(errorExistsVar));
    }
  }
Пример #15
0
SymbolTableEntry* Parser::parseSimpleExpressionPrime(SymbolTableEntry* prevEntry){
	SymbolTableEntry* temp = prevEntry;
	if(isNext(tc_ADDOP)){
		OpType t = m_currentToken->getOpType();
		match(tc_ADDOP);
		temp = newTemp();
		SymbolTableEntry* term = parseTerm();
		if(t == op_PLUS){
			m_code->generate(cd_ADD, prevEntry, term, temp);
		}
		else if(t == op_MINUS){
			m_code->generate(cd_SUB, prevEntry, term, temp);
		}
		else{
			m_code->generate(cd_OR, prevEntry, term, temp);
		}
		prevEntry = parseSimpleExpressionPrime(temp);
	}
	return temp;
}
Пример #16
0
void localizeGlobals() {
  if (fNoGlobalConstOpt) return;
  forv_Vec(FnSymbol, fn, gFnSymbols) {
    Map<Symbol*,VarSymbol*> globals;
    std::vector<BaseAST*> asts;
    collect_asts(fn->body, asts);
    for_vector(BaseAST, ast, asts) {
      if (SymExpr* se = toSymExpr(ast)) {
        Symbol* var = se->var;
        ModuleSymbol* parentmod = toModuleSymbol(var->defPoint->parentSymbol);
        CallExpr* parentExpr = toCallExpr(se->parentExpr);
        bool inAddrOf = parentExpr && parentExpr->isPrimitive(PRIM_ADDR_OF);

        // Is var a global constant?
        // Don't replace the var name in its init function since that's
        //      where we're setting the value. Similarly, dont replace them
        //      inside initStringLiterals
        // If the parentSymbol is the rootModule, the var is 'void,'
        //      'false,' '0,' ...
        // Also don't replace it when it's in an addr of primitive.
        if (parentmod &&
            fn != parentmod->initFn &&
            fn != initStringLiterals &&
            !inAddrOf &&
            var->hasFlag(FLAG_CONST) &&
            var->defPoint->parentSymbol != rootModule) {
          VarSymbol* local_global = globals.get(var);
          SET_LINENO(se); // Set the se line number for output
          if (!local_global) {
            const char * newname = astr("local_", var->cname);
            local_global = newTemp(newname, var->type);
            fn->insertAtHead(new CallExpr(PRIM_MOVE, local_global, var));
            fn->insertAtHead(new DefExpr(local_global));

            globals.put(var, local_global);
          }
          se->replace(new SymExpr(toSymbol(local_global)));
        }
      }
    }
  }
Пример #17
0
SymbolTableEntry* Parser::parseFactor(){
	SymbolTableEntry* factor = NULL;
	SymbolTableEntry* result = m_symbolTable->lookup(CodeFalse);
	if(isNext(tc_ID)){
		factor = m_currentToken->getSymTabEntry();
		match(tc_ID);
		result = parseFactorPrime(factor);
	}
	else if(isNext(tc_LPAREN)){
		match(tc_LPAREN);
		result = parseExpression();
		match(tc_RPAREN);
		if(m_parserError){
			TokenCode synch[] = {tc_RPAREN, tc_END, tc_ADDOP, tc_MULOP, tc_RELOP, tc_THEN, tc_DO, tc_COMMA, tc_RBRACKET, tc_SEMICOL, tc_ELSE, tc_NONE};
			recover(synch);
//			if(isNext(tc_RPAREN)){
//				match(tc_RPAREN);
//			}
		}
	}
	else if(isNext(tc_NOT)){
		match(tc_NOT);
		factor = parseFactor();
		result = newTemp();
		m_code->generate(cd_NOT, factor, NULL, result);
	}
	else{
		result = m_currentToken->getSymTabEntry();
		match(tc_NUMBER);
		if(m_parserError){
			TokenCode synch[] = {tc_RPAREN, tc_END, tc_ADDOP, tc_MULOP, tc_RELOP, tc_THEN, tc_DO, tc_COMMA, tc_RBRACKET, tc_SEMICOL, tc_ELSE, tc_NONE};
			recover(synch);
//			if(isNext(tc_NUMBER)){
//				match(tc_NUMBER);
//			}
		}
	}
	return result;
}
Пример #18
0
//进行规约的操作
bool LRGramar::doGuiYue(const int ruleNum)
{
    switch(ruleNum)
    {
    case  R1:
        //执行进出站等相关操作
        if(!doRules(A_NTERMINAL,4))
        {
            return false;
        }
        break;
    case R2:
        if(!doRules(B_NTERMINAL,3))
        {
            return false;
        }
        break;
    case R3:
        if(!doRules(C_NTERMINAL,3))
        {
            return false;
        }
        break;
    case R4:
        if(!doRules(C_NTERMINAL,0))
        {
            return false;
        }
        break;
    case R5:
        if(!doRules(D_NTERMINAL,1))
        {
            return false;
        }
        break;
    case R6:
    case R7:
        if(!doRules(D_NTERMINAL,1))
        {
            return false;
        }
        else
        {

        }
        break;
    case R8:
        if(!doRules(F_NTERMINAL,3))
        {
            return false;
        }
        else
        {
            //堆栈是先进先出
            int argP = variableBufferPtr--;
            int resultPtr = variableBufferPtr--;
            emit("=",variableBuffer[argP]," ",variableBuffer[resultPtr]);
        }
        break;
    case R9:
        if(!doRules(G_NTERMINAL,2))
        {
            return false;
        }
        else
        {
            backPatch(trueChainHead,nextq);  //回填真链头
        }
        break;
    case R10:
        if(!doRules(S_NTERMINAL,2))
        {
            return false;
        }
        else
        {
            backPatch(falseChain[falseChainPtr--],nextq);
        }
        break;
    case R11:
        if(!doRules(T_NTERMINAL,3))
        {
            return false;
        }
        else
        {

            emit("goto","","","0");
            backPatch(falseChain[falseChainPtr--],nextq);
            falseChain[++falseChainPtr] = nextq-1;
        }
        break;
    case R12:
        if(!doRules(S_NTERMINAL,2))
        {
            return false;
        }
        backPatch(falseChain[falseChainPtr--],nextq);
        break;
    case R13:
        if(!doRules(W_NTERMINAL,2))
        {
            return false;
        }
        else
        {
            backPatch(trueChainHead,doTrue[doTruePtr--]);
            backPatch(falseChain[falseChainPtr--],nextq);
        }
        break;
    case R14:
        if(!doRules(K_NTERMINAL,1))
        {
            return false;
        }
        doTrue[++doTruePtr] = nextq;//保存do后面的地址
        break;
    case R15:
        if(!doRules(L_NTERMINAL,2))
        {
            return false;
        }
        break;
    case R16:
        if(!doRules(N_NTERMINAL,2))
        {
            return false;
        }
        break;
    case R17:
        if(!doRules(Q_NTERMINAL,3))
        {
            return false;
        }
        else
        {
            trueChainHead = nextq;
            falseChain[++falseChainPtr]=nextq+1;
            char temp[10];
            int arg2 = variableBufferPtr--;
            int arg1 = variableBufferPtr--;
            sprintf(temp,"%s%s%s",variableBuffer[arg1],lastOp[OpPtr--],variableBuffer[arg2]);
            emit("if",temp,"goto","0");
            emit("goto","","","0");

        }
        break;
    case R18:
        if(!doRules(P_NTERMINAL,2))
        {
            return false;
        }
        else
        {
            if(strcmp(variableBuffer[variableBufferPtr],"null")!=0)
            {
                char *pPlace = newTemp();
                emit(lastOp[OpPtr--],variableBuffer[variableBufferPtr--],variableBuffer[variableBufferPtr--],pPlace);
                strcpy(variableBuffer[++variableBufferPtr],pPlace);
            }
            else {
                variableBufferPtr--;
            }
        }
        break;
    case R19:
        if(!doRules(H_NTERMINAL,3))
        {
            return false;
        }
        else
        {
            if(strcmp(variableBuffer[variableBufferPtr],"null")!=0)
            {
                char *hPlace = newTemp();
                emit(lastOp[OpPtr--],variableBuffer[variableBufferPtr--],variableBuffer[variableBufferPtr--],hPlace);
                strcpy(variableBuffer[++variableBufferPtr],hPlace);
            }
            else {
                variableBufferPtr--;
            }
            strcpy(lastOp[++OpPtr],"+");
        }
        break;
    case R20:
        if(!doRules(H_NTERMINAL,3))
        {
            return false;
        }
        else
        {
            if(strcmp(variableBuffer[variableBufferPtr],"null")!=0)
            {
                char *hPlace = newTemp();
                emit(lastOp[OpPtr--],variableBuffer[variableBufferPtr--],variableBuffer[variableBufferPtr--],hPlace);
                strcpy(variableBuffer[++variableBufferPtr],hPlace);
            }
            else
            {
                variableBufferPtr--;
            }
            strcpy(lastOp[++OpPtr],"-");
        }
        break;
    case R21:
        if(!doRules(H_NTERMINAL,0))
        {
            return false;
        }
        else
        {
            strcpy(variableBuffer[++variableBufferPtr],"null");
        }
        break;
    case R22:
        if(!doRules(Z_NTERMINAL,2))
        {
            return false;
        }
        else
        {
            if(strcmp(variableBuffer[variableBufferPtr],"null")!=0)
            {
                char *zPlace = newTemp();
                emit(lastOp[OpPtr--],variableBuffer[variableBufferPtr--],variableBuffer[variableBufferPtr--],zPlace);
                strcpy(variableBuffer[++variableBufferPtr],zPlace);
            }
            else
            {
                variableBufferPtr--;
            }
        }
        break;
    case R23:
        if(!doRules(V_NTERMINAL,3))
        {
            return false;
        }
        else
        {
            if(strcmp(variableBuffer[variableBufferPtr],"null")!=0)
            {
                char *vPlace = newTemp();
                emit(lastOp[--OpPtr],variableBuffer[variableBufferPtr--],variableBuffer[variableBufferPtr--],vPlace);
                strcpy(variableBuffer[++variableBufferPtr],vPlace);
            }
            else
            {
                variableBufferPtr--;
            }
            strcpy(lastOp[++OpPtr] ,"*");
        }
        break;
    case R24:
        if(!doRules(V_NTERMINAL,3))
        {
            return false;
        }
        else
        {
            if(strcmp(variableBuffer[variableBufferPtr],"null")!=0)
            {
                char *vPlace = newTemp();
                emit(lastOp[--OpPtr],variableBuffer[variableBufferPtr--],variableBuffer[variableBufferPtr--],vPlace);
                strcpy(variableBuffer[++variableBufferPtr],vPlace);
            }
            else
            {
                variableBufferPtr--;
            }
            strcpy(lastOp[++OpPtr] ,"/");
        }
        break;
    case R25:
    case R26:
        if(!doRules(U_NTERMINAL,1))
        {
            return false;
        }
        break;
    case R27:
        if(!doRules(U_NTERMINAL,3))
        {
            return false;
        }
        break;
    case R28:
        strcpy(lastOp[++OpPtr],"<");
        if(!doRules(Y_NTERMINAL,1))
        {
            return false;
        }
        break;
    case R29:
        if(!doRules(Y_NTERMINAL,1))
        {
            return false;
        }
        strcpy(lastOp[++OpPtr],"<=");
        break;
    case R30:
        if(!doRules(Y_NTERMINAL,1))
        {
            return false;
        }
        strcpy(lastOp[++OpPtr],">");
        break;
    case R31:
        if(!doRules(Y_NTERMINAL,1))
        {
            return false;
        }
        strcpy(lastOp[++OpPtr],">=");
        break;
    case R32:
        if(!doRules(Y_NTERMINAL,1))
        {
            return false;
        }
        strcpy(lastOp[++OpPtr],"==");
        break;
    case R33:
        if(!doRules(Y_NTERMINAL,1))
        {
            return false;
        }
        strcpy(lastOp[++OpPtr],"!=");
        break;
    case R34:
        if(!doRules(V_NTERMINAL,0))
        {
            return false;
        }
        else
        {
            strcpy(variableBuffer[++variableBufferPtr],"null");
        }
        break;
    default:
        return false;
    }
    return true;
}
Пример #19
0
//
// If call has the potential to cause communication, assert that the wide
// reference that might cause communication is local and remove its wide-ness
//
// The organization of this function follows the order of CallExpr::codegen()
// leaving out primitives that don't communicate.
//
static void localizeCall(CallExpr* call) {
  if (call->primitive) {
    switch (call->primitive->tag) {
    case PRIM_ARRAY_SET: /* Fallthru */
    case PRIM_ARRAY_SET_FIRST:
      if (call->get(1)->typeInfo()->symbol->hasFlag(FLAG_WIDE_CLASS)) {
        insertLocalTemp(call->get(1));
      }
      break;
    case PRIM_MOVE:
    case PRIM_ASSIGN: // Not sure about this one.
      if (CallExpr* rhs = toCallExpr(call->get(2))) {
        if (rhs->isPrimitive(PRIM_DEREF)) {
          if (rhs->get(1)->typeInfo()->symbol->hasFlag(FLAG_WIDE_REF) ||
              rhs->get(1)->typeInfo()->symbol->hasFlag(FLAG_WIDE_CLASS)) {
            insertLocalTemp(rhs->get(1));
            if (!rhs->get(1)->typeInfo()->symbol->hasFlag(FLAG_REF)) {
              INT_ASSERT(rhs->get(1)->typeInfo() == dtString);
              // special handling for wide strings
              rhs->replace(rhs->get(1)->remove());
            }
          }
          break;
        } 
        else if (rhs->isPrimitive(PRIM_GET_MEMBER) ||
                   rhs->isPrimitive(PRIM_GET_SVEC_MEMBER) ||
                   rhs->isPrimitive(PRIM_GET_MEMBER_VALUE) ||
                   rhs->isPrimitive(PRIM_GET_SVEC_MEMBER_VALUE)) {
          if (rhs->get(1)->typeInfo()->symbol->hasFlag(FLAG_WIDE_REF) ||
              rhs->get(1)->typeInfo()->symbol->hasFlag(FLAG_WIDE_CLASS)) {
            SymExpr* sym = toSymExpr(rhs->get(2));
            INT_ASSERT(sym);
            if (!sym->var->hasFlag(FLAG_SUPER_CLASS)) {
              insertLocalTemp(rhs->get(1));
            }
          }
          break;
        } else if (rhs->isPrimitive(PRIM_ARRAY_GET) ||
                   rhs->isPrimitive(PRIM_ARRAY_GET_VALUE)) {
          if (rhs->get(1)->typeInfo()->symbol->hasFlag(FLAG_WIDE_CLASS)) {
            SymExpr* lhs = toSymExpr(call->get(1));
            Expr* stmt = call->getStmtExpr();
            INT_ASSERT(lhs && stmt);

            SET_LINENO(stmt);
            insertLocalTemp(rhs->get(1));
            VarSymbol* localVar = NULL;
            if (rhs->isPrimitive(PRIM_ARRAY_GET))
              localVar = newTemp(astr("local_", lhs->var->name),
                                 lhs->var->type->getField("addr")->type);
            else
              localVar = newTemp(astr("local_", lhs->var->name),
                                 lhs->var->type);
            stmt->insertBefore(new DefExpr(localVar));
            lhs->replace(new SymExpr(localVar));
            stmt->insertAfter(new CallExpr(PRIM_MOVE, lhs,
                                           new SymExpr(localVar)));
          }
          break;
        } else if (rhs->isPrimitive(PRIM_GET_UNION_ID)) {
          if (rhs->get(1)->typeInfo()->symbol->hasFlag(FLAG_WIDE_REF)) {
            insertLocalTemp(rhs->get(1));
          }
          break;
        } else if (rhs->isPrimitive(PRIM_TESTCID) ||
                   rhs->isPrimitive(PRIM_GETCID)) {
          if (rhs->get(1)->typeInfo()->symbol->hasFlag(FLAG_WIDE_CLASS)) {
            insertLocalTemp(rhs->get(1));
          }
          break;
        }
        ;
      }
      if (call->get(1)->typeInfo()->symbol->hasFlag(FLAG_WIDE_CLASS) &&
          !call->get(2)->typeInfo()->symbol->hasFlag(FLAG_WIDE_CLASS)) {
        break;
      }
      if (call->get(1)->typeInfo()->symbol->hasFlag(FLAG_WIDE_REF) &&
          !call->get(2)->typeInfo()->symbol->hasFlag(FLAG_WIDE_REF) &&
          !call->get(2)->typeInfo()->symbol->hasFlag(FLAG_REF)) {
        insertLocalTemp(call->get(1));
      }
      break;
    case PRIM_DYNAMIC_CAST:
      if (call->get(2)->typeInfo()->symbol->hasFlag(FLAG_WIDE_CLASS)) {
        insertLocalTemp(call->get(2));
        if (call->get(1)->typeInfo()->symbol->hasFlag(FLAG_WIDE_CLASS) ||
            call->get(1)->typeInfo()->symbol->hasFlag(FLAG_WIDE_REF)) {
          toSymExpr(call->get(1))->var->type = call->get(1)->typeInfo()->getField("addr")->type;
        }
      }
      break;
    case PRIM_SETCID:
      if (call->get(1)->typeInfo()->symbol->hasFlag(FLAG_WIDE_CLASS)) {
        insertLocalTemp(call->get(1));
      }
      break;
    case PRIM_SET_UNION_ID:
      if (call->get(1)->typeInfo()->symbol->hasFlag(FLAG_WIDE_REF)) {
        insertLocalTemp(call->get(1));
      }
      break;
    case PRIM_SET_MEMBER:
    case PRIM_SET_SVEC_MEMBER:
      if (call->get(1)->typeInfo()->symbol->hasFlag(FLAG_WIDE_CLASS) ||
          call->get(1)->typeInfo()->symbol->hasFlag(FLAG_WIDE_REF)) {
        insertLocalTemp(call->get(1));
      }
      break;
    default:
      break;
    }
  }
}
Пример #20
0
static IRTemp for_sg__newIRTemp_cb ( IRType ty, void* opaque )
{
   PCEnv* pce = (PCEnv*)opaque;
   return newTemp( pce, ty, NonShad );
}
Пример #21
0
// 表达式
string CodeGenerator::Expr() {
    if(Tokens[CurToken].Type == String) {
        string res = newTemp("string");
        newConst("string", Tokens[CurToken].value);
        CurToken++;
        return res;
    }
    int L = CurToken, R;
    int cntBrac = 0;
    for(R = L; R < Tokens.size(); R++) {
        string val = Tokens[R].value;
        if(val == ";" || val == ")" && cntBrac == 0) break;
        if(val == "(") cntBrac++;
        if(val == ")") cntBrac--;
    }
    CurToken = R;

    map<string, int> Prior;
    Prior["("] = 10, Prior[")"] = 0;
    Prior["!"] = 1;
    Prior["%"] = Prior["*"] = Prior["/"] = 2;
    Prior["+"] = Prior["-"] = 3;
    Prior[">="] = Prior["<="] = Prior[">"] = Prior["<"] = 4;
    Prior["=="] = Prior["!="] = 5;
    Prior["&&"] = 6;
    Prior["||"] = 7;

    stack<string> Num, Op;
    for(int i = L; i < R; i++) {
        string Type = CodeToString(Tokens[i]);
        string val = Tokens[i].value;
        if(Type == "number" || Type == "id") {
            if(Type == "id") Num.push(val);
            else Num.push(newConst((string)(Tokens[i].Type == Integer ? "int" : "double"), itos(Tokens[i].num)));
        } else {
            if(val == "(") {
                Op.push(val);
            } else if(val == ")") {
                while(Op.top() != "(") {
                    string op = Op.top(); Op.pop();
                    string y = Num.top(); Num.pop();
                    if(op == "!") {
                        string res = newTemp(VarTable[y].Type); Num.push(res);
                        addQuad(op, y, "$", res);
                        continue;
                    }
                    string x = Num.top(); Num.pop();
                    string res = newTemp(VarTable[x].Type); Num.push(res);
                    if(op == ">=" || op == "<=" || op == "==" || op == "!=" || op == ">" || op == "<") {
                        addQuad("J" + op, x, y, itos(CurLabel + 3));
                        addQuad("=", res, "0", res);
                        addQuad("J", "$", "$", itos(CurLabel + 2));
                        addQuad("=", res, "1", res);
                    } else {
                        addQuad(op, x, y, res);
                    }
                }
                Op.pop();
            } else {
                while(!Op.empty() && Prior[val] >= Prior[Op.top()]) {
                    string op = Op.top(); Op.pop();
                    string y = Num.top(); Num.pop();
                    if(op == "!") {
                        string res = newTemp(VarTable[y].Type); Num.push(res);
                        addQuad(op, y, "$", res);
                        continue;
                    }
                    string x = Num.top(); Num.pop();
                    string res = newTemp(VarTable[x].Type); Num.push(res);
                    if(op == ">=" || op == "<=" || op == "==" || op == "!=" || op == ">" || op == "<") {
                        addQuad("J" + op, x, y, itos(CurLabel + 3));
                        addQuad("=", res, "0", res);
                        addQuad("J", "$", "$", itos(CurLabel + 2));
                        addQuad("=", res, "1", res);
                    } else {
                        addQuad(op, x, y, res);
                    }
                }
                Op.push(val);
            }
        }
    }
    while(!Op.empty()) {
        string op = Op.top(); Op.pop();
        string y = Num.top(); Num.pop();
        if(op == "!") {
            string res = newTemp(VarTable[y].Type); Num.push(res);
            addQuad(op, y, "$", res);
            continue;
        }
        string x = Num.top(); Num.pop();
        string res = newTemp(VarTable[x].Type); Num.push(res);
        if(op == ">=" || op == "<=" || op == "==" || op == "!=" || op == ">" || op == "<") {
            addQuad("J" + op, x, y, itos(CurLabel + 3));
            addQuad("=", res, "0", res);
            addQuad("J", "$", "$", itos(CurLabel + 2));
            addQuad("=", res, "1", res);
        } else {
            addQuad(op, x, y, res);
        }
    }
    return Num.top();
}
Пример #22
0
TAC* unaryOp_tac(tacType_t type, TAC* op)
{

	return append(op, tac(type, newTemp(), op->destination, NULL));
}
Пример #23
0
TAC* call_tac(TAC* funcId, TAC* args)
{
	return append(append(args, funcId), tac(TAC_CALL, newTemp(), funcId->destination, NULL));
}
Пример #24
0
TAC* pointer_declaration_tac(TAC* id, TAC* literal)
{
	linkedList_t* temp = newTemp();

	return tac(TAC_MOVE_I,temp,literal->destination,NULL);
}
Пример #25
0
TAC* generateCode(AST* ast)
{
	if(ast == NULL)
		return NULL;

	TAC* childTac[4];
	childTac[0] = generateCode(ast->child[0]);
	childTac[1] = generateCode(ast->child[1]);
	childTac[2] = generateCode(ast->child[2]);
	childTac[3] = generateCode(ast->child[3]);
	
	TAC* result;

	switch(ast->node_type)
	{
		case LITERAL: result = tac(TAC_SYMBOL, ast->node, NULL, NULL); break;
		case IDENTIFIER: result = tac(TAC_SYMBOL, ast->node, NULL, NULL); break;
		
		case ADDITION: result = binaryOp_tac(TAC_ADD, childTac); break;
		case SUBTRACTION: result = binaryOp_tac(TAC_SUB, childTac); break;
		case MULTIPLICATION: result = binaryOp_tac(TAC_MUL, childTac); break;
		case DIVISION: result = binaryOp_tac(TAC_DIV, childTac); break;
		case LESSERTHAN: result = binaryOp_tac(TAC_LESS, childTac); break;
		case GREATERTHAN: result = binaryOp_tac(TAC_GREATER, childTac); break;
		case LESSEREQUAL: result = binaryOp_tac(TAC_LESS_EQUAL, childTac); break;
		case GREATEREQUAL: result = binaryOp_tac(TAC_GREATER_EQUAL, childTac); break;
		case EQUAL: result = binaryOp_tac(TAC_EQUAL, childTac); break;
		case NOTEQUAL: result = binaryOp_tac(TAC_NOT_EQUAL, childTac); break;
		case AND: result = binaryOp_tac(TAC_AND, childTac); break;
		case OR: result = binaryOp_tac(TAC_OR, childTac); break;
		
		case REF: result = tac(TAC_REF, newTemp(), childTac[0]->destination, NULL); break;
		case DEREF: result = tac(TAC_DEREF, newTemp(), childTac[0]->destination, NULL); break;
		
		case IFTHEN:
		case IFTHENELSE:
			result = ifZero_tac(childTac[0], childTac[1], childTac[2]);
			break;
			
		case LOOP: result = loop_tac(childTac[0], childTac[1]); break;

		case ARRAYACCESS: result = tac(TAC_ARRAYACCESS, childTac[0]->destination, childTac[1]->destination, NULL); break;

		case ASSIGNMENT: result = assignment_tac(childTac[0], childTac[1]); break;
		
		case FUNCTIONCALL: result = call_tac(childTac[0], childTac[1]); break;

		case ARGUMENTLIST: result = args_tac(childTac); break;

		case ELEMENTLIST: result = output_args_tac(childTac); break;

		case RETURN: result = return_tac(childTac[0]); break;

		case DECLARATION: result = declaration_tac(childTac[1], childTac[2]); break;
		case ARRAYDECLARATION: result = array_declaration_tac(childTac[1], ast->child[3]); break;
		case POINTERDECLARATION: result = pointer_declaration_tac(childTac[1],childTac[2]); break;

		case INPUT: result = tac(TAC_READ, NULL, childTac[0]->destination, NULL); break;
		case OUTPUT: result = output_tac(childTac[0]); break;

		case FUNCTIONDEFINITION: result = fun_def_tac(ast->child[0]->child[1]->node, childTac[0], childTac[1], childTac[2]); break;
		
		case PARAMETERLIST: result = get_args_tac(childTac); break;
		
		case BLOCK:
		case COMMANDLIST:
		case PROGRAM:
		default:
			result = append(append(append(childTac[0], childTac[1]), childTac[2]), childTac[3]);
			break;
	}
	return result;
}
Пример #26
0
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;
}