]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
New upstream version 1.70.0+dfsg1
[rustc.git] / compiler / rustc_llvm / llvm-wrapper / PassWrapper.cpp
CommitLineData
1a4d82fc
JJ
1#include <stdio.h>
2
041b39d2 3#include <vector>
ff7c6d11 4#include <set>
041b39d2 5
1b1a35ee 6#include "LLVMWrapper.h"
970d7e83 7
6a06907d 8#include "llvm/Analysis/AliasAnalysis.h"
62682a34
SL
9#include "llvm/Analysis/TargetLibraryInfo.h"
10#include "llvm/Analysis/TargetTransformInfo.h"
0731742a 11#include "llvm/CodeGen/TargetSubtargetInfo.h"
5bcae85e 12#include "llvm/IR/AutoUpgrade.h"
041b39d2 13#include "llvm/IR/AssemblyAnnotationWriter.h"
0731742a 14#include "llvm/IR/IntrinsicInst.h"
74b04a01 15#include "llvm/IR/Verifier.h"
9ffffee4 16#include "llvm/MC/TargetRegistry.h"
f9f354fc
XL
17#include "llvm/Object/ObjectFile.h"
18#include "llvm/Object/IRObjectFile.h"
74b04a01 19#include "llvm/Passes/PassBuilder.h"
a2a8927a 20#include "llvm/Passes/PassPlugin.h"
74b04a01 21#include "llvm/Passes/StandardInstrumentations.h"
32a655c1
SL
22#include "llvm/Support/CBindingWrapping.h"
23#include "llvm/Support/FileSystem.h"
9ffffee4
FG
24#if LLVM_VERSION_GE(17, 0)
25#include "llvm/Support/VirtualFileSystem.h"
3c0e092e 26#endif
9ffffee4 27#include "llvm/Support/Host.h"
c1a9b12d 28#include "llvm/Target/TargetMachine.h"
476ff2be 29#include "llvm/Transforms/IPO/AlwaysInliner.h"
ea8adc8c 30#include "llvm/Transforms/IPO/FunctionImport.h"
2b03887a 31#include "llvm/Transforms/IPO/Internalize.h"
f2b60f7d 32#include "llvm/Transforms/IPO/ThinLTOBitcodeWriter.h"
c295e0f8 33#include "llvm/Transforms/Utils/AddDiscriminators.h"
ea8adc8c
XL
34#include "llvm/Transforms/Utils/FunctionImportUtils.h"
35#include "llvm/LTO/LTO.h"
2b03887a 36#include "llvm/Bitcode/BitcodeWriter.h"
970d7e83 37
60c5eb7d 38#include "llvm/Transforms/Instrumentation.h"
60c5eb7d 39#include "llvm/Transforms/Instrumentation/AddressSanitizer.h"
74b04a01 40#include "llvm/Support/TimeProfiler.h"
17df50a5
XL
41#include "llvm/Transforms/Instrumentation/GCOVProfiler.h"
42#include "llvm/Transforms/Instrumentation/InstrProfiling.h"
60c5eb7d
XL
43#include "llvm/Transforms/Instrumentation/ThreadSanitizer.h"
44#include "llvm/Transforms/Instrumentation/MemorySanitizer.h"
6a06907d 45#include "llvm/Transforms/Instrumentation/HWAddressSanitizer.h"
74b04a01 46#include "llvm/Transforms/Utils/CanonicalizeAliases.h"
74b04a01 47#include "llvm/Transforms/Utils/NameAnonGlobals.h"
c295e0f8 48#include "llvm/Transforms/Utils.h"
60c5eb7d 49
1a4d82fc 50using namespace llvm;
970d7e83 51
1a4d82fc
JJ
52typedef struct LLVMOpaquePass *LLVMPassRef;
53typedef struct LLVMOpaqueTargetMachine *LLVMTargetMachineRef;
54
55DEFINE_STDCXX_CONVERSION_FUNCTIONS(Pass, LLVMPassRef)
56DEFINE_STDCXX_CONVERSION_FUNCTIONS(TargetMachine, LLVMTargetMachineRef)
970d7e83 57
74b04a01 58extern "C" void LLVMTimeTraceProfilerInitialize() {
ba9703b0
XL
59 timeTraceProfilerInitialize(
60 /* TimeTraceGranularity */ 0,
61 /* ProcName */ "rustc");
74b04a01
XL
62}
63
3c0e092e
XL
64extern "C" void LLVMTimeTraceProfilerFinishThread() {
65 timeTraceProfilerFinishThread();
66}
67
74b04a01 68extern "C" void LLVMTimeTraceProfilerFinish(const char* FileName) {
74b04a01
XL
69 StringRef FN(FileName);
70 std::error_code EC;
71 raw_fd_ostream OS(FN, EC, sys::fs::CD_CreateAlways);
72
73 timeTraceProfilerWrite(OS);
74 timeTraceProfilerCleanup();
74b04a01
XL
75}
76
a7813a04
XL
77#ifdef LLVM_COMPONENT_X86
78#define SUBTARGET_X86 SUBTARGET(X86)
79#else
80#define SUBTARGET_X86
81#endif
82
83#ifdef LLVM_COMPONENT_ARM
84#define SUBTARGET_ARM SUBTARGET(ARM)
85#else
86#define SUBTARGET_ARM
87#endif
88
89#ifdef LLVM_COMPONENT_AARCH64
90#define SUBTARGET_AARCH64 SUBTARGET(AArch64)
91#else
92#define SUBTARGET_AARCH64
93#endif
94
f035d41b
XL
95#ifdef LLVM_COMPONENT_AVR
96#define SUBTARGET_AVR SUBTARGET(AVR)
97#else
98#define SUBTARGET_AVR
99#endif
100
c295e0f8
XL
101#ifdef LLVM_COMPONENT_M68k
102#define SUBTARGET_M68K SUBTARGET(M68k)
103#else
104#define SUBTARGET_M68K
105#endif
106
a7813a04
XL
107#ifdef LLVM_COMPONENT_MIPS
108#define SUBTARGET_MIPS SUBTARGET(Mips)
109#else
110#define SUBTARGET_MIPS
111#endif
112
113#ifdef LLVM_COMPONENT_POWERPC
114#define SUBTARGET_PPC SUBTARGET(PPC)
115#else
116#define SUBTARGET_PPC
117#endif
118
9e0c209e
SL
119#ifdef LLVM_COMPONENT_SYSTEMZ
120#define SUBTARGET_SYSTEMZ SUBTARGET(SystemZ)
121#else
122#define SUBTARGET_SYSTEMZ
123#endif
124
476ff2be
SL
125#ifdef LLVM_COMPONENT_MSP430
126#define SUBTARGET_MSP430 SUBTARGET(MSP430)
127#else
128#define SUBTARGET_MSP430
129#endif
130
b7449926
XL
131#ifdef LLVM_COMPONENT_RISCV
132#define SUBTARGET_RISCV SUBTARGET(RISCV)
133#else
134#define SUBTARGET_RISCV
135#endif
136
32a655c1
SL
137#ifdef LLVM_COMPONENT_SPARC
138#define SUBTARGET_SPARC SUBTARGET(Sparc)
139#else
140#define SUBTARGET_SPARC
141#endif
142
7cac9316
XL
143#ifdef LLVM_COMPONENT_HEXAGON
144#define SUBTARGET_HEXAGON SUBTARGET(Hexagon)
145#else
146#define SUBTARGET_HEXAGON
147#endif
148
353b0b11
FG
149#ifdef LLVM_COMPONENT_LOONGARCH
150#define SUBTARGET_LOONGARCH SUBTARGET(LoongArch)
151#else
152#define SUBTARGET_LOONGARCH
153#endif
154
32a655c1
SL
155#define GEN_SUBTARGETS \
156 SUBTARGET_X86 \
157 SUBTARGET_ARM \
158 SUBTARGET_AARCH64 \
f035d41b 159 SUBTARGET_AVR \
c295e0f8 160 SUBTARGET_M68K \
32a655c1
SL
161 SUBTARGET_MIPS \
162 SUBTARGET_PPC \
163 SUBTARGET_SYSTEMZ \
164 SUBTARGET_MSP430 \
7cac9316 165 SUBTARGET_SPARC \
b7449926
XL
166 SUBTARGET_HEXAGON \
167 SUBTARGET_RISCV \
353b0b11 168 SUBTARGET_LOONGARCH \
32a655c1
SL
169
170#define SUBTARGET(x) \
171 namespace llvm { \
172 extern const SubtargetFeatureKV x##FeatureKV[]; \
173 extern const SubtargetFeatureKV x##SubTypeKV[]; \
a7813a04
XL
174 }
175
176GEN_SUBTARGETS
177#undef SUBTARGET
178
32a655c1
SL
179extern "C" bool LLVMRustHasFeature(LLVMTargetMachineRef TM,
180 const char *Feature) {
181 TargetMachine *Target = unwrap(TM);
182 const MCSubtargetInfo *MCInfo = Target->getMCSubtargetInfo();
0531ce1d 183 return MCInfo->checkFeatures(std::string("+") + Feature);
a7813a04
XL
184}
185
5bcae85e 186enum class LLVMRustCodeModel {
f9f354fc 187 Tiny,
32a655c1
SL
188 Small,
189 Kernel,
190 Medium,
191 Large,
2c00a5a8 192 None,
5bcae85e
SL
193};
194
487cf647
FG
195#if LLVM_VERSION_LT(16, 0)
196static Optional<CodeModel::Model>
197#else
198static std::optional<CodeModel::Model>
199#endif
200fromRust(LLVMRustCodeModel Model) {
32a655c1 201 switch (Model) {
f9f354fc
XL
202 case LLVMRustCodeModel::Tiny:
203 return CodeModel::Tiny;
32a655c1
SL
204 case LLVMRustCodeModel::Small:
205 return CodeModel::Small;
206 case LLVMRustCodeModel::Kernel:
207 return CodeModel::Kernel;
208 case LLVMRustCodeModel::Medium:
209 return CodeModel::Medium;
210 case LLVMRustCodeModel::Large:
211 return CodeModel::Large;
f9f354fc 212 case LLVMRustCodeModel::None:
9c376795 213#if LLVM_VERSION_LT(16, 0)
f9f354fc 214 return None;
9c376795
FG
215#else
216 return std::nullopt;
217#endif
32a655c1 218 default:
ff7c6d11 219 report_fatal_error("Bad CodeModel.");
5bcae85e
SL
220 }
221}
222
223enum class LLVMRustCodeGenOptLevel {
32a655c1
SL
224 None,
225 Less,
226 Default,
227 Aggressive,
5bcae85e
SL
228};
229
32a655c1
SL
230static CodeGenOpt::Level fromRust(LLVMRustCodeGenOptLevel Level) {
231 switch (Level) {
232 case LLVMRustCodeGenOptLevel::None:
233 return CodeGenOpt::None;
234 case LLVMRustCodeGenOptLevel::Less:
235 return CodeGenOpt::Less;
236 case LLVMRustCodeGenOptLevel::Default:
237 return CodeGenOpt::Default;
238 case LLVMRustCodeGenOptLevel::Aggressive:
239 return CodeGenOpt::Aggressive;
240 default:
ff7c6d11 241 report_fatal_error("Bad CodeGenOptLevel.");
5bcae85e
SL
242 }
243}
244
74b04a01
XL
245enum class LLVMRustPassBuilderOptLevel {
246 O0,
247 O1,
248 O2,
249 O3,
250 Os,
251 Oz,
252};
253
94222f64 254static OptimizationLevel fromRust(LLVMRustPassBuilderOptLevel Level) {
74b04a01
XL
255 switch (Level) {
256 case LLVMRustPassBuilderOptLevel::O0:
94222f64 257 return OptimizationLevel::O0;
74b04a01 258 case LLVMRustPassBuilderOptLevel::O1:
94222f64 259 return OptimizationLevel::O1;
74b04a01 260 case LLVMRustPassBuilderOptLevel::O2:
94222f64 261 return OptimizationLevel::O2;
74b04a01 262 case LLVMRustPassBuilderOptLevel::O3:
94222f64 263 return OptimizationLevel::O3;
74b04a01 264 case LLVMRustPassBuilderOptLevel::Os:
94222f64 265 return OptimizationLevel::Os;
74b04a01 266 case LLVMRustPassBuilderOptLevel::Oz:
94222f64 267 return OptimizationLevel::Oz;
74b04a01
XL
268 default:
269 report_fatal_error("Bad PassBuilderOptLevel.");
270 }
271}
272
f9f354fc 273enum class LLVMRustRelocModel {
7cac9316
XL
274 Static,
275 PIC,
276 DynamicNoPic,
277 ROPI,
278 RWPI,
279 ROPIRWPI,
280};
281
f9f354fc 282static Reloc::Model fromRust(LLVMRustRelocModel RustReloc) {
7cac9316 283 switch (RustReloc) {
f9f354fc 284 case LLVMRustRelocModel::Static:
7cac9316 285 return Reloc::Static;
f9f354fc 286 case LLVMRustRelocModel::PIC:
7cac9316 287 return Reloc::PIC_;
f9f354fc 288 case LLVMRustRelocModel::DynamicNoPic:
7cac9316 289 return Reloc::DynamicNoPIC;
f9f354fc 290 case LLVMRustRelocModel::ROPI:
7cac9316 291 return Reloc::ROPI;
f9f354fc 292 case LLVMRustRelocModel::RWPI:
7cac9316 293 return Reloc::RWPI;
f9f354fc 294 case LLVMRustRelocModel::ROPIRWPI:
7cac9316 295 return Reloc::ROPI_RWPI;
7cac9316 296 }
ff7c6d11 297 report_fatal_error("Bad RelocModel.");
7cac9316
XL
298}
299
a1dfa0c6 300#ifdef LLVM_RUSTLLVM
5bcae85e 301/// getLongestEntryLength - Return the length of the longest entry in the table.
416331ca
XL
302template<typename KV>
303static size_t getLongestEntryLength(ArrayRef<KV> Table) {
5bcae85e
SL
304 size_t MaxLen = 0;
305 for (auto &I : Table)
306 MaxLen = std::max(MaxLen, std::strlen(I.Key));
307 return MaxLen;
308}
309
32a655c1
SL
310extern "C" void LLVMRustPrintTargetCPUs(LLVMTargetMachineRef TM) {
311 const TargetMachine *Target = unwrap(TM);
312 const MCSubtargetInfo *MCInfo = Target->getMCSubtargetInfo();
ea8adc8c
XL
313 const Triple::ArchType HostArch = Triple(sys::getProcessTriple()).getArch();
314 const Triple::ArchType TargetArch = Target->getTargetTriple().getArch();
416331ca 315 const ArrayRef<SubtargetSubTypeKV> CPUTable = MCInfo->getCPUTable();
32a655c1
SL
316 unsigned MaxCPULen = getLongestEntryLength(CPUTable);
317
318 printf("Available CPUs for this target:\n");
ea8adc8c
XL
319 if (HostArch == TargetArch) {
320 const StringRef HostCPU = sys::getHostCPUName();
321 printf(" %-*s - Select the CPU of the current host (currently %.*s).\n",
322 MaxCPULen, "native", (int)HostCPU.size(), HostCPU.data());
323 }
32a655c1 324 for (auto &CPU : CPUTable)
416331ca 325 printf(" %-*s\n", MaxCPULen, CPU.Key);
32a655c1 326 printf("\n");
5bcae85e
SL
327}
328
cdc7bbd5 329extern "C" size_t LLVMRustGetTargetFeaturesCount(LLVMTargetMachineRef TM) {
32a655c1
SL
330 const TargetMachine *Target = unwrap(TM);
331 const MCSubtargetInfo *MCInfo = Target->getMCSubtargetInfo();
332 const ArrayRef<SubtargetFeatureKV> FeatTable = MCInfo->getFeatureTable();
cdc7bbd5
XL
333 return FeatTable.size();
334}
32a655c1 335
cdc7bbd5
XL
336extern "C" void LLVMRustGetTargetFeature(LLVMTargetMachineRef TM, size_t Index,
337 const char** Feature, const char** Desc) {
338 const TargetMachine *Target = unwrap(TM);
339 const MCSubtargetInfo *MCInfo = Target->getMCSubtargetInfo();
340 const ArrayRef<SubtargetFeatureKV> FeatTable = MCInfo->getFeatureTable();
341 const SubtargetFeatureKV Feat = FeatTable[Index];
342 *Feature = Feat.Key;
343 *Desc = Feat.Desc;
5bcae85e
SL
344}
345
346#else
347
32a655c1
SL
348extern "C" void LLVMRustPrintTargetCPUs(LLVMTargetMachineRef) {
349 printf("Target CPU help is not supported by this LLVM version.\n\n");
5bcae85e
SL
350}
351
cdc7bbd5
XL
352extern "C" size_t LLVMRustGetTargetFeaturesCount(LLVMTargetMachineRef) {
353 return 0;
5bcae85e 354}
cdc7bbd5
XL
355
356extern "C" void LLVMRustGetTargetFeature(LLVMTargetMachineRef, const char**, const char**) {}
5bcae85e
SL
357#endif
358
b7449926
XL
359extern "C" const char* LLVMRustGetHostCPUName(size_t *len) {
360 StringRef Name = sys::getHostCPUName();
361 *len = Name.size();
362 return Name.data();
363}
364
32a655c1
SL
365extern "C" LLVMTargetMachineRef LLVMRustCreateTargetMachine(
366 const char *TripleStr, const char *CPU, const char *Feature,
f9f354fc 367 const char *ABIStr, LLVMRustCodeModel RustCM, LLVMRustRelocModel RustReloc,
32a655c1 368 LLVMRustCodeGenOptLevel RustOptLevel, bool UseSoftFloat,
f9f354fc 369 bool FunctionSections,
abe05a73 370 bool DataSections,
3c0e092e 371 bool UniqueSectionNames,
abe05a73 372 bool TrapUnreachable,
b7449926 373 bool Singlethread,
0bf4aa26 374 bool AsmComments,
60c5eb7d 375 bool EmitStackSizeSection,
f9f354fc 376 bool RelaxELFRelocations,
fc512014 377 bool UseInitArray,
353b0b11
FG
378 const char *SplitDwarfFile,
379 bool ForceEmulatedTls) {
5bcae85e 380
32a655c1 381 auto OptLevel = fromRust(RustOptLevel);
7cac9316 382 auto RM = fromRust(RustReloc);
f9f354fc 383 auto CM = fromRust(RustCM);
5bcae85e 384
32a655c1
SL
385 std::string Error;
386 Triple Trip(Triple::normalize(TripleStr));
387 const llvm::Target *TheTarget =
388 TargetRegistry::lookupTarget(Trip.getTriple(), Error);
389 if (TheTarget == nullptr) {
390 LLVMRustSetLastError(Error.c_str());
391 return nullptr;
392 }
1a4d82fc 393
32a655c1 394 TargetOptions Options;
5bcae85e 395
32a655c1
SL
396 Options.FloatABIType = FloatABI::Default;
397 if (UseSoftFloat) {
398 Options.FloatABIType = FloatABI::Soft;
399 }
400 Options.DataSections = DataSections;
401 Options.FunctionSections = FunctionSections;
3c0e092e 402 Options.UniqueSectionNames = UniqueSectionNames;
b7449926
XL
403 Options.MCOptions.AsmVerbose = AsmComments;
404 Options.MCOptions.PreserveAsmComments = AsmComments;
60c5eb7d 405 Options.MCOptions.ABIName = ABIStr;
fc512014
XL
406 if (SplitDwarfFile) {
407 Options.MCOptions.SplitDwarfFile = SplitDwarfFile;
408 }
60c5eb7d 409 Options.RelaxELFRelocations = RelaxELFRelocations;
f9f354fc 410 Options.UseInitArray = UseInitArray;
353b0b11
FG
411 if (ForceEmulatedTls) {
412 Options.ExplicitEmulatedTLS = true;
413 Options.EmulatedTLS = true;
414 }
32a655c1 415
abe05a73 416 if (TrapUnreachable) {
94b46f34 417 // Tell LLVM to codegen `unreachable` into an explicit trap instruction.
abe05a73
XL
418 // This limits the extent of possible undefined behavior in some cases, as
419 // it prevents control flow from "falling through" into whatever code
420 // happens to be laid out next in memory.
421 Options.TrapUnreachable = true;
422 }
423
424 if (Singlethread) {
425 Options.ThreadModel = ThreadModel::Single;
426 }
427
0bf4aa26
XL
428 Options.EmitStackSizeSection = EmitStackSizeSection;
429
32a655c1 430 TargetMachine *TM = TheTarget->createTargetMachine(
b7449926 431 Trip.getTriple(), CPU, Feature, Options, RM, CM, OptLevel);
32a655c1 432 return wrap(TM);
1a4d82fc
JJ
433}
434
32a655c1
SL
435extern "C" void LLVMRustDisposeTargetMachine(LLVMTargetMachineRef TM) {
436 delete unwrap(TM);
1a4d82fc
JJ
437}
438
1a4d82fc
JJ
439// Unfortunately, the LLVM C API doesn't provide a way to create the
440// TargetLibraryInfo pass, so we use this method to do so.
32a655c1
SL
441extern "C" void LLVMRustAddLibraryInfo(LLVMPassManagerRef PMR, LLVMModuleRef M,
442 bool DisableSimplifyLibCalls) {
443 Triple TargetTriple(unwrap(M)->getTargetTriple());
444 TargetLibraryInfoImpl TLII(TargetTriple);
445 if (DisableSimplifyLibCalls)
446 TLII.disableAllFunctions();
447 unwrap(PMR)->add(new TargetLibraryInfoWrapperPass(TLII));
1a4d82fc
JJ
448}
449
32a655c1
SL
450extern "C" void LLVMRustSetLLVMOptions(int Argc, char **Argv) {
451 // Initializing the command-line options more than once is not allowed. So,
9c376795 452 // check if they've already been initialized. (This could happen if we're
32a655c1
SL
453 // being called from rustpkg, for example). If the arguments change, then
454 // that's just kinda unfortunate.
455 static bool Initialized = false;
456 if (Initialized)
457 return;
458 Initialized = true;
459 cl::ParseCommandLineOptions(Argc, Argv);
1a4d82fc
JJ
460}
461
5bcae85e 462enum class LLVMRustFileType {
32a655c1
SL
463 AssemblyFile,
464 ObjectFile,
5bcae85e
SL
465};
466
dfeec247
XL
467static CodeGenFileType fromRust(LLVMRustFileType Type) {
468 switch (Type) {
469 case LLVMRustFileType::AssemblyFile:
470 return CGFT_AssemblyFile;
471 case LLVMRustFileType::ObjectFile:
472 return CGFT_ObjectFile;
473 default:
474 report_fatal_error("Bad FileType.");
475 }
476}
5bcae85e
SL
477
478extern "C" LLVMRustResult
32a655c1 479LLVMRustWriteOutputFile(LLVMTargetMachineRef Target, LLVMPassManagerRef PMR,
fc512014 480 LLVMModuleRef M, const char *Path, const char *DwoPath,
32a655c1 481 LLVMRustFileType RustFileType) {
5bcae85e 482 llvm::legacy::PassManager *PM = unwrap<llvm::legacy::PassManager>(PMR);
32a655c1 483 auto FileType = fromRust(RustFileType);
1a4d82fc
JJ
484
485 std::string ErrorInfo;
1a4d82fc 486 std::error_code EC;
17df50a5 487 raw_fd_ostream OS(Path, EC, sys::fs::OF_None);
1a4d82fc
JJ
488 if (EC)
489 ErrorInfo = EC.message();
1a4d82fc
JJ
490 if (ErrorInfo != "") {
491 LLVMRustSetLastError(ErrorInfo.c_str());
5bcae85e 492 return LLVMRustResult::Failure;
1a4d82fc 493 }
1a4d82fc 494
b7449926 495 buffer_ostream BOS(OS);
fc512014 496 if (DwoPath) {
17df50a5 497 raw_fd_ostream DOS(DwoPath, EC, sys::fs::OF_None);
fc512014
XL
498 EC.clear();
499 if (EC)
500 ErrorInfo = EC.message();
501 if (ErrorInfo != "") {
502 LLVMRustSetLastError(ErrorInfo.c_str());
503 return LLVMRustResult::Failure;
504 }
505 buffer_ostream DBOS(DOS);
506 unwrap(Target)->addPassesToEmitFile(*PM, BOS, &DBOS, FileType, false);
507 PM->run(*unwrap(M));
508 } else {
509 unwrap(Target)->addPassesToEmitFile(*PM, BOS, nullptr, FileType, false);
510 PM->run(*unwrap(M));
511 }
62682a34 512
b039eaaf 513 // Apparently `addPassesToEmitFile` adds a pointer to our on-the-stack output
62682a34
SL
514 // stream (OS), so the only real safe place to delete this is here? Don't we
515 // wish this was written in Rust?
60c5eb7d 516 LLVMDisposePassManager(PMR);
5bcae85e 517 return LLVMRustResult::Success;
1a4d82fc
JJ
518}
519
74b04a01
XL
520extern "C" typedef void (*LLVMRustSelfProfileBeforePassCallback)(void*, // LlvmSelfProfiler
521 const char*, // pass name
522 const char*); // IR name
523extern "C" typedef void (*LLVMRustSelfProfileAfterPassCallback)(void*); // LlvmSelfProfiler
524
74b04a01
XL
525std::string LLVMRustwrappedIrGetName(const llvm::Any &WrappedIr) {
526 if (any_isa<const Module *>(WrappedIr))
527 return any_cast<const Module *>(WrappedIr)->getName().str();
528 if (any_isa<const Function *>(WrappedIr))
529 return any_cast<const Function *>(WrappedIr)->getName().str();
530 if (any_isa<const Loop *>(WrappedIr))
531 return any_cast<const Loop *>(WrappedIr)->getName().str();
532 if (any_isa<const LazyCallGraph::SCC *>(WrappedIr))
533 return any_cast<const LazyCallGraph::SCC *>(WrappedIr)->getName();
534 return "<UNKNOWN>";
535}
536
537
538void LLVMSelfProfileInitializeCallbacks(
539 PassInstrumentationCallbacks& PIC, void* LlvmSelfProfiler,
540 LLVMRustSelfProfileBeforePassCallback BeforePassCallback,
541 LLVMRustSelfProfileAfterPassCallback AfterPassCallback) {
6a06907d
XL
542 PIC.registerBeforeNonSkippedPassCallback([LlvmSelfProfiler, BeforePassCallback](
543 StringRef Pass, llvm::Any Ir) {
544 std::string PassName = Pass.str();
545 std::string IrName = LLVMRustwrappedIrGetName(Ir);
546 BeforePassCallback(LlvmSelfProfiler, PassName.c_str(), IrName.c_str());
547 });
548
549 PIC.registerAfterPassCallback(
550 [LlvmSelfProfiler, AfterPassCallback](StringRef Pass, llvm::Any IR,
551 const PreservedAnalyses &Preserved) {
552 AfterPassCallback(LlvmSelfProfiler);
553 });
554
555 PIC.registerAfterPassInvalidatedCallback(
556 [LlvmSelfProfiler, AfterPassCallback](StringRef Pass, const PreservedAnalyses &Preserved) {
557 AfterPassCallback(LlvmSelfProfiler);
558 });
74b04a01
XL
559
560 PIC.registerBeforeAnalysisCallback([LlvmSelfProfiler, BeforePassCallback](
561 StringRef Pass, llvm::Any Ir) {
562 std::string PassName = Pass.str();
563 std::string IrName = LLVMRustwrappedIrGetName(Ir);
564 BeforePassCallback(LlvmSelfProfiler, PassName.c_str(), IrName.c_str());
565 });
566
567 PIC.registerAfterAnalysisCallback(
568 [LlvmSelfProfiler, AfterPassCallback](StringRef Pass, llvm::Any Ir) {
569 AfterPassCallback(LlvmSelfProfiler);
570 });
571}
74b04a01
XL
572
573enum class LLVMRustOptStage {
574 PreLinkNoLTO,
575 PreLinkThinLTO,
576 PreLinkFatLTO,
577 ThinLTO,
578 FatLTO,
579};
580
581struct LLVMRustSanitizerOptions {
f035d41b
XL
582 bool SanitizeAddress;
583 bool SanitizeAddressRecover;
74b04a01 584 bool SanitizeMemory;
f035d41b
XL
585 bool SanitizeMemoryRecover;
586 int SanitizeMemoryTrackOrigins;
74b04a01 587 bool SanitizeThread;
6a06907d
XL
588 bool SanitizeHWAddress;
589 bool SanitizeHWAddressRecover;
9ffffee4
FG
590 bool SanitizeKernelAddress;
591 bool SanitizeKernelAddressRecover;
74b04a01
XL
592};
593
17df50a5 594extern "C" LLVMRustResult
2b03887a 595LLVMRustOptimize(
74b04a01
XL
596 LLVMModuleRef ModuleRef,
597 LLVMTargetMachineRef TMRef,
598 LLVMRustPassBuilderOptLevel OptLevelRust,
599 LLVMRustOptStage OptStage,
600 bool NoPrepopulatePasses, bool VerifyIR, bool UseThinLTOBuffers,
601 bool MergeFunctions, bool UnrollLoops, bool SLPVectorize, bool LoopVectorize,
f9f354fc 602 bool DisableSimplifyLibCalls, bool EmitLifetimeMarkers,
74b04a01
XL
603 LLVMRustSanitizerOptions *SanitizerOptions,
604 const char *PGOGenPath, const char *PGOUsePath,
f2b60f7d
FG
605 bool InstrumentCoverage, const char *InstrProfileOutput,
606 bool InstrumentGCOV,
c295e0f8 607 const char *PGOSampleUsePath, bool DebugInfoForProfiling,
74b04a01
XL
608 void* LlvmSelfProfiler,
609 LLVMRustSelfProfileBeforePassCallback BeforePassCallback,
17df50a5 610 LLVMRustSelfProfileAfterPassCallback AfterPassCallback,
a2a8927a
XL
611 const char *ExtraPasses, size_t ExtraPassesLen,
612 const char *LLVMPlugins, size_t LLVMPluginsLen) {
74b04a01
XL
613 Module *TheModule = unwrap(ModuleRef);
614 TargetMachine *TM = unwrap(TMRef);
94222f64 615 OptimizationLevel OptLevel = fromRust(OptLevelRust);
74b04a01 616
74b04a01
XL
617
618 PipelineTuningOptions PTO;
619 PTO.LoopUnrolling = UnrollLoops;
620 PTO.LoopInterleaving = UnrollLoops;
621 PTO.LoopVectorization = LoopVectorize;
622 PTO.SLPVectorization = SLPVectorize;
6a06907d 623 PTO.MergeFunctions = MergeFunctions;
6a06907d
XL
624
625 // FIXME: We may want to expose this as an option.
626 bool DebugPassManager = false;
74b04a01
XL
627
628 PassInstrumentationCallbacks PIC;
487cf647 629#if LLVM_VERSION_LT(16, 0)
6a06907d 630 StandardInstrumentations SI(DebugPassManager);
487cf647
FG
631#else
632 StandardInstrumentations SI(TheModule->getContext(), DebugPassManager);
633#endif
74b04a01
XL
634 SI.registerCallbacks(PIC);
635
636 if (LlvmSelfProfiler){
637 LLVMSelfProfileInitializeCallbacks(PIC,LlvmSelfProfiler,BeforePassCallback,AfterPassCallback);
638 }
639
487cf647 640#if LLVM_VERSION_LT(16, 0)
74b04a01 641 Optional<PGOOptions> PGOOpt;
487cf647
FG
642#else
643 std::optional<PGOOptions> PGOOpt;
9ffffee4
FG
644#endif
645#if LLVM_VERSION_GE(17, 0)
646 auto FS = vfs::getRealFileSystem();
487cf647 647#endif
74b04a01 648 if (PGOGenPath) {
c295e0f8 649 assert(!PGOUsePath && !PGOSampleUsePath);
9ffffee4
FG
650 PGOOpt = PGOOptions(PGOGenPath, "", "",
651#if LLVM_VERSION_GE(17, 0)
652 FS,
653#endif
654 PGOOptions::IRInstr, PGOOptions::NoCSAction,
655 DebugInfoForProfiling);
74b04a01 656 } else if (PGOUsePath) {
c295e0f8 657 assert(!PGOSampleUsePath);
9ffffee4
FG
658 PGOOpt = PGOOptions(PGOUsePath, "", "",
659#if LLVM_VERSION_GE(17, 0)
660 FS,
661#endif
662 PGOOptions::IRUse, PGOOptions::NoCSAction,
663 DebugInfoForProfiling);
c295e0f8 664 } else if (PGOSampleUsePath) {
9ffffee4
FG
665 PGOOpt = PGOOptions(PGOSampleUsePath, "", "",
666#if LLVM_VERSION_GE(17, 0)
667 FS,
668#endif
669 PGOOptions::SampleUse, PGOOptions::NoCSAction,
670 DebugInfoForProfiling);
c295e0f8 671 } else if (DebugInfoForProfiling) {
9ffffee4
FG
672 PGOOpt = PGOOptions("", "", "",
673#if LLVM_VERSION_GE(17, 0)
674 FS,
675#endif
676 PGOOptions::NoAction, PGOOptions::NoCSAction,
677 DebugInfoForProfiling);
74b04a01
XL
678 }
679
3c0e092e 680 PassBuilder PB(TM, PTO, PGOOpt, &PIC);
17df50a5
XL
681 LoopAnalysisManager LAM;
682 FunctionAnalysisManager FAM;
683 CGSCCAnalysisManager CGAM;
684 ModuleAnalysisManager MAM;
74b04a01
XL
685
686 FAM.registerPass([&] { return PB.buildDefaultAAPipeline(); });
687
688 Triple TargetTriple(TheModule->getTargetTriple());
689 std::unique_ptr<TargetLibraryInfoImpl> TLII(new TargetLibraryInfoImpl(TargetTriple));
690 if (DisableSimplifyLibCalls)
691 TLII->disableAllFunctions();
692 FAM.registerPass([&] { return TargetLibraryAnalysis(*TLII); });
693
694 PB.registerModuleAnalyses(MAM);
695 PB.registerCGSCCAnalyses(CGAM);
696 PB.registerFunctionAnalyses(FAM);
697 PB.registerLoopAnalyses(LAM);
698 PB.crossRegisterProxies(LAM, FAM, CGAM, MAM);
699
700 // We manually collect pipeline callbacks so we can apply them at O0, where the
701 // PassBuilder does not create a pipeline.
94222f64 702 std::vector<std::function<void(ModulePassManager &, OptimizationLevel)>>
6a06907d 703 PipelineStartEPCallbacks;
94222f64 704 std::vector<std::function<void(ModulePassManager &, OptimizationLevel)>>
f035d41b 705 OptimizerLastEPCallbacks;
74b04a01
XL
706
707 if (VerifyIR) {
6a06907d 708 PipelineStartEPCallbacks.push_back(
94222f64 709 [VerifyIR](ModulePassManager &MPM, OptimizationLevel Level) {
74b04a01 710 MPM.addPass(VerifierPass());
6a06907d
XL
711 }
712 );
74b04a01
XL
713 }
714
17df50a5
XL
715 if (InstrumentGCOV) {
716 PipelineStartEPCallbacks.push_back(
94222f64 717 [](ModulePassManager &MPM, OptimizationLevel Level) {
17df50a5
XL
718 MPM.addPass(GCOVProfilerPass(GCOVOptions::getDefault()));
719 }
720 );
721 }
722
723 if (InstrumentCoverage) {
724 PipelineStartEPCallbacks.push_back(
f2b60f7d 725 [InstrProfileOutput](ModulePassManager &MPM, OptimizationLevel Level) {
17df50a5 726 InstrProfOptions Options;
f2b60f7d
FG
727 if (InstrProfileOutput) {
728 Options.InstrProfileOutput = InstrProfileOutput;
729 }
17df50a5
XL
730 MPM.addPass(InstrProfiling(Options, false));
731 }
732 );
733 }
734
74b04a01
XL
735 if (SanitizerOptions) {
736 if (SanitizerOptions->SanitizeMemory) {
f2b60f7d
FG
737 MemorySanitizerOptions Options(
738 SanitizerOptions->SanitizeMemoryTrackOrigins,
739 SanitizerOptions->SanitizeMemoryRecover,
740 /*CompileKernel=*/false,
741 /*EagerChecks=*/true);
f035d41b 742 OptimizerLastEPCallbacks.push_back(
94222f64 743 [Options](ModulePassManager &MPM, OptimizationLevel Level) {
9ffffee4 744#if LLVM_VERSION_LT(16, 0)
c295e0f8 745 MPM.addPass(ModuleMemorySanitizerPass(Options));
9ffffee4 746 MPM.addPass(createModuleToFunctionPassAdaptor(MemorySanitizerPass(Options)));
c295e0f8 747#else
f035d41b 748 MPM.addPass(MemorySanitizerPass(Options));
f2b60f7d 749#endif
f035d41b
XL
750 }
751 );
74b04a01
XL
752 }
753
754 if (SanitizerOptions->SanitizeThread) {
f035d41b 755 OptimizerLastEPCallbacks.push_back(
94222f64 756 [](ModulePassManager &MPM, OptimizationLevel Level) {
c295e0f8 757 MPM.addPass(ModuleThreadSanitizerPass());
f035d41b
XL
758 MPM.addPass(createModuleToFunctionPassAdaptor(ThreadSanitizerPass()));
759 }
760 );
74b04a01
XL
761 }
762
9ffffee4 763 if (SanitizerOptions->SanitizeAddress || SanitizerOptions->SanitizeKernelAddress) {
f035d41b 764 OptimizerLastEPCallbacks.push_back(
94222f64 765 [SanitizerOptions](ModulePassManager &MPM, OptimizationLevel Level) {
9ffffee4 766 auto CompileKernel = SanitizerOptions->SanitizeKernelAddress;
064997fb 767#if LLVM_VERSION_LT(15, 0)
f035d41b 768 MPM.addPass(RequireAnalysisPass<ASanGlobalsMetadataAnalysis, Module>());
064997fb 769#endif
3c0e092e 770 AddressSanitizerOptions opts = AddressSanitizerOptions{
9ffffee4
FG
771 CompileKernel,
772 SanitizerOptions->SanitizeAddressRecover
773 || SanitizerOptions->SanitizeKernelAddressRecover,
3c0e092e
XL
774 /*UseAfterScope=*/true,
775 AsanDetectStackUseAfterReturnMode::Runtime,
776 };
f2b60f7d 777#if LLVM_VERSION_LT(16, 0)
3c0e092e 778 MPM.addPass(ModuleAddressSanitizerPass(opts));
f2b60f7d
FG
779#else
780 MPM.addPass(AddressSanitizerPass(opts));
94222f64 781#endif
f035d41b
XL
782 }
783 );
6a06907d
XL
784 }
785 if (SanitizerOptions->SanitizeHWAddress) {
6a06907d 786 OptimizerLastEPCallbacks.push_back(
94222f64 787 [SanitizerOptions](ModulePassManager &MPM, OptimizationLevel Level) {
94222f64
XL
788 HWAddressSanitizerOptions opts(
789 /*CompileKernel=*/false, SanitizerOptions->SanitizeHWAddressRecover,
790 /*DisableOptimization=*/false);
791 MPM.addPass(HWAddressSanitizerPass(opts));
6a06907d
XL
792 }
793 );
74b04a01
XL
794 }
795 }
796
a2a8927a
XL
797 if (LLVMPluginsLen) {
798 auto PluginsStr = StringRef(LLVMPlugins, LLVMPluginsLen);
799 SmallVector<StringRef> Plugins;
800 PluginsStr.split(Plugins, ',', -1, false);
801 for (auto PluginPath: Plugins) {
802 auto Plugin = PassPlugin::Load(PluginPath.str());
803 if (!Plugin) {
804 LLVMRustSetLastError(("Failed to load pass plugin" + PluginPath.str()).c_str());
487cf647 805 return LLVMRustResult::Failure;
a2a8927a
XL
806 }
807 Plugin->registerPassBuilderCallbacks(PB);
808 }
809 }
810
17df50a5 811 ModulePassManager MPM;
6a06907d 812 bool NeedThinLTOBufferPasses = UseThinLTOBuffers;
74b04a01 813 if (!NoPrepopulatePasses) {
c295e0f8
XL
814 // The pre-link pipelines don't support O0 and require using budilO0DefaultPipeline() instead.
815 // At the same time, the LTO pipelines do support O0 and using them is required.
816 bool IsLTO = OptStage == LLVMRustOptStage::ThinLTO || OptStage == LLVMRustOptStage::FatLTO;
817 if (OptLevel == OptimizationLevel::O0 && !IsLTO) {
74b04a01 818 for (const auto &C : PipelineStartEPCallbacks)
6a06907d
XL
819 PB.registerPipelineStartEPCallback(C);
820 for (const auto &C : OptimizerLastEPCallbacks)
821 PB.registerOptimizerLastEPCallback(C);
74b04a01 822
6a06907d
XL
823 // Pass false as we manually schedule ThinLTOBufferPasses below.
824 MPM = PB.buildO0DefaultPipeline(OptLevel, /* PreLinkLTO */ false);
74b04a01
XL
825 } else {
826 for (const auto &C : PipelineStartEPCallbacks)
827 PB.registerPipelineStartEPCallback(C);
828 if (OptStage != LLVMRustOptStage::PreLinkThinLTO) {
829 for (const auto &C : OptimizerLastEPCallbacks)
830 PB.registerOptimizerLastEPCallback(C);
831 }
832
833 switch (OptStage) {
834 case LLVMRustOptStage::PreLinkNoLTO:
835 MPM = PB.buildPerModuleDefaultPipeline(OptLevel, DebugPassManager);
836 break;
837 case LLVMRustOptStage::PreLinkThinLTO:
6a06907d
XL
838 MPM = PB.buildThinLTOPreLinkDefaultPipeline(OptLevel);
839 // The ThinLTOPreLink pipeline already includes ThinLTOBuffer passes. However, callback
840 // passes may still run afterwards. This means we need to run the buffer passes again.
841 // FIXME: In LLVM 13, the ThinLTOPreLink pipeline also runs OptimizerLastEPCallbacks
842 // before the RequiredLTOPreLinkPasses, in which case we can remove these hacks.
843 if (OptimizerLastEPCallbacks.empty())
844 NeedThinLTOBufferPasses = false;
f035d41b
XL
845 for (const auto &C : OptimizerLastEPCallbacks)
846 C(MPM, OptLevel);
74b04a01
XL
847 break;
848 case LLVMRustOptStage::PreLinkFatLTO:
6a06907d
XL
849 MPM = PB.buildLTOPreLinkDefaultPipeline(OptLevel);
850 NeedThinLTOBufferPasses = false;
74b04a01
XL
851 break;
852 case LLVMRustOptStage::ThinLTO:
853 // FIXME: Does it make sense to pass the ModuleSummaryIndex?
854 // It only seems to be needed for C++ specific optimizations.
6a06907d 855 MPM = PB.buildThinLTODefaultPipeline(OptLevel, nullptr);
74b04a01
XL
856 break;
857 case LLVMRustOptStage::FatLTO:
6a06907d 858 MPM = PB.buildLTODefaultPipeline(OptLevel, nullptr);
74b04a01
XL
859 break;
860 }
861 }
04454e1e
FG
862 } else {
863 // We're not building any of the default pipelines but we still want to
864 // add the verifier, instrumentation, etc passes if they were requested
865 for (const auto &C : PipelineStartEPCallbacks)
866 C(MPM, OptLevel);
867 for (const auto &C : OptimizerLastEPCallbacks)
868 C(MPM, OptLevel);
74b04a01
XL
869 }
870
17df50a5
XL
871 if (ExtraPassesLen) {
872 if (auto Err = PB.parsePassPipeline(MPM, StringRef(ExtraPasses, ExtraPassesLen))) {
873 std::string ErrMsg = toString(std::move(Err));
874 LLVMRustSetLastError(ErrMsg.c_str());
875 return LLVMRustResult::Failure;
876 }
877 }
878
6a06907d 879 if (NeedThinLTOBufferPasses) {
74b04a01
XL
880 MPM.addPass(CanonicalizeAliasesPass());
881 MPM.addPass(NameAnonGlobalPass());
882 }
883
884 // Upgrade all calls to old intrinsics first.
885 for (Module::iterator I = TheModule->begin(), E = TheModule->end(); I != E;)
886 UpgradeCallsToIntrinsic(&*I++); // must be post-increment, as we remove
887
888 MPM.run(*TheModule, MAM);
17df50a5 889 return LLVMRustResult::Success;
74b04a01 890}
041b39d2
XL
891
892// Callback to demangle function name
893// Parameters:
894// * name to be demangled
895// * name len
896// * output buffer
897// * output buffer len
898// Returns len of demangled string, or 0 if demangle failed.
899typedef size_t (*DemangleFn)(const char*, size_t, char*, size_t);
900
901
902namespace {
903
904class RustAssemblyAnnotationWriter : public AssemblyAnnotationWriter {
905 DemangleFn Demangle;
906 std::vector<char> Buf;
907
908public:
909 RustAssemblyAnnotationWriter(DemangleFn Demangle) : Demangle(Demangle) {}
910
911 // Return empty string if demangle failed
912 // or if name does not need to be demangled
913 StringRef CallDemangle(StringRef name) {
914 if (!Demangle) {
915 return StringRef();
916 }
917
918 if (Buf.size() < name.size() * 2) {
919 // Semangled name usually shorter than mangled,
920 // but allocate twice as much memory just in case
921 Buf.resize(name.size() * 2);
922 }
923
924 auto R = Demangle(name.data(), name.size(), Buf.data(), Buf.size());
925 if (!R) {
926 // Demangle failed.
927 return StringRef();
928 }
929
930 auto Demangled = StringRef(Buf.data(), R);
931 if (Demangled == name) {
932 // Do not print anything if demangled name is equal to mangled.
933 return StringRef();
934 }
935
936 return Demangled;
937 }
938
939 void emitFunctionAnnot(const Function *F,
940 formatted_raw_ostream &OS) override {
941 StringRef Demangled = CallDemangle(F->getName());
942 if (Demangled.empty()) {
943 return;
944 }
945
946 OS << "; " << Demangled << "\n";
947 }
948
949 void emitInstructionAnnot(const Instruction *I,
950 formatted_raw_ostream &OS) override {
951 const char *Name;
952 const Value *Value;
953 if (const CallInst *CI = dyn_cast<CallInst>(I)) {
954 Name = "call";
f035d41b 955 Value = CI->getCalledOperand();
041b39d2
XL
956 } else if (const InvokeInst* II = dyn_cast<InvokeInst>(I)) {
957 Name = "invoke";
f035d41b 958 Value = II->getCalledOperand();
041b39d2
XL
959 } else {
960 // Could demangle more operations, e. g.
961 // `store %place, @function`.
962 return;
963 }
964
965 if (!Value->hasName()) {
966 return;
967 }
968
969 StringRef Demangled = CallDemangle(Value->getName());
970 if (Demangled.empty()) {
971 return;
972 }
973
974 OS << "; " << Name << " " << Demangled << "\n";
975 }
976};
977
041b39d2
XL
978} // namespace
979
532ac7d7 980extern "C" LLVMRustResult
60c5eb7d 981LLVMRustPrintModule(LLVMModuleRef M, const char *Path, DemangleFn Demangle) {
1a4d82fc 982 std::string ErrorInfo;
1a4d82fc 983 std::error_code EC;
17df50a5 984 raw_fd_ostream OS(Path, EC, sys::fs::OF_None);
1a4d82fc
JJ
985 if (EC)
986 ErrorInfo = EC.message();
532ac7d7
XL
987 if (ErrorInfo != "") {
988 LLVMRustSetLastError(ErrorInfo.c_str());
989 return LLVMRustResult::Failure;
990 }
1a4d82fc 991
60c5eb7d 992 RustAssemblyAnnotationWriter AAW(Demangle);
1a4d82fc 993 formatted_raw_ostream FOS(OS);
60c5eb7d 994 unwrap(M)->print(FOS, &AAW);
532ac7d7
XL
995
996 return LLVMRustResult::Success;
1a4d82fc
JJ
997}
998
32a655c1 999extern "C" void LLVMRustPrintPasses() {
9ffffee4
FG
1000 PassBuilder PB;
1001 PB.printPassNames(outs());
970d7e83
LB
1002}
1003
32a655c1
SL
1004extern "C" void LLVMRustRunRestrictionPass(LLVMModuleRef M, char **Symbols,
1005 size_t Len) {
32a655c1
SL
1006 auto PreserveFunctions = [=](const GlobalValue &GV) {
1007 for (size_t I = 0; I < Len; I++) {
1008 if (GV.getName() == Symbols[I]) {
1009 return true;
1010 }
1011 }
1012 return false;
1013 };
5bcae85e 1014
2b03887a 1015 internalizeModule(*unwrap(M), PreserveFunctions);
1a4d82fc
JJ
1016}
1017
c1a9b12d
SL
1018extern "C" void
1019LLVMRustSetDataLayoutFromTargetMachine(LLVMModuleRef Module,
1020 LLVMTargetMachineRef TMR) {
32a655c1
SL
1021 TargetMachine *Target = unwrap(TMR);
1022 unwrap(Module)->setDataLayout(Target->createDataLayout());
c1a9b12d
SL
1023}
1024
60c5eb7d
XL
1025extern "C" void LLVMRustSetModulePICLevel(LLVMModuleRef M) {
1026 unwrap(M)->setPICLevel(PICLevel::Level::BigPIC);
1027}
1028
32a655c1 1029extern "C" void LLVMRustSetModulePIELevel(LLVMModuleRef M) {
32a655c1 1030 unwrap(M)->setPIELevel(PIELevel::Level::Large);
5bcae85e 1031}
ea8adc8c 1032
6a06907d
XL
1033extern "C" void LLVMRustSetModuleCodeModel(LLVMModuleRef M,
1034 LLVMRustCodeModel Model) {
1035 auto CM = fromRust(Model);
2b03887a 1036 if (!CM)
6a06907d
XL
1037 return;
1038 unwrap(M)->setCodeModel(*CM);
1039}
1040
ea8adc8c
XL
1041// Here you'll find an implementation of ThinLTO as used by the Rust compiler
1042// right now. This ThinLTO support is only enabled on "recent ish" versions of
1043// LLVM, and otherwise it's just blanket rejected from other compilers.
1044//
1045// Most of this implementation is straight copied from LLVM. At the time of
1046// this writing it wasn't *quite* suitable to reuse more code from upstream
1047// for our purposes, but we should strive to upstream this support once it's
1048// ready to go! I figure we may want a bit of testing locally first before
1049// sending this upstream to LLVM. I hear though they're quite eager to receive
1050// feedback like this!
1051//
1052// If you're reading this code and wondering "what in the world" or you're
1053// working "good lord by LLVM upgrade is *still* failing due to these bindings"
1054// then fear not! (ok maybe fear a little). All code here is mostly based
1055// on `lib/LTO/ThinLTOCodeGenerator.cpp` in LLVM.
1056//
1057// You'll find that the general layout here roughly corresponds to the `run`
1058// method in that file as well as `ProcessThinLTOModule`. Functions are
1059// specifically commented below as well, but if you're updating this code
1060// or otherwise trying to understand it, the LLVM source will be useful in
1061// interpreting the mysteries within.
1062//
1063// Otherwise I'll apologize in advance, it probably requires a relatively
1064// significant investment on your part to "truly understand" what's going on
1065// here. Not saying I do myself, but it took me awhile staring at LLVM's source
1066// and various online resources about ThinLTO to make heads or tails of all
1067// this.
1068
ea8adc8c
XL
1069// This is a shared data structure which *must* be threadsafe to share
1070// read-only amongst threads. This also corresponds basically to the arguments
1071// of the `ProcessThinLTOModule` function in the LLVM source.
1072struct LLVMRustThinLTOData {
1073 // The combined index that is the global analysis over all modules we're
1074 // performing ThinLTO for. This is mostly managed by LLVM.
1075 ModuleSummaryIndex Index;
1076
1077 // All modules we may look at, stored as in-memory serialized versions. This
1078 // is later used when inlining to ensure we can extract any module to inline
1079 // from.
1080 StringMap<MemoryBufferRef> ModuleMap;
1081
1082 // A set that we manage of everything we *don't* want internalized. Note that
1083 // this includes all transitive references right now as well, but it may not
1084 // always!
1085 DenseSet<GlobalValue::GUID> GUIDPreservedSymbols;
1086
1087 // Not 100% sure what these are, but they impact what's internalized and
1088 // what's inlined across modules, I believe.
1089 StringMap<FunctionImporter::ImportMapTy> ImportLists;
1090 StringMap<FunctionImporter::ExportSetTy> ExportLists;
1091 StringMap<GVSummaryMapTy> ModuleToDefinedGVSummaries;
29967ef6 1092 StringMap<std::map<GlobalValue::GUID, GlobalValue::LinkageTypes>> ResolvedODR;
2c00a5a8 1093
9fa01778 1094 LLVMRustThinLTOData() : Index(/* HaveGVs = */ false) {}
ea8adc8c
XL
1095};
1096
1097// Just an argument to the `LLVMRustCreateThinLTOData` function below.
1098struct LLVMRustThinLTOModule {
1099 const char *identifier;
1100 const char *data;
1101 size_t len;
1102};
1103
1104// This is copied from `lib/LTO/ThinLTOCodeGenerator.cpp`, not sure what it
1105// does.
1106static const GlobalValueSummary *
1107getFirstDefinitionForLinker(const GlobalValueSummaryList &GVSummaryList) {
1108 auto StrongDefForLinker = llvm::find_if(
1109 GVSummaryList, [](const std::unique_ptr<GlobalValueSummary> &Summary) {
1110 auto Linkage = Summary->linkage();
1111 return !GlobalValue::isAvailableExternallyLinkage(Linkage) &&
1112 !GlobalValue::isWeakForLinker(Linkage);
1113 });
1114 if (StrongDefForLinker != GVSummaryList.end())
1115 return StrongDefForLinker->get();
1116
1117 auto FirstDefForLinker = llvm::find_if(
1118 GVSummaryList, [](const std::unique_ptr<GlobalValueSummary> &Summary) {
1119 auto Linkage = Summary->linkage();
1120 return !GlobalValue::isAvailableExternallyLinkage(Linkage);
1121 });
1122 if (FirstDefForLinker == GVSummaryList.end())
1123 return nullptr;
1124 return FirstDefForLinker->get();
1125}
1126
ea8adc8c
XL
1127// The main entry point for creating the global ThinLTO analysis. The structure
1128// here is basically the same as before threads are spawned in the `run`
1129// function of `lib/LTO/ThinLTOCodeGenerator.cpp`.
1130extern "C" LLVMRustThinLTOData*
1131LLVMRustCreateThinLTOData(LLVMRustThinLTOModule *modules,
1132 int num_modules,
1133 const char **preserved_symbols,
1134 int num_symbols) {
dfeec247 1135 auto Ret = std::make_unique<LLVMRustThinLTOData>();
ea8adc8c
XL
1136
1137 // Load each module's summary and merge it into one combined index
1138 for (int i = 0; i < num_modules; i++) {
1139 auto module = &modules[i];
1140 StringRef buffer(module->data, module->len);
1141 MemoryBufferRef mem_buffer(buffer, module->identifier);
1142
1143 Ret->ModuleMap[module->identifier] = mem_buffer;
1144
abe05a73
XL
1145 if (Error Err = readModuleSummaryIndex(mem_buffer, Ret->Index, i)) {
1146 LLVMRustSetLastError(toString(std::move(Err)).c_str());
1147 return nullptr;
1148 }
ea8adc8c
XL
1149 }
1150
1151 // Collect for each module the list of function it defines (GUID -> Summary)
1152 Ret->Index.collectDefinedGVSummariesPerModule(Ret->ModuleToDefinedGVSummaries);
1153
1154 // Convert the preserved symbols set from string to GUID, this is then needed
ff7c6d11 1155 // for internalization.
ea8adc8c 1156 for (int i = 0; i < num_symbols; i++) {
ff7c6d11
XL
1157 auto GUID = GlobalValue::getGUID(preserved_symbols[i]);
1158 Ret->GUIDPreservedSymbols.insert(GUID);
ea8adc8c
XL
1159 }
1160
1161 // Collect the import/export lists for all modules from the call-graph in the
1162 // combined index
1163 //
1164 // This is copied from `lib/LTO/ThinLTOCodeGenerator.cpp`
2c00a5a8
XL
1165 auto deadIsPrevailing = [&](GlobalValue::GUID G) {
1166 return PrevailingType::Unknown;
1167 };
48663c56
XL
1168 // We don't have a complete picture in our use of ThinLTO, just our immediate
1169 // crate, so we need `ImportEnabled = false` to limit internalization.
1170 // Otherwise, we sometimes lose `static` values -- see #60184.
9fa01778 1171 computeDeadSymbolsWithConstProp(Ret->Index, Ret->GUIDPreservedSymbols,
48663c56 1172 deadIsPrevailing, /* ImportEnabled = */ false);
ea8adc8c
XL
1173 // Resolve LinkOnce/Weak symbols, this has to be computed early be cause it
1174 // impacts the caching.
1175 //
ff7c6d11
XL
1176 // This is copied from `lib/LTO/ThinLTOCodeGenerator.cpp` with some of this
1177 // being lifted from `lib/LTO/LTO.cpp` as well
ea8adc8c
XL
1178 DenseMap<GlobalValue::GUID, const GlobalValueSummary *> PrevailingCopy;
1179 for (auto &I : Ret->Index) {
abe05a73
XL
1180 if (I.second.SummaryList.size() > 1)
1181 PrevailingCopy[I.first] = getFirstDefinitionForLinker(I.second.SummaryList);
ea8adc8c
XL
1182 }
1183 auto isPrevailing = [&](GlobalValue::GUID GUID, const GlobalValueSummary *S) {
1184 const auto &Prevailing = PrevailingCopy.find(GUID);
1185 if (Prevailing == PrevailingCopy.end())
1186 return true;
1187 return Prevailing->second == S;
1188 };
353b0b11
FG
1189 ComputeCrossModuleImport(
1190 Ret->Index,
1191 Ret->ModuleToDefinedGVSummaries,
1192#if LLVM_VERSION_GE(17, 0)
1193 isPrevailing,
1194#endif
1195 Ret->ImportLists,
1196 Ret->ExportLists
1197 );
1198
ea8adc8c
XL
1199 auto recordNewLinkage = [&](StringRef ModuleIdentifier,
1200 GlobalValue::GUID GUID,
1201 GlobalValue::LinkageTypes NewLinkage) {
29967ef6 1202 Ret->ResolvedODR[ModuleIdentifier][GUID] = NewLinkage;
ea8adc8c 1203 };
fc512014 1204
cdc7bbd5
XL
1205 // Uses FromPrevailing visibility scheme which works for many binary
1206 // formats. We probably could and should use ELF visibility scheme for many of
1207 // our targets, however.
1208 lto::Config conf;
1209 thinLTOResolvePrevailingInIndex(conf, Ret->Index, isPrevailing, recordNewLinkage,
1210 Ret->GUIDPreservedSymbols);
f2b60f7d 1211
ff7c6d11
XL
1212 // Here we calculate an `ExportedGUIDs` set for use in the `isExported`
1213 // callback below. This callback below will dictate the linkage for all
1214 // summaries in the index, and we basically just only want to ensure that dead
1215 // symbols are internalized. Otherwise everything that's already external
1216 // linkage will stay as external, and internal will stay as internal.
1217 std::set<GlobalValue::GUID> ExportedGUIDs;
1218 for (auto &List : Ret->Index) {
ff7c6d11 1219 for (auto &GVS: List.second.SummaryList) {
ff7c6d11
XL
1220 if (GlobalValue::isLocalLinkage(GVS->linkage()))
1221 continue;
1222 auto GUID = GVS->getOriginalName();
ff7c6d11 1223 if (GVS->flags().Live)
ff7c6d11
XL
1224 ExportedGUIDs.insert(GUID);
1225 }
1226 }
dfeec247
XL
1227 auto isExported = [&](StringRef ModuleIdentifier, ValueInfo VI) {
1228 const auto &ExportList = Ret->ExportLists.find(ModuleIdentifier);
1229 return (ExportList != Ret->ExportLists.end() &&
1230 ExportList->second.count(VI)) ||
1231 ExportedGUIDs.count(VI.getGUID());
1232 };
1233 thinLTOInternalizeAndPromoteInIndex(Ret->Index, isExported, isPrevailing);
ea8adc8c
XL
1234
1235 return Ret.release();
1236}
1237
1238extern "C" void
1239LLVMRustFreeThinLTOData(LLVMRustThinLTOData *Data) {
1240 delete Data;
1241}
1242
1243// Below are the various passes that happen *per module* when doing ThinLTO.
1244//
1245// In other words, these are the functions that are all run concurrently
1246// with one another, one per module. The passes here correspond to the analysis
1247// passes in `lib/LTO/ThinLTOCodeGenerator.cpp`, currently found in the
1248// `ProcessThinLTOModule` function. Here they're split up into separate steps
1249// so rustc can save off the intermediate bytecode between each step.
1250
f035d41b
XL
1251static bool
1252clearDSOLocalOnDeclarations(Module &Mod, TargetMachine &TM) {
1253 // When linking an ELF shared object, dso_local should be dropped. We
1254 // conservatively do this for -fpic.
1255 bool ClearDSOLocalOnDeclarations =
1256 TM.getTargetTriple().isOSBinFormatELF() &&
1257 TM.getRelocationModel() != Reloc::Static &&
1258 Mod.getPIELevel() == PIELevel::Default;
1259 return ClearDSOLocalOnDeclarations;
1260}
f035d41b 1261
ea8adc8c 1262extern "C" bool
f035d41b
XL
1263LLVMRustPrepareThinLTORename(const LLVMRustThinLTOData *Data, LLVMModuleRef M,
1264 LLVMTargetMachineRef TM) {
ea8adc8c 1265 Module &Mod = *unwrap(M);
f035d41b
XL
1266 TargetMachine &Target = *unwrap(TM);
1267
f035d41b
XL
1268 bool ClearDSOLocal = clearDSOLocalOnDeclarations(Mod, Target);
1269 bool error = renameModuleForThinLTO(Mod, Data->Index, ClearDSOLocal);
f035d41b
XL
1270
1271 if (error) {
ea8adc8c
XL
1272 LLVMRustSetLastError("renameModuleForThinLTO failed");
1273 return false;
1274 }
1275 return true;
1276}
1277
1278extern "C" bool
1279LLVMRustPrepareThinLTOResolveWeak(const LLVMRustThinLTOData *Data, LLVMModuleRef M) {
1280 Module &Mod = *unwrap(M);
1281 const auto &DefinedGlobals = Data->ModuleToDefinedGVSummaries.lookup(Mod.getModuleIdentifier());
c295e0f8 1282 thinLTOFinalizeInModule(Mod, DefinedGlobals, /*PropagateAttrs=*/true);
ea8adc8c
XL
1283 return true;
1284}
1285
1286extern "C" bool
1287LLVMRustPrepareThinLTOInternalize(const LLVMRustThinLTOData *Data, LLVMModuleRef M) {
1288 Module &Mod = *unwrap(M);
1289 const auto &DefinedGlobals = Data->ModuleToDefinedGVSummaries.lookup(Mod.getModuleIdentifier());
1290 thinLTOInternalizeModule(Mod, DefinedGlobals);
1291 return true;
1292}
1293
1294extern "C" bool
f035d41b
XL
1295LLVMRustPrepareThinLTOImport(const LLVMRustThinLTOData *Data, LLVMModuleRef M,
1296 LLVMTargetMachineRef TM) {
ea8adc8c 1297 Module &Mod = *unwrap(M);
f035d41b 1298 TargetMachine &Target = *unwrap(TM);
8faf50e0 1299
ea8adc8c
XL
1300 const auto &ImportList = Data->ImportLists.lookup(Mod.getModuleIdentifier());
1301 auto Loader = [&](StringRef Identifier) {
1302 const auto &Memory = Data->ModuleMap.lookup(Identifier);
1303 auto &Context = Mod.getContext();
8faf50e0
XL
1304 auto MOrErr = getLazyBitcodeModule(Memory, Context, true, true);
1305
1306 if (!MOrErr)
b7449926 1307 return MOrErr;
8faf50e0
XL
1308
1309 // The rest of this closure is a workaround for
1310 // https://bugs.llvm.org/show_bug.cgi?id=38184 where during ThinLTO imports
1311 // we accidentally import wasm custom sections into different modules,
1312 // duplicating them by in the final output artifact.
1313 //
1314 // The issue is worked around here by manually removing the
1315 // `wasm.custom_sections` named metadata node from any imported module. This
1316 // we know isn't used by any optimization pass so there's no need for it to
1317 // be imported.
1318 //
1319 // Note that the metadata is currently lazily loaded, so we materialize it
1320 // here before looking up if there's metadata inside. The `FunctionImporter`
1321 // will immediately materialize metadata anyway after an import, so this
1322 // shouldn't be a perf hit.
1323 if (Error Err = (*MOrErr)->materializeMetadata()) {
1324 Expected<std::unique_ptr<Module>> Ret(std::move(Err));
b7449926 1325 return Ret;
8faf50e0
XL
1326 }
1327
1328 auto *WasmCustomSections = (*MOrErr)->getNamedMetadata("wasm.custom_sections");
1329 if (WasmCustomSections)
1330 WasmCustomSections->eraseFromParent();
1331
b7449926 1332 return MOrErr;
ea8adc8c 1333 };
f035d41b
XL
1334 bool ClearDSOLocal = clearDSOLocalOnDeclarations(Mod, Target);
1335 FunctionImporter Importer(Data->Index, Loader, ClearDSOLocal);
ea8adc8c
XL
1336 Expected<bool> Result = Importer.importFunctions(Mod, ImportList);
1337 if (!Result) {
1338 LLVMRustSetLastError(toString(Result.takeError()).c_str());
1339 return false;
1340 }
1341 return true;
1342}
1343
1344// This struct and various functions are sort of a hack right now, but the
1345// problem is that we've got in-memory LLVM modules after we generate and
1346// optimize all codegen-units for one compilation in rustc. To be compatible
1347// with the LTO support above we need to serialize the modules plus their
1348// ThinLTO summary into memory.
1349//
1350// This structure is basically an owned version of a serialize module, with
1351// a ThinLTO summary attached.
1352struct LLVMRustThinLTOBuffer {
1353 std::string data;
1354};
1355
1356extern "C" LLVMRustThinLTOBuffer*
064997fb 1357LLVMRustThinLTOBufferCreate(LLVMModuleRef M, bool is_thin) {
dfeec247 1358 auto Ret = std::make_unique<LLVMRustThinLTOBuffer>();
ea8adc8c
XL
1359 {
1360 raw_string_ostream OS(Ret->data);
1361 {
064997fb 1362 if (is_thin) {
f2b60f7d
FG
1363 PassBuilder PB;
1364 LoopAnalysisManager LAM;
1365 FunctionAnalysisManager FAM;
1366 CGSCCAnalysisManager CGAM;
1367 ModuleAnalysisManager MAM;
1368 PB.registerModuleAnalyses(MAM);
1369 PB.registerCGSCCAnalyses(CGAM);
1370 PB.registerFunctionAnalyses(FAM);
1371 PB.registerLoopAnalyses(LAM);
1372 PB.crossRegisterProxies(LAM, FAM, CGAM, MAM);
1373 ModulePassManager MPM;
1374 MPM.addPass(ThinLTOBitcodeWriterPass(OS, nullptr));
1375 MPM.run(*unwrap(M), MAM);
064997fb 1376 } else {
2b03887a 1377 WriteBitcodeToFile(*unwrap(M), OS);
064997fb 1378 }
ea8adc8c
XL
1379 }
1380 }
1381 return Ret.release();
1382}
1383
1384extern "C" void
1385LLVMRustThinLTOBufferFree(LLVMRustThinLTOBuffer *Buffer) {
1386 delete Buffer;
1387}
1388
1389extern "C" const void*
1390LLVMRustThinLTOBufferPtr(const LLVMRustThinLTOBuffer *Buffer) {
1391 return Buffer->data.data();
1392}
1393
1394extern "C" size_t
1395LLVMRustThinLTOBufferLen(const LLVMRustThinLTOBuffer *Buffer) {
1396 return Buffer->data.length();
1397}
1398
1399// This is what we used to parse upstream bitcode for actual ThinLTO
9c376795 1400// processing. We'll call this once per module optimized through ThinLTO, and
ea8adc8c
XL
1401// it'll be called concurrently on many threads.
1402extern "C" LLVMModuleRef
9fa01778
XL
1403LLVMRustParseBitcodeForLTO(LLVMContextRef Context,
1404 const char *data,
1405 size_t len,
1406 const char *identifier) {
ea8adc8c
XL
1407 StringRef Data(data, len);
1408 MemoryBufferRef Buffer(Data, identifier);
1409 unwrap(Context)->enableDebugTypeODRUniquing();
1410 Expected<std::unique_ptr<Module>> SrcOrError =
1411 parseBitcodeFile(Buffer, *unwrap(Context));
1412 if (!SrcOrError) {
1413 LLVMRustSetLastError(toString(SrcOrError.takeError()).c_str());
1414 return nullptr;
1415 }
1416 return wrap(std::move(*SrcOrError).release());
1417}
1418
f9f354fc
XL
1419// Find the bitcode section in the object file data and return it as a slice.
1420// Fail if the bitcode section is present but empty.
1421//
1422// On success, the return value is the pointer to the start of the slice and
1423// `out_len` is filled with the (non-zero) length. On failure, the return value
1424// is `nullptr` and `out_len` is set to zero.
1425extern "C" const char*
1426LLVMRustGetBitcodeSliceFromObjectData(const char *data,
1427 size_t len,
1428 size_t *out_len) {
1429 *out_len = 0;
1430
1431 StringRef Data(data, len);
1432 MemoryBufferRef Buffer(Data, ""); // The id is unused.
1433
1434 Expected<MemoryBufferRef> BitcodeOrError =
1435 object::IRObjectFile::findBitcodeInMemBuffer(Buffer);
1436 if (!BitcodeOrError) {
1437 LLVMRustSetLastError(toString(BitcodeOrError.takeError()).c_str());
1438 return nullptr;
1439 }
1440
1441 *out_len = BitcodeOrError->getBufferSize();
1442 return BitcodeOrError->getBufferStart();
1443}
1444
ff7c6d11
XL
1445// Rewrite all `DICompileUnit` pointers to the `DICompileUnit` specified. See
1446// the comment in `back/lto.rs` for why this exists.
1447extern "C" void
064997fb 1448LLVMRustThinLTOGetDICompileUnit(LLVMModuleRef Mod,
ff7c6d11
XL
1449 DICompileUnit **A,
1450 DICompileUnit **B) {
1451 Module *M = unwrap(Mod);
1452 DICompileUnit **Cur = A;
1453 DICompileUnit **Next = B;
1454 for (DICompileUnit *CU : M->debug_compile_units()) {
1455 *Cur = CU;
1456 Cur = Next;
1457 Next = nullptr;
1458 if (Cur == nullptr)
1459 break;
1460 }
1461}
1462
1463// Rewrite all `DICompileUnit` pointers to the `DICompileUnit` specified. See
1464// the comment in `back/lto.rs` for why this exists.
1465extern "C" void
064997fb 1466LLVMRustThinLTOPatchDICompileUnit(LLVMModuleRef Mod, DICompileUnit *Unit) {
ff7c6d11
XL
1467 Module *M = unwrap(Mod);
1468
1469 // If the original source module didn't have a `DICompileUnit` then try to
1470 // merge all the existing compile units. If there aren't actually any though
1471 // then there's not much for us to do so return.
1472 if (Unit == nullptr) {
1473 for (DICompileUnit *CU : M->debug_compile_units()) {
1474 Unit = CU;
1475 break;
1476 }
1477 if (Unit == nullptr)
1478 return;
1479 }
1480
1481 // Use LLVM's built-in `DebugInfoFinder` to find a bunch of debuginfo and
f035d41b
XL
1482 // process it recursively. Note that we used to specifically iterate over
1483 // instructions to ensure we feed everything into it, but `processModule`
1484 // started doing this the same way in LLVM 7 (commit d769eb36ab2b8).
ff7c6d11
XL
1485 DebugInfoFinder Finder;
1486 Finder.processModule(*M);
ff7c6d11
XL
1487
1488 // After we've found all our debuginfo, rewrite all subprograms to point to
1489 // the same `DICompileUnit`.
1490 for (auto &F : Finder.subprograms()) {
1491 F->replaceUnit(Unit);
1492 }
1493
1494 // Erase any other references to other `DICompileUnit` instances, the verifier
1495 // will later ensure that we don't actually have any other stale references to
1496 // worry about.
1497 auto *MD = M->getNamedMetadata("llvm.dbg.cu");
1498 MD->clearOperands();
1499 MD->addOperand(Unit);
1500}
29967ef6
XL
1501
1502// Computes the LTO cache key for the provided 'ModId' in the given 'Data',
1503// storing the result in 'KeyOut'.
1504// Currently, this cache key is a SHA-1 hash of anything that could affect
1505// the result of optimizing this module (e.g. module imports, exports, liveness
1506// of access globals, etc).
1507// The precise details are determined by LLVM in `computeLTOCacheKey`, which is
1508// used during the normal linker-plugin incremental thin-LTO process.
1509extern "C" void
1510LLVMRustComputeLTOCacheKey(RustStringRef KeyOut, const char *ModId, LLVMRustThinLTOData *Data) {
1511 SmallString<40> Key;
1512 llvm::lto::Config conf;
1513 const auto &ImportList = Data->ImportLists.lookup(ModId);
1514 const auto &ExportList = Data->ExportLists.lookup(ModId);
1515 const auto &ResolvedODR = Data->ResolvedODR.lookup(ModId);
1516 const auto &DefinedGlobals = Data->ModuleToDefinedGVSummaries.lookup(ModId);
1517 std::set<GlobalValue::GUID> CfiFunctionDefs;
1518 std::set<GlobalValue::GUID> CfiFunctionDecls;
1519
1520 // Based on the 'InProcessThinBackend' constructor in LLVM
1521 for (auto &Name : Data->Index.cfiFunctionDefs())
1522 CfiFunctionDefs.insert(
1523 GlobalValue::getGUID(GlobalValue::dropLLVMManglingEscape(Name)));
1524 for (auto &Name : Data->Index.cfiFunctionDecls())
1525 CfiFunctionDecls.insert(
1526 GlobalValue::getGUID(GlobalValue::dropLLVMManglingEscape(Name)));
1527
1528 llvm::computeLTOCacheKey(Key, conf, Data->Index, ModId,
1529 ImportList, ExportList, ResolvedODR, DefinedGlobals, CfiFunctionDefs, CfiFunctionDecls
1530 );
1531
1532 LLVMRustStringWriteImpl(KeyOut, Key.c_str(), Key.size());
1533}