Exemple #1
0
GenRet BlockStmt::codegen() {
  GenInfo* info = gGenInfo;
  FILE* outfile = info->cfile;
  GenRet ret;

  codegenStmt(this);

  if( outfile ) {
    if (blockInfo) {
      if (blockInfo->isPrimitive(PRIM_BLOCK_WHILEDO_LOOP)) {
        std::string hdr = "while (" + codegenValue(blockInfo->get(1)).c + ") ";
        info->cStatements.push_back(hdr);
      } else if (blockInfo->isPrimitive(PRIM_BLOCK_DOWHILE_LOOP)) {
        info->cStatements.push_back("do ");
      } else if (blockInfo->isPrimitive(PRIM_BLOCK_FOR_LOOP)) {
        std::string hdr = "for (;" + codegenValue(blockInfo->get(1)).c + ";) ";
        info->cStatements.push_back(hdr);
      } else if (blockInfo->isPrimitive(PRIM_BLOCK_XMT_PRAGMA_FORALL_I_IN_N)) {
        std::string hdr = "_Pragma(\"mta for all streams ";
        hdr += codegenValue(blockInfo->get(1)).c;
        hdr += " of ";
        hdr += codegenValue(blockInfo->get(2)).c;
        hdr += "\")\n";
        info->cStatements.push_back(hdr);
      }
    }

    if (this != getFunction()->body)
      info->cStatements.push_back("{\n");

    if (!(fNoRepositionDefExpr)) {
      Vec<BaseAST*> asts;
      collect_top_asts(this, asts);
      forv_Vec(BaseAST, ast, asts) {
        if (DefExpr* def = toDefExpr(ast)) {
          if (def->parentExpr == this) {
            if (!toTypeSymbol(def->sym)) {
              if (fGenIDS && isVarSymbol(def->sym))
                info->cStatements.push_back("/* " + numToString(def->sym->id) + " */ ");
              def->sym->codegenDef();
            }
          }
        }
      }
    }

    body.codegen("");

    if (blockInfo && blockInfo->isPrimitive(PRIM_BLOCK_DOWHILE_LOOP)) {
      std::string ftr = "} while (" + codegenValue(blockInfo->get(1)).c + ");\n";
      info->cStatements.push_back(ftr);
    } else if (this != getFunction()->body) {
      std::string end = "}";
      CondStmt* cond = toCondStmt(parentExpr);
      if (!cond || !(cond->thenStmt == this && cond->elseStmt))
        end += "\n";
      info->cStatements.push_back(end);
    }
  } else {
Exemple #2
0
GenRet BlockStmt::codegen() {
  GenInfo* info    = gGenInfo;
  FILE*    outfile = info->cfile;
  GenRet   ret;

  codegenStmt(this);

  if (outfile) {
    if (this != getFunction()->body) {
      if (this->blockInfoGet()) {
        if (this->blockInfoGet()->isPrimitive(PRIM_BLOCK_LOCAL)) {
          info->cStatements.push_back("/* local block */\n");
        }
      }
      info->cStatements.push_back("{\n");
    }

    body.codegen("");

    if (this != getFunction()->body) {
      std::string end  = "}";
      CondStmt*   cond = toCondStmt(parentExpr);

      if (!cond || !(cond->thenStmt == this && cond->elseStmt))
        end += "\n";

      info->cStatements.push_back(end);
    }

  } else {
#ifdef HAVE_LLVM
    llvm::Function*   func          = info->builder->GetInsertBlock()->getParent();
    llvm::BasicBlock* blockStmtBody = NULL;

    getFunction()->codegenUniqueNum++;

    blockStmtBody = llvm::BasicBlock::Create(info->module->getContext(), FNAME("blk_body"));

    info->builder->CreateBr(blockStmtBody);

    // Now add the body.
    func->getBasicBlockList().push_back(blockStmtBody);

    info->builder->SetInsertPoint(blockStmtBody);

    info->lvt->addLayer();

    body.codegen("");

    info->lvt->removeLayer();

    INT_ASSERT(blockStmtBody->getParent() == func);
#endif
  }

  return ret;
}
Exemple #3
0
void Expr::prettyPrint(std::ostream *o) {
  if (BlockStmt *stmt = toBlockStmt(this))
    printf("blockstmt %s", stmt->userLabel);

  else if (CondStmt *stmt = toCondStmt(this))
    printf("condstmt %s", stmt->condExpr->parentSymbol->name);

  else if (GotoStmt *stmt = toGotoStmt(this))
    printf("gotostmt %s", stmt->label->parentSymbol->name);

  printf("Oh no! This method hasn't been defined for this class!\n");
}
Exemple #4
0
static bool
list_line(Expr* expr, BaseAST* parentAst) {
  if (expr->isStmt())
    return !*block_explanation(expr, parentAst);
  if (CondStmt* cond = toCondStmt(parentAst)) {
    if (cond->condExpr == expr)
      return false;
  }
  if (Expr* pExpr = toExpr(parentAst))
   if (pExpr->isStmt())
    return true;
  if (isSymbol(parentAst))
    return true;
  return false;
}
Exemple #5
0
static void
list_ast(BaseAST* ast, BaseAST* parentAst = NULL, int indent = 0) {
  bool do_list_line = false;
  bool is_C_loop = false;
  const char* block_explain = NULL;
  if (Expr* expr = toExpr(ast)) {
    do_list_line = !parentAst || list_line(expr, parentAst);
    if (do_list_line) {
      printf("%-7d ", expr->id);
      for (int i = 0; i < indent; i++)
        printf(" ");
    }
    if (GotoStmt* e = toGotoStmt(ast)) {
      printf("goto ");
      if (SymExpr* label = toSymExpr(e->label)) {
        if (label->var != gNil) {
          list_ast(e->label, ast, indent+1);
        }
      } else {
        list_ast(e->label, ast, indent+1);
      }
    } else if (toBlockStmt(ast)) {
      block_explain = block_explanation(ast, parentAst);
      printf("%s{\n", block_explain);
    } else if (toCondStmt(ast)) {
      printf("if ");
    } else if (CallExpr* e = toCallExpr(expr)) {
      if (e->isPrimitive(PRIM_BLOCK_C_FOR_LOOP))
          is_C_loop = true;
      if (e->primitive)
        printf("%s( ", e->primitive->name);
      else
        printf("call( ");
    } else if (NamedExpr* e = toNamedExpr(expr)) {
      printf("%s = ", e->name);
    } else if (toDefExpr(expr)) {
      printf("def ");
    } else if (SymExpr* e = toSymExpr(expr)) {
      list_sym(e->var, false);
    } else if (UnresolvedSymExpr* e = toUnresolvedSymExpr(expr)) {
      printf("%s ", e->unresolved);
    }
  }

  if (Symbol* sym = toSymbol(ast))
    list_sym(sym);

  bool early_newline = toFnSymbol(ast) || toModuleSymbol(ast); 
  if (early_newline || is_C_loop)
    printf("\n");

  int new_indent = indent;

  if (isExpr(ast))
    if (do_list_line)
      new_indent = indent+2;

  AST_CHILDREN_CALL(ast, list_ast, ast, new_indent);

  if (Expr* expr = toExpr(ast)) {
    CallExpr* parent_C_loop = NULL;
    if (CallExpr* call = toCallExpr(parentAst))
      if (call->isPrimitive(PRIM_BLOCK_C_FOR_LOOP))
        parent_C_loop = call;
    if (toCallExpr(expr)) {
      printf(") ");
    }
    if (toBlockStmt(ast)) {
      printf("%-7d ", expr->id);
      if (*block_explain)
        indent -= 2;
      for (int i = 0; i < indent; i++)
        printf(" ");
      if ((parent_C_loop && parent_C_loop->get(3) == expr) || *block_explain)
        printf("} ");
      else
        printf("}\n");
    } else if (CondStmt* cond = toCondStmt(parentAst)) {
      if (cond->condExpr == expr)
        printf("\n");
    } else if (!toCondStmt(expr) && do_list_line) {
      DefExpr* def = toDefExpr(expr);
      if (!(def && early_newline))
        if (!parent_C_loop)
          printf("\n");
    }
  }
}
Exemple #6
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 #7
0
static void
list_ast(BaseAST* ast, BaseAST* parentAst = NULL, int indent = 0) {
  bool do_list_line = false;
  bool is_C_loop = false;
  const char* block_explain = NULL;
  if (Expr* expr = toExpr(ast)) {
    if (ForallStmt* pfs = toForallStmt(parentAst)) {
      if (expr == pfs->fRecIterIRdef) {
        printf("fRecIterIRdef");
      } else if (expr == pfs->loopBody()) {
        if (pfs->numShadowVars() == 0)
          print_on_its_own_line(indent, "with() do\n");
        else
          print_on_its_own_line(indent, "do\n", false);
        indent -= 2;
      }
    }
    do_list_line = !parentAst || list_line(expr, parentAst);
    if (do_list_line) {
      printf("%-7d ", expr->id);
      print_indent(indent);
    }
    if (const char* expl = forall_explanation_start(ast, parentAst))
      printf("%s", expl);
    if (GotoStmt* e = toGotoStmt(ast)) {
      printf("goto ");
      if (SymExpr* label = toSymExpr(e->label)) {
        if (label->symbol() != gNil) {
          list_ast(e->label, ast, indent+1);
        }
      } else {
        list_ast(e->label, ast, indent+1);
      }
    } else if (toBlockStmt(ast)) {
      block_explain = block_explanation(ast, parentAst);
      const char* block_kind = ast->astTagAsString();
      if (!strcmp(block_kind, "BlockStmt")) block_kind = "";
      printf("%s{%s\n", block_explain, block_kind);
    } else if (toCondStmt(ast)) {
      printf("if ");
    } else if (toIfExpr(ast)) {
      printf("IfExpr ");
    } else if (toForallStmt(ast)) {
      printf("forall\n");
    } else if (CallExpr* e = toCallExpr(expr)) {
      if (e->isPrimitive(PRIM_BLOCK_C_FOR_LOOP))
          is_C_loop = true;
      if (e->primitive)
        printf("%s( ", e->primitive->name);
      else
        printf("call( ");
    } else if (ForallExpr* e = toForallExpr(expr)) {
      if (e->zippered) printf("zip ");
      printf("forall( ");
    } else if (NamedExpr* e = toNamedExpr(expr)) {
      printf("%s = ", e->name);
    } else if (toDefExpr(expr)) {
      Symbol* sym = toDefExpr(expr)->sym;
      if (sym->type != NULL) {
        printf("def %s ", sym->qualType().qualStr());
      } else {
        printf("def ");
      }
    } else if (SymExpr* e = toSymExpr(expr)) {
      list_sym(e->symbol(), false);
    } else if (UnresolvedSymExpr* e = toUnresolvedSymExpr(expr)) {
      printf("%s ", e->unresolved);
    } else if (isUseStmt(expr)) {
      printf("use ");
    }
  }

  if (Symbol* sym = toSymbol(ast))
    list_sym(sym);

  bool early_newline = toFnSymbol(ast) || toModuleSymbol(ast);
  if (early_newline || is_C_loop)
    printf("\n");

  int new_indent = indent;

  if (isExpr(ast))
    if (do_list_line)
      new_indent = indent+2;

  AST_CHILDREN_CALL(ast, list_ast, ast, new_indent);

  if (Expr* expr = toExpr(ast)) {
    CallExpr* parent_C_loop = NULL;
    if (CallExpr* call = toCallExpr(parentAst))
      if (call->isPrimitive(PRIM_BLOCK_C_FOR_LOOP))
        parent_C_loop = call;
    if (toCallExpr(expr)) {
      printf(") ");
    }
    if (toBlockStmt(ast)) {
      printf("%-7d ", expr->id);
      if (*block_explain)
        indent -= 2;
      print_indent(indent);
      if ((parent_C_loop && parent_C_loop->get(3) == expr) || *block_explain)
        printf("} ");
      else if (isDeferStmt(parentAst))
        printf("}"); // newline is coming
      else
        printf("}\n");
      if (isForallLoopBody(expr) && parentAst != NULL) {
        print_indent(indent);
        printf("        end forall %d", parentAst->id);
      }
    } else if (ForallExpr* e = toForallExpr(expr)) {
      if (e->cond) printf(") ");
      else         printf("} ");
    } else if (UseStmt* use = toUseStmt(expr)) {
      if (!use->isPlainUse()) {
        if (use->hasExceptList()) {
          printf("except ");
        } else {
          printf("only ");
        }
        bool first = true;
        for_vector(const char, str, use->named) {
          if (first) {
            first = false;
          } else {
            printf(", ");
          }
          printf("%s", str);
        }

        for (std::map<const char*, const char*>::iterator it = use->renamed.begin();
             it != use->renamed.end(); ++it) {
          if (first) {
            first = false;
          } else {
            printf(", ");
          }
          printf("%s as %s", it->second, it->first);
        }
        printf("\n");
      }
    } else if (CondStmt* cond = toCondStmt(parentAst)) {
// Returns true if the symbol is read in the containing expression,
// false otherwise.  If the operand is used as an address,
// that does not count as a 'read', so false is returned in that case.
static bool isUse(SymExpr* se)
{
  if (toGotoStmt(se->parentExpr))
    return false;

  if (toCondStmt(se->parentExpr))
    return true;

  if (toBlockStmt(se->parentExpr))
    return true;

  if (isDefExpr(se->parentExpr))
    return false;

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

  if (FnSymbol* fn = call->resolvedFunction())
  {
    // Skip the "base" symbol.
    if (se->symbol() == fn)
      return false;

    // A "normal" call.
    ArgSymbol* arg = actual_to_formal(se);

    if (arg->intent == INTENT_OUT ||
        (arg->intent & INTENT_FLAG_REF))
      return false;
  }

  else
  {
    INT_ASSERT(call->primitive);
    const bool isFirstActual = call->get(1) == se;

    switch(call->primitive->tag)
    {
     default:
      return true;

     case PRIM_MOVE:
     case PRIM_ASSIGN:
     case PRIM_ADD_ASSIGN:
     case PRIM_SUBTRACT_ASSIGN:
     case PRIM_MULT_ASSIGN:
     case PRIM_DIV_ASSIGN:
     case PRIM_MOD_ASSIGN:
     case PRIM_LSH_ASSIGN:
     case PRIM_RSH_ASSIGN:
     case PRIM_AND_ASSIGN:
     case PRIM_OR_ASSIGN:
     case PRIM_XOR_ASSIGN:
      if (isFirstActual)
      {
        return false;
      }
      return true;

     case PRIM_ADDR_OF:
     case PRIM_SET_REFERENCE:
      return false; // See Note #2.

     case PRIM_PRIVATE_BROADCAST:
      // The operand is used by name (it must be a manifest constant).
      // Thus it acts more like an address than a value.
      return false;

     case PRIM_CHPL_COMM_GET:
     case PRIM_CHPL_COMM_PUT:
     case PRIM_CHPL_COMM_ARRAY_GET:
     case PRIM_CHPL_COMM_ARRAY_PUT:
     case PRIM_CHPL_COMM_GET_STRD:
     case PRIM_CHPL_COMM_PUT_STRD:
      // ('comm_get/put' locAddr locale widePtr len)
      // The first and third operands are treated as addresses.
      // The second and fourth are values
      if (se == call->get(2) || se == call->get(4))
      {
        return true;
      }
      return false;

     case PRIM_CHPL_COMM_REMOTE_PREFETCH:
      // comm prefetch locale widePtr len
      // second argument is an address
      // first and third are values.
      if (isFirstActual || se == call->get(3))
      {
        return true;
      }
      return false;

     case PRIM_SET_MEMBER:
      // The first operand works like a reference, and the second is a field
      // name.  Only the third is a replaceable use.
      if (se == call->get(3))
      {
        return true;
      }
      return false;

     case PRIM_GET_MEMBER:
     case PRIM_GET_MEMBER_VALUE:
      if (isFirstActual)
      {
        return false;
      }
      return true;

     case PRIM_ARRAY_SET:
     case PRIM_ARRAY_SET_FIRST:
     case PRIM_ARRAY_GET:
     case PRIM_ARRAY_GET_VALUE:
      // The first operand is treated like a reference.
      if (isFirstActual)
      {
        return false;
      }
      return true;

     case PRIM_SET_UNION_ID:
      // The first operand is treated like a reference.
      if (isFirstActual)
      {
        return false;
      }

      return true;
    }
  }

  return true;
}
// This routine returns true if the value of the given symbol may have changed
// due to execution of the containing expression.
// If the symbol is a reference, this means that the address to which the
// symbol points will be changed, not the value contained in that address.  See
// isRefUse() for that case.
// To be conservative, the routine should return true by default and then
// select the cases where we are sure nothing has changed.
static bool needsKilling(SymExpr* se, std::set<Symbol*>& liveRefs)
{
  INT_ASSERT(se->isRef() == false);
  if (toGotoStmt(se->parentExpr)) {
    return false;
  }

  if (toCondStmt(se->parentExpr)) {
    return false;
  }

  if (toBlockStmt(se->parentExpr)) {
    return false;
  }

  if (isDefExpr(se->parentExpr)) {
    return false;
  }

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

  if (FnSymbol* fn = call->resolvedFunction())
  {
    // Skip the "base" symbol.
    if (se->symbol() == fn)
    {
      return false;
    }

    ArgSymbol* arg = actual_to_formal(se);

    if (arg->intent == INTENT_OUT   ||
        arg->intent == INTENT_INOUT ||
        arg->intent == INTENT_REF   ||
        arg->hasFlag(FLAG_ARG_THIS)) // Todo: replace with arg intent check?
    {
      liveRefs.insert(se->symbol());
      return true;
    }

    if (isRecordWrappedType(arg->type))
    {
      return true;
    }

    return false;
  }
  else
  {
    const bool isFirstActual = call->get(1) == se;
    if ((call->isPrimitive(PRIM_MOVE) || call->isPrimitive(PRIM_ASSIGN))
        && isFirstActual)
    {
      return true;
    }

    if (isOpEqualPrim(call) && isFirstActual)
    {
      return true;
    }

    if (call->isPrimitive(PRIM_SET_MEMBER) && isFirstActual)
    {
      return true;
    }

    if (call->isPrimitive(PRIM_ARRAY_SET) ||
        call->isPrimitive(PRIM_ARRAY_SET_FIRST))
    {
      if (isFirstActual)
      {
        return true;
      }

      return false;
    }

    if (call->isPrimitive(PRIM_GET_MEMBER))
    {
      // This creates an alias to a portion of the first arg.
      // We could track this as a reference and invalidate a pair containing
      // this symbol when the ref is dereferenced.  But for now, we want to
      // preserve the mapping ref = &value in the RefMap, so having a (ref,
      // value) pair also possibly mean ref = &(value.subfield) does not quite
      // fit.
      // We could keep the ability to do (deref ref) <- value substitution by
      // keeping a separate map for "true" references, or by performing those
      // substitutions in a separate pass.
      // For now, we treat subfield extraction as evidence of a future change
      // to the symbol itself, and use that fact to remove it from
      // consideration in copy propagation.
      if (isFirstActual)
      {
        // We select just the case where the referent is passed by value,
        // because in the other case, the address of the object is not
        // returned, so that means that the address (i.e. the value of the
        // reference variable) does not change.
        return true;
      }

      return false;
    }

    if (call->isPrimitive(PRIM_ADDR_OF) ||
        call->isPrimitive(PRIM_SET_REFERENCE)) {
      liveRefs.insert(se->symbol());
      return true;
    }

    return false;
  }

  INT_ASSERT(0); // Should never get here.

  return true;
}