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