Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:44:15

0001 //===- MCSymbol.h - Machine Code Symbols ------------------------*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 //
0009 // This file contains the declaration of the MCSymbol class.
0010 //
0011 //===----------------------------------------------------------------------===//
0012 
0013 #ifndef LLVM_MC_MCSYMBOL_H
0014 #define LLVM_MC_MCSYMBOL_H
0015 
0016 #include "llvm/ADT/StringMapEntry.h"
0017 #include "llvm/ADT/StringRef.h"
0018 #include "llvm/MC/MCExpr.h"
0019 #include "llvm/MC/MCFragment.h"
0020 #include "llvm/MC/MCSymbolTableEntry.h"
0021 #include "llvm/Support/ErrorHandling.h"
0022 #include "llvm/Support/MathExtras.h"
0023 #include <cassert>
0024 #include <cstddef>
0025 #include <cstdint>
0026 
0027 namespace llvm {
0028 
0029 class MCAsmInfo;
0030 class MCContext;
0031 class MCSection;
0032 class raw_ostream;
0033 
0034 /// MCSymbol - Instances of this class represent a symbol name in the MC file,
0035 /// and MCSymbols are created and uniqued by the MCContext class.  MCSymbols
0036 /// should only be constructed with valid names for the object file.
0037 ///
0038 /// If the symbol is defined/emitted into the current translation unit, the
0039 /// Section member is set to indicate what section it lives in.  Otherwise, if
0040 /// it is a reference to an external entity, it has a null section.
0041 class MCSymbol {
0042 protected:
0043   /// The kind of the symbol.  If it is any value other than unset then this
0044   /// class is actually one of the appropriate subclasses of MCSymbol.
0045   enum SymbolKind {
0046     SymbolKindUnset,
0047     SymbolKindCOFF,
0048     SymbolKindELF,
0049     SymbolKindGOFF,
0050     SymbolKindMachO,
0051     SymbolKindWasm,
0052     SymbolKindXCOFF,
0053   };
0054 
0055   /// A symbol can contain an Offset, or Value, or be Common, but never more
0056   /// than one of these.
0057   enum Contents : uint8_t {
0058     SymContentsUnset,
0059     SymContentsOffset,
0060     SymContentsVariable,
0061     SymContentsCommon,
0062     SymContentsTargetCommon, // Index stores the section index
0063   };
0064 
0065   // Special sentinel value for the absolute pseudo fragment.
0066   static MCFragment *AbsolutePseudoFragment;
0067 
0068   /// If a symbol has a Fragment, the section is implied, so we only need
0069   /// one pointer.
0070   /// The special AbsolutePseudoFragment value is for absolute symbols.
0071   /// If this is a variable symbol, this caches the variable value's fragment.
0072   /// FIXME: We might be able to simplify this by having the asm streamer create
0073   /// dummy fragments.
0074   /// If this is a section, then it gives the symbol is defined in. This is null
0075   /// for undefined symbols.
0076   ///
0077   /// If this is a fragment, then it gives the fragment this symbol's value is
0078   /// relative to, if any.
0079   mutable MCFragment *Fragment = nullptr;
0080 
0081   /// True if this symbol is named.  A named symbol will have a pointer to the
0082   /// name allocated in the bytes immediately prior to the MCSymbol.
0083   unsigned HasName : 1;
0084 
0085   /// IsTemporary - True if this is an assembler temporary label, which
0086   /// typically does not survive in the .o file's symbol table.  Usually
0087   /// "Lfoo" or ".foo".
0088   unsigned IsTemporary : 1;
0089 
0090   /// True if this symbol can be redefined.
0091   unsigned IsRedefinable : 1;
0092 
0093   /// IsUsed - True if this symbol has been used.
0094   mutable unsigned IsUsed : 1;
0095 
0096   mutable unsigned IsRegistered : 1;
0097 
0098   /// True if this symbol is visible outside this translation unit. Note: ELF
0099   /// uses binding instead of this bit.
0100   mutable unsigned IsExternal : 1;
0101 
0102   /// Mach-O specific: This symbol is private extern.
0103   mutable unsigned IsPrivateExtern : 1;
0104 
0105   /// This symbol is weak external.
0106   mutable unsigned IsWeakExternal : 1;
0107 
0108   /// LLVM RTTI discriminator. This is actually a SymbolKind enumerator, but is
0109   /// unsigned to avoid sign extension and achieve better bitpacking with MSVC.
0110   unsigned Kind : 3;
0111 
0112   /// True if we have created a relocation that uses this symbol.
0113   mutable unsigned IsUsedInReloc : 1;
0114 
0115   /// This is actually a Contents enumerator, but is unsigned to avoid sign
0116   /// extension and achieve better bitpacking with MSVC.
0117   unsigned SymbolContents : 3;
0118 
0119   /// The alignment of the symbol if it is 'common'.
0120   ///
0121   /// Internally, this is stored as log2(align) + 1.
0122   /// We reserve 5 bits to encode this value which allows the following values
0123   /// 0b00000 -> unset
0124   /// 0b00001 -> 1ULL <<  0 = 1
0125   /// 0b00010 -> 1ULL <<  1 = 2
0126   /// 0b00011 -> 1ULL <<  2 = 4
0127   /// ...
0128   /// 0b11111 -> 1ULL << 30 = 1 GiB
0129   enum : unsigned { NumCommonAlignmentBits = 5 };
0130   unsigned CommonAlignLog2 : NumCommonAlignmentBits;
0131 
0132   /// The Flags field is used by object file implementations to store
0133   /// additional per symbol information which is not easily classified.
0134   enum : unsigned { NumFlagsBits = 16 };
0135   mutable uint32_t Flags : NumFlagsBits;
0136 
0137   /// Index field, for use by the object file implementation.
0138   mutable uint32_t Index = 0;
0139 
0140   union {
0141     /// The offset to apply to the fragment address to form this symbol's value.
0142     uint64_t Offset;
0143 
0144     /// The size of the symbol, if it is 'common'.
0145     uint64_t CommonSize;
0146 
0147     /// If non-null, the value for a variable symbol.
0148     const MCExpr *Value;
0149   };
0150 
0151   // MCContext creates and uniques these.
0152   friend class MCExpr;
0153   friend class MCContext;
0154 
0155   /// The name for a symbol.
0156   /// MCSymbol contains a uint64_t so is probably aligned to 8.  On a 32-bit
0157   /// system, the name is a pointer so isn't going to satisfy the 8 byte
0158   /// alignment of uint64_t.  Account for that here.
0159   using NameEntryStorageTy = union {
0160     const MCSymbolTableEntry *NameEntry;
0161     uint64_t AlignmentPadding;
0162   };
0163 
0164   MCSymbol(SymbolKind Kind, const MCSymbolTableEntry *Name, bool isTemporary)
0165       : IsTemporary(isTemporary), IsRedefinable(false), IsUsed(false),
0166         IsRegistered(false), IsExternal(false), IsPrivateExtern(false),
0167         IsWeakExternal(false), Kind(Kind), IsUsedInReloc(false),
0168         SymbolContents(SymContentsUnset), CommonAlignLog2(0), Flags(0) {
0169     Offset = 0;
0170     HasName = !!Name;
0171     if (Name)
0172       getNameEntryPtr() = Name;
0173   }
0174 
0175   // Provide custom new/delete as we will only allocate space for a name
0176   // if we need one.
0177   void *operator new(size_t s, const MCSymbolTableEntry *Name, MCContext &Ctx);
0178 
0179 private:
0180   void operator delete(void *);
0181   /// Placement delete - required by std, but never called.
0182   void operator delete(void*, unsigned) {
0183     llvm_unreachable("Constructor throws?");
0184   }
0185   /// Placement delete - required by std, but never called.
0186   void operator delete(void*, unsigned, bool) {
0187     llvm_unreachable("Constructor throws?");
0188   }
0189 
0190   /// Get a reference to the name field.  Requires that we have a name
0191   const MCSymbolTableEntry *&getNameEntryPtr() {
0192     assert(HasName && "Name is required");
0193     NameEntryStorageTy *Name = reinterpret_cast<NameEntryStorageTy *>(this);
0194     return (*(Name - 1)).NameEntry;
0195   }
0196   const MCSymbolTableEntry *&getNameEntryPtr() const {
0197     return const_cast<MCSymbol*>(this)->getNameEntryPtr();
0198   }
0199 
0200 public:
0201   MCSymbol(const MCSymbol &) = delete;
0202   MCSymbol &operator=(const MCSymbol &) = delete;
0203 
0204   /// getName - Get the symbol name.
0205   StringRef getName() const {
0206     if (!HasName)
0207       return StringRef();
0208 
0209     return getNameEntryPtr()->first();
0210   }
0211 
0212   bool isRegistered() const { return IsRegistered; }
0213   void setIsRegistered(bool Value) const { IsRegistered = Value; }
0214 
0215   void setUsedInReloc() const { IsUsedInReloc = true; }
0216   bool isUsedInReloc() const { return IsUsedInReloc; }
0217 
0218   /// \name Accessors
0219   /// @{
0220 
0221   /// isTemporary - Check if this is an assembler temporary symbol.
0222   bool isTemporary() const { return IsTemporary; }
0223 
0224   /// isUsed - Check if this is used.
0225   bool isUsed() const { return IsUsed; }
0226 
0227   /// Check if this symbol is redefinable.
0228   bool isRedefinable() const { return IsRedefinable; }
0229   /// Mark this symbol as redefinable.
0230   void setRedefinable(bool Value) { IsRedefinable = Value; }
0231   /// Prepare this symbol to be redefined.
0232   void redefineIfPossible() {
0233     if (IsRedefinable) {
0234       if (SymbolContents == SymContentsVariable) {
0235         Value = nullptr;
0236         SymbolContents = SymContentsUnset;
0237       }
0238       setUndefined();
0239       IsRedefinable = false;
0240     }
0241   }
0242 
0243   /// @}
0244   /// \name Associated Sections
0245   /// @{
0246 
0247   /// isDefined - Check if this symbol is defined (i.e., it has an address).
0248   ///
0249   /// Defined symbols are either absolute or in some section.
0250   bool isDefined() const { return !isUndefined(); }
0251 
0252   /// isInSection - Check if this symbol is defined in some section (i.e., it
0253   /// is defined but not absolute).
0254   bool isInSection() const {
0255     return isDefined() && !isAbsolute();
0256   }
0257 
0258   /// isUndefined - Check if this symbol undefined (i.e., implicitly defined).
0259   bool isUndefined(bool SetUsed = true) const {
0260     return getFragment(SetUsed) == nullptr;
0261   }
0262 
0263   /// isAbsolute - Check if this is an absolute symbol.
0264   bool isAbsolute() const {
0265     return getFragment() == AbsolutePseudoFragment;
0266   }
0267 
0268   /// Get the section associated with a defined, non-absolute symbol.
0269   MCSection &getSection() const {
0270     assert(isInSection() && "Invalid accessor!");
0271     return *getFragment()->getParent();
0272   }
0273 
0274   /// Mark the symbol as defined in the fragment \p F.
0275   void setFragment(MCFragment *F) const {
0276     assert(!isVariable() && "Cannot set fragment of variable");
0277     Fragment = F;
0278   }
0279 
0280   /// Mark the symbol as undefined.
0281   void setUndefined() { Fragment = nullptr; }
0282 
0283   bool isELF() const { return Kind == SymbolKindELF; }
0284 
0285   bool isCOFF() const { return Kind == SymbolKindCOFF; }
0286 
0287   bool isGOFF() const { return Kind == SymbolKindGOFF; }
0288 
0289   bool isMachO() const { return Kind == SymbolKindMachO; }
0290 
0291   bool isWasm() const { return Kind == SymbolKindWasm; }
0292 
0293   bool isXCOFF() const { return Kind == SymbolKindXCOFF; }
0294 
0295   /// @}
0296   /// \name Variable Symbols
0297   /// @{
0298 
0299   /// isVariable - Check if this is a variable symbol.
0300   bool isVariable() const {
0301     return SymbolContents == SymContentsVariable;
0302   }
0303 
0304   /// getVariableValue - Get the value for variable symbols.
0305   const MCExpr *getVariableValue(bool SetUsed = true) const {
0306     assert(isVariable() && "Invalid accessor!");
0307     IsUsed |= SetUsed;
0308     return Value;
0309   }
0310 
0311   void setVariableValue(const MCExpr *Value);
0312 
0313   /// @}
0314 
0315   /// Get the (implementation defined) index.
0316   uint32_t getIndex() const {
0317     return Index;
0318   }
0319 
0320   /// Set the (implementation defined) index.
0321   void setIndex(uint32_t Value) const {
0322     Index = Value;
0323   }
0324 
0325   bool isUnset() const { return SymbolContents == SymContentsUnset; }
0326 
0327   uint64_t getOffset() const {
0328     assert((SymbolContents == SymContentsUnset ||
0329             SymbolContents == SymContentsOffset) &&
0330            "Cannot get offset for a common/variable symbol");
0331     return Offset;
0332   }
0333   void setOffset(uint64_t Value) {
0334     assert((SymbolContents == SymContentsUnset ||
0335             SymbolContents == SymContentsOffset) &&
0336            "Cannot set offset for a common/variable symbol");
0337     Offset = Value;
0338     SymbolContents = SymContentsOffset;
0339   }
0340 
0341   /// Return the size of a 'common' symbol.
0342   uint64_t getCommonSize() const {
0343     assert(isCommon() && "Not a 'common' symbol!");
0344     return CommonSize;
0345   }
0346 
0347   /// Mark this symbol as being 'common'.
0348   ///
0349   /// \param Size - The size of the symbol.
0350   /// \param Alignment - The alignment of the symbol.
0351   /// \param Target - Is the symbol a target-specific common-like symbol.
0352   void setCommon(uint64_t Size, Align Alignment, bool Target = false) {
0353     assert(getOffset() == 0);
0354     CommonSize = Size;
0355     SymbolContents = Target ? SymContentsTargetCommon : SymContentsCommon;
0356 
0357     unsigned Log2Align = encode(Alignment);
0358     assert(Log2Align < (1U << NumCommonAlignmentBits) &&
0359            "Out of range alignment");
0360     CommonAlignLog2 = Log2Align;
0361   }
0362 
0363   ///  Return the alignment of a 'common' symbol.
0364   MaybeAlign getCommonAlignment() const {
0365     assert(isCommon() && "Not a 'common' symbol!");
0366     return decodeMaybeAlign(CommonAlignLog2);
0367   }
0368 
0369   /// Declare this symbol as being 'common'.
0370   ///
0371   /// \param Size - The size of the symbol.
0372   /// \param Alignment - The alignment of the symbol.
0373   /// \param Target - Is the symbol a target-specific common-like symbol.
0374   /// \return True if symbol was already declared as a different type
0375   bool declareCommon(uint64_t Size, Align Alignment, bool Target = false) {
0376     assert(isCommon() || getOffset() == 0);
0377     if(isCommon()) {
0378       if (CommonSize != Size || getCommonAlignment() != Alignment ||
0379           isTargetCommon() != Target)
0380         return true;
0381     } else
0382       setCommon(Size, Alignment, Target);
0383     return false;
0384   }
0385 
0386   /// Is this a 'common' symbol.
0387   bool isCommon() const {
0388     return SymbolContents == SymContentsCommon ||
0389            SymbolContents == SymContentsTargetCommon;
0390   }
0391 
0392   /// Is this a target-specific common-like symbol.
0393   bool isTargetCommon() const {
0394     return SymbolContents == SymContentsTargetCommon;
0395   }
0396 
0397   MCFragment *getFragment(bool SetUsed = true) const {
0398     if (Fragment || !isVariable() || isWeakExternal())
0399       return Fragment;
0400     // If the symbol is a non-weak alias, get information about
0401     // the aliasee. (Don't try to resolve weak aliases.)
0402     Fragment = getVariableValue(SetUsed)->findAssociatedFragment();
0403     return Fragment;
0404   }
0405 
0406   // For ELF, use MCSymbolELF::setBinding instead.
0407   bool isExternal() const { return IsExternal; }
0408   void setExternal(bool Value) const { IsExternal = Value; }
0409 
0410   // COFF-specific
0411   bool isWeakExternal() const { return IsWeakExternal; }
0412 
0413   /// print - Print the value to the stream \p OS.
0414   void print(raw_ostream &OS, const MCAsmInfo *MAI) const;
0415 
0416   /// dump - Print the value to stderr.
0417   void dump() const;
0418 
0419 protected:
0420   /// Get the (implementation defined) symbol flags.
0421   uint32_t getFlags() const { return Flags; }
0422 
0423   /// Set the (implementation defined) symbol flags.
0424   void setFlags(uint32_t Value) const {
0425     assert(Value < (1U << NumFlagsBits) && "Out of range flags");
0426     Flags = Value;
0427   }
0428 
0429   /// Modify the flags via a mask
0430   void modifyFlags(uint32_t Value, uint32_t Mask) const {
0431     assert(Value < (1U << NumFlagsBits) && "Out of range flags");
0432     Flags = (Flags & ~Mask) | Value;
0433   }
0434 };
0435 
0436 inline raw_ostream &operator<<(raw_ostream &OS, const MCSymbol &Sym) {
0437   Sym.print(OS, nullptr);
0438   return OS;
0439 }
0440 
0441 } // end namespace llvm
0442 
0443 #endif // LLVM_MC_MCSYMBOL_H