LCOV - code coverage report
Current view: top level - include/llvm/MC - MCSymbol.h (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 56 64 87.5 %
Date: 2018-10-20 13:21:21 Functions: 3 7 42.9 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //===- MCSymbol.h - Machine Code Symbols ------------------------*- C++ -*-===//
       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 contains the declaration of the MCSymbol class.
      11             : //
      12             : //===----------------------------------------------------------------------===//
      13             : 
      14             : #ifndef LLVM_MC_MCSYMBOL_H
      15             : #define LLVM_MC_MCSYMBOL_H
      16             : 
      17             : #include "llvm/ADT/PointerIntPair.h"
      18             : #include "llvm/ADT/StringMap.h"
      19             : #include "llvm/ADT/StringRef.h"
      20             : #include "llvm/MC/MCFragment.h"
      21             : #include "llvm/Support/ErrorHandling.h"
      22             : #include "llvm/Support/MathExtras.h"
      23             : #include <cassert>
      24             : #include <cstddef>
      25             : #include <cstdint>
      26             : 
      27             : namespace llvm {
      28             : 
      29             : class MCAsmInfo;
      30             : class MCContext;
      31             : class MCExpr;
      32             : class MCSection;
      33             : class raw_ostream;
      34             : 
      35             : /// MCSymbol - Instances of this class represent a symbol name in the MC file,
      36             : /// and MCSymbols are created and uniqued by the MCContext class.  MCSymbols
      37             : /// should only be constructed with valid names for the object file.
      38             : ///
      39             : /// If the symbol is defined/emitted into the current translation unit, the
      40             : /// Section member is set to indicate what section it lives in.  Otherwise, if
      41             : /// it is a reference to an external entity, it has a null section.
      42             : class MCSymbol {
      43             : protected:
      44             :   /// The kind of the symbol.  If it is any value other than unset then this
      45             :   /// class is actually one of the appropriate subclasses of MCSymbol.
      46             :   enum SymbolKind {
      47             :     SymbolKindUnset,
      48             :     SymbolKindCOFF,
      49             :     SymbolKindELF,
      50             :     SymbolKindMachO,
      51             :     SymbolKindWasm,
      52             :   };
      53             : 
      54             :   /// A symbol can contain an Offset, or Value, or be Common, but never more
      55             :   /// than one of these.
      56             :   enum Contents : uint8_t {
      57             :     SymContentsUnset,
      58             :     SymContentsOffset,
      59             :     SymContentsVariable,
      60             :     SymContentsCommon,
      61             :   };
      62             : 
      63             :   // Special sentinal value for the absolute pseudo fragment.
      64             :   static MCFragment *AbsolutePseudoFragment;
      65             : 
      66             :   /// If a symbol has a Fragment, the section is implied, so we only need
      67             :   /// one pointer.
      68             :   /// The special AbsolutePseudoFragment value is for absolute symbols.
      69             :   /// If this is a variable symbol, this caches the variable value's fragment.
      70             :   /// FIXME: We might be able to simplify this by having the asm streamer create
      71             :   /// dummy fragments.
      72             :   /// If this is a section, then it gives the symbol is defined in. This is null
      73             :   /// for undefined symbols.
      74             :   ///
      75             :   /// If this is a fragment, then it gives the fragment this symbol's value is
      76             :   /// relative to, if any.
      77             :   ///
      78             :   /// For the 'HasName' integer, this is true if this symbol is named.
      79             :   /// A named symbol will have a pointer to the name allocated in the bytes
      80             :   /// immediately prior to the MCSymbol.
      81             :   mutable PointerIntPair<MCFragment *, 1> FragmentAndHasName;
      82             : 
      83             :   /// IsTemporary - True if this is an assembler temporary label, which
      84             :   /// typically does not survive in the .o file's symbol table.  Usually
      85             :   /// "Lfoo" or ".foo".
      86             :   unsigned IsTemporary : 1;
      87             : 
      88             :   /// True if this symbol can be redefined.
      89             :   unsigned IsRedefinable : 1;
      90             : 
      91             :   /// IsUsed - True if this symbol has been used.
      92             :   mutable unsigned IsUsed : 1;
      93             : 
      94             :   mutable unsigned IsRegistered : 1;
      95             : 
      96             :   /// This symbol is visible outside this translation unit.
      97             :   mutable unsigned IsExternal : 1;
      98             : 
      99             :   /// This symbol is private extern.
     100             :   mutable unsigned IsPrivateExtern : 1;
     101             : 
     102             :   /// LLVM RTTI discriminator. This is actually a SymbolKind enumerator, but is
     103             :   /// unsigned to avoid sign extension and achieve better bitpacking with MSVC.
     104             :   unsigned Kind : 3;
     105             : 
     106             :   /// True if we have created a relocation that uses this symbol.
     107             :   mutable unsigned IsUsedInReloc : 1;
     108             : 
     109             :   /// This is actually a Contents enumerator, but is unsigned to avoid sign
     110             :   /// extension and achieve better bitpacking with MSVC.
     111             :   unsigned SymbolContents : 2;
     112             : 
     113             :   /// The alignment of the symbol, if it is 'common', or -1.
     114             :   ///
     115             :   /// The alignment is stored as log2(align) + 1.  This allows all values from
     116             :   /// 0 to 2^31 to be stored which is every power of 2 representable by an
     117             :   /// unsigned.
     118             :   enum : unsigned { NumCommonAlignmentBits = 5 };
     119             :   unsigned CommonAlignLog2 : NumCommonAlignmentBits;
     120             : 
     121             :   /// The Flags field is used by object file implementations to store
     122             :   /// additional per symbol information which is not easily classified.
     123             :   enum : unsigned { NumFlagsBits = 16 };
     124             :   mutable uint32_t Flags : NumFlagsBits;
     125             : 
     126             :   /// Index field, for use by the object file implementation.
     127             :   mutable uint32_t Index = 0;
     128             : 
     129             :   union {
     130             :     /// The offset to apply to the fragment address to form this symbol's value.
     131             :     uint64_t Offset;
     132             : 
     133             :     /// The size of the symbol, if it is 'common'.
     134             :     uint64_t CommonSize;
     135             : 
     136             :     /// If non-null, the value for a variable symbol.
     137             :     const MCExpr *Value;
     138             :   };
     139             : 
     140             :   // MCContext creates and uniques these.
     141             :   friend class MCExpr;
     142             :   friend class MCContext;
     143             : 
     144             :   /// The name for a symbol.
     145             :   /// MCSymbol contains a uint64_t so is probably aligned to 8.  On a 32-bit
     146             :   /// system, the name is a pointer so isn't going to satisfy the 8 byte
     147             :   /// alignment of uint64_t.  Account for that here.
     148             :   using NameEntryStorageTy = union {
     149             :     const StringMapEntry<bool> *NameEntry;
     150             :     uint64_t AlignmentPadding;
     151             :   };
     152             : 
     153             :   MCSymbol(SymbolKind Kind, const StringMapEntry<bool> *Name, bool isTemporary)
     154    11212813 :       : IsTemporary(isTemporary), IsRedefinable(false), IsUsed(false),
     155             :         IsRegistered(false), IsExternal(false), IsPrivateExtern(false),
     156             :         Kind(Kind), IsUsedInReloc(false), SymbolContents(SymContentsUnset),
     157    11212813 :         CommonAlignLog2(0), Flags(0) {
     158    11212813 :     Offset = 0;
     159    11212813 :     FragmentAndHasName.setInt(!!Name);
     160    11212813 :     if (Name)
     161     6113060 :       getNameEntryPtr() = Name;
     162             :   }
     163             : 
     164             :   // Provide custom new/delete as we will only allocate space for a name
     165             :   // if we need one.
     166             :   void *operator new(size_t s, const StringMapEntry<bool> *Name,
     167             :                      MCContext &Ctx);
     168             : 
     169             : private:
     170             :   void operator delete(void *);
     171             :   /// Placement delete - required by std, but never called.
     172             :   void operator delete(void*, unsigned) {
     173             :     llvm_unreachable("Constructor throws?");
     174             :   }
     175             :   /// Placement delete - required by std, but never called.
     176             :   void operator delete(void*, unsigned, bool) {
     177             :     llvm_unreachable("Constructor throws?");
     178             :   }
     179             : 
     180             :   MCSection *getSectionPtr() const {
     181    18517872 :     if (MCFragment *F = getFragment()) {
     182             :       assert(F != AbsolutePseudoFragment);
     183    18517871 :       return F->getParent();
     184             :     }
     185             :     return nullptr;
     186             :   }
     187             : 
     188             :   /// Get a reference to the name field.  Requires that we have a name
     189             :   const StringMapEntry<bool> *&getNameEntryPtr() {
     190             :     assert(FragmentAndHasName.getInt() && "Name is required");
     191             :     NameEntryStorageTy *Name = reinterpret_cast<NameEntryStorageTy *>(this);
     192             :     return (*(Name - 1)).NameEntry;
     193             :   }
     194             :   const StringMapEntry<bool> *&getNameEntryPtr() const {
     195             :     return const_cast<MCSymbol*>(this)->getNameEntryPtr();
     196             :   }
     197             : 
     198             : public:
     199             :   MCSymbol(const MCSymbol &) = delete;
     200             :   MCSymbol &operator=(const MCSymbol &) = delete;
     201             : 
     202             :   /// getName - Get the symbol name.
     203             :   StringRef getName() const {
     204    17492476 :     if (!FragmentAndHasName.getInt())
     205             :       return StringRef();
     206             : 
     207     8739157 :     return getNameEntryPtr()->first();
     208             :   }
     209             : 
     210    18796630 :   bool isRegistered() const { return IsRegistered; }
     211     8576279 :   void setIsRegistered(bool Value) const { IsRegistered = Value; }
     212             : 
     213     5306484 :   void setUsedInReloc() const { IsUsedInReloc = true; }
     214     8765394 :   bool isUsedInReloc() const { return IsUsedInReloc; }
     215             : 
     216             :   /// \name Accessors
     217             :   /// @{
     218             : 
     219             :   /// isTemporary - Check if this is an assembler temporary symbol.
     220     8722917 :   bool isTemporary() const { return IsTemporary; }
     221             : 
     222             :   /// isUsed - Check if this is used.
     223         350 :   bool isUsed() const { return IsUsed; }
     224             : 
     225             :   /// Check if this symbol is redefinable.
     226             :   bool isRedefinable() const { return IsRedefinable; }
     227             :   /// Mark this symbol as redefinable.
     228         828 :   void setRedefinable(bool Value) { IsRedefinable = Value; }
     229             :   /// Prepare this symbol to be redefined.
     230             :   void redefineIfPossible() {
     231     8888995 :     if (IsRedefinable) {
     232           3 :       if (SymbolContents == SymContentsVariable) {
     233           3 :         Value = nullptr;
     234           3 :         SymbolContents = SymContentsUnset;
     235             :       }
     236             :       setUndefined();
     237           3 :       IsRedefinable = false;
     238             :     }
     239             :   }
     240             : 
     241             :   /// @}
     242             :   /// \name Associated Sections
     243             :   /// @{
     244             : 
     245             :   /// isDefined - Check if this symbol is defined (i.e., it has an address).
     246             :   ///
     247             :   /// Defined symbols are either absolute or in some section.
     248             :   bool isDefined() const { return !isUndefined(); }
     249             : 
     250             :   /// isInSection - Check if this symbol is defined in some section (i.e., it
     251             :   /// is defined but not absolute).
     252     9329735 :   bool isInSection() const {
     253     9329735 :     return isDefined() && !isAbsolute();
     254             :   }
     255             : 
     256             :   /// isUndefined - Check if this symbol undefined (i.e., implicitly defined).
     257             :   bool isUndefined(bool SetUsed = true) const {
     258    84119792 :     return getFragment(SetUsed) == nullptr;
     259             :   }
     260             : 
     261             :   /// isAbsolute - Check if this is an absolute symbol.
     262             :   bool isAbsolute() const {
     263     9090235 :     return getFragment() == AbsolutePseudoFragment;
     264             :   }
     265             : 
     266             :   /// Get the section associated with a defined, non-absolute symbol.
     267             :   MCSection &getSection() const {
     268             :     assert(isInSection() && "Invalid accessor!");
     269             :     return *getSectionPtr();
     270             :   }
     271             : 
     272             :   /// Mark the symbol as defined in the fragment \p F.
     273             :   void setFragment(MCFragment *F) const {
     274             :     assert(!isVariable() && "Cannot set fragment of variable");
     275             :     FragmentAndHasName.setPointer(F);
     276             :   }
     277             : 
     278             :   /// Mark the symbol as undefined.
     279             :   void setUndefined() { FragmentAndHasName.setPointer(nullptr); }
     280             : 
     281        1737 :   bool isELF() const { return Kind == SymbolKindELF; }
     282             : 
     283             :   bool isCOFF() const { return Kind == SymbolKindCOFF; }
     284             : 
     285             :   bool isMachO() const { return Kind == SymbolKindMachO; }
     286             : 
     287             :   bool isWasm() const { return Kind == SymbolKindWasm; }
     288             : 
     289             :   /// @}
     290             :   /// \name Variable Symbols
     291             :   /// @{
     292             : 
     293             :   /// isVariable - Check if this is a variable symbol.
     294             :   bool isVariable() const {
     295    87511269 :     return SymbolContents == SymContentsVariable;
     296             :   }
     297             : 
     298             :   /// getVariableValue - Get the value for variable symbols.
     299             :   const MCExpr *getVariableValue(bool SetUsed = true) const {
     300             :     assert(isVariable() && "Invalid accessor!");
     301       30576 :     IsUsed |= SetUsed;
     302       25926 :     return Value;
     303             :   }
     304             : 
     305             :   void setVariableValue(const MCExpr *Value);
     306             : 
     307             :   /// @}
     308             : 
     309             :   /// Get the (implementation defined) index.
     310           0 :   uint32_t getIndex() const {
     311           0 :     return Index;
     312             :   }
     313             : 
     314             :   /// Set the (implementation defined) index.
     315           0 :   void setIndex(uint32_t Value) const {
     316      700256 :     Index = Value;
     317           0 :   }
     318             : 
     319             :   bool isUnset() const { return SymbolContents == SymContentsUnset; }
     320             : 
     321           0 :   uint64_t getOffset() const {
     322             :     assert((SymbolContents == SymContentsUnset ||
     323             :             SymbolContents == SymContentsOffset) &&
     324             :            "Cannot get offset for a common/variable symbol");
     325           0 :     return Offset;
     326             :   }
     327             :   void setOffset(uint64_t Value) {
     328             :     assert((SymbolContents == SymContentsUnset ||
     329             :             SymbolContents == SymContentsOffset) &&
     330             :            "Cannot set offset for a common/variable symbol");
     331     7789561 :     Offset = Value;
     332     7789561 :     SymbolContents = SymContentsOffset;
     333             :   }
     334             : 
     335             :   /// Return the size of a 'common' symbol.
     336           0 :   uint64_t getCommonSize() const {
     337             :     assert(isCommon() && "Not a 'common' symbol!");
     338           0 :     return CommonSize;
     339             :   }
     340             : 
     341             :   /// Mark this symbol as being 'common'.
     342             :   ///
     343             :   /// \param Size - The size of the symbol.
     344             :   /// \param Align - The alignment of the symbol.
     345             :   void setCommon(uint64_t Size, unsigned Align) {
     346             :     assert(getOffset() == 0);
     347         667 :     CommonSize = Size;
     348         667 :     SymbolContents = SymContentsCommon;
     349             : 
     350             :     assert((!Align || isPowerOf2_32(Align)) &&
     351             :            "Alignment must be a power of 2");
     352         667 :     unsigned Log2Align = Log2_32(Align) + 1;
     353             :     assert(Log2Align < (1U << NumCommonAlignmentBits) &&
     354             :            "Out of range alignment");
     355         667 :     CommonAlignLog2 = Log2Align;
     356             :   }
     357             : 
     358             :   ///  Return the alignment of a 'common' symbol.
     359             :   unsigned getCommonAlignment() const {
     360             :     assert(isCommon() && "Not a 'common' symbol!");
     361         648 :     return CommonAlignLog2 ? (1U << (CommonAlignLog2 - 1)) : 0;
     362             :   }
     363             : 
     364             :   /// Declare this symbol as being 'common'.
     365             :   ///
     366             :   /// \param Size - The size of the symbol.
     367             :   /// \param Align - The alignment of the symbol.
     368             :   /// \return True if symbol was already declared as a different type
     369         597 :   bool declareCommon(uint64_t Size, unsigned Align) {
     370             :     assert(isCommon() || getOffset() == 0);
     371         597 :     if(isCommon()) {
     372           5 :       if(CommonSize != Size || getCommonAlignment() != Align)
     373           1 :        return true;
     374             :     } else
     375             :       setCommon(Size, Align);
     376             :     return false;
     377             :   }
     378             : 
     379             :   /// Is this a 'common' symbol.
     380             :   bool isCommon() const {
     381     1393718 :     return SymbolContents == SymContentsCommon;
     382             :   }
     383             : 
     384   181595734 :   MCFragment *getFragment(bool SetUsed = true) const {
     385   181595734 :     MCFragment *Fragment = FragmentAndHasName.getPointer();
     386   181595734 :     if (Fragment || !isVariable())
     387             :       return Fragment;
     388        5782 :     Fragment = getVariableValue(SetUsed)->findAssociatedFragment();
     389             :     FragmentAndHasName.setPointer(Fragment);
     390        5782 :     return Fragment;
     391             :   }
     392             : 
     393        6297 :   bool isExternal() const { return IsExternal; }
     394      259234 :   void setExternal(bool Value) const { IsExternal = Value; }
     395             : 
     396        1676 :   bool isPrivateExtern() const { return IsPrivateExtern; }
     397          22 :   void setPrivateExtern(bool Value) { IsPrivateExtern = Value; }
     398             : 
     399             :   /// print - Print the value to the stream \p OS.
     400             :   void print(raw_ostream &OS, const MCAsmInfo *MAI) const;
     401             : 
     402             :   /// dump - Print the value to stderr.
     403             :   void dump() const;
     404             : 
     405             : protected:
     406             :   /// Get the (implementation defined) symbol flags.
     407    31072341 :   uint32_t getFlags() const { return Flags; }
     408             : 
     409             :   /// Set the (implementation defined) symbol flags.
     410             :   void setFlags(uint32_t Value) const {
     411             :     assert(Value < (1U << NumFlagsBits) && "Out of range flags");
     412     3220245 :     Flags = Value;
     413             :   }
     414             : 
     415             :   /// Modify the flags via a mask
     416             :   void modifyFlags(uint32_t Value, uint32_t Mask) const {
     417             :     assert(Value < (1U << NumFlagsBits) && "Out of range flags");
     418        1470 :     Flags = (Flags & ~Mask) | Value;
     419             :   }
     420             : };
     421             : 
     422             : inline raw_ostream &operator<<(raw_ostream &OS, const MCSymbol &Sym) {
     423          25 :   Sym.print(OS, nullptr);
     424             :   return OS;
     425             : }
     426             : 
     427             : } // end namespace llvm
     428             : 
     429             : #endif // LLVM_MC_MCSYMBOL_H

Generated by: LCOV version 1.13