diff options
Diffstat (limited to 'tools/lto')
-rw-r--r-- | tools/lto/CMakeLists.txt | 2 | ||||
-rw-r--r-- | tools/lto/LTOCodeGenerator.cpp | 340 | ||||
-rw-r--r-- | tools/lto/LTOCodeGenerator.h | 105 | ||||
-rw-r--r-- | tools/lto/LTOModule.cpp | 437 | ||||
-rw-r--r-- | tools/lto/LTOModule.h | 250 | ||||
-rw-r--r-- | tools/lto/Makefile | 19 | ||||
-rw-r--r-- | tools/lto/lto.cpp | 348 | ||||
-rw-r--r-- | tools/lto/lto.exports | 1 |
8 files changed, 730 insertions, 772 deletions
diff --git a/tools/lto/CMakeLists.txt b/tools/lto/CMakeLists.txt index 7e2c5f0..9112976 100644 --- a/tools/lto/CMakeLists.txt +++ b/tools/lto/CMakeLists.txt @@ -1,6 +1,6 @@ set(LLVM_LINK_COMPONENTS ${LLVM_TARGETS_TO_BUILD} - ipo scalaropts linker bitreader bitwriter mcdisassembler) + ipo scalaropts linker bitreader bitwriter mcdisassembler vectorize) add_definitions( -DLLVM_VERSION_INFO=\"${PACKAGE_VERSION}\" ) diff --git a/tools/lto/LTOCodeGenerator.cpp b/tools/lto/LTOCodeGenerator.cpp index 6c8dbad..77c06a6 100644 --- a/tools/lto/LTOCodeGenerator.cpp +++ b/tools/lto/LTOCodeGenerator.cpp @@ -4,27 +4,26 @@ // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. -// +// //===----------------------------------------------------------------------===// // -// This file implements the Link Time Optimization library. This library is +// This file implements the Link Time Optimization library. This library is // intended to be used by linker to optimize code at link time. // //===----------------------------------------------------------------------===// -#include "LTOModule.h" #include "LTOCodeGenerator.h" +#include "LTOModule.h" #include "llvm/Constants.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/ADT/Triple.h" #include "llvm/Analysis/Passes.h" #include "llvm/Analysis/Verifier.h" #include "llvm/Bitcode/ReaderWriter.h" +#include "llvm/Config/config.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/SubtargetFeature.h" @@ -33,67 +32,55 @@ #include "llvm/Target/TargetData.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Transforms/IPO.h" +#include "llvm/Transforms/IPO/PassManagerBuilder.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/FormattedStream.h" #include "llvm/Support/MemoryBuffer.h" -#include "llvm/Support/SystemUtils.h" #include "llvm/Support/ToolOutputFile.h" #include "llvm/Support/Host.h" -#include "llvm/Support/Program.h" #include "llvm/Support/Signals.h" #include "llvm/Support/TargetRegistry.h" #include "llvm/Support/TargetSelect.h" #include "llvm/Support/system_error.h" -#include "llvm/Config/config.h" -#include "llvm/Transforms/IPO.h" -#include "llvm/Transforms/IPO/PassManagerBuilder.h" -#include <cstdlib> -#include <unistd.h> -#include <fcntl.h> - - +#include "llvm/ADT/StringExtras.h" using namespace llvm; -static cl::opt<bool> DisableInline("disable-inlining", +static cl::opt<bool> DisableInline("disable-inlining", cl::init(false), cl::desc("Do not run the inliner pass")); +static cl::opt<bool> DisableGVNLoadPRE("disable-gvn-loadpre", cl::init(false), + cl::desc("Do not run the GVN load PRE pass")); -const char* LTOCodeGenerator::getVersionString() -{ +const char* LTOCodeGenerator::getVersionString() { #ifdef LLVM_VERSION_INFO - return PACKAGE_NAME " version " PACKAGE_VERSION ", " LLVM_VERSION_INFO; + return PACKAGE_NAME " version " PACKAGE_VERSION ", " LLVM_VERSION_INFO; #else - return PACKAGE_NAME " version " PACKAGE_VERSION; + return PACKAGE_NAME " version " PACKAGE_VERSION; #endif } - -LTOCodeGenerator::LTOCodeGenerator() - : _context(getGlobalContext()), - _linker("LinkTimeOptimizer", "ld-temp.o", _context), _target(NULL), - _emitDwarfDebugInfo(false), _scopeRestrictionsDone(false), - _codeModel(LTO_CODEGEN_PIC_MODEL_DYNAMIC), - _nativeObjectFile(NULL) -{ - InitializeAllTargets(); - InitializeAllTargetMCs(); - InitializeAllAsmPrinters(); -} - -LTOCodeGenerator::~LTOCodeGenerator() -{ - delete _target; - delete _nativeObjectFile; +LTOCodeGenerator::LTOCodeGenerator() + : _context(getGlobalContext()), + _linker("LinkTimeOptimizer", "ld-temp.o", _context), _target(NULL), + _emitDwarfDebugInfo(false), _scopeRestrictionsDone(false), + _runInternalizePass(false), _codeModel(LTO_CODEGEN_PIC_MODEL_DYNAMIC), + _nativeObjectFile(NULL) { + InitializeAllTargets(); + InitializeAllTargetMCs(); + InitializeAllAsmPrinters(); } +LTOCodeGenerator::~LTOCodeGenerator() { + delete _target; + delete _nativeObjectFile; + for (std::vector<char*>::iterator I = _codegenOptions.begin(), + E = _codegenOptions.end(); I != E; ++I) + free(*I); +} -bool LTOCodeGenerator::addModule(LTOModule* mod, std::string& errMsg) -{ - - if(mod->getLLVVMModule()->MaterializeAllPermanently(&errMsg)) - return true; - +bool LTOCodeGenerator::addModule(LTOModule* mod, std::string& errMsg) { bool ret = _linker.LinkInModule(mod->getLLVVMModule(), &errMsg); const std::vector<const char*> &undefs = mod->getAsmUndefinedRefs(); @@ -102,55 +89,39 @@ bool LTOCodeGenerator::addModule(LTOModule* mod, std::string& errMsg) return ret; } - - -bool LTOCodeGenerator::setDebugInfo(lto_debug_model debug, std::string& errMsg) -{ - switch (debug) { - case LTO_DEBUG_MODEL_NONE: - _emitDwarfDebugInfo = false; - return false; - - case LTO_DEBUG_MODEL_DWARF: - _emitDwarfDebugInfo = true; - return false; - } - errMsg = "unknown debug format"; - return true; -} +bool LTOCodeGenerator::setDebugInfo(lto_debug_model debug, + std::string& errMsg) { + switch (debug) { + case LTO_DEBUG_MODEL_NONE: + _emitDwarfDebugInfo = false; + return false; -bool LTOCodeGenerator::setCodePICModel(lto_codegen_model model, - std::string& errMsg) -{ - switch (model) { - case LTO_CODEGEN_PIC_MODEL_STATIC: - case LTO_CODEGEN_PIC_MODEL_DYNAMIC: - case LTO_CODEGEN_PIC_MODEL_DYNAMIC_NO_PIC: - _codeModel = model; - return false; - } - errMsg = "unknown pic model"; - return true; -} - -void LTOCodeGenerator::setCpu(const char* mCpu) -{ - _mCpu = mCpu; + case LTO_DEBUG_MODEL_DWARF: + _emitDwarfDebugInfo = true; + return false; + } + llvm_unreachable("Unknown debug format!"); } -void LTOCodeGenerator::addMustPreserveSymbol(const char* sym) -{ - _mustPreserveSymbols[sym] = 1; +bool LTOCodeGenerator::setCodePICModel(lto_codegen_model model, + std::string& errMsg) { + switch (model) { + case LTO_CODEGEN_PIC_MODEL_STATIC: + case LTO_CODEGEN_PIC_MODEL_DYNAMIC: + case LTO_CODEGEN_PIC_MODEL_DYNAMIC_NO_PIC: + _codeModel = model; + return false; + } + llvm_unreachable("Unknown PIC model!"); } - bool LTOCodeGenerator::writeMergedModules(const char *path, std::string &errMsg) { if (determineTarget(errMsg)) return true; - // mark which symbols can not be internalized + // mark which symbols can not be internalized applyScopeRestrictions(); // create output file @@ -162,7 +133,7 @@ bool LTOCodeGenerator::writeMergedModules(const char *path, errMsg += path; return true; } - + // write bitcode to it WriteBitcodeToFile(_linker.getModule(), Out.os()); Out.os().close(); @@ -173,14 +144,12 @@ bool LTOCodeGenerator::writeMergedModules(const char *path, Out.os().clear_error(); return true; } - + Out.keep(); return false; } - -bool LTOCodeGenerator::compile_to_file(const char** name, std::string& errMsg) -{ +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) ) { @@ -194,12 +163,14 @@ bool LTOCodeGenerator::compile_to_file(const char** name, std::string& errMsg) tool_output_file objFile(uniqueObjPath.c_str(), errMsg); if (!errMsg.empty()) return true; + genResult = this->generateObjectFile(objFile.os(), errMsg); objFile.os().close(); if (objFile.os().has_error()) { objFile.os().clear_error(); return true; } + objFile.keep(); if ( genResult ) { uniqueObjPath.eraseFromDisk(); @@ -211,8 +182,7 @@ bool LTOCodeGenerator::compile_to_file(const char** name, std::string& errMsg) return false; } -const void* LTOCodeGenerator::compile(size_t* length, std::string& errMsg) -{ +const void* LTOCodeGenerator::compile(size_t* length, std::string& errMsg) { const char *name; if (compile_to_file(&name, errMsg)) return NULL; @@ -238,47 +208,48 @@ const void* LTOCodeGenerator::compile(size_t* length, std::string& errMsg) return _nativeObjectFile->getBufferStart(); } -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 - 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. - Reloc::Model RelocModel = Reloc::Default; - switch( _codeModel ) { - case LTO_CODEGEN_PIC_MODEL_STATIC: - RelocModel = Reloc::Static; - break; - case LTO_CODEGEN_PIC_MODEL_DYNAMIC: - RelocModel = Reloc::PIC_; - break; - case LTO_CODEGEN_PIC_MODEL_DYNAMIC_NO_PIC: - RelocModel = Reloc::DynamicNoPIC; - break; - } - - // construct LTOModule, hand over ownership of module and target - SubtargetFeatures Features; - Features.getDefaultSubtargetFeatures(llvm::Triple(Triple)); - std::string FeatureStr = Features.getString(); - _target = march->createTargetMachine(Triple, _mCpu, FeatureStr, - RelocModel); +bool LTOCodeGenerator::determineTarget(std::string& errMsg) { + if ( _target == NULL ) { + std::string Triple = _linker.getModule()->getTargetTriple(); + if (Triple.empty()) + Triple = sys::getDefaultTargetTriple(); + + // create target machine from info for merged modules + 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. + Reloc::Model RelocModel = Reloc::Default; + switch( _codeModel ) { + case LTO_CODEGEN_PIC_MODEL_STATIC: + RelocModel = Reloc::Static; + break; + case LTO_CODEGEN_PIC_MODEL_DYNAMIC: + RelocModel = Reloc::PIC_; + break; + case LTO_CODEGEN_PIC_MODEL_DYNAMIC_NO_PIC: + RelocModel = Reloc::DynamicNoPIC; + break; } - return false; + + // construct LTOModule, hand over ownership of module and target + SubtargetFeatures Features; + Features.getDefaultSubtargetFeatures(llvm::Triple(Triple)); + std::string FeatureStr = Features.getString(); + TargetOptions Options; + _target = march->createTargetMachine(Triple, _mCpu, FeatureStr, Options, + RelocModel); + } + return false; } -void LTOCodeGenerator::applyRestriction(GlobalValue &GV, - std::vector<const char*> &mustPreserveList, - SmallPtrSet<GlobalValue*, 8> &asmUsed, - Mangler &mangler) { +void LTOCodeGenerator:: +applyRestriction(GlobalValue &GV, + std::vector<const char*> &mustPreserveList, + SmallPtrSet<GlobalValue*, 8> &asmUsed, + Mangler &mangler) { SmallString<64> Buffer; mangler.getNameWithPrefix(Buffer, &GV, false); @@ -298,8 +269,8 @@ static void findUsedValues(GlobalVariable *LLVMUsed, if (Inits == 0) return; for (unsigned i = 0, e = Inits->getNumOperands(); i != e; ++i) - if (GlobalValue *GV = - dyn_cast<GlobalValue>(Inits->getOperand(i)->stripPointerCasts())) + if (GlobalValue *GV = + dyn_cast<GlobalValue>(Inits->getOperand(i)->stripPointerCasts())) UsedValues.insert(GV); } @@ -311,8 +282,8 @@ void LTOCodeGenerator::applyScopeRestrictions() { PassManager passes; passes.add(createVerifierPass()); - // mark which symbols can not be internalized - MCContext Context(*_target->getMCAsmInfo(), *_target->getRegisterInfo(), NULL); + // mark which symbols can not be internalized + MCContext Context(*_target->getMCAsmInfo(), *_target->getRegisterInfo(),NULL); Mangler mangler(Context, *_target->getTargetData()); std::vector<const char*> mustPreserveList; SmallPtrSet<GlobalValue*, 8> asmUsed; @@ -320,7 +291,7 @@ void LTOCodeGenerator::applyScopeRestrictions() { for (Module::iterator f = mergedModule->begin(), e = mergedModule->end(); f != e; ++f) applyRestriction(*f, mustPreserveList, asmUsed, mangler); - for (Module::global_iterator v = mergedModule->global_begin(), + for (Module::global_iterator v = mergedModule->global_begin(), e = mergedModule->global_end(); v != e; ++v) applyRestriction(*v, mustPreserveList, asmUsed, mangler); for (Module::alias_iterator a = mergedModule->alias_begin(), @@ -355,81 +326,82 @@ void LTOCodeGenerator::applyScopeRestrictions() { // apply scope restrictions passes.run(*mergedModule); - + _scopeRestrictionsDone = true; } /// Optimize merged modules using various IPO passes bool LTOCodeGenerator::generateObjectFile(raw_ostream &out, std::string &errMsg) { - if ( this->determineTarget(errMsg) ) - return true; + if ( this->determineTarget(errMsg) ) + return true; - // mark which symbols can not be internalized - this->applyScopeRestrictions(); + Module* mergedModule = _linker.getModule(); - Module* mergedModule = _linker.getModule(); + // if options were requested, set them + if ( !_codegenOptions.empty() ) + cl::ParseCommandLineOptions(_codegenOptions.size(), + const_cast<char **>(&_codegenOptions[0])); - // 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 + this->applyScopeRestrictions(); - // Instantiate the pass manager to organize the passes. - PassManager passes; + // Instantiate the pass manager to organize the passes. + PassManager passes; - // Start off with a verification pass. - passes.add(createVerifierPass()); + // Start off with a verification pass. + passes.add(createVerifierPass()); - // Add an appropriate TargetData instance for this module... - passes.add(new TargetData(*_target->getTargetData())); - - PassManagerBuilder().populateLTOPassManager(passes, /*Internalize=*/ false, - !DisableInline); + // Add an appropriate TargetData instance for this module... + passes.add(new TargetData(*_target->getTargetData())); - // Make sure everything is still good. - passes.add(createVerifierPass()); + PassManagerBuilder().populateLTOPassManager(passes, + _runInternalizePass, + !DisableInline, + DisableGVNLoadPRE); - FunctionPassManager *codeGenPasses = new FunctionPassManager(mergedModule); + // Make sure everything is still good. + passes.add(createVerifierPass()); - codeGenPasses->add(new TargetData(*_target->getTargetData())); + FunctionPassManager *codeGenPasses = new FunctionPassManager(mergedModule); - formatted_raw_ostream Out(out); + codeGenPasses->add(new TargetData(*_target->getTargetData())); - if (_target->addPassesToEmitFile(*codeGenPasses, Out, - TargetMachine::CGFT_ObjectFile, - CodeGenOpt::Aggressive)) { - errMsg = "target file type not supported"; - return true; - } + formatted_raw_ostream Out(out); - // Run our queue of passes all at once now, efficiently. - passes.run(*mergedModule); + if (_target->addPassesToEmitFile(*codeGenPasses, Out, + TargetMachine::CGFT_ObjectFile, + CodeGenOpt::Aggressive)) { + errMsg = "target file type not supported"; + return true; + } + + // Run our queue of passes all at once now, efficiently. + passes.run(*mergedModule); - // Run the code generator, and write assembly file - codeGenPasses->doInitialization(); + // 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); + for (Module::iterator + it = mergedModule->begin(), e = mergedModule->end(); it != e; ++it) + if (!it->isDeclaration()) + codeGenPasses->run(*it); - codeGenPasses->doFinalization(); - delete codeGenPasses; + codeGenPasses->doFinalization(); + delete codeGenPasses; - return false; // success + return false; // success } - -/// Optimize merged modules using various IPO passes -void LTOCodeGenerator::setCodeGenDebugOptions(const char* options) -{ - for (std::pair<StringRef, StringRef> 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.first.str().c_str())); - } +/// setCodeGenDebugOptions - Set codegen debugging options to aid in debugging +/// LTO problems. +void LTOCodeGenerator::setCodeGenDebugOptions(const char *options) { + for (std::pair<StringRef, StringRef> 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(strdup("libLTO")); + _codegenOptions.push_back(strdup(o.first.str().c_str())); + } } diff --git a/tools/lto/LTOCodeGenerator.h b/tools/lto/LTOCodeGenerator.h index f8fd357..bac3e6e 100644 --- a/tools/lto/LTOCodeGenerator.h +++ b/tools/lto/LTOCodeGenerator.h @@ -4,71 +4,82 @@ // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. -// +// //===----------------------------------------------------------------------===// // -// This file declares the LTOCodeGenerator class. +// This file declares the LTOCodeGenerator class. // //===----------------------------------------------------------------------===// - #ifndef LTO_CODE_GENERATOR_H #define LTO_CODE_GENERATOR_H #include "llvm/Linker.h" -#include "llvm/LLVMContext.h" #include "llvm/ADT/StringMap.h" -#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/SmallPtrSet.h" - +#include "llvm-c/lto.h" #include <string> +namespace llvm { + class LLVMContext; + class GlobalValue; + class Mangler; + class MemoryBuffer; + class TargetMachine; + class raw_ostream; +} -// -// C++ class which implements the opaque lto_code_gen_t -// - +//===----------------------------------------------------------------------===// +/// LTOCodeGenerator - C++ class which implements the opaque lto_code_gen_t +/// type. +/// struct LTOCodeGenerator { - static const char* getVersionString(); - - LTOCodeGenerator(); - ~LTOCodeGenerator(); - - bool addModule(struct LTOModule*, std::string& errMsg); - bool setDebugInfo(lto_debug_model, std::string& errMsg); - bool setCodePICModel(lto_codegen_model, std::string& errMsg); - void setCpu(const char *cpu); - void addMustPreserveSymbol(const char* sym); - bool writeMergedModules(const char* path, - std::string& errMsg); - bool compile_to_file(const char** name, std::string& errMsg); - const void* compile(size_t* length, std::string& errMsg); - void setCodeGenDebugOptions(const char *opts); + static const char *getVersionString(); + + LTOCodeGenerator(); + ~LTOCodeGenerator(); + + bool addModule(struct LTOModule*, std::string &errMsg); + bool setDebugInfo(lto_debug_model, std::string &errMsg); + bool setCodePICModel(lto_codegen_model, std::string &errMsg); + + void setCpu(const char* mCpu) { _mCpu = mCpu; } + + void addMustPreserveSymbol(const char* sym) { + _mustPreserveSymbols[sym] = 1; + } + + bool writeMergedModules(const char *path, std::string &errMsg); + bool compile_to_file(const char **name, std::string &errMsg); + const void *compile(size_t *length, std::string &errMsg); + void setCodeGenDebugOptions(const char *opts); + + void enableInternalizePass() { _runInternalizePass = true; } + private: - bool generateObjectFile(llvm::raw_ostream& out, - std::string& errMsg); - void applyScopeRestrictions(); - void applyRestriction(llvm::GlobalValue &GV, - std::vector<const char*> &mustPreserveList, + bool generateObjectFile(llvm::raw_ostream &out, std::string &errMsg); + void applyScopeRestrictions(); + void applyRestriction(llvm::GlobalValue &GV, + std::vector<const char*> &mustPreserveList, llvm::SmallPtrSet<llvm::GlobalValue*, 8> &asmUsed, - llvm::Mangler &mangler); - bool determineTarget(std::string& errMsg); - - typedef llvm::StringMap<uint8_t> StringSet; + llvm::Mangler &mangler); + bool determineTarget(std::string &errMsg); - llvm::LLVMContext& _context; - llvm::Linker _linker; - llvm::TargetMachine* _target; - bool _emitDwarfDebugInfo; - bool _scopeRestrictionsDone; - lto_codegen_model _codeModel; - StringSet _mustPreserveSymbols; - StringSet _asmUndefinedRefs; - llvm::MemoryBuffer* _nativeObjectFile; - std::vector<const char*> _codegenOptions; - std::string _mCpu; - std::string _nativeObjectPath; + typedef llvm::StringMap<uint8_t> StringSet; + + llvm::LLVMContext& _context; + llvm::Linker _linker; + llvm::TargetMachine* _target; + bool _emitDwarfDebugInfo; + bool _scopeRestrictionsDone; + bool _runInternalizePass; + lto_codegen_model _codeModel; + StringSet _mustPreserveSymbols; + StringSet _asmUndefinedRefs; + llvm::MemoryBuffer* _nativeObjectFile; + std::vector<char*> _codegenOptions; + std::string _mCpu; + std::string _nativeObjectPath; }; #endif // LTO_CODE_GENERATOR_H - diff --git a/tools/lto/LTOModule.cpp b/tools/lto/LTOModule.cpp index 4ba8985..1dbd64b 100644 --- a/tools/lto/LTOModule.cpp +++ b/tools/lto/LTOModule.cpp @@ -13,39 +13,37 @@ //===----------------------------------------------------------------------===// #include "LTOModule.h" - #include "llvm/Constants.h" #include "llvm/LLVMContext.h" #include "llvm/Module.h" -#include "llvm/ADT/OwningPtr.h" -#include "llvm/ADT/Triple.h" #include "llvm/Bitcode/ReaderWriter.h" -#include "llvm/Support/SystemUtils.h" -#include "llvm/Support/MemoryBuffer.h" -#include "llvm/Support/MathExtras.h" -#include "llvm/Support/Host.h" -#include "llvm/Support/Path.h" -#include "llvm/Support/Process.h" -#include "llvm/Support/SourceMgr.h" -#include "llvm/Support/TargetRegistry.h" -#include "llvm/Support/TargetSelect.h" -#include "llvm/Support/system_error.h" -#include "llvm/Target/Mangler.h" -#include "llvm/MC/MCAsmInfo.h" -#include "llvm/MC/MCContext.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCInst.h" -#include "llvm/MC/MCParser/MCAsmParser.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSubtargetInfo.h" #include "llvm/MC/MCSymbol.h" -#include "llvm/MC/SubtargetFeature.h" #include "llvm/MC/MCTargetAsmParser.h" -#include "llvm/Target/TargetMachine.h" +#include "llvm/MC/SubtargetFeature.h" +#include "llvm/MC/MCParser/MCAsmParser.h" #include "llvm/Target/TargetRegisterInfo.h" - +#include "llvm/Support/Host.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/Path.h" +#include "llvm/Support/SourceMgr.h" +#include "llvm/Support/TargetRegistry.h" +#include "llvm/Support/TargetSelect.h" +#include "llvm/Support/system_error.h" +#include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/Triple.h" using namespace llvm; +LTOModule::LTOModule(llvm::Module *m, llvm::TargetMachine *t) + : _module(m), _target(t), + _context(*_target->getMCAsmInfo(), *_target->getRegisterInfo(), NULL), + _mangler(_context, *_target->getTargetData()) {} + +/// isBitcodeFile - Returns 'true' if the file (or memory contents) is LLVM +/// bitcode. bool LTOModule::isBitcodeFile(const void *mem, size_t length) { return llvm::sys::IdentifyFileType((char*)mem, length) == llvm::sys::Bitcode_FileType; @@ -55,6 +53,8 @@ bool LTOModule::isBitcodeFile(const char *path) { return llvm::sys::Path(path).isBitcodeFile(); } +/// isBitcodeFileForTarget - Returns 'true' if the file (or memory contents) is +/// LLVM bitcode for the specified triple. bool LTOModule::isBitcodeFileForTarget(const void *mem, size_t length, const char *triplePrefix) { MemoryBuffer *buffer = makeBuffer(mem, length); @@ -63,7 +63,6 @@ bool LTOModule::isBitcodeFileForTarget(const void *mem, size_t length, return isTargetMatch(buffer, triplePrefix); } - bool LTOModule::isBitcodeFileForTarget(const char *path, const char *triplePrefix) { OwningPtr<MemoryBuffer> buffer; @@ -72,22 +71,17 @@ bool LTOModule::isBitcodeFileForTarget(const char *path, return isTargetMatch(buffer.take(), triplePrefix); } -// Takes ownership of buffer. +/// isTargetMatch - Returns 'true' if the memory buffer is for the specified +/// target triple. bool LTOModule::isTargetMatch(MemoryBuffer *buffer, const char *triplePrefix) { std::string Triple = getBitcodeTargetTriple(buffer, getGlobalContext()); delete buffer; - return (strncmp(Triple.c_str(), triplePrefix, - strlen(triplePrefix)) == 0); + return strncmp(Triple.c_str(), triplePrefix, strlen(triplePrefix)) == 0; } - -LTOModule::LTOModule(Module *m, TargetMachine *t) - : _module(m), _target(t) -{ -} - -LTOModule *LTOModule::makeLTOModule(const char *path, - std::string &errMsg) { +/// makeLTOModule - Create an LTOModule. N.B. These methods take ownership of +/// the buffer. +LTOModule *LTOModule::makeLTOModule(const char *path, std::string &errMsg) { OwningPtr<MemoryBuffer> buffer; if (error_code ec = MemoryBuffer::getFile(path, buffer)) { errMsg = ec.message(); @@ -97,8 +91,7 @@ LTOModule *LTOModule::makeLTOModule(const char *path, } LTOModule *LTOModule::makeLTOModule(int fd, const char *path, - size_t size, - std::string &errMsg) { + size_t size, std::string &errMsg) { return makeLTOModule(fd, path, size, size, 0, errMsg); } @@ -116,13 +109,6 @@ LTOModule *LTOModule::makeLTOModule(int fd, const char *path, return makeLTOModule(buffer.take(), errMsg); } -/// makeBuffer - Create a MemoryBuffer from a memory range. -MemoryBuffer *LTOModule::makeBuffer(const void *mem, size_t length) { - const char *startPtr = (char*)mem; - return MemoryBuffer::getMemBuffer(StringRef(startPtr, length), "", false); -} - - LTOModule *LTOModule::makeLTOModule(const void *mem, size_t length, std::string &errMsg) { OwningPtr<MemoryBuffer> buffer(makeBuffer(mem, length)); @@ -151,7 +137,7 @@ LTOModule *LTOModule::makeLTOModule(MemoryBuffer *buffer, std::string Triple = m->getTargetTriple(); if (Triple.empty()) - Triple = sys::getHostTriple(); + Triple = sys::getDefaultTargetTriple(); // find machine architecture for this module const Target *march = TargetRegistry::lookupTarget(Triple, errMsg); @@ -163,39 +149,33 @@ LTOModule *LTOModule::makeLTOModule(MemoryBuffer *buffer, Features.getDefaultSubtargetFeatures(llvm::Triple(Triple)); std::string FeatureStr = Features.getString(); std::string CPU; - TargetMachine *target = march->createTargetMachine(Triple, CPU, FeatureStr); + TargetOptions Options; + TargetMachine *target = march->createTargetMachine(Triple, CPU, FeatureStr, + Options); LTOModule *Ret = new LTOModule(m.take(), target); - bool Err = Ret->ParseSymbols(errMsg); - if (Err) { + if (Ret->parseSymbols(errMsg)) { delete Ret; return NULL; } - return Ret; -} - -const char *LTOModule::getTargetTriple() { - return _module->getTargetTriple().c_str(); -} - -void LTOModule::setTargetTriple(const char *triple) { - _module->setTargetTriple(triple); + return Ret; } -void LTOModule::addDefinedFunctionSymbol(Function *f, Mangler &mangler) { - // add to list of defined symbols - addDefinedSymbol(f, mangler, true); +/// makeBuffer - Create a MemoryBuffer from a memory range. +MemoryBuffer *LTOModule::makeBuffer(const void *mem, size_t length) { + const char *startPtr = (char*)mem; + return MemoryBuffer::getMemBuffer(StringRef(startPtr, length), "", false); } -// Get string that data pointer points to. +/// objcClassNameFromExpression - Get string that the data pointer points to. bool LTOModule::objcClassNameFromExpression(Constant *c, std::string &name) { if (ConstantExpr *ce = dyn_cast<ConstantExpr>(c)) { Constant *op = ce->getOperand(0); if (GlobalVariable *gvn = dyn_cast<GlobalVariable>(op)) { Constant *cn = gvn->getInitializer(); - if (ConstantArray *ca = dyn_cast<ConstantArray>(cn)) { + if (ConstantDataArray *ca = dyn_cast<ConstantDataArray>(cn)) { if (ca->isCString()) { - name = ".objc_class_name_" + ca->getAsCString(); + name = ".objc_class_name_" + ca->getAsCString().str(); return true; } } @@ -204,85 +184,92 @@ bool LTOModule::objcClassNameFromExpression(Constant *c, std::string &name) { return false; } -// Parse i386/ppc ObjC class data structure. +/// addObjCClass - Parse i386/ppc ObjC class data structure. void LTOModule::addObjCClass(GlobalVariable *clgv) { - if (ConstantStruct *c = dyn_cast<ConstantStruct>(clgv->getInitializer())) { - // second slot in __OBJC,__class is pointer to superclass name - std::string superclassName; - if (objcClassNameFromExpression(c->getOperand(1), superclassName)) { - NameAndAttributes info; - StringMap<NameAndAttributes>::value_type &entry = - _undefines.GetOrCreateValue(superclassName); - if (!entry.getValue().name) { - const char *symbolName = entry.getKey().data(); - info.name = symbolName; - info.attributes = LTO_SYMBOL_DEFINITION_UNDEFINED; - entry.setValue(info); - } - } - // third slot in __OBJC,__class is pointer to class name - std::string className; - if (objcClassNameFromExpression(c->getOperand(2), className)) { - StringSet::value_type &entry = - _defines.GetOrCreateValue(className); - entry.setValue(1); - NameAndAttributes info; - info.name = entry.getKey().data(); - info.attributes = (lto_symbol_attributes) - (LTO_SYMBOL_PERMISSIONS_DATA | - LTO_SYMBOL_DEFINITION_REGULAR | - LTO_SYMBOL_SCOPE_DEFAULT); - _symbols.push_back(info); - } - } -} - - -// Parse i386/ppc ObjC category data structure. -void LTOModule::addObjCCategory(GlobalVariable *clgv) { - if (ConstantStruct *c = dyn_cast<ConstantStruct>(clgv->getInitializer())) { - // second slot in __OBJC,__category is pointer to target class name - std::string targetclassName; - if (objcClassNameFromExpression(c->getOperand(1), targetclassName)) { - NameAndAttributes info; - - StringMap<NameAndAttributes>::value_type &entry = - _undefines.GetOrCreateValue(targetclassName); - - if (entry.getValue().name) - return; + ConstantStruct *c = dyn_cast<ConstantStruct>(clgv->getInitializer()); + if (!c) return; + // second slot in __OBJC,__class is pointer to superclass name + std::string superclassName; + if (objcClassNameFromExpression(c->getOperand(1), superclassName)) { + NameAndAttributes info; + StringMap<NameAndAttributes>::value_type &entry = + _undefines.GetOrCreateValue(superclassName); + if (!entry.getValue().name) { const char *symbolName = entry.getKey().data(); info.name = symbolName; info.attributes = LTO_SYMBOL_DEFINITION_UNDEFINED; + info.isFunction = false; + info.symbol = clgv; entry.setValue(info); } } + + // third slot in __OBJC,__class is pointer to class name + std::string className; + if (objcClassNameFromExpression(c->getOperand(2), className)) { + StringSet::value_type &entry = _defines.GetOrCreateValue(className); + entry.setValue(1); + + NameAndAttributes info; + info.name = entry.getKey().data(); + info.attributes = LTO_SYMBOL_PERMISSIONS_DATA | + LTO_SYMBOL_DEFINITION_REGULAR | LTO_SYMBOL_SCOPE_DEFAULT; + info.isFunction = false; + info.symbol = clgv; + _symbols.push_back(info); + } } +/// addObjCCategory - Parse i386/ppc ObjC category data structure. +void LTOModule::addObjCCategory(GlobalVariable *clgv) { + ConstantStruct *c = dyn_cast<ConstantStruct>(clgv->getInitializer()); + if (!c) return; -// Parse i386/ppc ObjC class list data structure. -void LTOModule::addObjCClassRef(GlobalVariable *clgv) { + // second slot in __OBJC,__category is pointer to target class name std::string targetclassName; - if (objcClassNameFromExpression(clgv->getInitializer(), targetclassName)) { - NameAndAttributes info; + if (!objcClassNameFromExpression(c->getOperand(1), targetclassName)) + return; - StringMap<NameAndAttributes>::value_type &entry = - _undefines.GetOrCreateValue(targetclassName); - if (entry.getValue().name) - return; + NameAndAttributes info; + StringMap<NameAndAttributes>::value_type &entry = + _undefines.GetOrCreateValue(targetclassName); - const char *symbolName = entry.getKey().data(); - info.name = symbolName; - info.attributes = LTO_SYMBOL_DEFINITION_UNDEFINED; - entry.setValue(info); - } + if (entry.getValue().name) + return; + + const char *symbolName = entry.getKey().data(); + info.name = symbolName; + info.attributes = LTO_SYMBOL_DEFINITION_UNDEFINED; + info.isFunction = false; + info.symbol = clgv; + entry.setValue(info); } +/// addObjCClassRef - Parse i386/ppc ObjC class list data structure. +void LTOModule::addObjCClassRef(GlobalVariable *clgv) { + std::string targetclassName; + if (!objcClassNameFromExpression(clgv->getInitializer(), targetclassName)) + return; + + NameAndAttributes info; + StringMap<NameAndAttributes>::value_type &entry = + _undefines.GetOrCreateValue(targetclassName); + if (entry.getValue().name) + return; + + const char *symbolName = entry.getKey().data(); + info.name = symbolName; + info.attributes = LTO_SYMBOL_DEFINITION_UNDEFINED; + info.isFunction = false; + info.symbol = clgv; + entry.setValue(info); +} -void LTOModule::addDefinedDataSymbol(GlobalValue *v, Mangler &mangler) { +/// addDefinedDataSymbol - Add a data symbol as defined to the list. +void LTOModule::addDefinedDataSymbol(GlobalValue *v) { // Add to list of defined symbols. - addDefinedSymbol(v, mangler, false); + addDefinedSymbol(v, false); // Special case i386/ppc ObjC data structures in magic sections: // The issue is that the old ObjC object format did some strange @@ -327,25 +314,30 @@ void LTOModule::addDefinedDataSymbol(GlobalValue *v, Mangler &mangler) { } } +/// addDefinedFunctionSymbol - Add a function symbol as defined to the list. +void LTOModule::addDefinedFunctionSymbol(Function *f) { + // add to list of defined symbols + addDefinedSymbol(f, true); +} -void LTOModule::addDefinedSymbol(GlobalValue *def, Mangler &mangler, - bool isFunction) { +/// addDefinedSymbol - Add a defined symbol to the list. +void LTOModule::addDefinedSymbol(GlobalValue *def, bool isFunction) { // ignore all llvm.* symbols if (def->getName().startswith("llvm.")) return; // string is owned by _defines SmallString<64> Buffer; - mangler.getNameWithPrefix(Buffer, def, false); + _mangler.getNameWithPrefix(Buffer, def, false); // set alignment part log2() can have rounding errors uint32_t align = def->getAlignment(); uint32_t attr = align ? CountTrailingZeros_32(def->getAlignment()) : 0; // set permissions part - if (isFunction) + if (isFunction) { attr |= LTO_SYMBOL_PERMISSIONS_CODE; - else { + } else { GlobalVariable *gv = dyn_cast<GlobalVariable>(def); if (gv && gv->isConstant()) attr |= LTO_SYMBOL_PERMISSIONS_RODATA; @@ -377,18 +369,24 @@ void LTOModule::addDefinedSymbol(GlobalValue *def, Mangler &mangler, else attr |= LTO_SYMBOL_SCOPE_INTERNAL; - // add to table of symbols - NameAndAttributes info; StringSet::value_type &entry = _defines.GetOrCreateValue(Buffer); entry.setValue(1); + // fill information structure + NameAndAttributes info; StringRef Name = entry.getKey(); info.name = Name.data(); assert(info.name[Name.size()] == '\0'); - info.attributes = (lto_symbol_attributes)attr; + info.attributes = attr; + info.isFunction = isFunction; + info.symbol = def; + + // add to table of symbols _symbols.push_back(info); } +/// addAsmGlobalSymbol - Add a global symbol from module-level ASM to the +/// defined list. void LTOModule::addAsmGlobalSymbol(const char *name, lto_symbol_attributes scope) { StringSet::value_type &entry = _defines.GetOrCreateValue(name); @@ -398,15 +396,41 @@ void LTOModule::addAsmGlobalSymbol(const char *name, return; entry.setValue(1); - const char *symbolName = entry.getKey().data(); - uint32_t attr = LTO_SYMBOL_DEFINITION_REGULAR; - attr |= scope; - NameAndAttributes info; - info.name = symbolName; - info.attributes = (lto_symbol_attributes)attr; - _symbols.push_back(info); + + NameAndAttributes &info = _undefines[entry.getKey().data()]; + + if (info.symbol == 0) { + // FIXME: This is trying to take care of module ASM like this: + // + // module asm ".zerofill __FOO, __foo, _bar_baz_qux, 0" + // + // but is gross and its mother dresses it funny. Have the ASM parser give us + // more details for this type of situation so that we're not guessing so + // much. + + // fill information structure + info.name = name; + info.attributes = + LTO_SYMBOL_PERMISSIONS_DATA | LTO_SYMBOL_DEFINITION_REGULAR | scope; + info.isFunction = false; + info.symbol = 0; + + // add to table of symbols + _symbols.push_back(info); + return; + } + + if (info.isFunction) + addDefinedFunctionSymbol(cast<Function>(info.symbol)); + else + addDefinedDataSymbol(info.symbol); + + _symbols.back().attributes &= ~LTO_SYMBOL_SCOPE_MASK; + _symbols.back().attributes |= scope; } +/// addAsmGlobalSymbolUndef - Add a global symbol from module-level ASM to the +/// undefined list. void LTOModule::addAsmGlobalSymbolUndef(const char *name) { StringMap<NameAndAttributes>::value_type &entry = _undefines.GetOrCreateValue(name); @@ -421,13 +445,16 @@ void LTOModule::addAsmGlobalSymbolUndef(const char *name) { attr |= LTO_SYMBOL_SCOPE_DEFAULT; NameAndAttributes info; info.name = entry.getKey().data(); - info.attributes = (lto_symbol_attributes)attr; + info.attributes = attr; + info.isFunction = false; + info.symbol = 0; entry.setValue(info); } -void LTOModule::addPotentialUndefinedSymbol(GlobalValue *decl, - Mangler &mangler) { +/// addPotentialUndefinedSymbol - Add a symbol which isn't defined just yet to a +/// list to be resolved later. +void LTOModule::addPotentialUndefinedSymbol(GlobalValue *decl, bool isFunc) { // ignore all llvm.* symbols if (decl->getName().startswith("llvm.")) return; @@ -437,7 +464,7 @@ void LTOModule::addPotentialUndefinedSymbol(GlobalValue *decl, return; SmallString<64> name; - mangler.getNameWithPrefix(name, decl, false); + _mangler.getNameWithPrefix(name, decl, false); StringMap<NameAndAttributes>::value_type &entry = _undefines.GetOrCreateValue(name); @@ -449,19 +476,22 @@ void LTOModule::addPotentialUndefinedSymbol(GlobalValue *decl, NameAndAttributes info; info.name = entry.getKey().data(); + if (decl->hasExternalWeakLinkage()) info.attributes = LTO_SYMBOL_DEFINITION_WEAKUNDEF; else info.attributes = LTO_SYMBOL_DEFINITION_UNDEFINED; + info.isFunction = isFunc; + info.symbol = decl; + entry.setValue(info); } - namespace { class RecordStreamer : public MCStreamer { public: - enum State { NeverSeen, Global, Defined, DefinedGlobal, Used}; + enum State { NeverSeen, Global, Defined, DefinedGlobal, Used }; private: StringMap<State> Symbols; @@ -550,14 +580,16 @@ namespace { RecordStreamer(MCContext &Context) : MCStreamer(Context) {} - virtual void ChangeSection(const MCSection *Section) {} - virtual void InitSections() {} + virtual void EmitInstruction(const MCInst &Inst) { + // Scan for values. + for (unsigned i = Inst.getNumOperands(); i--; ) + if (Inst.getOperand(i).isExpr()) + AddValueSymbols(Inst.getOperand(i).getExpr()); + } virtual void EmitLabel(MCSymbol *Symbol) { Symbol->setSection(*getCurrentSection()); markDefined(*Symbol); } - virtual void EmitAssemblerFlag(MCAssemblerFlag Flag) {} - virtual void EmitThumbFunc(MCSymbol *Func) {} virtual void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) { // FIXME: should we handle aliases? markDefined(*Symbol); @@ -566,20 +598,26 @@ namespace { if (Attribute == MCSA_Global) markGlobal(*Symbol); } - virtual void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) {} - virtual void EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) {} - virtual void BeginCOFFSymbolDef(const MCSymbol *Symbol) {} - virtual void EmitCOFFSymbolStorageClass(int StorageClass) {} virtual void EmitZerofill(const MCSection *Section, MCSymbol *Symbol, unsigned Size , unsigned ByteAlignment) { markDefined(*Symbol); } - virtual void EmitCOFFSymbolType(int Type) {} - virtual void EndCOFFSymbolDef() {} virtual void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, unsigned ByteAlignment) { markDefined(*Symbol); } + + // Noop calls. + virtual void ChangeSection(const MCSection *Section) {} + virtual void InitSections() {} + virtual void EmitAssemblerFlag(MCAssemblerFlag Flag) {} + virtual void EmitThumbFunc(MCSymbol *Func) {} + virtual void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) {} + virtual void EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) {} + virtual void BeginCOFFSymbolDef(const MCSymbol *Symbol) {} + virtual void EmitCOFFSymbolStorageClass(int StorageClass) {} + virtual void EmitCOFFSymbolType(int Type) {} + virtual void EndCOFFSymbolDef() {} virtual void EmitELFSize(MCSymbol *Symbol, const MCExpr *Value) {} virtual void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size, unsigned ByteAlignment) {} @@ -595,35 +633,30 @@ namespace { unsigned MaxBytesToEmit) {} virtual void EmitCodeAlignment(unsigned ByteAlignment, unsigned MaxBytesToEmit) {} - virtual void EmitValueToOffset(const MCExpr *Offset, - unsigned char Value ) {} + virtual bool EmitValueToOffset(const MCExpr *Offset, + unsigned char Value ) { return false; } virtual void EmitFileDirective(StringRef Filename) {} virtual void EmitDwarfAdvanceLineAddr(int64_t LineDelta, const MCSymbol *LastLabel, const MCSymbol *Label, unsigned PointerSize) {} - - virtual void EmitInstruction(const MCInst &Inst) { - // Scan for values. - for (unsigned i = Inst.getNumOperands(); i--; ) - if (Inst.getOperand(i).isExpr()) - AddValueSymbols(Inst.getOperand(i).getExpr()); - } - virtual void Finish() {} + virtual void FinishImpl() {} }; -} +} // end anonymous namespace -bool LTOModule::addAsmGlobalSymbols(MCContext &Context, std::string &errMsg) { +/// addAsmGlobalSymbols - Add global symbols from module-level ASM to the +/// defined or undefined lists. +bool LTOModule::addAsmGlobalSymbols(std::string &errMsg) { const std::string &inlineAsm = _module->getModuleInlineAsm(); if (inlineAsm.empty()) return false; - OwningPtr<RecordStreamer> Streamer(new RecordStreamer(Context)); + OwningPtr<RecordStreamer> Streamer(new RecordStreamer(_context)); MemoryBuffer *Buffer = MemoryBuffer::getMemBuffer(inlineAsm); SourceMgr SrcMgr; SrcMgr.AddNewSourceBuffer(Buffer, SMLoc()); OwningPtr<MCAsmParser> Parser(createMCAsmParser(SrcMgr, - Context, *Streamer, + _context, *Streamer, *_target->getMCAsmInfo())); OwningPtr<MCSubtargetInfo> STI(_target->getTarget(). createMCSubtargetInfo(_target->getTargetTriple(), @@ -657,6 +690,7 @@ bool LTOModule::addAsmGlobalSymbols(MCContext &Context, std::string &errMsg) { return false; } +/// isDeclaration - Return 'true' if the global value is a declaration. static bool isDeclaration(const GlobalValue &V) { if (V.hasAvailableExternallyLinkage()) return true; @@ -665,74 +699,49 @@ static bool isDeclaration(const GlobalValue &V) { return V.isDeclaration(); } -static bool isAliasToDeclaration(const GlobalAlias &V) { - return isDeclaration(*V.getAliasedGlobal()); -} - -bool LTOModule::ParseSymbols(std::string &errMsg) { - // Use mangler to add GlobalPrefix to names to match linker names. - MCContext Context(*_target->getMCAsmInfo(), *_target->getRegisterInfo(),NULL); - Mangler mangler(Context, *_target->getTargetData()); - +/// parseSymbols - Parse the symbols from the module and model-level ASM and add +/// them to either the defined or undefined lists. +bool LTOModule::parseSymbols(std::string &errMsg) { // add functions - for (Module::iterator f = _module->begin(); f != _module->end(); ++f) { + for (Module::iterator f = _module->begin(), e = _module->end(); f != e; ++f) { if (isDeclaration(*f)) - addPotentialUndefinedSymbol(f, mangler); + addPotentialUndefinedSymbol(f, true); else - addDefinedFunctionSymbol(f, mangler); + addDefinedFunctionSymbol(f); } // add data for (Module::global_iterator v = _module->global_begin(), e = _module->global_end(); v != e; ++v) { if (isDeclaration(*v)) - addPotentialUndefinedSymbol(v, mangler); + addPotentialUndefinedSymbol(v, false); else - addDefinedDataSymbol(v, mangler); + addDefinedDataSymbol(v); } // add asm globals - if (addAsmGlobalSymbols(Context, errMsg)) + if (addAsmGlobalSymbols(errMsg)) return true; // add aliases - for (Module::alias_iterator i = _module->alias_begin(), - e = _module->alias_end(); i != e; ++i) { - if (isAliasToDeclaration(*i)) - addPotentialUndefinedSymbol(i, mangler); + for (Module::alias_iterator a = _module->alias_begin(), + e = _module->alias_end(); a != e; ++a) { + if (isDeclaration(*a->getAliasedGlobal())) + // Is an alias to a declaration. + addPotentialUndefinedSymbol(a, false); else - addDefinedDataSymbol(i, mangler); + addDefinedDataSymbol(a); } // make symbols for all undefines - for (StringMap<NameAndAttributes>::iterator it=_undefines.begin(); - it != _undefines.end(); ++it) { - // if this symbol also has a definition, then don't make an undefine - // because it is a tentative definition - if (_defines.count(it->getKey()) == 0) { - NameAndAttributes info = it->getValue(); - _symbols.push_back(info); - } + for (StringMap<NameAndAttributes>::iterator u =_undefines.begin(), + e = _undefines.end(); u != e; ++u) { + // If this symbol also has a definition, then don't make an undefine because + // it is a tentative definition. + if (_defines.count(u->getKey())) continue; + NameAndAttributes info = u->getValue(); + _symbols.push_back(info); } - return false; -} - -uint32_t LTOModule::getSymbolCount() { - return _symbols.size(); -} - - -lto_symbol_attributes LTOModule::getSymbolAttributes(uint32_t index) { - if (index < _symbols.size()) - return _symbols[index].attributes; - else - return lto_symbol_attributes(0); -} - -const char *LTOModule::getSymbolName(uint32_t index) { - if (index < _symbols.size()) - return _symbols[index].name; - else - return NULL; + return false; } diff --git a/tools/lto/LTOModule.h b/tools/lto/LTOModule.h index ca08aea..cafb927 100644 --- a/tools/lto/LTOModule.h +++ b/tools/lto/LTOModule.h @@ -4,10 +4,10 @@ // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. -// +// //===----------------------------------------------------------------------===// // -// This file declares the LTOModule class. +// This file declares the LTOModule class. // //===----------------------------------------------------------------------===// @@ -15,110 +15,172 @@ #define LTO_MODULE_H #include "llvm/Module.h" -#include "llvm/ADT/OwningPtr.h" +#include "llvm/MC/MCContext.h" +#include "llvm/Target/Mangler.h" #include "llvm/Target/TargetMachine.h" +#include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/StringMap.h" - #include "llvm-c/lto.h" - #include <vector> #include <string> - -// forward references to llvm classes +// Forward references to llvm classes. namespace llvm { - class Mangler; - class MemoryBuffer; - class GlobalValue; - class Value; - class Function; + class Function; + class GlobalValue; + class MemoryBuffer; + class Value; } - -// -// C++ class which implements the opaque lto_module_t -// +//===----------------------------------------------------------------------===// +/// LTOModule - C++ class which implements the opaque lto_module_t type. +/// struct LTOModule { - - static bool isBitcodeFile(const void* mem, size_t length); - static bool isBitcodeFile(const char* path); - - static bool isBitcodeFileForTarget(const void* mem, - size_t length, const char* triplePrefix); - - static bool isBitcodeFileForTarget(const char* path, - const char* triplePrefix); - - static LTOModule* makeLTOModule(const char* path, - std::string& errMsg); - static LTOModule* makeLTOModule(int fd, const char *path, - size_t size, - std::string& errMsg); - static LTOModule* makeLTOModule(int fd, const char *path, - size_t file_size, - size_t map_size, - off_t offset, - std::string& errMsg); - static LTOModule* makeLTOModule(const void* mem, size_t length, - std::string& errMsg); - - const char* getTargetTriple(); - void setTargetTriple(const char*); - uint32_t getSymbolCount(); - lto_symbol_attributes getSymbolAttributes(uint32_t index); - const char* getSymbolName(uint32_t index); - - llvm::Module * getLLVVMModule() { return _module.get(); } - const std::vector<const char*> &getAsmUndefinedRefs() { - return _asm_undefines; - } +private: + typedef llvm::StringMap<uint8_t> StringSet; + + struct NameAndAttributes { + const char *name; + uint32_t attributes; + bool isFunction; + llvm::GlobalValue *symbol; + }; + + llvm::OwningPtr<llvm::Module> _module; + llvm::OwningPtr<llvm::TargetMachine> _target; + std::vector<NameAndAttributes> _symbols; + + // _defines and _undefines only needed to disambiguate tentative definitions + StringSet _defines; + llvm::StringMap<NameAndAttributes> _undefines; + std::vector<const char*> _asm_undefines; + llvm::MCContext _context; + + // Use mangler to add GlobalPrefix to names to match linker names. + llvm::Mangler _mangler; + + LTOModule(llvm::Module *m, llvm::TargetMachine *t); +public: + /// isBitcodeFile - Returns 'true' if the file or memory contents is LLVM + /// bitcode. + static bool isBitcodeFile(const void *mem, size_t length); + static bool isBitcodeFile(const char *path); + + /// isBitcodeFileForTarget - Returns 'true' if the file or memory contents + /// is LLVM bitcode for the specified triple. + static bool isBitcodeFileForTarget(const void *mem, + size_t length, + const char *triplePrefix); + static bool isBitcodeFileForTarget(const char *path, + const char *triplePrefix); + + /// makeLTOModule - Create an LTOModule. N.B. These methods take ownership + /// of the buffer. + static LTOModule *makeLTOModule(const char* path, + std::string &errMsg); + static LTOModule *makeLTOModule(int fd, const char *path, + size_t size, std::string &errMsg); + static LTOModule *makeLTOModule(int fd, const char *path, + size_t file_size, + size_t map_size, + off_t offset, + std::string& errMsg); + static LTOModule *makeLTOModule(const void *mem, size_t length, + std::string &errMsg); + + /// getTargetTriple - Return the Module's target triple. + const char *getTargetTriple() { + return _module->getTargetTriple().c_str(); + } + + /// setTargetTriple - Set the Module's target triple. + void setTargetTriple(const char *triple) { + _module->setTargetTriple(triple); + } + + /// getSymbolCount - Get the number of symbols + uint32_t getSymbolCount() { + return _symbols.size(); + } + + /// getSymbolAttributes - Get the attributes for a symbol at the specified + /// index. + lto_symbol_attributes getSymbolAttributes(uint32_t index) { + if (index < _symbols.size()) + return lto_symbol_attributes(_symbols[index].attributes); + return lto_symbol_attributes(0); + } + + /// getSymbolName - Get the name of the symbol at the specified index. + const char *getSymbolName(uint32_t index) { + if (index < _symbols.size()) + return _symbols[index].name; + return NULL; + } + + /// getLLVVMModule - Return the Module. + llvm::Module *getLLVVMModule() { return _module.get(); } + + /// getAsmUndefinedRefs - + const std::vector<const char*> &getAsmUndefinedRefs() { + return _asm_undefines; + } private: - LTOModule(llvm::Module* m, llvm::TargetMachine* t); - - bool ParseSymbols(std::string &errMsg); - void addDefinedSymbol(llvm::GlobalValue* def, - llvm::Mangler& mangler, - bool isFunction); - void addPotentialUndefinedSymbol(llvm::GlobalValue* decl, - llvm::Mangler &mangler); - void addDefinedFunctionSymbol(llvm::Function* f, - llvm::Mangler &mangler); - void addDefinedDataSymbol(llvm::GlobalValue* v, - llvm::Mangler &mangler); - bool addAsmGlobalSymbols(llvm::MCContext &Context, - std::string &errMsg); - void addAsmGlobalSymbol(const char *, - lto_symbol_attributes scope); - void addAsmGlobalSymbolUndef(const char *); - void addObjCClass(llvm::GlobalVariable* clgv); - void addObjCCategory(llvm::GlobalVariable* clgv); - void addObjCClassRef(llvm::GlobalVariable* clgv); - bool objcClassNameFromExpression(llvm::Constant* c, - std::string& name); - - static bool isTargetMatch(llvm::MemoryBuffer* memBuffer, - const char* triplePrefix); - - static LTOModule* makeLTOModule(llvm::MemoryBuffer* buffer, - std::string& errMsg); - static llvm::MemoryBuffer* makeBuffer(const void* mem, size_t length); - - typedef llvm::StringMap<uint8_t> StringSet; - - struct NameAndAttributes { - const char* name; - lto_symbol_attributes attributes; - }; - - llvm::OwningPtr<llvm::Module> _module; - llvm::OwningPtr<llvm::TargetMachine> _target; - std::vector<NameAndAttributes> _symbols; - // _defines and _undefines only needed to disambiguate tentative definitions - StringSet _defines; - llvm::StringMap<NameAndAttributes> _undefines; - std::vector<const char*> _asm_undefines; + /// parseSymbols - Parse the symbols from the module and model-level ASM and + /// add them to either the defined or undefined lists. + bool parseSymbols(std::string &errMsg); + + /// addPotentialUndefinedSymbol - Add a symbol which isn't defined just yet + /// to a list to be resolved later. + void addPotentialUndefinedSymbol(llvm::GlobalValue *dcl, bool isFunc); + + /// addDefinedSymbol - Add a defined symbol to the list. + void addDefinedSymbol(llvm::GlobalValue *def, bool isFunction); + + /// addDefinedFunctionSymbol - Add a function symbol as defined to the list. + void addDefinedFunctionSymbol(llvm::Function *f); + + /// addDefinedDataSymbol - Add a data symbol as defined to the list. + void addDefinedDataSymbol(llvm::GlobalValue *v); + + /// addAsmGlobalSymbols - Add global symbols from module-level ASM to the + /// defined or undefined lists. + bool addAsmGlobalSymbols(std::string &errMsg); + + /// addAsmGlobalSymbol - Add a global symbol from module-level ASM to the + /// defined list. + void addAsmGlobalSymbol(const char *, lto_symbol_attributes scope); + + /// addAsmGlobalSymbolUndef - Add a global symbol from module-level ASM to + /// the undefined list. + void addAsmGlobalSymbolUndef(const char *); + + /// addObjCClass - Parse i386/ppc ObjC class data structure. + void addObjCClass(llvm::GlobalVariable *clgv); + + /// addObjCCategory - Parse i386/ppc ObjC category data structure. + void addObjCCategory(llvm::GlobalVariable *clgv); + + /// addObjCClassRef - Parse i386/ppc ObjC class list data structure. + void addObjCClassRef(llvm::GlobalVariable *clgv); + + /// objcClassNameFromExpression - Get string that the data pointer points + /// to. + bool objcClassNameFromExpression(llvm::Constant* c, std::string &name); + + /// isTargetMatch - Returns 'true' if the memory buffer is for the specified + /// target triple. + static bool isTargetMatch(llvm::MemoryBuffer *memBuffer, + const char *triplePrefix); + + /// makeLTOModule - Create an LTOModule (private version). N.B. This + /// method takes ownership of the buffer. + static LTOModule *makeLTOModule(llvm::MemoryBuffer *buffer, + std::string &errMsg); + + /// makeBuffer - Create a MemoryBuffer from a memory range. + static llvm::MemoryBuffer *makeBuffer(const void *mem, size_t length); }; #endif // LTO_MODULE_H - diff --git a/tools/lto/Makefile b/tools/lto/Makefile index 46925e7..153fa03 100644 --- a/tools/lto/Makefile +++ b/tools/lto/Makefile @@ -7,22 +7,15 @@ # ##===----------------------------------------------------------------------===## -LEVEL = ../.. -LIBRARYNAME = LTO +LEVEL := ../.. +LIBRARYNAME := LTO +LINK_COMPONENTS := all-targets ipo scalaropts linker bitreader bitwriter \ + mcdisassembler vectorize +LINK_LIBS_IN_SHARED := 1 +SHARED_LIBRARY := 1 EXPORTED_SYMBOL_FILE = $(PROJ_SRC_DIR)/lto.exports -# Include this here so we can get the configuration of the targets -# that have been configured for construction. We have to do this -# early so we can set up LINK_COMPONENTS before including Makefile.rules -include $(LEVEL)/Makefile.config - -LINK_LIBS_IN_SHARED = 1 -SHARED_LIBRARY = 1 - -LINK_COMPONENTS := $(TARGETS_TO_BUILD) ipo scalaropts linker bitreader \ - bitwriter mcdisassembler - include $(LEVEL)/Makefile.common ifdef LLVM_VERSION_INFO diff --git a/tools/lto/lto.cpp b/tools/lto/lto.cpp index dd658d1..addf787 100644 --- a/tools/lto/lto.cpp +++ b/tools/lto/lto.cpp @@ -4,10 +4,10 @@ // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. -// +// //===----------------------------------------------------------------------===// // -// This file implements the Link Time Optimization library. This library is +// This file implements the Link Time Optimization library. This library is // intended to be used by linker to optimize code at link time. // //===----------------------------------------------------------------------===// @@ -19,292 +19,202 @@ #include "LTOCodeGenerator.h" -// holds most recent error string -// *** not thread safe *** +// Holds most recent error string. +// *** Not thread safe *** static std::string sLastErrorString; - - -// -// returns a printable string -// -extern const char* lto_get_version() -{ - return LTOCodeGenerator::getVersionString(); +/// lto_get_version - Returns a printable string. +extern const char* lto_get_version() { + return LTOCodeGenerator::getVersionString(); } -// -// returns the last error string or NULL if last operation was successful -// -const char* lto_get_error_message() -{ - return sLastErrorString.c_str(); +/// lto_get_error_message - Returns the last error string or NULL if last +/// operation was successful. +const char* lto_get_error_message() { + return sLastErrorString.c_str(); } - - -// -// validates if a file is a loadable object file -// -bool lto_module_is_object_file(const char* path) -{ - return LTOModule::isBitcodeFile(path); +/// lto_module_is_object_file - Validates if a file is a loadable object file. +bool lto_module_is_object_file(const char* path) { + return LTOModule::isBitcodeFile(path); } - -// -// validates if a file is a loadable object file compilable for requested target -// -bool lto_module_is_object_file_for_target(const char* path, - const char* target_triplet_prefix) -{ - return LTOModule::isBitcodeFileForTarget(path, target_triplet_prefix); +/// lto_module_is_object_file_for_target - Validates if a file is a loadable +/// object file compilable for requested target. +bool lto_module_is_object_file_for_target(const char* path, + const char* target_triplet_prefix) { + return LTOModule::isBitcodeFileForTarget(path, target_triplet_prefix); } - -// -// validates if a buffer is a loadable object file -// -bool lto_module_is_object_file_in_memory(const void* mem, size_t length) -{ - return LTOModule::isBitcodeFile(mem, length); +/// lto_module_is_object_file_in_memory - Validates if a buffer is a loadable +/// object file. +bool lto_module_is_object_file_in_memory(const void* mem, size_t length) { + return LTOModule::isBitcodeFile(mem, length); } - -// -// validates if a buffer is a loadable object file compilable for the target -// -bool lto_module_is_object_file_in_memory_for_target(const void* mem, - size_t length, const char* target_triplet_prefix) -{ - return LTOModule::isBitcodeFileForTarget(mem, length, target_triplet_prefix); +/// lto_module_is_object_file_in_memory_for_target - Validates if a buffer is a +/// loadable object file compilable for the target. +bool +lto_module_is_object_file_in_memory_for_target(const void* mem, + size_t length, + const char* target_triplet_prefix) { + return LTOModule::isBitcodeFileForTarget(mem, length, target_triplet_prefix); } - - -// -// loads an object file from disk -// returns NULL on error (check lto_get_error_message() for details) -// -lto_module_t lto_module_create(const char* path) -{ - return LTOModule::makeLTOModule(path, sLastErrorString); +/// lto_module_create - Loads an object file from disk. Returns NULL on error +/// (check lto_get_error_message() for details). +lto_module_t lto_module_create(const char* path) { + return LTOModule::makeLTOModule(path, sLastErrorString); } -// -// loads an object file from disk -// returns NULL on error (check lto_get_error_message() for details) -// -lto_module_t lto_module_create_from_fd(int fd, const char *path, size_t size) -{ - return LTOModule::makeLTOModule(fd, path, size, sLastErrorString); +/// lto_module_create_from_fd - Loads an object file from disk. Returns NULL on +/// error (check lto_get_error_message() for details). +lto_module_t lto_module_create_from_fd(int fd, const char *path, size_t size) { + return LTOModule::makeLTOModule(fd, path, size, sLastErrorString); } -// -// loads an object file from disk -// returns NULL on error (check lto_get_error_message() for details) -// +/// lto_module_create_from_fd_at_offset - Loads an object file from disk. +/// Returns NULL on error (check lto_get_error_message() for details). lto_module_t lto_module_create_from_fd_at_offset(int fd, const char *path, size_t file_size, size_t map_size, - off_t offset) -{ - return LTOModule::makeLTOModule(fd, path, file_size, map_size, - offset, sLastErrorString); + off_t offset) { + return LTOModule::makeLTOModule(fd, path, file_size, map_size, + offset, sLastErrorString); } -// -// loads an object file from memory -// returns NULL on error (check lto_get_error_message() for details) -// -lto_module_t lto_module_create_from_memory(const void* mem, size_t length) -{ - return LTOModule::makeLTOModule(mem, length, sLastErrorString); +/// lto_module_create_from_memory - Loads an object file from memory. Returns +/// NULL on error (check lto_get_error_message() for details). +lto_module_t lto_module_create_from_memory(const void* mem, size_t length) { + return LTOModule::makeLTOModule(mem, length, sLastErrorString); } - -// -// frees all memory for a module -// upon return the lto_module_t is no longer valid -// -void lto_module_dispose(lto_module_t mod) -{ - delete mod; +/// lto_module_dispose - Frees all memory for a module. Upon return the +/// lto_module_t is no longer valid. +void lto_module_dispose(lto_module_t mod) { + delete mod; } - -// -// returns triplet string which the object module was compiled under -// -const char* lto_module_get_target_triple(lto_module_t mod) -{ - return mod->getTargetTriple(); +/// lto_module_get_target_triple - Returns triplet string which the object +/// module was compiled under. +const char* lto_module_get_target_triple(lto_module_t mod) { + return mod->getTargetTriple(); } -// -// sets triple string with which the object will be codegened. -// -void lto_module_set_target_triple(lto_module_t mod, const char *triple) -{ - return mod->setTargetTriple(triple); +/// lto_module_set_target_triple - Sets triple string with which the object will +/// be codegened. +void lto_module_set_target_triple(lto_module_t mod, const char *triple) { + return mod->setTargetTriple(triple); } - -// -// returns the number of symbols in the object module -// -unsigned int lto_module_get_num_symbols(lto_module_t mod) -{ - return mod->getSymbolCount(); +/// lto_module_get_num_symbols - Returns the number of symbols in the object +/// module. +unsigned int lto_module_get_num_symbols(lto_module_t mod) { + return mod->getSymbolCount(); } -// -// returns the name of the ith symbol in the object module -// -const char* lto_module_get_symbol_name(lto_module_t mod, unsigned int index) -{ - return mod->getSymbolName(index); +/// lto_module_get_symbol_name - Returns the name of the ith symbol in the +/// object module. +const char* lto_module_get_symbol_name(lto_module_t mod, unsigned int index) { + return mod->getSymbolName(index); } - -// -// returns the attributes of the ith symbol in the object module -// -lto_symbol_attributes lto_module_get_symbol_attribute(lto_module_t mod, - unsigned int index) -{ - return mod->getSymbolAttributes(index); +/// lto_module_get_symbol_attribute - Returns the attributes of the ith symbol +/// in the object module. +lto_symbol_attributes lto_module_get_symbol_attribute(lto_module_t mod, + unsigned int index) { + return mod->getSymbolAttributes(index); } - - - - -// -// instantiates a code generator -// returns NULL if there is an error -// -lto_code_gen_t lto_codegen_create(void) -{ - return new LTOCodeGenerator(); +/// lto_codegen_create - Instantiates a code generator. Returns NULL if there +/// is an error. +lto_code_gen_t lto_codegen_create(void) { + return new LTOCodeGenerator(); } - - -// -// frees all memory for a code generator -// upon return the lto_code_gen_t is no longer valid -// -void lto_codegen_dispose(lto_code_gen_t cg) -{ - delete cg; +/// lto_codegen_dispose - Frees all memory for a code generator. Upon return the +/// lto_code_gen_t is no longer valid. +void lto_codegen_dispose(lto_code_gen_t cg) { + delete cg; } - - -// -// add an object module to the set of modules for which code will be generated -// returns true on error (check lto_get_error_message() for details) -// -bool lto_codegen_add_module(lto_code_gen_t cg, lto_module_t mod) -{ - return cg->addModule(mod, sLastErrorString); +/// lto_codegen_add_module - Add an object module to the set of modules for +/// which code will be generated. Returns true on error (check +/// lto_get_error_message() for details). +bool lto_codegen_add_module(lto_code_gen_t cg, lto_module_t mod) { + return cg->addModule(mod, sLastErrorString); } - -// -// sets what if any format of debug info should be generated -// returns true on error (check lto_get_error_message() for details) -// -bool lto_codegen_set_debug_model(lto_code_gen_t cg, lto_debug_model debug) -{ - return cg->setDebugInfo(debug, sLastErrorString); +/// lto_codegen_set_debug_model - Sets what if any format of debug info should +/// be generated. Returns true on error (check lto_get_error_message() for +/// details). +bool lto_codegen_set_debug_model(lto_code_gen_t cg, lto_debug_model debug) { + return cg->setDebugInfo(debug, sLastErrorString); } - -// -// sets what code model to generated -// returns true on error (check lto_get_error_message() for details) -// -bool lto_codegen_set_pic_model(lto_code_gen_t cg, lto_codegen_model model) -{ +/// lto_codegen_set_pic_model - Sets what code model to generated. Returns true +/// on error (check lto_get_error_message() for details). +bool lto_codegen_set_pic_model(lto_code_gen_t cg, lto_codegen_model model) { return cg->setCodePICModel(model, sLastErrorString); } -// -// sets the cpu to generate code for -// -void lto_codegen_set_cpu(lto_code_gen_t cg, const char* cpu) -{ +/// lto_codegen_set_cpu - Sets the cpu to generate code for. +void lto_codegen_set_cpu(lto_code_gen_t cg, const char *cpu) { return cg->setCpu(cpu); } -// -// sets the path to the assembler tool -// -void lto_codegen_set_assembler_path(lto_code_gen_t cg, const char* path) -{ +/// lto_codegen_set_assembler_path - Sets the path to the assembler tool. +void lto_codegen_set_assembler_path(lto_code_gen_t cg, const char *path) { // In here only for backwards compatibility. We use MC now. } - -// -// sets extra arguments that libLTO should pass to the assembler -// -void lto_codegen_set_assembler_args(lto_code_gen_t cg, const char** args, - int nargs) -{ +/// lto_codegen_set_assembler_args - Sets extra arguments that libLTO should +/// pass to the assembler. +void lto_codegen_set_assembler_args(lto_code_gen_t cg, const char **args, + int nargs) { // In here only for backwards compatibility. We use MC now. } -// -// adds to a list of all global symbols that must exist in the final -// generated code. If a function is not listed there, it might be -// inlined into every usage and optimized away. -// -void lto_codegen_add_must_preserve_symbol(lto_code_gen_t cg, const char* symbol) -{ +/// lto_codegen_add_must_preserve_symbol - Adds to a list of all global symbols +/// that must exist in the final generated code. If a function is not listed +/// there, it might be inlined into every usage and optimized away. +void lto_codegen_add_must_preserve_symbol(lto_code_gen_t cg, + const char *symbol) { cg->addMustPreserveSymbol(symbol); } +/// lto_codegen_set_whole_program_optimization - Enable the internalize pass +/// during LTO optimizations. +void lto_codegen_set_whole_program_optimization(lto_code_gen_t cg) { + cg->enableInternalizePass(); +} -// -// writes a new file at the specified path that contains the -// merged contents of all modules added so far. -// returns true on error (check lto_get_error_message() for details) -// -bool lto_codegen_write_merged_modules(lto_code_gen_t cg, const char* path) -{ +/// lto_codegen_write_merged_modules - Writes a new file at the specified path +/// that contains the merged contents of all modules added so far. Returns true +/// on error (check lto_get_error_message() for details). +bool lto_codegen_write_merged_modules(lto_code_gen_t cg, const char *path) { return cg->writeMergedModules(path, sLastErrorString); } - -// -// Generates code for all added modules into one native object file. -// On success returns a pointer to a generated mach-o/ELF buffer and -// length set to the buffer size. The buffer is owned by the -// lto_code_gen_t and will be freed when lto_codegen_dispose() -// is called, or lto_codegen_compile() is called again. -// On failure, returns NULL (check lto_get_error_message() for details). -// -extern const void* -lto_codegen_compile(lto_code_gen_t cg, size_t* length) -{ +/// lto_codegen_compile - Generates code for all added modules into one native +/// object file. On success returns a pointer to a generated mach-o/ELF buffer +/// and length set to the buffer size. The buffer is owned by the lto_code_gen_t +/// object and will be freed when lto_codegen_dispose() is called, or +/// lto_codegen_compile() is called again. On failure, returns NULL (check +/// lto_get_error_message() for details). +const void *lto_codegen_compile(lto_code_gen_t cg, size_t *length) { return cg->compile(length, sLastErrorString); } -extern bool -lto_codegen_compile_to_file(lto_code_gen_t cg, const char **name) -{ +/// lto_codegen_compile_to_file - Generates code for all added modules into one +/// native object file. The name of the file is written to name. Returns true on +/// error. +bool lto_codegen_compile_to_file(lto_code_gen_t cg, const char **name) { return cg->compile_to_file(name, sLastErrorString); } - -// -// Used to pass extra options to the code generator -// -extern void -lto_codegen_debug_options(lto_code_gen_t cg, const char * opt) -{ +/// lto_codegen_debug_options - Used to pass extra options to the code +/// generator. +void lto_codegen_debug_options(lto_code_gen_t cg, const char *opt) { cg->setCodeGenDebugOptions(opt); } diff --git a/tools/lto/lto.exports b/tools/lto/lto.exports index b900bfb..f471f1a 100644 --- a/tools/lto/lto.exports +++ b/tools/lto/lto.exports @@ -27,6 +27,7 @@ lto_codegen_set_assembler_args lto_codegen_set_assembler_path lto_codegen_set_cpu lto_codegen_compile_to_file +lto_codegen_set_whole_program_optimization LLVMCreateDisasm LLVMDisasmDispose LLVMDisasmInstruction |