Exemple #1
0
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;
}
Exemple #2
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;
}
 for_fields(field, copy_type) {
   if (FnSymbol* fn = toFnSymbol(field)) {
     copy_type->methods.add(fn);
   }
 }
Exemple #4
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 (LoopExpr* e = toLoopExpr(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 (LoopExpr* e = toLoopExpr(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)) {
static
bool symExprIsUsedAsConstRef(SymExpr* use) {
  if (CallExpr* call = toCallExpr(use->parentExpr)) {
    if (FnSymbol* calledFn = call->resolvedFunction()) {
      ArgSymbol* formal = actual_to_formal(use);

      // generally, use const-ref-return if passing to const ref formal
      if (formal->intent == INTENT_CONST_REF) {
        // but make an exception for initCopy calls
        if (calledFn->hasFlag(FLAG_INIT_COPY_FN))
          return false;

        // TODO: tuples of types with blank intent
        // being 'in' should perhaps use the value version.
        return true;
      }

    } else if (call->isPrimitive(PRIM_RETURN) ||
               call->isPrimitive(PRIM_YIELD)) {
      FnSymbol* inFn = toFnSymbol(call->parentSymbol);

      // use const-ref-return if returning by const ref intent
      if (inFn->retTag == RET_CONST_REF)
        return true;

    } else if (call->isPrimitive(PRIM_WIDE_GET_LOCALE) ||
               call->isPrimitive(PRIM_WIDE_GET_NODE)) {
      // If we are extracting a field from the wide pointer,
      // we need to keep it as a pointer.

      // use const-ref-return if querying locale
      return true;

    } else {
      // Check for the case that sym is moved to a compiler-introduced
      // variable, possibly with PRIM_MOVE tmp, PRIM_ADDR_OF sym
      if (call->isPrimitive(PRIM_ADDR_OF) ||
          call->isPrimitive(PRIM_SET_REFERENCE) ||
          call->isPrimitive(PRIM_GET_MEMBER) ||
          call->isPrimitive(PRIM_GET_SVEC_MEMBER))
        call = toCallExpr(call->parentExpr);

      if (call->isPrimitive(PRIM_MOVE)) {
        SymExpr* lhs = toSymExpr(call->get(1));
        Symbol* lhsSymbol = lhs->symbol();

        if (lhsSymbol->hasFlag(FLAG_REF_VAR)) {
          // intended to handle 'const ref'
          // it would be an error to reach this point if it is not const
          INT_ASSERT(lhsSymbol->hasFlag(FLAG_CONST));
          return true;
        }

        if (lhs != use &&
            lhsSymbol->isRef() &&
            symbolIsUsedAsConstRef(lhsSymbol))
          return true;
      }
    }
  }
  return false;
}
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;
}