LCOV - code coverage report
Current view: top level - include/llvm/MC - MCSymbol.h (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 63 63 100.0 %
Date: 2017-09-14 15:23:50 Functions: 3 3 100.0 %
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             :   /// \brief 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             :   /// \brief 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     2940426 :       : IsTemporary(isTemporary), IsRedefinable(false), IsUsed(false),
     155             :         IsRegistered(false), IsExternal(false), IsPrivateExtern(false),
     156             :         Kind(Kind), IsUsedInReloc(false), SymbolContents(SymContentsUnset),
     157     5880852 :         CommonAlignLog2(0), Flags(0) {
     158     2940426 :     Offset = 0;
     159     5880852 :     FragmentAndHasName.setInt(!!Name);
     160     2940426 :     if (Name)
     161     1813103 :       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             :   /// \brief Placement delete - required by std, but never called.
     172             :   void operator delete(void*, unsigned) {
     173             :     llvm_unreachable("Constructor throws?");
     174             :   }
     175             :   /// \brief 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(bool SetUsed = true) const {
     181     3996987 :     if (MCFragment *F = getFragment(SetUsed)) {
     182             :       assert(F != AbsolutePseudoFragment);
     183     3996987 :       return F->getParent();
     184             :     }
     185             :     return nullptr;
     186             :   }
     187             : 
     188             :   /// \brief 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     3752456 :     NameEntryStorageTy *Name = reinterpret_cast<NameEntryStorageTy *>(this);
     192             :     return (*(Name - 1)).NameEntry;
     193             :   }
     194             :   const StringMapEntry<bool> *&getNameEntryPtr() const {
     195     1939353 :     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     4597526 :     if (!FragmentAndHasName.getInt())
     205             :       return StringRef();
     206             : 
     207     1939353 :     return getNameEntryPtr()->first();
     208             :   }
     209             : 
     210     3283428 :   bool isRegistered() const { return IsRegistered; }
     211     1648159 :   void setIsRegistered(bool Value) const { IsRegistered = Value; }
     212             : 
     213     1273076 :   void setUsedInReloc() const { IsUsedInReloc = true; }
     214     1677803 :   bool isUsedInReloc() const { return IsUsedInReloc; }
     215             : 
     216             :   /// \name Accessors
     217             :   /// @{
     218             : 
     219             :   /// isTemporary - Check if this is an assembler temporary symbol.
     220     1740380 :   bool isTemporary() const { return IsTemporary; }
     221             : 
     222             :   /// isUsed - Check if this is used.
     223         281 :   bool isUsed() const { return IsUsed; }
     224             :   void setUsed(bool Value) const { IsUsed |= Value; }
     225             : 
     226             :   /// \brief Check if this symbol is redefinable.
     227             :   bool isRedefinable() const { return IsRedefinable; }
     228             :   /// \brief Mark this symbol as redefinable.
     229         545 :   void setRedefinable(bool Value) { IsRedefinable = Value; }
     230             :   /// \brief Prepare this symbol to be redefined.
     231             :   void redefineIfPossible() {
     232     1795346 :     if (IsRedefinable) {
     233           3 :       if (SymbolContents == SymContentsVariable) {
     234           3 :         Value = nullptr;
     235           3 :         SymbolContents = SymContentsUnset;
     236             :       }
     237           3 :       setUndefined();
     238           3 :       IsRedefinable = false;
     239             :     }
     240             :   }
     241             : 
     242             :   /// @}
     243             :   /// \name Associated Sections
     244             :   /// @{
     245             : 
     246             :   /// isDefined - Check if this symbol is defined (i.e., it has an address).
     247             :   ///
     248             :   /// Defined symbols are either absolute or in some section.
     249             :   bool isDefined(bool SetUsed = true) const {
     250    16454125 :     return getFragment(SetUsed) != nullptr;
     251             :   }
     252             : 
     253             :   /// isInSection - Check if this symbol is defined in some section (i.e., it
     254             :   /// is defined but not absolute).
     255     1729950 :   bool isInSection(bool SetUsed = true) const {
     256     5171546 :     return isDefined(SetUsed) && !isAbsolute(SetUsed);
     257             :   }
     258             : 
     259             :   /// isUndefined - Check if this symbol undefined (i.e., implicitly defined).
     260    22156640 :   bool isUndefined(bool SetUsed = true) const { return !isDefined(SetUsed); }
     261             : 
     262             :   /// isAbsolute - Check if this is an absolute symbol.
     263             :   bool isAbsolute(bool SetUsed = true) const {
     264     1830035 :     return getFragment(SetUsed) == AbsolutePseudoFragment;
     265             :   }
     266             : 
     267             :   /// Get the section associated with a defined, non-absolute symbol.
     268             :   MCSection &getSection(bool SetUsed = true) const {
     269             :     assert(isInSection(SetUsed) && "Invalid accessor!");
     270     7993973 :     return *getSectionPtr(SetUsed);
     271             :   }
     272             : 
     273             :   /// Mark the symbol as defined in the fragment \p F.
     274             :   void setFragment(MCFragment *F) const {
     275             :     assert(!isVariable() && "Cannot set fragment of variable");
     276     8235652 :     FragmentAndHasName.setPointer(F);
     277             :   }
     278             : 
     279             :   /// Mark the symbol as undefined.
     280       14152 :   void setUndefined() { FragmentAndHasName.setPointer(nullptr); }
     281             : 
     282        1035 :   bool isELF() const { return Kind == SymbolKindELF; }
     283             : 
     284             :   bool isCOFF() const { return Kind == SymbolKindCOFF; }
     285             : 
     286             :   bool isMachO() const { return Kind == SymbolKindMachO; }
     287             : 
     288             :   bool isWasm() const { return Kind == SymbolKindWasm; }
     289             : 
     290             :   /// @}
     291             :   /// \name Variable Symbols
     292             :   /// @{
     293             : 
     294             :   /// isVariable - Check if this is a variable symbol.
     295             :   bool isVariable() const {
     296    18880560 :     return SymbolContents == SymContentsVariable;
     297             :   }
     298             : 
     299             :   /// getVariableValue - Get the value for variable symbols.
     300             :   const MCExpr *getVariableValue(bool SetUsed = true) const {
     301             :     assert(isVariable() && "Invalid accessor!");
     302       15993 :     IsUsed |= SetUsed;
     303       15993 :     return Value;
     304             :   }
     305             : 
     306             :   void setVariableValue(const MCExpr *Value);
     307             : 
     308             :   /// @}
     309             : 
     310             :   /// Get the (implementation defined) index.
     311             :   uint32_t getIndex() const {
     312             :     return Index;
     313             :   }
     314             : 
     315             :   /// Set the (implementation defined) index.
     316             :   void setIndex(uint32_t Value) const {
     317      118520 :     Index = Value;
     318             :   }
     319             : 
     320             :   uint64_t getOffset() const {
     321             :     assert((SymbolContents == SymContentsUnset ||
     322             :             SymbolContents == SymContentsOffset) &&
     323             :            "Cannot get offset for a common/variable symbol");
     324             :     return Offset;
     325             :   }
     326             :   void setOffset(uint64_t Value) {
     327             :     assert((SymbolContents == SymContentsUnset ||
     328             :             SymbolContents == SymContentsOffset) &&
     329             :            "Cannot set offset for a common/variable symbol");
     330     1266002 :     Offset = Value;
     331     1266002 :     SymbolContents = SymContentsOffset;
     332             :   }
     333             : 
     334             :   /// Return the size of a 'common' symbol.
     335             :   uint64_t getCommonSize() const {
     336             :     assert(isCommon() && "Not a 'common' symbol!");
     337             :     return CommonSize;
     338             :   }
     339             : 
     340             :   /// Mark this symbol as being 'common'.
     341             :   ///
     342             :   /// \param Size - The size of the symbol.
     343             :   /// \param Align - The alignment of the symbol.
     344             :   void setCommon(uint64_t Size, unsigned Align) {
     345             :     assert(getOffset() == 0);
     346         247 :     CommonSize = Size;
     347         247 :     SymbolContents = SymContentsCommon;
     348             : 
     349             :     assert((!Align || isPowerOf2_32(Align)) &&
     350             :            "Alignment must be a power of 2");
     351         247 :     unsigned Log2Align = Log2_32(Align) + 1;
     352             :     assert(Log2Align < (1U << NumCommonAlignmentBits) &&
     353             :            "Out of range alignment");
     354         247 :     CommonAlignLog2 = Log2Align;
     355             :   }
     356             : 
     357             :   ///  Return the alignment of a 'common' symbol.
     358             :   unsigned getCommonAlignment() const {
     359             :     assert(isCommon() && "Not a 'common' symbol!");
     360         411 :     return CommonAlignLog2 ? (1U << (CommonAlignLog2 - 1)) : 0;
     361             :   }
     362             : 
     363             :   /// Declare this symbol as being 'common'.
     364             :   ///
     365             :   /// \param Size - The size of the symbol.
     366             :   /// \param Align - The alignment of the symbol.
     367             :   /// \return True if symbol was already declared as a different type
     368         183 :   bool declareCommon(uint64_t Size, unsigned Align) {
     369             :     assert(isCommon() || getOffset() == 0);
     370         183 :     if(isCommon()) {
     371           5 :       if(CommonSize != Size || getCommonAlignment() != Align)
     372             :        return true;
     373             :     } else
     374             :       setCommon(Size, Align);
     375             :     return false;
     376             :   }
     377             : 
     378             :   /// Is this a 'common' symbol.
     379             :   bool isCommon() const {
     380      351638 :     return SymbolContents == SymContentsCommon;
     381             :   }
     382             : 
     383    34088245 :   MCFragment *getFragment(bool SetUsed = true) const {
     384    68176490 :     MCFragment *Fragment = FragmentAndHasName.getPointer();
     385    36099130 :     if (Fragment || !isVariable())
     386             :       return Fragment;
     387        6008 :     Fragment = getVariableValue(SetUsed)->findAssociatedFragment();
     388        6008 :     FragmentAndHasName.setPointer(Fragment);
     389        3004 :     return Fragment;
     390             :   }
     391             : 
     392        5209 :   bool isExternal() const { return IsExternal; }
     393       13990 :   void setExternal(bool Value) const { IsExternal = Value; }
     394             : 
     395        1497 :   bool isPrivateExtern() const { return IsPrivateExtern; }
     396          17 :   void setPrivateExtern(bool Value) { IsPrivateExtern = Value; }
     397             : 
     398             :   /// print - Print the value to the stream \p OS.
     399             :   void print(raw_ostream &OS, const MCAsmInfo *MAI) const;
     400             : 
     401             :   /// dump - Print the value to stderr.
     402             :   void dump() const;
     403             : 
     404             : protected:
     405             :   /// Get the (implementation defined) symbol flags.
     406    16634735 :   uint32_t getFlags() const { return Flags; }
     407             : 
     408             :   /// Set the (implementation defined) symbol flags.
     409             :   void setFlags(uint32_t Value) const {
     410             :     assert(Value < (1U << NumFlagsBits) && "Out of range flags");
     411     3808825 :     Flags = Value;
     412             :   }
     413             : 
     414             :   /// Modify the flags via a mask
     415             :   void modifyFlags(uint32_t Value, uint32_t Mask) const {
     416             :     assert(Value < (1U << NumFlagsBits) && "Out of range flags");
     417       11316 :     Flags = (Flags & ~Mask) | Value;
     418             :   }
     419             : };
     420             : 
     421             : inline raw_ostream &operator<<(raw_ostream &OS, const MCSymbol &Sym) {
     422          14 :   Sym.print(OS, nullptr);
     423             :   return OS;
     424             : }
     425             : 
     426             : } // end namespace llvm
     427             : 
     428             : #endif // LLVM_MC_MCSYMBOL_H

Generated by: LCOV version 1.13