diff options
author | dim <dim@FreeBSD.org> | 2011-05-02 19:34:44 +0000 |
---|---|---|
committer | dim <dim@FreeBSD.org> | 2011-05-02 19:34:44 +0000 |
commit | 2b066988909948dc3d53d01760bc2d71d32f3feb (patch) | |
tree | fc5f365fb9035b2d0c622bbf06c9bbe8627d7279 /tools/lto | |
parent | c80ac9d286b8fcc6d1ee5d76048134cf80aa9edc (diff) | |
download | FreeBSD-src-2b066988909948dc3d53d01760bc2d71d32f3feb.zip FreeBSD-src-2b066988909948dc3d53d01760bc2d71d32f3feb.tar.gz |
Vendor import of llvm trunk r130700:
http://llvm.org/svn/llvm-project/llvm/trunk@130700
Diffstat (limited to 'tools/lto')
-rw-r--r-- | tools/lto/CMakeLists.txt | 27 | ||||
-rw-r--r-- | tools/lto/LTOCodeGenerator.cpp | 204 | ||||
-rw-r--r-- | tools/lto/LTOCodeGenerator.h | 8 | ||||
-rw-r--r-- | tools/lto/LTOModule.cpp | 356 | ||||
-rw-r--r-- | tools/lto/LTOModule.h | 21 | ||||
-rw-r--r-- | tools/lto/Makefile | 3 | ||||
-rw-r--r-- | tools/lto/lto.cpp | 23 | ||||
-rw-r--r-- | tools/lto/lto.exports | 5 |
8 files changed, 471 insertions, 176 deletions
diff --git a/tools/lto/CMakeLists.txt b/tools/lto/CMakeLists.txt new file mode 100644 index 0000000..7e2c5f0 --- /dev/null +++ b/tools/lto/CMakeLists.txt @@ -0,0 +1,27 @@ +set(LLVM_LINK_COMPONENTS + ${LLVM_TARGETS_TO_BUILD} + ipo scalaropts linker bitreader bitwriter mcdisassembler) + +add_definitions( -DLLVM_VERSION_INFO=\"${PACKAGE_VERSION}\" ) + +set(SOURCES + LTOCodeGenerator.cpp + lto.cpp + LTOModule.cpp + ) + +if( NOT WIN32 AND LLVM_ENABLE_PIC ) + set(bsl ${BUILD_SHARED_LIBS}) + set(BUILD_SHARED_LIBS ON) + add_llvm_library(LTO ${SOURCES}) + set_property(TARGET LTO PROPERTY OUTPUT_NAME "LTO") + set(BUILD_SHARED_LIBS ${bsl}) + set(LTO_STATIC_TARGET_NAME LTO_static) +else() + set(LTO_STATIC_TARGET_NAME LTO) +endif() + +if( NOT BUILD_SHARED_LIBS ) + add_llvm_library(${LTO_STATIC_TARGET_NAME} ${SOURCES}) + set_property(TARGET ${LTO_STATIC_TARGET_NAME} PROPERTY OUTPUT_NAME "LTO") +endif() diff --git a/tools/lto/LTOCodeGenerator.cpp b/tools/lto/LTOCodeGenerator.cpp index f72fdb0..d95f354 100644 --- a/tools/lto/LTOCodeGenerator.cpp +++ b/tools/lto/LTOCodeGenerator.cpp @@ -75,7 +75,6 @@ LTOCodeGenerator::LTOCodeGenerator() { InitializeAllTargets(); InitializeAllAsmPrinters(); - InitializeAllAsmParsers(); } LTOCodeGenerator::~LTOCodeGenerator() @@ -88,7 +87,17 @@ LTOCodeGenerator::~LTOCodeGenerator() bool LTOCodeGenerator::addModule(LTOModule* mod, std::string& errMsg) { - return _linker.LinkInModule(mod->getLLVVMModule(), &errMsg); + + if(mod->getLLVVMModule()->MaterializeAllPermanently(&errMsg)) + return true; + + bool ret = _linker.LinkInModule(mod->getLLVVMModule(), &errMsg); + + const std::vector<const char*> &undefs = mod->getAsmUndefinedRefs(); + for (int i = 0, e = undefs.size(); i != e; ++i) + _asmUndefinedRefs[undefs[i]] = 1; + + return ret; } @@ -167,51 +176,63 @@ bool LTOCodeGenerator::writeMergedModules(const char *path, } -const void* LTOCodeGenerator::compile(size_t* length, 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) ) { - uniqueObjPath.eraseFromDisk(); - return NULL; - } - sys::RemoveFileOnSignal(uniqueObjPath); - - // generate object file - bool genResult = false; - tool_output_file objFile(uniqueObjPath.c_str(), errMsg); - if (!errMsg.empty()) - return NULL; - genResult = this->generateObjectFile(objFile.os(), errMsg); - objFile.os().close(); - if (objFile.os().has_error()) { - objFile.os().clear_error(); - return NULL; - } - objFile.keep(); - if ( genResult ) { - uniqueObjPath.eraseFromDisk(); - return NULL; - } + // make unique temp .o file to put generated object file + sys::PathWithStatus uniqueObjPath("lto-llvm.o"); + if ( uniqueObjPath.createTemporaryFileOnDisk(false, &errMsg) ) { + uniqueObjPath.eraseFromDisk(); + return true; + } + sys::RemoveFileOnSignal(uniqueObjPath); + + // generate object file + bool genResult = false; + tool_output_file objFile(uniqueObjPath.c_str(), errMsg); + if (!errMsg.empty()) + return NULL; + 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(); + return true; + } - const std::string& uniqueObjStr = uniqueObjPath.str(); - // remove old buffer if compile() called twice - delete _nativeObjectFile; + _nativeObjectPath = uniqueObjPath.str(); + *name = _nativeObjectPath.c_str(); + return false; +} - // read .o file into memory buffer - OwningPtr<MemoryBuffer> BuffPtr; - if (error_code ec = MemoryBuffer::getFile(uniqueObjStr.c_str(),BuffPtr)) - errMsg = ec.message(); - _nativeObjectFile = BuffPtr.take(); +const void* LTOCodeGenerator::compile(size_t* length, std::string& errMsg) +{ + const char *name; + if (compile_to_file(&name, errMsg)) + return NULL; + + // remove old buffer if compile() called twice + delete _nativeObjectFile; + + // read .o file into memory buffer + OwningPtr<MemoryBuffer> BuffPtr; + if (error_code ec = MemoryBuffer::getFile(name, BuffPtr, -1, false)) { + errMsg = ec.message(); + return NULL; + } + _nativeObjectFile = BuffPtr.take(); - // remove temp files - uniqueObjPath.eraseFromDisk(); + // remove temp files + sys::Path(_nativeObjectPath).eraseFromDisk(); - // return buffer, unless error - if ( _nativeObjectFile == NULL ) - return NULL; - *length = _nativeObjectFile->getBufferSize(); - return _nativeObjectFile->getBufferStart(); + // return buffer, unless error + if ( _nativeObjectFile == NULL ) + return NULL; + *length = _nativeObjectFile->getBufferSize(); + return _nativeObjectFile->getBufferStart(); } bool LTOCodeGenerator::determineTarget(std::string& errMsg) @@ -249,6 +270,34 @@ bool LTOCodeGenerator::determineTarget(std::string& errMsg) return false; } +void LTOCodeGenerator::applyRestriction(GlobalValue &GV, + std::vector<const char*> &mustPreserveList, + SmallPtrSet<GlobalValue*, 8> &asmUsed, + Mangler &mangler) { + SmallString<64> Buffer; + mangler.getNameWithPrefix(Buffer, &GV, false); + + if (GV.isDeclaration()) + return; + if (_mustPreserveSymbols.count(Buffer)) + mustPreserveList.push_back(GV.getName().data()); + if (_asmUndefinedRefs.count(Buffer)) + asmUsed.insert(&GV); +} + +static void findUsedValues(GlobalVariable *LLVMUsed, + SmallPtrSet<GlobalValue*, 8> &UsedValues) { + if (LLVMUsed == 0) return; + + ConstantArray *Inits = dyn_cast<ConstantArray>(LLVMUsed->getInitializer()); + if (Inits == 0) return; + + for (unsigned i = 0, e = Inits->getNumOperands(); i != e; ++i) + if (GlobalValue *GV = + dyn_cast<GlobalValue>(Inits->getOperand(i)->stripPointerCasts())) + UsedValues.insert(GV); +} + void LTOCodeGenerator::applyScopeRestrictions() { if (_scopeRestrictionsDone) return; Module *mergedModule = _linker.getModule(); @@ -258,38 +307,47 @@ void LTOCodeGenerator::applyScopeRestrictions() { passes.add(createVerifierPass()); // mark which symbols can not be internalized - if (!_mustPreserveSymbols.empty()) { - MCContext Context(*_target->getMCAsmInfo(), NULL); - Mangler mangler(Context, *_target->getTargetData()); - std::vector<const char*> mustPreserveList; - SmallString<64> Buffer; - for (Module::iterator f = mergedModule->begin(), - e = mergedModule->end(); f != e; ++f) { - Buffer.clear(); - mangler.getNameWithPrefix(Buffer, f, false); - if (!f->isDeclaration() && - _mustPreserveSymbols.count(Buffer)) - mustPreserveList.push_back(f->getName().data()); - } - for (Module::global_iterator v = mergedModule->global_begin(), - e = mergedModule->global_end(); v != e; ++v) { - Buffer.clear(); - mangler.getNameWithPrefix(Buffer, v, false); - if (!v->isDeclaration() && - _mustPreserveSymbols.count(Buffer)) - mustPreserveList.push_back(v->getName().data()); - } - for (Module::alias_iterator a = mergedModule->alias_begin(), - e = mergedModule->alias_end(); a != e; ++a) { - Buffer.clear(); - mangler.getNameWithPrefix(Buffer, a, false); - if (!a->isDeclaration() && - _mustPreserveSymbols.count(Buffer)) - mustPreserveList.push_back(a->getName().data()); - } - passes.add(createInternalizePass(mustPreserveList)); + MCContext Context(*_target->getMCAsmInfo(), NULL); + Mangler mangler(Context, *_target->getTargetData()); + std::vector<const char*> mustPreserveList; + SmallPtrSet<GlobalValue*, 8> asmUsed; + + 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(), + e = mergedModule->global_end(); v != e; ++v) + applyRestriction(*v, mustPreserveList, asmUsed, mangler); + for (Module::alias_iterator a = mergedModule->alias_begin(), + e = mergedModule->alias_end(); a != e; ++a) + applyRestriction(*a, mustPreserveList, asmUsed, mangler); + + GlobalVariable *LLVMCompilerUsed = + mergedModule->getGlobalVariable("llvm.compiler.used"); + findUsedValues(LLVMCompilerUsed, asmUsed); + if (LLVMCompilerUsed) + LLVMCompilerUsed->eraseFromParent(); + + const llvm::Type *i8PTy = llvm::Type::getInt8PtrTy(_context); + std::vector<Constant*> asmUsed2; + for (SmallPtrSet<GlobalValue*, 16>::const_iterator i = asmUsed.begin(), + e = asmUsed.end(); i !=e; ++i) { + GlobalValue *GV = *i; + Constant *c = ConstantExpr::getBitCast(GV, i8PTy); + asmUsed2.push_back(c); } - + + llvm::ArrayType *ATy = llvm::ArrayType::get(i8PTy, asmUsed2.size()); + LLVMCompilerUsed = + new llvm::GlobalVariable(*mergedModule, ATy, false, + llvm::GlobalValue::AppendingLinkage, + llvm::ConstantArray::get(ATy, asmUsed2), + "llvm.compiler.used"); + + LLVMCompilerUsed->setSection("llvm.metadata"); + + passes.add(createInternalizePass(mustPreserveList)); + // apply scope restrictions passes.run(*mergedModule); diff --git a/tools/lto/LTOCodeGenerator.h b/tools/lto/LTOCodeGenerator.h index 0556520..f8fd357 100644 --- a/tools/lto/LTOCodeGenerator.h +++ b/tools/lto/LTOCodeGenerator.h @@ -19,6 +19,7 @@ #include "llvm/LLVMContext.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/SmallPtrSet.h" #include <string> @@ -40,12 +41,17 @@ struct LTOCodeGenerator { 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); private: 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; @@ -57,9 +63,11 @@ private: bool _scopeRestrictionsDone; lto_codegen_model _codeModel; StringSet _mustPreserveSymbols; + StringSet _asmUndefinedRefs; llvm::MemoryBuffer* _nativeObjectFile; std::vector<const 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 1eac22c..8f2b1f4 100644 --- a/tools/lto/LTOModule.cpp +++ b/tools/lto/LTOModule.cpp @@ -26,11 +26,18 @@ #include "llvm/Support/Host.h" #include "llvm/Support/Path.h" #include "llvm/Support/Process.h" +#include "llvm/Support/SourceMgr.h" #include "llvm/Support/system_error.h" #include "llvm/Target/Mangler.h" #include "llvm/Target/SubtargetFeature.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/MCSymbol.h" +#include "llvm/Target/TargetAsmParser.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetRegistry.h" #include "llvm/Target/TargetSelect.h" @@ -73,7 +80,7 @@ bool LTOModule::isTargetMatch(MemoryBuffer *buffer, const char *triplePrefix) { LTOModule::LTOModule(Module *m, TargetMachine *t) - : _module(m), _target(t), _symbolsParsed(false) + : _module(m), _target(t) { } @@ -84,32 +91,33 @@ LTOModule *LTOModule::makeLTOModule(const char *path, errMsg = ec.message(); return NULL; } - return makeLTOModule(buffer.get(), errMsg); + return makeLTOModule(buffer.take(), errMsg); } LTOModule *LTOModule::makeLTOModule(int fd, const char *path, - off_t size, + size_t size, + std::string &errMsg) { + return makeLTOModule(fd, path, size, size, 0, errMsg); +} + +LTOModule *LTOModule::makeLTOModule(int fd, const char *path, + size_t file_size, + size_t map_size, + off_t offset, std::string &errMsg) { OwningPtr<MemoryBuffer> buffer; - if (error_code ec = MemoryBuffer::getOpenFile(fd, path, buffer, size)) { + if (error_code ec = MemoryBuffer::getOpenFile(fd, path, buffer, file_size, + map_size, offset, false)) { errMsg = ec.message(); return NULL; } - return makeLTOModule(buffer.get(), errMsg); + return makeLTOModule(buffer.take(), errMsg); } -/// makeBuffer - Create a MemoryBuffer from a memory range. MemoryBuffer -/// requires the byte past end of the buffer to be a zero. We might get lucky -/// and already be that way, otherwise make a copy. Also if next byte is on a -/// different page, don't assume it is readable. +/// makeBuffer - Create a MemoryBuffer from a memory range. MemoryBuffer *LTOModule::makeBuffer(const void *mem, size_t length) { const char *startPtr = (char*)mem; - const char *endPtr = startPtr+length; - if (((uintptr_t)endPtr & (sys::Process::GetPageSize()-1)) == 0 || - *endPtr != 0) - return MemoryBuffer::getMemBufferCopy(StringRef(startPtr, length)); - - return MemoryBuffer::getMemBuffer(StringRef(startPtr, length)); + return MemoryBuffer::getMemBuffer(StringRef(startPtr, length), "", false); } @@ -118,17 +126,25 @@ LTOModule *LTOModule::makeLTOModule(const void *mem, size_t length, OwningPtr<MemoryBuffer> buffer(makeBuffer(mem, length)); if (!buffer) return NULL; - return makeLTOModule(buffer.get(), errMsg); + return makeLTOModule(buffer.take(), errMsg); } LTOModule *LTOModule::makeLTOModule(MemoryBuffer *buffer, std::string &errMsg) { - InitializeAllTargets(); + static bool Initialized = false; + if (!Initialized) { + InitializeAllTargets(); + InitializeAllAsmParsers(); + Initialized = true; + } // parse bitcode buffer - OwningPtr<Module> m(ParseBitcodeFile(buffer, getGlobalContext(), &errMsg)); - if (!m) + OwningPtr<Module> m(getLazyBitcodeModule(buffer, getGlobalContext(), + &errMsg)); + if (!m) { + delete buffer; return NULL; + } std::string Triple = m->getTargetTriple(); if (Triple.empty()) @@ -139,12 +155,18 @@ LTOModule *LTOModule::makeLTOModule(MemoryBuffer *buffer, if (!march) return NULL; - // construct LTModule, hand over ownership of module and target + // construct LTOModule, hand over ownership of module and target SubtargetFeatures Features; Features.getDefaultSubtargetFeatures("" /* cpu */, llvm::Triple(Triple)); std::string FeatureStr = Features.getString(); TargetMachine *target = march->createTargetMachine(Triple, FeatureStr); - return new LTOModule(m.take(), target); + LTOModule *Ret = new LTOModule(m.take(), target); + bool Err = Ret->ParseSymbols(); + if (Err) { + delete Ret; + return NULL; + } + return Ret; } @@ -159,16 +181,6 @@ void LTOModule::setTargetTriple(const char *triple) { 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); - } - } - } } // Get string that data pointer points to. @@ -309,12 +321,6 @@ void LTOModule::addDefinedDataSymbol(GlobalValue *v, Mangler &mangler) { } } } - - // add external symbols referenced by this data. - for (unsigned count = 0, total = v->getNumOperands(); - count != total; ++count) { - findExternalRefs(v->getOperand(count), mangler); - } } @@ -324,10 +330,6 @@ void LTOModule::addDefinedSymbol(GlobalValue *def, Mangler &mangler, if (def->getName().startswith("llvm.")) return; - // ignore available_externally - if (def->hasAvailableExternallyLinkage()) - return; - // string is owned by _defines SmallString<64> Buffer; mangler.getNameWithPrefix(Buffer, def, false); @@ -383,7 +385,8 @@ void LTOModule::addDefinedSymbol(GlobalValue *def, Mangler &mangler, _symbols.push_back(info); } -void LTOModule::addAsmGlobalSymbol(const char *name) { +void LTOModule::addAsmGlobalSymbol(const char *name, + lto_symbol_attributes scope) { StringSet::value_type &entry = _defines.GetOrCreateValue(name); // only add new define if not already defined @@ -393,13 +396,32 @@ void LTOModule::addAsmGlobalSymbol(const char *name) { entry.setValue(1); const char *symbolName = entry.getKey().data(); uint32_t attr = LTO_SYMBOL_DEFINITION_REGULAR; - attr |= LTO_SYMBOL_SCOPE_DEFAULT; + attr |= scope; NameAndAttributes info; info.name = symbolName; info.attributes = (lto_symbol_attributes)attr; _symbols.push_back(info); } +void LTOModule::addAsmGlobalSymbolUndef(const char *name) { + StringMap<NameAndAttributes>::value_type &entry = + _undefines.GetOrCreateValue(name); + + _asm_undefines.push_back(entry.getKey().data()); + + // we already have the symbol + if (entry.getValue().name) + return; + + uint32_t attr = LTO_SYMBOL_DEFINITION_UNDEFINED;; + attr |= LTO_SYMBOL_SCOPE_DEFAULT; + NameAndAttributes info; + info.name = entry.getKey().data(); + info.attributes = (lto_symbol_attributes)attr; + + entry.setValue(info); +} + void LTOModule::addPotentialUndefinedSymbol(GlobalValue *decl, Mangler &mangler) { // ignore all llvm.* symbols @@ -432,41 +454,211 @@ void LTOModule::addPotentialUndefinedSymbol(GlobalValue *decl, } +namespace { + class RecordStreamer : public MCStreamer { + public: + enum State { NeverSeen, Global, Defined, DefinedGlobal, Used}; + + private: + StringMap<State> Symbols; + + void markDefined(const MCSymbol &Symbol) { + State &S = Symbols[Symbol.getName()]; + switch (S) { + case DefinedGlobal: + case Global: + S = DefinedGlobal; + break; + case NeverSeen: + case Defined: + case Used: + S = Defined; + break; + } + } + void markGlobal(const MCSymbol &Symbol) { + State &S = Symbols[Symbol.getName()]; + switch (S) { + case DefinedGlobal: + case Defined: + S = DefinedGlobal; + break; + + case NeverSeen: + case Global: + case Used: + S = Global; + break; + } + } + void markUsed(const MCSymbol &Symbol) { + State &S = Symbols[Symbol.getName()]; + switch (S) { + case DefinedGlobal: + case Defined: + case Global: + break; + + case NeverSeen: + case Used: + S = Used; + break; + } + } + + // FIXME: mostly copied for the obj streamer. + void AddValueSymbols(const MCExpr *Value) { + switch (Value->getKind()) { + case MCExpr::Target: + // FIXME: What should we do in here? + break; + + case MCExpr::Constant: + break; + + case MCExpr::Binary: { + const MCBinaryExpr *BE = cast<MCBinaryExpr>(Value); + AddValueSymbols(BE->getLHS()); + AddValueSymbols(BE->getRHS()); + break; + } + + case MCExpr::SymbolRef: + markUsed(cast<MCSymbolRefExpr>(Value)->getSymbol()); + break; -// Find external symbols referenced by VALUE. This is a recursive function. -void LTOModule::findExternalRefs(Value *value, Mangler &mangler) { - if (GlobalValue *gv = dyn_cast<GlobalValue>(value)) { - if (!gv->hasExternalLinkage()) - addPotentialUndefinedSymbol(gv, mangler); - // If this is a variable definition, do not recursively process - // initializer. It might contain a reference to this variable - // and cause an infinite loop. The initializer will be - // processed in addDefinedDataSymbol(). - return; - } + case MCExpr::Unary: + AddValueSymbols(cast<MCUnaryExpr>(Value)->getSubExpr()); + break; + } + } + + public: + typedef StringMap<State>::const_iterator const_iterator; + + const_iterator begin() { + return Symbols.begin(); + } - // GlobalValue, even with InternalLinkage type, may have operands with - // ExternalLinkage type. Do not ignore these operands. - if (Constant *c = dyn_cast<Constant>(value)) { - // Handle ConstantExpr, ConstantStruct, ConstantArry etc. - for (unsigned i = 0, e = c->getNumOperands(); i != e; ++i) - findExternalRefs(c->getOperand(i), mangler); + const_iterator end() { + return Symbols.end(); + } + + RecordStreamer(MCContext &Context) : MCStreamer(Context) {} + + virtual void ChangeSection(const MCSection *Section) {} + virtual void InitSections() {} + 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); + } + virtual void EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) { + 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); + } + virtual void EmitELFSize(MCSymbol *Symbol, const MCExpr *Value) {} + virtual void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size) {} + virtual void EmitTBSSSymbol(const MCSection *Section, MCSymbol *Symbol, + uint64_t Size, unsigned ByteAlignment) {} + virtual void EmitBytes(StringRef Data, unsigned AddrSpace) {} + virtual void EmitValueImpl(const MCExpr *Value, unsigned Size, + unsigned AddrSpace) {} + virtual void EmitULEB128Value(const MCExpr *Value) {} + virtual void EmitSLEB128Value(const MCExpr *Value) {} + virtual void EmitValueToAlignment(unsigned ByteAlignment, int64_t Value, + unsigned ValueSize, + unsigned MaxBytesToEmit) {} + virtual void EmitCodeAlignment(unsigned ByteAlignment, + unsigned MaxBytesToEmit) {} + virtual void EmitValueToOffset(const MCExpr *Offset, + unsigned char Value ) {} + virtual void EmitFileDirective(StringRef Filename) {} + virtual void EmitDwarfAdvanceLineAddr(int64_t LineDelta, + const MCSymbol *LastLabel, + const MCSymbol *Label) {} + + 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() {} + }; +} + +bool LTOModule::addAsmGlobalSymbols(MCContext &Context) { + const std::string &inlineAsm = _module->getModuleInlineAsm(); + + OwningPtr<RecordStreamer> Streamer(new RecordStreamer(Context)); + MemoryBuffer *Buffer = MemoryBuffer::getMemBuffer(inlineAsm); + SourceMgr SrcMgr; + SrcMgr.AddNewSourceBuffer(Buffer, SMLoc()); + OwningPtr<MCAsmParser> Parser(createMCAsmParser(_target->getTarget(), SrcMgr, + Context, *Streamer, + *_target->getMCAsmInfo())); + OwningPtr<TargetAsmParser> + TAP(_target->getTarget().createAsmParser(*Parser.get(), *_target.get())); + Parser->setTargetParser(*TAP); + int Res = Parser->Run(false); + if (Res) + return true; + + for (RecordStreamer::const_iterator i = Streamer->begin(), + e = Streamer->end(); i != e; ++i) { + StringRef Key = i->first(); + RecordStreamer::State Value = i->second; + if (Value == RecordStreamer::DefinedGlobal) + addAsmGlobalSymbol(Key.data(), LTO_SYMBOL_SCOPE_DEFAULT); + else if (Value == RecordStreamer::Defined) + addAsmGlobalSymbol(Key.data(), LTO_SYMBOL_SCOPE_INTERNAL); + else if (Value == RecordStreamer::Global || + Value == RecordStreamer::Used) + addAsmGlobalSymbolUndef(Key.data()); } + return false; } -void LTOModule::lazyParseSymbols() { - if (_symbolsParsed) - return; +static bool isDeclaration(const GlobalValue &V) { + if (V.hasAvailableExternallyLinkage()) + return true; + if (V.isMaterializable()) + return false; + return V.isDeclaration(); +} - _symbolsParsed = true; +static bool isAliasToDeclaration(const GlobalAlias &V) { + return isDeclaration(*V.getAliasedGlobal()); +} +bool LTOModule::ParseSymbols() { // Use mangler to add GlobalPrefix to names to match linker names. MCContext Context(*_target->getMCAsmInfo(), NULL); Mangler mangler(Context, *_target->getTargetData()); // add functions for (Module::iterator f = _module->begin(); f != _module->end(); ++f) { - if (f->isDeclaration()) + if (isDeclaration(*f)) addPotentialUndefinedSymbol(f, mangler); else addDefinedFunctionSymbol(f, mangler); @@ -475,42 +667,20 @@ void LTOModule::lazyParseSymbols() { // add data for (Module::global_iterator v = _module->global_begin(), e = _module->global_end(); v != e; ++v) { - if (v->isDeclaration()) + if (isDeclaration(*v)) addPotentialUndefinedSymbol(v, mangler); else addDefinedDataSymbol(v, mangler); } // add asm globals - const std::string &inlineAsm = _module->getModuleInlineAsm(); - const std::string glbl = ".globl"; - std::string asmSymbolName; - std::string::size_type pos = inlineAsm.find(glbl, 0); - while (pos != std::string::npos) { - // eat .globl - pos = pos + 6; - - // skip white space between .globl and symbol name - std::string::size_type pbegin = inlineAsm.find_first_not_of(' ', pos); - if (pbegin == std::string::npos) - break; - - // find end-of-line - std::string::size_type pend = inlineAsm.find_first_of('\n', pbegin); - if (pend == std::string::npos) - break; - - asmSymbolName.assign(inlineAsm, pbegin, pend - pbegin); - addAsmGlobalSymbol(asmSymbolName.c_str()); - - // search next .globl - pos = inlineAsm.find(glbl, pend); - } + if (addAsmGlobalSymbols(Context)) + return true; // add aliases for (Module::alias_iterator i = _module->alias_begin(), e = _module->alias_end(); i != e; ++i) { - if (i->isDeclaration()) + if (isAliasToDeclaration(*i)) addPotentialUndefinedSymbol(i, mangler); else addDefinedDataSymbol(i, mangler); @@ -526,17 +696,16 @@ void LTOModule::lazyParseSymbols() { _symbols.push_back(info); } } + return false; } 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 @@ -544,7 +713,6 @@ 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/lto/LTOModule.h b/tools/lto/LTOModule.h index 1794d81..0b64a90 100644 --- a/tools/lto/LTOModule.h +++ b/tools/lto/LTOModule.h @@ -52,7 +52,12 @@ struct LTOModule { static LTOModule* makeLTOModule(const char* path, std::string& errMsg); static LTOModule* makeLTOModule(int fd, const char *path, - off_t size, + 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); @@ -64,23 +69,27 @@ struct LTOModule { const char* getSymbolName(uint32_t index); llvm::Module * getLLVVMModule() { return _module.get(); } + const std::vector<const char*> &getAsmUndefinedRefs() { + return _asm_undefines; + } private: LTOModule(llvm::Module* m, llvm::TargetMachine* t); - void lazyParseSymbols(); + bool ParseSymbols(); void addDefinedSymbol(llvm::GlobalValue* def, llvm::Mangler& mangler, bool isFunction); 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); - void addAsmGlobalSymbol(const char *); + bool addAsmGlobalSymbols(llvm::MCContext &Context); + 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); @@ -103,11 +112,11 @@ private: llvm::OwningPtr<llvm::Module> _module; llvm::OwningPtr<llvm::TargetMachine> _target; - bool _symbolsParsed; 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; }; #endif // LTO_MODULE_H diff --git a/tools/lto/Makefile b/tools/lto/Makefile index 294c81b..46925e7 100644 --- a/tools/lto/Makefile +++ b/tools/lto/Makefile @@ -20,7 +20,8 @@ include $(LEVEL)/Makefile.config LINK_LIBS_IN_SHARED = 1 SHARED_LIBRARY = 1 -LINK_COMPONENTS := $(TARGETS_TO_BUILD) ipo scalaropts linker bitreader bitwriter +LINK_COMPONENTS := $(TARGETS_TO_BUILD) ipo scalaropts linker bitreader \ + bitwriter mcdisassembler include $(LEVEL)/Makefile.common diff --git a/tools/lto/lto.cpp b/tools/lto/lto.cpp index f48570c..dd658d1 100644 --- a/tools/lto/lto.cpp +++ b/tools/lto/lto.cpp @@ -95,12 +95,25 @@ lto_module_t lto_module_create(const char* path) // 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, off_t size) +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_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); +} + +// // loads an object file from memory // returns NULL on error (check lto_get_error_message() for details) // @@ -268,7 +281,7 @@ bool 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 +// 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. @@ -280,6 +293,12 @@ 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) +{ + return cg->compile_to_file(name, sLastErrorString); +} + // // Used to pass extra options to the code generator diff --git a/tools/lto/lto.exports b/tools/lto/lto.exports index a374091..b900bfb 100644 --- a/tools/lto/lto.exports +++ b/tools/lto/lto.exports @@ -2,6 +2,7 @@ lto_get_error_message lto_get_version lto_module_create lto_module_create_from_fd +lto_module_create_from_fd_at_offset lto_module_create_from_memory lto_module_get_num_symbols lto_module_get_symbol_attribute @@ -25,3 +26,7 @@ lto_codegen_debug_options lto_codegen_set_assembler_args lto_codegen_set_assembler_path lto_codegen_set_cpu +lto_codegen_compile_to_file +LLVMCreateDisasm +LLVMDisasmDispose +LLVMDisasmInstruction |