/Users/buildslave/jenkins/sharedspace/clang-stage2-coverage-R@2/llvm/include/llvm/MC/MCSymbol.h
Line | Count | Source (jump to first uncovered line) |
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 | | |
27 | | namespace llvm { |
28 | | |
29 | | class MCAsmInfo; |
30 | | class MCContext; |
31 | | class MCExpr; |
32 | | class MCSection; |
33 | | class 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. |
42 | | class MCSymbol { |
43 | | protected: |
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 | 8.63M | CommonAlignLog2(0), Flags(0) { |
158 | 8.63M | Offset = 0; |
159 | 8.63M | FragmentAndHasName.setInt(!!Name); |
160 | 8.63M | if (Name) |
161 | 4.94M | getNameEntryPtr() = Name; |
162 | 8.63M | } |
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 | | |
169 | | private: |
170 | | void operator delete(void *); |
171 | | /// \brief Placement delete - required by std, but never called. |
172 | 0 | void operator delete(void*, unsigned) { |
173 | 0 | llvm_unreachable("Constructor throws?"); |
174 | 0 | } |
175 | | /// \brief Placement delete - required by std, but never called. |
176 | 0 | void operator delete(void*, unsigned, bool) { |
177 | 0 | llvm_unreachable("Constructor throws?"); |
178 | 0 | } |
179 | | |
180 | 6.00M | MCSection *getSectionPtr(bool SetUsed = true) const { |
181 | 6.00M | if (MCFragment *F6.00M = getFragment(SetUsed)) { |
182 | 6.00M | assert(F != AbsolutePseudoFragment); |
183 | 6.00M | return F->getParent(); |
184 | 6.00M | } |
185 | 1 | return nullptr; |
186 | 6.00M | } |
187 | | |
188 | | /// \brief Get a reference to the name field. Requires that we have a name |
189 | 21.3M | const StringMapEntry<bool> *&getNameEntryPtr() { |
190 | 21.3M | assert(FragmentAndHasName.getInt() && "Name is required"); |
191 | 21.3M | NameEntryStorageTy *Name = reinterpret_cast<NameEntryStorageTy *>(this); |
192 | 21.3M | return (*(Name - 1)).NameEntry; |
193 | 21.3M | } |
194 | 16.3M | const StringMapEntry<bool> *&getNameEntryPtr() const { |
195 | 16.3M | return const_cast<MCSymbol*>(this)->getNameEntryPtr(); |
196 | 16.3M | } |
197 | | |
198 | | public: |
199 | | MCSymbol(const MCSymbol &) = delete; |
200 | | MCSymbol &operator=(const MCSymbol &) = delete; |
201 | | |
202 | | /// getName - Get the symbol name. |
203 | 16.3M | StringRef getName() const { |
204 | 16.3M | if (!FragmentAndHasName.getInt()) |
205 | 560 | return StringRef(); |
206 | 16.3M | |
207 | 16.3M | return getNameEntryPtr()->first(); |
208 | 16.3M | } |
209 | | |
210 | 16.1M | bool isRegistered() const { return IsRegistered; } |
211 | 7.15M | void setIsRegistered(bool Value) const { IsRegistered = Value; } |
212 | | |
213 | 9.66k | void setUsedInReloc() const { IsUsedInReloc = true; } |
214 | 21.0M | bool isUsedInReloc() const { return IsUsedInReloc; } |
215 | | |
216 | | /// \name Accessors |
217 | | /// @{ |
218 | | |
219 | | /// isTemporary - Check if this is an assembler temporary symbol. |
220 | 47.8M | bool isTemporary() const { return IsTemporary; } |
221 | | |
222 | | /// isUsed - Check if this is used. |
223 | 335 | bool isUsed() const { return IsUsed; } |
224 | 0 | void setUsed(bool Value) const { IsUsed |= Value; } |
225 | | |
226 | | /// \brief Check if this symbol is redefinable. |
227 | 0 | bool isRedefinable() const { return IsRedefinable; } |
228 | | /// \brief Mark this symbol as redefinable. |
229 | 655 | void setRedefinable(bool Value) { IsRedefinable = Value; } |
230 | | /// \brief Prepare this symbol to be redefined. |
231 | 8.05M | void redefineIfPossible() { |
232 | 8.05M | if (IsRedefinable8.05M ) { |
233 | 3 | if (SymbolContents == SymContentsVariable3 ) { |
234 | 3 | Value = nullptr; |
235 | 3 | SymbolContents = SymContentsUnset; |
236 | 3 | } |
237 | 3 | setUndefined(); |
238 | 3 | IsRedefinable = false; |
239 | 3 | } |
240 | 8.05M | } |
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 | 69.1M | bool isDefined(bool SetUsed = true) const { |
250 | 69.1M | return getFragment(SetUsed) != nullptr; |
251 | 69.1M | } |
252 | | |
253 | | /// isInSection - Check if this symbol is defined in some section (i.e., it |
254 | | /// is defined but not absolute). |
255 | 38.2M | bool isInSection(bool SetUsed = true) const { |
256 | 31.9M | return isDefined(SetUsed) && !isAbsolute(SetUsed); |
257 | 38.2M | } |
258 | | |
259 | | /// isUndefined - Check if this symbol undefined (i.e., implicitly defined). |
260 | 20.2M | bool isUndefined(bool SetUsed = true) const { return !isDefined(SetUsed); } |
261 | | |
262 | | /// isAbsolute - Check if this is an absolute symbol. |
263 | 34.5M | bool isAbsolute(bool SetUsed = true) const { |
264 | 34.5M | return getFragment(SetUsed) == AbsolutePseudoFragment; |
265 | 34.5M | } |
266 | | |
267 | | /// Get the section associated with a defined, non-absolute symbol. |
268 | 6.00M | MCSection &getSection(bool SetUsed = true) const { |
269 | 6.00M | assert(isInSection(SetUsed) && "Invalid accessor!"); |
270 | 6.00M | return *getSectionPtr(SetUsed); |
271 | 6.00M | } |
272 | | |
273 | | /// Mark the symbol as defined in the fragment \p F. |
274 | 14.3M | void setFragment(MCFragment *F) const { |
275 | 14.3M | assert(!isVariable() && "Cannot set fragment of variable"); |
276 | 14.3M | FragmentAndHasName.setPointer(F); |
277 | 14.3M | } |
278 | | |
279 | | /// Mark the symbol as undefined. |
280 | 174k | void setUndefined() { FragmentAndHasName.setPointer(nullptr); } |
281 | | |
282 | 62.9k | bool isELF() const { return Kind == SymbolKindELF; } |
283 | | |
284 | 0 | bool isCOFF() const { return Kind == SymbolKindCOFF; } |
285 | | |
286 | 0 | bool isMachO() const { return Kind == SymbolKindMachO; } |
287 | | |
288 | 0 | bool isWasm() const { return Kind == SymbolKindWasm; } |
289 | | |
290 | | /// @} |
291 | | /// \name Variable Symbols |
292 | | /// @{ |
293 | | |
294 | | /// isVariable - Check if this is a variable symbol. |
295 | 72.7M | bool isVariable() const { |
296 | 72.7M | return SymbolContents == SymContentsVariable; |
297 | 72.7M | } |
298 | | |
299 | | /// getVariableValue - Get the value for variable symbols. |
300 | 904k | const MCExpr *getVariableValue(bool SetUsed = true) const { |
301 | 904k | assert(isVariable() && "Invalid accessor!"); |
302 | 904k | IsUsed |= SetUsed; |
303 | 904k | return Value; |
304 | 904k | } |
305 | | |
306 | | void setVariableValue(const MCExpr *Value); |
307 | | |
308 | | /// @} |
309 | | |
310 | | /// Get the (implementation defined) index. |
311 | 4.87M | uint32_t getIndex() const { |
312 | 4.87M | return Index; |
313 | 4.87M | } |
314 | | |
315 | | /// Set the (implementation defined) index. |
316 | 1.49M | void setIndex(uint32_t Value) const { |
317 | 1.49M | Index = Value; |
318 | 1.49M | } |
319 | | |
320 | 14.5M | uint64_t getOffset() const { |
321 | 14.5M | assert((SymbolContents == SymContentsUnset || |
322 | 14.5M | SymbolContents == SymContentsOffset) && |
323 | 14.5M | "Cannot get offset for a common/variable symbol"); |
324 | 14.5M | return Offset; |
325 | 14.5M | } |
326 | 6.41M | void setOffset(uint64_t Value) { |
327 | 6.41M | assert((SymbolContents == SymContentsUnset || |
328 | 6.41M | SymbolContents == SymContentsOffset) && |
329 | 6.41M | "Cannot set offset for a common/variable symbol"); |
330 | 6.41M | Offset = Value; |
331 | 6.41M | SymbolContents = SymContentsOffset; |
332 | 6.41M | } |
333 | | |
334 | | /// Return the size of a 'common' symbol. |
335 | 21.4k | uint64_t getCommonSize() const { |
336 | 21.4k | assert(isCommon() && "Not a 'common' symbol!"); |
337 | 21.4k | return CommonSize; |
338 | 21.4k | } |
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 | 21.6k | void setCommon(uint64_t Size, unsigned Align) { |
345 | 21.6k | assert(getOffset() == 0); |
346 | 21.6k | CommonSize = Size; |
347 | 21.6k | SymbolContents = SymContentsCommon; |
348 | 21.6k | |
349 | 21.6k | assert((!Align || isPowerOf2_32(Align)) && |
350 | 21.6k | "Alignment must be a power of 2"); |
351 | 21.6k | unsigned Log2Align = Log2_32(Align) + 1; |
352 | 21.6k | assert(Log2Align < (1U << NumCommonAlignmentBits) && |
353 | 21.6k | "Out of range alignment"); |
354 | 21.6k | CommonAlignLog2 = Log2Align; |
355 | 21.6k | } |
356 | | |
357 | | /// Return the alignment of a 'common' symbol. |
358 | 21.6k | unsigned getCommonAlignment() const { |
359 | 21.6k | assert(isCommon() && "Not a 'common' symbol!"); |
360 | 21.6k | return CommonAlignLog2 ? (1U << (CommonAlignLog2 - 1))21.5k : 021 ; |
361 | 21.6k | } |
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 | 138 | bool declareCommon(uint64_t Size, unsigned Align) { |
369 | 138 | assert(isCommon() || getOffset() == 0); |
370 | 138 | if(isCommon()138 ) { |
371 | 3 | if(CommonSize != Size || 3 getCommonAlignment() != Align2 ) |
372 | 1 | return true; |
373 | 3 | } else |
374 | 135 | setCommon(Size, Align); |
375 | 137 | return false; |
376 | 138 | } |
377 | | |
378 | | /// Is this a 'common' symbol. |
379 | 1.73M | bool isCommon() const { |
380 | 1.73M | return SymbolContents == SymContentsCommon; |
381 | 1.73M | } |
382 | | |
383 | 152M | MCFragment *getFragment(bool SetUsed = true) const { |
384 | 152M | MCFragment *Fragment = FragmentAndHasName.getPointer(); |
385 | 152M | if (Fragment || 152M !isVariable()17.6M ) |
386 | 152M | return Fragment; |
387 | 170k | Fragment = getVariableValue(SetUsed)->findAssociatedFragment(); |
388 | 170k | FragmentAndHasName.setPointer(Fragment); |
389 | 170k | return Fragment; |
390 | 152M | } |
391 | | |
392 | 4.45M | bool isExternal() const { return IsExternal; } |
393 | 586k | void setExternal(bool Value) const { IsExternal = Value; } |
394 | | |
395 | 1.48M | bool isPrivateExtern() const { return IsPrivateExtern; } |
396 | 17.4k | 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 | | |
404 | | protected: |
405 | | /// Get the (implementation defined) symbol flags. |
406 | 9.69M | uint32_t getFlags() const { return Flags; } |
407 | | |
408 | | /// Set the (implementation defined) symbol flags. |
409 | 3.48M | void setFlags(uint32_t Value) const { |
410 | 3.48M | assert(Value < (1U << NumFlagsBits) && "Out of range flags"); |
411 | 3.48M | Flags = Value; |
412 | 3.48M | } |
413 | | |
414 | | /// Modify the flags via a mask |
415 | 7.41M | void modifyFlags(uint32_t Value, uint32_t Mask) const { |
416 | 7.41M | assert(Value < (1U << NumFlagsBits) && "Out of range flags"); |
417 | 7.41M | Flags = (Flags & ~Mask) | Value; |
418 | 7.41M | } |
419 | | }; |
420 | | |
421 | 14 | inline raw_ostream &operator<<(raw_ostream &OS, const MCSymbol &Sym) { |
422 | 14 | Sym.print(OS, nullptr); |
423 | 14 | return OS; |
424 | 14 | } |
425 | | |
426 | | } // end namespace llvm |
427 | | |
428 | | #endif // LLVM_MC_MCSYMBOL_H |