Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 1 | //===- MCSymbol.h - Machine Code Symbols ------------------------*- C++ -*-===// |
| 2 | // |
Andrew Walbran | 16937d0 | 2019-10-22 13:54:20 +0100 | [diff] [blame] | 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 |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 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" |
Olivier Deprez | f4ef2d0 | 2021-04-20 13:36:24 +0200 | [diff] [blame] | 19 | #include "llvm/MC/MCExpr.h" |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 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; |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 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, |
Andrew Walbran | 3d2c197 | 2020-04-07 12:24:26 +0100 | [diff] [blame] | 51 | SymbolKindXCOFF, |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 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, |
Andrew Walbran | 3d2c197 | 2020-04-07 12:24:26 +0100 | [diff] [blame] | 61 | SymContentsTargetCommon, // Index stores the section index |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 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 | |
Andrew Scull | cdfcccc | 2018-10-05 20:58:37 +0100 | [diff] [blame] | 89 | /// True if this symbol can be redefined. |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 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 | |
Olivier Deprez | f4ef2d0 | 2021-04-20 13:36:24 +0200 | [diff] [blame] | 97 | /// True if this symbol is visible outside this translation unit. Note: ELF |
| 98 | /// uses binding instead of this bit. |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 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. |
Andrew Walbran | 3d2c197 | 2020-04-07 12:24:26 +0100 | [diff] [blame] | 113 | unsigned SymbolContents : 3; |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 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 | |
Andrew Scull | cdfcccc | 2018-10-05 20:58:37 +0100 | [diff] [blame] | 146 | /// The name for a symbol. |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 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 | |
| 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 *); |
Andrew Scull | cdfcccc | 2018-10-05 20:58:37 +0100 | [diff] [blame] | 173 | /// Placement delete - required by std, but never called. |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 174 | void operator delete(void*, unsigned) { |
| 175 | llvm_unreachable("Constructor throws?"); |
| 176 | } |
Andrew Scull | cdfcccc | 2018-10-05 20:58:37 +0100 | [diff] [blame] | 177 | /// Placement delete - required by std, but never called. |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 178 | void operator delete(void*, unsigned, bool) { |
| 179 | llvm_unreachable("Constructor throws?"); |
| 180 | } |
| 181 | |
Andrew Scull | cdfcccc | 2018-10-05 20:58:37 +0100 | [diff] [blame] | 182 | /// Get a reference to the name field. Requires that we have a name |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 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 | } |
| 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. |
| 197 | StringRef getName() const { |
| 198 | if (!FragmentAndHasName.getInt()) |
| 199 | return StringRef(); |
| 200 | |
| 201 | return getNameEntryPtr()->first(); |
| 202 | } |
| 203 | |
| 204 | bool isRegistered() const { return IsRegistered; } |
| 205 | void setIsRegistered(bool Value) const { IsRegistered = Value; } |
| 206 | |
| 207 | void setUsedInReloc() const { IsUsedInReloc = true; } |
| 208 | bool isUsedInReloc() const { return IsUsedInReloc; } |
| 209 | |
| 210 | /// \name Accessors |
| 211 | /// @{ |
| 212 | |
| 213 | /// isTemporary - Check if this is an assembler temporary symbol. |
| 214 | bool isTemporary() const { return IsTemporary; } |
| 215 | |
| 216 | /// isUsed - Check if this is used. |
| 217 | bool isUsed() const { return IsUsed; } |
| 218 | |
Andrew Scull | cdfcccc | 2018-10-05 20:58:37 +0100 | [diff] [blame] | 219 | /// Check if this symbol is redefinable. |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 220 | bool isRedefinable() const { return IsRedefinable; } |
Andrew Scull | cdfcccc | 2018-10-05 20:58:37 +0100 | [diff] [blame] | 221 | /// Mark this symbol as redefinable. |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 222 | void setRedefinable(bool Value) { IsRedefinable = Value; } |
Andrew Scull | cdfcccc | 2018-10-05 20:58:37 +0100 | [diff] [blame] | 223 | /// Prepare this symbol to be redefined. |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 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. |
| 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). |
| 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. |
| 256 | bool isAbsolute() const { |
| 257 | return getFragment() == AbsolutePseudoFragment; |
| 258 | } |
| 259 | |
| 260 | /// Get the section associated with a defined, non-absolute symbol. |
| 261 | MCSection &getSection() const { |
| 262 | assert(isInSection() && "Invalid accessor!"); |
Olivier Deprez | f4ef2d0 | 2021-04-20 13:36:24 +0200 | [diff] [blame] | 263 | return *getFragment()->getParent(); |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 264 | } |
| 265 | |
| 266 | /// Mark the symbol as defined in the fragment \p 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. |
| 273 | void setUndefined() { FragmentAndHasName.setPointer(nullptr); } |
| 274 | |
| 275 | bool isELF() const { return Kind == SymbolKindELF; } |
| 276 | |
| 277 | bool isCOFF() const { return Kind == SymbolKindCOFF; } |
| 278 | |
| 279 | bool isMachO() const { return Kind == SymbolKindMachO; } |
| 280 | |
| 281 | bool isWasm() const { return Kind == SymbolKindWasm; } |
| 282 | |
Andrew Walbran | 3d2c197 | 2020-04-07 12:24:26 +0100 | [diff] [blame] | 283 | bool isXCOFF() const { return Kind == SymbolKindXCOFF; } |
| 284 | |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 285 | /// @} |
| 286 | /// \name Variable Symbols |
| 287 | /// @{ |
| 288 | |
| 289 | /// isVariable - Check if this is a variable symbol. |
| 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. |
| 306 | uint32_t getIndex() const { |
| 307 | return Index; |
| 308 | } |
| 309 | |
| 310 | /// Set the (implementation defined) index. |
| 311 | void setIndex(uint32_t Value) const { |
| 312 | Index = Value; |
| 313 | } |
| 314 | |
Andrew Scull | cdfcccc | 2018-10-05 20:58:37 +0100 | [diff] [blame] | 315 | bool isUnset() const { return SymbolContents == SymContentsUnset; } |
| 316 | |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 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 | } |
| 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. |
| 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. |
Andrew Walbran | 3d2c197 | 2020-04-07 12:24:26 +0100 | [diff] [blame] | 341 | /// \param Target - Is the symbol a target-specific common-like symbol. |
| 342 | void setCommon(uint64_t Size, unsigned Align, bool Target = false) { |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 343 | assert(getOffset() == 0); |
| 344 | CommonSize = Size; |
Andrew Walbran | 3d2c197 | 2020-04-07 12:24:26 +0100 | [diff] [blame] | 345 | SymbolContents = Target ? SymContentsTargetCommon : SymContentsCommon; |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 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. |
| 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. |
Andrew Walbran | 3d2c197 | 2020-04-07 12:24:26 +0100 | [diff] [blame] | 365 | /// \param Target - Is the symbol a target-specific common-like symbol. |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 366 | /// \return True if symbol was already declared as a different type |
Andrew Walbran | 3d2c197 | 2020-04-07 12:24:26 +0100 | [diff] [blame] | 367 | bool declareCommon(uint64_t Size, unsigned Align, bool Target = false) { |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 368 | assert(isCommon() || getOffset() == 0); |
| 369 | if(isCommon()) { |
Andrew Walbran | 3d2c197 | 2020-04-07 12:24:26 +0100 | [diff] [blame] | 370 | if (CommonSize != Size || getCommonAlignment() != Align || |
| 371 | isTargetCommon() != Target) |
| 372 | return true; |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 373 | } else |
Andrew Walbran | 3d2c197 | 2020-04-07 12:24:26 +0100 | [diff] [blame] | 374 | setCommon(Size, Align, Target); |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 375 | return false; |
| 376 | } |
| 377 | |
| 378 | /// Is this a 'common' symbol. |
| 379 | bool isCommon() const { |
Andrew Walbran | 3d2c197 | 2020-04-07 12:24:26 +0100 | [diff] [blame] | 380 | return SymbolContents == SymContentsCommon || |
| 381 | SymbolContents == SymContentsTargetCommon; |
| 382 | } |
| 383 | |
| 384 | /// Is this a target-specific common-like symbol. |
| 385 | bool isTargetCommon() const { |
| 386 | return SymbolContents == SymContentsTargetCommon; |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 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 | |
| 398 | bool isExternal() const { return IsExternal; } |
| 399 | void setExternal(bool Value) const { IsExternal = Value; } |
| 400 | |
| 401 | bool isPrivateExtern() const { return IsPrivateExtern; } |
| 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. |
| 412 | uint32_t getFlags() const { return Flags; } |
| 413 | |
| 414 | /// Set the (implementation defined) symbol flags. |
| 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 |
| 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 |