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; }
// // 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); } }
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; }