void initForTaskIntents() { FnSymbol* tiMarkHost = NULL; markPruned = gVoid; markUnspecified = gNil; tiMarkBlank = new ArgSymbol(INTENT_BLANK, "tiMarkBlank", dtVoid); tiMarkIn = new ArgSymbol(INTENT_IN, "tiMarkIn", dtVoid); tiMarkConstDflt = new ArgSymbol(INTENT_CONST, "tiMarkConstDflt", dtVoid); tiMarkConstIn = new ArgSymbol(INTENT_CONST_IN, "tiMarkConstIn", dtVoid); tiMarkConstRef = new ArgSymbol(INTENT_CONST_REF, "tiMarkConstRef", dtVoid); tiMarkRef = new ArgSymbol(INTENT_REF, "tiMarkRef", dtVoid); tiMarkHost = new FnSymbol("tiMarkHost"); tiMarkHost->insertFormalAtTail(tiMarkBlank); tiMarkHost->insertFormalAtTail(tiMarkIn); tiMarkHost->insertFormalAtTail(tiMarkConstDflt); tiMarkHost->insertFormalAtTail(tiMarkConstIn); tiMarkHost->insertFormalAtTail(tiMarkConstRef); tiMarkHost->insertFormalAtTail(tiMarkRef); tiMarkHost->insertAtTail(new CallExpr(PRIM_RETURN, gVoid)); rootModule->block->insertAtTail(new DefExpr(tiMarkHost)); }
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; }
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; }