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