6 #include "LLVMWrapper.h"
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"
28 #include "llvm/MC/TargetRegistry.h"
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"
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"
53 typedef struct LLVMOpaquePass *LLVMPassRef;
54 typedef struct LLVMOpaqueTargetMachine *LLVMTargetMachineRef;
56 DEFINE_STDCXX_CONVERSION_FUNCTIONS(Pass, LLVMPassRef)
57 DEFINE_STDCXX_CONVERSION_FUNCTIONS(TargetMachine, LLVMTargetMachineRef)
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);
73 extern "C" void LLVMTimeTraceProfilerInitialize() {
74 timeTraceProfilerInitialize(
75 /* TimeTraceGranularity */ 0,
76 /* ProcName */ "rustc");
79 extern "C" void LLVMTimeTraceProfilerFinishThread() {
80 timeTraceProfilerFinishThread();
83 extern "C" void LLVMTimeTraceProfilerFinish(const char* FileName) {
84 StringRef FN(FileName);
86 raw_fd_ostream OS(FN, EC, sys::fs::CD_CreateAlways);
88 timeTraceProfilerWrite(OS);
89 timeTraceProfilerCleanup();
92 enum class LLVMRustPassKind {
98 static LLVMRustPassKind toRust(PassKind Kind) {
101 return LLVMRustPassKind::Function;
103 return LLVMRustPassKind::Module;
105 return LLVMRustPassKind::Other;
109 extern "C" LLVMPassRef LLVMRustFindAndCreatePass(const char *PassName) {
110 #if LLVM_VERSION_LT(15, 0)
111 StringRef SR(PassName);
112 PassRegistry *PR = PassRegistry::getPassRegistry();
114 const PassInfo *PI = PR->getPassInfo(SR);
116 return wrap(PI->createPass());
120 report_fatal_error("Legacy PM not supported with LLVM 15");
124 extern "C" LLVMPassRef LLVMRustCreateAddressSanitizerFunctionPass(bool Recover) {
125 #if LLVM_VERSION_LT(15, 0)
126 const bool CompileKernel = false;
127 const bool UseAfterScope = true;
129 return wrap(createAddressSanitizerFunctionPass(CompileKernel, Recover, UseAfterScope));
131 report_fatal_error("Legacy PM not supported with LLVM 15");
135 extern "C" LLVMPassRef LLVMRustCreateModuleAddressSanitizerPass(bool Recover) {
136 #if LLVM_VERSION_LT(15, 0)
137 const bool CompileKernel = false;
139 return wrap(createModuleAddressSanitizerLegacyPassPass(CompileKernel, Recover));
141 report_fatal_error("Legacy PM not supported with LLVM 15");
145 extern "C" LLVMPassRef LLVMRustCreateMemorySanitizerPass(int TrackOrigins, bool Recover) {
146 #if LLVM_VERSION_LT(15, 0)
147 const bool CompileKernel = false;
149 return wrap(createMemorySanitizerLegacyPassPass(
150 MemorySanitizerOptions{TrackOrigins, Recover, CompileKernel}));
152 report_fatal_error("Legacy PM not supported with LLVM 15");
156 extern "C" LLVMPassRef LLVMRustCreateThreadSanitizerPass() {
157 #if LLVM_VERSION_LT(15, 0)
158 return wrap(createThreadSanitizerLegacyPassPass());
160 report_fatal_error("Legacy PM not supported with LLVM 15");
164 extern "C" LLVMPassRef LLVMRustCreateHWAddressSanitizerPass(bool Recover) {
165 #if LLVM_VERSION_LT(15, 0)
166 const bool CompileKernel = false;
168 return wrap(createHWAddressSanitizerLegacyPassPass(CompileKernel, Recover));
170 report_fatal_error("Legacy PM not supported with LLVM 15");
174 extern "C" LLVMRustPassKind LLVMRustPassKind(LLVMPassRef RustPass) {
176 Pass *Pass = unwrap(RustPass);
177 return toRust(Pass->getPassKind());
180 extern "C" void LLVMRustAddPass(LLVMPassManagerRef PMR, LLVMPassRef RustPass) {
181 #if LLVM_VERSION_LT(15, 0)
183 Pass *Pass = unwrap(RustPass);
184 PassManagerBase *PMB = unwrap(PMR);
187 report_fatal_error("Legacy PM not supported with LLVM 15");
191 extern "C" LLVMPassManagerBuilderRef LLVMRustPassManagerBuilderCreate() {
192 #if LLVM_VERSION_LT(15, 0)
193 return LLVMPassManagerBuilderCreate();
195 report_fatal_error("Legacy PM not supported with LLVM 15");
199 extern "C" void LLVMRustPassManagerBuilderDispose(LLVMPassManagerBuilderRef PMB) {
200 #if LLVM_VERSION_LT(15, 0)
201 LLVMPassManagerBuilderDispose(PMB);
203 report_fatal_error("Legacy PM not supported with LLVM 15");
207 extern "C" void LLVMRustPassManagerBuilderPopulateFunctionPassManager(
208 LLVMPassManagerBuilderRef PMB, LLVMPassManagerRef PM) {
209 #if LLVM_VERSION_LT(15, 0)
210 LLVMPassManagerBuilderPopulateFunctionPassManager(PMB, PM);
212 report_fatal_error("Legacy PM not supported with LLVM 15");
216 extern "C" void LLVMRustPassManagerBuilderPopulateModulePassManager(
217 LLVMPassManagerBuilderRef PMB, LLVMPassManagerRef PM) {
218 #if LLVM_VERSION_LT(15, 0)
219 LLVMPassManagerBuilderPopulateModulePassManager(PMB, PM);
221 report_fatal_error("Legacy PM not supported with LLVM 15");
225 extern "C" void LLVMRustPassManagerBuilderPopulateLTOPassManager(
226 LLVMPassManagerBuilderRef PMB, LLVMPassManagerRef PM, bool Internalize, bool RunInliner) {
227 #if LLVM_VERSION_LT(15, 0)
228 LLVMPassManagerBuilderPopulateLTOPassManager(PMB, PM, Internalize, RunInliner);
230 report_fatal_error("Legacy PM not supported with LLVM 15");
235 void LLVMRustPassManagerBuilderPopulateThinLTOPassManager(
236 LLVMPassManagerBuilderRef PMBR,
237 LLVMPassManagerRef PMR
239 #if LLVM_VERSION_LT(15, 0)
240 unwrap(PMBR)->populateThinLTOPassManager(*unwrap(PMR));
242 report_fatal_error("Legacy PM not supported with LLVM 15");
246 extern "C" void LLVMRustPassManagerBuilderUseInlinerWithThreshold(
247 LLVMPassManagerBuilderRef PMB, unsigned Threshold) {
248 #if LLVM_VERSION_LT(15, 0)
249 LLVMPassManagerBuilderUseInlinerWithThreshold(PMB, Threshold);
251 report_fatal_error("Legacy PM not supported with LLVM 15");
256 void LLVMRustAddLastExtensionPasses(
257 LLVMPassManagerBuilderRef PMBR, LLVMPassRef *Passes, size_t NumPasses) {
258 #if LLVM_VERSION_LT(15, 0)
259 auto AddExtensionPasses = [Passes, NumPasses](
260 const PassManagerBuilder &Builder, PassManagerBase &PM) {
261 for (size_t I = 0; I < NumPasses; I++) {
262 PM.add(unwrap(Passes[I]));
265 // Add the passes to both of the pre-finalization extension points,
266 // so they are run for optimized and non-optimized builds.
267 unwrap(PMBR)->addExtension(PassManagerBuilder::EP_OptimizerLast,
269 unwrap(PMBR)->addExtension(PassManagerBuilder::EP_EnabledOnOptLevel0,
272 report_fatal_error("Legacy PM not supported with LLVM 15");
276 #ifdef LLVM_COMPONENT_X86
277 #define SUBTARGET_X86 SUBTARGET(X86)
279 #define SUBTARGET_X86
282 #ifdef LLVM_COMPONENT_ARM
283 #define SUBTARGET_ARM SUBTARGET(ARM)
285 #define SUBTARGET_ARM
288 #ifdef LLVM_COMPONENT_AARCH64
289 #define SUBTARGET_AARCH64 SUBTARGET(AArch64)
291 #define SUBTARGET_AARCH64
294 #ifdef LLVM_COMPONENT_AVR
295 #define SUBTARGET_AVR SUBTARGET(AVR)
297 #define SUBTARGET_AVR
300 #ifdef LLVM_COMPONENT_M68k
301 #define SUBTARGET_M68K SUBTARGET(M68k)
303 #define SUBTARGET_M68K
306 #ifdef LLVM_COMPONENT_MIPS
307 #define SUBTARGET_MIPS SUBTARGET(Mips)
309 #define SUBTARGET_MIPS
312 #ifdef LLVM_COMPONENT_POWERPC
313 #define SUBTARGET_PPC SUBTARGET(PPC)
315 #define SUBTARGET_PPC
318 #ifdef LLVM_COMPONENT_SYSTEMZ
319 #define SUBTARGET_SYSTEMZ SUBTARGET(SystemZ)
321 #define SUBTARGET_SYSTEMZ
324 #ifdef LLVM_COMPONENT_MSP430
325 #define SUBTARGET_MSP430 SUBTARGET(MSP430)
327 #define SUBTARGET_MSP430
330 #ifdef LLVM_COMPONENT_RISCV
331 #define SUBTARGET_RISCV SUBTARGET(RISCV)
333 #define SUBTARGET_RISCV
336 #ifdef LLVM_COMPONENT_SPARC
337 #define SUBTARGET_SPARC SUBTARGET(Sparc)
339 #define SUBTARGET_SPARC
342 #ifdef LLVM_COMPONENT_HEXAGON
343 #define SUBTARGET_HEXAGON SUBTARGET(Hexagon)
345 #define SUBTARGET_HEXAGON
348 #define GEN_SUBTARGETS \
362 #define SUBTARGET(x) \
364 extern const SubtargetFeatureKV x##FeatureKV[]; \
365 extern const SubtargetFeatureKV x##SubTypeKV[]; \
371 extern "C" bool LLVMRustHasFeature(LLVMTargetMachineRef TM,
372 const char *Feature) {
373 TargetMachine *Target = unwrap(TM);
374 const MCSubtargetInfo *MCInfo = Target->getMCSubtargetInfo();
375 return MCInfo->checkFeatures(std::string("+") + Feature);
378 enum class LLVMRustCodeModel {
387 static Optional<CodeModel::Model> fromRust(LLVMRustCodeModel Model) {
389 case LLVMRustCodeModel::Tiny:
390 return CodeModel::Tiny;
391 case LLVMRustCodeModel::Small:
392 return CodeModel::Small;
393 case LLVMRustCodeModel::Kernel:
394 return CodeModel::Kernel;
395 case LLVMRustCodeModel::Medium:
396 return CodeModel::Medium;
397 case LLVMRustCodeModel::Large:
398 return CodeModel::Large;
399 case LLVMRustCodeModel::None:
402 report_fatal_error("Bad CodeModel.");
406 enum class LLVMRustCodeGenOptLevel {
413 static CodeGenOpt::Level fromRust(LLVMRustCodeGenOptLevel Level) {
415 case LLVMRustCodeGenOptLevel::None:
416 return CodeGenOpt::None;
417 case LLVMRustCodeGenOptLevel::Less:
418 return CodeGenOpt::Less;
419 case LLVMRustCodeGenOptLevel::Default:
420 return CodeGenOpt::Default;
421 case LLVMRustCodeGenOptLevel::Aggressive:
422 return CodeGenOpt::Aggressive;
424 report_fatal_error("Bad CodeGenOptLevel.");
428 enum class LLVMRustPassBuilderOptLevel {
437 #if LLVM_VERSION_LT(14,0)
438 using OptimizationLevel = PassBuilder::OptimizationLevel;
441 static OptimizationLevel fromRust(LLVMRustPassBuilderOptLevel Level) {
443 case LLVMRustPassBuilderOptLevel::O0:
444 return OptimizationLevel::O0;
445 case LLVMRustPassBuilderOptLevel::O1:
446 return OptimizationLevel::O1;
447 case LLVMRustPassBuilderOptLevel::O2:
448 return OptimizationLevel::O2;
449 case LLVMRustPassBuilderOptLevel::O3:
450 return OptimizationLevel::O3;
451 case LLVMRustPassBuilderOptLevel::Os:
452 return OptimizationLevel::Os;
453 case LLVMRustPassBuilderOptLevel::Oz:
454 return OptimizationLevel::Oz;
456 report_fatal_error("Bad PassBuilderOptLevel.");
460 enum class LLVMRustRelocModel {
469 static Reloc::Model fromRust(LLVMRustRelocModel RustReloc) {
471 case LLVMRustRelocModel::Static:
472 return Reloc::Static;
473 case LLVMRustRelocModel::PIC:
475 case LLVMRustRelocModel::DynamicNoPic:
476 return Reloc::DynamicNoPIC;
477 case LLVMRustRelocModel::ROPI:
479 case LLVMRustRelocModel::RWPI:
481 case LLVMRustRelocModel::ROPIRWPI:
482 return Reloc::ROPI_RWPI;
484 report_fatal_error("Bad RelocModel.");
488 /// getLongestEntryLength - Return the length of the longest entry in the table.
489 template<typename KV>
490 static size_t getLongestEntryLength(ArrayRef<KV> Table) {
492 for (auto &I : Table)
493 MaxLen = std::max(MaxLen, std::strlen(I.Key));
497 extern "C" void LLVMRustPrintTargetCPUs(LLVMTargetMachineRef TM) {
498 const TargetMachine *Target = unwrap(TM);
499 const MCSubtargetInfo *MCInfo = Target->getMCSubtargetInfo();
500 const Triple::ArchType HostArch = Triple(sys::getProcessTriple()).getArch();
501 const Triple::ArchType TargetArch = Target->getTargetTriple().getArch();
502 const ArrayRef<SubtargetSubTypeKV> CPUTable = MCInfo->getCPUTable();
503 unsigned MaxCPULen = getLongestEntryLength(CPUTable);
505 printf("Available CPUs for this target:\n");
506 if (HostArch == TargetArch) {
507 const StringRef HostCPU = sys::getHostCPUName();
508 printf(" %-*s - Select the CPU of the current host (currently %.*s).\n",
509 MaxCPULen, "native", (int)HostCPU.size(), HostCPU.data());
511 for (auto &CPU : CPUTable)
512 printf(" %-*s\n", MaxCPULen, CPU.Key);
516 extern "C" size_t LLVMRustGetTargetFeaturesCount(LLVMTargetMachineRef TM) {
517 const TargetMachine *Target = unwrap(TM);
518 const MCSubtargetInfo *MCInfo = Target->getMCSubtargetInfo();
519 const ArrayRef<SubtargetFeatureKV> FeatTable = MCInfo->getFeatureTable();
520 return FeatTable.size();
523 extern "C" void LLVMRustGetTargetFeature(LLVMTargetMachineRef TM, size_t Index,
524 const char** Feature, const char** Desc) {
525 const TargetMachine *Target = unwrap(TM);
526 const MCSubtargetInfo *MCInfo = Target->getMCSubtargetInfo();
527 const ArrayRef<SubtargetFeatureKV> FeatTable = MCInfo->getFeatureTable();
528 const SubtargetFeatureKV Feat = FeatTable[Index];
535 extern "C" void LLVMRustPrintTargetCPUs(LLVMTargetMachineRef) {
536 printf("Target CPU help is not supported by this LLVM version.\n\n");
539 extern "C" size_t LLVMRustGetTargetFeaturesCount(LLVMTargetMachineRef) {
543 extern "C" void LLVMRustGetTargetFeature(LLVMTargetMachineRef, const char**, const char**) {}
546 extern "C" const char* LLVMRustGetHostCPUName(size_t *len) {
547 StringRef Name = sys::getHostCPUName();
552 extern "C" LLVMTargetMachineRef LLVMRustCreateTargetMachine(
553 const char *TripleStr, const char *CPU, const char *Feature,
554 const char *ABIStr, LLVMRustCodeModel RustCM, LLVMRustRelocModel RustReloc,
555 LLVMRustCodeGenOptLevel RustOptLevel, bool UseSoftFloat,
556 bool FunctionSections,
558 bool UniqueSectionNames,
559 bool TrapUnreachable,
562 bool EmitStackSizeSection,
563 bool RelaxELFRelocations,
565 const char *SplitDwarfFile) {
567 auto OptLevel = fromRust(RustOptLevel);
568 auto RM = fromRust(RustReloc);
569 auto CM = fromRust(RustCM);
572 Triple Trip(Triple::normalize(TripleStr));
573 const llvm::Target *TheTarget =
574 TargetRegistry::lookupTarget(Trip.getTriple(), Error);
575 if (TheTarget == nullptr) {
576 LLVMRustSetLastError(Error.c_str());
580 TargetOptions Options;
582 Options.FloatABIType = FloatABI::Default;
584 Options.FloatABIType = FloatABI::Soft;
586 Options.DataSections = DataSections;
587 Options.FunctionSections = FunctionSections;
588 Options.UniqueSectionNames = UniqueSectionNames;
589 Options.MCOptions.AsmVerbose = AsmComments;
590 Options.MCOptions.PreserveAsmComments = AsmComments;
591 Options.MCOptions.ABIName = ABIStr;
592 if (SplitDwarfFile) {
593 Options.MCOptions.SplitDwarfFile = SplitDwarfFile;
595 Options.RelaxELFRelocations = RelaxELFRelocations;
596 Options.UseInitArray = UseInitArray;
598 if (TrapUnreachable) {
599 // Tell LLVM to codegen `unreachable` into an explicit trap instruction.
600 // This limits the extent of possible undefined behavior in some cases, as
601 // it prevents control flow from "falling through" into whatever code
602 // happens to be laid out next in memory.
603 Options.TrapUnreachable = true;
607 Options.ThreadModel = ThreadModel::Single;
610 Options.EmitStackSizeSection = EmitStackSizeSection;
612 TargetMachine *TM = TheTarget->createTargetMachine(
613 Trip.getTriple(), CPU, Feature, Options, RM, CM, OptLevel);
617 extern "C" void LLVMRustDisposeTargetMachine(LLVMTargetMachineRef TM) {
621 extern "C" void LLVMRustConfigurePassManagerBuilder(
622 LLVMPassManagerBuilderRef PMBR, LLVMRustCodeGenOptLevel OptLevel,
623 bool MergeFunctions, bool SLPVectorize, bool LoopVectorize, bool PrepareForThinLTO,
624 const char* PGOGenPath, const char* PGOUsePath, const char* PGOSampleUsePath,
626 #if LLVM_VERSION_LT(15, 0)
627 unwrap(PMBR)->MergeFunctions = MergeFunctions;
628 unwrap(PMBR)->SLPVectorize = SLPVectorize;
629 unwrap(PMBR)->OptLevel = fromRust(OptLevel);
630 unwrap(PMBR)->LoopVectorize = LoopVectorize;
631 unwrap(PMBR)->PrepareForThinLTO = PrepareForThinLTO;
632 unwrap(PMBR)->SizeLevel = SizeLevel;
633 unwrap(PMBR)->DisableUnrollLoops = SizeLevel != 0;
636 assert(!PGOUsePath && !PGOSampleUsePath);
637 unwrap(PMBR)->EnablePGOInstrGen = true;
638 unwrap(PMBR)->PGOInstrGen = PGOGenPath;
639 } else if (PGOUsePath) {
640 assert(!PGOSampleUsePath);
641 unwrap(PMBR)->PGOInstrUse = PGOUsePath;
642 } else if (PGOSampleUsePath) {
643 unwrap(PMBR)->PGOSampleUse = PGOSampleUsePath;
646 report_fatal_error("Legacy PM not supported with LLVM 15");
650 // Unfortunately, the LLVM C API doesn't provide a way to set the `LibraryInfo`
651 // field of a PassManagerBuilder, we expose our own method of doing so.
652 extern "C" void LLVMRustAddBuilderLibraryInfo(LLVMPassManagerBuilderRef PMBR,
654 bool DisableSimplifyLibCalls) {
655 Triple TargetTriple(unwrap(M)->getTargetTriple());
656 TargetLibraryInfoImpl *TLI = new TargetLibraryInfoImpl(TargetTriple);
657 if (DisableSimplifyLibCalls)
658 TLI->disableAllFunctions();
659 unwrap(PMBR)->LibraryInfo = TLI;
662 // Unfortunately, the LLVM C API doesn't provide a way to create the
663 // TargetLibraryInfo pass, so we use this method to do so.
664 extern "C" void LLVMRustAddLibraryInfo(LLVMPassManagerRef PMR, LLVMModuleRef M,
665 bool DisableSimplifyLibCalls) {
666 Triple TargetTriple(unwrap(M)->getTargetTriple());
667 TargetLibraryInfoImpl TLII(TargetTriple);
668 if (DisableSimplifyLibCalls)
669 TLII.disableAllFunctions();
670 unwrap(PMR)->add(new TargetLibraryInfoWrapperPass(TLII));
673 // Unfortunately, the LLVM C API doesn't provide an easy way of iterating over
674 // all the functions in a module, so we do that manually here. You'll find
675 // similar code in clang's BackendUtil.cpp file.
676 extern "C" void LLVMRustRunFunctionPassManager(LLVMPassManagerRef PMR,
678 llvm::legacy::FunctionPassManager *P =
679 unwrap<llvm::legacy::FunctionPassManager>(PMR);
680 P->doInitialization();
682 // Upgrade all calls to old intrinsics first.
683 for (Module::iterator I = unwrap(M)->begin(), E = unwrap(M)->end(); I != E;)
684 UpgradeCallsToIntrinsic(&*I++); // must be post-increment, as we remove
686 for (Module::iterator I = unwrap(M)->begin(), E = unwrap(M)->end(); I != E;
688 if (!I->isDeclaration())
694 extern "C" void LLVMRustSetLLVMOptions(int Argc, char **Argv) {
695 // Initializing the command-line options more than once is not allowed. So,
696 // check if they've already been initialized. (This could happen if we're
697 // being called from rustpkg, for example). If the arguments change, then
698 // that's just kinda unfortunate.
699 static bool Initialized = false;
703 cl::ParseCommandLineOptions(Argc, Argv);
706 enum class LLVMRustFileType {
711 static CodeGenFileType fromRust(LLVMRustFileType Type) {
713 case LLVMRustFileType::AssemblyFile:
714 return CGFT_AssemblyFile;
715 case LLVMRustFileType::ObjectFile:
716 return CGFT_ObjectFile;
718 report_fatal_error("Bad FileType.");
722 extern "C" LLVMRustResult
723 LLVMRustWriteOutputFile(LLVMTargetMachineRef Target, LLVMPassManagerRef PMR,
724 LLVMModuleRef M, const char *Path, const char *DwoPath,
725 LLVMRustFileType RustFileType) {
726 llvm::legacy::PassManager *PM = unwrap<llvm::legacy::PassManager>(PMR);
727 auto FileType = fromRust(RustFileType);
729 std::string ErrorInfo;
731 raw_fd_ostream OS(Path, EC, sys::fs::OF_None);
733 ErrorInfo = EC.message();
734 if (ErrorInfo != "") {
735 LLVMRustSetLastError(ErrorInfo.c_str());
736 return LLVMRustResult::Failure;
739 buffer_ostream BOS(OS);
741 raw_fd_ostream DOS(DwoPath, EC, sys::fs::OF_None);
744 ErrorInfo = EC.message();
745 if (ErrorInfo != "") {
746 LLVMRustSetLastError(ErrorInfo.c_str());
747 return LLVMRustResult::Failure;
749 buffer_ostream DBOS(DOS);
750 unwrap(Target)->addPassesToEmitFile(*PM, BOS, &DBOS, FileType, false);
753 unwrap(Target)->addPassesToEmitFile(*PM, BOS, nullptr, FileType, false);
757 // Apparently `addPassesToEmitFile` adds a pointer to our on-the-stack output
758 // stream (OS), so the only real safe place to delete this is here? Don't we
759 // wish this was written in Rust?
760 LLVMDisposePassManager(PMR);
761 return LLVMRustResult::Success;
764 extern "C" typedef void (*LLVMRustSelfProfileBeforePassCallback)(void*, // LlvmSelfProfiler
765 const char*, // pass name
766 const char*); // IR name
767 extern "C" typedef void (*LLVMRustSelfProfileAfterPassCallback)(void*); // LlvmSelfProfiler
769 std::string LLVMRustwrappedIrGetName(const llvm::Any &WrappedIr) {
770 if (any_isa<const Module *>(WrappedIr))
771 return any_cast<const Module *>(WrappedIr)->getName().str();
772 if (any_isa<const Function *>(WrappedIr))
773 return any_cast<const Function *>(WrappedIr)->getName().str();
774 if (any_isa<const Loop *>(WrappedIr))
775 return any_cast<const Loop *>(WrappedIr)->getName().str();
776 if (any_isa<const LazyCallGraph::SCC *>(WrappedIr))
777 return any_cast<const LazyCallGraph::SCC *>(WrappedIr)->getName();
782 void LLVMSelfProfileInitializeCallbacks(
783 PassInstrumentationCallbacks& PIC, void* LlvmSelfProfiler,
784 LLVMRustSelfProfileBeforePassCallback BeforePassCallback,
785 LLVMRustSelfProfileAfterPassCallback AfterPassCallback) {
786 PIC.registerBeforeNonSkippedPassCallback([LlvmSelfProfiler, BeforePassCallback](
787 StringRef Pass, llvm::Any Ir) {
788 std::string PassName = Pass.str();
789 std::string IrName = LLVMRustwrappedIrGetName(Ir);
790 BeforePassCallback(LlvmSelfProfiler, PassName.c_str(), IrName.c_str());
793 PIC.registerAfterPassCallback(
794 [LlvmSelfProfiler, AfterPassCallback](StringRef Pass, llvm::Any IR,
795 const PreservedAnalyses &Preserved) {
796 AfterPassCallback(LlvmSelfProfiler);
799 PIC.registerAfterPassInvalidatedCallback(
800 [LlvmSelfProfiler, AfterPassCallback](StringRef Pass, const PreservedAnalyses &Preserved) {
801 AfterPassCallback(LlvmSelfProfiler);
804 PIC.registerBeforeAnalysisCallback([LlvmSelfProfiler, BeforePassCallback](
805 StringRef Pass, llvm::Any Ir) {
806 std::string PassName = Pass.str();
807 std::string IrName = LLVMRustwrappedIrGetName(Ir);
808 BeforePassCallback(LlvmSelfProfiler, PassName.c_str(), IrName.c_str());
811 PIC.registerAfterAnalysisCallback(
812 [LlvmSelfProfiler, AfterPassCallback](StringRef Pass, llvm::Any Ir) {
813 AfterPassCallback(LlvmSelfProfiler);
817 enum class LLVMRustOptStage {
825 struct LLVMRustSanitizerOptions {
826 bool SanitizeAddress;
827 bool SanitizeAddressRecover;
829 bool SanitizeMemoryRecover;
830 int SanitizeMemoryTrackOrigins;
832 bool SanitizeHWAddress;
833 bool SanitizeHWAddressRecover;
836 extern "C" LLVMRustResult
837 LLVMRustOptimizeWithNewPassManager(
838 LLVMModuleRef ModuleRef,
839 LLVMTargetMachineRef TMRef,
840 LLVMRustPassBuilderOptLevel OptLevelRust,
841 LLVMRustOptStage OptStage,
842 bool NoPrepopulatePasses, bool VerifyIR, bool UseThinLTOBuffers,
843 bool MergeFunctions, bool UnrollLoops, bool SLPVectorize, bool LoopVectorize,
844 bool DisableSimplifyLibCalls, bool EmitLifetimeMarkers,
845 LLVMRustSanitizerOptions *SanitizerOptions,
846 const char *PGOGenPath, const char *PGOUsePath,
847 bool InstrumentCoverage, bool InstrumentGCOV,
848 const char *PGOSampleUsePath, bool DebugInfoForProfiling,
849 void* LlvmSelfProfiler,
850 LLVMRustSelfProfileBeforePassCallback BeforePassCallback,
851 LLVMRustSelfProfileAfterPassCallback AfterPassCallback,
852 const char *ExtraPasses, size_t ExtraPassesLen,
853 const char *LLVMPlugins, size_t LLVMPluginsLen) {
854 Module *TheModule = unwrap(ModuleRef);
855 TargetMachine *TM = unwrap(TMRef);
856 OptimizationLevel OptLevel = fromRust(OptLevelRust);
859 PipelineTuningOptions PTO;
860 PTO.LoopUnrolling = UnrollLoops;
861 PTO.LoopInterleaving = UnrollLoops;
862 PTO.LoopVectorization = LoopVectorize;
863 PTO.SLPVectorization = SLPVectorize;
864 PTO.MergeFunctions = MergeFunctions;
866 // FIXME: We may want to expose this as an option.
867 bool DebugPassManager = false;
869 PassInstrumentationCallbacks PIC;
870 StandardInstrumentations SI(DebugPassManager);
871 SI.registerCallbacks(PIC);
873 if (LlvmSelfProfiler){
874 LLVMSelfProfileInitializeCallbacks(PIC,LlvmSelfProfiler,BeforePassCallback,AfterPassCallback);
877 Optional<PGOOptions> PGOOpt;
879 assert(!PGOUsePath && !PGOSampleUsePath);
880 PGOOpt = PGOOptions(PGOGenPath, "", "", PGOOptions::IRInstr,
881 PGOOptions::NoCSAction, DebugInfoForProfiling);
882 } else if (PGOUsePath) {
883 assert(!PGOSampleUsePath);
884 PGOOpt = PGOOptions(PGOUsePath, "", "", PGOOptions::IRUse,
885 PGOOptions::NoCSAction, DebugInfoForProfiling);
886 } else if (PGOSampleUsePath) {
887 PGOOpt = PGOOptions(PGOSampleUsePath, "", "", PGOOptions::SampleUse,
888 PGOOptions::NoCSAction, DebugInfoForProfiling);
889 } else if (DebugInfoForProfiling) {
890 PGOOpt = PGOOptions("", "", "", PGOOptions::NoAction,
891 PGOOptions::NoCSAction, DebugInfoForProfiling);
894 #if LLVM_VERSION_GE(13, 0)
895 PassBuilder PB(TM, PTO, PGOOpt, &PIC);
896 LoopAnalysisManager LAM;
897 FunctionAnalysisManager FAM;
898 CGSCCAnalysisManager CGAM;
899 ModuleAnalysisManager MAM;
901 PassBuilder PB(DebugPassManager, TM, PTO, PGOOpt, &PIC);
902 LoopAnalysisManager LAM(DebugPassManager);
903 FunctionAnalysisManager FAM(DebugPassManager);
904 CGSCCAnalysisManager CGAM(DebugPassManager);
905 ModuleAnalysisManager MAM(DebugPassManager);
908 FAM.registerPass([&] { return PB.buildDefaultAAPipeline(); });
910 Triple TargetTriple(TheModule->getTargetTriple());
911 std::unique_ptr<TargetLibraryInfoImpl> TLII(new TargetLibraryInfoImpl(TargetTriple));
912 if (DisableSimplifyLibCalls)
913 TLII->disableAllFunctions();
914 FAM.registerPass([&] { return TargetLibraryAnalysis(*TLII); });
916 PB.registerModuleAnalyses(MAM);
917 PB.registerCGSCCAnalyses(CGAM);
918 PB.registerFunctionAnalyses(FAM);
919 PB.registerLoopAnalyses(LAM);
920 PB.crossRegisterProxies(LAM, FAM, CGAM, MAM);
922 // We manually collect pipeline callbacks so we can apply them at O0, where the
923 // PassBuilder does not create a pipeline.
924 std::vector<std::function<void(ModulePassManager &, OptimizationLevel)>>
925 PipelineStartEPCallbacks;
926 std::vector<std::function<void(ModulePassManager &, OptimizationLevel)>>
927 OptimizerLastEPCallbacks;
930 PipelineStartEPCallbacks.push_back(
931 [VerifyIR](ModulePassManager &MPM, OptimizationLevel Level) {
932 MPM.addPass(VerifierPass());
937 if (InstrumentGCOV) {
938 PipelineStartEPCallbacks.push_back(
939 [](ModulePassManager &MPM, OptimizationLevel Level) {
940 MPM.addPass(GCOVProfilerPass(GCOVOptions::getDefault()));
945 if (InstrumentCoverage) {
946 PipelineStartEPCallbacks.push_back(
947 [](ModulePassManager &MPM, OptimizationLevel Level) {
948 InstrProfOptions Options;
949 MPM.addPass(InstrProfiling(Options, false));
954 if (SanitizerOptions) {
955 if (SanitizerOptions->SanitizeMemory) {
956 MemorySanitizerOptions Options(
957 SanitizerOptions->SanitizeMemoryTrackOrigins,
958 SanitizerOptions->SanitizeMemoryRecover,
959 /*CompileKernel=*/false);
960 OptimizerLastEPCallbacks.push_back(
961 [Options](ModulePassManager &MPM, OptimizationLevel Level) {
962 #if LLVM_VERSION_GE(14, 0)
963 MPM.addPass(ModuleMemorySanitizerPass(Options));
965 MPM.addPass(MemorySanitizerPass(Options));
967 MPM.addPass(createModuleToFunctionPassAdaptor(MemorySanitizerPass(Options)));
972 if (SanitizerOptions->SanitizeThread) {
973 OptimizerLastEPCallbacks.push_back(
974 [](ModulePassManager &MPM, OptimizationLevel Level) {
975 #if LLVM_VERSION_GE(14, 0)
976 MPM.addPass(ModuleThreadSanitizerPass());
978 MPM.addPass(ThreadSanitizerPass());
980 MPM.addPass(createModuleToFunctionPassAdaptor(ThreadSanitizerPass()));
985 if (SanitizerOptions->SanitizeAddress) {
986 OptimizerLastEPCallbacks.push_back(
987 [SanitizerOptions](ModulePassManager &MPM, OptimizationLevel Level) {
988 #if LLVM_VERSION_LT(15, 0)
989 MPM.addPass(RequireAnalysisPass<ASanGlobalsMetadataAnalysis, Module>());
991 #if LLVM_VERSION_GE(14, 0)
992 AddressSanitizerOptions opts = AddressSanitizerOptions{
993 /*CompileKernel=*/false,
994 SanitizerOptions->SanitizeAddressRecover,
995 /*UseAfterScope=*/true,
996 AsanDetectStackUseAfterReturnMode::Runtime,
998 MPM.addPass(ModuleAddressSanitizerPass(opts));
1000 MPM.addPass(ModuleAddressSanitizerPass(
1001 /*CompileKernel=*/false, SanitizerOptions->SanitizeAddressRecover));
1002 MPM.addPass(createModuleToFunctionPassAdaptor(AddressSanitizerPass(
1003 /*CompileKernel=*/false, SanitizerOptions->SanitizeAddressRecover,
1004 /*UseAfterScope=*/true)));
1009 if (SanitizerOptions->SanitizeHWAddress) {
1010 OptimizerLastEPCallbacks.push_back(
1011 [SanitizerOptions](ModulePassManager &MPM, OptimizationLevel Level) {
1012 #if LLVM_VERSION_GE(14, 0)
1013 HWAddressSanitizerOptions opts(
1014 /*CompileKernel=*/false, SanitizerOptions->SanitizeHWAddressRecover,
1015 /*DisableOptimization=*/false);
1016 MPM.addPass(HWAddressSanitizerPass(opts));
1018 MPM.addPass(HWAddressSanitizerPass(
1019 /*CompileKernel=*/false, SanitizerOptions->SanitizeHWAddressRecover));
1026 if (LLVMPluginsLen) {
1027 auto PluginsStr = StringRef(LLVMPlugins, LLVMPluginsLen);
1028 SmallVector<StringRef> Plugins;
1029 PluginsStr.split(Plugins, ',', -1, false);
1030 for (auto PluginPath: Plugins) {
1031 auto Plugin = PassPlugin::Load(PluginPath.str());
1033 LLVMRustSetLastError(("Failed to load pass plugin" + PluginPath.str()).c_str());
1036 Plugin->registerPassBuilderCallbacks(PB);
1040 #if LLVM_VERSION_GE(13, 0)
1041 ModulePassManager MPM;
1043 ModulePassManager MPM(DebugPassManager);
1045 bool NeedThinLTOBufferPasses = UseThinLTOBuffers;
1046 if (!NoPrepopulatePasses) {
1047 // The pre-link pipelines don't support O0 and require using budilO0DefaultPipeline() instead.
1048 // At the same time, the LTO pipelines do support O0 and using them is required.
1049 bool IsLTO = OptStage == LLVMRustOptStage::ThinLTO || OptStage == LLVMRustOptStage::FatLTO;
1050 if (OptLevel == OptimizationLevel::O0 && !IsLTO) {
1051 for (const auto &C : PipelineStartEPCallbacks)
1052 PB.registerPipelineStartEPCallback(C);
1053 for (const auto &C : OptimizerLastEPCallbacks)
1054 PB.registerOptimizerLastEPCallback(C);
1056 // Pass false as we manually schedule ThinLTOBufferPasses below.
1057 MPM = PB.buildO0DefaultPipeline(OptLevel, /* PreLinkLTO */ false);
1059 for (const auto &C : PipelineStartEPCallbacks)
1060 PB.registerPipelineStartEPCallback(C);
1061 if (OptStage != LLVMRustOptStage::PreLinkThinLTO) {
1062 for (const auto &C : OptimizerLastEPCallbacks)
1063 PB.registerOptimizerLastEPCallback(C);
1067 case LLVMRustOptStage::PreLinkNoLTO:
1068 MPM = PB.buildPerModuleDefaultPipeline(OptLevel, DebugPassManager);
1070 case LLVMRustOptStage::PreLinkThinLTO:
1071 MPM = PB.buildThinLTOPreLinkDefaultPipeline(OptLevel);
1072 // The ThinLTOPreLink pipeline already includes ThinLTOBuffer passes. However, callback
1073 // passes may still run afterwards. This means we need to run the buffer passes again.
1074 // FIXME: In LLVM 13, the ThinLTOPreLink pipeline also runs OptimizerLastEPCallbacks
1075 // before the RequiredLTOPreLinkPasses, in which case we can remove these hacks.
1076 if (OptimizerLastEPCallbacks.empty())
1077 NeedThinLTOBufferPasses = false;
1078 for (const auto &C : OptimizerLastEPCallbacks)
1081 case LLVMRustOptStage::PreLinkFatLTO:
1082 MPM = PB.buildLTOPreLinkDefaultPipeline(OptLevel);
1083 NeedThinLTOBufferPasses = false;
1085 case LLVMRustOptStage::ThinLTO:
1086 // FIXME: Does it make sense to pass the ModuleSummaryIndex?
1087 // It only seems to be needed for C++ specific optimizations.
1088 MPM = PB.buildThinLTODefaultPipeline(OptLevel, nullptr);
1090 case LLVMRustOptStage::FatLTO:
1091 MPM = PB.buildLTODefaultPipeline(OptLevel, nullptr);
1096 // We're not building any of the default pipelines but we still want to
1097 // add the verifier, instrumentation, etc passes if they were requested
1098 for (const auto &C : PipelineStartEPCallbacks)
1100 for (const auto &C : OptimizerLastEPCallbacks)
1104 if (ExtraPassesLen) {
1105 if (auto Err = PB.parsePassPipeline(MPM, StringRef(ExtraPasses, ExtraPassesLen))) {
1106 std::string ErrMsg = toString(std::move(Err));
1107 LLVMRustSetLastError(ErrMsg.c_str());
1108 return LLVMRustResult::Failure;
1112 if (NeedThinLTOBufferPasses) {
1113 MPM.addPass(CanonicalizeAliasesPass());
1114 MPM.addPass(NameAnonGlobalPass());
1117 // Upgrade all calls to old intrinsics first.
1118 for (Module::iterator I = TheModule->begin(), E = TheModule->end(); I != E;)
1119 UpgradeCallsToIntrinsic(&*I++); // must be post-increment, as we remove
1121 MPM.run(*TheModule, MAM);
1122 return LLVMRustResult::Success;
1125 // Callback to demangle function name
1127 // * name to be demangled
1130 // * output buffer len
1131 // Returns len of demangled string, or 0 if demangle failed.
1132 typedef size_t (*DemangleFn)(const char*, size_t, char*, size_t);
1137 class RustAssemblyAnnotationWriter : public AssemblyAnnotationWriter {
1138 DemangleFn Demangle;
1139 std::vector<char> Buf;
1142 RustAssemblyAnnotationWriter(DemangleFn Demangle) : Demangle(Demangle) {}
1144 // Return empty string if demangle failed
1145 // or if name does not need to be demangled
1146 StringRef CallDemangle(StringRef name) {
1151 if (Buf.size() < name.size() * 2) {
1152 // Semangled name usually shorter than mangled,
1153 // but allocate twice as much memory just in case
1154 Buf.resize(name.size() * 2);
1157 auto R = Demangle(name.data(), name.size(), Buf.data(), Buf.size());
1163 auto Demangled = StringRef(Buf.data(), R);
1164 if (Demangled == name) {
1165 // Do not print anything if demangled name is equal to mangled.
1172 void emitFunctionAnnot(const Function *F,
1173 formatted_raw_ostream &OS) override {
1174 StringRef Demangled = CallDemangle(F->getName());
1175 if (Demangled.empty()) {
1179 OS << "; " << Demangled << "\n";
1182 void emitInstructionAnnot(const Instruction *I,
1183 formatted_raw_ostream &OS) override {
1186 if (const CallInst *CI = dyn_cast<CallInst>(I)) {
1188 Value = CI->getCalledOperand();
1189 } else if (const InvokeInst* II = dyn_cast<InvokeInst>(I)) {
1191 Value = II->getCalledOperand();
1193 // Could demangle more operations, e. g.
1194 // `store %place, @function`.
1198 if (!Value->hasName()) {
1202 StringRef Demangled = CallDemangle(Value->getName());
1203 if (Demangled.empty()) {
1207 OS << "; " << Name << " " << Demangled << "\n";
1213 extern "C" LLVMRustResult
1214 LLVMRustPrintModule(LLVMModuleRef M, const char *Path, DemangleFn Demangle) {
1215 std::string ErrorInfo;
1217 raw_fd_ostream OS(Path, EC, sys::fs::OF_None);
1219 ErrorInfo = EC.message();
1220 if (ErrorInfo != "") {
1221 LLVMRustSetLastError(ErrorInfo.c_str());
1222 return LLVMRustResult::Failure;
1225 RustAssemblyAnnotationWriter AAW(Demangle);
1226 formatted_raw_ostream FOS(OS);
1227 unwrap(M)->print(FOS, &AAW);
1229 return LLVMRustResult::Success;
1232 extern "C" void LLVMRustPrintPasses() {
1233 LLVMInitializePasses();
1234 struct MyListener : PassRegistrationListener {
1235 void passEnumerate(const PassInfo *Info) {
1236 StringRef PassArg = Info->getPassArgument();
1237 StringRef PassName = Info->getPassName();
1238 if (!PassArg.empty()) {
1239 // These unsigned->signed casts could theoretically overflow, but
1240 // realistically never will (and even if, the result is implementation
1241 // defined rather plain UB).
1242 printf("%15.*s - %.*s\n", (int)PassArg.size(), PassArg.data(),
1243 (int)PassName.size(), PassName.data());
1248 PassRegistry *PR = PassRegistry::getPassRegistry();
1249 PR->enumerateWith(&Listener);
1252 extern "C" void LLVMRustAddAlwaysInlinePass(LLVMPassManagerBuilderRef PMBR,
1253 bool AddLifetimes) {
1254 unwrap(PMBR)->Inliner = llvm::createAlwaysInlinerLegacyPass(AddLifetimes);
1257 extern "C" void LLVMRustRunRestrictionPass(LLVMModuleRef M, char **Symbols,
1259 llvm::legacy::PassManager passes;
1261 auto PreserveFunctions = [=](const GlobalValue &GV) {
1262 for (size_t I = 0; I < Len; I++) {
1263 if (GV.getName() == Symbols[I]) {
1270 passes.add(llvm::createInternalizePass(PreserveFunctions));
1272 passes.run(*unwrap(M));
1276 LLVMRustSetDataLayoutFromTargetMachine(LLVMModuleRef Module,
1277 LLVMTargetMachineRef TMR) {
1278 TargetMachine *Target = unwrap(TMR);
1279 unwrap(Module)->setDataLayout(Target->createDataLayout());
1282 extern "C" void LLVMRustSetModulePICLevel(LLVMModuleRef M) {
1283 unwrap(M)->setPICLevel(PICLevel::Level::BigPIC);
1286 extern "C" void LLVMRustSetModulePIELevel(LLVMModuleRef M) {
1287 unwrap(M)->setPIELevel(PIELevel::Level::Large);
1290 extern "C" void LLVMRustSetModuleCodeModel(LLVMModuleRef M,
1291 LLVMRustCodeModel Model) {
1292 auto CM = fromRust(Model);
1295 unwrap(M)->setCodeModel(*CM);
1298 // Here you'll find an implementation of ThinLTO as used by the Rust compiler
1299 // right now. This ThinLTO support is only enabled on "recent ish" versions of
1300 // LLVM, and otherwise it's just blanket rejected from other compilers.
1302 // Most of this implementation is straight copied from LLVM. At the time of
1303 // this writing it wasn't *quite* suitable to reuse more code from upstream
1304 // for our purposes, but we should strive to upstream this support once it's
1305 // ready to go! I figure we may want a bit of testing locally first before
1306 // sending this upstream to LLVM. I hear though they're quite eager to receive
1307 // feedback like this!
1309 // If you're reading this code and wondering "what in the world" or you're
1310 // working "good lord by LLVM upgrade is *still* failing due to these bindings"
1311 // then fear not! (ok maybe fear a little). All code here is mostly based
1312 // on `lib/LTO/ThinLTOCodeGenerator.cpp` in LLVM.
1314 // You'll find that the general layout here roughly corresponds to the `run`
1315 // method in that file as well as `ProcessThinLTOModule`. Functions are
1316 // specifically commented below as well, but if you're updating this code
1317 // or otherwise trying to understand it, the LLVM source will be useful in
1318 // interpreting the mysteries within.
1320 // Otherwise I'll apologize in advance, it probably requires a relatively
1321 // significant investment on your part to "truly understand" what's going on
1322 // here. Not saying I do myself, but it took me awhile staring at LLVM's source
1323 // and various online resources about ThinLTO to make heads or tails of all
1326 // This is a shared data structure which *must* be threadsafe to share
1327 // read-only amongst threads. This also corresponds basically to the arguments
1328 // of the `ProcessThinLTOModule` function in the LLVM source.
1329 struct LLVMRustThinLTOData {
1330 // The combined index that is the global analysis over all modules we're
1331 // performing ThinLTO for. This is mostly managed by LLVM.
1332 ModuleSummaryIndex Index;
1334 // All modules we may look at, stored as in-memory serialized versions. This
1335 // is later used when inlining to ensure we can extract any module to inline
1337 StringMap<MemoryBufferRef> ModuleMap;
1339 // A set that we manage of everything we *don't* want internalized. Note that
1340 // this includes all transitive references right now as well, but it may not
1342 DenseSet<GlobalValue::GUID> GUIDPreservedSymbols;
1344 // Not 100% sure what these are, but they impact what's internalized and
1345 // what's inlined across modules, I believe.
1346 StringMap<FunctionImporter::ImportMapTy> ImportLists;
1347 StringMap<FunctionImporter::ExportSetTy> ExportLists;
1348 StringMap<GVSummaryMapTy> ModuleToDefinedGVSummaries;
1349 StringMap<std::map<GlobalValue::GUID, GlobalValue::LinkageTypes>> ResolvedODR;
1351 LLVMRustThinLTOData() : Index(/* HaveGVs = */ false) {}
1354 // Just an argument to the `LLVMRustCreateThinLTOData` function below.
1355 struct LLVMRustThinLTOModule {
1356 const char *identifier;
1361 // This is copied from `lib/LTO/ThinLTOCodeGenerator.cpp`, not sure what it
1363 static const GlobalValueSummary *
1364 getFirstDefinitionForLinker(const GlobalValueSummaryList &GVSummaryList) {
1365 auto StrongDefForLinker = llvm::find_if(
1366 GVSummaryList, [](const std::unique_ptr<GlobalValueSummary> &Summary) {
1367 auto Linkage = Summary->linkage();
1368 return !GlobalValue::isAvailableExternallyLinkage(Linkage) &&
1369 !GlobalValue::isWeakForLinker(Linkage);
1371 if (StrongDefForLinker != GVSummaryList.end())
1372 return StrongDefForLinker->get();
1374 auto FirstDefForLinker = llvm::find_if(
1375 GVSummaryList, [](const std::unique_ptr<GlobalValueSummary> &Summary) {
1376 auto Linkage = Summary->linkage();
1377 return !GlobalValue::isAvailableExternallyLinkage(Linkage);
1379 if (FirstDefForLinker == GVSummaryList.end())
1381 return FirstDefForLinker->get();
1384 // The main entry point for creating the global ThinLTO analysis. The structure
1385 // here is basically the same as before threads are spawned in the `run`
1386 // function of `lib/LTO/ThinLTOCodeGenerator.cpp`.
1387 extern "C" LLVMRustThinLTOData*
1388 LLVMRustCreateThinLTOData(LLVMRustThinLTOModule *modules,
1390 const char **preserved_symbols,
1392 auto Ret = std::make_unique<LLVMRustThinLTOData>();
1394 // Load each module's summary and merge it into one combined index
1395 for (int i = 0; i < num_modules; i++) {
1396 auto module = &modules[i];
1397 StringRef buffer(module->data, module->len);
1398 MemoryBufferRef mem_buffer(buffer, module->identifier);
1400 Ret->ModuleMap[module->identifier] = mem_buffer;
1402 if (Error Err = readModuleSummaryIndex(mem_buffer, Ret->Index, i)) {
1403 LLVMRustSetLastError(toString(std::move(Err)).c_str());
1408 // Collect for each module the list of function it defines (GUID -> Summary)
1409 Ret->Index.collectDefinedGVSummariesPerModule(Ret->ModuleToDefinedGVSummaries);
1411 // Convert the preserved symbols set from string to GUID, this is then needed
1412 // for internalization.
1413 for (int i = 0; i < num_symbols; i++) {
1414 auto GUID = GlobalValue::getGUID(preserved_symbols[i]);
1415 Ret->GUIDPreservedSymbols.insert(GUID);
1418 // Collect the import/export lists for all modules from the call-graph in the
1421 // This is copied from `lib/LTO/ThinLTOCodeGenerator.cpp`
1422 auto deadIsPrevailing = [&](GlobalValue::GUID G) {
1423 return PrevailingType::Unknown;
1425 // We don't have a complete picture in our use of ThinLTO, just our immediate
1426 // crate, so we need `ImportEnabled = false` to limit internalization.
1427 // Otherwise, we sometimes lose `static` values -- see #60184.
1428 computeDeadSymbolsWithConstProp(Ret->Index, Ret->GUIDPreservedSymbols,
1429 deadIsPrevailing, /* ImportEnabled = */ false);
1430 ComputeCrossModuleImport(
1432 Ret->ModuleToDefinedGVSummaries,
1437 // Resolve LinkOnce/Weak symbols, this has to be computed early be cause it
1438 // impacts the caching.
1440 // This is copied from `lib/LTO/ThinLTOCodeGenerator.cpp` with some of this
1441 // being lifted from `lib/LTO/LTO.cpp` as well
1442 DenseMap<GlobalValue::GUID, const GlobalValueSummary *> PrevailingCopy;
1443 for (auto &I : Ret->Index) {
1444 if (I.second.SummaryList.size() > 1)
1445 PrevailingCopy[I.first] = getFirstDefinitionForLinker(I.second.SummaryList);
1447 auto isPrevailing = [&](GlobalValue::GUID GUID, const GlobalValueSummary *S) {
1448 const auto &Prevailing = PrevailingCopy.find(GUID);
1449 if (Prevailing == PrevailingCopy.end())
1451 return Prevailing->second == S;
1453 auto recordNewLinkage = [&](StringRef ModuleIdentifier,
1454 GlobalValue::GUID GUID,
1455 GlobalValue::LinkageTypes NewLinkage) {
1456 Ret->ResolvedODR[ModuleIdentifier][GUID] = NewLinkage;
1459 #if LLVM_VERSION_GE(13,0)
1460 // Uses FromPrevailing visibility scheme which works for many binary
1461 // formats. We probably could and should use ELF visibility scheme for many of
1462 // our targets, however.
1464 thinLTOResolvePrevailingInIndex(conf, Ret->Index, isPrevailing, recordNewLinkage,
1465 Ret->GUIDPreservedSymbols);
1467 thinLTOResolvePrevailingInIndex(Ret->Index, isPrevailing, recordNewLinkage,
1468 Ret->GUIDPreservedSymbols);
1470 // Here we calculate an `ExportedGUIDs` set for use in the `isExported`
1471 // callback below. This callback below will dictate the linkage for all
1472 // summaries in the index, and we basically just only want to ensure that dead
1473 // symbols are internalized. Otherwise everything that's already external
1474 // linkage will stay as external, and internal will stay as internal.
1475 std::set<GlobalValue::GUID> ExportedGUIDs;
1476 for (auto &List : Ret->Index) {
1477 for (auto &GVS: List.second.SummaryList) {
1478 if (GlobalValue::isLocalLinkage(GVS->linkage()))
1480 auto GUID = GVS->getOriginalName();
1481 if (GVS->flags().Live)
1482 ExportedGUIDs.insert(GUID);
1485 auto isExported = [&](StringRef ModuleIdentifier, ValueInfo VI) {
1486 const auto &ExportList = Ret->ExportLists.find(ModuleIdentifier);
1487 return (ExportList != Ret->ExportLists.end() &&
1488 ExportList->second.count(VI)) ||
1489 ExportedGUIDs.count(VI.getGUID());
1491 thinLTOInternalizeAndPromoteInIndex(Ret->Index, isExported, isPrevailing);
1493 return Ret.release();
1497 LLVMRustFreeThinLTOData(LLVMRustThinLTOData *Data) {
1501 // Below are the various passes that happen *per module* when doing ThinLTO.
1503 // In other words, these are the functions that are all run concurrently
1504 // with one another, one per module. The passes here correspond to the analysis
1505 // passes in `lib/LTO/ThinLTOCodeGenerator.cpp`, currently found in the
1506 // `ProcessThinLTOModule` function. Here they're split up into separate steps
1507 // so rustc can save off the intermediate bytecode between each step.
1510 clearDSOLocalOnDeclarations(Module &Mod, TargetMachine &TM) {
1511 // When linking an ELF shared object, dso_local should be dropped. We
1512 // conservatively do this for -fpic.
1513 bool ClearDSOLocalOnDeclarations =
1514 TM.getTargetTriple().isOSBinFormatELF() &&
1515 TM.getRelocationModel() != Reloc::Static &&
1516 Mod.getPIELevel() == PIELevel::Default;
1517 return ClearDSOLocalOnDeclarations;
1521 LLVMRustPrepareThinLTORename(const LLVMRustThinLTOData *Data, LLVMModuleRef M,
1522 LLVMTargetMachineRef TM) {
1523 Module &Mod = *unwrap(M);
1524 TargetMachine &Target = *unwrap(TM);
1526 bool ClearDSOLocal = clearDSOLocalOnDeclarations(Mod, Target);
1527 bool error = renameModuleForThinLTO(Mod, Data->Index, ClearDSOLocal);
1530 LLVMRustSetLastError("renameModuleForThinLTO failed");
1537 LLVMRustPrepareThinLTOResolveWeak(const LLVMRustThinLTOData *Data, LLVMModuleRef M) {
1538 Module &Mod = *unwrap(M);
1539 const auto &DefinedGlobals = Data->ModuleToDefinedGVSummaries.lookup(Mod.getModuleIdentifier());
1540 #if LLVM_VERSION_GE(14, 0)
1541 thinLTOFinalizeInModule(Mod, DefinedGlobals, /*PropagateAttrs=*/true);
1543 thinLTOResolvePrevailingInModule(Mod, DefinedGlobals);
1549 LLVMRustPrepareThinLTOInternalize(const LLVMRustThinLTOData *Data, LLVMModuleRef M) {
1550 Module &Mod = *unwrap(M);
1551 const auto &DefinedGlobals = Data->ModuleToDefinedGVSummaries.lookup(Mod.getModuleIdentifier());
1552 thinLTOInternalizeModule(Mod, DefinedGlobals);
1557 LLVMRustPrepareThinLTOImport(const LLVMRustThinLTOData *Data, LLVMModuleRef M,
1558 LLVMTargetMachineRef TM) {
1559 Module &Mod = *unwrap(M);
1560 TargetMachine &Target = *unwrap(TM);
1562 const auto &ImportList = Data->ImportLists.lookup(Mod.getModuleIdentifier());
1563 auto Loader = [&](StringRef Identifier) {
1564 const auto &Memory = Data->ModuleMap.lookup(Identifier);
1565 auto &Context = Mod.getContext();
1566 auto MOrErr = getLazyBitcodeModule(Memory, Context, true, true);
1571 // The rest of this closure is a workaround for
1572 // https://bugs.llvm.org/show_bug.cgi?id=38184 where during ThinLTO imports
1573 // we accidentally import wasm custom sections into different modules,
1574 // duplicating them by in the final output artifact.
1576 // The issue is worked around here by manually removing the
1577 // `wasm.custom_sections` named metadata node from any imported module. This
1578 // we know isn't used by any optimization pass so there's no need for it to
1581 // Note that the metadata is currently lazily loaded, so we materialize it
1582 // here before looking up if there's metadata inside. The `FunctionImporter`
1583 // will immediately materialize metadata anyway after an import, so this
1584 // shouldn't be a perf hit.
1585 if (Error Err = (*MOrErr)->materializeMetadata()) {
1586 Expected<std::unique_ptr<Module>> Ret(std::move(Err));
1590 auto *WasmCustomSections = (*MOrErr)->getNamedMetadata("wasm.custom_sections");
1591 if (WasmCustomSections)
1592 WasmCustomSections->eraseFromParent();
1596 bool ClearDSOLocal = clearDSOLocalOnDeclarations(Mod, Target);
1597 FunctionImporter Importer(Data->Index, Loader, ClearDSOLocal);
1598 Expected<bool> Result = Importer.importFunctions(Mod, ImportList);
1600 LLVMRustSetLastError(toString(Result.takeError()).c_str());
1606 extern "C" typedef void (*LLVMRustModuleNameCallback)(void*, // payload
1607 const char*, // importing module name
1608 const char*); // imported module name
1610 // Calls `module_name_callback` for each module import done by ThinLTO.
1611 // The callback is provided with regular null-terminated C strings.
1613 LLVMRustGetThinLTOModules(const LLVMRustThinLTOData *data,
1614 LLVMRustModuleNameCallback module_name_callback,
1615 void* callback_payload) {
1616 for (const auto& importing_module : data->ImportLists) {
1617 const std::string importing_module_id = importing_module.getKey().str();
1618 const auto& imports = importing_module.getValue();
1619 for (const auto& imported_module : imports) {
1620 const std::string imported_module_id = imported_module.getKey().str();
1621 module_name_callback(callback_payload,
1622 importing_module_id.c_str(),
1623 imported_module_id.c_str());
1628 // This struct and various functions are sort of a hack right now, but the
1629 // problem is that we've got in-memory LLVM modules after we generate and
1630 // optimize all codegen-units for one compilation in rustc. To be compatible
1631 // with the LTO support above we need to serialize the modules plus their
1632 // ThinLTO summary into memory.
1634 // This structure is basically an owned version of a serialize module, with
1635 // a ThinLTO summary attached.
1636 struct LLVMRustThinLTOBuffer {
1640 extern "C" LLVMRustThinLTOBuffer*
1641 LLVMRustThinLTOBufferCreate(LLVMModuleRef M) {
1642 auto Ret = std::make_unique<LLVMRustThinLTOBuffer>();
1644 raw_string_ostream OS(Ret->data);
1646 legacy::PassManager PM;
1647 PM.add(createWriteThinLTOBitcodePass(OS));
1651 return Ret.release();
1655 LLVMRustThinLTOBufferFree(LLVMRustThinLTOBuffer *Buffer) {
1659 extern "C" const void*
1660 LLVMRustThinLTOBufferPtr(const LLVMRustThinLTOBuffer *Buffer) {
1661 return Buffer->data.data();
1665 LLVMRustThinLTOBufferLen(const LLVMRustThinLTOBuffer *Buffer) {
1666 return Buffer->data.length();
1669 // This is what we used to parse upstream bitcode for actual ThinLTO
1670 // processing. We'll call this once per module optimized through ThinLTO, and
1671 // it'll be called concurrently on many threads.
1672 extern "C" LLVMModuleRef
1673 LLVMRustParseBitcodeForLTO(LLVMContextRef Context,
1676 const char *identifier) {
1677 StringRef Data(data, len);
1678 MemoryBufferRef Buffer(Data, identifier);
1679 unwrap(Context)->enableDebugTypeODRUniquing();
1680 Expected<std::unique_ptr<Module>> SrcOrError =
1681 parseBitcodeFile(Buffer, *unwrap(Context));
1683 LLVMRustSetLastError(toString(SrcOrError.takeError()).c_str());
1686 return wrap(std::move(*SrcOrError).release());
1689 // Find the bitcode section in the object file data and return it as a slice.
1690 // Fail if the bitcode section is present but empty.
1692 // On success, the return value is the pointer to the start of the slice and
1693 // `out_len` is filled with the (non-zero) length. On failure, the return value
1694 // is `nullptr` and `out_len` is set to zero.
1695 extern "C" const char*
1696 LLVMRustGetBitcodeSliceFromObjectData(const char *data,
1701 StringRef Data(data, len);
1702 MemoryBufferRef Buffer(Data, ""); // The id is unused.
1704 Expected<MemoryBufferRef> BitcodeOrError =
1705 object::IRObjectFile::findBitcodeInMemBuffer(Buffer);
1706 if (!BitcodeOrError) {
1707 LLVMRustSetLastError(toString(BitcodeOrError.takeError()).c_str());
1711 *out_len = BitcodeOrError->getBufferSize();
1712 return BitcodeOrError->getBufferStart();
1715 // Rewrite all `DICompileUnit` pointers to the `DICompileUnit` specified. See
1716 // the comment in `back/lto.rs` for why this exists.
1718 LLVMRustThinLTOGetDICompileUnit(LLVMModuleRef Mod,
1720 DICompileUnit **B) {
1721 Module *M = unwrap(Mod);
1722 DICompileUnit **Cur = A;
1723 DICompileUnit **Next = B;
1724 for (DICompileUnit *CU : M->debug_compile_units()) {
1733 // Rewrite all `DICompileUnit` pointers to the `DICompileUnit` specified. See
1734 // the comment in `back/lto.rs` for why this exists.
1736 LLVMRustThinLTOPatchDICompileUnit(LLVMModuleRef Mod, DICompileUnit *Unit) {
1737 Module *M = unwrap(Mod);
1739 // If the original source module didn't have a `DICompileUnit` then try to
1740 // merge all the existing compile units. If there aren't actually any though
1741 // then there's not much for us to do so return.
1742 if (Unit == nullptr) {
1743 for (DICompileUnit *CU : M->debug_compile_units()) {
1747 if (Unit == nullptr)
1751 // Use LLVM's built-in `DebugInfoFinder` to find a bunch of debuginfo and
1752 // process it recursively. Note that we used to specifically iterate over
1753 // instructions to ensure we feed everything into it, but `processModule`
1754 // started doing this the same way in LLVM 7 (commit d769eb36ab2b8).
1755 DebugInfoFinder Finder;
1756 Finder.processModule(*M);
1758 // After we've found all our debuginfo, rewrite all subprograms to point to
1759 // the same `DICompileUnit`.
1760 for (auto &F : Finder.subprograms()) {
1761 F->replaceUnit(Unit);
1764 // Erase any other references to other `DICompileUnit` instances, the verifier
1765 // will later ensure that we don't actually have any other stale references to
1767 auto *MD = M->getNamedMetadata("llvm.dbg.cu");
1768 MD->clearOperands();
1769 MD->addOperand(Unit);
1772 // Computes the LTO cache key for the provided 'ModId' in the given 'Data',
1773 // storing the result in 'KeyOut'.
1774 // Currently, this cache key is a SHA-1 hash of anything that could affect
1775 // the result of optimizing this module (e.g. module imports, exports, liveness
1776 // of access globals, etc).
1777 // The precise details are determined by LLVM in `computeLTOCacheKey`, which is
1778 // used during the normal linker-plugin incremental thin-LTO process.
1780 LLVMRustComputeLTOCacheKey(RustStringRef KeyOut, const char *ModId, LLVMRustThinLTOData *Data) {
1781 SmallString<40> Key;
1782 llvm::lto::Config conf;
1783 const auto &ImportList = Data->ImportLists.lookup(ModId);
1784 const auto &ExportList = Data->ExportLists.lookup(ModId);
1785 const auto &ResolvedODR = Data->ResolvedODR.lookup(ModId);
1786 const auto &DefinedGlobals = Data->ModuleToDefinedGVSummaries.lookup(ModId);
1787 std::set<GlobalValue::GUID> CfiFunctionDefs;
1788 std::set<GlobalValue::GUID> CfiFunctionDecls;
1790 // Based on the 'InProcessThinBackend' constructor in LLVM
1791 for (auto &Name : Data->Index.cfiFunctionDefs())
1792 CfiFunctionDefs.insert(
1793 GlobalValue::getGUID(GlobalValue::dropLLVMManglingEscape(Name)));
1794 for (auto &Name : Data->Index.cfiFunctionDecls())
1795 CfiFunctionDecls.insert(
1796 GlobalValue::getGUID(GlobalValue::dropLLVMManglingEscape(Name)));
1798 llvm::computeLTOCacheKey(Key, conf, Data->Index, ModId,
1799 ImportList, ExportList, ResolvedODR, DefinedGlobals, CfiFunctionDefs, CfiFunctionDecls
1802 LLVMRustStringWriteImpl(KeyOut, Key.c_str(), Key.size());