forv_Vec(FnSymbol, fn, gFnSymbols)
  {
    if (VarSymbol* ret = toVarSymbol(fn->getReturnSymbol()))
    {
      // The return value of an initCopy function should not be autodestroyed.
      // Normally, the return value of a function is autoCopied, but since
      // autoCopy is typically defined in terms of initCopy, this would lead to
      // infinite recursion.  That is, the return value of initCopy must be
      // handled specially.
      if (fn->hasFlag(FLAG_INIT_COPY_FN))
        ret->removeFlag(FLAG_INSERT_AUTO_DESTROY);

      // This is just a workaround for memory management being handled specially
      // for internally reference-counted types. (sandboxing)
      TypeSymbol* ts = ret->type->symbol;
      if (ts->hasFlag(FLAG_ARRAY) ||
          ts->hasFlag(FLAG_DOMAIN))
        ret->removeFlag(FLAG_INSERT_AUTO_DESTROY);
      // Do we need to add other record-wrapped types here?  Testing will tell.

      // NOTE 1: When the value of a record field is established in a default
      // constructor, it is initialized using a MOVE.  That means that ownership
      // of that value is shared between the formal_tmp and the record field.
      // If the autodestroy flag is left on that formal temp, then it will be
      // destroyed which -- for ref-counted types -- can result in a dangling
      // reference.  So here, we look for that case and remove it.  
      if (fn->hasFlag(FLAG_DEFAULT_CONSTRUCTOR))
      {
        Map<Symbol*,Vec<SymExpr*>*> defMap;
        Map<Symbol*,Vec<SymExpr*>*> useMap;
        buildDefUseMaps(fn, defMap, useMap);

        std::vector<DefExpr*> defs;
        collectDefExprs(fn, defs);

        for_vector(DefExpr, def, defs)
        {
          if (VarSymbol* var = toVarSymbol(def->sym))
          {
            // Examine only those bearing the explicit autodestroy flag.
            if (! var->hasFlag(FLAG_INSERT_AUTO_DESTROY))
              continue;

            // Look for a use in a PRIM_SET_MEMBER where the field is a record
            // type, and remove the flag.
            // (We don't actually check that var is of record type, because
            // chpl__autoDestroy() does nothing when applied to all other types.
            for_uses(se, useMap, var)
            {
              CallExpr* call = toCallExpr(se->parentExpr);
              if (call->isPrimitive(PRIM_SET_MEMBER) &&
                  toSymExpr(call->get(3))->var == var)
                var->removeFlag(FLAG_INSERT_AUTO_DESTROY);
            }
          }
        }

        freeDefUseMaps(defMap, useMap);
      }
Exemple #2
0
void
viewFlags(BaseAST* ast) {
  if (!viewFlagsShort && !viewFlagsName && !viewFlagsComment)
    viewFlagsName = true;
  if (Symbol* sym = toSymbol(ast)) {
    for (int flagNum = FLAG_FIRST; flagNum <= FLAG_LAST; flagNum++) {
      if (sym->flags[flagNum]) {
        if (viewFlagsName)
          printf("%s ", flagNames[flagNum]);
        if (viewFlagsPragma)
          printf("%s", flagPragma[flagNum] ? "ypr " : "npr ");
        if (viewFlagsShort)
          printf("\"%s\" ", flagShortNames[flagNum]);
        if (viewFlagsComment)
          printf("// %s",
                 *flagComments[flagNum] ? flagComments[flagNum] : "ncm");
        printf("\n");
      }
    }
    if (viewFlagsExtras) {
      if (VarSymbol* vs = toVarSymbol(sym)) {
        if (vs->immediate) {
          printf("immediate ");
          fprint_imm(stdout, *toVarSymbol(sym)->immediate, true);
          printf("\n");
        }
      } else if (ArgSymbol* as = toArgSymbol(sym)) {
        printf("%s arg\n", as->intentDescrString());
      } else if (toTypeSymbol(sym)) {
        printf("a TypeSymbol\n");
      } else if (FnSymbol* fs = toFnSymbol(sym)) {
        printf("fn %s(%d args) %s\n",
               fs->_this ? intentDescrString(fs->thisTag) : "",
               fs->numFormals(), retTagDescrString(fs->retTag));
      } else if (toEnumSymbol(sym)) {
        printf("an EnumSymbol\n");
      } else if (ModuleSymbol* ms = toModuleSymbol(sym)) {
        printf("module %s\n", modTagDescrString(ms->modTag));
      } else if (toLabelSymbol(sym)) {
        printf("a LabelSymbol\n");
      } else {
        printf("unknown symbol kind\n");
      }
    }
  } else {
    printf("[%d]: not a Symbol, has no flags\n", ast->id);
  }
}
Exemple #3
0
static void
list_sym(Symbol* sym, bool type = true) {
  if (VarSymbol* var = toVarSymbol(sym)) {
    if (var->immediate) {
      if (var->immediate->const_kind == NUM_KIND_INT) {
        printf("%"PRId64" ", var->immediate->int_value());
        return;
      } else if (var->immediate->const_kind == CONST_KIND_STRING) {
        printf("\"%s\" ", var->immediate->v_string);
        return;
      }
    }
  }
  if (toFnSymbol(sym)) {
    printf("fn ");
  } else if (toArgSymbol(sym)) {
    printf("arg ");
  } else if (toTypeSymbol(sym)) {
    printf("type ");
  }
  printf("%s", sym->name);
  printf("[%d]", sym->id);
  if (!type) {
    printf(" ");
  } else if (FnSymbol* fn = toFnSymbol(sym)) {
    printf(":%s", fn->retType->symbol->name);
    printf("[%d] ", fn->retType->symbol->id);
  } else if (sym->type && sym->type->symbol) {
    printf(":%s", sym->type->symbol->name);
    printf("[%d] ", sym->type->symbol->id);
  } else {
    printf(" ");
  }
}
Exemple #4
0
IpeValue IpeEnv::valueForVariable(LcnSymbol* lcn) const
{
  IpeValue retval;

  if (lcn->isImmediate() == true)
  {
    VarSymbol* var  = toVarSymbol(lcn);
    Immediate* imm  = var->immediate;
    Type*      type = var->type;

    INT_ASSERT(type);
    INT_ASSERT(type->symbol);
    INT_ASSERT(type->symbol->name);

    if      (strcmp(type->symbol->name, "bool")     == 0)
      retval.boolSet(imm->v_bool);

    else if (strcmp(type->symbol->name, "int")      == 0)
      retval.integerSet(imm->v_int64);

    else if (strcmp(type->symbol->name, "real")     == 0)
      retval.realSet(imm->v_float64);

    else if (strcmp(type->symbol->name, "c_string") == 0)
      retval.cstringSet(imm->v_string);

    else
      INT_ASSERT(false);
  }

  else
    retval = valueFetch(lcn);

  return retval;
}
Exemple #5
0
//
// SymExpr
//
void AstDumpToHtml::visitSymExpr(SymExpr* node) {
  Symbol*    sym = node->var;
  VarSymbol* var = toVarSymbol(sym);

  if (isBlockStmt(node->parentExpr) == true) {
    fprintf(mFP, "<DL>\n");
  }

  fprintf(mFP, " ");

  if (var != 0 && var->immediate != 0) {
    const size_t bufSize = 128;
    char         imm[bufSize];

    snprint_imm(imm, bufSize, *var->immediate);

    fprintf(mFP, "<i><FONT COLOR=\"blue\">%s%s</FONT></i>", imm, is_imag_type(var->type) ? "i" : "");
      
  } else {
    writeSymbol(sym, false);
  }

  if (isBlockStmt(node->parentExpr)) {
    fprintf(mFP, "</DL>\n");
  }
}
Exemple #6
0
  forv_Vec(DefExpr, def, gDefExprs) {
    if (toVarSymbol(def->sym)) {
      // The test for FLAG_TEMP allows compiler-generated (temporary) variables
      // to be declared without an explicit type or initializer expression.
      if ((!def->init || def->init->isNoInitExpr())
          && !def->exprType && !def->sym->hasFlag(FLAG_TEMP))
        if (isBlockStmt(def->parentExpr) && !isArgSymbol(def->parentSymbol))
          if (def->parentExpr != rootModule->block && def->parentExpr != stringLiteralModule->block)
            if (!def->sym->hasFlag(FLAG_INDEX_VAR))
              USR_FATAL_CONT(def->sym,
                             "Variable '%s' is not initialized or has no type",
                             def->sym->name);
    }

    //
    // This test checks to see if query domains (e.g., '[?D]') are
    // used in places other than formal argument type specifiers.
    //
    if (!isFnSymbol(def->parentSymbol)) {
      if (CallExpr* type = toCallExpr(def->exprType)) {
        if (type->isNamed("chpl__buildArrayRuntimeType")) {
          if (CallExpr* domainExpr = toCallExpr(type->get(1))) {
            DefExpr* queryDomain = toDefExpr(domainExpr->get(1));
            if (queryDomain) {
              USR_FATAL_CONT(queryDomain,
                             "Domain query expressions may currently only be used in formal argument types");
            }
          }
        }
      }
    }

    checkPrivateDecls(def);
  }
Exemple #7
0
void IpeModuleRoot::init()
{
  mState = kResolved;

  initialize();

  for (int i = 1; i <= sHighWater; i++)
  {
    DefExpr* expr = toDefExpr(rootModule->block->body.get(i));

    INT_ASSERT(expr);

    if      (mEnv->findLocal(expr->sym->name) != NULL)
    {
      printf("   Attempt to redefine identifier %s\n", expr->sym->name);
      INT_ASSERT(false);
    }

    else if (TypeSymbol* sym = toTypeSymbol(expr->sym))
    {
      int        offset = mEnv->allocateValue(sym->type);
      VarSymbol* var    = new VarSymbol(sym->name, gIpeTypeType);

      INT_ASSERT(expr->exprType == NULL);
      INT_ASSERT(expr->init     == NULL);

      var->addFlag(FLAG_CONST);
      var->locationSet(0, offset);

      mEnv->varAdd(var);
    }

    else if (expr->sym->isImmediate() == true)
    {
      VarSymbol* var    = toVarSymbol(expr->sym);
      int        offset = mEnv->allocateValue(var->type);

      var->addFlag(FLAG_CONST);
      var->locationSet(0, offset);

      mEnv->varAdd(var);
    }

    else
    {
      AstDumpToNode logger(stdout, 3);

      printf("Unexpected expression while initializing RootModule\n");
      printf("   ");
      expr->accept(&logger);
      printf("\n");

      INT_ASSERT(false);
    }
  }

  moduleAdd(this);
}
//
// A forall-intents variation on findOuterVars() in createTaskFunctions.cpp:
// Find all symbols used in 'block' and defined outside of it.
//
static void findOuterVars(BlockStmt* block, SymbolMap* uses) {
  std::vector<SymExpr*> symExprs;
  collectSymExprsSTL(block, symExprs);
  for_vector(SymExpr, symExpr, symExprs) {
    Symbol* sym = symExpr->var;
    if (toVarSymbol(sym) || toArgSymbol(sym))
      if (!isCorrespIndexVar(block, sym) && isOuterVar(sym, block))
        uses->put(sym,gNil);
  }
// Walk backwards from the current statement to determine if a sequence of
// moves have copied a variable that is marked for auto destruction in to
// the dedicated return-temp within the current scope.
//
// Note that the value we are concerned about may be copied in to one or
// more temporary variables between being copied to the return temp.
static VarSymbol* variableToExclude(FnSymbol* fn, Expr* refStmt) {
  VarSymbol* retVar = toVarSymbol(fn->getReturnSymbol());
  VarSymbol* retval = NULL;

  if (retVar != NULL) {
    if (isUserDefinedRecord(retVar)    == true ||
        fn->hasFlag(FLAG_INIT_COPY_FN) == true) {
      VarSymbol* needle = retVar;
      Expr*      expr   = refStmt;

      // Walk backwards looking for the variable that is being returned
      while (retval == NULL && expr != NULL && needle != NULL) {
        if (CallExpr* move = toCallExpr(expr)) {
          if (move->isPrimitive(PRIM_MOVE) == true) {
            SymExpr*   lhs    = toSymExpr(move->get(1));
            VarSymbol* lhsVar = toVarSymbol(lhs->symbol());

            if (needle == lhsVar) {
              if (SymExpr* rhs = toSymExpr(move->get(2))) {
                VarSymbol* rhsVar = toVarSymbol(rhs->symbol());

                if (isAutoDestroyedVariable(rhsVar) == true) {
                  retval = rhsVar;
                } else {
                  needle = rhsVar;
                }
              } else {
                needle = NULL;
              }
            }
          }
        }

        expr = expr->prev;
      }
    }
  }

  return retval;
}
Exemple #10
0
static Expr* postFoldNormal(CallExpr* call) {
  FnSymbol* fn     = call->resolvedFunction();
  Expr*     retval = call;

  if (fn->retTag == RET_PARAM || fn->hasFlag(FLAG_MAYBE_PARAM) == true) {
    VarSymbol* ret = toVarSymbol(fn->getReturnSymbol());

    if (ret != NULL && ret->immediate != NULL) {
      retval = new SymExpr(ret);

      call->replace(retval);

    } else if (EnumSymbol* es = toEnumSymbol(fn->getReturnSymbol())) {
      retval = new SymExpr(es);

      call->replace(retval);

    } else if (ret == gVoid) {
      retval = new SymExpr(gVoid);

      call->replace(retval);
    }
  }

  if (fn->hasFlag(FLAG_MAYBE_TYPE)                       == true &&
      fn->getReturnSymbol()->hasFlag(FLAG_TYPE_VARIABLE) == true) {
    fn->retTag = RET_TYPE;
  }

  if (fn->retTag == RET_TYPE) {
    Symbol* ret = fn->getReturnSymbol();

    if (ret->type->symbol->hasFlag(FLAG_HAS_RUNTIME_TYPE) == false) {
      retval = new SymExpr(ret->type->symbol);

      call->replace(retval);
    }
  }

  if (call->isNamedAstr(astrSequals) == true) {
    if (SymExpr* lhs = toSymExpr(call->get(1))) {
      if (lhs->symbol()->hasFlag(FLAG_MAYBE_PARAM) == true ||
          lhs->symbol()->isParameter()             == true) {
        if (paramMap.get(lhs->symbol())) {
          USR_FATAL(call, "parameter set multiple times");
        }
      }
    }
  }

  return retval;
}
Exemple #11
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)));
        }
      }
    }
  }
//
// finds outer vars directly used in a function
//
static void
findOuterVars(FnSymbol* fn, SymbolMap* uses) {
  Vec<BaseAST*> asts;
  collect_asts(fn, asts);
  forv_Vec(BaseAST, ast, asts) {
    if (SymExpr* symExpr = toSymExpr(ast)) {
      Symbol* sym = symExpr->var;
      if (toVarSymbol(sym) || toArgSymbol(sym))
        if (isOuterVar(sym, fn))
          uses->put(sym,gNil);
    }
  }
}
Exemple #13
0
 forv_Vec(DefExpr, def, gDefExprs) {
   if (toVarSymbol(def->sym))
     // The test for FLAG_TEMP allows compiler-generated (temporary) variables
     // to be declared without an explicit type or initializer expression.
     if ((!def->init || def->init->isNoInitExpr())
         && !def->exprType && !def->sym->hasFlag(FLAG_TEMP))
       if (isBlockStmt(def->parentExpr) && !isArgSymbol(def->parentSymbol))
         if (def->parentExpr != rootModule->block)
           if (!def->sym->hasFlag(FLAG_INDEX_VAR))
             USR_FATAL_CONT(def->sym,
                            "Variable '%s' is not initialized or has no type",
                            def->sym->name);
 }
Exemple #14
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);
            }
          }
        }
      }
    }
  }
}
Exemple #15
0
static QualifiedType
returnInfoGetMember(CallExpr* call) {
  AggregateType* ct = toAggregateType(call->get(1)->typeInfo());
  if (ct->symbol->hasFlag(FLAG_REF))
    ct = toAggregateType(ct->getValType());
  if (!ct)
    INT_FATAL(call, "bad member primitive");
  SymExpr* sym = toSymExpr(call->get(2));
  if (!sym)
    INT_FATAL(call, "bad member primitive");
  VarSymbol* var = toVarSymbol(sym->symbol());
  if (!var)
    INT_FATAL(call, "bad member primitive");
  if (var->immediate) {
    const char* name = var->immediate->v_string;
    for_fields(field, ct) {
      if (!strcmp(field->name, name))
        return field->qualType();
    }
  } else
    return sym->qualType();
Exemple #16
0
const char* CallInfo::toString() {
  bool        method = false;
  bool        _this  = false;
  int         start  = 0;
  const char* retval = "";

  if (actuals.n            >  1 &&
      actuals.head()->type == dtMethodToken) {
    method = true;
    start  =    2;
  }

  if (name == astrThis) {
    _this  =  true;
    method = false;
    start  =     2;
  }

  if (method == true) {
    if (actuals.v[1] &&
        actuals.v[1]->hasFlag(FLAG_TYPE_VARIABLE)) {
      retval = astr(retval, "type ", ::toString(actuals.v[1]->type), ".");

    } else {
      retval = astr(retval,          ::toString(actuals.v[1]->type), ".");
    }
  }

  if (developer                                   == false &&
      strncmp("_type_construct_", name, 16) == 0) {
    retval = astr(retval, name+16);

  } else if (developer == false &&
             strncmp("_construct_", name, 11) == 0) {
    retval = astr(retval, name + 11);
    retval = astr(retval, ".init");

  } else if (_this == false) {
    retval = astr(retval, name);
  }

  if (call->methodTag == false) {
    if (call->square == true) {
      retval = astr(retval, "[");
    } else {
      retval = astr(retval, "(");
    }
  }

  for (int i = start; i < actuals.n; i++) {
    Symbol*        sym  = actuals.v[i];
    VarSymbol*     var  = toVarSymbol(sym);
    Type*          type = sym->type;
    AggregateType* at   = toAggregateType(type);
    IteratorInfo*  ii   = (at != NULL) ? at->iteratorInfo : NULL;

    if (i > start) {
      retval = astr(retval, ", ");
    }

    if (actualNames.v[i] != NULL) {
      retval = astr(retval, actualNames.v[i], "=");
    }

    if (type->symbol->hasFlag(FLAG_ITERATOR_RECORD)   == true &&
        ii->iterator->hasFlag(FLAG_PROMOTION_WRAPPER) == true) {
      retval = astr(retval, "promoted expression");

    } else if (sym->hasFlag(FLAG_TYPE_VARIABLE) == true) {
      retval = astr(retval, "type ", ::toString(type));

    } else if (var != NULL && var->immediate != NULL) {
      if (var->immediate->const_kind == CONST_KIND_STRING) {
        retval = astr(retval, "\"", var->immediate->v_string, "\"");

      } else {
        const size_t bufSize = 512;
        char         buff[bufSize];

        snprint_imm(buff, bufSize, *var->immediate);

        retval = astr(retval, buff);
      }

    } else {
      retval = astr(retval, ::toString(type));
    }
  }

  if (call->methodTag == false) {
    if (call->square == true) {
      retval = astr(retval, "]");
    } else {
      retval = astr(retval, ")");
    }
  }

  return retval;
}
Exemple #17
0
// This routine looks for loops in which the condition variable is *not*
// updated within the body of the loop, and issues a warning for places
// in the code where that occurs.
void WhileStmt::checkConstLoops()
{
  SymExpr* tmpVar  = condExprForTmpVariableGet();

  // Get the loop condition variable.
  if (VarSymbol* condSym = toVarSymbol(tmpVar->symbol()))
  {
    // Look for definitions of the loop condition variable
    // within the body of the loop.
    if (SymExpr* condDef = getWhileCondDef(condSym))
    {
      // Get the call expression that updates the condition variable.
      if (CallExpr* outerCall = toCallExpr(condDef->parentExpr))
      {
        // Assume the outer call is a move expression and that its LHS is
        // the (SymExpr that contains the) loop condition variable.
        if (outerCall->get(1) == condDef)
        {
          if (outerCall->isPrimitive(PRIM_MOVE))
          {
            // Expect the update to be the result of a call to _cond_test.
            if (CallExpr* innerCall = toCallExpr(outerCall->get(2)))
            {
              FnSymbol* fn = innerCall->resolvedFunction();

              if (innerCall->numActuals()        == 1 &&
                  strcmp(fn->name, "_cond_test") == 0)
              {
                checkWhileLoopCondition(innerCall->get(1));
              }
              else
              {
                INT_FATAL(innerCall,
                          "Expected the update of a loop conditional "
                          "to be piped through _cond_test().");
              }
            }

            // The RHS of the move can also be a SymExpr as the result of param
            // folding ...
            else if (SymExpr* moveSrc = toSymExpr(outerCall->get(2)))
            {
              // ... in which case, the literal should be 'true' or 'false'.
              if (moveSrc->symbol() == gTrue)
              {
                // while true do ... ;  -- probably OK.
                // User said to loop forever ... .
              }

              else if (moveSrc->symbol() == gFalse)
              {
                // while false do ...; -- probably nothing to worry about
                // We probably don't get here unless fRemoveUnreachableBlocks
                // is false.
              }

              else
              {
                INT_FATAL(moveSrc,
                          "Expected const loop condition variable to be "
                          "true or false.");
              }
            }

            else
            {
              // The RHS was neither a CallExpr nor a SymExpr.
              INT_FATAL(outerCall,
                        "Invalid RHS in a loop condition variable update "
                        "expression.");
            }
          }

          else
          {
            INT_FATAL(outerCall,
                      "Expected a loop condition variable update to "
                      "be a MOVE.");
          }
        }
        else
        {
          // Note that this being true depends on the compiler inserting a temp
          // that is the result of applying _cond_test to a more-general loop
          // conditional expression.
          // Copy propagation could potentially make this false again....
          INT_FATAL(condDef,
                    "Expected loop condition variable to be only "
                    "updated (not read).");
        }
      }

      else
      {
        INT_FATAL(condDef,
                  "The update of a loop condition variable could not "
                  "be converted to a call.");
      }
    }
    else
    {
      // There was no update of the loop condition variable in the
      // body of the loop.
      // It could be an infinite loop, or it could have a
      // 'break' or 'return' in it.
    }
  }

  else
  {
    INT_FATAL(tmpVar,
              "The loop condition variable could not be converted "
              "to a VarSymbol.");
  }
}
Exemple #18
0
void IpeEnv::describe(const char* pad, int index, LcnSymbol* var) const
{
  const char* symName  = var->name;
  const char* typeName = "";
  ArgSymbol*  argSym   = toArgSymbol(var);
  VarSymbol*  varSym   = toVarSymbol(var);

  if (var->type)
    typeName = var->type->symbol->name;

  printf("%s %5d: %-30s", pad, index, symName);

  if      (argSym                      != NULL)
  {
    if (argSym->intent & INTENT_REF)
      printf("ref   %-12s", typeName);
    else
      printf("arg   %-12s", typeName);
  }

  else if (varSym->immediate           != NULL)
    printf("const %-12s", typeName);

  else if (varSym->hasFlag(FLAG_CONST) == true)
    printf("const %-12s", typeName);

  else if (varSym->hasFlag(FLAG_PARAM) == true)
    printf("param %-12s", typeName);

  else
    printf("var   %-12s", typeName);

  if (var->depth() >= 0 && var->offset() >= 0)
    printf("%4d %4d ", var->depth(), var->offset());
  else
    printf("          ");

  if      (argSym != NULL && (argSym->intent & INTENT_REF) != 0)
  {
    if (mFrameData != NULL)
    {
      int       offset = argSym->offset();
      IpeValue* ref    = *((IpeValue**) (((char*) mFrameData) + offset));

      printf("0x%012lX", (long) ref);
    }
  }

  else if (var->offset() <    0)
    ;

  else if (var->type     == NULL)
    ;

  else if (var->type     == gIpeTypeType)
    printf("%s", symName);

  else if (var->type     == dtBool)
  {
    if (mDepth == 0 || mFrameData != NULL)
      printf("%s", (fetchBool(var) == true) ?  "true" : "false");
  }

  else if (var->type     == dtInt[INT_SIZE_64])
  {
    if (mDepth == 0 || mFrameData != NULL)
      printf("%8ld", fetchInteger(var));
  }

  else if (var->type     == dtReal[FLOAT_SIZE_64])
  {
    if (mDepth == 0 || mFrameData != NULL)
      printf("   %8.2f", fetchReal(var));
  }

  else if (var->type     == gIpeTypeModule)
  {
    if (mDepth == 0 || mFrameData != NULL)
    {
      IpeModule* value = (IpeModule*) fetchPtr(var);

      printf("#<IpeModule    %-20s 0x%012lX>", value->name(), (long) value);
    }
  }

  else if (var->type     == gIpeTypeProcedure)
  {
    if (mDepth == 0 || mFrameData != NULL)
    {
      IpeProcedure* value = (IpeProcedure*) fetchPtr(var);

      if (value->methodCount() == 1)
        printf("#<IpeProcedure %-20s with %3d method  0x%012lX>",
               value->name(),
               value->methodCount(),
               (long) value);
      else
        printf("#<IpeProcedure %-20s with %3d methods 0x%012lX>",
               value->name(),
               value->methodCount(),
               (long) value);
    }
  }

  else
    printf("Really??  Really??");

  printf("\n");
}
Exemple #19
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);
            }
          }
        }
      }
Exemple #20
0
CallExpr* ParamForLoop::foldForResolve()
{
  SymExpr*   idxExpr   = indexExprGet();
  SymExpr*   lse       = lowExprGet();
  SymExpr*   hse       = highExprGet();
  SymExpr*   sse       = strideExprGet();

  if (!lse             || !hse             || !sse)
    USR_FATAL(this, "param for loop must be defined over a bounded param range");

  VarSymbol* lvar      = toVarSymbol(lse->var);
  VarSymbol* hvar      = toVarSymbol(hse->var);
  VarSymbol* svar      = toVarSymbol(sse->var);

  CallExpr*  noop      = new CallExpr(PRIM_NOOP);

  if (!lvar            || !hvar            || !svar)
    USR_FATAL(this, "param for loop must be defined over a bounded param range");

  if (!lvar->immediate || !hvar->immediate || !svar->immediate)
    USR_FATAL(this, "param for loop must be defined over a bounded param range");

  Symbol*      idxSym  = idxExpr->var;
  Symbol*      continueSym = continueLabelGet();
  Type*        idxType = indexType();
  IF1_int_type idxSize = (get_width(idxType) == 32) ? INT_SIZE_32 : INT_SIZE_64;

  // Insert an "insertion marker" for loop unrolling
  insertAfter(noop);

  if (is_int_type(idxType))
  {
    int64_t low    = lvar->immediate->to_int();
    int64_t high   = hvar->immediate->to_int();
    int64_t stride = svar->immediate->to_int();

    if (stride <= 0)
    {
      for (int64_t i = high; i >= low; i += stride)
      {
        SymbolMap map;

        map.put(idxSym, new_IntSymbol(i, idxSize));
        copyBodyHelper(noop, i, &map, this, continueSym);
      }
    }
    else
    {
      for (int64_t i = low; i <= high; i += stride)
      {
        SymbolMap map;

        map.put(idxSym, new_IntSymbol(i, idxSize));

        copyBodyHelper(noop, i, &map, this, continueSym);
      }
    }
  }
  else
  {
    INT_ASSERT(is_uint_type(idxType) || is_bool_type(idxType));

    uint64_t low    = lvar->immediate->to_uint();
    uint64_t high   = hvar->immediate->to_uint();
    int64_t  stride = svar->immediate->to_int();

    if (stride <= 0)
    {
      for (uint64_t i = high; i >= low; i += stride)
      {
        SymbolMap map;

        map.put(idxSym, new_UIntSymbol(i, idxSize));

        copyBodyHelper(noop, i, &map, this, continueSym);
      }
    }
    else
    {
      for (uint64_t i = low; i <= high; i += stride)
      {
        SymbolMap map;

        map.put(idxSym, new_UIntSymbol(i, idxSize));

        copyBodyHelper(noop, i, &map, this, continueSym);
      }
    }
  }

  // Remove the "insertion marker"
  noop->remove();

  // Replace the paramLoop with the NO-OP
  replace(noop);

  return noop;
}
Exemple #21
0
// Returns max local frame space to evaluate this expr
int locationExpr(Expr* expr, IpeEnv* env)
{
  int retval = 0;

  if (DefExpr* defExpr = toDefExpr(expr))
  {
    VarSymbol* var   = toVarSymbol(defExpr->sym);
    int        delta = 8;           // NOAKES  Size of every type is currently 8

    INT_ASSERT(var);

    env->locationSet(var);

    retval = delta;
  }

  else if (isCallExpr(expr) == true)
    retval = 0;

  else if (CondStmt*    stmt = toCondStmt(expr))
  {
    if (stmt->elseStmt == NULL)
    {
      retval = locationExpr(stmt->thenStmt, env);
    }

    else
    {
      int thenSize = locationExpr(stmt->thenStmt, env);
      int elseSize = locationExpr(stmt->elseStmt, env);

      retval = (thenSize > elseSize) ? thenSize : elseSize;
    }
  }

  else if (WhileDoStmt* stmt = toWhileDoStmt(expr))
  {
    Expr* body = stmt->body.get(1);

    INT_ASSERT(stmt->body.length == 1);
    INT_ASSERT(isBlockStmt(body));

    retval = locationExpr(body, env);
  }

  else if (BlockStmt* stmt = toBlockStmt(expr))
  {
    IpeBlockStmt* ipeStmt  = (IpeBlockStmt*) stmt;
    int           maxFrame = 0;
    IpeEnv        env(ipeStmt->scopeGet());

    for (int i = 1; i <= ipeStmt->body.length; i++)
    {
      int localSize = locationExpr(ipeStmt->body.get(i), &env);

      if (localSize > maxFrame)
        maxFrame = localSize;
    }

    retval = maxFrame;
  }

  else
  {
    AstDumpToNode logger(stdout, 3);

    printf("   locationExpr(Expr*, IpeEnv* env)  unsupported\n");
    printf("   ");
    expr->accept(&logger);
    printf("\n\n");

    env->describe(3);
    printf("\n\n");

    INT_ASSERT(false);
  }

  return retval;
}
Exemple #22
0
//
// DefExpr
//
bool AstDumpToHtml::enterDefExpr(DefExpr* node) {
  bool retval = true;

  if (isBlockStmt(node->parentExpr)) {
    fprintf(mFP, "<DL>\n");
  }

  fprintf(mFP, " ");

  if (FnSymbol* fn = toFnSymbol(node->sym)) {
    fprintf(mFP, "<UL CLASS =\"mktree\">\n<LI>");

    adjacent_passes(fn);

    fprintf(mFP, "<CHPLTAG=\"FN%d\">\n", fn->id);
    fprintf(mFP, "<B>function ");

    writeFnSymbol(fn);

    fprintf(mFP, "</B><UL>\n");

  } else if (isTypeSymbol(node->sym)) {
    if (toAggregateType(node->sym->type)) {
      fprintf(mFP, "<UL CLASS =\"mktree\">\n");
      fprintf(mFP, "<LI>");

      if (node->sym->hasFlag(FLAG_SYNC))
        fprintf(mFP, "<B>sync</B> ");

      if (node->sym->hasFlag(FLAG_SINGLE))
        fprintf(mFP, "<B>single</B> ");

      fprintf(mFP, "<B>type ");
      writeSymbol(node->sym, true);
      fprintf(mFP, "</B><UL>\n");

    } else {
      fprintf(mFP, "<B>type </B> ");
      writeSymbol(node->sym, true);
    }

  } else if (VarSymbol* vs = toVarSymbol(node->sym)) {
    if (vs->type->symbol->hasFlag(FLAG_SYNC))
      fprintf(mFP, "<B>sync </B>");

    if (vs->type->symbol->hasFlag(FLAG_SINGLE))
      fprintf(mFP, "<B>single </B>");

    fprintf(mFP, "<B>var </B> ");
    writeSymbol(node->sym, true);

  } else if (ArgSymbol* s = toArgSymbol(node->sym)) {
    switch (s->intent) {
      case INTENT_IN:        fprintf(mFP, "<B>in</B> ");        break;
      case INTENT_INOUT:     fprintf(mFP, "<B>inout</B> ");     break;
      case INTENT_OUT:       fprintf(mFP, "<B>out</B> ");       break;
      case INTENT_CONST:     fprintf(mFP, "<B>const</B> ");     break;
      case INTENT_CONST_IN:  fprintf(mFP, "<B>const in</B> ");  break;
      case INTENT_CONST_REF: fprintf(mFP, "<B>const ref</B> "); break;
      case INTENT_REF:       fprintf(mFP, "<B>ref</B> ");       break;
      case INTENT_PARAM:     fprintf(mFP, "<B>param</B> ");     break;
      case INTENT_TYPE:      fprintf(mFP, "<B>type</B> ");      break;
      case INTENT_BLANK:                                        break;
    }

    fprintf(mFP, "<B>arg</B> ");

    writeSymbol(node->sym, true);

  } else if (isLabelSymbol(node->sym)) {
    fprintf(mFP, "<B>label</B> ");
    writeSymbol(node->sym, true);

  } else if (isModuleSymbol(node->sym)) {
    fprintf(mFP, "</DL>\n");
    // Don't process nested modules -- they'll be handled at the top-level
    retval = false;

  } else {
    fprintf(mFP, "<B>def</B> ");
    writeSymbol(node->sym, true);
  }

  return retval;
}
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));
      }
    }
  }
}