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(Out&: 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(Start: 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, PrefixTy: 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, PrefixTy: 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(Ty: A.getType()); |
112 | |
113 | // Size should be aligned to pointer size. |
114 | ArgWords += alignTo(Value: AllocSize, Align: 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, GVName: "__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>(Val: GV->getAliaseeObject()); |
150 | |
151 | // Don't add byte count suffixes when '\01' or '?' are in the first |
152 | // character. |
153 | if (Name.starts_with(Prefix: "\01" ) || |
154 | (DL.doNotMangleLeadingQuestionMark() && Name.starts_with(Prefix: "?" ))) |
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, GVName: 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, F: 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(Name: 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(OS&: FlagOS, GV, CannotUsePrivateLabel: false); |
229 | FlagOS.flush(); |
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()) |
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 | FlagOS.flush(); |
269 | if (Flag[0] == GV->getDataLayout().getGlobalPrefix()) |
270 | OS << Flag.substr(pos: 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(Name: GV->getName()); |
286 | if (NeedQuotes) |
287 | OS << "\"" ; |
288 | M.getNameWithPrefix(OS, GV, CannotUsePrivateLabel: 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(Other: "$$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(Str: "@@" ); |
304 | size_t ThreeAtSignsIdx = Name.find(Str: "@@@" ); |
305 | if (InsertIdx != std::string::npos && InsertIdx != ThreeAtSignsIdx) { |
306 | InsertIdx += 2; |
307 | } else { |
308 | InsertIdx = Name.find(Str: "@" ); |
309 | if (InsertIdx != std::string::npos) |
310 | InsertIdx++; |
311 | } |
312 | } else { |
313 | Prefix = "#" ; |
314 | } |
315 | |
316 | return std::optional<std::string>( |
317 | (Name.substr(Start: 0, N: InsertIdx) + Prefix + Name.substr(Start: 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(Start: 1)); |
324 | if (Name[0] != '?') |
325 | return std::nullopt; |
326 | |
327 | std::pair<StringRef, StringRef> Pair = Name.split(Separator: "$$h" ); |
328 | if (Pair.second.empty()) |
329 | return std::nullopt; |
330 | return std::optional<std::string>((Pair.first + Pair.second).str()); |
331 | } |
332 | |