diff options
author | dim <dim@FreeBSD.org> | 2014-11-24 17:02:24 +0000 |
---|---|---|
committer | dim <dim@FreeBSD.org> | 2014-11-24 17:02:24 +0000 |
commit | 2c8643c6396b0a3db33430cf9380e70bbb9efce0 (patch) | |
tree | 4df130b28021d86e13bf4565ef58c1c5a5e093b4 /contrib/llvm/lib/LTO | |
parent | 678318cd20f7db4e6c6b85d83fe00fa327b04fca (diff) | |
parent | e27feadae0885aa074df58ebfda2e7a7f7a7d590 (diff) | |
download | FreeBSD-src-2c8643c6396b0a3db33430cf9380e70bbb9efce0.zip FreeBSD-src-2c8643c6396b0a3db33430cf9380e70bbb9efce0.tar.gz |
Merge llvm 3.5.0 release from ^/vendor/llvm/dist, resolve conflicts, and
preserve our customizations, where necessary.
Diffstat (limited to 'contrib/llvm/lib/LTO')
-rw-r--r-- | contrib/llvm/lib/LTO/LTOCodeGenerator.cpp | 179 | ||||
-rw-r--r-- | contrib/llvm/lib/LTO/LTOModule.cpp | 570 |
2 files changed, 311 insertions, 438 deletions
diff --git a/contrib/llvm/lib/LTO/LTOCodeGenerator.cpp b/contrib/llvm/lib/LTO/LTOCodeGenerator.cpp index 2b3648e..45a49e4 100644 --- a/contrib/llvm/lib/LTO/LTOCodeGenerator.cpp +++ b/contrib/llvm/lib/LTO/LTOCodeGenerator.cpp @@ -13,20 +13,23 @@ //===----------------------------------------------------------------------===// #include "llvm/LTO/LTOCodeGenerator.h" -#include "llvm/LTO/LTOModule.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Analysis/Passes.h" -#include "llvm/Analysis/Verifier.h" #include "llvm/Bitcode/ReaderWriter.h" #include "llvm/CodeGen/RuntimeLibcalls.h" #include "llvm/Config/config.h" #include "llvm/IR/Constants.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/DiagnosticInfo.h" +#include "llvm/IR/DiagnosticPrinter.h" #include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Mangler.h" #include "llvm/IR/Module.h" +#include "llvm/IR/Verifier.h" #include "llvm/InitializePasses.h" -#include "llvm/Linker.h" +#include "llvm/LTO/LTOModule.h" +#include "llvm/Linker/Linker.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/SubtargetFeature.h" @@ -40,15 +43,15 @@ #include "llvm/Support/TargetRegistry.h" #include "llvm/Support/TargetSelect.h" #include "llvm/Support/ToolOutputFile.h" -#include "llvm/Support/system_error.h" +#include "llvm/Support/raw_ostream.h" #include "llvm/Target/TargetLibraryInfo.h" #include "llvm/Target/TargetLowering.h" #include "llvm/Target/TargetOptions.h" #include "llvm/Target/TargetRegisterInfo.h" -#include "llvm/Target/Mangler.h" #include "llvm/Transforms/IPO.h" #include "llvm/Transforms/IPO/PassManagerBuilder.h" #include "llvm/Transforms/ObjCARC.h" +#include <system_error> using namespace llvm; const char* LTOCodeGenerator::getVersionString() { @@ -60,19 +63,20 @@ const char* LTOCodeGenerator::getVersionString() { } LTOCodeGenerator::LTOCodeGenerator() - : Context(getGlobalContext()), Linker(new Module("ld-temp.o", Context)), - TargetMach(NULL), EmitDwarfDebugInfo(false), ScopeRestrictionsDone(false), - CodeModel(LTO_CODEGEN_PIC_MODEL_DYNAMIC), NativeObjectFile(NULL) { + : Context(getGlobalContext()), IRLinker(new Module("ld-temp.o", Context)), + TargetMach(nullptr), EmitDwarfDebugInfo(false), + ScopeRestrictionsDone(false), CodeModel(LTO_CODEGEN_PIC_MODEL_DEFAULT), + NativeObjectFile(nullptr), DiagHandler(nullptr), DiagContext(nullptr) { initializeLTOPasses(); } LTOCodeGenerator::~LTOCodeGenerator() { delete TargetMach; delete NativeObjectFile; - TargetMach = NULL; - NativeObjectFile = NULL; + TargetMach = nullptr; + NativeObjectFile = nullptr; - Linker.deleteModule(); + IRLinker.deleteModule(); for (std::vector<char *>::iterator I = CodegenOptions.begin(), E = CodegenOptions.end(); @@ -82,8 +86,7 @@ LTOCodeGenerator::~LTOCodeGenerator() { // Initialize LTO passes. Please keep this funciton in sync with // PassManagerBuilder::populateLTOPassManager(), and make sure all LTO -// passes are initialized. -// +// passes are initialized. void LTOCodeGenerator::initializeLTOPasses() { PassRegistry &R = *PassRegistry::getPassRegistry(); @@ -104,6 +107,7 @@ void LTOCodeGenerator::initializeLTOPasses() { initializeFunctionAttrsPass(R); initializeGlobalsModRefPass(R); initializeLICMPass(R); + initializeMergedLoadStoreMotionPass(R); initializeGVNPass(R); initializeMemCpyOptPass(R); initializeDCEPass(R); @@ -111,7 +115,7 @@ void LTOCodeGenerator::initializeLTOPasses() { } bool LTOCodeGenerator::addModule(LTOModule* mod, std::string& errMsg) { - bool ret = Linker.linkInModule(mod->getLLVVMModule(), &errMsg); + bool ret = IRLinker.linkInModule(&mod->getModule(), &errMsg); const std::vector<const char*> &undefs = mod->getAsmUndefinedRefs(); for (int i = 0, e = undefs.size(); i != e; ++i) @@ -121,24 +125,7 @@ bool LTOCodeGenerator::addModule(LTOModule* mod, std::string& errMsg) { } void LTOCodeGenerator::setTargetOptions(TargetOptions options) { - Options.LessPreciseFPMADOption = options.LessPreciseFPMADOption; - Options.NoFramePointerElim = options.NoFramePointerElim; - Options.AllowFPOpFusion = options.AllowFPOpFusion; - Options.UnsafeFPMath = options.UnsafeFPMath; - Options.NoInfsFPMath = options.NoInfsFPMath; - Options.NoNaNsFPMath = options.NoNaNsFPMath; - Options.HonorSignDependentRoundingFPMathOption = - options.HonorSignDependentRoundingFPMathOption; - Options.UseSoftFloat = options.UseSoftFloat; - Options.FloatABIType = options.FloatABIType; - Options.NoZerosInBSS = options.NoZerosInBSS; - Options.GuaranteedTailCallOpt = options.GuaranteedTailCallOpt; - Options.DisableTailCalls = options.DisableTailCalls; - Options.StackAlignmentOverride = options.StackAlignmentOverride; - Options.TrapFuncName = options.TrapFuncName; - Options.PositionIndependentExecutable = options.PositionIndependentExecutable; - Options.EnableSegmentedStacks = options.EnableSegmentedStacks; - Options.UseInitArray = options.UseInitArray; + Options = options; } void LTOCodeGenerator::setDebugInfo(lto_debug_model debug) { @@ -159,6 +146,7 @@ void LTOCodeGenerator::setCodePICModel(lto_codegen_model model) { case LTO_CODEGEN_PIC_MODEL_STATIC: case LTO_CODEGEN_PIC_MODEL_DYNAMIC: case LTO_CODEGEN_PIC_MODEL_DYNAMIC_NO_PIC: + case LTO_CODEGEN_PIC_MODEL_DEFAULT: CodeModel = model; return; } @@ -175,7 +163,7 @@ bool LTOCodeGenerator::writeMergedModules(const char *path, // create output file std::string ErrInfo; - tool_output_file Out(path, ErrInfo, sys::fs::F_Binary); + tool_output_file Out(path, ErrInfo, sys::fs::F_None); if (!ErrInfo.empty()) { errMsg = "could not open bitcode file for writing: "; errMsg += path; @@ -183,7 +171,7 @@ bool LTOCodeGenerator::writeMergedModules(const char *path, } // write bitcode to it - WriteBitcodeToFile(Linker.getModule(), Out.os()); + WriteBitcodeToFile(IRLinker.getModule(), Out.os()); Out.os().close(); if (Out.os().has_error()) { @@ -197,7 +185,7 @@ bool LTOCodeGenerator::writeMergedModules(const char *path, return true; } -bool LTOCodeGenerator::compile_to_file(const char** name, +bool LTOCodeGenerator::compile_to_file(const char** name, bool disableOpt, bool disableInline, bool disableGVNLoadPRE, @@ -205,7 +193,8 @@ bool LTOCodeGenerator::compile_to_file(const char** name, // make unique temp .o file to put generated object file SmallString<128> Filename; int FD; - error_code EC = sys::fs::createTemporaryFile("lto-llvm", "o", FD, Filename); + std::error_code EC = + sys::fs::createTemporaryFile("lto-llvm", "o", FD, Filename); if (EC) { errMsg = EC.message(); return false; @@ -242,42 +231,43 @@ const void* LTOCodeGenerator::compile(size_t* length, const char *name; if (!compile_to_file(&name, disableOpt, disableInline, disableGVNLoadPRE, errMsg)) - return NULL; + return nullptr; // 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(); + ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrErr = + MemoryBuffer::getFile(name, -1, false); + if (std::error_code EC = BufferOrErr.getError()) { + errMsg = EC.message(); sys::fs::remove(NativeObjectPath); - return NULL; + return nullptr; } - NativeObjectFile = BuffPtr.take(); + NativeObjectFile = BufferOrErr.get().release(); // remove temp files sys::fs::remove(NativeObjectPath); // return buffer, unless error - if (NativeObjectFile == NULL) - return NULL; + if (!NativeObjectFile) + return nullptr; *length = NativeObjectFile->getBufferSize(); return NativeObjectFile->getBufferStart(); } bool LTOCodeGenerator::determineTarget(std::string &errMsg) { - if (TargetMach != NULL) + if (TargetMach) return true; - std::string TripleStr = Linker.getModule()->getTargetTriple(); + std::string TripleStr = IRLinker.getModule()->getTargetTriple(); if (TripleStr.empty()) TripleStr = sys::getDefaultTargetTriple(); llvm::Triple Triple(TripleStr); // create target machine from info for merged modules const Target *march = TargetRegistry::lookupTarget(TripleStr, errMsg); - if (march == NULL) + if (!march) return false; // The relocation model is actually a static member of TargetMachine and @@ -293,10 +283,14 @@ bool LTOCodeGenerator::determineTarget(std::string &errMsg) { case LTO_CODEGEN_PIC_MODEL_DYNAMIC_NO_PIC: RelocModel = Reloc::DynamicNoPIC; break; + case LTO_CODEGEN_PIC_MODEL_DEFAULT: + // RelocModel is already the default, so leave it that way. + break; } - // construct LTOModule, hand over ownership of module and target - SubtargetFeatures Features; + // Construct LTOModule, hand over ownership of module and target. Use MAttr as + // the default set of features. + SubtargetFeatures Features(MAttr); Features.getDefaultSubtargetFeatures(Triple); std::string FeatureStr = Features.getString(); // Set a default CPU for Darwin triples. @@ -305,6 +299,9 @@ bool LTOCodeGenerator::determineTarget(std::string &errMsg) { MCpu = "core2"; else if (Triple.getArch() == llvm::Triple::x86) MCpu = "yonah"; + else if (Triple.getArch() == llvm::Triple::arm64 || + Triple.getArch() == llvm::Triple::aarch64) + MCpu = "cyclone"; } TargetMach = march->createTargetMachine(TripleStr, MCpu, FeatureStr, Options, @@ -319,11 +316,17 @@ applyRestriction(GlobalValue &GV, std::vector<const char*> &MustPreserveList, SmallPtrSet<GlobalValue*, 8> &AsmUsed, Mangler &Mangler) { - SmallString<64> Buffer; - Mangler.getNameWithPrefix(Buffer, &GV, false); - + // There are no restrictions to apply to declarations. if (GV.isDeclaration()) return; + + // There is nothing more restrictive than private linkage. + if (GV.hasPrivateLinkage()) + return; + + SmallString<64> Buffer; + TargetMach->getNameWithPrefix(Buffer, &GV, Mangler); + if (MustPreserveSymbols.count(Buffer)) MustPreserveList.push_back(GV.getName().data()); if (AsmUndefinedRefs.count(Buffer)) @@ -341,7 +344,7 @@ applyRestriction(GlobalValue &GV, static void findUsedValues(GlobalVariable *LLVMUsed, SmallPtrSet<GlobalValue*, 8> &UsedValues) { - if (LLVMUsed == 0) return; + if (!LLVMUsed) return; ConstantArray *Inits = cast<ConstantArray>(LLVMUsed->getInitializer()); for (unsigned i = 0, e = Inits->getNumOperands(); i != e; ++i) @@ -380,14 +383,15 @@ static void accumulateAndSortLibcalls(std::vector<StringRef> &Libcalls, void LTOCodeGenerator::applyScopeRestrictions() { if (ScopeRestrictionsDone) return; - Module *mergedModule = Linker.getModule(); + Module *mergedModule = IRLinker.getModule(); // Start off with a verification pass. PassManager passes; passes.add(createVerifierPass()); + passes.add(createDebugInfoVerifierPass()); // mark which symbols can not be internalized - Mangler Mangler(TargetMach); + Mangler Mangler(TargetMach->getDataLayout()); std::vector<const char*> MustPreserveList; SmallPtrSet<GlobalValue*, 8> AsmUsed; std::vector<StringRef> Libcalls; @@ -413,9 +417,7 @@ void LTOCodeGenerator::applyScopeRestrictions() { if (!AsmUsed.empty()) { llvm::Type *i8PTy = llvm::Type::getInt8PtrTy(Context); std::vector<Constant*> asmUsed2; - for (SmallPtrSet<GlobalValue*, 16>::const_iterator i = AsmUsed.begin(), - e = AsmUsed.end(); i !=e; ++i) { - GlobalValue *GV = *i; + for (auto *GV : AsmUsed) { Constant *c = ConstantExpr::getBitCast(GV, i8PTy); asmUsed2.push_back(c); } @@ -447,7 +449,7 @@ bool LTOCodeGenerator::generateObjectFile(raw_ostream &out, if (!this->determineTarget(errMsg)) return false; - Module *mergedModule = Linker.getModule(); + Module *mergedModule = IRLinker.getModule(); // Mark which symbols can not be internalized this->applyScopeRestrictions(); @@ -457,9 +459,15 @@ bool LTOCodeGenerator::generateObjectFile(raw_ostream &out, // Start off with a verification pass. passes.add(createVerifierPass()); + passes.add(createDebugInfoVerifierPass()); // Add an appropriate DataLayout instance for this module... - passes.add(new DataLayout(*TargetMach->getDataLayout())); + mergedModule->setDataLayout(TargetMach->getDataLayout()); + passes.add(new DataLayoutPass(mergedModule)); + + // Add appropriate TargetLibraryInfo for this module. + passes.add(new TargetLibraryInfo(Triple(TargetMach->getTargetTriple()))); + TargetMach->addAnalysisPasses(passes); // Enabling internalize here would use its AllButMain variant. It @@ -473,11 +481,11 @@ bool LTOCodeGenerator::generateObjectFile(raw_ostream &out, // Make sure everything is still good. passes.add(createVerifierPass()); + passes.add(createDebugInfoVerifierPass()); PassManager codeGenPasses; - codeGenPasses.add(new DataLayout(*TargetMach->getDataLayout())); - TargetMach->addAnalysisPasses(codeGenPasses); + codeGenPasses.add(new DataLayoutPass(mergedModule)); formatted_raw_ostream Out(out); @@ -519,3 +527,50 @@ void LTOCodeGenerator::parseCodeGenDebugOptions() { cl::ParseCommandLineOptions(CodegenOptions.size(), const_cast<char **>(&CodegenOptions[0])); } + +void LTOCodeGenerator::DiagnosticHandler(const DiagnosticInfo &DI, + void *Context) { + ((LTOCodeGenerator *)Context)->DiagnosticHandler2(DI); +} + +void LTOCodeGenerator::DiagnosticHandler2(const DiagnosticInfo &DI) { + // Map the LLVM internal diagnostic severity to the LTO diagnostic severity. + lto_codegen_diagnostic_severity_t Severity; + switch (DI.getSeverity()) { + case DS_Error: + Severity = LTO_DS_ERROR; + break; + case DS_Warning: + Severity = LTO_DS_WARNING; + break; + case DS_Remark: + Severity = LTO_DS_REMARK; + break; + case DS_Note: + Severity = LTO_DS_NOTE; + break; + } + // Create the string that will be reported to the external diagnostic handler. + std::string MsgStorage; + raw_string_ostream Stream(MsgStorage); + DiagnosticPrinterRawOStream DP(Stream); + DI.print(DP); + Stream.flush(); + + // If this method has been called it means someone has set up an external + // diagnostic handler. Assert on that. + assert(DiagHandler && "Invalid diagnostic handler"); + (*DiagHandler)(Severity, MsgStorage.c_str(), DiagContext); +} + +void +LTOCodeGenerator::setDiagnosticHandler(lto_diagnostic_handler_t DiagHandler, + void *Ctxt) { + this->DiagHandler = DiagHandler; + this->DiagContext = Ctxt; + if (!DiagHandler) + return Context.setDiagnosticHandler(nullptr, nullptr); + // Register the LTOCodeGenerator stub in the LLVMContext to forward the + // diagnostic to the external DiagHandler. + Context.setDiagnosticHandler(LTOCodeGenerator::DiagnosticHandler, this); +} diff --git a/contrib/llvm/lib/LTO/LTOModule.cpp b/contrib/llvm/lib/LTO/LTOModule.cpp index 65416be..844c0f2 100644 --- a/contrib/llvm/lib/LTO/LTOModule.cpp +++ b/contrib/llvm/lib/LTO/LTOModule.cpp @@ -13,38 +13,39 @@ //===----------------------------------------------------------------------===// #include "llvm/LTO/LTOModule.h" -#include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/Triple.h" #include "llvm/Bitcode/ReaderWriter.h" #include "llvm/IR/Constants.h" #include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Metadata.h" #include "llvm/IR/Module.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCInst.h" #include "llvm/MC/MCInstrInfo.h" #include "llvm/MC/MCParser/MCAsmParser.h" -#include "llvm/MC/MCStreamer.h" +#include "llvm/MC/MCSection.h" #include "llvm/MC/MCSubtargetInfo.h" #include "llvm/MC/MCSymbol.h" #include "llvm/MC/MCTargetAsmParser.h" #include "llvm/MC/SubtargetFeature.h" #include "llvm/Support/CommandLine.h" -#include "llvm/Support/Host.h" #include "llvm/Support/FileSystem.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/Target/TargetLowering.h" +#include "llvm/Target/TargetLoweringObjectFile.h" #include "llvm/Target/TargetRegisterInfo.h" #include "llvm/Transforms/Utils/GlobalStatus.h" +#include <system_error> using namespace llvm; -LTOModule::LTOModule(llvm::Module *m, llvm::TargetMachine *t) - : _module(m), _target(t), - _context(_target->getMCAsmInfo(), _target->getRegisterInfo(), NULL), - _mangler(t) {} +LTOModule::LTOModule(std::unique_ptr<object::IRObjectFile> Obj, + llvm::TargetMachine *TM) + : IRFile(std::move(Obj)), _target(TM) {} /// isBitcodeFile - Returns 'true' if the file (or memory contents) is LLVM /// bitcode. @@ -60,85 +61,63 @@ bool LTOModule::isBitcodeFile(const char *path) { return type == sys::fs::file_magic::bitcode; } -/// 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); - if (!buffer) - return false; - return isTargetMatch(buffer, triplePrefix); -} - -bool LTOModule::isBitcodeFileForTarget(const char *path, - const char *triplePrefix) { - OwningPtr<MemoryBuffer> buffer; - if (MemoryBuffer::getFile(path, buffer)) - return false; - return isTargetMatch(buffer.take(), triplePrefix); -} - -/// isTargetMatch - Returns 'true' if the memory buffer is for the specified -/// target triple. -bool LTOModule::isTargetMatch(MemoryBuffer *buffer, const char *triplePrefix) { +bool LTOModule::isBitcodeForTarget(MemoryBuffer *buffer, + StringRef triplePrefix) { std::string Triple = getBitcodeTargetTriple(buffer, getGlobalContext()); - delete buffer; - return strncmp(Triple.c_str(), triplePrefix, strlen(triplePrefix)) == 0; + return StringRef(Triple).startswith(triplePrefix); } -/// makeLTOModule - Create an LTOModule. N.B. These methods take ownership of -/// the buffer. -LTOModule *LTOModule::makeLTOModule(const char *path, TargetOptions options, - std::string &errMsg) { - OwningPtr<MemoryBuffer> buffer; - if (error_code ec = MemoryBuffer::getFile(path, buffer)) { - errMsg = ec.message(); - return NULL; +LTOModule *LTOModule::createFromFile(const char *path, TargetOptions options, + std::string &errMsg) { + ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrErr = + MemoryBuffer::getFile(path); + if (std::error_code EC = BufferOrErr.getError()) { + errMsg = EC.message(); + return nullptr; } - return makeLTOModule(buffer.take(), options, errMsg); + return makeLTOModule(std::move(BufferOrErr.get()), options, errMsg); } -LTOModule *LTOModule::makeLTOModule(int fd, const char *path, - size_t size, TargetOptions options, - std::string &errMsg) { - return makeLTOModule(fd, path, size, 0, options, errMsg); +LTOModule *LTOModule::createFromOpenFile(int fd, const char *path, size_t size, + TargetOptions options, + std::string &errMsg) { + return createFromOpenFileSlice(fd, path, size, 0, options, errMsg); } -LTOModule *LTOModule::makeLTOModule(int fd, const char *path, - size_t map_size, - off_t offset, - TargetOptions options, - std::string &errMsg) { - OwningPtr<MemoryBuffer> buffer; - if (error_code ec = - MemoryBuffer::getOpenFileSlice(fd, path, buffer, map_size, offset)) { - errMsg = ec.message(); - return NULL; +LTOModule *LTOModule::createFromOpenFileSlice(int fd, const char *path, + size_t map_size, off_t offset, + TargetOptions options, + std::string &errMsg) { + ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrErr = + MemoryBuffer::getOpenFileSlice(fd, path, map_size, offset); + if (std::error_code EC = BufferOrErr.getError()) { + errMsg = EC.message(); + return nullptr; } - return makeLTOModule(buffer.take(), options, errMsg); + return makeLTOModule(std::move(BufferOrErr.get()), options, errMsg); } -LTOModule *LTOModule::makeLTOModule(const void *mem, size_t length, - TargetOptions options, - std::string &errMsg) { - OwningPtr<MemoryBuffer> buffer(makeBuffer(mem, length)); +LTOModule *LTOModule::createFromBuffer(const void *mem, size_t length, + TargetOptions options, + std::string &errMsg, StringRef path) { + std::unique_ptr<MemoryBuffer> buffer(makeBuffer(mem, length, path)); if (!buffer) - return NULL; - return makeLTOModule(buffer.take(), options, errMsg); + return nullptr; + return makeLTOModule(std::move(buffer), options, errMsg); } -LTOModule *LTOModule::makeLTOModule(MemoryBuffer *buffer, +LTOModule *LTOModule::makeLTOModule(std::unique_ptr<MemoryBuffer> Buffer, TargetOptions options, std::string &errMsg) { - // parse bitcode buffer - OwningPtr<Module> m(getLazyBitcodeModule(buffer, getGlobalContext(), - &errMsg)); - if (!m) { - delete buffer; - return NULL; + ErrorOr<Module *> MOrErr = + getLazyBitcodeModule(Buffer.get(), getGlobalContext()); + if (std::error_code EC = MOrErr.getError()) { + errMsg = EC.message(); + return nullptr; } + std::unique_ptr<Module> M(MOrErr.get()); - std::string TripleStr = m->getTargetTriple(); + std::string TripleStr = M->getTargetTriple(); if (TripleStr.empty()) TripleStr = sys::getDefaultTargetTriple(); llvm::Triple Triple(TripleStr); @@ -146,7 +125,7 @@ LTOModule *LTOModule::makeLTOModule(MemoryBuffer *buffer, // find machine architecture for this module const Target *march = TargetRegistry::lookupTarget(TripleStr, errMsg); if (!march) - return NULL; + return nullptr; // construct LTOModule, hand over ownership of module and target SubtargetFeatures Features; @@ -159,25 +138,36 @@ LTOModule *LTOModule::makeLTOModule(MemoryBuffer *buffer, CPU = "core2"; else if (Triple.getArch() == llvm::Triple::x86) CPU = "yonah"; + else if (Triple.getArch() == llvm::Triple::arm64 || + Triple.getArch() == llvm::Triple::aarch64) + CPU = "cyclone"; } TargetMachine *target = march->createTargetMachine(TripleStr, CPU, FeatureStr, options); - m->MaterializeAllPermanently(); + M->materializeAllPermanently(true); + M->setDataLayout(target->getDataLayout()); + + std::unique_ptr<object::IRObjectFile> IRObj( + new object::IRObjectFile(std::move(Buffer), std::move(M))); + + LTOModule *Ret = new LTOModule(std::move(IRObj), target); - LTOModule *Ret = new LTOModule(m.take(), target); if (Ret->parseSymbols(errMsg)) { delete Ret; - return NULL; + return nullptr; } + Ret->parseMetadata(); + return Ret; } -/// makeBuffer - Create a MemoryBuffer from a memory range. -MemoryBuffer *LTOModule::makeBuffer(const void *mem, size_t length) { +/// Create a MemoryBuffer from a memory range with an optional name. +MemoryBuffer *LTOModule::makeBuffer(const void *mem, size_t length, + StringRef name) { const char *startPtr = (const char*)mem; - return MemoryBuffer::getMemBuffer(StringRef(startPtr, length), "", false); + return MemoryBuffer::getMemBuffer(StringRef(startPtr, length), name, false); } /// objcClassNameFromExpression - Get string that the data pointer points to. @@ -280,10 +270,20 @@ void LTOModule::addObjCClassRef(const GlobalVariable *clgv) { entry.setValue(info); } -/// addDefinedDataSymbol - Add a data symbol as defined to the list. -void LTOModule::addDefinedDataSymbol(const GlobalValue *v) { +void LTOModule::addDefinedDataSymbol(const object::BasicSymbolRef &Sym) { + SmallString<64> Buffer; + { + raw_svector_ostream OS(Buffer); + Sym.printName(OS); + } + + const GlobalValue *V = IRFile->getSymbolGV(Sym.getRawDataRefImpl()); + addDefinedDataSymbol(Buffer.c_str(), V); +} + +void LTOModule::addDefinedDataSymbol(const char *Name, const GlobalValue *v) { // Add to list of defined symbols. - addDefinedSymbol(v, false); + addDefinedSymbol(Name, v, false); if (!v->hasSection() /* || !isTargetDarwin */) return; @@ -309,34 +309,47 @@ void LTOModule::addDefinedDataSymbol(const GlobalValue *v) { // from the ObjC data structures generated by the front end. // special case if this data blob is an ObjC class definition - if (v->getSection().compare(0, 15, "__OBJC,__class,") == 0) { + std::string Section = v->getSection(); + if (Section.compare(0, 15, "__OBJC,__class,") == 0) { if (const GlobalVariable *gv = dyn_cast<GlobalVariable>(v)) { addObjCClass(gv); } } // special case if this data blob is an ObjC category definition - else if (v->getSection().compare(0, 18, "__OBJC,__category,") == 0) { + else if (Section.compare(0, 18, "__OBJC,__category,") == 0) { if (const GlobalVariable *gv = dyn_cast<GlobalVariable>(v)) { addObjCCategory(gv); } } // special case if this data blob is the list of referenced classes - else if (v->getSection().compare(0, 18, "__OBJC,__cls_refs,") == 0) { + else if (Section.compare(0, 18, "__OBJC,__cls_refs,") == 0) { if (const GlobalVariable *gv = dyn_cast<GlobalVariable>(v)) { addObjCClassRef(gv); } } } -/// addDefinedFunctionSymbol - Add a function symbol as defined to the list. -void LTOModule::addDefinedFunctionSymbol(const Function *f) { +void LTOModule::addDefinedFunctionSymbol(const object::BasicSymbolRef &Sym) { + SmallString<64> Buffer; + { + raw_svector_ostream OS(Buffer); + Sym.printName(OS); + } + + const Function *F = + cast<Function>(IRFile->getSymbolGV(Sym.getRawDataRefImpl())); + addDefinedFunctionSymbol(Buffer.c_str(), F); +} + +void LTOModule::addDefinedFunctionSymbol(const char *Name, const Function *F) { // add to list of defined symbols - addDefinedSymbol(f, true); + addDefinedSymbol(Name, F, true); } static bool canBeHidden(const GlobalValue *GV) { + // FIXME: this is duplicated with another static function in AsmPrinter.cpp GlobalValue::LinkageTypes L = GV->getLinkage(); if (L != GlobalValue::LinkOnceODRLinkage) @@ -345,6 +358,13 @@ static bool canBeHidden(const GlobalValue *GV) { if (GV->hasUnnamedAddr()) return true; + // If it is a non constant variable, it needs to be uniqued across shared + // objects. + if (const GlobalVariable *Var = dyn_cast<GlobalVariable>(GV)) { + if (!Var->isConstant()) + return false; + } + GlobalStatus GS; if (GlobalStatus::analyzeGlobal(GV, GS)) return false; @@ -352,19 +372,11 @@ static bool canBeHidden(const GlobalValue *GV) { return !GS.IsCompared; } -/// addDefinedSymbol - Add a defined symbol to the list. -void LTOModule::addDefinedSymbol(const 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); - +void LTOModule::addDefinedSymbol(const char *Name, const GlobalValue *def, + bool isFunction) { // set alignment part log2() can have rounding errors uint32_t align = def->getAlignment(); - uint32_t attr = align ? countTrailingZeros(def->getAlignment()) : 0; + uint32_t attr = align ? countTrailingZeros(align) : 0; // set permissions part if (isFunction) { @@ -378,8 +390,7 @@ void LTOModule::addDefinedSymbol(const GlobalValue *def, bool isFunction) { } // set definition part - if (def->hasWeakLinkage() || def->hasLinkOnceLinkage() || - def->hasLinkerPrivateWeakLinkage()) + if (def->hasWeakLinkage() || def->hasLinkOnceLinkage()) attr |= LTO_SYMBOL_DEFINITION_WEAK; else if (def->hasCommonLinkage()) attr |= LTO_SYMBOL_DEFINITION_TENTATIVE; @@ -387,27 +398,26 @@ void LTOModule::addDefinedSymbol(const GlobalValue *def, bool isFunction) { attr |= LTO_SYMBOL_DEFINITION_REGULAR; // set scope part - if (def->hasHiddenVisibility()) + if (def->hasLocalLinkage()) + // Ignore visibility if linkage is local. + attr |= LTO_SYMBOL_SCOPE_INTERNAL; + else if (def->hasHiddenVisibility()) attr |= LTO_SYMBOL_SCOPE_HIDDEN; else if (def->hasProtectedVisibility()) attr |= LTO_SYMBOL_SCOPE_PROTECTED; else if (canBeHidden(def)) attr |= LTO_SYMBOL_SCOPE_DEFAULT_CAN_BE_HIDDEN; - else if (def->hasExternalLinkage() || def->hasWeakLinkage() || - def->hasLinkOnceLinkage() || def->hasCommonLinkage() || - def->hasLinkerPrivateWeakLinkage()) - attr |= LTO_SYMBOL_SCOPE_DEFAULT; else - attr |= LTO_SYMBOL_SCOPE_INTERNAL; + attr |= LTO_SYMBOL_SCOPE_DEFAULT; - StringSet::value_type &entry = _defines.GetOrCreateValue(Buffer); + StringSet::value_type &entry = _defines.GetOrCreateValue(Name); entry.setValue(1); // fill information structure NameAndAttributes info; - StringRef Name = entry.getKey(); - info.name = Name.data(); - assert(info.name[Name.size()] == '\0'); + StringRef NameRef = entry.getKey(); + info.name = NameRef.data(); + assert(info.name[NameRef.size()] == '\0'); info.attributes = attr; info.isFunction = isFunction; info.symbol = def; @@ -430,7 +440,7 @@ void LTOModule::addAsmGlobalSymbol(const char *name, NameAndAttributes &info = _undefines[entry.getKey().data()]; - if (info.symbol == 0) { + if (info.symbol == nullptr) { // FIXME: This is trying to take care of module ASM like this: // // module asm ".zerofill __FOO, __foo, _bar_baz_qux, 0" @@ -444,7 +454,7 @@ void LTOModule::addAsmGlobalSymbol(const char *name, info.attributes = LTO_SYMBOL_PERMISSIONS_DATA | LTO_SYMBOL_DEFINITION_REGULAR | scope; info.isFunction = false; - info.symbol = 0; + info.symbol = nullptr; // add to table of symbols _symbols.push_back(info); @@ -452,9 +462,9 @@ void LTOModule::addAsmGlobalSymbol(const char *name, } if (info.isFunction) - addDefinedFunctionSymbol(cast<Function>(info.symbol)); + addDefinedFunctionSymbol(info.name, cast<Function>(info.symbol)); else - addDefinedDataSymbol(info.symbol); + addDefinedDataSymbol(info.name, info.symbol); _symbols.back().attributes &= ~LTO_SYMBOL_SCOPE_MASK; _symbols.back().attributes |= scope; @@ -472,31 +482,25 @@ void LTOModule::addAsmGlobalSymbolUndef(const char *name) { if (entry.getValue().name) return; - uint32_t attr = LTO_SYMBOL_DEFINITION_UNDEFINED;; + uint32_t attr = LTO_SYMBOL_DEFINITION_UNDEFINED; attr |= LTO_SYMBOL_SCOPE_DEFAULT; NameAndAttributes info; info.name = entry.getKey().data(); info.attributes = attr; info.isFunction = false; - info.symbol = 0; + info.symbol = nullptr; entry.setValue(info); } -/// addPotentialUndefinedSymbol - Add a symbol which isn't defined just yet to a -/// list to be resolved later. -void -LTOModule::addPotentialUndefinedSymbol(const GlobalValue *decl, bool isFunc) { - // ignore all llvm.* symbols - if (decl->getName().startswith("llvm.")) - return; - - // ignore all aliases - if (isa<GlobalAlias>(decl)) - return; - +/// Add a symbol which isn't defined just yet to a list to be resolved later. +void LTOModule::addPotentialUndefinedSymbol(const object::BasicSymbolRef &Sym, + bool isFunc) { SmallString<64> name; - _mangler.getNameWithPrefix(name, decl, false); + { + raw_svector_ostream OS(name); + Sym.printName(OS); + } StringMap<NameAndAttributes>::value_type &entry = _undefines.GetOrCreateValue(name); @@ -509,6 +513,8 @@ LTOModule::addPotentialUndefinedSymbol(const GlobalValue *decl, bool isFunc) { info.name = entry.getKey().data(); + const GlobalValue *decl = IRFile->getSymbolGV(Sym.getRawDataRefImpl()); + if (decl->hasExternalWeakLinkage()) info.attributes = LTO_SYMBOL_DEFINITION_WEAKUNDEF; else @@ -520,264 +526,52 @@ LTOModule::addPotentialUndefinedSymbol(const GlobalValue *decl, bool isFunc) { entry.setValue(info); } -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; - - case MCExpr::Unary: - AddValueSymbols(cast<MCUnaryExpr>(Value)->getSubExpr()); - break; +/// 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) { + for (auto &Sym : IRFile->symbols()) { + const GlobalValue *GV = IRFile->getSymbolGV(Sym.getRawDataRefImpl()); + uint32_t Flags = Sym.getFlags(); + if (Flags & object::BasicSymbolRef::SF_FormatSpecific) + continue; + + bool IsUndefined = Flags & object::BasicSymbolRef::SF_Undefined; + + if (!GV) { + SmallString<64> Buffer; + { + raw_svector_ostream OS(Buffer); + Sym.printName(OS); } + const char *Name = Buffer.c_str(); + + if (IsUndefined) + addAsmGlobalSymbolUndef(Name); + else if (Flags & object::BasicSymbolRef::SF_Global) + addAsmGlobalSymbol(Name, LTO_SYMBOL_SCOPE_DEFAULT); + else + addAsmGlobalSymbol(Name, LTO_SYMBOL_SCOPE_INTERNAL); + continue; } - public: - typedef StringMap<State>::const_iterator const_iterator; - - const_iterator begin() { - return Symbols.begin(); + auto *F = dyn_cast<Function>(GV); + if (IsUndefined) { + addPotentialUndefinedSymbol(Sym, F != nullptr); + continue; } - const_iterator end() { - return Symbols.end(); - } - - RecordStreamer(MCContext &Context) : MCStreamer(Context, 0) {} - - 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().first); - markDefined(*Symbol); - } - virtual void EmitDebugLabel(MCSymbol *Symbol) { - EmitLabel(Symbol); - } - virtual void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) { - // FIXME: should we handle aliases? - markDefined(*Symbol); - } - virtual bool EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) { - if (Attribute == MCSA_Global) - markGlobal(*Symbol); - return true; - } - virtual void EmitZerofill(const MCSection *Section, MCSymbol *Symbol, - uint64_t Size , unsigned ByteAlignment) { - markDefined(*Symbol); - } - virtual void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, - unsigned ByteAlignment) { - markDefined(*Symbol); + if (F) { + addDefinedFunctionSymbol(Sym); + continue; } - virtual void EmitBundleAlignMode(unsigned AlignPow2) {} - virtual void EmitBundleLock(bool AlignToEnd) {} - virtual void EmitBundleUnlock() {} - - // Noop calls. - virtual void ChangeSection(const MCSection *Section, - const MCExpr *Subsection) {} - virtual void InitToTextSection() {} - 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) {} - virtual void EmitTBSSSymbol(const MCSection *Section, MCSymbol *Symbol, - uint64_t Size, unsigned ByteAlignment) {} - virtual void EmitBytes(StringRef Data) {} - virtual void EmitValueImpl(const MCExpr *Value, unsigned Size) {} - 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 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 FinishImpl() {} - virtual void EmitCFIEndProcImpl(MCDwarfFrameInfo &Frame) { - RecordProcEnd(Frame); + if (isa<GlobalVariable>(GV)) { + addDefinedDataSymbol(Sym); + continue; } - }; -} // end anonymous namespace - -/// 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)); - MemoryBuffer *Buffer = MemoryBuffer::getMemBuffer(inlineAsm); - SourceMgr SrcMgr; - SrcMgr.AddNewSourceBuffer(Buffer, SMLoc()); - OwningPtr<MCAsmParser> Parser(createMCAsmParser(SrcMgr, - _context, *Streamer, - *_target->getMCAsmInfo())); - const Target &T = _target->getTarget(); - OwningPtr<MCInstrInfo> MCII(T.createMCInstrInfo()); - OwningPtr<MCSubtargetInfo> - STI(T.createMCSubtargetInfo(_target->getTargetTriple(), - _target->getTargetCPU(), - _target->getTargetFeatureString())); - OwningPtr<MCTargetAsmParser> TAP(T.createMCAsmParser(*STI, *Parser.get(), *MCII)); - if (!TAP) { - errMsg = "target " + std::string(T.getName()) + - " does not define AsmParser."; - return true; - } - - Parser->setTargetParser(*TAP); - if (Parser->Run(false)) - 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; -} - -/// isDeclaration - Return 'true' if the global value is a declaration. -static bool isDeclaration(const GlobalValue &V) { - if (V.hasAvailableExternallyLinkage()) - return true; - - if (V.isMaterializable()) - return false; - - return V.isDeclaration(); -} - -/// 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(), e = _module->end(); f != e; ++f) { - if (isDeclaration(*f)) - addPotentialUndefinedSymbol(f, true); - else - addDefinedFunctionSymbol(f); - } - - // add data - for (Module::global_iterator v = _module->global_begin(), - e = _module->global_end(); v != e; ++v) { - if (isDeclaration(*v)) - addPotentialUndefinedSymbol(v, false); - else - addDefinedDataSymbol(v); - } - - // add asm globals - if (addAsmGlobalSymbols(errMsg)) - return true; - - // add aliases - 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(a); + assert(isa<GlobalAlias>(GV)); + addDefinedDataSymbol(Sym); } // make symbols for all undefines @@ -792,3 +586,27 @@ bool LTOModule::parseSymbols(std::string &errMsg) { return false; } + +/// parseMetadata - Parse metadata from the module +void LTOModule::parseMetadata() { + // Linker Options + if (Value *Val = getModule().getModuleFlag("Linker Options")) { + MDNode *LinkerOptions = cast<MDNode>(Val); + for (unsigned i = 0, e = LinkerOptions->getNumOperands(); i != e; ++i) { + MDNode *MDOptions = cast<MDNode>(LinkerOptions->getOperand(i)); + for (unsigned ii = 0, ie = MDOptions->getNumOperands(); ii != ie; ++ii) { + MDString *MDOption = cast<MDString>(MDOptions->getOperand(ii)); + StringRef Op = _linkeropt_strings. + GetOrCreateValue(MDOption->getString()).getKey(); + StringRef DepLibName = _target->getTargetLowering()-> + getObjFileLowering().getDepLibFromLinkerOpt(Op); + if (!DepLibName.empty()) + _deplibs.push_back(DepLibName.data()); + else if (!Op.empty()) + _linkeropts.push_back(Op.data()); + } + } + } + + // Add other interesting metadata here. +} |