X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=tools%2Flto%2FLTOCodeGenerator.cpp;h=93eb0a561eacc686764c05e493a45e2b79c65ce5;hb=21c14e3649b3e2a70ac36ebb148f17648f10a2a9;hp=dcbae95bd69fef84184659aebf4ddbc08dcf9a1e;hpb=e0f0e0be1c5f6f80cd866d84643509ef399eec96;p=oota-llvm.git diff --git a/tools/lto/LTOCodeGenerator.cpp b/tools/lto/LTOCodeGenerator.cpp index dcbae95bd69..93eb0a561ea 100644 --- a/tools/lto/LTOCodeGenerator.cpp +++ b/tools/lto/LTOCodeGenerator.cpp @@ -16,39 +16,41 @@ #include "LTOCodeGenerator.h" -#include "llvm/Module.h" -#include "llvm/PassManager.h" -#include "llvm/Linker.h" #include "llvm/Constants.h" #include "llvm/DerivedTypes.h" +#include "llvm/Linker.h" +#include "llvm/LLVMContext.h" +#include "llvm/Module.h" #include "llvm/ModuleProvider.h" +#include "llvm/PassManager.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/Triple.h" +#include "llvm/Analysis/Passes.h" +#include "llvm/Analysis/LoopPass.h" +#include "llvm/Analysis/Verifier.h" #include "llvm/Bitcode/ReaderWriter.h" +#include "llvm/CodeGen/FileWriters.h" #include "llvm/Support/CommandLine.h" +#include "llvm/Support/FormattedStream.h" #include "llvm/Support/Mangler.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/StandardPasses.h" #include "llvm/Support/SystemUtils.h" -#include "llvm/Support/raw_ostream.h" +#include "llvm/System/Host.h" +#include "llvm/System/Program.h" #include "llvm/System/Signals.h" -#include "llvm/Analysis/Passes.h" -#include "llvm/Analysis/LoopPass.h" -#include "llvm/Analysis/Verifier.h" -#include "llvm/CodeGen/FileWriters.h" #include "llvm/Target/SubtargetFeature.h" #include "llvm/Target/TargetOptions.h" +#include "llvm/MC/MCAsmInfo.h" #include "llvm/Target/TargetData.h" #include "llvm/Target/TargetMachine.h" -#include "llvm/Target/TargetMachineRegistry.h" -#include "llvm/Target/TargetAsmInfo.h" +#include "llvm/Target/TargetRegistry.h" +#include "llvm/Target/TargetSelect.h" #include "llvm/Transforms/IPO.h" #include "llvm/Transforms/Scalar.h" -#include "llvm/ADT/StringExtras.h" #include "llvm/Config/config.h" - - -#include +#include #include -#include #include @@ -69,12 +71,14 @@ const char* LTOCodeGenerator::getVersionString() LTOCodeGenerator::LTOCodeGenerator() - : _linker("LinkTimeOptimizer", "ld-temp.o"), _target(NULL), + : _context(getGlobalContext()), + _linker("LinkTimeOptimizer", "ld-temp.o", _context), _target(NULL), _emitDwarfDebugInfo(false), _scopeRestrictionsDone(false), _codeModel(LTO_CODEGEN_PIC_MODEL_DYNAMIC), - _nativeObjectFile(NULL), _gccPath(NULL) + _nativeObjectFile(NULL), _assemblerPath(NULL) { - + InitializeAllTargets(); + InitializeAllAsmPrinters(); } LTOCodeGenerator::~LTOCodeGenerator() @@ -108,7 +112,7 @@ bool LTOCodeGenerator::setDebugInfo(lto_debug_model debug, std::string& errMsg) bool LTOCodeGenerator::setCodePICModel(lto_codegen_model model, - std::string& errMsg) + std::string& errMsg) { switch (model) { case LTO_CODEGEN_PIC_MODEL_STATIC: @@ -121,11 +125,11 @@ bool LTOCodeGenerator::setCodePICModel(lto_codegen_model model, return true; } -void LTOCodeGenerator::setGccPath(const char* path) +void LTOCodeGenerator::setAssemblerPath(const char* path) { - if ( _gccPath ) - delete _gccPath; - _gccPath = new sys::Path(path); + if ( _assemblerPath ) + delete _assemblerPath; + _assemblerPath = new sys::Path(path); } void LTOCodeGenerator::addMustPreserveSymbol(const char* sym) @@ -134,31 +138,34 @@ void LTOCodeGenerator::addMustPreserveSymbol(const char* sym) } -bool LTOCodeGenerator::writeMergedModules(const char* path, std::string& errMsg) -{ - if ( this->determineTarget(errMsg) ) - return true; +bool LTOCodeGenerator::writeMergedModules(const char *path, + std::string &errMsg) { + if (determineTarget(errMsg)) + return true; - // mark which symbols can not be internalized - this->applyScopeRestrictions(); + // mark which symbols can not be internalized + applyScopeRestrictions(); - // create output file - std::ofstream out(path, std::ios_base::out|std::ios::trunc|std::ios::binary); - if ( out.fail() ) { - errMsg = "could not open bitcode file for writing: "; - errMsg += path; - return true; - } - - // write bitcode to it - WriteBitcodeToFile(_linker.getModule(), out); - if ( out.fail() ) { - errMsg = "could not write bitcode file: "; - errMsg += path; - return true; - } + // create output file + std::string ErrInfo; + raw_fd_ostream Out(path, ErrInfo, + raw_fd_ostream::F_Binary); + if (!ErrInfo.empty()) { + errMsg = "could not open bitcode file for writing: "; + errMsg += path; + return true; + } - return false; + // write bitcode to it + WriteBitcodeToFile(_linker.getModule(), Out); + + if (Out.has_error()) { + errMsg = "could not write bitcode file: "; + errMsg += path; + return true; + } + + return false; } @@ -173,7 +180,8 @@ const void* LTOCodeGenerator::compile(size_t* length, std::string& errMsg) // generate assembly code bool genResult = false; { - raw_fd_ostream asmFile(uniqueAsmPath.c_str(), false, errMsg); + raw_fd_ostream asmFD(uniqueAsmPath.c_str(), errMsg); + formatted_raw_ostream asmFile(asmFD); if (!errMsg.empty()) return NULL; genResult = this->generateAssemblyCode(asmFile, errMsg); @@ -194,9 +202,8 @@ const void* LTOCodeGenerator::compile(size_t* length, std::string& errMsg) sys::RemoveFileOnSignal(uniqueObjPath); // assemble the assembly code - const std::string& uniqueObjStr = uniqueObjPath.toString(); - bool asmResult = this->assemble(uniqueAsmPath.toString(), - uniqueObjStr, errMsg); + const std::string& uniqueObjStr = uniqueObjPath.str(); + bool asmResult = this->assemble(uniqueAsmPath.str(), uniqueObjStr, errMsg); if ( !asmResult ) { // remove old buffer if compile() called twice delete _nativeObjectFile; @@ -220,13 +227,15 @@ const void* LTOCodeGenerator::compile(size_t* length, std::string& errMsg) bool LTOCodeGenerator::assemble(const std::string& asmPath, const std::string& objPath, std::string& errMsg) { - sys::Path gcc; - if ( _gccPath ) { - gcc = *_gccPath; + sys::Path tool; + bool needsCompilerOptions = true; + if ( _assemblerPath ) { + tool = *_assemblerPath; + needsCompilerOptions = false; } else { // find compiler driver - gcc = sys::Program::FindProgramByName("gcc"); - if ( gcc.isEmpty() ) { + tool = sys::Program::FindProgramByName("gcc"); + if ( tool.isEmpty() ) { errMsg = "can't locate gcc"; return true; } @@ -234,57 +243,33 @@ bool LTOCodeGenerator::assemble(const std::string& asmPath, // build argument list std::vector args; - std::string targetTriple = _linker.getModule()->getTargetTriple(); - args.push_back(gcc.c_str()); - if ( targetTriple.find("darwin") != targetTriple.size() ) { - if (strncmp(targetTriple.c_str(), "i386-apple-", 11) == 0) { - args.push_back("-arch"); - args.push_back("i386"); - } - else if (strncmp(targetTriple.c_str(), "x86_64-apple-", 13) == 0) { - args.push_back("-arch"); - args.push_back("x86_64"); - } - else if (strncmp(targetTriple.c_str(), "powerpc-apple-", 14) == 0) { - args.push_back("-arch"); - args.push_back("ppc"); - } - else if (strncmp(targetTriple.c_str(), "powerpc64-apple-", 16) == 0) { - args.push_back("-arch"); - args.push_back("ppc64"); - } - else if (strncmp(targetTriple.c_str(), "arm-apple-", 10) == 0) { - args.push_back("-arch"); - args.push_back("arm"); - } - else if ((strncmp(targetTriple.c_str(), "armv4t-apple-", 13) == 0) || - (strncmp(targetTriple.c_str(), "thumbv4t-apple-", 15) == 0)) { - args.push_back("-arch"); - args.push_back("armv4t"); - } - else if ((strncmp(targetTriple.c_str(), "armv5-apple-", 12) == 0) || - (strncmp(targetTriple.c_str(), "armv5e-apple-", 13) == 0) || - (strncmp(targetTriple.c_str(), "thumbv5-apple-", 14) == 0) || - (strncmp(targetTriple.c_str(), "thumbv5e-apple-", 15) == 0)) { - args.push_back("-arch"); - args.push_back("armv5"); - } - else if ((strncmp(targetTriple.c_str(), "armv6-apple-", 12) == 0) || - (strncmp(targetTriple.c_str(), "thumbv6-apple-", 14) == 0)) { + llvm::Triple targetTriple(_linker.getModule()->getTargetTriple()); + const char *arch = targetTriple.getArchNameForAssembler(); + + args.push_back(tool.c_str()); + + if (targetTriple.getOS() == Triple::Darwin) { + // darwin specific command line options + if (arch != NULL) { args.push_back("-arch"); - args.push_back("armv6"); + args.push_back(arch); } + // add -static to assembler command line when code model requires + if ( (_assemblerPath != NULL) && (_codeModel == LTO_CODEGEN_PIC_MODEL_STATIC) ) + args.push_back("-static"); + } + if ( needsCompilerOptions ) { + args.push_back("-c"); + args.push_back("-x"); + args.push_back("assembler"); } - args.push_back("-c"); - args.push_back("-x"); - args.push_back("assembler"); args.push_back("-o"); args.push_back(objPath.c_str()); args.push_back(asmPath.c_str()); args.push_back(0); // invoke assembler - if ( sys::Program::ExecuteAndWait(gcc, &args[0], 0, 0, 0, 0, &errMsg) ) { + if ( sys::Program::ExecuteAndWait(tool, &args[0], 0, 0, 0, 0, &errMsg) ) { errMsg = "error in assembly"; return true; } @@ -296,18 +281,33 @@ bool LTOCodeGenerator::assemble(const std::string& asmPath, bool LTOCodeGenerator::determineTarget(std::string& errMsg) { if ( _target == NULL ) { + std::string Triple = _linker.getModule()->getTargetTriple(); + if (Triple.empty()) + Triple = sys::getHostTriple(); + // create target machine from info for merged modules - Module* mergedModule = _linker.getModule(); - const TargetMachineRegistry::entry* march = - TargetMachineRegistry::getClosestStaticTargetForModule( - *mergedModule, errMsg); + const Target *march = TargetRegistry::lookupTarget(Triple, errMsg); if ( march == NULL ) return true; + // The relocation model is actually a static member of TargetMachine + // and needs to be set before the TargetMachine is instantiated. + switch( _codeModel ) { + case LTO_CODEGEN_PIC_MODEL_STATIC: + TargetMachine::setRelocationModel(Reloc::Static); + break; + case LTO_CODEGEN_PIC_MODEL_DYNAMIC: + TargetMachine::setRelocationModel(Reloc::PIC_); + break; + case LTO_CODEGEN_PIC_MODEL_DYNAMIC_NO_PIC: + TargetMachine::setRelocationModel(Reloc::DynamicNoPIC); + break; + } + // construct LTModule, hand over ownership of module and target - std::string FeatureStr = - getFeatureString(_linker.getModule()->getTargetTriple().c_str()); - _target = march->CtorFn(*mergedModule, FeatureStr.c_str()); + const std::string FeatureStr = + SubtargetFeatures::getDefaultSubtargetFeatures(llvm::Triple(Triple)); + _target = march->createTargetMachine(Triple, FeatureStr); } return false; } @@ -324,19 +324,19 @@ void LTOCodeGenerator::applyScopeRestrictions() // mark which symbols can not be internalized if ( !_mustPreserveSymbols.empty() ) { Mangler mangler(*mergedModule, - _target->getTargetAsmInfo()->getGlobalPrefix()); + _target->getMCAsmInfo()->getGlobalPrefix()); std::vector mustPreserveList; for (Module::iterator f = mergedModule->begin(), e = mergedModule->end(); f != e; ++f) { if ( !f->isDeclaration() - && _mustPreserveSymbols.count(mangler.getValueName(f)) ) - mustPreserveList.push_back(::strdup(f->getName().c_str())); + && _mustPreserveSymbols.count(mangler.getMangledName(f)) ) + mustPreserveList.push_back(::strdup(f->getNameStr().c_str())); } for (Module::global_iterator v = mergedModule->global_begin(), e = mergedModule->global_end(); v != e; ++v) { if ( !v->isDeclaration() - && _mustPreserveSymbols.count(mangler.getValueName(v)) ) - mustPreserveList.push_back(::strdup(v->getName().c_str())); + && _mustPreserveSymbols.count(mangler.getMangledName(v)) ) + mustPreserveList.push_back(::strdup(v->getNameStr().c_str())); } passes.add(createInternalizePass(mustPreserveList)); } @@ -348,10 +348,10 @@ void LTOCodeGenerator::applyScopeRestrictions() } /// Optimize merged modules using various IPO passes -bool LTOCodeGenerator::generateAssemblyCode(raw_ostream& out, +bool LTOCodeGenerator::generateAssemblyCode(formatted_raw_ostream& out, std::string& errMsg) { - if ( this->determineTarget(errMsg) ) + if ( this->determineTarget(errMsg) ) return true; // mark which symbols can not be internalized @@ -359,21 +359,18 @@ bool LTOCodeGenerator::generateAssemblyCode(raw_ostream& out, Module* mergedModule = _linker.getModule(); - // If target supports exception handling then enable it now. - if ( _target->getTargetAsmInfo()->doesSupportExceptionHandling() ) - llvm::ExceptionHandling = true; - - // set codegen model - switch( _codeModel ) { - case LTO_CODEGEN_PIC_MODEL_STATIC: - _target->setRelocationModel(Reloc::Static); - break; - case LTO_CODEGEN_PIC_MODEL_DYNAMIC: - _target->setRelocationModel(Reloc::PIC_); - break; - case LTO_CODEGEN_PIC_MODEL_DYNAMIC_NO_PIC: - _target->setRelocationModel(Reloc::DynamicNoPIC); - break; + // If target supports exception handling then enable it now. + switch (_target->getMCAsmInfo()->getExceptionHandlingType()) { + case ExceptionHandling::Dwarf: + llvm::DwarfExceptionHandling = true; + break; + case ExceptionHandling::SjLj: + llvm::SjLjExceptionHandling = true; + break; + case ExceptionHandling::None: + break; + default: + assert (0 && "Unknown exception handling model!"); } // if options were requested, set them @@ -401,16 +398,16 @@ bool LTOCodeGenerator::generateAssemblyCode(raw_ostream& out, codeGenPasses->add(new TargetData(*_target->getTargetData())); - MachineCodeEmitter* mce = NULL; + ObjectCodeEmitter* oce = NULL; switch (_target->addPassesToEmitFile(*codeGenPasses, out, TargetMachine::AssemblyFile, CodeGenOpt::Aggressive)) { case FileModel::MachOFile: - mce = AddMachOWriter(*codeGenPasses, out, *_target); + oce = AddMachOWriter(*codeGenPasses, out, *_target); break; case FileModel::ElfFile: - mce = AddELFWriter(*codeGenPasses, out, *_target); + oce = AddELFWriter(*codeGenPasses, out, *_target); break; case FileModel::AsmFile: break; @@ -420,7 +417,7 @@ bool LTOCodeGenerator::generateAssemblyCode(raw_ostream& out, return true; } - if (_target->addPassesToEmitFileFinish(*codeGenPasses, mce, + if (_target->addPassesToEmitFileFinish(*codeGenPasses, oce, CodeGenOpt::Aggressive)) { errMsg = "target does not support generation of this file type"; return true; @@ -438,6 +435,7 @@ bool LTOCodeGenerator::generateAssemblyCode(raw_ostream& out, codeGenPasses->run(*it); codeGenPasses->doFinalization(); + return false; // success } @@ -445,12 +443,12 @@ bool LTOCodeGenerator::generateAssemblyCode(raw_ostream& out, /// Optimize merged modules using various IPO passes void LTOCodeGenerator::setCodeGenDebugOptions(const char* options) { - std::string ops(options); - for (std::string o = getToken(ops); !o.empty(); o = getToken(ops)) { + for (std::pair o = getToken(options); + !o.first.empty(); o = getToken(o.second)) { // ParseCommandLineOptions() expects argv[0] to be program name. // Lazily add that. if ( _codegenOptions.empty() ) _codegenOptions.push_back("libLTO"); - _codegenOptions.push_back(strdup(o.c_str())); + _codegenOptions.push_back(strdup(o.first.str().c_str())); } }