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; }
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()); }