Example #1
0
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
}
Example #2
0
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
}
Example #3
0
File: linker.cpp Project: torje/ldc
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;
}
Example #4
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;
  }
Example #5
0
  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);
   }