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