File indexing completed on 2026-05-10 08:44:15
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #ifndef LLVM_MC_MCSYMBOL_H
0014 #define LLVM_MC_MCSYMBOL_H
0015
0016 #include "llvm/ADT/StringMapEntry.h"
0017 #include "llvm/ADT/StringRef.h"
0018 #include "llvm/MC/MCExpr.h"
0019 #include "llvm/MC/MCFragment.h"
0020 #include "llvm/MC/MCSymbolTableEntry.h"
0021 #include "llvm/Support/ErrorHandling.h"
0022 #include "llvm/Support/MathExtras.h"
0023 #include <cassert>
0024 #include <cstddef>
0025 #include <cstdint>
0026
0027 namespace llvm {
0028
0029 class MCAsmInfo;
0030 class MCContext;
0031 class MCSection;
0032 class raw_ostream;
0033
0034
0035
0036
0037
0038
0039
0040
0041 class MCSymbol {
0042 protected:
0043
0044
0045 enum SymbolKind {
0046 SymbolKindUnset,
0047 SymbolKindCOFF,
0048 SymbolKindELF,
0049 SymbolKindGOFF,
0050 SymbolKindMachO,
0051 SymbolKindWasm,
0052 SymbolKindXCOFF,
0053 };
0054
0055
0056
0057 enum Contents : uint8_t {
0058 SymContentsUnset,
0059 SymContentsOffset,
0060 SymContentsVariable,
0061 SymContentsCommon,
0062 SymContentsTargetCommon,
0063 };
0064
0065
0066 static MCFragment *AbsolutePseudoFragment;
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079 mutable MCFragment *Fragment = nullptr;
0080
0081
0082
0083 unsigned HasName : 1;
0084
0085
0086
0087
0088 unsigned IsTemporary : 1;
0089
0090
0091 unsigned IsRedefinable : 1;
0092
0093
0094 mutable unsigned IsUsed : 1;
0095
0096 mutable unsigned IsRegistered : 1;
0097
0098
0099
0100 mutable unsigned IsExternal : 1;
0101
0102
0103 mutable unsigned IsPrivateExtern : 1;
0104
0105
0106 mutable unsigned IsWeakExternal : 1;
0107
0108
0109
0110 unsigned Kind : 3;
0111
0112
0113 mutable unsigned IsUsedInReloc : 1;
0114
0115
0116
0117 unsigned SymbolContents : 3;
0118
0119
0120
0121
0122
0123
0124
0125
0126
0127
0128
0129 enum : unsigned { NumCommonAlignmentBits = 5 };
0130 unsigned CommonAlignLog2 : NumCommonAlignmentBits;
0131
0132
0133
0134 enum : unsigned { NumFlagsBits = 16 };
0135 mutable uint32_t Flags : NumFlagsBits;
0136
0137
0138 mutable uint32_t Index = 0;
0139
0140 union {
0141
0142 uint64_t Offset;
0143
0144
0145 uint64_t CommonSize;
0146
0147
0148 const MCExpr *Value;
0149 };
0150
0151
0152 friend class MCExpr;
0153 friend class MCContext;
0154
0155
0156
0157
0158
0159 using NameEntryStorageTy = union {
0160 const MCSymbolTableEntry *NameEntry;
0161 uint64_t AlignmentPadding;
0162 };
0163
0164 MCSymbol(SymbolKind Kind, const MCSymbolTableEntry *Name, bool isTemporary)
0165 : IsTemporary(isTemporary), IsRedefinable(false), IsUsed(false),
0166 IsRegistered(false), IsExternal(false), IsPrivateExtern(false),
0167 IsWeakExternal(false), Kind(Kind), IsUsedInReloc(false),
0168 SymbolContents(SymContentsUnset), CommonAlignLog2(0), Flags(0) {
0169 Offset = 0;
0170 HasName = !!Name;
0171 if (Name)
0172 getNameEntryPtr() = Name;
0173 }
0174
0175
0176
0177 void *operator new(size_t s, const MCSymbolTableEntry *Name, MCContext &Ctx);
0178
0179 private:
0180 void operator delete(void *);
0181
0182 void operator delete(void*, unsigned) {
0183 llvm_unreachable("Constructor throws?");
0184 }
0185
0186 void operator delete(void*, unsigned, bool) {
0187 llvm_unreachable("Constructor throws?");
0188 }
0189
0190
0191 const MCSymbolTableEntry *&getNameEntryPtr() {
0192 assert(HasName && "Name is required");
0193 NameEntryStorageTy *Name = reinterpret_cast<NameEntryStorageTy *>(this);
0194 return (*(Name - 1)).NameEntry;
0195 }
0196 const MCSymbolTableEntry *&getNameEntryPtr() const {
0197 return const_cast<MCSymbol*>(this)->getNameEntryPtr();
0198 }
0199
0200 public:
0201 MCSymbol(const MCSymbol &) = delete;
0202 MCSymbol &operator=(const MCSymbol &) = delete;
0203
0204
0205 StringRef getName() const {
0206 if (!HasName)
0207 return StringRef();
0208
0209 return getNameEntryPtr()->first();
0210 }
0211
0212 bool isRegistered() const { return IsRegistered; }
0213 void setIsRegistered(bool Value) const { IsRegistered = Value; }
0214
0215 void setUsedInReloc() const { IsUsedInReloc = true; }
0216 bool isUsedInReloc() const { return IsUsedInReloc; }
0217
0218
0219
0220
0221
0222 bool isTemporary() const { return IsTemporary; }
0223
0224
0225 bool isUsed() const { return IsUsed; }
0226
0227
0228 bool isRedefinable() const { return IsRedefinable; }
0229
0230 void setRedefinable(bool Value) { IsRedefinable = Value; }
0231
0232 void redefineIfPossible() {
0233 if (IsRedefinable) {
0234 if (SymbolContents == SymContentsVariable) {
0235 Value = nullptr;
0236 SymbolContents = SymContentsUnset;
0237 }
0238 setUndefined();
0239 IsRedefinable = false;
0240 }
0241 }
0242
0243
0244
0245
0246
0247
0248
0249
0250 bool isDefined() const { return !isUndefined(); }
0251
0252
0253
0254 bool isInSection() const {
0255 return isDefined() && !isAbsolute();
0256 }
0257
0258
0259 bool isUndefined(bool SetUsed = true) const {
0260 return getFragment(SetUsed) == nullptr;
0261 }
0262
0263
0264 bool isAbsolute() const {
0265 return getFragment() == AbsolutePseudoFragment;
0266 }
0267
0268
0269 MCSection &getSection() const {
0270 assert(isInSection() && "Invalid accessor!");
0271 return *getFragment()->getParent();
0272 }
0273
0274
0275 void setFragment(MCFragment *F) const {
0276 assert(!isVariable() && "Cannot set fragment of variable");
0277 Fragment = F;
0278 }
0279
0280
0281 void setUndefined() { Fragment = nullptr; }
0282
0283 bool isELF() const { return Kind == SymbolKindELF; }
0284
0285 bool isCOFF() const { return Kind == SymbolKindCOFF; }
0286
0287 bool isGOFF() const { return Kind == SymbolKindGOFF; }
0288
0289 bool isMachO() const { return Kind == SymbolKindMachO; }
0290
0291 bool isWasm() const { return Kind == SymbolKindWasm; }
0292
0293 bool isXCOFF() const { return Kind == SymbolKindXCOFF; }
0294
0295
0296
0297
0298
0299
0300 bool isVariable() const {
0301 return SymbolContents == SymContentsVariable;
0302 }
0303
0304
0305 const MCExpr *getVariableValue(bool SetUsed = true) const {
0306 assert(isVariable() && "Invalid accessor!");
0307 IsUsed |= SetUsed;
0308 return Value;
0309 }
0310
0311 void setVariableValue(const MCExpr *Value);
0312
0313
0314
0315
0316 uint32_t getIndex() const {
0317 return Index;
0318 }
0319
0320
0321 void setIndex(uint32_t Value) const {
0322 Index = Value;
0323 }
0324
0325 bool isUnset() const { return SymbolContents == SymContentsUnset; }
0326
0327 uint64_t getOffset() const {
0328 assert((SymbolContents == SymContentsUnset ||
0329 SymbolContents == SymContentsOffset) &&
0330 "Cannot get offset for a common/variable symbol");
0331 return Offset;
0332 }
0333 void setOffset(uint64_t Value) {
0334 assert((SymbolContents == SymContentsUnset ||
0335 SymbolContents == SymContentsOffset) &&
0336 "Cannot set offset for a common/variable symbol");
0337 Offset = Value;
0338 SymbolContents = SymContentsOffset;
0339 }
0340
0341
0342 uint64_t getCommonSize() const {
0343 assert(isCommon() && "Not a 'common' symbol!");
0344 return CommonSize;
0345 }
0346
0347
0348
0349
0350
0351
0352 void setCommon(uint64_t Size, Align Alignment, bool Target = false) {
0353 assert(getOffset() == 0);
0354 CommonSize = Size;
0355 SymbolContents = Target ? SymContentsTargetCommon : SymContentsCommon;
0356
0357 unsigned Log2Align = encode(Alignment);
0358 assert(Log2Align < (1U << NumCommonAlignmentBits) &&
0359 "Out of range alignment");
0360 CommonAlignLog2 = Log2Align;
0361 }
0362
0363
0364 MaybeAlign getCommonAlignment() const {
0365 assert(isCommon() && "Not a 'common' symbol!");
0366 return decodeMaybeAlign(CommonAlignLog2);
0367 }
0368
0369
0370
0371
0372
0373
0374
0375 bool declareCommon(uint64_t Size, Align Alignment, bool Target = false) {
0376 assert(isCommon() || getOffset() == 0);
0377 if(isCommon()) {
0378 if (CommonSize != Size || getCommonAlignment() != Alignment ||
0379 isTargetCommon() != Target)
0380 return true;
0381 } else
0382 setCommon(Size, Alignment, Target);
0383 return false;
0384 }
0385
0386
0387 bool isCommon() const {
0388 return SymbolContents == SymContentsCommon ||
0389 SymbolContents == SymContentsTargetCommon;
0390 }
0391
0392
0393 bool isTargetCommon() const {
0394 return SymbolContents == SymContentsTargetCommon;
0395 }
0396
0397 MCFragment *getFragment(bool SetUsed = true) const {
0398 if (Fragment || !isVariable() || isWeakExternal())
0399 return Fragment;
0400
0401
0402 Fragment = getVariableValue(SetUsed)->findAssociatedFragment();
0403 return Fragment;
0404 }
0405
0406
0407 bool isExternal() const { return IsExternal; }
0408 void setExternal(bool Value) const { IsExternal = Value; }
0409
0410
0411 bool isWeakExternal() const { return IsWeakExternal; }
0412
0413
0414 void print(raw_ostream &OS, const MCAsmInfo *MAI) const;
0415
0416
0417 void dump() const;
0418
0419 protected:
0420
0421 uint32_t getFlags() const { return Flags; }
0422
0423
0424 void setFlags(uint32_t Value) const {
0425 assert(Value < (1U << NumFlagsBits) && "Out of range flags");
0426 Flags = Value;
0427 }
0428
0429
0430 void modifyFlags(uint32_t Value, uint32_t Mask) const {
0431 assert(Value < (1U << NumFlagsBits) && "Out of range flags");
0432 Flags = (Flags & ~Mask) | Value;
0433 }
0434 };
0435
0436 inline raw_ostream &operator<<(raw_ostream &OS, const MCSymbol &Sym) {
0437 Sym.print(OS, nullptr);
0438 return OS;
0439 }
0440
0441 }
0442
0443 #endif