LCOV - code coverage report
Current view: top level - lib/LTO - LTOModule.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 156 244 63.9 %
Date: 2018-10-20 13:21:21 Functions: 16 29 55.2 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //===-- LTOModule.cpp - LLVM Link Time Optimizer --------------------------===//
       2             : //
       3             : //                     The LLVM Compiler Infrastructure
       4             : //
       5             : // This file is distributed under the University of Illinois Open Source
       6             : // License. See LICENSE.TXT for details.
       7             : //
       8             : //===----------------------------------------------------------------------===//
       9             : //
      10             : // This file implements the Link Time Optimization library. This library is
      11             : // intended to be used by linker to optimize code at link time.
      12             : //
      13             : //===----------------------------------------------------------------------===//
      14             : 
      15             : #include "llvm/LTO/legacy/LTOModule.h"
      16             : #include "llvm/ADT/Triple.h"
      17             : #include "llvm/Bitcode/BitcodeReader.h"
      18             : #include "llvm/CodeGen/TargetSubtargetInfo.h"
      19             : #include "llvm/IR/Constants.h"
      20             : #include "llvm/IR/LLVMContext.h"
      21             : #include "llvm/IR/Mangler.h"
      22             : #include "llvm/IR/Metadata.h"
      23             : #include "llvm/IR/Module.h"
      24             : #include "llvm/MC/MCExpr.h"
      25             : #include "llvm/MC/MCInst.h"
      26             : #include "llvm/MC/MCParser/MCAsmParser.h"
      27             : #include "llvm/MC/MCSection.h"
      28             : #include "llvm/MC/MCSubtargetInfo.h"
      29             : #include "llvm/MC/MCSymbol.h"
      30             : #include "llvm/MC/SubtargetFeature.h"
      31             : #include "llvm/Object/IRObjectFile.h"
      32             : #include "llvm/Object/ObjectFile.h"
      33             : #include "llvm/Support/FileSystem.h"
      34             : #include "llvm/Support/Host.h"
      35             : #include "llvm/Support/MemoryBuffer.h"
      36             : #include "llvm/Support/Path.h"
      37             : #include "llvm/Support/SourceMgr.h"
      38             : #include "llvm/Support/TargetRegistry.h"
      39             : #include "llvm/Support/TargetSelect.h"
      40             : #include "llvm/Target/TargetLoweringObjectFile.h"
      41             : #include "llvm/Transforms/Utils/GlobalStatus.h"
      42             : #include <system_error>
      43             : using namespace llvm;
      44             : using namespace llvm::object;
      45             : 
      46          50 : LTOModule::LTOModule(std::unique_ptr<Module> M, MemoryBufferRef MBRef,
      47          50 :                      llvm::TargetMachine *TM)
      48          50 :     : Mod(std::move(M)), MBRef(MBRef), _target(TM) {
      49          50 :   SymTab.addModule(Mod.get());
      50          50 : }
      51             : 
      52         148 : LTOModule::~LTOModule() {}
      53             : 
      54             : /// isBitcodeFile - Returns 'true' if the file (or memory contents) is LLVM
      55             : /// bitcode.
      56           0 : bool LTOModule::isBitcodeFile(const void *Mem, size_t Length) {
      57             :   Expected<MemoryBufferRef> BCData = IRObjectFile::findBitcodeInMemBuffer(
      58           0 :       MemoryBufferRef(StringRef((const char *)Mem, Length), "<mem>"));
      59           0 :   return !errorToBool(BCData.takeError());
      60             : }
      61             : 
      62           0 : bool LTOModule::isBitcodeFile(StringRef Path) {
      63             :   ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrErr =
      64           0 :       MemoryBuffer::getFile(Path);
      65           0 :   if (!BufferOrErr)
      66             :     return false;
      67             : 
      68             :   Expected<MemoryBufferRef> BCData = IRObjectFile::findBitcodeInMemBuffer(
      69           0 :       BufferOrErr.get()->getMemBufferRef());
      70           0 :   return !errorToBool(BCData.takeError());
      71             : }
      72             : 
      73           0 : bool LTOModule::isThinLTO() {
      74           0 :   Expected<BitcodeLTOInfo> Result = getBitcodeLTOInfo(MBRef);
      75           0 :   if (!Result) {
      76           0 :     logAllUnhandledErrors(Result.takeError(), errs(), "");
      77           0 :     return false;
      78             :   }
      79           0 :   return Result->IsThinLTO;
      80             : }
      81             : 
      82           0 : bool LTOModule::isBitcodeForTarget(MemoryBuffer *Buffer,
      83             :                                    StringRef TriplePrefix) {
      84             :   Expected<MemoryBufferRef> BCOrErr =
      85           0 :       IRObjectFile::findBitcodeInMemBuffer(Buffer->getMemBufferRef());
      86           0 :   if (errorToBool(BCOrErr.takeError()))
      87             :     return false;
      88           0 :   LLVMContext Context;
      89             :   ErrorOr<std::string> TripleOrErr =
      90           0 :       expectedToErrorOrAndEmitErrors(Context, getBitcodeTargetTriple(*BCOrErr));
      91           0 :   if (!TripleOrErr)
      92             :     return false;
      93             :   return StringRef(*TripleOrErr).startswith(TriplePrefix);
      94             : }
      95             : 
      96           0 : std::string LTOModule::getProducerString(MemoryBuffer *Buffer) {
      97             :   Expected<MemoryBufferRef> BCOrErr =
      98           0 :       IRObjectFile::findBitcodeInMemBuffer(Buffer->getMemBufferRef());
      99           0 :   if (errorToBool(BCOrErr.takeError()))
     100           0 :     return "";
     101           0 :   LLVMContext Context;
     102             :   ErrorOr<std::string> ProducerOrErr = expectedToErrorOrAndEmitErrors(
     103           0 :       Context, getBitcodeProducerString(*BCOrErr));
     104           0 :   if (!ProducerOrErr)
     105           0 :     return "";
     106             :   return *ProducerOrErr;
     107             : }
     108             : 
     109             : ErrorOr<std::unique_ptr<LTOModule>>
     110          49 : LTOModule::createFromFile(LLVMContext &Context, StringRef path,
     111             :                           const TargetOptions &options) {
     112             :   ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrErr =
     113          49 :       MemoryBuffer::getFile(path);
     114          49 :   if (std::error_code EC = BufferOrErr.getError()) {
     115           1 :     Context.emitError(EC.message());
     116             :     return EC;
     117             :   }
     118             :   std::unique_ptr<MemoryBuffer> Buffer = std::move(BufferOrErr.get());
     119             :   return makeLTOModule(Buffer->getMemBufferRef(), options, Context,
     120          48 :                        /* ShouldBeLazy*/ false);
     121             : }
     122             : 
     123             : ErrorOr<std::unique_ptr<LTOModule>>
     124           0 : LTOModule::createFromOpenFile(LLVMContext &Context, int fd, StringRef path,
     125             :                               size_t size, const TargetOptions &options) {
     126           0 :   return createFromOpenFileSlice(Context, fd, path, size, 0, options);
     127             : }
     128             : 
     129             : ErrorOr<std::unique_ptr<LTOModule>>
     130           0 : LTOModule::createFromOpenFileSlice(LLVMContext &Context, int fd, StringRef path,
     131             :                                    size_t map_size, off_t offset,
     132             :                                    const TargetOptions &options) {
     133             :   ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrErr =
     134           0 :       MemoryBuffer::getOpenFileSlice(fd, path, map_size, offset);
     135           0 :   if (std::error_code EC = BufferOrErr.getError()) {
     136           0 :     Context.emitError(EC.message());
     137             :     return EC;
     138             :   }
     139             :   std::unique_ptr<MemoryBuffer> Buffer = std::move(BufferOrErr.get());
     140             :   return makeLTOModule(Buffer->getMemBufferRef(), options, Context,
     141           0 :                        /* ShouldBeLazy */ false);
     142             : }
     143             : 
     144             : ErrorOr<std::unique_ptr<LTOModule>>
     145           0 : LTOModule::createFromBuffer(LLVMContext &Context, const void *mem,
     146             :                             size_t length, const TargetOptions &options,
     147             :                             StringRef path) {
     148             :   StringRef Data((const char *)mem, length);
     149             :   MemoryBufferRef Buffer(Data, path);
     150           0 :   return makeLTOModule(Buffer, options, Context, /* ShouldBeLazy */ false);
     151             : }
     152             : 
     153             : ErrorOr<std::unique_ptr<LTOModule>>
     154           4 : LTOModule::createInLocalContext(std::unique_ptr<LLVMContext> Context,
     155             :                                 const void *mem, size_t length,
     156             :                                 const TargetOptions &options, StringRef path) {
     157             :   StringRef Data((const char *)mem, length);
     158             :   MemoryBufferRef Buffer(Data, path);
     159             :   // If we own a context, we know this is being used only for symbol extraction,
     160             :   // not linking.  Be lazy in that case.
     161             :   ErrorOr<std::unique_ptr<LTOModule>> Ret =
     162           4 :       makeLTOModule(Buffer, options, *Context, /* ShouldBeLazy */ true);
     163           3 :   if (Ret)
     164           3 :     (*Ret)->OwnedContext = std::move(Context);
     165           3 :   return Ret;
     166             : }
     167             : 
     168             : static ErrorOr<std::unique_ptr<Module>>
     169          52 : parseBitcodeFileImpl(MemoryBufferRef Buffer, LLVMContext &Context,
     170             :                      bool ShouldBeLazy) {
     171             :   // Find the buffer.
     172             :   Expected<MemoryBufferRef> MBOrErr =
     173          52 :       IRObjectFile::findBitcodeInMemBuffer(Buffer);
     174          52 :   if (Error E = MBOrErr.takeError()) {
     175           1 :     std::error_code EC = errorToErrorCode(std::move(E));
     176           1 :     Context.emitError(EC.message());
     177             :     return EC;
     178             :   }
     179             : 
     180          51 :   if (!ShouldBeLazy) {
     181             :     // Parse the full file.
     182             :     return expectedToErrorOrAndEmitErrors(Context,
     183          48 :                                           parseBitcodeFile(*MBOrErr, Context));
     184             :   }
     185             : 
     186             :   // Parse lazily.
     187             :   return expectedToErrorOrAndEmitErrors(
     188             :       Context,
     189           3 :       getLazyBitcodeModule(*MBOrErr, Context, true /*ShouldLazyLoadMetadata*/));
     190             : }
     191             : 
     192             : ErrorOr<std::unique_ptr<LTOModule>>
     193          52 : LTOModule::makeLTOModule(MemoryBufferRef Buffer, const TargetOptions &options,
     194             :                          LLVMContext &Context, bool ShouldBeLazy) {
     195             :   ErrorOr<std::unique_ptr<Module>> MOrErr =
     196          52 :       parseBitcodeFileImpl(Buffer, Context, ShouldBeLazy);
     197          50 :   if (std::error_code EC = MOrErr.getError())
     198             :     return EC;
     199             :   std::unique_ptr<Module> &M = *MOrErr;
     200             : 
     201             :   std::string TripleStr = M->getTargetTriple();
     202          50 :   if (TripleStr.empty())
     203          14 :     TripleStr = sys::getDefaultTargetTriple();
     204          50 :   llvm::Triple Triple(TripleStr);
     205             : 
     206             :   // find machine architecture for this module
     207             :   std::string errMsg;
     208          50 :   const Target *march = TargetRegistry::lookupTarget(TripleStr, errMsg);
     209          50 :   if (!march)
     210           0 :     return make_error_code(object::object_error::arch_not_found);
     211             : 
     212             :   // construct LTOModule, hand over ownership of module and target
     213          50 :   SubtargetFeatures Features;
     214          50 :   Features.getDefaultSubtargetFeatures(Triple);
     215          50 :   std::string FeatureStr = Features.getString();
     216             :   // Set a default CPU for Darwin triples.
     217             :   std::string CPU;
     218             :   if (Triple.isOSDarwin()) {
     219          17 :     if (Triple.getArch() == llvm::Triple::x86_64)
     220             :       CPU = "core2";
     221           1 :     else if (Triple.getArch() == llvm::Triple::x86)
     222             :       CPU = "yonah";
     223           1 :     else if (Triple.getArch() == llvm::Triple::aarch64)
     224             :       CPU = "cyclone";
     225             :   }
     226             : 
     227             :   TargetMachine *target =
     228          50 :       march->createTargetMachine(TripleStr, CPU, FeatureStr, options, None);
     229             : 
     230         100 :   std::unique_ptr<LTOModule> Ret(new LTOModule(std::move(M), Buffer, target));
     231          50 :   Ret->parseSymbols();
     232          50 :   Ret->parseMetadata();
     233             : 
     234             :   return std::move(Ret);
     235             : }
     236             : 
     237             : /// Create a MemoryBuffer from a memory range with an optional name.
     238             : std::unique_ptr<MemoryBuffer>
     239           0 : LTOModule::makeBuffer(const void *mem, size_t length, StringRef name) {
     240             :   const char *startPtr = (const char*)mem;
     241           0 :   return MemoryBuffer::getMemBuffer(StringRef(startPtr, length), name, false);
     242             : }
     243             : 
     244             : /// objcClassNameFromExpression - Get string that the data pointer points to.
     245             : bool
     246           0 : LTOModule::objcClassNameFromExpression(const Constant *c, std::string &name) {
     247             :   if (const ConstantExpr *ce = dyn_cast<ConstantExpr>(c)) {
     248             :     Constant *op = ce->getOperand(0);
     249             :     if (GlobalVariable *gvn = dyn_cast<GlobalVariable>(op)) {
     250             :       Constant *cn = gvn->getInitializer();
     251             :       if (ConstantDataArray *ca = dyn_cast<ConstantDataArray>(cn)) {
     252           0 :         if (ca->isCString()) {
     253           0 :           name = (".objc_class_name_" + ca->getAsCString()).str();
     254           0 :           return true;
     255             :         }
     256             :       }
     257             :     }
     258             :   }
     259             :   return false;
     260             : }
     261             : 
     262             : /// addObjCClass - Parse i386/ppc ObjC class data structure.
     263           0 : void LTOModule::addObjCClass(const GlobalVariable *clgv) {
     264             :   const ConstantStruct *c = dyn_cast<ConstantStruct>(clgv->getInitializer());
     265           0 :   if (!c) return;
     266             : 
     267             :   // second slot in __OBJC,__class is pointer to superclass name
     268             :   std::string superclassName;
     269           0 :   if (objcClassNameFromExpression(c->getOperand(1), superclassName)) {
     270             :     auto IterBool =
     271           0 :         _undefines.insert(std::make_pair(superclassName, NameAndAttributes()));
     272           0 :     if (IterBool.second) {
     273             :       NameAndAttributes &info = IterBool.first->second;
     274           0 :       info.name = IterBool.first->first();
     275           0 :       info.attributes = LTO_SYMBOL_DEFINITION_UNDEFINED;
     276           0 :       info.isFunction = false;
     277           0 :       info.symbol = clgv;
     278             :     }
     279             :   }
     280             : 
     281             :   // third slot in __OBJC,__class is pointer to class name
     282             :   std::string className;
     283           0 :   if (objcClassNameFromExpression(c->getOperand(2), className)) {
     284             :     auto Iter = _defines.insert(className).first;
     285             : 
     286           0 :     NameAndAttributes info;
     287           0 :     info.name = Iter->first();
     288           0 :     info.attributes = LTO_SYMBOL_PERMISSIONS_DATA |
     289             :       LTO_SYMBOL_DEFINITION_REGULAR | LTO_SYMBOL_SCOPE_DEFAULT;
     290             :     info.isFunction = false;
     291           0 :     info.symbol = clgv;
     292           0 :     _symbols.push_back(info);
     293             :   }
     294             : }
     295             : 
     296             : /// addObjCCategory - Parse i386/ppc ObjC category data structure.
     297           0 : void LTOModule::addObjCCategory(const GlobalVariable *clgv) {
     298             :   const ConstantStruct *c = dyn_cast<ConstantStruct>(clgv->getInitializer());
     299           0 :   if (!c) return;
     300             : 
     301             :   // second slot in __OBJC,__category is pointer to target class name
     302             :   std::string targetclassName;
     303           0 :   if (!objcClassNameFromExpression(c->getOperand(1), targetclassName))
     304             :     return;
     305             : 
     306             :   auto IterBool =
     307           0 :       _undefines.insert(std::make_pair(targetclassName, NameAndAttributes()));
     308             : 
     309           0 :   if (!IterBool.second)
     310             :     return;
     311             : 
     312             :   NameAndAttributes &info = IterBool.first->second;
     313           0 :   info.name = IterBool.first->first();
     314           0 :   info.attributes = LTO_SYMBOL_DEFINITION_UNDEFINED;
     315           0 :   info.isFunction = false;
     316           0 :   info.symbol = clgv;
     317             : }
     318             : 
     319             : /// addObjCClassRef - Parse i386/ppc ObjC class list data structure.
     320           0 : void LTOModule::addObjCClassRef(const GlobalVariable *clgv) {
     321             :   std::string targetclassName;
     322           0 :   if (!objcClassNameFromExpression(clgv->getInitializer(), targetclassName))
     323             :     return;
     324             : 
     325             :   auto IterBool =
     326           0 :       _undefines.insert(std::make_pair(targetclassName, NameAndAttributes()));
     327             : 
     328           0 :   if (!IterBool.second)
     329             :     return;
     330             : 
     331             :   NameAndAttributes &info = IterBool.first->second;
     332           0 :   info.name = IterBool.first->first();
     333           0 :   info.attributes = LTO_SYMBOL_DEFINITION_UNDEFINED;
     334           0 :   info.isFunction = false;
     335           0 :   info.symbol = clgv;
     336             : }
     337             : 
     338          29 : void LTOModule::addDefinedDataSymbol(ModuleSymbolTable::Symbol Sym) {
     339             :   SmallString<64> Buffer;
     340             :   {
     341             :     raw_svector_ostream OS(Buffer);
     342          29 :     SymTab.printSymbolName(OS, Sym);
     343             :     Buffer.c_str();
     344             :   }
     345             : 
     346             :   const GlobalValue *V = Sym.get<GlobalValue *>();
     347          29 :   addDefinedDataSymbol(Buffer, V);
     348          29 : }
     349             : 
     350          29 : void LTOModule::addDefinedDataSymbol(StringRef Name, const GlobalValue *v) {
     351             :   // Add to list of defined symbols.
     352          29 :   addDefinedSymbol(Name, v, false);
     353             : 
     354          29 :   if (!v->hasSection() /* || !isTargetDarwin */)
     355             :     return;
     356             : 
     357             :   // Special case i386/ppc ObjC data structures in magic sections:
     358             :   // The issue is that the old ObjC object format did some strange
     359             :   // contortions to avoid real linker symbols.  For instance, the
     360             :   // ObjC class data structure is allocated statically in the executable
     361             :   // that defines that class.  That data structures contains a pointer to
     362             :   // its superclass.  But instead of just initializing that part of the
     363             :   // struct to the address of its superclass, and letting the static and
     364             :   // dynamic linkers do the rest, the runtime works by having that field
     365             :   // instead point to a C-string that is the name of the superclass.
     366             :   // At runtime the objc initialization updates that pointer and sets
     367             :   // it to point to the actual super class.  As far as the linker
     368             :   // knows it is just a pointer to a string.  But then someone wanted the
     369             :   // linker to issue errors at build time if the superclass was not found.
     370             :   // So they figured out a way in mach-o object format to use an absolute
     371             :   // symbols (.objc_class_name_Foo = 0) and a floating reference
     372             :   // (.reference .objc_class_name_Bar) to cause the linker into erroring when
     373             :   // a class was missing.
     374             :   // The following synthesizes the implicit .objc_* symbols for the linker
     375             :   // from the ObjC data structures generated by the front end.
     376             : 
     377             :   // special case if this data blob is an ObjC class definition
     378             :   if (const GlobalVariable *GV = dyn_cast<GlobalVariable>(v)) {
     379           0 :     StringRef Section = GV->getSection();
     380             :     if (Section.startswith("__OBJC,__class,")) {
     381           0 :       addObjCClass(GV);
     382             :     }
     383             : 
     384             :     // special case if this data blob is an ObjC category definition
     385             :     else if (Section.startswith("__OBJC,__category,")) {
     386           0 :       addObjCCategory(GV);
     387             :     }
     388             : 
     389             :     // special case if this data blob is the list of referenced classes
     390             :     else if (Section.startswith("__OBJC,__cls_refs,")) {
     391           0 :       addObjCClassRef(GV);
     392             :     }
     393             :   }
     394             : }
     395             : 
     396          78 : void LTOModule::addDefinedFunctionSymbol(ModuleSymbolTable::Symbol Sym) {
     397             :   SmallString<64> Buffer;
     398             :   {
     399             :     raw_svector_ostream OS(Buffer);
     400          78 :     SymTab.printSymbolName(OS, Sym);
     401             :     Buffer.c_str();
     402             :   }
     403             : 
     404             :   const Function *F = cast<Function>(Sym.get<GlobalValue *>());
     405          78 :   addDefinedFunctionSymbol(Buffer, F);
     406          78 : }
     407             : 
     408          81 : void LTOModule::addDefinedFunctionSymbol(StringRef Name, const Function *F) {
     409             :   // add to list of defined symbols
     410          81 :   addDefinedSymbol(Name, F, true);
     411          81 : }
     412             : 
     413         110 : void LTOModule::addDefinedSymbol(StringRef Name, const GlobalValue *def,
     414             :                                  bool isFunction) {
     415             :   // set alignment part log2() can have rounding errors
     416         110 :   uint32_t align = def->getAlignment();
     417         110 :   uint32_t attr = align ? countTrailingZeros(align) : 0;
     418             : 
     419             :   // set permissions part
     420         110 :   if (isFunction) {
     421          81 :     attr |= LTO_SYMBOL_PERMISSIONS_CODE;
     422             :   } else {
     423             :     const GlobalVariable *gv = dyn_cast<GlobalVariable>(def);
     424          28 :     if (gv && gv->isConstant())
     425          11 :       attr |= LTO_SYMBOL_PERMISSIONS_RODATA;
     426             :     else
     427          18 :       attr |= LTO_SYMBOL_PERMISSIONS_DATA;
     428             :   }
     429             : 
     430             :   // set definition part
     431         109 :   if (def->hasWeakLinkage() || def->hasLinkOnceLinkage())
     432          17 :     attr |= LTO_SYMBOL_DEFINITION_WEAK;
     433          93 :   else if (def->hasCommonLinkage())
     434           1 :     attr |= LTO_SYMBOL_DEFINITION_TENTATIVE;
     435             :   else
     436          92 :     attr |= LTO_SYMBOL_DEFINITION_REGULAR;
     437             : 
     438             :   // set scope part
     439             :   if (def->hasLocalLinkage())
     440             :     // Ignore visibility if linkage is local.
     441           3 :     attr |= LTO_SYMBOL_SCOPE_INTERNAL;
     442         107 :   else if (def->hasHiddenVisibility())
     443           2 :     attr |= LTO_SYMBOL_SCOPE_HIDDEN;
     444         105 :   else if (def->hasProtectedVisibility())
     445           0 :     attr |= LTO_SYMBOL_SCOPE_PROTECTED;
     446         105 :   else if (def->canBeOmittedFromSymbolTable())
     447           8 :     attr |= LTO_SYMBOL_SCOPE_DEFAULT_CAN_BE_HIDDEN;
     448             :   else
     449          97 :     attr |= LTO_SYMBOL_SCOPE_DEFAULT;
     450             : 
     451         110 :   if (def->hasComdat())
     452           0 :     attr |= LTO_SYMBOL_COMDAT;
     453             : 
     454         110 :   if (isa<GlobalAlias>(def))
     455           1 :     attr |= LTO_SYMBOL_ALIAS;
     456             : 
     457             :   auto Iter = _defines.insert(Name).first;
     458             : 
     459             :   // fill information structure
     460         110 :   NameAndAttributes info;
     461             :   StringRef NameRef = Iter->first();
     462         110 :   info.name = NameRef;
     463             :   assert(NameRef.data()[NameRef.size()] == '\0');
     464         110 :   info.attributes = attr;
     465         110 :   info.isFunction = isFunction;
     466         110 :   info.symbol = def;
     467             : 
     468             :   // add to table of symbols
     469         110 :   _symbols.push_back(info);
     470         110 : }
     471             : 
     472             : /// addAsmGlobalSymbol - Add a global symbol from module-level ASM to the
     473             : /// defined list.
     474          14 : void LTOModule::addAsmGlobalSymbol(StringRef name,
     475             :                                    lto_symbol_attributes scope) {
     476             :   auto IterBool = _defines.insert(name);
     477             : 
     478             :   // only add new define if not already defined
     479          14 :   if (!IterBool.second)
     480             :     return;
     481             : 
     482          14 :   NameAndAttributes &info = _undefines[IterBool.first->first()];
     483             : 
     484          14 :   if (info.symbol == nullptr) {
     485             :     // FIXME: This is trying to take care of module ASM like this:
     486             :     //
     487             :     //   module asm ".zerofill __FOO, __foo, _bar_baz_qux, 0"
     488             :     //
     489             :     // but is gross and its mother dresses it funny. Have the ASM parser give us
     490             :     // more details for this type of situation so that we're not guessing so
     491             :     // much.
     492             : 
     493             :     // fill information structure
     494          11 :     info.name = IterBool.first->first();
     495          11 :     info.attributes =
     496          11 :       LTO_SYMBOL_PERMISSIONS_DATA | LTO_SYMBOL_DEFINITION_REGULAR | scope;
     497          11 :     info.isFunction = false;
     498          11 :     info.symbol = nullptr;
     499             : 
     500             :     // add to table of symbols
     501          11 :     _symbols.push_back(info);
     502          11 :     return;
     503             :   }
     504             : 
     505           3 :   if (info.isFunction)
     506           3 :     addDefinedFunctionSymbol(info.name, cast<Function>(info.symbol));
     507             :   else
     508           0 :     addDefinedDataSymbol(info.name, info.symbol);
     509             : 
     510           3 :   _symbols.back().attributes &= ~LTO_SYMBOL_SCOPE_MASK;
     511           3 :   _symbols.back().attributes |= scope;
     512             : }
     513             : 
     514             : /// addAsmGlobalSymbolUndef - Add a global symbol from module-level ASM to the
     515             : /// undefined list.
     516           4 : void LTOModule::addAsmGlobalSymbolUndef(StringRef name) {
     517           4 :   auto IterBool = _undefines.insert(std::make_pair(name, NameAndAttributes()));
     518             : 
     519           8 :   _asm_undefines.push_back(IterBool.first->first());
     520             : 
     521             :   // we already have the symbol
     522           4 :   if (!IterBool.second)
     523             :     return;
     524             : 
     525             :   uint32_t attr = LTO_SYMBOL_DEFINITION_UNDEFINED;
     526             :   attr |= LTO_SYMBOL_SCOPE_DEFAULT;
     527             :   NameAndAttributes &info = IterBool.first->second;
     528           4 :   info.name = IterBool.first->first();
     529           4 :   info.attributes = attr;
     530           4 :   info.isFunction = false;
     531           4 :   info.symbol = nullptr;
     532             : }
     533             : 
     534             : /// Add a symbol which isn't defined just yet to a list to be resolved later.
     535          19 : void LTOModule::addPotentialUndefinedSymbol(ModuleSymbolTable::Symbol Sym,
     536             :                                             bool isFunc) {
     537             :   SmallString<64> name;
     538             :   {
     539             :     raw_svector_ostream OS(name);
     540          19 :     SymTab.printSymbolName(OS, Sym);
     541             :     name.c_str();
     542             :   }
     543             : 
     544          38 :   auto IterBool = _undefines.insert(std::make_pair(name, NameAndAttributes()));
     545             : 
     546             :   // we already have the symbol
     547          19 :   if (!IterBool.second)
     548             :     return;
     549             : 
     550             :   NameAndAttributes &info = IterBool.first->second;
     551             : 
     552          19 :   info.name = IterBool.first->first();
     553             : 
     554             :   const GlobalValue *decl = Sym.dyn_cast<GlobalValue *>();
     555             : 
     556          19 :   if (decl->hasExternalWeakLinkage())
     557           0 :     info.attributes = LTO_SYMBOL_DEFINITION_WEAKUNDEF;
     558             :   else
     559          19 :     info.attributes = LTO_SYMBOL_DEFINITION_UNDEFINED;
     560             : 
     561          19 :   info.isFunction = isFunc;
     562          19 :   info.symbol = decl;
     563             : }
     564             : 
     565          50 : void LTOModule::parseSymbols() {
     566         205 :   for (auto Sym : SymTab.symbols()) {
     567             :     auto *GV = Sym.dyn_cast<GlobalValue *>();
     568         155 :     uint32_t Flags = SymTab.getSymbolFlags(Sym);
     569         155 :     if (Flags & object::BasicSymbolRef::SF_FormatSpecific)
     570             :       continue;
     571             : 
     572         144 :     bool IsUndefined = Flags & object::BasicSymbolRef::SF_Undefined;
     573             : 
     574         144 :     if (!GV) {
     575             :       SmallString<64> Buffer;
     576             :       {
     577             :         raw_svector_ostream OS(Buffer);
     578          18 :         SymTab.printSymbolName(OS, Sym);
     579             :         Buffer.c_str();
     580             :       }
     581          18 :       StringRef Name(Buffer);
     582             : 
     583          18 :       if (IsUndefined)
     584           4 :         addAsmGlobalSymbolUndef(Name);
     585          14 :       else if (Flags & object::BasicSymbolRef::SF_Global)
     586           8 :         addAsmGlobalSymbol(Name, LTO_SYMBOL_SCOPE_DEFAULT);
     587             :       else
     588           6 :         addAsmGlobalSymbol(Name, LTO_SYMBOL_SCOPE_INTERNAL);
     589             :       continue;
     590             :     }
     591             : 
     592             :     auto *F = dyn_cast<Function>(GV);
     593         126 :     if (IsUndefined) {
     594          19 :       addPotentialUndefinedSymbol(Sym, F != nullptr);
     595          19 :       continue;
     596             :     }
     597             : 
     598         107 :     if (F) {
     599          78 :       addDefinedFunctionSymbol(Sym);
     600          78 :       continue;
     601             :     }
     602             : 
     603          29 :     if (isa<GlobalVariable>(GV)) {
     604          28 :       addDefinedDataSymbol(Sym);
     605          28 :       continue;
     606             :     }
     607             : 
     608             :     assert(isa<GlobalAlias>(GV));
     609           1 :     addDefinedDataSymbol(Sym);
     610             :   }
     611             : 
     612             :   // make symbols for all undefines
     613          50 :   for (StringMap<NameAndAttributes>::iterator u =_undefines.begin(),
     614          84 :          e = _undefines.end(); u != e; ++u) {
     615             :     // If this symbol also has a definition, then don't make an undefine because
     616             :     // it is a tentative definition.
     617          68 :     if (_defines.count(u->getKey())) continue;
     618          16 :     NameAndAttributes info = u->getValue();
     619          16 :     _symbols.push_back(info);
     620             :   }
     621          50 : }
     622             : 
     623             : /// parseMetadata - Parse metadata from the module
     624          50 : void LTOModule::parseMetadata() {
     625          54 :   raw_string_ostream OS(LinkerOpts);
     626             : 
     627             :   // Linker Options
     628          50 :   if (NamedMDNode *LinkerOptions =
     629          50 :           getModule().getNamedMetadata("llvm.linker.options")) {
     630           0 :     for (unsigned i = 0, e = LinkerOptions->getNumOperands(); i != e; ++i) {
     631           0 :       MDNode *MDOptions = LinkerOptions->getOperand(i);
     632           0 :       for (unsigned ii = 0, ie = MDOptions->getNumOperands(); ii != ie; ++ii) {
     633             :         MDString *MDOption = cast<MDString>(MDOptions->getOperand(ii));
     634           0 :         OS << " " << MDOption->getString();
     635             :       }
     636             :     }
     637             :   }
     638             : 
     639             :   // Globals - we only need to do this for COFF.
     640          50 :   const Triple TT(_target->getTargetTriple());
     641          50 :   if (!TT.isOSBinFormatCOFF())
     642             :     return;
     643             :   Mangler M;
     644          12 :   for (const NameAndAttributes &Sym : _symbols) {
     645           8 :     if (!Sym.symbol)
     646             :       continue;
     647           8 :     emitLinkerFlagsForGlobalCOFF(OS, Sym.symbol, TT, M);
     648             :   }
     649             : 
     650             :   // Add other interesting metadata here.
     651             : }

Generated by: LCOV version 1.13