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 27namespace llvm { 28 29class MCAsmInfo; 30class MCContext; 31class MCExpr; 32class MCSection; 33class 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. 42class MCSymbol { 43protected: 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 : IsTemporary(isTemporary), IsRedefinable(false), IsUsed(false), 155 IsRegistered(false), IsExternal(false), IsPrivateExtern(false), 156 Kind(Kind), IsUsedInReloc(false), SymbolContents(SymContentsUnset), 157 CommonAlignLog2(0), Flags(0) { 158 Offset = 0; 159 FragmentAndHasName.setInt(!!Name); 160 if (Name) 161 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 169private: 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 if (MCFragment *F = getFragment(SetUsed)) { 182 assert(F != AbsolutePseudoFragment); 183 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 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 198public: 199 MCSymbol(const MCSymbol &) = delete; 200 MCSymbol &operator=(const MCSymbol &) = delete; 201 202 /// getName - Get the symbol name. 203 StringRef getName() const { 204 if (!FragmentAndHasName.getInt()) 205 return StringRef(); 206 207 return getNameEntryPtr()->first(); 208 } 209 210 bool isRegistered() const { return IsRegistered; } 211 void setIsRegistered(bool Value) const { IsRegistered = Value; } 212 213 void setUsedInReloc() const { IsUsedInReloc = true; } 214 bool isUsedInReloc() const { return IsUsedInReloc; } 215 216 /// \name Accessors 217 /// @{ 218 219 /// isTemporary - Check if this is an assembler temporary symbol. 220 bool isTemporary() const { return IsTemporary; } 221 222 /// isUsed - Check if this is used. 223 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 void setRedefinable(bool Value) { IsRedefinable = Value; } 230 /// \brief Prepare this symbol to be redefined. 231 void redefineIfPossible() { 232 if (IsRedefinable) { 233 if (SymbolContents == SymContentsVariable) { 234 Value = nullptr; 235 SymbolContents = SymContentsUnset; 236 } 237 setUndefined(); 238 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 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 bool isInSection(bool SetUsed = true) const { 256 return isDefined(SetUsed) && !isAbsolute(SetUsed); 257 } 258 259 /// isUndefined - Check if this symbol undefined (i.e., implicitly defined). 260 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 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 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 FragmentAndHasName.setPointer(F); 277 } 278 279 /// Mark the symbol as undefined. 280 void setUndefined() { FragmentAndHasName.setPointer(nullptr); } 281 282 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 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 IsUsed |= SetUsed; 303 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 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 Offset = Value; 331 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 CommonSize = Size; 347 SymbolContents = SymContentsCommon; 348 349 assert((!Align || isPowerOf2_32(Align)) && 350 "Alignment must be a power of 2"); 351 unsigned Log2Align = Log2_32(Align) + 1; 352 assert(Log2Align < (1U << NumCommonAlignmentBits) && 353 "Out of range alignment"); 354 CommonAlignLog2 = Log2Align; 355 } 356 357 /// Return the alignment of a 'common' symbol. 358 unsigned getCommonAlignment() const { 359 assert(isCommon() && "Not a 'common' symbol!"); 360 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 bool declareCommon(uint64_t Size, unsigned Align) { 369 assert(isCommon() || getOffset() == 0); 370 if(isCommon()) { 371 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 return SymbolContents == SymContentsCommon; 381 } 382 383 MCFragment *getFragment(bool SetUsed = true) const { 384 MCFragment *Fragment = FragmentAndHasName.getPointer(); 385 if (Fragment || !isVariable()) 386 return Fragment; 387 Fragment = getVariableValue(SetUsed)->findAssociatedFragment(); 388 FragmentAndHasName.setPointer(Fragment); 389 return Fragment; 390 } 391 392 bool isExternal() const { return IsExternal; } 393 void setExternal(bool Value) const { IsExternal = Value; } 394 395 bool isPrivateExtern() const { return IsPrivateExtern; } 396 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 404protected: 405 /// Get the (implementation defined) symbol flags. 406 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 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 Flags = (Flags & ~Mask) | Value; 418 } 419}; 420 421inline raw_ostream &operator<<(raw_ostream &OS, const MCSymbol &Sym) { 422 Sym.print(OS, nullptr); 423 return OS; 424} 425 426} // end namespace llvm 427 428#endif // LLVM_MC_MCSYMBOL_H 429