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