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