Exemple #1
0
static void
view_ast(BaseAST* ast, bool number = false, int mark = -1, int indent = 0) {
  if (!ast)
    return;
  if (Expr* expr = toExpr(ast)) {
    printf("\n");
    for (int i = 0; i < indent; i++)
      printf(" ");
    printf("(");
    if (ast->id == mark)
      printf("***");
    if (number)
      printf("%d ", ast->id);
    printf("%s", expr->astTagAsString());

    if (isBlockStmt(expr))
      if (FnSymbol* fn = toFnSymbol(expr->parentSymbol))
        if (expr == fn->where)
          printf(" where");

    if (GotoStmt *gs= toGotoStmt(ast)) {
      printf( " ");
      view_ast(gs->label, number, mark, indent+1);
    }

    if (CallExpr* call = toCallExpr(expr))
      if (call->primitive)
        printf(" %s", call->primitive->name);

    if (NamedExpr* named = toNamedExpr(expr))
      printf(" \"%s\"", named->name);

    if (toDefExpr(expr))
      printf(" ");

    int64_t i;
    const char *str;
    if (get_int(expr, &i)) {
      printf(" %" PRId64, i);
    } else if (get_string(expr, &str)) {
      printf(" \"%s\"", str);
    }

    if (SymExpr* sym = toSymExpr(expr)) {
      printf(" ");
      view_sym(sym->var, number, mark);
    } else if (UnresolvedSymExpr* sym = toUnresolvedSymExpr(expr)) {
      printf(" '%s'", sym->unresolved);
    }
  }

  if (Symbol* sym = toSymbol(ast)) {
    view_sym(sym, number, mark);
  }

  AST_CHILDREN_CALL(ast, view_ast, number, mark, indent+2);

  if (toExpr(ast))
    printf(")");
}
Exemple #2
0
/*
 * Attempts to replace iteration over simple anonymous ranges with calls to
 * direct iterators that take low, high and stride as arguments. This is to
 * avoid the cost of constructing ranges, and if the stride is known at compile
 * time, provide a more optimized iterator that uses "<, <=, >, or >=" as the
 * relational operator.
 *
 * This is only meant to replace anonymous range iteration for "simple" bounded
 * ranges. Simple means it's a range of the form "low..high" or "low..high by
 * stride". Anything more complex is ignored with the thinking that this should
 * optimize the most common range iterators, but it could be expanded to handle
 * more cases.
 *
 * An alternative is to update scalar replacement of aggregates to work on
 * ranges, which should be able to achieve similar results as this optimization
 * while handling all ranges, including non-anonymous ranges.
 *
 * Will optimize things like:
 * - "for i in 1..10"
 * - "for i in 1..10+1"
 * - "var lo=1, hi=10;for i in lo..hi"
 * - "for i in 1..10 by 2"
 * - "for (i, j) in zip(1..10 by 2, 1..10 by -2)"
 * - "for (i, j) in zip(A, 1..10 by 2)" // will optimize range iter still
 * - "coforall i in 1..10 by 2"         // works for coforalls as well
 *
 * Will not optimize ranges like:
 * - "for in in (1..)"             // doesn't handle unbounded ranges
 * - "for i in 1..10 by 2 by 2"    // doesn't handle more than one by operator
 * - "for i in 1..10 align 2"      // doesn't handle align operator
 * - "for i in 1..#10"             // doesn't handle # operator
 * - "var r = 1..10"; for i in r"  // not an anonymous range
 * - "forall i in 1..10"           // does not get applied to foralls
 *
 * Note that this function is pretty fragile because it relies on names of
 * functions/iterators as well as the arguments and order of those
 * functions/iterators but there's not really a way around it this early in
 * compilation. If the iterator can't be replaced, it is left unchanged.
 */
static void tryToReplaceWithDirectRangeIterator(Expr* iteratorExpr)
{
  CallExpr* range = NULL;
  Expr* stride = NULL;
  if (CallExpr* call = toCallExpr(iteratorExpr))
  {
    // grab the stride if we have a strided range
    if (call->isNamed("chpl_by"))
    {
      range = toCallExpr(call->get(1)->copy());
      stride = toExpr(call->get(2)->copy());
    }
    // assume the call is the range (checked below) and set default stride
    else
    {
      range = call;
      stride = new SymExpr(new_IntSymbol(1));
    }
    // see if we're looking at a builder for a bounded range. the builder is
    // iteratable since range has these() iterators
    if (range && range->isNamed("chpl_build_bounded_range"))
    {
      // replace the range construction with a direct range iterator
      Expr* low = range->get(1)->copy();
      Expr* high = range->get(2)->copy();
      iteratorExpr->replace(new CallExpr("chpl_direct_range_iter", low, high, stride));
    }
  }
}
Exemple #3
0
UseStmt::UseStmt(BaseAST*                            source,
                 std::vector<const char*>*           args,
                 bool                                exclude,
                 std::map<const char*, const char*>* renames) :
  Stmt(E_UseStmt),
  src(NULL),
  named(),
  renamed(),
  except(exclude),
  relatedNames()
{
  if (Symbol* b = toSymbol(source)) {
    src = new SymExpr(b);
  } else if (Expr* b = toExpr(source)) {
    src = b;
  } else {
    INT_FATAL(this, "Bad mod in UseStmt constructor");
  }

  if (args->size() > 0) {
    // Symbols to search when going through this module's scope from an outside
    // scope
    for_vector(const char, str, *args) {
      named.push_back(str);
    }
  }
Exemple #4
0
void collect_stmts(BaseAST* ast, Vec<Expr*>& stmts) {
  if (Expr* expr = toExpr(ast)) {
    stmts.add(expr);
    if (isBlockStmt(expr) || isCondStmt(expr)) {
      AST_CHILDREN_CALL(ast, collect_stmts, stmts);
    }
  }
}
void collect_stmts_STL(BaseAST* ast, std::vector<Expr*>& stmts) {
  if (Expr* expr = toExpr(ast)) {
    stmts.push_back(expr);
    if (isBlockStmt(expr) || isCondStmt(expr)) {
      AST_CHILDREN_CALL(ast, collect_stmts_STL, stmts);
    }
  }
}
Exemple #6
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 #7
0
UseStmt::UseStmt(BaseAST* source) : Stmt(E_UseStmt) {
  src    = NULL;
  except = false;

  if (Symbol* b = toSymbol(source)) {
    src = new SymExpr(b);

  } else if (Expr* b = toExpr(source)) {
    src = b;

  } else {
    INT_FATAL(this, "Bad mod in UseStmt constructor");
  }

  gUseStmts.add(this);
}
Exemple #8
0
UseStmt::UseStmt(BaseAST* source):
  Stmt(E_UseStmt),
  src(NULL),
  named(),
  renamed(),
  except(false),
  relatedNames()
{
  if (Symbol* b = toSymbol(source)) {
    src = new SymExpr(b);
  } else if (Expr* b = toExpr(source)) {
    src = b;
  } else {
    INT_FATAL(this, "Bad mod in UseStmt constructor");
  }

  gUseStmts.add(this);
}
Exemple #9
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 #10
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)) {
void collectExprs(BaseAST* ast, std::vector<Expr*>& exprs) {
  AST_CHILDREN_CALL(ast, collectExprs, exprs);
  if (Expr* expr = toExpr(ast))
    exprs.push_back(expr);
}
Exemple #12
0
/*
 * Attempts to replace iteration over simple anonymous ranges with calls to
 * direct iterators that take low, high and stride as arguments. This is to
 * avoid the cost of constructing ranges, and if the stride is known at compile
 * time, provide a more optimized iterator that uses "<, <=, >, or >=" as the
 * relational operator.
 *
 * This is only meant to replace anonymous range iteration for "simple" ranges.
 * Simple means it's a range of the form "low..high", "low..high by stride", or
 * "low..#count". Anything more complex is ignored with the thinking that this
 * should optimize the most common range iterators, but it could be expanded to
 * handle more cases.
 *
 * An alternative is to update scalar replacement of aggregates to work on
 * ranges, which should be able to achieve similar results as this optimization
 * while handling all ranges, including non-anonymous ranges.
 *
 * This function will optimize things like:
 * - "for i in 1..10"
 * - "for i in 1..10+1"
 * - "var lo=1, hi=10;for i in lo..hi"
 * - "for i in 1..10 by 2"
 * - "for i in 1..#10"
 * - "for (i, j) in zip(1..10 by 2, 1..10 by -2)"
 * - "for (i, j) in zip(A, 1..10 by 2)" // will optimize range iter still
 * - "coforall i in 1..10 by 2"         // works for coforalls as well
 *
 * Will not optimize ranges like:
 * - "for in in (1..)"             // doesn't handle unbounded ranges
 * - "for i in 1..10 by 2 by 2"    // doesn't handle more than one by operator
 * - "for i in 1..10 align 2"      // doesn't handle align operator
 * - "for i in (1..10)#2"          // doesn't handle bounded counted ranges
 * - "for i in 1..#10 by 2"        // doesn't handle strided and counted ranges
 * - "var r = 1..10"; for i in r"  // not an anonymous range
 * - "forall i in 1..10"           // doesn't get applied to foralls
 *
 * Note that this function is pretty fragile because it relies on names of
 * functions/iterators as well as the arguments and order of those
 * functions/iterators but there's not really a way around it this early in
 * compilation. If the iterator can't be replaced, it is left unchanged.
 */
static void tryToReplaceWithDirectRangeIterator(Expr* iteratorExpr)
{
  if (CallExpr* call = toCallExpr(iteratorExpr))
  {
    CallExpr* range = NULL;
    Expr* stride = NULL;
    Expr* count = NULL;
    // grab the stride if we have a strided range
    if (call->isNamed("chpl_by"))
    {
      range = toCallExpr(call->get(1)->copy());
      stride = toExpr(call->get(2)->copy());
    }
    // or grab the count if we have a counted range and set unit stride
    else if (call->isNamed("#"))
    {
      range = toCallExpr(call->get(1)->copy());
      count = toExpr(call->get(2)->copy());
      stride = new SymExpr(new_IntSymbol(1));
    }
    // or assume the call is the range (checked below) and set unit stride
    else
    {
      range = call;
      stride = new SymExpr(new_IntSymbol(1));
    }

    //
    // see if we're looking at a range builder. The builder is iteratable since
    // range has these() iterators
    //

    // replace fully bounded (and possibly strided range) with a direct range
    // iter. e.g. replace:
    //
    //   `low..high by stride`
    //
    // with:
    //
    // `chpl_direct_range_iter(low, high, stride)`
    if (range && range->isNamed("chpl_build_bounded_range"))
    {
      // replace the range construction with a direct range iterator
      Expr* low = range->get(1)->copy();
      Expr* high = range->get(2)->copy();
      iteratorExpr->replace(new CallExpr("chpl_direct_range_iter", low, high, stride));
    }

    // replace a counted, low bounded range with unit stride with an equivalent
    // direct range iter. e.g. replace:
    //
    //   `low..#count` (which is equivalent to `low..low+count-1`)
    //
    // with:
    //
    //   `chpl_direct_range_iter(low, low+count-1, 1)`
    else if (count && range && range->isNamed("chpl_build_low_bounded_range"))
    {
      Expr* low = range->get(1)->copy();
      Expr* high = new CallExpr("-", new CallExpr("+", low->copy(), count), new_IntSymbol(1));
      iteratorExpr->replace(new CallExpr("chpl_direct_range_iter", low, high, stride));
    }
  }
}
Exemple #13
0
value caml_toExpr(value t)
{
  CAMLparam1(t);
  CAMLreturn(alloc_Expr(toExpr(Type_val(t))));
}
Exemple #14
0
static bool
printErrorHeader(BaseAST* ast) {
  if (!err_print) {
    if (Expr* expr = toExpr(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->hasFlag(FLAG_INLINE) &&
            err_fn->linenum()) {
          fprintf(stderr, "%s:%d: In ",
                  cleanFilename(err_fn), err_fn->linenum());
          if (!strncmp(err_fn->name, "_construct_", 11)) {
            fprintf(stderr, "initializer '%s':\n", err_fn->name+11);
          } 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;
}