LCOV - code coverage report
Current view: top level - lib/Target - TargetLoweringObjectFile.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 95 100 95.0 %
Date: 2018-10-20 13:21:21 Functions: 17 18 94.4 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //===-- llvm/Target/TargetLoweringObjectFile.cpp - Object File Info -------===//
       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 classes used to handle lowerings specific to common
      11             : // object file formats.
      12             : //
      13             : //===----------------------------------------------------------------------===//
      14             : 
      15             : #include "llvm/Target/TargetLoweringObjectFile.h"
      16             : #include "llvm/BinaryFormat/Dwarf.h"
      17             : #include "llvm/IR/Constants.h"
      18             : #include "llvm/IR/DataLayout.h"
      19             : #include "llvm/IR/DerivedTypes.h"
      20             : #include "llvm/IR/Function.h"
      21             : #include "llvm/IR/GlobalVariable.h"
      22             : #include "llvm/IR/Mangler.h"
      23             : #include "llvm/MC/MCContext.h"
      24             : #include "llvm/MC/MCExpr.h"
      25             : #include "llvm/MC/MCStreamer.h"
      26             : #include "llvm/MC/MCSymbol.h"
      27             : #include "llvm/Support/ErrorHandling.h"
      28             : #include "llvm/Support/raw_ostream.h"
      29             : #include "llvm/Target/TargetMachine.h"
      30             : #include "llvm/Target/TargetOptions.h"
      31             : using namespace llvm;
      32             : 
      33             : //===----------------------------------------------------------------------===//
      34             : //                              Generic Code
      35             : //===----------------------------------------------------------------------===//
      36             : 
      37             : /// Initialize - this method must be called before any actual lowering is
      38             : /// done.  This specifies the current context for codegen, and gives the
      39             : /// lowering implementations a chance to set up their default sections.
      40       27325 : void TargetLoweringObjectFile::Initialize(MCContext &ctx,
      41             :                                           const TargetMachine &TM) {
      42       27325 :   Ctx = &ctx;
      43             :   // `Initialize` can be called more than once.
      44       27382 :   delete Mang;
      45       27325 :   Mang = new Mangler();
      46       27325 :   InitMCObjectFileInfo(TM.getTargetTriple(), TM.isPositionIndependent(), *Ctx,
      47       27325 :                        TM.getCodeModel() == CodeModel::Large);
      48             : 
      49             :   // Reset various EH DWARF encodings.
      50       27325 :   PersonalityEncoding = LSDAEncoding = TTypeEncoding = dwarf::DW_EH_PE_absptr;
      51       27325 : }
      52             : 
      53       34295 : TargetLoweringObjectFile::~TargetLoweringObjectFile() {
      54       55230 :   delete Mang;
      55       34294 : }
      56           0 : 
      57             : static bool isNullOrUndef(const Constant *C) {
      58           0 :   // Check that the constant isn't all zeros or undefs.
      59       34295 :   if (C->isNullValue() || isa<UndefValue>(C))
      60       55230 :     return true;
      61       34294 :   if (!isa<ConstantAggregate>(C))
      62             :     return false;
      63      307327 :   for (auto Operand : C->operand_values()) {
      64             :     if (!isNullOrUndef(cast<Constant>(Operand)))
      65      307327 :       return false;
      66             :   }
      67             :   return true;
      68             : }
      69       57936 : 
      70       32294 : static bool isSuitableForBSS(const GlobalVariable *GV) {
      71             :   const Constant *C = GV->getInitializer();
      72             : 
      73             :   // Must have zero initializer.
      74             :   if (!isNullOrUndef(C))
      75             :     return false;
      76      275033 : 
      77             :   // Leave constant zeros in readonly constant sections, so they can be shared.
      78             :   if (GV->isConstant())
      79             :     return false;
      80      275033 : 
      81             :   // If the global has an explicit section specified, don't put it in BSS.
      82             :   if (GV->hasSection())
      83             :     return false;
      84       45968 : 
      85             :   // Otherwise, put it in BSS!
      86             :   return true;
      87             : }
      88       42947 : 
      89          63 : /// IsNullTerminatedString - Return true if the specified constant (which is
      90             : /// known to have a type that is an array of 1/2/4 byte elements) ends with a
      91             : /// nul value and contains no other nuls in it.  Note that this is more general
      92             : /// than ConstantDataSequential::isString because we allow 2 & 4 byte strings.
      93             : static bool IsNullTerminatedString(const Constant *C) {
      94             :   // First check: is we have constant array terminated with zero
      95             :   if (const ConstantDataSequential *CDS = dyn_cast<ConstantDataSequential>(C)) {
      96             :     unsigned NumElts = CDS->getNumElements();
      97             :     assert(NumElts != 0 && "Can't have an empty CDS");
      98             : 
      99      197173 :     if (CDS->getElementAsInteger(NumElts-1) != 0)
     100             :       return false; // Not null terminated.
     101             : 
     102      196625 :     // Verify that the null doesn't occur anywhere else in the string.
     103             :     for (unsigned i = 0; i != NumElts-1; ++i)
     104             :       if (CDS->getElementAsInteger(i) == 0)
     105      196625 :         return false;
     106             :     return true;
     107             :   }
     108             : 
     109    12236876 :   // Another possibility: [1 x i8] zeroinitializer
     110    12049807 :   if (isa<ConstantAggregateZero>(C))
     111             :     return cast<ArrayType>(C->getType())->getNumElements() == 1;
     112             : 
     113             :   return false;
     114             : }
     115             : 
     116         548 : MCSymbol *TargetLoweringObjectFile::getSymbolWithGlobalValueBase(
     117         544 :     const GlobalValue *GV, StringRef Suffix, const TargetMachine &TM) const {
     118             :   assert(!Suffix.empty());
     119             : 
     120             :   SmallString<60> NameStr;
     121             :   NameStr += GV->getParent()->getDataLayout().getPrivateGlobalPrefix();
     122        1004 :   TM.getNameWithPrefix(NameStr, GV, *Mang);
     123             :   NameStr.append(Suffix.begin(), Suffix.end());
     124             :   return Ctx->getOrCreateSymbol(NameStr);
     125             : }
     126             : 
     127        1004 : MCSymbol *TargetLoweringObjectFile::getCFIPersonalitySymbol(
     128        1004 :     const GlobalValue *GV, const TargetMachine &TM,
     129        1004 :     MachineModuleInfo *MMI) const {
     130        2008 :   return TM.getSymbol(GV);
     131             : }
     132             : 
     133         165 : void TargetLoweringObjectFile::emitPersonalityValue(MCStreamer &Streamer,
     134             :                                                     const DataLayout &,
     135             :                                                     const MCSymbol *Sym) const {
     136         165 : }
     137             : 
     138             : 
     139          27 : /// getKindForGlobal - This is a top-level target-independent classifier for
     140             : /// a global object.  Given a global variable and information from the TM, this
     141             : /// function classifies the global in a target independent manner. This function
     142          27 : /// may be overridden by the target implementation.
     143             : SectionKind TargetLoweringObjectFile::getKindForGlobal(const GlobalObject *GO,
     144             :                                                        const TargetMachine &TM){
     145             :   assert(!GO->isDeclaration() && !GO->hasAvailableExternallyLinkage() &&
     146             :          "Can only be used for global definitions");
     147             : 
     148             :   // Functions are classified as text sections.
     149      684443 :   if (isa<Function>(GO))
     150             :     return SectionKind::getText();
     151             : 
     152             :   // Global variables require more detailed analysis.
     153             :   const auto *GVar = cast<GlobalVariable>(GO);
     154             : 
     155      684443 :   // Handle thread-local data first.
     156             :   if (GVar->isThreadLocal()) {
     157             :     if (isSuitableForBSS(GVar) && !TM.Options.NoZerosInBSS)
     158             :       return SectionKind::getThreadBSS();
     159             :     return SectionKind::getThreadData();
     160             :   }
     161             : 
     162      278440 :   // Variables with common linkage always get classified as common.
     163         376 :   if (GVar->hasCommonLinkage())
     164             :     return SectionKind::getCommon();
     165             : 
     166             :   // Most non-mergeable zero data can be put in the BSS section unless otherwise
     167             :   // specified.
     168             :   if (isSuitableForBSS(GVar) && !TM.Options.NoZerosInBSS) {
     169      278064 :     if (GVar->hasLocalLinkage())
     170             :       return SectionKind::getBSSLocal();
     171             :     else if (GVar->hasExternalLinkage())
     172             :       return SectionKind::getBSSExtern();
     173             :     return SectionKind::getBSS();
     174      274657 :   }
     175             : 
     176             :   // If the global is marked constant, we can put it into a mergable section,
     177       14162 :   // a mergable string section, or general .data if it contains relocations.
     178             :   if (GVar->isConstant()) {
     179             :     // If the initializer for the global contains something that requires a
     180             :     // relocation, then we may have to drop this into a writable data section
     181             :     // even though it is marked const.
     182             :     const Constant *C = GVar->getInitializer();
     183             :     if (!C->needsRelocation()) {
     184      232011 :       // If the global is required to have a unique address, it can't be put
     185             :       // into a mergable section: just drop it into the general read-only
     186             :       // section instead.
     187             :       if (!GVar->hasGlobalUnnamedAddr())
     188             :         return SectionKind::getReadOnly();
     189      224369 : 
     190             :       // If initializer is a null-terminated string, put it in a "cstring"
     191             :       // section of the right width.
     192             :       if (ArrayType *ATy = dyn_cast<ArrayType>(C->getType())) {
     193      209840 :         if (IntegerType *ITy =
     194             :               dyn_cast<IntegerType>(ATy->getElementType())) {
     195             :           if ((ITy->getBitWidth() == 8 || ITy->getBitWidth() == 16 ||
     196             :                ITy->getBitWidth() == 32) &&
     197             :               IsNullTerminatedString(C)) {
     198      199251 :             if (ITy->getBitWidth() == 8)
     199             :               return SectionKind::getMergeable1ByteCString();
     200      197486 :             if (ITy->getBitWidth() == 16)
     201       10303 :               return SectionKind::getMergeable2ByteCString();
     202      394434 : 
     203      197173 :             assert(ITy->getBitWidth() == 32 && "Unknown width");
     204      187601 :             return SectionKind::getMergeable4ByteCString();
     205             :           }
     206        1299 :         }
     207             :       }
     208             : 
     209             :       // Otherwise, just drop it into a mergable constant section.  If we have
     210             :       // a section for this size, use it, otherwise use the arbitrary sized
     211             :       // mergable section.
     212             :       switch (
     213             :           GVar->getParent()->getDataLayout().getTypeAllocSize(C->getType())) {
     214             :       case 4:  return SectionKind::getMergeableConst4();
     215             :       case 8:  return SectionKind::getMergeableConst8();
     216             :       case 16: return SectionKind::getMergeableConst16();
     217             :       case 32: return SectionKind::getMergeableConst32();
     218       11650 :       default:
     219       11650 :         return SectionKind::getReadOnly();
     220             :       }
     221             : 
     222             :     } else {
     223             :       // In static, ROPI and RWPI relocation models, the linker will resolve
     224             :       // all addresses, so the relocation entries will actually be constants by
     225             :       // the time the app starts up.  However, we can't put this into a
     226             :       // mergable section, because the linker doesn't take relocations into
     227             :       // consideration when it tries to merge entries in the section.
     228             :       Reloc::Model ReloModel = TM.getRelocationModel();
     229             :       if (ReloModel == Reloc::Static || ReloModel == Reloc::ROPI ||
     230             :           ReloModel == Reloc::RWPI || ReloModel == Reloc::ROPI_RWPI)
     231             :         return SectionKind::getReadOnly();
     232             : 
     233             :       // Otherwise, the dynamic linker needs to fix it up, put it in the
     234       14529 :       // writable data.rel section.
     235       14529 :       return SectionKind::getReadOnlyWithRel();
     236        1662 :     }
     237             :   }
     238             : 
     239             :   // Okay, this isn't a constant.
     240             :   return SectionKind::getData();
     241             : }
     242             : 
     243             : /// This method computes the appropriate section to emit the specified global
     244             : /// variable or function definition.  This should not be passed external (or
     245             : /// available externally) globals.
     246             : MCSection *TargetLoweringObjectFile::SectionForGlobal(
     247             :     const GlobalObject *GO, SectionKind Kind, const TargetMachine &TM) const {
     248             :   // Select section name.
     249             :   if (GO->hasSection())
     250             :     return getExplicitSectionGlobal(GO, Kind, TM);
     251             : 
     252      677747 :   if (auto *GVar = dyn_cast<GlobalVariable>(GO)) {
     253             :     auto Attrs = GVar->getAttributes();
     254             :     if ((Attrs.hasAttribute("bss-section") && Kind.isBSS()) ||
     255      677747 :         (Attrs.hasAttribute("data-section") && Kind.isData()) ||
     256        4537 :         (Attrs.hasAttribute("rodata-section") && Kind.isReadOnly()))  {
     257             :        return getExplicitSectionGlobal(GO, Kind, TM);
     258             :     }
     259      270747 :   }
     260      541500 : 
     261      541496 :   if (auto *F = dyn_cast<Function>(GO)) {
     262      541471 :     if (F->hasFnAttribute("implicit-section-name"))
     263          13 :       return getExplicitSectionGlobal(GO, Kind, TM);
     264             :   }
     265             : 
     266             :   // Use default section depending on the 'type' of global
     267             :   return SelectSectionForGlobal(GO, Kind, TM);
     268      402463 : }
     269           2 : 
     270             : MCSection *TargetLoweringObjectFile::getSectionForJumpTable(
     271             :     const Function &F, const TargetMachine &TM) const {
     272             :   unsigned Align = 0;
     273      673195 :   return getSectionForConstant(F.getParent()->getDataLayout(),
     274             :                                SectionKind::getReadOnly(), /*C=*/nullptr,
     275             :                                Align);
     276           6 : }
     277             : 
     278           6 : bool TargetLoweringObjectFile::shouldPutJumpTableInFunctionSection(
     279           6 :     bool UsesLabelDifference, const Function &F) const {
     280             :   // In PIC mode, we need to emit the jump table to the same section as the
     281           6 :   // function body itself, otherwise the label differences won't make sense.
     282             :   // FIXME: Need a better predicate for this: what about custom entries?
     283             :   if (UsesLabelDifference)
     284          31 :     return true;
     285             : 
     286             :   // We should also do if the section name is NULL or function is declared
     287             :   // in discardable section
     288             :   // FIXME: this isn't the right predicate, should be based on the MCSection
     289          31 :   // for the function.
     290             :   return F.isWeakForLinker();
     291             : }
     292             : 
     293             : /// Given a mergable constant with the specified size and relocation
     294             : /// information, return a section that it should be placed in.
     295             : MCSection *TargetLoweringObjectFile::getSectionForConstant(
     296             :     const DataLayout &DL, SectionKind Kind, const Constant *C,
     297             :     unsigned &Align) const {
     298             :   if (Kind.isReadOnly() && ReadOnlySection != nullptr)
     299             :     return ReadOnlySection;
     300             : 
     301          21 :   return DataSection;
     302             : }
     303             : 
     304          21 : /// getTTypeGlobalReference - Return an MCExpr to use for a
     305             : /// reference to the specified global variable from exception
     306             : /// handling information.
     307           0 : const MCExpr *TargetLoweringObjectFile::getTTypeGlobalReference(
     308             :     const GlobalValue *GV, unsigned Encoding, const TargetMachine &TM,
     309             :     MachineModuleInfo *MMI, MCStreamer &Streamer) const {
     310             :   const MCSymbolRefExpr *Ref =
     311             :       MCSymbolRefExpr::create(TM.getSymbol(GV), getContext());
     312             : 
     313       11505 :   return getTTypeReference(Ref, Encoding, Streamer);
     314             : }
     315             : 
     316             : const MCExpr *TargetLoweringObjectFile::
     317       11505 : getTTypeReference(const MCSymbolRefExpr *Sym, unsigned Encoding,
     318             :                   MCStreamer &Streamer) const {
     319       11505 :   switch (Encoding & 0x70) {
     320             :   default:
     321             :     report_fatal_error("We do not support this DWARF encoding yet!");
     322       11562 :   case dwarf::DW_EH_PE_absptr:
     323             :     // Do nothing special
     324             :     return Sym;
     325       11562 :   case dwarf::DW_EH_PE_pcrel: {
     326           0 :     // Emit a label to the streamer for the current position.  This gives us
     327           0 :     // .-foo addressing.
     328             :     MCSymbol *PCSym = getContext().createTempSymbol();
     329             :     Streamer.EmitLabel(PCSym);
     330             :     const MCExpr *PC = MCSymbolRefExpr::create(PCSym, getContext());
     331          57 :     return MCBinaryExpr::createSub(Sym, PC, getContext());
     332             :   }
     333             :   }
     334          57 : }
     335          57 : 
     336          57 : const MCExpr *TargetLoweringObjectFile::getDebugThreadLocalSymbol(const MCSymbol *Sym) const {
     337          57 :   // FIXME: It's not clear what, if any, default this should have - perhaps a
     338             :   // null return could mean 'no location' & we should just do that here.
     339             :   return MCSymbolRefExpr::create(Sym, *Ctx);
     340             : }
     341             : 
     342           6 : void TargetLoweringObjectFile::getNameWithPrefix(
     343             :     SmallVectorImpl<char> &OutName, const GlobalValue *GV,
     344             :     const TargetMachine &TM) const {
     345           6 :   Mang->getNameWithPrefix(OutName, GV, /*CannotUsePrivateLabel=*/false);
     346             : }

Generated by: LCOV version 1.13