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
getNameWithPrefixImpl(raw_ostream & OS,const Twine & GVName,ManglerPrefixTy PrefixTy,const DataLayout & DL,char Prefix)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
getNameWithPrefixImpl(raw_ostream & OS,const Twine & GVName,const DataLayout & DL,ManglerPrefixTy PrefixTy)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
getNameWithPrefix(raw_ostream & OS,const Twine & GVName,const DataLayout & DL)71 void Mangler::getNameWithPrefix(raw_ostream &OS, const Twine &GVName,
72 const DataLayout &DL) {
73 return getNameWithPrefixImpl(OS, GVName, DL, Default);
74 }
75
getNameWithPrefix(SmallVectorImpl<char> & OutName,const Twine & GVName,const DataLayout & DL)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
hasByteCountSuffix(CallingConv::ID CC)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.
addByteCountSuffix(raw_ostream & OS,const Function * F,const DataLayout & DL)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
getNameWithPrefix(raw_ostream & OS,const GlobalValue * GV,bool CannotUsePrivateLabel) const121 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
getNameWithPrefix(SmallVectorImpl<char> & OutName,const GlobalValue * GV,bool CannotUsePrivateLabel) const188 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.
canBeUnquotedInDirective(char C)196 static bool canBeUnquotedInDirective(char C) {
197 return isAlnum(C) || C == '_' || C == '@' || C == '#';
198 }
199
canBeUnquotedInDirective(StringRef Name)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
emitLinkerFlagsForGlobalCOFF(raw_ostream & OS,const GlobalValue * GV,const Triple & TT,Mangler & Mangler)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
emitLinkerFlagsForUsedCOFF(raw_ostream & OS,const GlobalValue * GV,const Triple & T,Mangler & M)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
getArm64ECMangledFunctionName(StringRef Name)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>
getArm64ECDemangledFunctionName(StringRef Name)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