Пример #1
0
static ArgSymbol* addOutErrorArg(FnSymbol* fn)
{
  ArgSymbol* outError = NULL;

  SET_LINENO(fn);

  outError = new ArgSymbol(INTENT_REF, "error_out", dtError);
  outError->addFlag(FLAG_ERROR_VARIABLE);
  fn->insertFormalAtTail(outError);

  return outError;
}
Пример #2
0
void ReturnByRef::insertAssignmentToFormal(FnSymbol* fn, ArgSymbol* formal)
{
  Expr*     returnPrim  = fn->body->body.tail;

  SET_LINENO(returnPrim);

  CallExpr* returnCall  = toCallExpr(returnPrim);
  Expr*     returnValue = returnCall->get(1)->remove();
  CallExpr* moveExpr    = new CallExpr(PRIM_MOVE, formal, returnValue);

  returnPrim->insertBefore(moveExpr);
}
Пример #3
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)));
        }
      }
    }
  }
Пример #4
0
ArgSymbol* ReturnByRef::addFormal(FnSymbol* fn)
{
  SET_LINENO(fn);

  Type*          type    = fn->retType;
  AggregateType* refType = type->refType;
  IntentTag      intent  = blankIntentForType(refType);
  ArgSymbol*     formal  = new ArgSymbol(intent, "_retArg", refType);

  fn->insertFormalAtTail(formal);

  return formal;
}
Пример #5
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));
}
Пример #6
0
//
// Do a breadth first search starting from functions generated for local blocks
// for all function calls in each level of the search, if they directly cause
// communication, add a local temp that isn't wide. If it is a resolved call,
// meaning that it isn't a primitive or external function, clone it and add it
// to the queue of functions to handle at the next iteration of the BFS.
//
static void handleLocalBlocks() {
  Map<FnSymbol*,FnSymbol*> cache; // cache of localized functions
  Vec<BlockStmt*> queue; // queue of blocks to localize

  forv_Vec(BlockStmt, block, gBlockStmts) {
    if (block->parentSymbol) {
      // NOAKES 2014/11/25 Transitional.  Avoid calling blockInfoGet()
      if (block->isLoopStmt() == true) {

      } else if (block->blockInfoGet()) {
        if (block->blockInfoGet()->isPrimitive(PRIM_BLOCK_LOCAL)) {
          queue.add(block);
        }
      }
    }
  }

  forv_Vec(BlockStmt, block, queue) {
    std::vector<CallExpr*> calls;
    collectCallExprs(block, calls);
    for_vector(CallExpr, call, calls) {
      localizeCall(call);
      if (FnSymbol* fn = call->isResolved()) {
        SET_LINENO(fn);
        if (FnSymbol* alreadyLocal = cache.get(fn)) {
          call->baseExpr->replace(new SymExpr(alreadyLocal));
        } else {
          if (!fn->hasFlag(FLAG_EXTERN)) {
            FnSymbol* local = fn->copy();
            local->addFlag(FLAG_LOCAL_FN);
            local->name = astr("_local_", fn->name);
            local->cname = astr("_local_", fn->cname);
            fn->defPoint->insertBefore(new DefExpr(local));
            call->baseExpr->replace(new SymExpr(local));
            queue.add(local->body);
            cache.put(fn, local);
            cache.put(local, local); // to handle recursion
            if (local->retType->symbol->hasFlag(FLAG_WIDE_REF)) {
              CallExpr* ret = toCallExpr(local->body->body.tail);
              INT_ASSERT(ret && ret->isPrimitive(PRIM_RETURN));
              // Capture the return expression in a local temp.
              insertLocalTemp(ret->get(1));
              local->retType = ret->get(1)->typeInfo();
            }
          }
        }
      }
    }
Пример #7
0
ArgSymbol* ReturnByRef::addFormal(FnSymbol* fn)
{
  SET_LINENO(fn);

  Type*          type    = fn->retType;
  AggregateType* refType = type->refType;
  IntentTag      intent  = blankIntentForType(refType);
  // Note: other code does strcmps against the name _retArg
  ArgSymbol*     formal  = new ArgSymbol(intent, "_retArg", refType);
  formal->addFlag(FLAG_RETARG);

  fn->insertFormalAtTail(formal);
  fn->addFlag(FLAG_FN_RETARG);

  return formal;
}
Пример #8
0
static void lowerErrorHandling(FnSymbol* fn)
{
  ArgSymbol*   outError = NULL;
  LabelSymbol* epilogue = NULL;

  if (fn->throwsError()) {
    SET_LINENO(fn);

    outError = addOutErrorArg(fn);
    epilogue = fn->getOrCreateEpilogueLabel();
    INT_ASSERT(epilogue); // throws requires an epilogue
  }

  ErrorHandlingVisitor visitor = ErrorHandlingVisitor(outError, epilogue);
  fn->accept(&visitor);
}
//
// inlines the function called by 'call' at that call site
//
static void
inlineCall(FnSymbol* fn, CallExpr* call) {
  INT_ASSERT(call->isResolved() == fn);
  SET_LINENO(call);

  Expr* stmt = call->getStmtExpr();

  //
  // calculate a map from actual symbols to formal symbols
  //
  SymbolMap map;
  for_formals_actuals(formal, actual, call) {
    SymExpr* se = toSymExpr(actual);
    INT_ASSERT(se);
    map.put(formal, se->var);
  }
Пример #10
0
 forv_Vec(FnSymbol, fn, gFnSymbols) {
   SET_LINENO(fn);
   if (!fn->hasFlag(FLAG_TYPE_CONSTRUCTOR) &&
       !fn->hasFlag(FLAG_DEFAULT_CONSTRUCTOR))
     fixup_array_formals(fn);
   if (fn->hasFlag(FLAG_LOCALE_MODEL_ALLOC)) {
     INT_ASSERT(gChplHereAlloc==NULL);
     gChplHereAlloc = fn;
   }
   if (fn->hasFlag(FLAG_LOCALE_MODEL_FREE)) {
     INT_ASSERT(gChplHereFree==NULL);
     gChplHereFree = fn;
   }
   clone_parameterized_primitive_methods(fn);
   fixup_query_formals(fn);
   change_method_into_constructor(fn);
 }
Пример #11
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));
    }
  }
Пример #12
0
//
// Consider a function that takes a formal of type Record by const ref
// and that returns that value from the function.  The compiler inserts
// a PRIM_MOVE operation.
//
// This work-around inserts an autoCopy to compensate
//
void ReturnByRef::updateAssignmentsFromRefArgToValue(FnSymbol* fn)
{
  std::vector<CallExpr*> callExprs;

  collectCallExprs(fn, callExprs);

  for (size_t i = 0; i < callExprs.size(); i++)
  {
    CallExpr* move = callExprs[i];

    if (move->isPrimitive(PRIM_MOVE) == true)
    {
      SymExpr* lhs = toSymExpr(move->get(1));
      SymExpr* rhs = toSymExpr(move->get(2));

      if (lhs != NULL && rhs != NULL)
      {
        VarSymbol* symLhs = toVarSymbol(lhs->symbol());
        ArgSymbol* symRhs = toArgSymbol(rhs->symbol());

        if (symLhs != NULL && symRhs != NULL)
        {
          if (isUserDefinedRecord(symLhs->type) == true &&
              symRhs->type                      == symLhs->type)
          {
            if (symLhs->hasFlag(FLAG_ARG_THIS) == false &&
                (symRhs->intent == INTENT_REF ||
                 symRhs->intent == INTENT_CONST_REF))
            {
              SET_LINENO(move);

              CallExpr* autoCopy = NULL;

              rhs->remove();
              autoCopy = new CallExpr(autoCopyMap.get(symRhs->type), rhs);
              move->insertAtTail(autoCopy);
            }
          }
        }
      }
    }
  }
}
Пример #13
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)));
        }
      }
    }
  }
Пример #14
0
Expr* postFold(Expr* expr) {
  SET_LINENO(expr);

  Expr* retval = expr;

  INT_ASSERT(expr->inTree());

  if (CallExpr* call = toCallExpr(expr)) {
    if (call->isResolved() == true) {
      retval = postFoldNormal(call);

    } else if (call->isPrimitive() == true) {
      retval = postFoldPrimop(call);
    }

  } else if (SymExpr* sym = toSymExpr(expr)) {
    retval = postFoldSymExpr(sym);
  }

  return retval;
}
Пример #15
0
void buildDefaultFunctions() {
  build_chpl_entry_points();

  SET_LINENO(rootModule); // todo - remove reset_ast_loc() calls below?

  std::vector<BaseAST*> asts;
  collect_asts(rootModule, asts);
  for_vector(BaseAST, ast, asts) {
    if (TypeSymbol* type = toTypeSymbol(ast)) {
      // Here we build default functions that are always generated (even when
      // the type symbol has FLAG_NO_DEFAULT_FUNCTIONS attached).
      if (AggregateType* ct = toAggregateType(type->type)) {
        buildFieldAccessorFunctions(ct);

        if (!ct->symbol->hasFlag(FLAG_REF))
          buildDefaultDestructor(ct);
        // Classes should use the nil:<type> _defaultOf method unless they
        // do not inherit from object.  For those types and records, call
        // we need a more complicated _defaultOf method generated by the
        // compiler
        if (!ct->isClass() || ct->symbol->hasFlag(FLAG_NO_OBJECT))
          build_record_init_function(ct);
      }

      if (type->hasFlag(FLAG_NO_DEFAULT_FUNCTIONS))
        continue;

      // Here we build default functions that respect the "no default
      // functions" pragma.
      if (AggregateType* ct = toAggregateType(type->type))
      {
        buildDefaultReadWriteFunctions(ct);

        if (isRecord(ct)) {
          if (!isRecordWrappedType(ct)) {
            build_record_equality_function(ct);
            build_record_inequality_function(ct);
          }
          build_record_assignment_function(ct);
          build_record_cast_function(ct);
          build_record_copy_function(ct);
          build_record_hash_function(ct);
        }
        if (isUnion(ct))
          build_union_assignment_function(ct);
      }
      else if (EnumType* et = toEnumType(type->type)) {
        //buildDefaultReadFunction(et);
        buildStringCastFunction(et);

        build_enum_cast_function(et);
        build_enum_assignment_function(et);
        build_enum_first_function(et);
        build_enum_enumerate_function(et);
      }
      else
      {
        // The type is a simple type.

        // Other simple types are handled explicitly in the module code.
        // But to avoid putting a catch-all case there to implement assignment
        // for extern types that are simple (as far as we can tell), we build
        // definitions for those assignments here.
        if (type->hasFlag(FLAG_EXTERN)) {
          build_extern_init_function(type->type);
          build_extern_assignment_function(type->type);
        }
      }
    }
  }
}
Пример #16
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;
    }
  }
}
Пример #17
0
void ReturnByRef::updateAssignmentsFromRefTypeToValue(FnSymbol* fn)
{
  std::vector<CallExpr*> callExprs;

  collectCallExprs(fn, callExprs);

  Map<Symbol*,Vec<SymExpr*>*> defMap;
  Map<Symbol*,Vec<SymExpr*>*> useMap;
  buildDefUseMaps(fn, defMap, useMap);

  for (size_t i = 0; i < callExprs.size(); i++)
  {
    CallExpr* move = callExprs[i];

    if (move->isPrimitive(PRIM_MOVE) == true)
    {
      SymExpr*  symLhs  = toSymExpr (move->get(1));
      CallExpr* callRhs = toCallExpr(move->get(2));

      if (symLhs && callRhs && callRhs->isPrimitive(PRIM_DEREF))
      {
        VarSymbol* varLhs = toVarSymbol(symLhs->symbol());
        SymExpr*   symRhs = toSymExpr(callRhs->get(1));
        VarSymbol* varRhs = toVarSymbol(symRhs->symbol());

        // MPF 2016-10-02: It seems to me that this code should also handle the
        // case that symRhs is an ArgSymbol, but adding that caused problems
        // in the handling of out argument intents.

        if (varLhs != NULL && varRhs != NULL)
        {
          if (isUserDefinedRecord(varLhs->type) == true &&
              varRhs->type                      == varLhs->type->refType)
          {

            // HARSHBARGER 2015-12-11:
            // `init_untyped_var` in the `normalize` pass may insert an
            // initCopy, which means that we should not insert an autocopy
            // for that same variable.
            bool initCopied = false;
            for_uses(use, useMap, varLhs) {
              if (CallExpr* call = toCallExpr(use->parentExpr)) {
                if (FnSymbol* parentFn = call->isResolved()) {
                  if (parentFn->hasFlag(FLAG_INIT_COPY_FN)) {
                    initCopied = true;
                    break;
                  }
                }
              }
            }

            if (!initCopied) {
              SET_LINENO(move);

              SymExpr*  lhsCopy0 = symLhs->copy();
              SymExpr*  lhsCopy1 = symLhs->copy();
              FnSymbol* autoCopy = autoCopyMap.get(varLhs->type);
              CallExpr* copyExpr = new CallExpr(autoCopy, lhsCopy0);
              CallExpr* moveExpr = new CallExpr(PRIM_MOVE,lhsCopy1, copyExpr);

              move->insertAfter(moveExpr);
            }
          }
        }
      }
Пример #18
0
void AutoDestroyScope::variablesDestroy(Expr*      refStmt,
                                        VarSymbol* excludeVar,
                                        std::set<VarSymbol*>* ignored) const {
  // Handle the primary locals
  if (mLocalsHandled == false) {
    Expr*  insertBeforeStmt = refStmt;
    Expr*  noop             = NULL;
    size_t count            = mLocalsAndDefers.size();

    // If this is a simple nested block, insert after the final stmt
    // But always insert the destruction calls in reverse declaration order.
    // Do not get tricked by sequences of unreachable code
    if (refStmt->next == NULL) {
      if (mParent != NULL && isGotoStmt(refStmt) == false) {
        SET_LINENO(refStmt);
        // Add a PRIM_NOOP to insert before
        noop = new CallExpr(PRIM_NOOP);
        refStmt->insertAfter(noop);
        insertBeforeStmt = noop;
      }
    }

    for (size_t i = 1; i <= count; i++) {
      BaseAST*  localOrDefer = mLocalsAndDefers[count - i];
      VarSymbol* var = toVarSymbol(localOrDefer);
      DeferStmt* defer = toDeferStmt(localOrDefer);
      // This code only handles VarSymbols and DeferStmts.
      // It handles both in one vector because the order
      // of interleaving matters.
      INT_ASSERT(var || defer);

      if (var != NULL && var != excludeVar &&
          (ignored == NULL || ignored->count(var) == 0)) {
        if (FnSymbol* autoDestroyFn = autoDestroyMap.get(var->type)) {
          SET_LINENO(var);

          INT_ASSERT(autoDestroyFn->hasFlag(FLAG_AUTO_DESTROY_FN));

          CallExpr* autoDestroy = new CallExpr(autoDestroyFn, var);

          insertBeforeStmt->insertBefore(autoDestroy);
        }
      }

      if (defer != NULL) {
        SET_LINENO(defer);
        BlockStmt* deferBlockCopy = defer->body()->copy();
        insertBeforeStmt->insertBefore(deferBlockCopy);
        deferBlockCopy->flattenAndRemove();
      }
    }

    // remove the PRIM_NOOP if we added one.
    if (noop != NULL)
      noop->remove();
  }

  // Handle the formal temps
  if (isReturnStmt(refStmt) == true) {
    size_t count = mFormalTemps.size();

    for (size_t i = 1; i <= count; i++) {
      VarSymbol* var = mFormalTemps[count - i];

      if (FnSymbol* autoDestroyFn = autoDestroyMap.get(var->type)) {
        SET_LINENO(var);

        refStmt->insertBefore(new CallExpr(autoDestroyFn, var));
      }
    }
  }
}
Пример #19
0
//
// Attempts to replace references with the variables the references point to,
// provided the references have a single definition.
//
// For example:
// var foo : int;
// ref A : int;
// (move A (addr-of foo))
//
// (move B (deref A))     --->    (move B foo)
//
void
eliminateSingleAssignmentReference(Map<Symbol*,Vec<SymExpr*>*>& defMap,
                                   Map<Symbol*,Vec<SymExpr*>*>& useMap,
                                   Symbol* var) {
  if (CallExpr* move = findRefDef(defMap, var)) {
    if (CallExpr* rhs = toCallExpr(move->get(2))) {
      if (rhs->isPrimitive(PRIM_ADDR_OF) || rhs->isPrimitive(PRIM_SET_REFERENCE)) {
        bool stillAlive = false;
        for_uses(se, useMap, var) {
          CallExpr* parent = toCallExpr(se->parentExpr);
          SET_LINENO(se);
          if (parent && (parent->isPrimitive(PRIM_DEREF) || isDerefMove(parent))) {
            SymExpr* se = toSymExpr(rhs->get(1)->copy());
            INT_ASSERT(se);
            Expr* toReplace = parent;
            if (isMoveOrAssign(parent)) {
              toReplace = parent->get(2);
            }
            toReplace->replace(se);
            ++s_ref_repl_count;
            addUse(useMap, se);
          } else if (parent &&
                     (parent->isPrimitive(PRIM_GET_MEMBER_VALUE) ||
                      parent->isPrimitive(PRIM_GET_MEMBER) ||
                      parent->isPrimitive(PRIM_GET_MEMBER_VALUE) ||
                      parent->isPrimitive(PRIM_GET_MEMBER))) {
            SymExpr* se = toSymExpr(rhs->get(1)->copy());
            INT_ASSERT(se);
            parent->get(1)->replace(se);
            ++s_ref_repl_count;
            addUse(useMap, se);
          }
          else if (parent && (parent->isPrimitive(PRIM_MOVE) || parent->isPrimitive(PRIM_SET_REFERENCE))) {
            CallExpr* rhsCopy = rhs->copy();
            if (parent->isPrimitive(PRIM_SET_REFERENCE)) {
              // Essentially a pointer copy like a (move refA refB)
              parent = toCallExpr(parent->parentExpr);
              INT_ASSERT(parent && isMoveOrAssign(parent));
            }
            parent->get(2)->replace(rhsCopy);
            ++s_ref_repl_count;
            SymExpr* se = toSymExpr(rhsCopy->get(1));
            INT_ASSERT(se);
            addUse(useMap, se);
            // BHARSH TODO: Is it possible to handle the following case safely
            // for PRIM_ASSIGN?
            //
            // ref i_foo : T;
            // (move i_foo (set reference bar))
            // (= call_tmp i_foo)
            //
            // Should that turn into (= call_tmp bar)?
          } else if (parent && parent->isPrimitive(PRIM_ASSIGN) && parent->get(1) == se) {
            // for_defs should handle this case
          } else if (parent && parent->isResolved()) {
            stillAlive = true;
            // TODO -- a reference argument can be passed directly
          } else {
            stillAlive = true;
          }
        }
        for_defs(se, defMap, var) {
          CallExpr* parent = toCallExpr(se->parentExpr);
          SET_LINENO(se);
          if (parent == move)
            continue;
          if (parent && isMoveOrAssign(parent)) {
            SymExpr* se = toSymExpr(rhs->get(1)->copy());
            INT_ASSERT(se);
            parent->get(1)->replace(se);
            ++s_ref_repl_count;
            addDef(defMap, se);
          } else
            stillAlive = true;
        }
        if (!stillAlive) {
          var->defPoint->remove();
          Vec<SymExpr*>* defs = defMap.get(var);
          if (defs == NULL) {
            INT_FATAL(var, "Expected var to be defined");
          }
          // Remove the first definition from the AST.
          defs->v[0]->getStmtExpr()->remove();
        }
      } else if (rhs->isPrimitive(PRIM_GET_MEMBER) ||
Пример #20
0
IpeCallExpr* IpeProcedure::resolve(SymExpr*            procSymExpr,
                                   std::vector<Expr*>& actuals) const
{
  IpeMethod*   matchMethod = NULL;
  int          matchIndex  =    0;
  int          matchCount  =    0;

  IpeCallExpr* retval      =    0;

  for (size_t i = 0; i < mMethods.size(); i++)
  {
    mMethods[i]->resolveFormals();
    mMethods[i]->resolveReturnType();
  }

  for (size_t i = 0; i < mMethods.size(); i++)
  {
    if (mMethods[i]->isExactMatch(actuals) == true)
    {
      matchMethod = mMethods[i];
      matchIndex  = i;
      matchCount  = matchCount + 1;
    }
  }

  if (matchCount == 1)
  {
    SET_LINENO(procSymExpr);

    retval = new IpeCallExpr(procSymExpr->copy(), matchMethod->typeGet(), mVersion, matchIndex);

    for (size_t i = 0; i < actuals.size(); i++)
    {
      ArgSymbol* formal      = matchMethod->formalGet(i);
      bool       formalIsRef = formal->intent & INTENT_REF;

      Expr*      actual      = actuals[i];
      bool       actualIsRef = isActualRef(actual);

      Expr*      actualCopy  = actual;
      Expr*      actualNew   = NULL;

      if      (formalIsRef == false && actualIsRef == false)
        actualNew = actualCopy;

      else if (formalIsRef == false && actualIsRef ==  true)
        INT_ASSERT(false);

      else if (formalIsRef == true  && actualIsRef == false)
        actualNew = new IpeCallExpr(PRIM_ADDR_OF, actualCopy);

      else if (formalIsRef == true  && actualIsRef ==  true)
        INT_ASSERT(false);

      retval->argList.insertAtTail(actualNew);
    }
  }
  else
  {
    AstDumpToNode logger(stdout, 6);

    printf("   IpeProcedure::resolve(SymExpr*, actuals[])\n");
    printf("   matchCount = %d\n", matchCount);
    printf("\n\n");

    printf("      ");
    procSymExpr->accept(&logger);
    printf("\n");

    for (size_t i = 0; i < actuals.size(); i++)
    {
      printf("   %d: ", (int) i);
      actuals[i]->accept(&logger);
      printf("\n");
    }

    INT_ASSERT(false);
  }

  return retval;
}