xref: /freebsd/contrib/llvm-project/llvm/lib/IR/Mangler.cpp (revision 415efcecd8b80f68e76376ef2b854cb6f5c84b5a)
10b57cec5SDimitry Andric //===-- Mangler.cpp - Self-contained c/asm llvm name mangler --------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // Unified name mangler for assembly backends.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric 
130b57cec5SDimitry Andric #include "llvm/IR/Mangler.h"
140b57cec5SDimitry Andric #include "llvm/ADT/SmallString.h"
15e8d8bef9SDimitry Andric #include "llvm/ADT/StringExtras.h"
160b57cec5SDimitry Andric #include "llvm/ADT/Twine.h"
17*415efcecSDimitry Andric #include "llvm/Demangle/Demangle.h"
180b57cec5SDimitry Andric #include "llvm/IR/DataLayout.h"
190b57cec5SDimitry Andric #include "llvm/IR/DerivedTypes.h"
200b57cec5SDimitry Andric #include "llvm/IR/Function.h"
210b57cec5SDimitry Andric #include "llvm/IR/Module.h"
220b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
2306c3fb27SDimitry Andric #include "llvm/TargetParser/Triple.h"
240fca6ea1SDimitry Andric 
250b57cec5SDimitry Andric using namespace llvm;
260b57cec5SDimitry Andric 
270b57cec5SDimitry Andric namespace {
280b57cec5SDimitry Andric enum ManglerPrefixTy {
290b57cec5SDimitry Andric   Default,      ///< Emit default string before each symbol.
300b57cec5SDimitry Andric   Private,      ///< Emit "private" prefix before each symbol.
310b57cec5SDimitry Andric   LinkerPrivate ///< Emit "linker private" prefix before each symbol.
320b57cec5SDimitry Andric };
330b57cec5SDimitry Andric }
340b57cec5SDimitry Andric 
getNameWithPrefixImpl(raw_ostream & OS,const Twine & GVName,ManglerPrefixTy PrefixTy,const DataLayout & DL,char Prefix)350b57cec5SDimitry Andric static void getNameWithPrefixImpl(raw_ostream &OS, const Twine &GVName,
360b57cec5SDimitry Andric                                   ManglerPrefixTy PrefixTy,
370b57cec5SDimitry Andric                                   const DataLayout &DL, char Prefix) {
380b57cec5SDimitry Andric   SmallString<256> TmpData;
390b57cec5SDimitry Andric   StringRef Name = GVName.toStringRef(TmpData);
400b57cec5SDimitry Andric   assert(!Name.empty() && "getNameWithPrefix requires non-empty name");
410b57cec5SDimitry Andric 
420b57cec5SDimitry Andric   // No need to do anything special if the global has the special "do not
430b57cec5SDimitry Andric   // mangle" flag in the name.
440b57cec5SDimitry Andric   if (Name[0] == '\1') {
450b57cec5SDimitry Andric     OS << Name.substr(1);
460b57cec5SDimitry Andric     return;
470b57cec5SDimitry Andric   }
480b57cec5SDimitry Andric 
490b57cec5SDimitry Andric   if (DL.doNotMangleLeadingQuestionMark() && Name[0] == '?')
500b57cec5SDimitry Andric     Prefix = '\0';
510b57cec5SDimitry Andric 
520b57cec5SDimitry Andric   if (PrefixTy == Private)
530b57cec5SDimitry Andric     OS << DL.getPrivateGlobalPrefix();
540b57cec5SDimitry Andric   else if (PrefixTy == LinkerPrivate)
550b57cec5SDimitry Andric     OS << DL.getLinkerPrivateGlobalPrefix();
560b57cec5SDimitry Andric 
570b57cec5SDimitry Andric   if (Prefix != '\0')
580b57cec5SDimitry Andric     OS << Prefix;
590b57cec5SDimitry Andric 
600b57cec5SDimitry Andric   // If this is a simple string that doesn't need escaping, just append it.
610b57cec5SDimitry Andric   OS << Name;
620b57cec5SDimitry Andric }
630b57cec5SDimitry Andric 
getNameWithPrefixImpl(raw_ostream & OS,const Twine & GVName,const DataLayout & DL,ManglerPrefixTy PrefixTy)640b57cec5SDimitry Andric static void getNameWithPrefixImpl(raw_ostream &OS, const Twine &GVName,
650b57cec5SDimitry Andric                                   const DataLayout &DL,
660b57cec5SDimitry Andric                                   ManglerPrefixTy PrefixTy) {
670b57cec5SDimitry Andric   char Prefix = DL.getGlobalPrefix();
680b57cec5SDimitry Andric   return getNameWithPrefixImpl(OS, GVName, PrefixTy, DL, Prefix);
690b57cec5SDimitry Andric }
700b57cec5SDimitry Andric 
getNameWithPrefix(raw_ostream & OS,const Twine & GVName,const DataLayout & DL)710b57cec5SDimitry Andric void Mangler::getNameWithPrefix(raw_ostream &OS, const Twine &GVName,
720b57cec5SDimitry Andric                                 const DataLayout &DL) {
730b57cec5SDimitry Andric   return getNameWithPrefixImpl(OS, GVName, DL, Default);
740b57cec5SDimitry Andric }
750b57cec5SDimitry Andric 
getNameWithPrefix(SmallVectorImpl<char> & OutName,const Twine & GVName,const DataLayout & DL)760b57cec5SDimitry Andric void Mangler::getNameWithPrefix(SmallVectorImpl<char> &OutName,
770b57cec5SDimitry Andric                                 const Twine &GVName, const DataLayout &DL) {
780b57cec5SDimitry Andric   raw_svector_ostream OS(OutName);
790b57cec5SDimitry Andric   char Prefix = DL.getGlobalPrefix();
800b57cec5SDimitry Andric   return getNameWithPrefixImpl(OS, GVName, Default, DL, Prefix);
810b57cec5SDimitry Andric }
820b57cec5SDimitry Andric 
hasByteCountSuffix(CallingConv::ID CC)830b57cec5SDimitry Andric static bool hasByteCountSuffix(CallingConv::ID CC) {
840b57cec5SDimitry Andric   switch (CC) {
850b57cec5SDimitry Andric   case CallingConv::X86_FastCall:
860b57cec5SDimitry Andric   case CallingConv::X86_StdCall:
870b57cec5SDimitry Andric   case CallingConv::X86_VectorCall:
880b57cec5SDimitry Andric     return true;
890b57cec5SDimitry Andric   default:
900b57cec5SDimitry Andric     return false;
910b57cec5SDimitry Andric   }
920b57cec5SDimitry Andric }
930b57cec5SDimitry Andric 
940b57cec5SDimitry Andric /// Microsoft fastcall and stdcall functions require a suffix on their name
950b57cec5SDimitry Andric /// indicating the number of words of arguments they take.
addByteCountSuffix(raw_ostream & OS,const Function * F,const DataLayout & DL)960b57cec5SDimitry Andric static void addByteCountSuffix(raw_ostream &OS, const Function *F,
970b57cec5SDimitry Andric                                const DataLayout &DL) {
980b57cec5SDimitry Andric   // Calculate arguments size total.
990b57cec5SDimitry Andric   unsigned ArgWords = 0;
1005ffd83dbSDimitry Andric 
1015ffd83dbSDimitry Andric   const unsigned PtrSize = DL.getPointerSize();
1025ffd83dbSDimitry Andric 
103fe6060f1SDimitry Andric   for (const Argument &A : F->args()) {
104349cc55cSDimitry Andric     // For the purposes of the byte count suffix, structs returned by pointer
105349cc55cSDimitry Andric     // do not count as function arguments.
106349cc55cSDimitry Andric     if (A.hasStructRetAttr())
107349cc55cSDimitry Andric       continue;
108349cc55cSDimitry Andric 
1090b57cec5SDimitry Andric     // 'Dereference' type in case of byval or inalloca parameter attribute.
110fe6060f1SDimitry Andric     uint64_t AllocSize = A.hasPassPointeeByValueCopyAttr() ?
111fe6060f1SDimitry Andric       A.getPassPointeeByValueCopySize(DL) :
112fe6060f1SDimitry Andric       DL.getTypeAllocSize(A.getType());
1135ffd83dbSDimitry Andric 
1140b57cec5SDimitry Andric     // Size should be aligned to pointer size.
1155ffd83dbSDimitry Andric     ArgWords += alignTo(AllocSize, PtrSize);
1160b57cec5SDimitry Andric   }
1170b57cec5SDimitry Andric 
1180b57cec5SDimitry Andric   OS << '@' << ArgWords;
1190b57cec5SDimitry Andric }
1200b57cec5SDimitry Andric 
getNameWithPrefix(raw_ostream & OS,const GlobalValue * GV,bool CannotUsePrivateLabel) const1210b57cec5SDimitry Andric void Mangler::getNameWithPrefix(raw_ostream &OS, const GlobalValue *GV,
1220b57cec5SDimitry Andric                                 bool CannotUsePrivateLabel) const {
1230b57cec5SDimitry Andric   ManglerPrefixTy PrefixTy = Default;
12406c3fb27SDimitry Andric   assert(GV != nullptr && "Invalid Global Value");
1250b57cec5SDimitry Andric   if (GV->hasPrivateLinkage()) {
1260b57cec5SDimitry Andric     if (CannotUsePrivateLabel)
1270b57cec5SDimitry Andric       PrefixTy = LinkerPrivate;
1280b57cec5SDimitry Andric     else
1290b57cec5SDimitry Andric       PrefixTy = Private;
1300b57cec5SDimitry Andric   }
1310b57cec5SDimitry Andric 
1320fca6ea1SDimitry Andric   const DataLayout &DL = GV->getDataLayout();
1330b57cec5SDimitry Andric   if (!GV->hasName()) {
1340b57cec5SDimitry Andric     // Get the ID for the global, assigning a new one if we haven't got one
1350b57cec5SDimitry Andric     // already.
1360b57cec5SDimitry Andric     unsigned &ID = AnonGlobalIDs[GV];
1370b57cec5SDimitry Andric     if (ID == 0)
1380b57cec5SDimitry Andric       ID = AnonGlobalIDs.size();
1390b57cec5SDimitry Andric 
1400b57cec5SDimitry Andric     // Must mangle the global into a unique ID.
1410b57cec5SDimitry Andric     getNameWithPrefixImpl(OS, "__unnamed_" + Twine(ID), DL, PrefixTy);
1420b57cec5SDimitry Andric     return;
1430b57cec5SDimitry Andric   }
1440b57cec5SDimitry Andric 
1450b57cec5SDimitry Andric   StringRef Name = GV->getName();
1460b57cec5SDimitry Andric   char Prefix = DL.getGlobalPrefix();
1470b57cec5SDimitry Andric 
1480b57cec5SDimitry Andric   // Mangle functions with Microsoft calling conventions specially.  Only do
1490b57cec5SDimitry Andric   // this mangling for x86_64 vectorcall and 32-bit x86.
150d781ede6SDimitry Andric   const Function *MSFunc = dyn_cast_or_null<Function>(GV->getAliaseeObject());
1510b57cec5SDimitry Andric 
1520b57cec5SDimitry Andric   // Don't add byte count suffixes when '\01' or '?' are in the first
1530b57cec5SDimitry Andric   // character.
1545f757f3fSDimitry Andric   if (Name.starts_with("\01") ||
1555f757f3fSDimitry Andric       (DL.doNotMangleLeadingQuestionMark() && Name.starts_with("?")))
1560b57cec5SDimitry Andric     MSFunc = nullptr;
1570b57cec5SDimitry Andric 
1580b57cec5SDimitry Andric   CallingConv::ID CC =
1590b57cec5SDimitry Andric       MSFunc ? MSFunc->getCallingConv() : (unsigned)CallingConv::C;
1600b57cec5SDimitry Andric   if (!DL.hasMicrosoftFastStdCallMangling() &&
1610b57cec5SDimitry Andric       CC != CallingConv::X86_VectorCall)
1620b57cec5SDimitry Andric     MSFunc = nullptr;
1630b57cec5SDimitry Andric   if (MSFunc) {
1640b57cec5SDimitry Andric     if (CC == CallingConv::X86_FastCall)
1650b57cec5SDimitry Andric       Prefix = '@'; // fastcall functions have an @ prefix instead of _.
1660b57cec5SDimitry Andric     else if (CC == CallingConv::X86_VectorCall)
1670b57cec5SDimitry Andric       Prefix = '\0'; // vectorcall functions have no prefix.
1680b57cec5SDimitry Andric   }
1690b57cec5SDimitry Andric 
1700b57cec5SDimitry Andric   getNameWithPrefixImpl(OS, Name, PrefixTy, DL, Prefix);
1710b57cec5SDimitry Andric 
1720b57cec5SDimitry Andric   if (!MSFunc)
1730b57cec5SDimitry Andric     return;
1740b57cec5SDimitry Andric 
1750b57cec5SDimitry Andric   // If we are supposed to add a microsoft-style suffix for stdcall, fastcall,
1760b57cec5SDimitry Andric   // or vectorcall, add it.  These functions have a suffix of @N where N is the
1770b57cec5SDimitry Andric   // cumulative byte size of all of the parameters to the function in decimal.
1780b57cec5SDimitry Andric   if (CC == CallingConv::X86_VectorCall)
1790b57cec5SDimitry Andric     OS << '@'; // vectorcall functions use a double @ suffix.
1800b57cec5SDimitry Andric   FunctionType *FT = MSFunc->getFunctionType();
1810b57cec5SDimitry Andric   if (hasByteCountSuffix(CC) &&
1820b57cec5SDimitry Andric       // "Pure" variadic functions do not receive @0 suffix.
1830b57cec5SDimitry Andric       (!FT->isVarArg() || FT->getNumParams() == 0 ||
1840b57cec5SDimitry Andric        (FT->getNumParams() == 1 && MSFunc->hasStructRetAttr())))
1850b57cec5SDimitry Andric     addByteCountSuffix(OS, MSFunc, DL);
1860b57cec5SDimitry Andric }
1870b57cec5SDimitry Andric 
getNameWithPrefix(SmallVectorImpl<char> & OutName,const GlobalValue * GV,bool CannotUsePrivateLabel) const1880b57cec5SDimitry Andric void Mangler::getNameWithPrefix(SmallVectorImpl<char> &OutName,
1890b57cec5SDimitry Andric                                 const GlobalValue *GV,
1900b57cec5SDimitry Andric                                 bool CannotUsePrivateLabel) const {
1910b57cec5SDimitry Andric   raw_svector_ostream OS(OutName);
1920b57cec5SDimitry Andric   getNameWithPrefix(OS, GV, CannotUsePrivateLabel);
1930b57cec5SDimitry Andric }
1940b57cec5SDimitry Andric 
195e8d8bef9SDimitry Andric // Check if the name needs quotes to be safe for the linker to interpret.
canBeUnquotedInDirective(char C)196e8d8bef9SDimitry Andric static bool canBeUnquotedInDirective(char C) {
1970fca6ea1SDimitry Andric   return isAlnum(C) || C == '_' || C == '@' || C == '#';
198e8d8bef9SDimitry Andric }
199e8d8bef9SDimitry Andric 
canBeUnquotedInDirective(StringRef Name)200e8d8bef9SDimitry Andric static bool canBeUnquotedInDirective(StringRef Name) {
201e8d8bef9SDimitry Andric   if (Name.empty())
202e8d8bef9SDimitry Andric     return false;
203e8d8bef9SDimitry Andric 
204e8d8bef9SDimitry Andric   // If any of the characters in the string is an unacceptable character, force
205e8d8bef9SDimitry Andric   // quotes.
206e8d8bef9SDimitry Andric   for (char C : Name) {
207e8d8bef9SDimitry Andric     if (!canBeUnquotedInDirective(C))
208e8d8bef9SDimitry Andric       return false;
209e8d8bef9SDimitry Andric   }
210e8d8bef9SDimitry Andric 
211e8d8bef9SDimitry Andric   return true;
212e8d8bef9SDimitry Andric }
213e8d8bef9SDimitry Andric 
emitLinkerFlagsForGlobalCOFF(raw_ostream & OS,const GlobalValue * GV,const Triple & TT,Mangler & Mangler)2140b57cec5SDimitry Andric void llvm::emitLinkerFlagsForGlobalCOFF(raw_ostream &OS, const GlobalValue *GV,
2150b57cec5SDimitry Andric                                         const Triple &TT, Mangler &Mangler) {
216bdd1243dSDimitry Andric   if (GV->hasDLLExportStorageClass() && !GV->isDeclaration()) {
2170b57cec5SDimitry Andric 
2180b57cec5SDimitry Andric     if (TT.isWindowsMSVCEnvironment())
2190b57cec5SDimitry Andric       OS << " /EXPORT:";
2200b57cec5SDimitry Andric     else
2210b57cec5SDimitry Andric       OS << " -export:";
2220b57cec5SDimitry Andric 
223e8d8bef9SDimitry Andric     bool NeedQuotes = GV->hasName() && !canBeUnquotedInDirective(GV->getName());
224e8d8bef9SDimitry Andric     if (NeedQuotes)
225e8d8bef9SDimitry Andric       OS << "\"";
2260b57cec5SDimitry Andric     if (TT.isWindowsGNUEnvironment() || TT.isWindowsCygwinEnvironment()) {
2270b57cec5SDimitry Andric       std::string Flag;
2280b57cec5SDimitry Andric       raw_string_ostream FlagOS(Flag);
2290b57cec5SDimitry Andric       Mangler.getNameWithPrefix(FlagOS, GV, false);
2300b57cec5SDimitry Andric       FlagOS.flush();
2310fca6ea1SDimitry Andric       if (Flag[0] == GV->getDataLayout().getGlobalPrefix())
2320b57cec5SDimitry Andric         OS << Flag.substr(1);
2330b57cec5SDimitry Andric       else
2340b57cec5SDimitry Andric         OS << Flag;
2350b57cec5SDimitry Andric     } else {
2360b57cec5SDimitry Andric       Mangler.getNameWithPrefix(OS, GV, false);
2370b57cec5SDimitry Andric     }
2380fca6ea1SDimitry Andric     if (TT.isWindowsArm64EC()) {
2390fca6ea1SDimitry Andric       // Use EXPORTAS for mangled ARM64EC symbols.
2400fca6ea1SDimitry Andric       // FIXME: During LTO, we're invoked prior to the EC lowering pass,
2410fca6ea1SDimitry Andric       // so symbols are not yet mangled. Emitting the unmangled name
2420fca6ea1SDimitry Andric       // typically functions correctly; the linker can resolve the export
2430fca6ea1SDimitry Andric       // with the demangled alias.
2440fca6ea1SDimitry Andric       if (std::optional<std::string> demangledName =
2450fca6ea1SDimitry Andric               getArm64ECDemangledFunctionName(GV->getName()))
2460fca6ea1SDimitry Andric         OS << ",EXPORTAS," << *demangledName;
2470fca6ea1SDimitry Andric     }
248e8d8bef9SDimitry Andric     if (NeedQuotes)
249e8d8bef9SDimitry Andric       OS << "\"";
2500b57cec5SDimitry Andric 
2510b57cec5SDimitry Andric     if (!GV->getValueType()->isFunctionTy()) {
2520b57cec5SDimitry Andric       if (TT.isWindowsMSVCEnvironment())
2530b57cec5SDimitry Andric         OS << ",DATA";
2540b57cec5SDimitry Andric       else
2550b57cec5SDimitry Andric         OS << ",data";
2560b57cec5SDimitry Andric     }
2570b57cec5SDimitry Andric   }
258bdd1243dSDimitry Andric   if (GV->hasHiddenVisibility() && !GV->isDeclaration() && TT.isOSCygMing()) {
259bdd1243dSDimitry Andric 
260bdd1243dSDimitry Andric     OS << " -exclude-symbols:";
261bdd1243dSDimitry Andric 
262bdd1243dSDimitry Andric     bool NeedQuotes = GV->hasName() && !canBeUnquotedInDirective(GV->getName());
263bdd1243dSDimitry Andric     if (NeedQuotes)
264bdd1243dSDimitry Andric       OS << "\"";
265bdd1243dSDimitry Andric 
266bdd1243dSDimitry Andric     std::string Flag;
267bdd1243dSDimitry Andric     raw_string_ostream FlagOS(Flag);
268bdd1243dSDimitry Andric     Mangler.getNameWithPrefix(FlagOS, GV, false);
269bdd1243dSDimitry Andric     FlagOS.flush();
2700fca6ea1SDimitry Andric     if (Flag[0] == GV->getDataLayout().getGlobalPrefix())
271bdd1243dSDimitry Andric       OS << Flag.substr(1);
272bdd1243dSDimitry Andric     else
273bdd1243dSDimitry Andric       OS << Flag;
274bdd1243dSDimitry Andric 
275bdd1243dSDimitry Andric     if (NeedQuotes)
276bdd1243dSDimitry Andric       OS << "\"";
277bdd1243dSDimitry Andric   }
278bdd1243dSDimitry Andric }
2790b57cec5SDimitry Andric 
emitLinkerFlagsForUsedCOFF(raw_ostream & OS,const GlobalValue * GV,const Triple & T,Mangler & M)2800b57cec5SDimitry Andric void llvm::emitLinkerFlagsForUsedCOFF(raw_ostream &OS, const GlobalValue *GV,
2810b57cec5SDimitry Andric                                       const Triple &T, Mangler &M) {
2820b57cec5SDimitry Andric   if (!T.isWindowsMSVCEnvironment())
2830b57cec5SDimitry Andric     return;
2840b57cec5SDimitry Andric 
2850b57cec5SDimitry Andric   OS << " /INCLUDE:";
286e8d8bef9SDimitry Andric   bool NeedQuotes = GV->hasName() && !canBeUnquotedInDirective(GV->getName());
287e8d8bef9SDimitry Andric   if (NeedQuotes)
288e8d8bef9SDimitry Andric     OS << "\"";
2890b57cec5SDimitry Andric   M.getNameWithPrefix(OS, GV, false);
290e8d8bef9SDimitry Andric   if (NeedQuotes)
291e8d8bef9SDimitry Andric     OS << "\"";
2920b57cec5SDimitry Andric }
2930b57cec5SDimitry Andric 
getArm64ECMangledFunctionName(StringRef Name)2940fca6ea1SDimitry Andric std::optional<std::string> llvm::getArm64ECMangledFunctionName(StringRef Name) {
295*415efcecSDimitry Andric   if (Name[0] != '?') {
296*415efcecSDimitry Andric     // For non-C++ symbols, prefix the name with "#" unless it's already
297*415efcecSDimitry Andric     // mangled.
298*415efcecSDimitry Andric     if (Name[0] == '#')
2990fca6ea1SDimitry Andric       return std::nullopt;
300*415efcecSDimitry Andric     return std::optional<std::string>(("#" + Name).str());
301*415efcecSDimitry Andric   }
302*415efcecSDimitry Andric 
303*415efcecSDimitry Andric   // If the name contains $$h, then it is already mangled.
304*415efcecSDimitry Andric   if (Name.contains("$$h"))
3050fca6ea1SDimitry Andric     return std::nullopt;
3060fca6ea1SDimitry Andric 
307*415efcecSDimitry Andric   // Ask the demangler where we should insert "$$h".
308*415efcecSDimitry Andric   auto InsertIdx = getArm64ECInsertionPointInMangledName(Name);
309*415efcecSDimitry Andric   if (!InsertIdx)
310*415efcecSDimitry Andric     return std::nullopt;
3110fca6ea1SDimitry Andric 
3120fca6ea1SDimitry Andric   return std::optional<std::string>(
313*415efcecSDimitry Andric       (Name.substr(0, *InsertIdx) + "$$h" + Name.substr(*InsertIdx)).str());
3140fca6ea1SDimitry Andric }
3150fca6ea1SDimitry Andric 
3160fca6ea1SDimitry Andric std::optional<std::string>
getArm64ECDemangledFunctionName(StringRef Name)3170fca6ea1SDimitry Andric llvm::getArm64ECDemangledFunctionName(StringRef Name) {
3180fca6ea1SDimitry Andric   if (Name[0] == '#')
3190fca6ea1SDimitry Andric     return std::optional<std::string>(Name.substr(1));
3200fca6ea1SDimitry Andric   if (Name[0] != '?')
3210fca6ea1SDimitry Andric     return std::nullopt;
3220fca6ea1SDimitry Andric 
3230fca6ea1SDimitry Andric   std::pair<StringRef, StringRef> Pair = Name.split("$$h");
3240fca6ea1SDimitry Andric   if (Pair.second.empty())
3250fca6ea1SDimitry Andric     return std::nullopt;
3260fca6ea1SDimitry Andric   return std::optional<std::string>((Pair.first + Pair.second).str());
3270fca6ea1SDimitry Andric }
328