bool
  SpecializeArguments::runOnModule(Module& M)
  {
    Function* f = M.getFunction("main");

    if (f == NULL)
    {
      errs() << "Running on module without 'main' function.\n"
          << "Ignoring...\n";
      return false;
    }

    if (f->getArgumentList().size() != 2)
    {
      errs() << "Main module has incorrect signature\n" << f->getFunctionType();
      return false;
    }

    // Build the array constant
    Type* const i32type = IntegerType::get(M.getContext(), 32);
    Type* const stringtype = PointerType::getUnqual(IntegerType::get(
        M.getContext(), 8));

    Function *new_main = Function::Create(f->getFunctionType(),
        f->getLinkage(), "", &M);
    new_main->takeName(f);
    Function::arg_iterator ai = new_main->arg_begin();
    ai++;
    Value* argvArg = (Value*) &(*ai);

    BasicBlock* bb = BasicBlock::Create(M.getContext());
    new_main->getBasicBlockList().push_front(bb);
    IRBuilder<> irb(bb);
    std::vector<Value*> cargs;
    std::vector<Constant*> init;

    if (this->progName) {
      GlobalVariable* gv = materializeStringLiteral(M, this->progName);
      cargs.push_back(irb.CreateConstGEP2_32(gv, 0, 0));
    } else {
      Value* progName = irb.CreateLoad(argvArg, false);
      cargs.push_back(progName);
    }

    for (int i = 0; i < this->argc; ++i)
    {
      GlobalVariable* gv = materializeStringLiteral(M, this->argv[i]);
      cargs.push_back(irb.CreateConstGEP2_32(gv, 0, 0));
    }

    Value* argv = irb.CreateAlloca(stringtype, ConstantInt::get(i32type,
        cargs.size(), false));

    int idx = 0;
    for (std::vector<Value*>::iterator i = cargs.begin(), e = cargs.end(); i
        != e; ++i, ++idx)
    {
      Value* argptr = irb.CreateConstGEP1_32(argv, idx);
      irb.CreateStore(*i, argptr);
    }

    Value* res = irb.CreateCall2(f, ConstantInt::getSigned(IntegerType::get(
        M.getContext(), 32), cargs.size()), argv);
    irb.CreateRet(res);

    f->setLinkage(GlobalValue::PrivateLinkage);
    f->addFnAttr(Attribute::AlwaysInline);

    PassManager mgr;
    mgr.add(createAlwaysInlinerPass());
    mgr.run(M);

    return true;
  }
Exemplo n.º 2
0
  void BackendPass::CreatePasses(const clang::LangOptions& LangOpts,
                                 const clang::CodeGenOptions& CodeGenOpts) {
    // See clang/lib/CodeGen/BackendUtil.cpp EmitAssemblyHelper::CreatePasses()
    unsigned OptLevel = CodeGenOpts.OptimizationLevel;
    CodeGenOptions::InliningMethod Inlining = CodeGenOpts.getInlining();

    // Handle disabling of LLVM optimization, where we want to preserve the
    // internal module before any optimization.
    if (CodeGenOpts.DisableLLVMOpts) {
      OptLevel = 0;
      Inlining = CodeGenOpts.NoInlining;
    }

    PassManagerBuilderWithOpts PMBuilder(LangOpts, CodeGenOpts);
    PMBuilder.OptLevel = OptLevel;
    PMBuilder.SizeLevel = CodeGenOpts.OptimizeSize;
    PMBuilder.BBVectorize = CodeGenOpts.VectorizeBB;
    PMBuilder.SLPVectorize = CodeGenOpts.VectorizeSLP;
    PMBuilder.LoopVectorize = CodeGenOpts.VectorizeLoop;

    PMBuilder.DisableUnitAtATime = !CodeGenOpts.UnitAtATime;
    PMBuilder.DisableUnrollLoops = !CodeGenOpts.UnrollLoops;
    PMBuilder.RerollLoops = CodeGenOpts.RerollLoops;

#if 0
    if (!CodeGenOpts.SampleProfileFile.empty())
      PMBuilder.addExtension(PassManagerBuilder::EP_EarlyAsPossible,
                             addSampleProfileLoaderPass);
#endif

    // In ObjC ARC mode, add the main ARC optimization passes.
    if (LangOpts.ObjCAutoRefCount) {
      PMBuilder.addExtension(PassManagerBuilder::EP_EarlyAsPossible,
                             addObjCARCExpandPass);
      PMBuilder.addExtension(PassManagerBuilder::EP_ModuleOptimizerEarly,
                             addObjCARCAPElimPass);
      PMBuilder.addExtension(PassManagerBuilder::EP_ScalarOptimizerLate,
                             addObjCARCOptPass);
    }

    if (LangOpts.Sanitize.LocalBounds) {
      PMBuilder.addExtension(PassManagerBuilder::EP_ScalarOptimizerLate,
                             addBoundsCheckingPass);
      PMBuilder.addExtension(PassManagerBuilder::EP_EnabledOnOptLevel0,
                             addBoundsCheckingPass);
    }

    if (LangOpts.Sanitize.Address) {
      PMBuilder.addExtension(PassManagerBuilder::EP_OptimizerLast,
                             addAddressSanitizerPasses);
      PMBuilder.addExtension(PassManagerBuilder::EP_EnabledOnOptLevel0,
                             addAddressSanitizerPasses);
    }

    if (LangOpts.Sanitize.Memory) {
      PMBuilder.addExtension(PassManagerBuilder::EP_OptimizerLast,
                             addMemorySanitizerPass);
      PMBuilder.addExtension(PassManagerBuilder::EP_EnabledOnOptLevel0,
                             addMemorySanitizerPass);
    }

    if (LangOpts.Sanitize.Thread) {
      PMBuilder.addExtension(PassManagerBuilder::EP_OptimizerLast,
                             addThreadSanitizerPass);
      PMBuilder.addExtension(PassManagerBuilder::EP_EnabledOnOptLevel0,
                             addThreadSanitizerPass);
    }

    if (LangOpts.Sanitize.DataFlow) {
      PMBuilder.addExtension(PassManagerBuilder::EP_OptimizerLast,
                             addDataFlowSanitizerPass);
      PMBuilder.addExtension(PassManagerBuilder::EP_EnabledOnOptLevel0,
                             addDataFlowSanitizerPass);
    }

    // Figure out TargetLibraryInfo.
    Triple TargetTriple(m_Module->getTargetTriple());
    PMBuilder.LibraryInfo = new TargetLibraryInfo(TargetTriple);
    if (!CodeGenOpts.SimplifyLibCalls)
      PMBuilder.LibraryInfo->disableAllFunctions();

    switch (Inlining) {
    case CodeGenOptions::NoInlining: break;
    case CodeGenOptions::NormalInlining: {
      // FIXME: Derive these constants in a principled fashion.
      unsigned Threshold = 225;
      if (CodeGenOpts.OptimizeSize == 1)      // -Os
        Threshold = 75;
      else if (CodeGenOpts.OptimizeSize == 2) // -Oz
        Threshold = 25;
      else if (OptLevel > 2)
        Threshold = 275;
      // Creates a SimpleInliner that requests InsertLifetime.
      PMBuilder.Inliner
        = new InlinerKeepDeadFunc(createFunctionInliningPass(Threshold));
      break;
    }
    case CodeGenOptions::OnlyAlwaysInlining:
      // Respect always_inline.
      if (OptLevel == 0)
        // Do not insert lifetime intrinsics at -O0.
        PMBuilder.Inliner
          = new InlinerKeepDeadFunc(createAlwaysInlinerPass(false));
      else
        PMBuilder.Inliner
          = new InlinerKeepDeadFunc(createAlwaysInlinerPass());
      break;
    }

    // Set up the per-function pass manager.
    FunctionPassManager *FPM = getPerFunctionPasses();
    if (CodeGenOpts.VerifyModule)
      FPM->add(createVerifierPass());
    PMBuilder.populateFunctionPassManager(*FPM);

    // The Inliner is a module pass; register it.
    PMBuilder.populateModulePassManager(*getPerModulePasses());
  }