Expression *Expression::inlineCopy(Scope *sc) { #if 0 /* See Bugzilla 2935 for explanation of why just a copy() is broken */ return copy(); #else if (op == TOKdelegate) { DelegateExp *de = (DelegateExp *)this; if (de->func->isNested()) { /* See Bugzilla 4820 * Defer checking until later if we actually need the 'this' pointer */ Expression *e = de->copy(); return e; } } InlineCostState ics; memset(&ics, 0, sizeof(ics)); ics.hdrscan = 1; // so DeclarationExp:: will work on 'statics' which are not int cost = expressionInlineCost(this, &ics); if (cost >= COST_MAX) { error("cannot inline default argument %s", toChars()); return new ErrorExp(); } InlineDoState ids; memset(&ids, 0, sizeof(ids)); ids.parent = sc->parent; Expression *e = doInline(&ids); return e; #endif }
Expression *Expression::inlineCopy(Scope *sc) { #if 0 /* See Bugzilla 2935 for explanation of why just a copy() is broken */ return copy(); #else InlineCostState ics; memset(&ics, 0, sizeof(ics)); ics.hdrscan = 1; // so DeclarationExp:: will work on 'statics' which are not int cost = inlineCost(&ics); if (cost >= COST_MAX) { error("cannot inline default argument %s", toChars()); return new ErrorExp(); } InlineDoState ids; memset(&ids, 0, sizeof(ids)); ids.parent = sc->parent; Expression *e = doInline(&ids); return e; #endif }
int linkExecutable(const char* argv0) { Logger::println("*** Linking executable ***"); // error string std::string errstr; // find the llvm-ld program llvm::sys::Path ldpath = llvm::sys::Program::FindProgramByName("llvm-ld"); if (ldpath.isEmpty()) { ldpath.set("llvm-ld"); } // build arguments std::vector<const char*> args; // first the program name ?? args.push_back("llvm-ld"); // output filename std::string exestr; if (global.params.exefile) { // explicit exestr = global.params.exefile; } else { // inferred // try root module name if (Module::rootModule) exestr = Module::rootModule->toChars(); else exestr = "a.out"; } if (global.params.os == OSWindows && !(exestr.substr(exestr.length()-4) == ".exe")) exestr.append(".exe"); std::string outopt = "-o=" + exestr; args.push_back(outopt.c_str()); // set the global gExePath gExePath.set(exestr); assert(gExePath.isValid()); // create path to exe llvm::sys::Path exedir(llvm::sys::path::parent_path(gExePath.str())); if (!llvm::sys::fs::exists(exedir.str())) { exedir.createDirectoryOnDisk(true, &errstr); if (!errstr.empty()) { error("failed to create path to linking output: %s\n%s", exedir.c_str(), errstr.c_str()); fatal(); } } // strip debug info if (!global.params.symdebug) args.push_back("-strip-debug"); // optimization level if (!optimize()) args.push_back("-disable-opt"); else { switch(optLevel()) { case 0: args.push_back("-disable-opt"); break; case 1: args.push_back("-globaldce"); args.push_back("-disable-opt"); args.push_back("-globaldce"); args.push_back("-mem2reg"); case 2: case 3: case 4: case 5: // use default optimization break; default: assert(0); } } // inlining if (!(global.params.useInline || doInline())) { args.push_back("-disable-inlining"); } // additional linker switches for (unsigned i = 0; i < global.params.linkswitches->dim; i++) { char *p = (char *)global.params.linkswitches->data[i]; args.push_back(p); } // native please args.push_back("-native"); // user libs for (unsigned i = 0; i < global.params.libfiles->dim; i++) { char *p = (char *)global.params.libfiles->data[i]; args.push_back(p); } // default libs switch(global.params.os) { case OSLinux: case OSMacOSX: args.push_back("-ldl"); case OSFreeBSD: args.push_back("-lpthread"); args.push_back("-lm"); break; case OSHaiku: args.push_back("-lroot"); break; case OSWindows: // FIXME: I'd assume kernel32 etc break; } // object files for (unsigned i = 0; i < global.params.objfiles->dim; i++) { char *p = (char *)global.params.objfiles->data[i]; args.push_back(p); } // print link command? if (!quiet || global.params.verbose) { // Print it for (int i = 0; i < args.size(); i++) printf("%s ", args[i]); printf("\n"); fflush(stdout); } // terminate args list args.push_back(NULL); // try to call linker!!! if (int status = llvm::sys::Program::ExecuteAndWait(ldpath, &args[0], NULL, NULL, 0,0, &errstr)) { error("linking failed:\nstatus: %d", status); if (!errstr.empty()) error("message: %s", errstr.c_str()); return status; } return 0; }
SExpr* SCodeScope::inlineMerge(SendInfo* info, MergeNode*& merge) { // inline the send by type-casing; return uninlined cases in others list // If merge has no predecessors, return NULL for merge ref. SExpr* res = NULL; assert(info->rcvr->isMergeSExpr(), "must be a merge"); MergeSExpr* r = (MergeSExpr*)info->rcvr; stringOop sel = info->sel; merge = NULL; if (r->isSplittable() && shouldSplit(info)) { return splitMerge(info, merge); } fint ncases = r->exprs->length(); if (ncases > SICTypeCaseLimit) { info->needRealSend = true; if (PrintInlining) { lprintf("%*s*not type-casing %s (%ld > SICTypeCaseLimit)\n", (void*)depth, "", selector_string(sel), (void*)ncases); } return res; } assert( merge == NULL, "I assume merge is out param only"); merge = new MergeNode("inlineMerge merge"); if (SICDebug) { char* s = NEW_RESOURCE_ARRAY(char, 200); sprintf(s, "begin type-case of %s (ends at node N%ld)", sel->copy_null_terminated(), long(merge->id())); theNodeGen->comment(s); } if (PrintInlining) { lprintf("%*s*type-casing %s\n", (void*)depth, "", selector_string(sel)); } // build list of cases to inline // (add only immediate maps at first, collect others in ...2 lists SSelfScopeBList* slist = new SSelfScopeBList(ncases); SSelfScopeBList* slist2 = new SSelfScopeBList(ncases); SExprBList* elist = new SExprBList(ncases); SExprBList* elist2 = new SExprBList(ncases); SExprBList* others = new SExprBList(ncases); OopBList* mlist = new OopBList(ncases); OopBList* mlist2 = new OopBList(ncases); bool needMapLoad = false; fint i; for (i = 0; i < ncases; i++) { SExpr* nth = r->exprs->nth(i); assert(!nth->isConstantSExpr() || nth->next == NULL || nth->constant() == nth->next->constant(), "shouldn't happen: merged consts - convert to map"); SSelfScope* s; if (!nth->hasMap() || (s = tryLookup(info, nth)) == NULL) { // cannot inline others->append(nth); info->needRealSend = true; continue; } // can inline this case // Notice that for immediates, instead of putting the constants in the mlist, // we put the maps. No point in optimizing just for 17. -- dmu 6/05 Map* map = nth->map(); if (map == Memory->smi_map || map == Memory->float_map) { slist ->append(s); // immediate maps go first // Bug fix: instead of nth->shallowCopy, must generalize to any // with same map, not just the same constant, because other ints (for example) // will pass the type test, too. -- dmu 6/05 elist ->append(new MapSExpr(map->enclosing_mapOop(), r->preg(), NULL)); mlist ->append(map->enclosing_mapOop()); continue; } // can inline but not immediate map slist2->append(s); // append later elist2->append(nth->shallowCopy(r->preg(), NULL)); // use preg of merge if (nth->isConstantSExpr()) { mlist2->append(nth->constant()); } else { needMapLoad = true; // will need to load map of testee mlist2->append(map->enclosing_mapOop()); } } mlist->appendList(mlist2); elist->appendList(elist2); slist->appendList(slist2); // now do the type test and inline the individual cases if (slist->length() > 0) { memoizeBlocks(sel); Node* typeCase = theNodeGen->append(new TypeTestNode(r->preg(), mlist, needMapLoad, info->needRealSend)); Node* fallThrough = typeCase->append(new NopNode); for (i = 0; i < slist->length(); i++) { theNodeGen->current = typeCase->append(i + 1, new NopNode); SExpr* e = doInline(slist->nth(i), elist->nth(i), theNodeGen->current, merge); if (!e->isNoResultSExpr()) { theNodeGen->append(new NopNode); e = e->shallowCopy(info->resReg, theNodeGen->current); res = res ? res->mergeWith(e, merge) : e; } theNodeGen->branch(merge); } theNodeGen->current = fallThrough; } if (res && res->isMergeSExpr()) res->setNode(merge, info->resReg); assert( info->needRealSend && others->length() || !info->needRealSend && !others->length(), "inconsistent"); // NB: *must* use uncommon branch if marked unlikely because // future type tests won't test for unknown if (others->isEmpty()) { // typecase cannot fail theNodeGen->deadEnd(); } else if ( others->length() == 1 && others->first()->isUnknownSExpr() && ((UnknownSExpr*)others->first())->isUnlikely()) { // generate an uncommon branch for the unknown case, not a send theNodeGen->uncommonBranch(currentExprStack(0), info->restartPrim); info->needRealSend = false; if (PrintInlining) lprintf("%*s*making %s uncommon (2)\n", (void*)depth,"",selector_string(sel)); } return res; }
SExpr* SCodeScope::inlineSend(SendInfo* info) { stringOop sel = info->sel; SExpr* res = NULL; info->resReg = new SAPReg(this); MergeNode* merge = NULL; fint argc = sel->arg_count(); if (!Inline && !InlineSTMessages) { // don't do any inlining info->needRealSend = true; } else { info->rcvr = picPredict(info); UnknownSExpr* u = info->rcvr->findUnknown(); if (u && !u->isUnlikely()) { info->rcvr = typePredict(info); } if (info->rcvr->really_hasMap(this)) { // single map - try to inline this send SSelfScope* s = tryLookup(info, info->rcvr); if (s) { SExpr* r = doInline(s, info->rcvr, theNodeGen->current, NULL); if (r->isNoResultSExpr()) { res = r; } else { theNodeGen->append(new NopNode()); // to get right scope for r res = r->shallowCopy(r->preg(), theNodeGen->current); } } else { if (PrintInlining) { lprintf("%*s*marking %s send ReceiverStatic\n", (void*)depth,"", selector_string(sel)); } // receiver type is constant (but e.g. method was too big to inline) info->l |= ReceiverStaticBit; info->needRealSend = true; } } else if (info->rcvr->isMergeSExpr()) { res = inlineMerge(info, merge); } else { // unknown receiver // NB: *must* use uncommon branch if marked unlikely because // future type tests won't test for unknown if (info->rcvr->findUnknown()->isUnlikely()) { // generate an uncommon branch for the unknown case, not a send theNodeGen->current = theNodeGen->uncommonBranch(currentExprStack(0), info->restartPrim); info->needRealSend = false; if (PrintInlining) { lprintf("%*s*making %s uncommon\n", (void*)depth,"",selector_string(sel)); } } else { info->needRealSend = true; } } } if (info->needRealSend) { SExpr* r = genRealSend(info); res = res ? res->mergeWith(r, merge) : r; } if (merge && res && !res->isNoResultSExpr()) theNodeGen->branch(merge); // now pop expr stack for (fint i = 0; i < argc; i++) exprStack->pop(); if (!info->isSelfImplicit) exprStack->pop(); if (!res) res = new NoResultSExpr; return res; }
int main (int argc, char* argv[]) { // Main Function for default example ROSE Preprocessor // This is an example of a preprocessor that can be built with ROSE // Build the project object (AST) which we will fill up with multiple files and use as a // handle for all processing of the AST(s) associated with one or more source files. SgProject* sageProject = frontend(argc,argv); // DQ (7/20/2004): Added internal consistancy tests on AST AstTests::runAllTests(sageProject); // This is not needed here // FixSgProject(sageProject); bool changed = true; int count = 0; /* Inline one call at a time until all have been inlined. Loops on recursive code. */ while (changed) { changed = false; calls_to_inline.clear(); FindCallsVisitor().traverseInputFiles(sageProject, preorder); for (std::vector<SgFunctionCallExp*>::iterator i = calls_to_inline.begin(); i != calls_to_inline.end(); ++i) { // cout << (*i)->unparseToString() << endl; // generateAstGraph(sageProject, 400000); if (doInline(*i)) { changed = true; // AstTests::runAllTests(sageProject); break; } } ++count; #if 0 sageProject.unparse(); #endif // To prevent infinite loops if (count == 10) { break; } } #if 1 // Rename each variable declaration renameVariables(sageProject); #if 1 // Fold up blocks flattenBlocks(sageProject); // Clean up inliner-generated code cleanupInlinedCode(sageProject); #endif // Change members to public changeAllMembersToPublic(sageProject); // AstPDFGeneration().generateInputFiles(sageProject); // AstDOTGeneration().generateInputFiles(sageProject); #endif AstTests::runAllTests(sageProject); #if 0 // Output an optional graph of the AST (just the tree, when active) printf ("Generating a dot file... (ROSE Release Note: turn off output of dot files before committing code) \n"); generateDOT (*sageProject ); // generateAstGraph(project, 2000); #endif #if 1 // Output an optional graph of the AST (the whole graph, of bounded complexity, when active) const int MAX_NUMBER_OF_IR_NODES_TO_GRAPH_FOR_WHOLE_GRAPH = 8000; generateAstGraph(sageProject,MAX_NUMBER_OF_IR_NODES_TO_GRAPH_FOR_WHOLE_GRAPH); #endif return backend(sageProject); }