From ef194ed74033eba099f4f391ffdfc176f9aa6f26 Mon Sep 17 00:00:00 2001 From: Nick Kledzik Date: Wed, 27 Feb 2008 22:25:36 +0000 Subject: [PATCH] fixes from review of first commit git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@47695 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm-c/lto.h | 7 +- tools/lto2/LTOCodeGenerator.cpp | 74 ++++------ tools/lto2/LTOCodeGenerator.h | 7 +- tools/lto2/LTOModule.cpp | 238 +++++++++++++++----------------- tools/lto2/LTOModule.h | 45 ++++-- tools/lto2/lto.cpp | 15 +- 6 files changed, 184 insertions(+), 202 deletions(-) diff --git a/include/llvm-c/lto.h b/include/llvm-c/lto.h index 8d4590b6753..e42271dea01 100644 --- a/include/llvm-c/lto.h +++ b/include/llvm-c/lto.h @@ -218,11 +218,12 @@ lto_codegen_write_merged_modules(lto_code_gen_t cg, const char* path); /** * Generates code for all added modules into one native object file. * On sucess returns a pointer to a generated mach-o/ELF buffer and - * length set to the buffer size. Client owns the buffer and should - * free() it when done. + * 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 void* +extern const void* lto_codegen_compile(lto_code_gen_t cg, size_t* length); diff --git a/tools/lto2/LTOCodeGenerator.cpp b/tools/lto2/LTOCodeGenerator.cpp index 795aca01f56..024db24b476 100644 --- a/tools/lto2/LTOCodeGenerator.cpp +++ b/tools/lto2/LTOCodeGenerator.cpp @@ -12,6 +12,10 @@ // //===----------------------------------------------------------------------===// +#include "LTOModule.h" +#include "LTOCodeGenerator.h" + + #include "llvm/Module.h" #include "llvm/PassManager.h" #include "llvm/Linker.h" @@ -19,18 +23,15 @@ #include "llvm/DerivedTypes.h" #include "llvm/ModuleProvider.h" #include "llvm/Bitcode/ReaderWriter.h" -#include "llvm/Support/CommandLine.h" -#include "llvm/Support/FileUtilities.h" #include "llvm/Support/SystemUtils.h" #include "llvm/Support/Mangler.h" #include "llvm/Support/MemoryBuffer.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/Analysis/LoadValueNumbering.h" #include "llvm/CodeGen/FileWriters.h" -#include "llvm/Target/SubtargetFeature.h" #include "llvm/Target/TargetOptions.h" #include "llvm/Target/TargetData.h" #include "llvm/Target/TargetMachine.h" @@ -38,12 +39,8 @@ #include "llvm/Target/TargetAsmInfo.h" #include "llvm/Transforms/IPO.h" #include "llvm/Transforms/Scalar.h" -#include "llvm/Analysis/LoadValueNumbering.h" -#include "llvm/Support/MathExtras.h" #include "llvm/Config/config.h" -#include "LTOModule.h" -#include "LTOCodeGenerator.h" #include #include @@ -68,14 +65,16 @@ const char* LTOCodeGenerator::getVersionString() LTOCodeGenerator::LTOCodeGenerator() : _linker("LinkTimeOptimizer", "ld-temp.o"), _target(NULL), _emitDwarfDebugInfo(false), _scopeRestrictionsDone(false), - _codeModel(LTO_CODEGEN_PIC_MODEL_DYNAMIC) + _codeModel(LTO_CODEGEN_PIC_MODEL_DYNAMIC), + _nativeObjectFile(NULL) { } LTOCodeGenerator::~LTOCodeGenerator() { - // FIXME + delete _target; + delete _nativeObjectFile; } @@ -151,9 +150,9 @@ bool LTOCodeGenerator::writeMergedModules(const char* path, std::string& errMsg) } -void* LTOCodeGenerator::compile(size_t* length, std::string& errMsg) +const void* LTOCodeGenerator::compile(size_t* length, std::string& errMsg) { - // make unqiue temp .s file to put generated assembly code + // make unique temp .s file to put generated assembly code sys::Path uniqueAsmPath("lto-llvm.s"); if ( uniqueAsmPath.createTemporaryFileOnDisk(true, &errMsg) ) return NULL; @@ -169,7 +168,7 @@ void* LTOCodeGenerator::compile(size_t* length, std::string& errMsg) return NULL; } - // make unqiue temp .o file to put generated object file + // make unique temp .o file to put generated object file sys::PathWithStatus uniqueObjPath("lto-llvm.o"); if ( uniqueObjPath.createTemporaryFileOnDisk(true, &errMsg) ) { if ( uniqueAsmPath.exists() ) @@ -179,46 +178,27 @@ void* LTOCodeGenerator::compile(size_t* length, std::string& errMsg) sys::RemoveFileOnSignal(uniqueObjPath); // assemble the assembly code - void* buffer = NULL; + const std::string& uniqueObjStr = uniqueObjPath.toString(); bool asmResult = this->assemble(uniqueAsmPath.toString(), - uniqueObjPath.toString(), errMsg); + uniqueObjStr, errMsg); if ( !asmResult ) { + // remove old buffer if compile() called twice + delete _nativeObjectFile; + // read .o file into memory buffer - const sys::FileStatus* objStatus; - objStatus = uniqueObjPath.getFileStatus(false, &errMsg); - if ( objStatus != NULL ) { - *length = objStatus->getSize(); - // use malloc() because caller will own this buffer and free() it - buffer = ::malloc(*length); - if ( buffer != NULL ) { - int fd = ::open(uniqueObjPath.c_str(), O_RDONLY, 0); - if ( fd != -1 ) { - // read object file contents into buffer - if ( ::read(fd, buffer, *length) != (ssize_t)*length ) { - errMsg = "error reading object file"; - free(buffer); - buffer = NULL; - } - close(fd); - } - else { - errMsg = "error opening object file"; - free(buffer); - buffer = NULL; - } - } - else { - errMsg = "error mallocing space for object file"; - } - } - else { - errMsg = "error stat'ing object file"; - } + _nativeObjectFile = MemoryBuffer::getFile(&uniqueObjStr[0], + uniqueObjStr.size(), &errMsg); } - // clean up temp files + + // remove temp files uniqueAsmPath.eraseFromDisk(); uniqueObjPath.eraseFromDisk(); - return buffer; + + // return buffer, unless error + if ( _nativeObjectFile == NULL ) + return NULL; + *length = _nativeObjectFile->getBufferSize(); + return _nativeObjectFile->getBufferStart(); } diff --git a/tools/lto2/LTOCodeGenerator.h b/tools/lto2/LTOCodeGenerator.h index e9c1f7822a5..eab076ebc88 100644 --- a/tools/lto2/LTOCodeGenerator.h +++ b/tools/lto2/LTOCodeGenerator.h @@ -18,6 +18,7 @@ #include "llvm/Linker.h" #include "llvm/ADT/StringMap.h" +#include // @@ -34,8 +35,9 @@ public: bool setDebugInfo(lto_debug_model, std::string& errMsg); bool setCodePICModel(lto_codegen_model, std::string& errMsg); void addMustPreserveSymbol(const char* sym); - bool writeMergedModules(const char* path, std::string& errMsg); - void* compile(size_t* length, std::string& errMsg); + bool writeMergedModules(const char* path, + std::string& errMsg); + const void* compile(size_t* length, std::string& errMsg); private: bool generateAssemblyCode(std::ostream& out, @@ -53,6 +55,7 @@ private: bool _scopeRestrictionsDone; lto_codegen_model _codeModel; StringSet _mustPreserveSymbols; + llvm::MemoryBuffer* _nativeObjectFile; }; #endif // LTO_CODE_GENERATOR_H diff --git a/tools/lto2/LTOModule.cpp b/tools/lto2/LTOModule.cpp index e10ea5f925f..aad173ccb8a 100644 --- a/tools/lto2/LTOModule.cpp +++ b/tools/lto2/LTOModule.cpp @@ -12,33 +12,21 @@ // //===----------------------------------------------------------------------===// +#include "LTOModule.h" + #include "llvm/Module.h" -#include "llvm/PassManager.h" -#include "llvm/Linker.h" -#include "llvm/Constants.h" -#include "llvm/DerivedTypes.h" #include "llvm/ModuleProvider.h" +#include "llvm/ADT/OwningPtr.h" #include "llvm/Bitcode/ReaderWriter.h" -#include "llvm/Support/CommandLine.h" -#include "llvm/Support/FileUtilities.h" #include "llvm/Support/SystemUtils.h" #include "llvm/Support/Mangler.h" #include "llvm/Support/MemoryBuffer.h" -#include "llvm/System/Program.h" +#include "llvm/Support/MathExtras.h" #include "llvm/System/Path.h" -#include "llvm/System/Signals.h" -#include "llvm/Target/SubtargetFeature.h" -#include "llvm/Target/TargetOptions.h" -#include "llvm/Target/TargetData.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetMachineRegistry.h" #include "llvm/Target/TargetAsmInfo.h" -#include "llvm/Transforms/IPO.h" -#include "llvm/Transforms/Scalar.h" -#include "llvm/Analysis/LoadValueNumbering.h" -#include "llvm/Support/MathExtras.h" -#include "LTOModule.h" #include @@ -58,51 +46,35 @@ bool LTOModule::isBitcodeFile(const char* path) bool LTOModule::isBitcodeFileForTarget(const void* mem, size_t length, const char* triplePrefix) { - bool result = false; - MemoryBuffer* buffer; - buffer = MemoryBuffer::getMemBuffer((char*)mem, (char*)mem+length); - if ( buffer != NULL ) { - ModuleProvider* mp = getBitcodeModuleProvider(buffer); - if ( mp != NULL ) { - std::string actualTarget = mp->getModule()->getTargetTriple(); - if ( strncmp(actualTarget.c_str(), triplePrefix, - strlen(triplePrefix)) == 0) { - result = true; - } - // mp destructor will delete buffer - delete mp; - } - else { - // if getBitcodeModuleProvider failed, we need to delete buffer - delete buffer; - } - } - return result; + MemoryBuffer* buffer = MemoryBuffer::getMemBuffer((char*)mem, + (char*)mem+length); + if ( buffer == NULL ) + return false; + return isTargetMatch(buffer, triplePrefix); } + bool LTOModule::isBitcodeFileForTarget(const char* path, const char* triplePrefix) { - bool result = false; - MemoryBuffer* buffer; - buffer = MemoryBuffer::getFile(path, strlen(path)); - if ( buffer != NULL ) { - ModuleProvider* mp = getBitcodeModuleProvider(buffer); - if ( mp != NULL ) { - std::string actualTarget = mp->getModule()->getTargetTriple(); - if ( strncmp(actualTarget.c_str(), triplePrefix, - strlen(triplePrefix)) == 0) { - result = true; - } - // mp destructor will delete buffer - delete mp; - } - else { - // if getBitcodeModuleProvider failed, we need to delete buffer - delete buffer; - } + MemoryBuffer* buffer = MemoryBuffer::getFile(path, strlen(path)); + if ( buffer == NULL ) + return false; + return isTargetMatch(buffer, triplePrefix); +} + +// takes ownership of buffer +bool LTOModule::isTargetMatch(MemoryBuffer* buffer, const char* triplePrefix) +{ + OwningPtr mp(getBitcodeModuleProvider(buffer)); + // on success, mp owns buffer and both are deleted at end of this method + if ( !mp ) { + delete buffer; + return false; } - return result; + std::string actualTarget = mp->getModule()->getTargetTriple(); + return ( strncmp(actualTarget.c_str(), triplePrefix, + strlen(triplePrefix)) == 0); } @@ -111,68 +83,86 @@ LTOModule::LTOModule(Module* m, TargetMachine* t) { } -LTOModule::~LTOModule() +LTOModule* LTOModule::makeLTOModule(const char* path, std::string& errMsg) { - delete _module; - if ( _target != NULL ) - delete _target; + OwningPtr buffer(MemoryBuffer::getFile( + path, strlen(path), &errMsg)); + if ( !buffer ) + return NULL; + return makeLTOModule(buffer.get(), errMsg); } +LTOModule* LTOModule::makeLTOModule(const void* mem, size_t length, + std::string& errMsg) +{ + OwningPtr buffer(MemoryBuffer::getMemBuffer((char*)mem, + (char*)mem+length)); + if ( !buffer ) + return NULL; + return makeLTOModule(buffer.get(), errMsg); +} -LTOModule* LTOModule::makeLTOModule(const char* path, std::string& errMsg) +LTOModule* LTOModule::makeLTOModule(MemoryBuffer* buffer, std::string& errMsg) { - MemoryBuffer* buffer = MemoryBuffer::getFile(path, strlen(path)); - if ( buffer != NULL ) { - Module* m = ParseBitcodeFile(buffer, &errMsg); - delete buffer; - if ( m != NULL ) { - const TargetMachineRegistry::entry* march = - TargetMachineRegistry::getClosestStaticTargetForModule(*m, errMsg); - if ( march != NULL ) { - std::string features; - TargetMachine* target = march->CtorFn(*m, features); - return new LTOModule(m, target); - } - } - } - return NULL; + // parse bitcode buffer + OwningPtr m(ParseBitcodeFile(buffer, &errMsg)); + if ( !m ) + return NULL; + // find machine architecture for this module + const TargetMachineRegistry::entry* march = + TargetMachineRegistry::getClosestStaticTargetForModule(*m, errMsg); + if ( march == NULL ) + return NULL; + // construct LTModule, hand over ownership of module and target + std::string features; + TargetMachine* target = march->CtorFn(*m, features); + return new LTOModule(m.take(), target); } -LTOModule* LTOModule::makeLTOModule(const void* mem, size_t length, - std::string& errMsg) + +const char* LTOModule::getTargetTriple() { - MemoryBuffer* buffer; - buffer = MemoryBuffer::getMemBuffer((char*)mem, (char*)mem+length); - if ( buffer != NULL ) { - Module* m = ParseBitcodeFile(buffer, &errMsg); - delete buffer; - if ( m != NULL ) { - const TargetMachineRegistry::entry* march = - TargetMachineRegistry::getClosestStaticTargetForModule(*m, errMsg); - if ( march != NULL ) { - std::string features; - TargetMachine* target = march->CtorFn(*m, features); - return new LTOModule(m, target); + return _module->getTargetTriple().c_str(); +} + +void LTOModule::addDefinedFunctionSymbol(Function* f, Mangler &mangler) +{ + // add to list of defined symbols + addDefinedSymbol(f, mangler, true); + + // add external symbols referenced by this function. + for (Function::iterator b = f->begin(); b != f->end(); ++b) { + for (BasicBlock::iterator i = b->begin(); i != b->end(); ++i) { + for (unsigned count = 0, total = i->getNumOperands(); + count != total; ++count) { + findExternalRefs(i->getOperand(count), mangler); } } } - return NULL; } +void LTOModule::addDefinedDataSymbol(GlobalValue* v, Mangler &mangler) +{ + // add to list of defined symbols + addDefinedSymbol(v, mangler, false); -const char* LTOModule::getTargetTriple() -{ - return _module->getTargetTriple().c_str(); + // add external symbols referenced by this data. + for (unsigned count = 0, total = v->getNumOperands();\ + count != total; ++count) { + findExternalRefs(v->getOperand(count), mangler); + } } + void LTOModule::addDefinedSymbol(GlobalValue* def, Mangler &mangler, bool isFunction) { + // string is owned by _defines const char* symbolName = ::strdup(mangler.getValueName(def).c_str()); // set alignment part log2() can have rounding errors uint32_t align = def->getAlignment(); - uint32_t attr = align ? __builtin_ctz(def->getAlignment()) : 0; + uint32_t attr = align ? CountTrailingZeros_32(def->getAlignment()) : 0; // set permissions part if ( isFunction ) @@ -220,8 +210,9 @@ void LTOModule::addDefinedSymbol(GlobalValue* def, Mangler &mangler, } -void LTOModule::addUndefinedSymbol(const char* name) -{ +void LTOModule::addPotentialUndefinedSymbol(GlobalValue* decl, Mangler &mangler) +{ + const char* name = mangler.getValueName(decl).c_str(); // ignore all llvm.* symbols if ( strncmp(name, "llvm.", 5) != 0 ) { _undefines[name] = 1; @@ -235,7 +226,7 @@ void LTOModule::findExternalRefs(Value* value, Mangler &mangler) { if (GlobalValue* gv = dyn_cast(value)) { if ( !gv->hasExternalLinkage() ) - addUndefinedSymbol(mangler.getValueName(gv).c_str()); + addPotentialUndefinedSymbol(gv, mangler); } // GlobalValue, even with InternalLinkage type, may have operands with @@ -247,8 +238,7 @@ void LTOModule::findExternalRefs(Value* value, Mangler &mangler) { } } - -uint32_t LTOModule::getSymbolCount() +void LTOModule::lazyParseSymbols() { if ( !_symbolsParsed ) { _symbolsParsed = true; @@ -258,38 +248,19 @@ uint32_t LTOModule::getSymbolCount() // add functions for (Module::iterator f = _module->begin(); f != _module->end(); ++f) { - if ( f->isDeclaration() ) { - addUndefinedSymbol(mangler.getValueName(f).c_str()); - } - else { - addDefinedSymbol(f, mangler, true); - // add external symbols referenced by this function. - for (Function::iterator b = f->begin(); b != f->end(); ++b) { - for (BasicBlock::iterator i = b->begin(); - i != b->end(); ++i) { - for (unsigned count = 0, total = i->getNumOperands(); - count != total; ++count) { - findExternalRefs(i->getOperand(count), mangler); - } - } - } - } + if ( f->isDeclaration() ) + addPotentialUndefinedSymbol(f, mangler); + else + addDefinedFunctionSymbol(f, mangler); } // add data for (Module::global_iterator v = _module->global_begin(), e = _module->global_end(); v != e; ++v) { - if ( v->isDeclaration() ) { - addUndefinedSymbol(mangler.getValueName(v).c_str()); - } - else { - addDefinedSymbol(v, mangler, false); - // add external symbols referenced by this data - for (unsigned count = 0, total = v->getNumOperands(); - count != total; ++count) { - findExternalRefs(v->getOperand(count), mangler); - } - } + if ( v->isDeclaration() ) + addPotentialUndefinedSymbol(v, mangler); + else + addDefinedDataSymbol(v, mangler); } // make symbols for all undefines @@ -297,22 +268,28 @@ uint32_t LTOModule::getSymbolCount() 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.find(it->getKeyData(), it->getKeyData()+it->getKeyLength()) == _defines.end() ) { + if ( _defines.count(it->getKeyData(), it->getKeyData()+ + it->getKeyLength()) == 0 ) { NameAndAttributes info; info.name = it->getKeyData(); info.attributes = LTO_SYMBOL_DEFINITION_UNDEFINED; _symbols.push_back(info); } } - - } - + } +} + + +uint32_t LTOModule::getSymbolCount() +{ + lazyParseSymbols(); return _symbols.size(); } lto_symbol_attributes LTOModule::getSymbolAttributes(uint32_t index) { + lazyParseSymbols(); if ( index < _symbols.size() ) return _symbols[index].attributes; else @@ -321,6 +298,7 @@ lto_symbol_attributes LTOModule::getSymbolAttributes(uint32_t index) const char* LTOModule::getSymbolName(uint32_t index) { + lazyParseSymbols(); if ( index < _symbols.size() ) return _symbols[index].name; else diff --git a/tools/lto2/LTOModule.h b/tools/lto2/LTOModule.h index 9770757339b..7735e2f2a57 100644 --- a/tools/lto2/LTOModule.h +++ b/tools/lto2/LTOModule.h @@ -15,15 +15,24 @@ #define LTO_MODULE_H #include "llvm/Module.h" -#include "llvm/GlobalValue.h" -#include "llvm/Constants.h" -#include "llvm/Support/Mangler.h" +#include "llvm/ADT/OwningPtr.h" #include "llvm/Target/TargetMachine.h" #include "llvm/ADT/StringMap.h" #include "llvm-c/lto.h" #include +#include + + +// forward references to llvm classes +namespace llvm { + class Mangler; + class MemoryBuffer; + class GlobalValue; + class Value; + class Function; +} // @@ -44,26 +53,35 @@ public: static LTOModule* makeLTOModule(const char* path, std::string& errMsg); static LTOModule* makeLTOModule(const void* mem, size_t length, std::string& errMsg); - ~LTOModule(); const char* getTargetTriple(); uint32_t getSymbolCount(); lto_symbol_attributes getSymbolAttributes(uint32_t index); const char* getSymbolName(uint32_t index); - llvm::Module * getLLVVMModule() { return _module; } - bool targetSupported() { return (_target != NULL); } + llvm::Module * getLLVVMModule() { return _module.get(); } private: LTOModule(llvm::Module* m, llvm::TargetMachine* t); + void lazyParseSymbols(); void addDefinedSymbol(llvm::GlobalValue* def, llvm::Mangler& mangler, bool isFunction); - void addUndefinedSymbol(const char* name); + void addPotentialUndefinedSymbol(llvm::GlobalValue* decl, + llvm::Mangler &mangler); void findExternalRefs(llvm::Value* value, llvm::Mangler& mangler); + void addDefinedFunctionSymbol(llvm::Function* f, + llvm::Mangler &mangler); + void addDefinedDataSymbol(llvm::GlobalValue* v, + llvm::Mangler &mangler); + static bool isTargetMatch(llvm::MemoryBuffer* memBuffer, + const char* triplePrefix); + static LTOModule* makeLTOModule(llvm::MemoryBuffer* buffer, + std::string& errMsg); + typedef llvm::StringMap StringSet; struct NameAndAttributes { @@ -71,12 +89,13 @@ private: lto_symbol_attributes attributes; }; - llvm::Module * _module; - llvm::TargetMachine * _target; - bool _symbolsParsed; - std::vector _symbols; - StringSet _defines; // only needed to disambiguate tentative definitions - StringSet _undefines; // only needed to disambiguate tentative definitions + llvm::OwningPtr _module; + llvm::OwningPtr _target; + bool _symbolsParsed; + std::vector _symbols; + // _defines and _undefines only needed to disambiguate tentative definitions + StringSet _defines; + StringSet _undefines; }; #endif // LTO_MODULE_H diff --git a/tools/lto2/lto.cpp b/tools/lto2/lto.cpp index d6f1d98b168..f60f7b5ac09 100644 --- a/tools/lto2/lto.cpp +++ b/tools/lto2/lto.cpp @@ -33,7 +33,7 @@ extern const char* lto_get_version() } // -// returns the last error string or NULL if last operation was sucessful +// returns the last error string or NULL if last operation was successful // const char* lto_get_error_message() { @@ -224,13 +224,14 @@ bool lto_codegen_write_merged_modules(lto_code_gen_t cg, const char* path) // -// generates code for all added modules into one object file -// On sucess returns a pointer to a generated mach-o buffer and -// length set to the buffer size. Client must free() the buffer -// when done. -// On failure, returns NULL (check lto_get_error_message() for details) +// Generates code for all added modules into one native object file. +// On sucess 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 void* +extern const void* lto_codegen_compile(lto_code_gen_t cg, size_t* length) { return cg->compile(length, sLastErrorString); -- 2.34.1