compiler/resolution/functionResolution.cpp
//
// Insert return temps for functions that return values if no
// variable captures the result. If the value is a sync/single var or a
// reference to a sync/single var, pass it through the _statementLevelSymbol
// function to get the semantics of reading a sync/single var. If the value
// is an iterator pass it through another overload of
// _statementLevelSymbol to iterate through it for side effects.
// Note that we do not do this for --minimal-modules compilation
// because we do not support sync/singles for minimal modules.
//
Insert return temps for functions that return values if no
variable captures the result. If the value is a sync/single var or a
reference to a sync/single var, pass it through the _statementLevelSymbol
function to get the semantics of reading a sync/single var. If the value
is an iterator pass it through another overload of
_statementLevelSymbol to iterate through it for side effects.
Note that we do not do this for --minimal-modules compilation
because we do not support sync/singles for minimal modules.
Insert return temps for functions that return values if no variable captures the result . If the value is a sync / single var or a reference to a sync / single var pass it through the _statementLevelSymbol function to get the semantics of reading a sync / single var . If the value is an iterator pass it through another overload of _statementLevelSymbol to iterate through it for side effects . Note that we do not do this for -- minimal - modules compilation because we do not support sync / singles for minimal modules .
forv_Vec(CallExpr, call, gCallExprs) {
    if (call->inTree()) {
      if (call->list == NULL && isForallRecIterHelper(call))
        continue;
      if (FnSymbol* fn = call->resolvedOrVirtualFunction()) {
        if (fn->retType != dtVoid && fn->retTag != RET_TYPE) {
          ContextCallExpr* contextCall = toContextCallExpr(call->parentExpr);
          Expr*            contextCallOrCall; 
          if (contextCall) {
            contextCallOrCall = contextCall;
            if (call != getDesignatedCall(contextCall))
              continue;
          } else {
            contextCallOrCall = call;
          }
          Expr* parent = contextCallOrCall->parentExpr;
          if (isForallIterExpr(contextCallOrCall))
            continue; 
          if (!isCallExpr(parent) && !isDefExpr(parent)) { 
            SET_LINENO(call); 
            VarSymbol* tmp = newTemp("_return_tmp_", fn->retType);
            DefExpr*   def = new DefExpr(tmp);
            if (isUserDefinedRecord(fn->retType) == true)
              tmp->addFlag(FLAG_INSERT_AUTO_DESTROY);
            contextCallOrCall->insertBefore(def);
            if (fMinimalModules == false) {
              if ((fn->retType->getValType() &&
                   (isSyncType(fn->retType->getValType()) ||
                    isSingleType(fn->retType->getValType())))         ||
                  isSyncType(fn->retType)                             ||
                  isSingleType(fn->retType)                           ||
                  fn->isIterator()) {
                CallExpr* sls = new CallExpr("_statementLevelSymbol", tmp);
                contextCallOrCall->insertBefore(sls);
                reset_ast_loc(sls, call);
                resolveCallAndCallee(sls);
              }
            }
            if (isTypeExpr(contextCallOrCall)) {
              tmp->addFlag(FLAG_MAYBE_TYPE);
              tmp->addFlag(FLAG_MAYBE_PARAM);
            }
            def->insertAfter(new CallExpr(PRIM_MOVE,
                                          tmp,
                                          contextCallOrCall->remove()));
          }
        }
      }
    }
  }
forv_Vec ( CallExpr , call , gCallExprs ) { if ( call -> inTree ( ) ) { if ( call -> list == NULL && isForallRecIterHelper ( call ) ) continue ; if ( FnSymbol * fn = call -> resolvedOrVirtualFunction ( ) ) { if ( fn -> retType != dtVoid && fn -> retTag != RET_TYPE ) { ContextCallExpr * contextCall = toContextCallExpr ( call -> parentExpr ) ; Expr * contextCallOrCall ; if ( contextCall ) { contextCallOrCall = contextCall ; if ( call != getDesignatedCall ( contextCall ) ) continue ; } else { contextCallOrCall = call ; } Expr * parent = contextCallOrCall -> parentExpr ; if ( isForallIterExpr ( contextCallOrCall ) ) continue ; if ( ! isCallExpr ( parent ) && ! isDefExpr ( parent ) ) { SET_LINENO ( call ) ; VarSymbol * tmp = newTemp ( " " , fn -> retType ) ; DefExpr * def = new DefExpr ( tmp ) ; if ( isUserDefinedRecord ( fn -> retType ) == true ) tmp -> addFlag ( FLAG_INSERT_AUTO_DESTROY ) ; contextCallOrCall -> insertBefore ( def ) ; if ( fMinimalModules == false ) { if ( ( fn -> retType -> getValType ( ) && ( isSyncType ( fn -> retType -> getValType ( ) ) || isSingleType ( fn -> retType -> getValType ( ) ) ) ) || isSyncType ( fn -> retType ) || isSingleType ( fn -> retType ) || fn -> isIterator ( ) ) { CallExpr * sls = new CallExpr ( " " , tmp ) ; contextCallOrCall -> insertBefore ( sls ) ; reset_ast_loc ( sls , call ) ; resolveCallAndCallee ( sls ) ; } } if ( isTypeExpr ( contextCallOrCall ) ) { tmp -> addFlag ( FLAG_MAYBE_TYPE ) ; tmp -> addFlag ( FLAG_MAYBE_PARAM ) ; } def -> insertAfter ( new CallExpr ( PRIM_MOVE , tmp , contextCallOrCall -> remove ( ) ) ) ; } } } } }
Insert return temps for functions that return values if no
variable captures the result.
Insert return temps for functions that return values if no variable captures the result .
// insert before, remove it // Only consider the designated call; the other // call need not be considered by this transformation. // not really a top-level expression // no use // TODO: reset_ast_loc() below?