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
25using namespace llvm;
26
27namespace {
28enum 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
35static 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(Out&: 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(Start: 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
64static 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
71void Mangler::getNameWithPrefix(raw_ostream &OS, const Twine &GVName,
72 const DataLayout &DL) {
73 return getNameWithPrefixImpl(OS, GVName, DL, PrefixTy: Default);
74}
75
76void 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, PrefixTy: Default, DL, Prefix);
81}
82
83static 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.
96static 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(Ty: A.getType());
113
114 // Size should be aligned to pointer size.
115 ArgWords += alignTo(Value: AllocSize, Align: PtrSize);
116 }
117
118 OS << '@' << ArgWords;
119}
120
121void 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, GVName: "__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>(Val: GV->getAliaseeObject());
151
152 // Don't add byte count suffixes when '\01' or '?' are in the first
153 // character.
154 if (Name.starts_with(Prefix: "\01") ||
155 (DL.doNotMangleLeadingQuestionMark() && Name.starts_with(Prefix: "?")))
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, GVName: 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, F: MSFunc, DL);
186}
187
188void 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.
196static bool canBeUnquotedInDirective(char C) {
197 return isAlnum(C) || C == '_' || C == '@' || C == '#';
198}
199
200static 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
214void 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() || TT.isUEFI())
219 OS << " /EXPORT:";
220 else
221 OS << " -export:";
222
223 bool NeedQuotes = GV->hasName() && !canBeUnquotedInDirective(Name: 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(OS&: FlagOS, GV, CannotUsePrivateLabel: false);
230 if (Flag[0] == GV->getDataLayout().getGlobalPrefix())
231 OS << Flag.substr(pos: 1);
232 else
233 OS << Flag;
234 } else {
235 Mangler.getNameWithPrefix(OS, GV, CannotUsePrivateLabel: 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(Name: GV->getName()))
245 OS << ",EXPORTAS," << *demangledName;
246 }
247 if (NeedQuotes)
248 OS << "\"";
249
250 if (!GV->getValueType()->isFunctionTy()) {
251 if (TT.isWindowsMSVCEnvironment() || TT.isUEFI())
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(Name: GV->getName());
262 if (NeedQuotes)
263 OS << "\"";
264
265 std::string Flag;
266 raw_string_ostream FlagOS(Flag);
267 Mangler.getNameWithPrefix(OS&: FlagOS, GV, CannotUsePrivateLabel: false);
268 if (Flag[0] == GV->getDataLayout().getGlobalPrefix())
269 OS << Flag.substr(pos: 1);
270 else
271 OS << Flag;
272
273 if (NeedQuotes)
274 OS << "\"";
275 }
276}
277
278void llvm::emitLinkerFlagsForUsedCOFF(raw_ostream &OS, const GlobalValue *GV,
279 const Triple &T, Mangler &M) {
280 if (!T.isWindowsMSVCEnvironment())
281 return;
282
283 OS << " /INCLUDE:";
284 bool NeedQuotes = GV->hasName() && !canBeUnquotedInDirective(Name: GV->getName());
285 if (NeedQuotes)
286 OS << "\"";
287 M.getNameWithPrefix(OS, GV, CannotUsePrivateLabel: false);
288 if (NeedQuotes)
289 OS << "\"";
290}
291
292std::optional<std::string> llvm::getArm64ECMangledFunctionName(StringRef Name) {
293 assert(!Name.empty() &&
294 "getArm64ECMangledFunctionName requires non-empty name");
295
296 if (Name[0] != '?') {
297 // For non-C++ symbols, prefix the name with "#" unless it's already
298 // mangled.
299 if (Name[0] == '#')
300 return std::nullopt;
301 return std::optional<std::string>(("#" + Name).str());
302 }
303
304 // If the name contains $$h, then it is already mangled.
305 if (Name.contains(Other: "$$h"))
306 return std::nullopt;
307
308 // Handle MD5 mangled names, which use a slightly different rule from
309 // other C++ manglings.
310 //
311 // A non-Arm64EC function:
312 //
313 // ??@aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa@
314 //
315 // An Arm64EC function:
316 //
317 // ??@aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa@$$h@
318 if (Name.starts_with(Prefix: "??@") && Name.ends_with(Suffix: "@"))
319 return (Name + "$$h@").str();
320
321 // Ask the demangler where we should insert "$$h".
322 auto InsertIdx = getArm64ECInsertionPointInMangledName(MangledName: Name);
323 if (!InsertIdx)
324 return std::nullopt;
325
326 return std::optional<std::string>(
327 (Name.substr(Start: 0, N: *InsertIdx) + "$$h" + Name.substr(Start: *InsertIdx)).str());
328}
329
330std::optional<std::string>
331llvm::getArm64ECDemangledFunctionName(StringRef Name) {
332 // For non-C++ names, drop the "#" prefix.
333 if (Name[0] == '#')
334 return std::optional<std::string>(Name.substr(Start: 1));
335 if (Name[0] != '?')
336 return std::nullopt;
337
338 // MD5 mangled name; see comment in getArm64ECMangledFunctionName.
339 if (Name.starts_with(Prefix: "??@") && Name.ends_with(Suffix: "@$$h@"))
340 return Name.drop_back(N: 4).str();
341
342 // Drop the ARM64EC "$$h" tag.
343 std::pair<StringRef, StringRef> Pair = Name.split(Separator: "$$h");
344 if (Pair.second.empty())
345 return std::nullopt;
346 return std::optional<std::string>((Pair.first + Pair.second).str());
347}
348