1 //===-- Mangler.cpp - Self-contained c/asm llvm name mangler --------------===// 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 // 9 // Unified name mangler for assembly backends. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "llvm/IR/Mangler.h" 14 #include "llvm/ADT/SmallString.h" 15 #include "llvm/ADT/StringExtras.h" 16 #include "llvm/ADT/Twine.h" 17 #include "llvm/Demangle/Demangle.h" 18 #include "llvm/IR/DataLayout.h" 19 #include "llvm/IR/DerivedTypes.h" 20 #include "llvm/IR/Function.h" 21 #include "llvm/IR/Module.h" 22 #include "llvm/Support/raw_ostream.h" 23 #include "llvm/TargetParser/Triple.h" 24 25 using namespace llvm; 26 27 namespace { 28 enum ManglerPrefixTy { 29 Default, ///< Emit default string before each symbol. 30 Private, ///< Emit "private" prefix before each symbol. 31 LinkerPrivate ///< Emit "linker private" prefix before each symbol. 32 }; 33 } 34 35 static void getNameWithPrefixImpl(raw_ostream &OS, const Twine &GVName, 36 ManglerPrefixTy PrefixTy, 37 const DataLayout &DL, char Prefix) { 38 SmallString<256> TmpData; 39 StringRef Name = GVName.toStringRef(TmpData); 40 assert(!Name.empty() && "getNameWithPrefix requires non-empty name"); 41 42 // No need to do anything special if the global has the special "do not 43 // mangle" flag in the name. 44 if (Name[0] == '\1') { 45 OS << Name.substr(1); 46 return; 47 } 48 49 if (DL.doNotMangleLeadingQuestionMark() && Name[0] == '?') 50 Prefix = '\0'; 51 52 if (PrefixTy == Private) 53 OS << DL.getPrivateGlobalPrefix(); 54 else if (PrefixTy == LinkerPrivate) 55 OS << DL.getLinkerPrivateGlobalPrefix(); 56 57 if (Prefix != '\0') 58 OS << Prefix; 59 60 // If this is a simple string that doesn't need escaping, just append it. 61 OS << Name; 62 } 63 64 static void getNameWithPrefixImpl(raw_ostream &OS, const Twine &GVName, 65 const DataLayout &DL, 66 ManglerPrefixTy PrefixTy) { 67 char Prefix = DL.getGlobalPrefix(); 68 return getNameWithPrefixImpl(OS, GVName, PrefixTy, DL, Prefix); 69 } 70 71 void Mangler::getNameWithPrefix(raw_ostream &OS, const Twine &GVName, 72 const DataLayout &DL) { 73 return getNameWithPrefixImpl(OS, GVName, DL, Default); 74 } 75 76 void Mangler::getNameWithPrefix(SmallVectorImpl<char> &OutName, 77 const Twine &GVName, const DataLayout &DL) { 78 raw_svector_ostream OS(OutName); 79 char Prefix = DL.getGlobalPrefix(); 80 return getNameWithPrefixImpl(OS, GVName, Default, DL, Prefix); 81 } 82 83 static bool hasByteCountSuffix(CallingConv::ID CC) { 84 switch (CC) { 85 case CallingConv::X86_FastCall: 86 case CallingConv::X86_StdCall: 87 case CallingConv::X86_VectorCall: 88 return true; 89 default: 90 return false; 91 } 92 } 93 94 /// Microsoft fastcall and stdcall functions require a suffix on their name 95 /// indicating the number of words of arguments they take. 96 static void addByteCountSuffix(raw_ostream &OS, const Function *F, 97 const DataLayout &DL) { 98 // Calculate arguments size total. 99 unsigned ArgWords = 0; 100 101 const unsigned PtrSize = DL.getPointerSize(); 102 103 for (const Argument &A : F->args()) { 104 // For the purposes of the byte count suffix, structs returned by pointer 105 // do not count as function arguments. 106 if (A.hasStructRetAttr()) 107 continue; 108 109 // 'Dereference' type in case of byval or inalloca parameter attribute. 110 uint64_t AllocSize = A.hasPassPointeeByValueCopyAttr() ? 111 A.getPassPointeeByValueCopySize(DL) : 112 DL.getTypeAllocSize(A.getType()); 113 114 // Size should be aligned to pointer size. 115 ArgWords += alignTo(AllocSize, PtrSize); 116 } 117 118 OS << '@' << ArgWords; 119 } 120 121 void Mangler::getNameWithPrefix(raw_ostream &OS, const GlobalValue *GV, 122 bool CannotUsePrivateLabel) const { 123 ManglerPrefixTy PrefixTy = Default; 124 assert(GV != nullptr && "Invalid Global Value"); 125 if (GV->hasPrivateLinkage()) { 126 if (CannotUsePrivateLabel) 127 PrefixTy = LinkerPrivate; 128 else 129 PrefixTy = Private; 130 } 131 132 const DataLayout &DL = GV->getDataLayout(); 133 if (!GV->hasName()) { 134 // Get the ID for the global, assigning a new one if we haven't got one 135 // already. 136 unsigned &ID = AnonGlobalIDs[GV]; 137 if (ID == 0) 138 ID = AnonGlobalIDs.size(); 139 140 // Must mangle the global into a unique ID. 141 getNameWithPrefixImpl(OS, "__unnamed_" + Twine(ID), DL, PrefixTy); 142 return; 143 } 144 145 StringRef Name = GV->getName(); 146 char Prefix = DL.getGlobalPrefix(); 147 148 // Mangle functions with Microsoft calling conventions specially. Only do 149 // this mangling for x86_64 vectorcall and 32-bit x86. 150 const Function *MSFunc = dyn_cast_or_null<Function>(GV->getAliaseeObject()); 151 152 // Don't add byte count suffixes when '\01' or '?' are in the first 153 // character. 154 if (Name.starts_with("\01") || 155 (DL.doNotMangleLeadingQuestionMark() && Name.starts_with("?"))) 156 MSFunc = nullptr; 157 158 CallingConv::ID CC = 159 MSFunc ? MSFunc->getCallingConv() : (unsigned)CallingConv::C; 160 if (!DL.hasMicrosoftFastStdCallMangling() && 161 CC != CallingConv::X86_VectorCall) 162 MSFunc = nullptr; 163 if (MSFunc) { 164 if (CC == CallingConv::X86_FastCall) 165 Prefix = '@'; // fastcall functions have an @ prefix instead of _. 166 else if (CC == CallingConv::X86_VectorCall) 167 Prefix = '\0'; // vectorcall functions have no prefix. 168 } 169 170 getNameWithPrefixImpl(OS, Name, PrefixTy, DL, Prefix); 171 172 if (!MSFunc) 173 return; 174 175 // If we are supposed to add a microsoft-style suffix for stdcall, fastcall, 176 // or vectorcall, add it. These functions have a suffix of @N where N is the 177 // cumulative byte size of all of the parameters to the function in decimal. 178 if (CC == CallingConv::X86_VectorCall) 179 OS << '@'; // vectorcall functions use a double @ suffix. 180 FunctionType *FT = MSFunc->getFunctionType(); 181 if (hasByteCountSuffix(CC) && 182 // "Pure" variadic functions do not receive @0 suffix. 183 (!FT->isVarArg() || FT->getNumParams() == 0 || 184 (FT->getNumParams() == 1 && MSFunc->hasStructRetAttr()))) 185 addByteCountSuffix(OS, MSFunc, DL); 186 } 187 188 void Mangler::getNameWithPrefix(SmallVectorImpl<char> &OutName, 189 const GlobalValue *GV, 190 bool CannotUsePrivateLabel) const { 191 raw_svector_ostream OS(OutName); 192 getNameWithPrefix(OS, GV, CannotUsePrivateLabel); 193 } 194 195 // Check if the name needs quotes to be safe for the linker to interpret. 196 static bool canBeUnquotedInDirective(char C) { 197 return isAlnum(C) || C == '_' || C == '@' || C == '#'; 198 } 199 200 static bool canBeUnquotedInDirective(StringRef Name) { 201 if (Name.empty()) 202 return false; 203 204 // If any of the characters in the string is an unacceptable character, force 205 // quotes. 206 for (char C : Name) { 207 if (!canBeUnquotedInDirective(C)) 208 return false; 209 } 210 211 return true; 212 } 213 214 void llvm::emitLinkerFlagsForGlobalCOFF(raw_ostream &OS, const GlobalValue *GV, 215 const Triple &TT, Mangler &Mangler) { 216 if (GV->hasDLLExportStorageClass() && !GV->isDeclaration()) { 217 218 if (TT.isWindowsMSVCEnvironment()) 219 OS << " /EXPORT:"; 220 else 221 OS << " -export:"; 222 223 bool NeedQuotes = GV->hasName() && !canBeUnquotedInDirective(GV->getName()); 224 if (NeedQuotes) 225 OS << "\""; 226 if (TT.isWindowsGNUEnvironment() || TT.isWindowsCygwinEnvironment()) { 227 std::string Flag; 228 raw_string_ostream FlagOS(Flag); 229 Mangler.getNameWithPrefix(FlagOS, GV, false); 230 FlagOS.flush(); 231 if (Flag[0] == GV->getDataLayout().getGlobalPrefix()) 232 OS << Flag.substr(1); 233 else 234 OS << Flag; 235 } else { 236 Mangler.getNameWithPrefix(OS, GV, false); 237 } 238 if (TT.isWindowsArm64EC()) { 239 // Use EXPORTAS for mangled ARM64EC symbols. 240 // FIXME: During LTO, we're invoked prior to the EC lowering pass, 241 // so symbols are not yet mangled. Emitting the unmangled name 242 // typically functions correctly; the linker can resolve the export 243 // with the demangled alias. 244 if (std::optional<std::string> demangledName = 245 getArm64ECDemangledFunctionName(GV->getName())) 246 OS << ",EXPORTAS," << *demangledName; 247 } 248 if (NeedQuotes) 249 OS << "\""; 250 251 if (!GV->getValueType()->isFunctionTy()) { 252 if (TT.isWindowsMSVCEnvironment()) 253 OS << ",DATA"; 254 else 255 OS << ",data"; 256 } 257 } 258 if (GV->hasHiddenVisibility() && !GV->isDeclaration() && TT.isOSCygMing()) { 259 260 OS << " -exclude-symbols:"; 261 262 bool NeedQuotes = GV->hasName() && !canBeUnquotedInDirective(GV->getName()); 263 if (NeedQuotes) 264 OS << "\""; 265 266 std::string Flag; 267 raw_string_ostream FlagOS(Flag); 268 Mangler.getNameWithPrefix(FlagOS, GV, false); 269 FlagOS.flush(); 270 if (Flag[0] == GV->getDataLayout().getGlobalPrefix()) 271 OS << Flag.substr(1); 272 else 273 OS << Flag; 274 275 if (NeedQuotes) 276 OS << "\""; 277 } 278 } 279 280 void llvm::emitLinkerFlagsForUsedCOFF(raw_ostream &OS, const GlobalValue *GV, 281 const Triple &T, Mangler &M) { 282 if (!T.isWindowsMSVCEnvironment()) 283 return; 284 285 OS << " /INCLUDE:"; 286 bool NeedQuotes = GV->hasName() && !canBeUnquotedInDirective(GV->getName()); 287 if (NeedQuotes) 288 OS << "\""; 289 M.getNameWithPrefix(OS, GV, false); 290 if (NeedQuotes) 291 OS << "\""; 292 } 293 294 std::optional<std::string> llvm::getArm64ECMangledFunctionName(StringRef Name) { 295 if (Name[0] != '?') { 296 // For non-C++ symbols, prefix the name with "#" unless it's already 297 // mangled. 298 if (Name[0] == '#') 299 return std::nullopt; 300 return std::optional<std::string>(("#" + Name).str()); 301 } 302 303 // If the name contains $$h, then it is already mangled. 304 if (Name.contains("$$h")) 305 return std::nullopt; 306 307 // Ask the demangler where we should insert "$$h". 308 auto InsertIdx = getArm64ECInsertionPointInMangledName(Name); 309 if (!InsertIdx) 310 return std::nullopt; 311 312 return std::optional<std::string>( 313 (Name.substr(0, *InsertIdx) + "$$h" + Name.substr(*InsertIdx)).str()); 314 } 315 316 std::optional<std::string> 317 llvm::getArm64ECDemangledFunctionName(StringRef Name) { 318 if (Name[0] == '#') 319 return std::optional<std::string>(Name.substr(1)); 320 if (Name[0] != '?') 321 return std::nullopt; 322 323 std::pair<StringRef, StringRef> Pair = Name.split("$$h"); 324 if (Pair.second.empty()) 325 return std::nullopt; 326 return std::optional<std::string>((Pair.first + Pair.second).str()); 327 } 328