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