Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/lib/IR/Mangler.cpp
35233 views
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
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
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
71
void Mangler::getNameWithPrefix(raw_ostream &OS, const Twine &GVName,
72
const DataLayout &DL) {
73
return getNameWithPrefixImpl(OS, GVName, DL, Default);
74
}
75
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
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.
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
121
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
188
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.
196
static bool canBeUnquotedInDirective(char C) {
197
return isAlnum(C) || C == '_' || C == '@' || C == '#';
198
}
199
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
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
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
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>
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
329