forv_Vec(FnSymbol, fn, gFnSymbols) { if (VarSymbol* ret = toVarSymbol(fn->getReturnSymbol())) { // The return value of an initCopy function should not be autodestroyed. // Normally, the return value of a function is autoCopied, but since // autoCopy is typically defined in terms of initCopy, this would lead to // infinite recursion. That is, the return value of initCopy must be // handled specially. if (fn->hasFlag(FLAG_INIT_COPY_FN)) ret->removeFlag(FLAG_INSERT_AUTO_DESTROY); // This is just a workaround for memory management being handled specially // for internally reference-counted types. (sandboxing) TypeSymbol* ts = ret->type->symbol; if (ts->hasFlag(FLAG_ARRAY) || ts->hasFlag(FLAG_DOMAIN)) ret->removeFlag(FLAG_INSERT_AUTO_DESTROY); // Do we need to add other record-wrapped types here? Testing will tell. // NOTE 1: When the value of a record field is established in a default // constructor, it is initialized using a MOVE. That means that ownership // of that value is shared between the formal_tmp and the record field. // If the autodestroy flag is left on that formal temp, then it will be // destroyed which -- for ref-counted types -- can result in a dangling // reference. So here, we look for that case and remove it. if (fn->hasFlag(FLAG_DEFAULT_CONSTRUCTOR)) { Map<Symbol*,Vec<SymExpr*>*> defMap; Map<Symbol*,Vec<SymExpr*>*> useMap; buildDefUseMaps(fn, defMap, useMap); std::vector<DefExpr*> defs; collectDefExprs(fn, defs); for_vector(DefExpr, def, defs) { if (VarSymbol* var = toVarSymbol(def->sym)) { // Examine only those bearing the explicit autodestroy flag. if (! var->hasFlag(FLAG_INSERT_AUTO_DESTROY)) continue; // Look for a use in a PRIM_SET_MEMBER where the field is a record // type, and remove the flag. // (We don't actually check that var is of record type, because // chpl__autoDestroy() does nothing when applied to all other types. for_uses(se, useMap, var) { CallExpr* call = toCallExpr(se->parentExpr); if (call->isPrimitive(PRIM_SET_MEMBER) && toSymExpr(call->get(3))->var == var) var->removeFlag(FLAG_INSERT_AUTO_DESTROY); } } } freeDefUseMaps(defMap, useMap); }
void viewFlags(BaseAST* ast) { if (!viewFlagsShort && !viewFlagsName && !viewFlagsComment) viewFlagsName = true; if (Symbol* sym = toSymbol(ast)) { for (int flagNum = FLAG_FIRST; flagNum <= FLAG_LAST; flagNum++) { if (sym->flags[flagNum]) { if (viewFlagsName) printf("%s ", flagNames[flagNum]); if (viewFlagsPragma) printf("%s", flagPragma[flagNum] ? "ypr " : "npr "); if (viewFlagsShort) printf("\"%s\" ", flagShortNames[flagNum]); if (viewFlagsComment) printf("// %s", *flagComments[flagNum] ? flagComments[flagNum] : "ncm"); printf("\n"); } } if (viewFlagsExtras) { if (VarSymbol* vs = toVarSymbol(sym)) { if (vs->immediate) { printf("immediate "); fprint_imm(stdout, *toVarSymbol(sym)->immediate, true); printf("\n"); } } else if (ArgSymbol* as = toArgSymbol(sym)) { printf("%s arg\n", as->intentDescrString()); } else if (toTypeSymbol(sym)) { printf("a TypeSymbol\n"); } else if (FnSymbol* fs = toFnSymbol(sym)) { printf("fn %s(%d args) %s\n", fs->_this ? intentDescrString(fs->thisTag) : "", fs->numFormals(), retTagDescrString(fs->retTag)); } else if (toEnumSymbol(sym)) { printf("an EnumSymbol\n"); } else if (ModuleSymbol* ms = toModuleSymbol(sym)) { printf("module %s\n", modTagDescrString(ms->modTag)); } else if (toLabelSymbol(sym)) { printf("a LabelSymbol\n"); } else { printf("unknown symbol kind\n"); } } } else { printf("[%d]: not a Symbol, has no flags\n", ast->id); } }
static void list_sym(Symbol* sym, bool type = true) { if (VarSymbol* var = toVarSymbol(sym)) { if (var->immediate) { if (var->immediate->const_kind == NUM_KIND_INT) { printf("%"PRId64" ", var->immediate->int_value()); return; } else if (var->immediate->const_kind == CONST_KIND_STRING) { printf("\"%s\" ", var->immediate->v_string); return; } } } if (toFnSymbol(sym)) { printf("fn "); } else if (toArgSymbol(sym)) { printf("arg "); } else if (toTypeSymbol(sym)) { printf("type "); } printf("%s", sym->name); printf("[%d]", sym->id); if (!type) { printf(" "); } else if (FnSymbol* fn = toFnSymbol(sym)) { printf(":%s", fn->retType->symbol->name); printf("[%d] ", fn->retType->symbol->id); } else if (sym->type && sym->type->symbol) { printf(":%s", sym->type->symbol->name); printf("[%d] ", sym->type->symbol->id); } else { printf(" "); } }
IpeValue IpeEnv::valueForVariable(LcnSymbol* lcn) const { IpeValue retval; if (lcn->isImmediate() == true) { VarSymbol* var = toVarSymbol(lcn); Immediate* imm = var->immediate; Type* type = var->type; INT_ASSERT(type); INT_ASSERT(type->symbol); INT_ASSERT(type->symbol->name); if (strcmp(type->symbol->name, "bool") == 0) retval.boolSet(imm->v_bool); else if (strcmp(type->symbol->name, "int") == 0) retval.integerSet(imm->v_int64); else if (strcmp(type->symbol->name, "real") == 0) retval.realSet(imm->v_float64); else if (strcmp(type->symbol->name, "c_string") == 0) retval.cstringSet(imm->v_string); else INT_ASSERT(false); } else retval = valueFetch(lcn); return retval; }
// // SymExpr // void AstDumpToHtml::visitSymExpr(SymExpr* node) { Symbol* sym = node->var; VarSymbol* var = toVarSymbol(sym); if (isBlockStmt(node->parentExpr) == true) { fprintf(mFP, "<DL>\n"); } fprintf(mFP, " "); if (var != 0 && var->immediate != 0) { const size_t bufSize = 128; char imm[bufSize]; snprint_imm(imm, bufSize, *var->immediate); fprintf(mFP, "<i><FONT COLOR=\"blue\">%s%s</FONT></i>", imm, is_imag_type(var->type) ? "i" : ""); } else { writeSymbol(sym, false); } if (isBlockStmt(node->parentExpr)) { fprintf(mFP, "</DL>\n"); } }
forv_Vec(DefExpr, def, gDefExprs) { if (toVarSymbol(def->sym)) { // The test for FLAG_TEMP allows compiler-generated (temporary) variables // to be declared without an explicit type or initializer expression. if ((!def->init || def->init->isNoInitExpr()) && !def->exprType && !def->sym->hasFlag(FLAG_TEMP)) if (isBlockStmt(def->parentExpr) && !isArgSymbol(def->parentSymbol)) if (def->parentExpr != rootModule->block && def->parentExpr != stringLiteralModule->block) if (!def->sym->hasFlag(FLAG_INDEX_VAR)) USR_FATAL_CONT(def->sym, "Variable '%s' is not initialized or has no type", def->sym->name); } // // This test checks to see if query domains (e.g., '[?D]') are // used in places other than formal argument type specifiers. // if (!isFnSymbol(def->parentSymbol)) { if (CallExpr* type = toCallExpr(def->exprType)) { if (type->isNamed("chpl__buildArrayRuntimeType")) { if (CallExpr* domainExpr = toCallExpr(type->get(1))) { DefExpr* queryDomain = toDefExpr(domainExpr->get(1)); if (queryDomain) { USR_FATAL_CONT(queryDomain, "Domain query expressions may currently only be used in formal argument types"); } } } } } checkPrivateDecls(def); }
void IpeModuleRoot::init() { mState = kResolved; initialize(); for (int i = 1; i <= sHighWater; i++) { DefExpr* expr = toDefExpr(rootModule->block->body.get(i)); INT_ASSERT(expr); if (mEnv->findLocal(expr->sym->name) != NULL) { printf(" Attempt to redefine identifier %s\n", expr->sym->name); INT_ASSERT(false); } else if (TypeSymbol* sym = toTypeSymbol(expr->sym)) { int offset = mEnv->allocateValue(sym->type); VarSymbol* var = new VarSymbol(sym->name, gIpeTypeType); INT_ASSERT(expr->exprType == NULL); INT_ASSERT(expr->init == NULL); var->addFlag(FLAG_CONST); var->locationSet(0, offset); mEnv->varAdd(var); } else if (expr->sym->isImmediate() == true) { VarSymbol* var = toVarSymbol(expr->sym); int offset = mEnv->allocateValue(var->type); var->addFlag(FLAG_CONST); var->locationSet(0, offset); mEnv->varAdd(var); } else { AstDumpToNode logger(stdout, 3); printf("Unexpected expression while initializing RootModule\n"); printf(" "); expr->accept(&logger); printf("\n"); INT_ASSERT(false); } } moduleAdd(this); }
// // A forall-intents variation on findOuterVars() in createTaskFunctions.cpp: // Find all symbols used in 'block' and defined outside of it. // static void findOuterVars(BlockStmt* block, SymbolMap* uses) { std::vector<SymExpr*> symExprs; collectSymExprsSTL(block, symExprs); for_vector(SymExpr, symExpr, symExprs) { Symbol* sym = symExpr->var; if (toVarSymbol(sym) || toArgSymbol(sym)) if (!isCorrespIndexVar(block, sym) && isOuterVar(sym, block)) uses->put(sym,gNil); }
// Walk backwards from the current statement to determine if a sequence of // moves have copied a variable that is marked for auto destruction in to // the dedicated return-temp within the current scope. // // Note that the value we are concerned about may be copied in to one or // more temporary variables between being copied to the return temp. static VarSymbol* variableToExclude(FnSymbol* fn, Expr* refStmt) { VarSymbol* retVar = toVarSymbol(fn->getReturnSymbol()); VarSymbol* retval = NULL; if (retVar != NULL) { if (isUserDefinedRecord(retVar) == true || fn->hasFlag(FLAG_INIT_COPY_FN) == true) { VarSymbol* needle = retVar; Expr* expr = refStmt; // Walk backwards looking for the variable that is being returned while (retval == NULL && expr != NULL && needle != NULL) { if (CallExpr* move = toCallExpr(expr)) { if (move->isPrimitive(PRIM_MOVE) == true) { SymExpr* lhs = toSymExpr(move->get(1)); VarSymbol* lhsVar = toVarSymbol(lhs->symbol()); if (needle == lhsVar) { if (SymExpr* rhs = toSymExpr(move->get(2))) { VarSymbol* rhsVar = toVarSymbol(rhs->symbol()); if (isAutoDestroyedVariable(rhsVar) == true) { retval = rhsVar; } else { needle = rhsVar; } } else { needle = NULL; } } } } expr = expr->prev; } } } return retval; }
static Expr* postFoldNormal(CallExpr* call) { FnSymbol* fn = call->resolvedFunction(); Expr* retval = call; if (fn->retTag == RET_PARAM || fn->hasFlag(FLAG_MAYBE_PARAM) == true) { VarSymbol* ret = toVarSymbol(fn->getReturnSymbol()); if (ret != NULL && ret->immediate != NULL) { retval = new SymExpr(ret); call->replace(retval); } else if (EnumSymbol* es = toEnumSymbol(fn->getReturnSymbol())) { retval = new SymExpr(es); call->replace(retval); } else if (ret == gVoid) { retval = new SymExpr(gVoid); call->replace(retval); } } if (fn->hasFlag(FLAG_MAYBE_TYPE) == true && fn->getReturnSymbol()->hasFlag(FLAG_TYPE_VARIABLE) == true) { fn->retTag = RET_TYPE; } if (fn->retTag == RET_TYPE) { Symbol* ret = fn->getReturnSymbol(); if (ret->type->symbol->hasFlag(FLAG_HAS_RUNTIME_TYPE) == false) { retval = new SymExpr(ret->type->symbol); call->replace(retval); } } if (call->isNamedAstr(astrSequals) == true) { if (SymExpr* lhs = toSymExpr(call->get(1))) { if (lhs->symbol()->hasFlag(FLAG_MAYBE_PARAM) == true || lhs->symbol()->isParameter() == true) { if (paramMap.get(lhs->symbol())) { USR_FATAL(call, "parameter set multiple times"); } } } } return retval; }
void localizeGlobals() { if (fNoGlobalConstOpt) return; forv_Vec(FnSymbol, fn, gFnSymbols) { Map<Symbol*,VarSymbol*> globals; std::vector<BaseAST*> asts; collect_asts(fn->body, asts); for_vector(BaseAST, ast, asts) { if (SymExpr* se = toSymExpr(ast)) { Symbol* var = se->symbol(); ModuleSymbol* parentmod = toModuleSymbol(var->defPoint->parentSymbol); CallExpr* parentExpr = toCallExpr(se->parentExpr); bool inAddrOf = parentExpr && parentExpr->isPrimitive(PRIM_ADDR_OF); bool lhsOfMove = parentExpr && isMoveOrAssign(parentExpr) && (parentExpr->get(1) == se); // Is var a global constant? // Don't replace the var name in its init function since that's // where we're setting the value. Similarly, dont replace them // inside initStringLiterals // If the parentSymbol is the rootModule, the var is 'void,' // 'false,' '0,' ... // Also don't replace it when it's in an addr of primitive. if (parentmod && fn != parentmod->initFn && fn != initStringLiterals && !inAddrOf && !lhsOfMove && var->hasFlag(FLAG_CONST) && var->defPoint->parentSymbol != rootModule) { VarSymbol* local_global = globals.get(var); SET_LINENO(se); // Set the se line number for output if (!local_global) { const char * newname = astr("local_", var->cname); local_global = newTemp(newname, var->type); fn->insertAtHead(new CallExpr(PRIM_MOVE, local_global, var)); fn->insertAtHead(new DefExpr(local_global)); // Copy string immediates to localized strings so that // we can show the string value in comments next to uses. if (!llvmCodegen) if (VarSymbol* localVarSym = toVarSymbol(var)) if (Immediate* immediate = localVarSym->immediate) if (immediate->const_kind == CONST_KIND_STRING) local_global->immediate = new Immediate(immediate->v_string, immediate->string_kind); globals.put(var, local_global); } se->replace(new SymExpr(toSymbol(local_global))); } } } }
// // finds outer vars directly used in a function // static void findOuterVars(FnSymbol* fn, SymbolMap* uses) { Vec<BaseAST*> asts; collect_asts(fn, asts); forv_Vec(BaseAST, ast, asts) { if (SymExpr* symExpr = toSymExpr(ast)) { Symbol* sym = symExpr->var; if (toVarSymbol(sym) || toArgSymbol(sym)) if (isOuterVar(sym, fn)) uses->put(sym,gNil); } } }
forv_Vec(DefExpr, def, gDefExprs) { if (toVarSymbol(def->sym)) // The test for FLAG_TEMP allows compiler-generated (temporary) variables // to be declared without an explicit type or initializer expression. if ((!def->init || def->init->isNoInitExpr()) && !def->exprType && !def->sym->hasFlag(FLAG_TEMP)) if (isBlockStmt(def->parentExpr) && !isArgSymbol(def->parentSymbol)) if (def->parentExpr != rootModule->block) if (!def->sym->hasFlag(FLAG_INDEX_VAR)) USR_FATAL_CONT(def->sym, "Variable '%s' is not initialized or has no type", def->sym->name); }
// // Consider a function that takes a formal of type Record by const ref // and that returns that value from the function. The compiler inserts // a PRIM_MOVE operation. // // This work-around inserts an autoCopy to compensate // void ReturnByRef::updateAssignmentsFromRefArgToValue(FnSymbol* fn) { std::vector<CallExpr*> callExprs; collectCallExprs(fn, callExprs); for (size_t i = 0; i < callExprs.size(); i++) { CallExpr* move = callExprs[i]; if (move->isPrimitive(PRIM_MOVE) == true) { SymExpr* lhs = toSymExpr(move->get(1)); SymExpr* rhs = toSymExpr(move->get(2)); if (lhs != NULL && rhs != NULL) { VarSymbol* symLhs = toVarSymbol(lhs->symbol()); ArgSymbol* symRhs = toArgSymbol(rhs->symbol()); if (symLhs != NULL && symRhs != NULL) { if (isUserDefinedRecord(symLhs->type) == true && symRhs->type == symLhs->type) { if (symLhs->hasFlag(FLAG_ARG_THIS) == false && (symRhs->intent == INTENT_REF || symRhs->intent == INTENT_CONST_REF)) { SET_LINENO(move); CallExpr* autoCopy = NULL; rhs->remove(); autoCopy = new CallExpr(autoCopyMap.get(symRhs->type), rhs); move->insertAtTail(autoCopy); } } } } } } }
static QualifiedType returnInfoGetMember(CallExpr* call) { AggregateType* ct = toAggregateType(call->get(1)->typeInfo()); if (ct->symbol->hasFlag(FLAG_REF)) ct = toAggregateType(ct->getValType()); if (!ct) INT_FATAL(call, "bad member primitive"); SymExpr* sym = toSymExpr(call->get(2)); if (!sym) INT_FATAL(call, "bad member primitive"); VarSymbol* var = toVarSymbol(sym->symbol()); if (!var) INT_FATAL(call, "bad member primitive"); if (var->immediate) { const char* name = var->immediate->v_string; for_fields(field, ct) { if (!strcmp(field->name, name)) return field->qualType(); } } else return sym->qualType();
const char* CallInfo::toString() { bool method = false; bool _this = false; int start = 0; const char* retval = ""; if (actuals.n > 1 && actuals.head()->type == dtMethodToken) { method = true; start = 2; } if (name == astrThis) { _this = true; method = false; start = 2; } if (method == true) { if (actuals.v[1] && actuals.v[1]->hasFlag(FLAG_TYPE_VARIABLE)) { retval = astr(retval, "type ", ::toString(actuals.v[1]->type), "."); } else { retval = astr(retval, ::toString(actuals.v[1]->type), "."); } } if (developer == false && strncmp("_type_construct_", name, 16) == 0) { retval = astr(retval, name+16); } else if (developer == false && strncmp("_construct_", name, 11) == 0) { retval = astr(retval, name + 11); retval = astr(retval, ".init"); } else if (_this == false) { retval = astr(retval, name); } if (call->methodTag == false) { if (call->square == true) { retval = astr(retval, "["); } else { retval = astr(retval, "("); } } for (int i = start; i < actuals.n; i++) { Symbol* sym = actuals.v[i]; VarSymbol* var = toVarSymbol(sym); Type* type = sym->type; AggregateType* at = toAggregateType(type); IteratorInfo* ii = (at != NULL) ? at->iteratorInfo : NULL; if (i > start) { retval = astr(retval, ", "); } if (actualNames.v[i] != NULL) { retval = astr(retval, actualNames.v[i], "="); } if (type->symbol->hasFlag(FLAG_ITERATOR_RECORD) == true && ii->iterator->hasFlag(FLAG_PROMOTION_WRAPPER) == true) { retval = astr(retval, "promoted expression"); } else if (sym->hasFlag(FLAG_TYPE_VARIABLE) == true) { retval = astr(retval, "type ", ::toString(type)); } else if (var != NULL && var->immediate != NULL) { if (var->immediate->const_kind == CONST_KIND_STRING) { retval = astr(retval, "\"", var->immediate->v_string, "\""); } else { const size_t bufSize = 512; char buff[bufSize]; snprint_imm(buff, bufSize, *var->immediate); retval = astr(retval, buff); } } else { retval = astr(retval, ::toString(type)); } } if (call->methodTag == false) { if (call->square == true) { retval = astr(retval, "]"); } else { retval = astr(retval, ")"); } } return retval; }
// This routine looks for loops in which the condition variable is *not* // updated within the body of the loop, and issues a warning for places // in the code where that occurs. void WhileStmt::checkConstLoops() { SymExpr* tmpVar = condExprForTmpVariableGet(); // Get the loop condition variable. if (VarSymbol* condSym = toVarSymbol(tmpVar->symbol())) { // Look for definitions of the loop condition variable // within the body of the loop. if (SymExpr* condDef = getWhileCondDef(condSym)) { // Get the call expression that updates the condition variable. if (CallExpr* outerCall = toCallExpr(condDef->parentExpr)) { // Assume the outer call is a move expression and that its LHS is // the (SymExpr that contains the) loop condition variable. if (outerCall->get(1) == condDef) { if (outerCall->isPrimitive(PRIM_MOVE)) { // Expect the update to be the result of a call to _cond_test. if (CallExpr* innerCall = toCallExpr(outerCall->get(2))) { FnSymbol* fn = innerCall->resolvedFunction(); if (innerCall->numActuals() == 1 && strcmp(fn->name, "_cond_test") == 0) { checkWhileLoopCondition(innerCall->get(1)); } else { INT_FATAL(innerCall, "Expected the update of a loop conditional " "to be piped through _cond_test()."); } } // The RHS of the move can also be a SymExpr as the result of param // folding ... else if (SymExpr* moveSrc = toSymExpr(outerCall->get(2))) { // ... in which case, the literal should be 'true' or 'false'. if (moveSrc->symbol() == gTrue) { // while true do ... ; -- probably OK. // User said to loop forever ... . } else if (moveSrc->symbol() == gFalse) { // while false do ...; -- probably nothing to worry about // We probably don't get here unless fRemoveUnreachableBlocks // is false. } else { INT_FATAL(moveSrc, "Expected const loop condition variable to be " "true or false."); } } else { // The RHS was neither a CallExpr nor a SymExpr. INT_FATAL(outerCall, "Invalid RHS in a loop condition variable update " "expression."); } } else { INT_FATAL(outerCall, "Expected a loop condition variable update to " "be a MOVE."); } } else { // Note that this being true depends on the compiler inserting a temp // that is the result of applying _cond_test to a more-general loop // conditional expression. // Copy propagation could potentially make this false again.... INT_FATAL(condDef, "Expected loop condition variable to be only " "updated (not read)."); } } else { INT_FATAL(condDef, "The update of a loop condition variable could not " "be converted to a call."); } } else { // There was no update of the loop condition variable in the // body of the loop. // It could be an infinite loop, or it could have a // 'break' or 'return' in it. } } else { INT_FATAL(tmpVar, "The loop condition variable could not be converted " "to a VarSymbol."); } }
void IpeEnv::describe(const char* pad, int index, LcnSymbol* var) const { const char* symName = var->name; const char* typeName = ""; ArgSymbol* argSym = toArgSymbol(var); VarSymbol* varSym = toVarSymbol(var); if (var->type) typeName = var->type->symbol->name; printf("%s %5d: %-30s", pad, index, symName); if (argSym != NULL) { if (argSym->intent & INTENT_REF) printf("ref %-12s", typeName); else printf("arg %-12s", typeName); } else if (varSym->immediate != NULL) printf("const %-12s", typeName); else if (varSym->hasFlag(FLAG_CONST) == true) printf("const %-12s", typeName); else if (varSym->hasFlag(FLAG_PARAM) == true) printf("param %-12s", typeName); else printf("var %-12s", typeName); if (var->depth() >= 0 && var->offset() >= 0) printf("%4d %4d ", var->depth(), var->offset()); else printf(" "); if (argSym != NULL && (argSym->intent & INTENT_REF) != 0) { if (mFrameData != NULL) { int offset = argSym->offset(); IpeValue* ref = *((IpeValue**) (((char*) mFrameData) + offset)); printf("0x%012lX", (long) ref); } } else if (var->offset() < 0) ; else if (var->type == NULL) ; else if (var->type == gIpeTypeType) printf("%s", symName); else if (var->type == dtBool) { if (mDepth == 0 || mFrameData != NULL) printf("%s", (fetchBool(var) == true) ? "true" : "false"); } else if (var->type == dtInt[INT_SIZE_64]) { if (mDepth == 0 || mFrameData != NULL) printf("%8ld", fetchInteger(var)); } else if (var->type == dtReal[FLOAT_SIZE_64]) { if (mDepth == 0 || mFrameData != NULL) printf(" %8.2f", fetchReal(var)); } else if (var->type == gIpeTypeModule) { if (mDepth == 0 || mFrameData != NULL) { IpeModule* value = (IpeModule*) fetchPtr(var); printf("#<IpeModule %-20s 0x%012lX>", value->name(), (long) value); } } else if (var->type == gIpeTypeProcedure) { if (mDepth == 0 || mFrameData != NULL) { IpeProcedure* value = (IpeProcedure*) fetchPtr(var); if (value->methodCount() == 1) printf("#<IpeProcedure %-20s with %3d method 0x%012lX>", value->name(), value->methodCount(), (long) value); else printf("#<IpeProcedure %-20s with %3d methods 0x%012lX>", value->name(), value->methodCount(), (long) value); } } else printf("Really?? Really??"); printf("\n"); }
void ReturnByRef::updateAssignmentsFromRefTypeToValue(FnSymbol* fn) { std::vector<CallExpr*> callExprs; collectCallExprs(fn, callExprs); Map<Symbol*,Vec<SymExpr*>*> defMap; Map<Symbol*,Vec<SymExpr*>*> useMap; buildDefUseMaps(fn, defMap, useMap); for (size_t i = 0; i < callExprs.size(); i++) { CallExpr* move = callExprs[i]; if (move->isPrimitive(PRIM_MOVE) == true) { SymExpr* symLhs = toSymExpr (move->get(1)); CallExpr* callRhs = toCallExpr(move->get(2)); if (symLhs && callRhs && callRhs->isPrimitive(PRIM_DEREF)) { VarSymbol* varLhs = toVarSymbol(symLhs->symbol()); SymExpr* symRhs = toSymExpr(callRhs->get(1)); VarSymbol* varRhs = toVarSymbol(symRhs->symbol()); // MPF 2016-10-02: It seems to me that this code should also handle the // case that symRhs is an ArgSymbol, but adding that caused problems // in the handling of out argument intents. if (varLhs != NULL && varRhs != NULL) { if (isUserDefinedRecord(varLhs->type) == true && varRhs->type == varLhs->type->refType) { // HARSHBARGER 2015-12-11: // `init_untyped_var` in the `normalize` pass may insert an // initCopy, which means that we should not insert an autocopy // for that same variable. bool initCopied = false; for_uses(use, useMap, varLhs) { if (CallExpr* call = toCallExpr(use->parentExpr)) { if (FnSymbol* parentFn = call->isResolved()) { if (parentFn->hasFlag(FLAG_INIT_COPY_FN)) { initCopied = true; break; } } } } if (!initCopied) { SET_LINENO(move); SymExpr* lhsCopy0 = symLhs->copy(); SymExpr* lhsCopy1 = symLhs->copy(); FnSymbol* autoCopy = autoCopyMap.get(varLhs->type); CallExpr* copyExpr = new CallExpr(autoCopy, lhsCopy0); CallExpr* moveExpr = new CallExpr(PRIM_MOVE,lhsCopy1, copyExpr); move->insertAfter(moveExpr); } } } }
CallExpr* ParamForLoop::foldForResolve() { SymExpr* idxExpr = indexExprGet(); SymExpr* lse = lowExprGet(); SymExpr* hse = highExprGet(); SymExpr* sse = strideExprGet(); if (!lse || !hse || !sse) USR_FATAL(this, "param for loop must be defined over a bounded param range"); VarSymbol* lvar = toVarSymbol(lse->var); VarSymbol* hvar = toVarSymbol(hse->var); VarSymbol* svar = toVarSymbol(sse->var); CallExpr* noop = new CallExpr(PRIM_NOOP); if (!lvar || !hvar || !svar) USR_FATAL(this, "param for loop must be defined over a bounded param range"); if (!lvar->immediate || !hvar->immediate || !svar->immediate) USR_FATAL(this, "param for loop must be defined over a bounded param range"); Symbol* idxSym = idxExpr->var; Symbol* continueSym = continueLabelGet(); Type* idxType = indexType(); IF1_int_type idxSize = (get_width(idxType) == 32) ? INT_SIZE_32 : INT_SIZE_64; // Insert an "insertion marker" for loop unrolling insertAfter(noop); if (is_int_type(idxType)) { int64_t low = lvar->immediate->to_int(); int64_t high = hvar->immediate->to_int(); int64_t stride = svar->immediate->to_int(); if (stride <= 0) { for (int64_t i = high; i >= low; i += stride) { SymbolMap map; map.put(idxSym, new_IntSymbol(i, idxSize)); copyBodyHelper(noop, i, &map, this, continueSym); } } else { for (int64_t i = low; i <= high; i += stride) { SymbolMap map; map.put(idxSym, new_IntSymbol(i, idxSize)); copyBodyHelper(noop, i, &map, this, continueSym); } } } else { INT_ASSERT(is_uint_type(idxType) || is_bool_type(idxType)); uint64_t low = lvar->immediate->to_uint(); uint64_t high = hvar->immediate->to_uint(); int64_t stride = svar->immediate->to_int(); if (stride <= 0) { for (uint64_t i = high; i >= low; i += stride) { SymbolMap map; map.put(idxSym, new_UIntSymbol(i, idxSize)); copyBodyHelper(noop, i, &map, this, continueSym); } } else { for (uint64_t i = low; i <= high; i += stride) { SymbolMap map; map.put(idxSym, new_UIntSymbol(i, idxSize)); copyBodyHelper(noop, i, &map, this, continueSym); } } } // Remove the "insertion marker" noop->remove(); // Replace the paramLoop with the NO-OP replace(noop); return noop; }
// 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; }
// // 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; }
void AutoDestroyScope::variablesDestroy(Expr* refStmt, VarSymbol* excludeVar, std::set<VarSymbol*>* ignored) const { // Handle the primary locals if (mLocalsHandled == false) { Expr* insertBeforeStmt = refStmt; Expr* noop = NULL; size_t count = mLocalsAndDefers.size(); // If this is a simple nested block, insert after the final stmt // But always insert the destruction calls in reverse declaration order. // Do not get tricked by sequences of unreachable code if (refStmt->next == NULL) { if (mParent != NULL && isGotoStmt(refStmt) == false) { SET_LINENO(refStmt); // Add a PRIM_NOOP to insert before noop = new CallExpr(PRIM_NOOP); refStmt->insertAfter(noop); insertBeforeStmt = noop; } } for (size_t i = 1; i <= count; i++) { BaseAST* localOrDefer = mLocalsAndDefers[count - i]; VarSymbol* var = toVarSymbol(localOrDefer); DeferStmt* defer = toDeferStmt(localOrDefer); // This code only handles VarSymbols and DeferStmts. // It handles both in one vector because the order // of interleaving matters. INT_ASSERT(var || defer); if (var != NULL && var != excludeVar && (ignored == NULL || ignored->count(var) == 0)) { if (FnSymbol* autoDestroyFn = autoDestroyMap.get(var->type)) { SET_LINENO(var); INT_ASSERT(autoDestroyFn->hasFlag(FLAG_AUTO_DESTROY_FN)); CallExpr* autoDestroy = new CallExpr(autoDestroyFn, var); insertBeforeStmt->insertBefore(autoDestroy); } } if (defer != NULL) { SET_LINENO(defer); BlockStmt* deferBlockCopy = defer->body()->copy(); insertBeforeStmt->insertBefore(deferBlockCopy); deferBlockCopy->flattenAndRemove(); } } // remove the PRIM_NOOP if we added one. if (noop != NULL) noop->remove(); } // Handle the formal temps if (isReturnStmt(refStmt) == true) { size_t count = mFormalTemps.size(); for (size_t i = 1; i <= count; i++) { VarSymbol* var = mFormalTemps[count - i]; if (FnSymbol* autoDestroyFn = autoDestroyMap.get(var->type)) { SET_LINENO(var); refStmt->insertBefore(new CallExpr(autoDestroyFn, var)); } } } }