1 //===- MCSymbolMachO.h - ---------------------------------------*- C++ -*-===// 2 // 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 6 // 7 //===----------------------------------------------------------------------===// 8 #ifndef LLVM_MC_MCSYMBOLMACHO_H 9 #define LLVM_MC_MCSYMBOLMACHO_H 10 11 #include "llvm/ADT/Twine.h" 12 #include "llvm/MC/MCSymbol.h" 13 #include "llvm/MC/MCSymbolTableEntry.h" 14 15 namespace llvm { 16 class MCSymbolMachO : public MCSymbol { 17 /// We store the value for the 'desc' symbol field in the 18 /// lowest 16 bits of the implementation defined flags. 19 enum MachOSymbolFlags : uint16_t { // See <mach-o/nlist.h>. 20 SF_DescFlagsMask = 0xFFFF, 21 22 // Reference type flags. 23 SF_ReferenceTypeMask = 0x0007, 24 SF_ReferenceTypeUndefinedNonLazy = 0x0000, 25 SF_ReferenceTypeUndefinedLazy = 0x0001, 26 SF_ReferenceTypeDefined = 0x0002, 27 SF_ReferenceTypePrivateDefined = 0x0003, 28 SF_ReferenceTypePrivateUndefinedNonLazy = 0x0004, 29 SF_ReferenceTypePrivateUndefinedLazy = 0x0005, 30 31 // Other 'desc' flags. 32 SF_ThumbFunc = 0x0008, 33 SF_NoDeadStrip = 0x0020, 34 SF_WeakReference = 0x0040, 35 SF_WeakDefinition = 0x0080, 36 SF_SymbolResolver = 0x0100, 37 SF_AltEntry = 0x0200, 38 SF_Cold = 0x0400, 39 40 // Common alignment 41 SF_CommonAlignmentMask = 0xF0FF, 42 SF_CommonAlignmentShift = 8 43 }; 44 45 public: MCSymbolMachO(const MCSymbolTableEntry * Name,bool isTemporary)46 MCSymbolMachO(const MCSymbolTableEntry *Name, bool isTemporary) 47 : MCSymbol(SymbolKindMachO, Name, isTemporary) {} 48 isPrivateExtern()49 bool isPrivateExtern() const { return IsPrivateExtern; } setPrivateExtern(bool Value)50 void setPrivateExtern(bool Value) { IsPrivateExtern = Value; } 51 52 // Reference type methods. 53 clearReferenceType()54 void clearReferenceType() const { 55 modifyFlags(0, SF_ReferenceTypeMask); 56 } 57 setReferenceTypeUndefinedLazy(bool Value)58 void setReferenceTypeUndefinedLazy(bool Value) const { 59 modifyFlags(Value ? SF_ReferenceTypeUndefinedLazy : 0, 60 SF_ReferenceTypeUndefinedLazy); 61 } 62 63 // Other 'desc' methods. 64 setThumbFunc()65 void setThumbFunc() const { 66 modifyFlags(SF_ThumbFunc, SF_ThumbFunc); 67 } 68 isNoDeadStrip()69 bool isNoDeadStrip() const { 70 return getFlags() & SF_NoDeadStrip; 71 } setNoDeadStrip()72 void setNoDeadStrip() const { 73 modifyFlags(SF_NoDeadStrip, SF_NoDeadStrip); 74 } 75 isWeakReference()76 bool isWeakReference() const { 77 return getFlags() & SF_WeakReference; 78 } setWeakReference()79 void setWeakReference() const { 80 modifyFlags(SF_WeakReference, SF_WeakReference); 81 } 82 isWeakDefinition()83 bool isWeakDefinition() const { 84 return getFlags() & SF_WeakDefinition; 85 } setWeakDefinition()86 void setWeakDefinition() const { 87 modifyFlags(SF_WeakDefinition, SF_WeakDefinition); 88 } 89 isSymbolResolver()90 bool isSymbolResolver() const { 91 return getFlags() & SF_SymbolResolver; 92 } setSymbolResolver()93 void setSymbolResolver() const { 94 modifyFlags(SF_SymbolResolver, SF_SymbolResolver); 95 } 96 setAltEntry()97 void setAltEntry() const { 98 modifyFlags(SF_AltEntry, SF_AltEntry); 99 } 100 isAltEntry()101 bool isAltEntry() const { 102 return getFlags() & SF_AltEntry; 103 } 104 setCold()105 void setCold() const { modifyFlags(SF_Cold, SF_Cold); } 106 isCold()107 bool isCold() const { return getFlags() & SF_Cold; } 108 setDesc(unsigned Value)109 void setDesc(unsigned Value) const { 110 assert(Value == (Value & SF_DescFlagsMask) && 111 "Invalid .desc value!"); 112 setFlags(Value & SF_DescFlagsMask); 113 } 114 115 // Check whether a particular symbol is visible to the linker and is required 116 // in the symbol table, or whether it can be discarded by the assembler. This 117 // also effects whether the assembler treats the label as potentially defining 118 // a separate atom. isSymbolLinkerVisible()119 bool isSymbolLinkerVisible() const { 120 // Non-temporary labels should always be visible to the linker. 121 if (!isTemporary()) 122 return true; 123 124 return isUsedInReloc(); 125 } 126 127 /// Get the encoded value of the flags as they will be emitted in to 128 /// the MachO binary getEncodedFlags(bool EncodeAsAltEntry)129 uint16_t getEncodedFlags(bool EncodeAsAltEntry) const { 130 uint16_t Flags = getFlags(); 131 132 // Common alignment is packed into the 'desc' bits. 133 if (isCommon()) { 134 if (MaybeAlign MaybeAlignment = getCommonAlignment()) { 135 Align Alignment = *MaybeAlignment; 136 unsigned Log2Size = Log2(Alignment); 137 if (Log2Size > 15) 138 report_fatal_error("invalid 'common' alignment '" + 139 Twine(Alignment.value()) + "' for '" + 140 getName() + "'", 141 false); 142 Flags = (Flags & SF_CommonAlignmentMask) | 143 (Log2Size << SF_CommonAlignmentShift); 144 } 145 } 146 147 if (EncodeAsAltEntry) 148 Flags |= SF_AltEntry; 149 150 return Flags; 151 } 152 classof(const MCSymbol * S)153 static bool classof(const MCSymbol *S) { return S->isMachO(); } 154 }; 155 } 156 157 #endif 158