コード例 #1
0
ファイル: inferConstRefs.cpp プロジェクト: rlugojr/chapel
  // Build a map from Symbols to ConstInfo. This is somewhat like
  // buildDefUseMaps, except we don't want to put defs and uses in different
  // lists (for simplicity).
  //
  // TODO: Can we use for_SymbolSymExprs here instead?
  forv_Vec(SymExpr, se, gSymExprs) {
    if (!(isVarSymbol(se->symbol()) || isArgSymbol(se->symbol()))) continue;
    // TODO: BHARSH: Skip classes for now. Not sure how to deal with aliasing
    if (!se->isRef() && isClass(se->typeInfo())) continue;

    ConstInfo* info = NULL;
    ConstInfoIter it = infoMap.find(se->symbol());
    if (it == infoMap.end()) {
      info = new ConstInfo(se->symbol());
      infoMap[se->symbol()] = info;
    } else {
      info = it->second;
    }

    info->todo.push_back(se);
  }
コード例 #2
0
ファイル: FnSymbol.cpp プロジェクト: DawidvC/chapel
void FnSymbol::verify() {
  Symbol::verify();

  if (astTag != E_FnSymbol) {
    INT_FATAL(this, "Bad FnSymbol::astTag");
  }

  if (_this && _this->defPoint->parentSymbol != this)
    INT_FATAL(this, "Each method must contain a 'this' declaration.");

  if (normalized) {
    CallExpr* last = toCallExpr(body->body.last());

    if (last == NULL || last->isPrimitive(PRIM_RETURN) == false) {
      INT_FATAL(this, "Last statement in normalized function is not a return");
    }
  }

  if (formals.parent != this) {
    INT_FATAL(this, "Bad AList::parent in FnSymbol");
  }

  if (where && where->parentSymbol != this) {
    INT_FATAL(this, "Bad FnSymbol::where::parentSymbol");
  }

  if (retExprType && retExprType->parentSymbol != this) {
    INT_FATAL(this, "Bad FnSymbol::retExprType::parentSymbol");
  }

  if (body && body->parentSymbol != this) {
    INT_FATAL(this, "Bad FnSymbol::body::parentSymbol");
  }

  for_alist(fExpr, formals) {
    DefExpr* argDef = toDefExpr(fExpr);

    INT_ASSERT(argDef);
    INT_ASSERT(isArgSymbol(argDef->sym));
  }
コード例 #3
0
ファイル: foralls.cpp プロジェクト: rchyena/chapel
void ForallIntents::verifyFI(BlockStmt* parentB) {
  Expr* parentE = (Expr*)parentB;
  int nv = numVars();
  INT_ASSERT((int)(fiVars.size())   == nv);
  INT_ASSERT((int)(fIntents.size()) == nv);
  INT_ASSERT((int)(riSpecs.size())  == nv);

  for (int i = 0; i < nv; i++) {
    Expr* fiVar = fiVars[i];
    if (SymExpr* fiVarSE = toSymExpr(fiVar)) {
      INT_ASSERT(isVarSymbol(fiVarSE->symbol()) ||
                 isArgSymbol(fiVarSE->symbol()));  // no modules, fns, etc.
    } else {
      // fiVars[i] is either resolved or unresolved sym expr; never NULL.
      INT_ASSERT(isUnresolvedSymExpr(fiVar));
      // These should be resolved during scopeResolve.
      INT_ASSERT(!normalized);
    }
    verifyNotOnList(fiVar);
    INT_ASSERT(fiVar->parentExpr == parentE);

    Expr* ri = riSpecs[i];
    INT_ASSERT(isReduce(i) == !!ri);
    if (ri) {
      // ri can be UnresolvedSymExpr, SymExpr, CallExpr, ... (?)
      verifyNotOnList(ri);
      INT_ASSERT(ri->parentExpr == parentE);
    }
  }

  INT_ASSERT(!iterRec || iterRec->parentExpr == parentE);
  INT_ASSERT(!leadIdx || leadIdx->parentExpr == parentE);
  INT_ASSERT(!leadIdxCopy || leadIdxCopy->parentExpr == parentE);
  verifyNotOnList(iterRec);
  verifyNotOnList(leadIdx);
  verifyNotOnList(leadIdxCopy);

  // ForallIntents are gone during resolve().
  INT_ASSERT(!resolved);
}
コード例 #4
0
//
// Functions have an informal epilogue defined by code that
//
//   1) appears after a common "return label" (if present)
//   2) copies values to out/in-out formals
//
// We must      destroy the primaries before (1).
// We choose to destroy the primaries before (2).
//
// This code detects the start of (2)
//
bool AutoDestroyScope::handlingFormalTemps(const Expr* stmt) const {
  bool retval = false;

  if (mLocalsHandled == false) {
    if (const CallExpr* call = toConstCallExpr(stmt)) {
      if (FnSymbol* fn = call->resolvedFunction()) {
        if (fn->hasFlag(FLAG_ASSIGNOP) == true && call->numActuals() == 2) {
          SymExpr* lhs = toSymExpr(call->get(1));
          SymExpr* rhs = toSymExpr(call->get(2));

          if (lhs                                      != NULL &&
              rhs                                      != NULL &&
              isArgSymbol(lhs->symbol())               == true &&
              rhs->symbol()->hasFlag(FLAG_FORMAL_TEMP) == true) {
            retval = true;
          }
        }
      }
    }
  }

  return retval;
}
コード例 #5
0
ファイル: astutil.cpp プロジェクト: deniskin82/chapel
static void collect_top_asts_internal(BaseAST* ast, Vec<BaseAST*>& asts) {
  if (!isSymbol(ast) || isArgSymbol(ast)) {
    AST_CHILDREN_CALL(ast, collect_top_asts_internal, asts);
    asts.add(ast);
  }
}
コード例 #6
0
ファイル: misc.cpp プロジェクト: DawidvC/chapel
static bool printErrorHeader(const BaseAST* ast) {
  if (!err_print) {
    if (const Expr* expr = toConstExpr(ast)) {
      Symbol* parent = expr->parentSymbol;

      if (isArgSymbol(parent))
        parent = parent->defPoint->parentSymbol;

      FnSymbol* fn = toFnSymbol(parent);

      fn = findNonTaskCaller(fn);

      if (fn && fn != err_fn) {
        err_fn = fn;

        while ((fn = toFnSymbol(err_fn->defPoint->parentSymbol))) {
          if (fn == fn->getModule()->initFn) {
            break;
          }

          err_fn = fn;
        }

        // If the function is compiler-generated, or inlined, or doesn't match
        // the error function and line number, nothing is printed.
        if (err_fn->getModule()->initFn != err_fn     &&
            !err_fn->hasFlag(FLAG_COMPILER_GENERATED) &&
            err_fn->linenum()) {
          bool suppress = false;

          // Initializer might be inlined
          if (err_fn->hasFlag(FLAG_INLINE) == true) {
            suppress = (strcmp(err_fn->name, "init") != 0) ? true : false;
          }

          if (suppress == false) {
            fprintf(stderr,
                    "%s:%d: In ",
                    cleanFilename(err_fn),
                    err_fn->linenum());

            if (strncmp(err_fn->name, "_construct_", 11) == 0) {
              fprintf(stderr, "initializer '%s':\n", err_fn->name+11);

            } else if (strcmp(err_fn->name, "init") == 0) {
              fprintf(stderr, "initializer:\n");

            } else {
              fprintf(stderr,
                      "%s '%s':\n",
                      (err_fn->isIterator() ? "iterator" : "function"),
                      err_fn->name);
            }
          }
        }
      }
    }
  }

  bool have_ast_line = false;
  const char* filename;
  int linenum;

  if ( ast && ast->linenum() ) {
    have_ast_line = true;
    filename = cleanFilename(ast);
    linenum = ast->linenum();
  } else {
    have_ast_line = false;
    if ( !err_print && currentAstLoc.filename && currentAstLoc.lineno > 0 ) {
      // Use our best guess for the line number for user errors,
      // but don't do that for err_print (USR_PRINT) notes that don't
      // come with line numbers.
      filename = cleanFilename(currentAstLoc.filename);
      linenum = currentAstLoc.lineno;
    } else {
      filename = NULL;
      linenum = -1;
    }
  }

  bool guess = filename && !have_ast_line;

  if (filename) {
    fprintf(stderr, "%s:%d: ", filename, linenum);
  }

  if (err_print) {
    fprintf(stderr, "note: ");
  } else if (err_fatal) {
    if (err_user) {
      fprintf(stderr, "error: ");
    } else {
      fprintf(stderr, "internal error: ");
    }
  } else {
    fprintf(stderr, "warning: ");
  }

  if (!err_user) {
    if (!developer) {
      print_user_internal_error();
    }
  }
  return guess;
}
コード例 #7
0
ファイル: inferConstRefs.cpp プロジェクト: rlugojr/chapel
static bool inferRefToConst(Symbol* sym) {
  INT_ASSERT(sym->isRef());

  bool isConstRef = sym->qualType().getQual() == QUAL_CONST_REF;
  const bool wasRefToConst = sym->hasFlag(FLAG_REF_TO_CONST);

  ConstInfo* info = infoMap[sym];

  // If this ref isn't const, then it can't point to a const thing
  if (info == NULL) {
    return false;
  } else if (info->finalizedRefToConst || wasRefToConst || !isConstRef) {
    return wasRefToConst;
  }

  bool isFirstCall = false;
  if (info->alreadyCalled == false) {
    isFirstCall = true;
    info->alreadyCalled = true;
  }

  bool isRefToConst = true;

  if (isArgSymbol(sym)) {
    // Check each call and set isRefToConst to false if any actual is not a ref
    // to a const.
    FnSymbol* fn = toFnSymbol(sym->defPoint->parentSymbol);
    if (fn->hasFlag(FLAG_VIRTUAL) ||
        fn->hasFlag(FLAG_EXPORT)  ||
        fn->hasFlag(FLAG_EXTERN)) {
      // Not sure how to best handle virtual calls, so simply set false for now
      //
      // For export or extern functions, return false because we don't have
      // all the information about how the function is called.
      isRefToConst = false;
    } else {
      // Need this part to be re-entrant in case of recursive functions
      while (info->fnUses != NULL && isRefToConst) {
        SymExpr* se = info->fnUses;
        info->fnUses = se->symbolSymExprsNext;

        CallExpr* call = toCallExpr(se->parentExpr);
        INT_ASSERT(call && call->isResolved());

        Symbol* actual = toSymExpr(formal_to_actual(call, sym))->symbol();

        if (actual->isRef()) {
          // I don't think we technically need to skip if the actual is the
          // same symbol as the formal, but it makes things simpler.
          if (actual != sym && !inferRefToConst(actual)) {
            isRefToConst = false;
          }
        } else {
          // Passing a non-ref actual to a reference formal is currently
          // considered to be the same as an addr-of
          if (actual->qualType().getQual() != QUAL_CONST_VAL) {
            isRefToConst = false;
          }
        }
      }
    }
  }

  while (info->hasMore() && isRefToConst) {
    SymExpr* use = info->next();

    CallExpr* call = toCallExpr(use->parentExpr);
    if (call == NULL) continue;

    if (isMoveOrAssign(call)) {
      if (use == call->get(1)) {
        if (SymExpr* se = toSymExpr(call->get(2))) {
          if (se->isRef() && !inferRefToConst(se->symbol())) {
            isRefToConst = false;
          }
        }
        else {
          CallExpr* RHS = toCallExpr(call->get(2));
          INT_ASSERT(RHS);
          if (RHS->isPrimitive(PRIM_ADDR_OF) ||
              RHS->isPrimitive(PRIM_SET_REFERENCE)) {
            SymExpr* src = toSymExpr(RHS->get(1));
            if (src->isRef()) {
              if (!inferRefToConst(src->symbol())) {
                isRefToConst = false;
              }
            } else {
              if (src->symbol()->qualType().getQual() != QUAL_CONST_VAL) {
                isRefToConst = false;
              }
            }
          } else {
            isRefToConst = false;
          }
        }
      }
    }
    else if (call->isResolved()) {
      isRefToConst = true;
    }
    else {
      isRefToConst = isSafeRefPrimitive(use);
    }
  }

  if (isFirstCall) {
    if (isRefToConst) {
      INT_ASSERT(info->finalizedRefToConst == false);
      sym->addFlag(FLAG_REF_TO_CONST);
    }

    info->reset();
    info->finalizedRefToConst = true;
  } else if (!isRefToConst) {
    info->finalizedRefToConst = true;
  }

  return isRefToConst;
}
コード例 #8
0
static void collect_top_asts_internal_STL(BaseAST* ast, std::vector<BaseAST*>& asts) {
  if (!isSymbol(ast) || isArgSymbol(ast)) {
    AST_CHILDREN_CALL(ast, collect_top_asts_internal_STL, asts);
    asts.push_back(ast);
  }
}