#include "LTOCodeGenerator.h"
#include "LTOModule.h"
-#include "llvm/Constants.h"
-#include "llvm/DataLayout.h"
-#include "llvm/DerivedTypes.h"
-#include "llvm/Linker.h"
-#include "llvm/LLVMContext.h"
-#include "llvm/Module.h"
-#include "llvm/PassManager.h"
+#include "llvm/ADT/StringExtras.h"
#include "llvm/Analysis/Passes.h"
#include "llvm/Analysis/Verifier.h"
#include "llvm/Bitcode/ReaderWriter.h"
#include "llvm/Config/config.h"
+#include "llvm/IR/Constants.h"
+#include "llvm/IR/DataLayout.h"
+#include "llvm/IR/DerivedTypes.h"
+#include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/Module.h"
+#include "llvm/InitializePasses.h"
+#include "llvm/Linker.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/SubtargetFeature.h"
-#include "llvm/Target/Mangler.h"
-#include "llvm/Target/TargetOptions.h"
-#include "llvm/Target/TargetMachine.h"
-#include "llvm/Target/TargetRegisterInfo.h"
-#include "llvm/Transforms/IPO.h"
-#include "llvm/Transforms/IPO/PassManagerBuilder.h"
+#include "llvm/PassManager.h"
#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/FileSystem.h"
#include "llvm/Support/FormattedStream.h"
-#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/ToolOutputFile.h"
#include "llvm/Support/Host.h"
+#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Signals.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/TargetSelect.h"
+#include "llvm/Support/ToolOutputFile.h"
#include "llvm/Support/system_error.h"
-#include "llvm/ADT/StringExtras.h"
+#include "llvm/Target/Mangler.h"
+#include "llvm/Target/TargetMachine.h"
+#include "llvm/Target/TargetOptions.h"
+#include "llvm/Target/TargetRegisterInfo.h"
+#include "llvm/Transforms/IPO.h"
+#include "llvm/Transforms/IPO/PassManagerBuilder.h"
+#include "llvm/Transforms/ObjCARC.h"
using namespace llvm;
+static cl::opt<bool>
+DisableOpt("disable-opt", cl::init(false),
+ cl::desc("Do not run any optimization passes"));
+
static cl::opt<bool>
DisableInline("disable-inlining", cl::init(false),
cl::desc("Do not run the inliner pass"));
LTOCodeGenerator::LTOCodeGenerator()
: _context(getGlobalContext()),
- _linker("LinkTimeOptimizer", "ld-temp.o", _context), _target(NULL),
+ _linker(new Module("ld-temp.o", _context)), _target(NULL),
_emitDwarfDebugInfo(false), _scopeRestrictionsDone(false),
_codeModel(LTO_CODEGEN_PIC_MODEL_DYNAMIC),
_nativeObjectFile(NULL) {
InitializeAllTargets();
InitializeAllTargetMCs();
InitializeAllAsmPrinters();
+ initializeLTOPasses();
}
LTOCodeGenerator::~LTOCodeGenerator() {
delete _target;
delete _nativeObjectFile;
+ delete _linker.getModule();
for (std::vector<char*>::iterator I = _codegenOptions.begin(),
E = _codegenOptions.end(); I != E; ++I)
free(*I);
}
+// Initialize LTO passes. Please keep this funciton in sync with
+// PassManagerBuilder::populateLTOPassManager(), and make sure all LTO
+// passes are initialized.
+//
+void LTOCodeGenerator::initializeLTOPasses() {
+ PassRegistry &R = *PassRegistry::getPassRegistry();
+
+ initializeInternalizePassPass(R);
+ initializeIPSCCPPass(R);
+ initializeGlobalOptPass(R);
+ initializeConstantMergePass(R);
+ initializeDAHPass(R);
+ initializeInstCombinerPass(R);
+ initializeSimpleInlinerPass(R);
+ initializePruneEHPass(R);
+ initializeGlobalDCEPass(R);
+ initializeArgPromotionPass(R);
+ initializeJumpThreadingPass(R);
+ initializeSROAPass(R);
+ initializeSROA_DTPass(R);
+ initializeSROA_SSAUpPass(R);
+ initializeFunctionAttrsPass(R);
+ initializeGlobalsModRefPass(R);
+ initializeLICMPass(R);
+ initializeGVNPass(R);
+ initializeMemCpyOptPass(R);
+ initializeDCEPass(R);
+ initializeCFGSimplifyPassPass(R);
+}
+
bool LTOCodeGenerator::addModule(LTOModule* mod, std::string& errMsg) {
- bool ret = _linker.LinkInModule(mod->getLLVVMModule(), &errMsg);
+ bool ret = _linker.linkInModule(mod->getLLVVMModule(), &errMsg);
const std::vector<const char*> &undefs = mod->getAsmUndefinedRefs();
for (int i = 0, e = undefs.size(); i != e; ++i)
if (determineTarget(errMsg))
return true;
- // mark which symbols can not be internalized
- applyScopeRestrictions();
+ // Run the verifier on the merged modules.
+ PassManager passes;
+ passes.add(createVerifierPass());
+ passes.run(*_linker.getModule());
// create output file
std::string ErrInfo;
- tool_output_file Out(path, ErrInfo,
- raw_fd_ostream::F_Binary);
+ tool_output_file Out(path, ErrInfo, sys::fs::F_Binary);
if (!ErrInfo.empty()) {
errMsg = "could not open bitcode file for writing: ";
errMsg += path;
bool LTOCodeGenerator::compile_to_file(const char** name, std::string& errMsg) {
// make unique temp .o file to put generated object file
- sys::PathWithStatus uniqueObjPath("lto-llvm.o");
- if (uniqueObjPath.createTemporaryFileOnDisk(false, &errMsg)) {
- uniqueObjPath.eraseFromDisk();
+ SmallString<128> Filename;
+ int FD;
+ error_code EC = sys::fs::createTemporaryFile("lto-llvm", "o", FD, Filename);
+ if (EC) {
+ errMsg = EC.message();
return true;
}
- sys::RemoveFileOnSignal(uniqueObjPath);
// generate object file
- bool genResult = false;
- tool_output_file objFile(uniqueObjPath.c_str(), errMsg);
- if (!errMsg.empty()) {
- uniqueObjPath.eraseFromDisk();
- return true;
- }
+ tool_output_file objFile(Filename.c_str(), FD);
- genResult = this->generateObjectFile(objFile.os(), errMsg);
+ bool genResult = generateObjectFile(objFile.os(), errMsg);
objFile.os().close();
if (objFile.os().has_error()) {
objFile.os().clear_error();
- uniqueObjPath.eraseFromDisk();
+ sys::fs::remove(Twine(Filename));
return true;
}
objFile.keep();
if (genResult) {
- uniqueObjPath.eraseFromDisk();
+ sys::fs::remove(Twine(Filename));
return true;
}
- _nativeObjectPath = uniqueObjPath.str();
+ _nativeObjectPath = Filename.c_str();
*name = _nativeObjectPath.c_str();
return false;
}
OwningPtr<MemoryBuffer> BuffPtr;
if (error_code ec = MemoryBuffer::getFile(name, BuffPtr, -1, false)) {
errMsg = ec.message();
- sys::Path(_nativeObjectPath).eraseFromDisk();
+ sys::fs::remove(_nativeObjectPath);
return NULL;
}
_nativeObjectFile = BuffPtr.take();
// remove temp files
- sys::Path(_nativeObjectPath).eraseFromDisk();
+ sys::fs::remove(_nativeObjectPath);
// return buffer, unless error
if (_nativeObjectFile == NULL)
return _nativeObjectFile->getBufferStart();
}
-bool LTOCodeGenerator::determineTarget(std::string& errMsg) {
+bool LTOCodeGenerator::determineTarget(std::string &errMsg) {
if (_target != NULL)
return false;
- std::string Triple = _linker.getModule()->getTargetTriple();
- if (Triple.empty())
- Triple = sys::getDefaultTargetTriple();
+ // if options were requested, set them
+ if (!_codegenOptions.empty())
+ cl::ParseCommandLineOptions(_codegenOptions.size(),
+ const_cast<char **>(&_codegenOptions[0]));
+
+ std::string TripleStr = _linker.getModule()->getTargetTriple();
+ if (TripleStr.empty())
+ TripleStr = sys::getDefaultTargetTriple();
+ llvm::Triple Triple(TripleStr);
// create target machine from info for merged modules
- const Target *march = TargetRegistry::lookupTarget(Triple, errMsg);
+ const Target *march = TargetRegistry::lookupTarget(TripleStr, errMsg);
if (march == NULL)
return true;
// construct LTOModule, hand over ownership of module and target
SubtargetFeatures Features;
- Features.getDefaultSubtargetFeatures(llvm::Triple(Triple));
+ Features.getDefaultSubtargetFeatures(Triple);
std::string FeatureStr = Features.getString();
+ // Set a default CPU for Darwin triples.
+ if (_mCpu.empty() && Triple.isOSDarwin()) {
+ if (Triple.getArch() == llvm::Triple::x86_64)
+ _mCpu = "core2";
+ else if (Triple.getArch() == llvm::Triple::x86)
+ _mCpu = "yonah";
+ }
TargetOptions Options;
LTOModule::getTargetOptions(Options);
- _target = march->createTargetMachine(Triple, _mCpu, FeatureStr, Options,
+ _target = march->createTargetMachine(TripleStr, _mCpu, FeatureStr, Options,
RelocModel, CodeModel::Default,
CodeGenOpt::Aggressive);
return false;
SmallPtrSet<GlobalValue*, 8> &UsedValues) {
if (LLVMUsed == 0) return;
- ConstantArray *Inits = dyn_cast<ConstantArray>(LLVMUsed->getInitializer());
- if (Inits == 0) return;
-
+ ConstantArray *Inits = cast<ConstantArray>(LLVMUsed->getInitializer());
for (unsigned i = 0, e = Inits->getNumOperands(); i != e; ++i)
if (GlobalValue *GV =
dyn_cast<GlobalValue>(Inits->getOperand(i)->stripPointerCasts()))
passes.add(createVerifierPass());
// mark which symbols can not be internalized
- MCContext Context(*_target->getMCAsmInfo(), *_target->getRegisterInfo(),NULL);
- Mangler mangler(Context, *_target->getDataLayout());
+ MCContext Context(_target->getMCAsmInfo(), _target->getRegisterInfo(), NULL);
+ Mangler mangler(Context, _target);
std::vector<const char*> mustPreserveList;
SmallPtrSet<GlobalValue*, 8> asmUsed;
if (LLVMCompilerUsed)
LLVMCompilerUsed->eraseFromParent();
- llvm::Type *i8PTy = llvm::Type::getInt8PtrTy(_context);
- std::vector<Constant*> asmUsed2;
- for (SmallPtrSet<GlobalValue*, 16>::const_iterator i = asmUsed.begin(),
- e = asmUsed.end(); i !=e; ++i) {
- GlobalValue *GV = *i;
- Constant *c = ConstantExpr::getBitCast(GV, i8PTy);
- asmUsed2.push_back(c);
+ if (!asmUsed.empty()) {
+ llvm::Type *i8PTy = llvm::Type::getInt8PtrTy(_context);
+ std::vector<Constant*> asmUsed2;
+ for (SmallPtrSet<GlobalValue*, 16>::const_iterator i = asmUsed.begin(),
+ e = asmUsed.end(); i !=e; ++i) {
+ GlobalValue *GV = *i;
+ Constant *c = ConstantExpr::getBitCast(GV, i8PTy);
+ asmUsed2.push_back(c);
+ }
+
+ llvm::ArrayType *ATy = llvm::ArrayType::get(i8PTy, asmUsed2.size());
+ LLVMCompilerUsed =
+ new llvm::GlobalVariable(*mergedModule, ATy, false,
+ llvm::GlobalValue::AppendingLinkage,
+ llvm::ConstantArray::get(ATy, asmUsed2),
+ "llvm.compiler.used");
+
+ LLVMCompilerUsed->setSection("llvm.metadata");
}
- llvm::ArrayType *ATy = llvm::ArrayType::get(i8PTy, asmUsed2.size());
- LLVMCompilerUsed =
- new llvm::GlobalVariable(*mergedModule, ATy, false,
- llvm::GlobalValue::AppendingLinkage,
- llvm::ConstantArray::get(ATy, asmUsed2),
- "llvm.compiler.used");
-
- LLVMCompilerUsed->setSection("llvm.metadata");
-
passes.add(createInternalizePass(mustPreserveList));
// apply scope restrictions
Module* mergedModule = _linker.getModule();
- // if options were requested, set them
- if (!_codegenOptions.empty())
- cl::ParseCommandLineOptions(_codegenOptions.size(),
- const_cast<char **>(&_codegenOptions[0]));
-
- // mark which symbols can not be internalized
+ // Mark which symbols can not be internalized
this->applyScopeRestrictions();
// Instantiate the pass manager to organize the passes.
// Add an appropriate DataLayout instance for this module...
passes.add(new DataLayout(*_target->getDataLayout()));
+ _target->addAnalysisPasses(passes);
// Enabling internalize here would use its AllButMain variant. It
// keeps only main if it exists and does nothing for libraries. Instead
// we create the pass ourselves with the symbol list provided by the linker.
- PassManagerBuilder().populateLTOPassManager(passes, /*Internalize=*/false,
+ if (!DisableOpt)
+ PassManagerBuilder().populateLTOPassManager(passes,
+ /*Internalize=*/false,
!DisableInline,
DisableGVNLoadPRE);
// Make sure everything is still good.
passes.add(createVerifierPass());
- FunctionPassManager *codeGenPasses = new FunctionPassManager(mergedModule);
+ PassManager codeGenPasses;
- codeGenPasses->add(new DataLayout(*_target->getDataLayout()));
+ codeGenPasses.add(new DataLayout(*_target->getDataLayout()));
+ _target->addAnalysisPasses(codeGenPasses);
formatted_raw_ostream Out(out);
- if (_target->addPassesToEmitFile(*codeGenPasses, Out,
+ // If the bitcode files contain ARC code and were compiled with optimization,
+ // the ObjCARCContractPass must be run, so do it unconditionally here.
+ codeGenPasses.add(createObjCARCContractPass());
+
+ if (_target->addPassesToEmitFile(codeGenPasses, Out,
TargetMachine::CGFT_ObjectFile)) {
errMsg = "target file type not supported";
return true;
passes.run(*mergedModule);
// Run the code generator, and write assembly file
- codeGenPasses->doInitialization();
-
- for (Module::iterator
- it = mergedModule->begin(), e = mergedModule->end(); it != e; ++it)
- if (!it->isDeclaration())
- codeGenPasses->run(*it);
-
- codeGenPasses->doFinalization();
- delete codeGenPasses;
+ codeGenPasses.run(*mergedModule);
return false; // success
}