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/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"
27 #include "llvm/MC/TargetRegistry.h"
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"
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"
52 typedef struct LLVMOpaquePass *LLVMPassRef;
53 typedef struct LLVMOpaqueTargetMachine *LLVMTargetMachineRef;
55 DEFINE_STDCXX_CONVERSION_FUNCTIONS(Pass, LLVMPassRef)
56 DEFINE_STDCXX_CONVERSION_FUNCTIONS(TargetMachine, LLVMTargetMachineRef)
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);
72 extern "C" void LLVMTimeTraceProfilerInitialize() {
73 timeTraceProfilerInitialize(
74 /* TimeTraceGranularity */ 0,
75 /* ProcName */ "rustc");
78 extern "C" void LLVMTimeTraceProfilerFinishThread() {
79 timeTraceProfilerFinishThread();
82 extern "C" void LLVMTimeTraceProfilerFinish(const char* FileName) {
83 StringRef FN(FileName);
85 raw_fd_ostream OS(FN, EC, sys::fs::CD_CreateAlways);
87 timeTraceProfilerWrite(OS);
88 timeTraceProfilerCleanup();
91 enum class LLVMRustPassKind {
97 static LLVMRustPassKind toRust(PassKind Kind) {
100 return LLVMRustPassKind::Function;
102 return LLVMRustPassKind::Module;
104 return LLVMRustPassKind::Other;
108 extern "C" LLVMPassRef LLVMRustFindAndCreatePass(const char *PassName) {
109 StringRef SR(PassName);
110 PassRegistry *PR = PassRegistry::getPassRegistry();
112 const PassInfo *PI = PR->getPassInfo(SR);
114 return wrap(PI->createPass());
119 extern "C" LLVMPassRef LLVMRustCreateAddressSanitizerFunctionPass(bool Recover) {
120 const bool CompileKernel = false;
121 const bool UseAfterScope = true;
123 return wrap(createAddressSanitizerFunctionPass(CompileKernel, Recover, UseAfterScope));
126 extern "C" LLVMPassRef LLVMRustCreateModuleAddressSanitizerPass(bool Recover) {
127 const bool CompileKernel = false;
129 return wrap(createModuleAddressSanitizerLegacyPassPass(CompileKernel, Recover));
132 extern "C" LLVMPassRef LLVMRustCreateMemorySanitizerPass(int TrackOrigins, bool Recover) {
133 const bool CompileKernel = false;
135 return wrap(createMemorySanitizerLegacyPassPass(
136 MemorySanitizerOptions{TrackOrigins, Recover, CompileKernel}));
139 extern "C" LLVMPassRef LLVMRustCreateThreadSanitizerPass() {
140 return wrap(createThreadSanitizerLegacyPassPass());
143 extern "C" LLVMPassRef LLVMRustCreateHWAddressSanitizerPass(bool Recover) {
144 const bool CompileKernel = false;
146 return wrap(createHWAddressSanitizerLegacyPassPass(CompileKernel, Recover));
149 extern "C" LLVMRustPassKind LLVMRustPassKind(LLVMPassRef RustPass) {
151 Pass *Pass = unwrap(RustPass);
152 return toRust(Pass->getPassKind());
155 extern "C" void LLVMRustAddPass(LLVMPassManagerRef PMR, LLVMPassRef RustPass) {
157 Pass *Pass = unwrap(RustPass);
158 PassManagerBase *PMB = unwrap(PMR);
163 void LLVMRustPassManagerBuilderPopulateThinLTOPassManager(
164 LLVMPassManagerBuilderRef PMBR,
165 LLVMPassManagerRef PMR
167 unwrap(PMBR)->populateThinLTOPassManager(*unwrap(PMR));
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]));
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,
183 unwrap(PMBR)->addExtension(PassManagerBuilder::EP_EnabledOnOptLevel0,
187 #ifdef LLVM_COMPONENT_X86
188 #define SUBTARGET_X86 SUBTARGET(X86)
190 #define SUBTARGET_X86
193 #ifdef LLVM_COMPONENT_ARM
194 #define SUBTARGET_ARM SUBTARGET(ARM)
196 #define SUBTARGET_ARM
199 #ifdef LLVM_COMPONENT_AARCH64
200 #define SUBTARGET_AARCH64 SUBTARGET(AArch64)
202 #define SUBTARGET_AARCH64
205 #ifdef LLVM_COMPONENT_AVR
206 #define SUBTARGET_AVR SUBTARGET(AVR)
208 #define SUBTARGET_AVR
211 #ifdef LLVM_COMPONENT_M68k
212 #define SUBTARGET_M68K SUBTARGET(M68k)
214 #define SUBTARGET_M68K
217 #ifdef LLVM_COMPONENT_MIPS
218 #define SUBTARGET_MIPS SUBTARGET(Mips)
220 #define SUBTARGET_MIPS
223 #ifdef LLVM_COMPONENT_POWERPC
224 #define SUBTARGET_PPC SUBTARGET(PPC)
226 #define SUBTARGET_PPC
229 #ifdef LLVM_COMPONENT_SYSTEMZ
230 #define SUBTARGET_SYSTEMZ SUBTARGET(SystemZ)
232 #define SUBTARGET_SYSTEMZ
235 #ifdef LLVM_COMPONENT_MSP430
236 #define SUBTARGET_MSP430 SUBTARGET(MSP430)
238 #define SUBTARGET_MSP430
241 #ifdef LLVM_COMPONENT_RISCV
242 #define SUBTARGET_RISCV SUBTARGET(RISCV)
244 #define SUBTARGET_RISCV
247 #ifdef LLVM_COMPONENT_SPARC
248 #define SUBTARGET_SPARC SUBTARGET(Sparc)
250 #define SUBTARGET_SPARC
253 #ifdef LLVM_COMPONENT_HEXAGON
254 #define SUBTARGET_HEXAGON SUBTARGET(Hexagon)
256 #define SUBTARGET_HEXAGON
259 #define GEN_SUBTARGETS \
273 #define SUBTARGET(x) \
275 extern const SubtargetFeatureKV x##FeatureKV[]; \
276 extern const SubtargetFeatureKV x##SubTypeKV[]; \
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);
289 enum class LLVMRustCodeModel {
298 static Optional<CodeModel::Model> fromRust(LLVMRustCodeModel 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:
313 report_fatal_error("Bad CodeModel.");
317 enum class LLVMRustCodeGenOptLevel {
324 static CodeGenOpt::Level fromRust(LLVMRustCodeGenOptLevel 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;
335 report_fatal_error("Bad CodeGenOptLevel.");
339 enum class LLVMRustPassBuilderOptLevel {
348 #if LLVM_VERSION_LT(14,0)
349 using OptimizationLevel = PassBuilder::OptimizationLevel;
352 static OptimizationLevel fromRust(LLVMRustPassBuilderOptLevel 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;
367 report_fatal_error("Bad PassBuilderOptLevel.");
371 enum class LLVMRustRelocModel {
380 static Reloc::Model fromRust(LLVMRustRelocModel RustReloc) {
382 case LLVMRustRelocModel::Static:
383 return Reloc::Static;
384 case LLVMRustRelocModel::PIC:
386 case LLVMRustRelocModel::DynamicNoPic:
387 return Reloc::DynamicNoPIC;
388 case LLVMRustRelocModel::ROPI:
390 case LLVMRustRelocModel::RWPI:
392 case LLVMRustRelocModel::ROPIRWPI:
393 return Reloc::ROPI_RWPI;
395 report_fatal_error("Bad RelocModel.");
399 /// getLongestEntryLength - Return the length of the longest entry in the table.
400 template<typename KV>
401 static size_t getLongestEntryLength(ArrayRef<KV> Table) {
403 for (auto &I : Table)
404 MaxLen = std::max(MaxLen, std::strlen(I.Key));
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);
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());
422 for (auto &CPU : CPUTable)
423 printf(" %-*s\n", MaxCPULen, CPU.Key);
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();
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];
446 extern "C" void LLVMRustPrintTargetCPUs(LLVMTargetMachineRef) {
447 printf("Target CPU help is not supported by this LLVM version.\n\n");
450 extern "C" size_t LLVMRustGetTargetFeaturesCount(LLVMTargetMachineRef) {
454 extern "C" void LLVMRustGetTargetFeature(LLVMTargetMachineRef, const char**, const char**) {}
457 extern "C" const char* LLVMRustGetHostCPUName(size_t *len) {
458 StringRef Name = sys::getHostCPUName();
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,
469 bool UniqueSectionNames,
470 bool TrapUnreachable,
473 bool EmitStackSizeSection,
474 bool RelaxELFRelocations,
476 const char *SplitDwarfFile) {
478 auto OptLevel = fromRust(RustOptLevel);
479 auto RM = fromRust(RustReloc);
480 auto CM = fromRust(RustCM);
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());
491 TargetOptions Options;
493 Options.FloatABIType = FloatABI::Default;
495 Options.FloatABIType = FloatABI::Soft;
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;
506 Options.RelaxELFRelocations = RelaxELFRelocations;
507 Options.UseInitArray = UseInitArray;
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;
518 Options.ThreadModel = ThreadModel::Single;
521 Options.EmitStackSizeSection = EmitStackSizeSection;
523 TargetMachine *TM = TheTarget->createTargetMachine(
524 Trip.getTriple(), CPU, Feature, Options, RM, CM, OptLevel);
528 extern "C" void LLVMRustDisposeTargetMachine(LLVMTargetMachineRef TM) {
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;
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;
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.
556 extern "C" void LLVMRustAddBuilderLibraryInfo(LLVMPassManagerBuilderRef PMBR,
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;
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.
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));
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.
580 extern "C" void LLVMRustRunFunctionPassManager(LLVMPassManagerRef PMR,
582 llvm::legacy::FunctionPassManager *P =
583 unwrap<llvm::legacy::FunctionPassManager>(PMR);
584 P->doInitialization();
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
590 for (Module::iterator I = unwrap(M)->begin(), E = unwrap(M)->end(); I != E;
592 if (!I->isDeclaration())
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;
607 cl::ParseCommandLineOptions(Argc, Argv);
610 enum class LLVMRustFileType {
615 static CodeGenFileType fromRust(LLVMRustFileType Type) {
617 case LLVMRustFileType::AssemblyFile:
618 return CGFT_AssemblyFile;
619 case LLVMRustFileType::ObjectFile:
620 return CGFT_ObjectFile;
622 report_fatal_error("Bad FileType.");
626 extern "C" LLVMRustResult
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);
633 std::string ErrorInfo;
635 raw_fd_ostream OS(Path, EC, sys::fs::OF_None);
637 ErrorInfo = EC.message();
638 if (ErrorInfo != "") {
639 LLVMRustSetLastError(ErrorInfo.c_str());
640 return LLVMRustResult::Failure;
643 buffer_ostream BOS(OS);
645 raw_fd_ostream DOS(DwoPath, EC, sys::fs::OF_None);
648 ErrorInfo = EC.message();
649 if (ErrorInfo != "") {
650 LLVMRustSetLastError(ErrorInfo.c_str());
651 return LLVMRustResult::Failure;
653 buffer_ostream DBOS(DOS);
654 unwrap(Target)->addPassesToEmitFile(*PM, BOS, &DBOS, FileType, false);
657 unwrap(Target)->addPassesToEmitFile(*PM, BOS, nullptr, FileType, false);
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;
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
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();
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());
697 PIC.registerAfterPassCallback(
698 [LlvmSelfProfiler, AfterPassCallback](StringRef Pass, llvm::Any IR,
699 const PreservedAnalyses &Preserved) {
700 AfterPassCallback(LlvmSelfProfiler);
703 PIC.registerAfterPassInvalidatedCallback(
704 [LlvmSelfProfiler, AfterPassCallback](StringRef Pass, const PreservedAnalyses &Preserved) {
705 AfterPassCallback(LlvmSelfProfiler);
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());
715 PIC.registerAfterAnalysisCallback(
716 [LlvmSelfProfiler, AfterPassCallback](StringRef Pass, llvm::Any Ir) {
717 AfterPassCallback(LlvmSelfProfiler);
721 enum class LLVMRustOptStage {
729 struct LLVMRustSanitizerOptions {
730 bool SanitizeAddress;
731 bool SanitizeAddressRecover;
733 bool SanitizeMemoryRecover;
734 int SanitizeMemoryTrackOrigins;
736 bool SanitizeHWAddress;
737 bool SanitizeHWAddressRecover;
740 extern "C" LLVMRustResult
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);
762 PipelineTuningOptions PTO;
763 PTO.LoopUnrolling = UnrollLoops;
764 PTO.LoopInterleaving = UnrollLoops;
765 PTO.LoopVectorization = LoopVectorize;
766 PTO.SLPVectorization = SLPVectorize;
767 PTO.MergeFunctions = MergeFunctions;
769 // FIXME: We may want to expose this as an option.
770 bool DebugPassManager = false;
772 PassInstrumentationCallbacks PIC;
773 StandardInstrumentations SI(DebugPassManager);
774 SI.registerCallbacks(PIC);
776 if (LlvmSelfProfiler){
777 LLVMSelfProfileInitializeCallbacks(PIC,LlvmSelfProfiler,BeforePassCallback,AfterPassCallback);
780 Optional<PGOOptions> PGOOpt;
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);
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;
804 PassBuilder PB(DebugPassManager, TM, PTO, PGOOpt, &PIC);
805 LoopAnalysisManager LAM(DebugPassManager);
806 FunctionAnalysisManager FAM(DebugPassManager);
807 CGSCCAnalysisManager CGAM(DebugPassManager);
808 ModuleAnalysisManager MAM(DebugPassManager);
811 FAM.registerPass([&] { return PB.buildDefaultAAPipeline(); });
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); });
819 PB.registerModuleAnalyses(MAM);
820 PB.registerCGSCCAnalyses(CGAM);
821 PB.registerFunctionAnalyses(FAM);
822 PB.registerLoopAnalyses(LAM);
823 PB.crossRegisterProxies(LAM, FAM, CGAM, MAM);
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;
833 PipelineStartEPCallbacks.push_back(
834 [VerifyIR](ModulePassManager &MPM, OptimizationLevel Level) {
835 MPM.addPass(VerifierPass());
840 if (InstrumentGCOV) {
841 PipelineStartEPCallbacks.push_back(
842 [](ModulePassManager &MPM, OptimizationLevel Level) {
843 MPM.addPass(GCOVProfilerPass(GCOVOptions::getDefault()));
848 if (InstrumentCoverage) {
849 PipelineStartEPCallbacks.push_back(
850 [](ModulePassManager &MPM, OptimizationLevel Level) {
851 InstrProfOptions Options;
852 MPM.addPass(InstrProfiling(Options, false));
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));
868 MPM.addPass(MemorySanitizerPass(Options));
870 MPM.addPass(createModuleToFunctionPassAdaptor(MemorySanitizerPass(Options)));
875 if (SanitizerOptions->SanitizeThread) {
876 OptimizerLastEPCallbacks.push_back(
877 [](ModulePassManager &MPM, OptimizationLevel Level) {
878 #if LLVM_VERSION_GE(14, 0)
879 MPM.addPass(ModuleThreadSanitizerPass());
881 MPM.addPass(ThreadSanitizerPass());
883 MPM.addPass(createModuleToFunctionPassAdaptor(ThreadSanitizerPass()));
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,
899 MPM.addPass(ModuleAddressSanitizerPass(opts));
900 MPM.addPass(createModuleToFunctionPassAdaptor(AddressSanitizerPass(opts)));
902 MPM.addPass(ModuleAddressSanitizerPass(
903 /*CompileKernel=*/false, SanitizerOptions->SanitizeAddressRecover));
904 MPM.addPass(createModuleToFunctionPassAdaptor(AddressSanitizerPass(
905 /*CompileKernel=*/false, SanitizerOptions->SanitizeAddressRecover,
906 /*UseAfterScope=*/true)));
911 if (SanitizerOptions->SanitizeHWAddress) {
912 OptimizerLastEPCallbacks.push_back(
913 [SanitizerOptions](ModulePassManager &MPM, OptimizationLevel Level) {
914 #if LLVM_VERSION_GE(14, 0)
915 HWAddressSanitizerOptions opts(
916 /*CompileKernel=*/false, SanitizerOptions->SanitizeHWAddressRecover,
917 /*DisableOptimization=*/false);
918 MPM.addPass(HWAddressSanitizerPass(opts));
920 MPM.addPass(HWAddressSanitizerPass(
921 /*CompileKernel=*/false, SanitizerOptions->SanitizeHWAddressRecover));
928 #if LLVM_VERSION_GE(13, 0)
929 ModulePassManager MPM;
931 ModulePassManager MPM(DebugPassManager);
933 bool NeedThinLTOBufferPasses = UseThinLTOBuffers;
934 if (!NoPrepopulatePasses) {
935 // The pre-link pipelines don't support O0 and require using budilO0DefaultPipeline() instead.
936 // At the same time, the LTO pipelines do support O0 and using them is required.
937 bool IsLTO = OptStage == LLVMRustOptStage::ThinLTO || OptStage == LLVMRustOptStage::FatLTO;
938 if (OptLevel == OptimizationLevel::O0 && !IsLTO) {
939 for (const auto &C : PipelineStartEPCallbacks)
940 PB.registerPipelineStartEPCallback(C);
941 for (const auto &C : OptimizerLastEPCallbacks)
942 PB.registerOptimizerLastEPCallback(C);
944 // Pass false as we manually schedule ThinLTOBufferPasses below.
945 MPM = PB.buildO0DefaultPipeline(OptLevel, /* PreLinkLTO */ false);
947 for (const auto &C : PipelineStartEPCallbacks)
948 PB.registerPipelineStartEPCallback(C);
949 if (OptStage != LLVMRustOptStage::PreLinkThinLTO) {
950 for (const auto &C : OptimizerLastEPCallbacks)
951 PB.registerOptimizerLastEPCallback(C);
955 case LLVMRustOptStage::PreLinkNoLTO:
956 MPM = PB.buildPerModuleDefaultPipeline(OptLevel, DebugPassManager);
958 case LLVMRustOptStage::PreLinkThinLTO:
959 MPM = PB.buildThinLTOPreLinkDefaultPipeline(OptLevel);
960 // The ThinLTOPreLink pipeline already includes ThinLTOBuffer passes. However, callback
961 // passes may still run afterwards. This means we need to run the buffer passes again.
962 // FIXME: In LLVM 13, the ThinLTOPreLink pipeline also runs OptimizerLastEPCallbacks
963 // before the RequiredLTOPreLinkPasses, in which case we can remove these hacks.
964 if (OptimizerLastEPCallbacks.empty())
965 NeedThinLTOBufferPasses = false;
966 for (const auto &C : OptimizerLastEPCallbacks)
969 case LLVMRustOptStage::PreLinkFatLTO:
970 MPM = PB.buildLTOPreLinkDefaultPipeline(OptLevel);
971 NeedThinLTOBufferPasses = false;
973 case LLVMRustOptStage::ThinLTO:
974 // FIXME: Does it make sense to pass the ModuleSummaryIndex?
975 // It only seems to be needed for C++ specific optimizations.
976 MPM = PB.buildThinLTODefaultPipeline(OptLevel, nullptr);
978 case LLVMRustOptStage::FatLTO:
979 MPM = PB.buildLTODefaultPipeline(OptLevel, nullptr);
985 if (ExtraPassesLen) {
986 if (auto Err = PB.parsePassPipeline(MPM, StringRef(ExtraPasses, ExtraPassesLen))) {
987 std::string ErrMsg = toString(std::move(Err));
988 LLVMRustSetLastError(ErrMsg.c_str());
989 return LLVMRustResult::Failure;
993 if (NeedThinLTOBufferPasses) {
994 MPM.addPass(CanonicalizeAliasesPass());
995 MPM.addPass(NameAnonGlobalPass());
998 // Upgrade all calls to old intrinsics first.
999 for (Module::iterator I = TheModule->begin(), E = TheModule->end(); I != E;)
1000 UpgradeCallsToIntrinsic(&*I++); // must be post-increment, as we remove
1002 MPM.run(*TheModule, MAM);
1003 return LLVMRustResult::Success;
1006 // Callback to demangle function name
1008 // * name to be demangled
1011 // * output buffer len
1012 // Returns len of demangled string, or 0 if demangle failed.
1013 typedef size_t (*DemangleFn)(const char*, size_t, char*, size_t);
1018 class RustAssemblyAnnotationWriter : public AssemblyAnnotationWriter {
1019 DemangleFn Demangle;
1020 std::vector<char> Buf;
1023 RustAssemblyAnnotationWriter(DemangleFn Demangle) : Demangle(Demangle) {}
1025 // Return empty string if demangle failed
1026 // or if name does not need to be demangled
1027 StringRef CallDemangle(StringRef name) {
1032 if (Buf.size() < name.size() * 2) {
1033 // Semangled name usually shorter than mangled,
1034 // but allocate twice as much memory just in case
1035 Buf.resize(name.size() * 2);
1038 auto R = Demangle(name.data(), name.size(), Buf.data(), Buf.size());
1044 auto Demangled = StringRef(Buf.data(), R);
1045 if (Demangled == name) {
1046 // Do not print anything if demangled name is equal to mangled.
1053 void emitFunctionAnnot(const Function *F,
1054 formatted_raw_ostream &OS) override {
1055 StringRef Demangled = CallDemangle(F->getName());
1056 if (Demangled.empty()) {
1060 OS << "; " << Demangled << "\n";
1063 void emitInstructionAnnot(const Instruction *I,
1064 formatted_raw_ostream &OS) override {
1067 if (const CallInst *CI = dyn_cast<CallInst>(I)) {
1069 Value = CI->getCalledOperand();
1070 } else if (const InvokeInst* II = dyn_cast<InvokeInst>(I)) {
1072 Value = II->getCalledOperand();
1074 // Could demangle more operations, e. g.
1075 // `store %place, @function`.
1079 if (!Value->hasName()) {
1083 StringRef Demangled = CallDemangle(Value->getName());
1084 if (Demangled.empty()) {
1088 OS << "; " << Name << " " << Demangled << "\n";
1094 extern "C" LLVMRustResult
1095 LLVMRustPrintModule(LLVMModuleRef M, const char *Path, DemangleFn Demangle) {
1096 std::string ErrorInfo;
1098 raw_fd_ostream OS(Path, EC, sys::fs::OF_None);
1100 ErrorInfo = EC.message();
1101 if (ErrorInfo != "") {
1102 LLVMRustSetLastError(ErrorInfo.c_str());
1103 return LLVMRustResult::Failure;
1106 RustAssemblyAnnotationWriter AAW(Demangle);
1107 formatted_raw_ostream FOS(OS);
1108 unwrap(M)->print(FOS, &AAW);
1110 return LLVMRustResult::Success;
1113 extern "C" void LLVMRustPrintPasses() {
1114 LLVMInitializePasses();
1115 struct MyListener : PassRegistrationListener {
1116 void passEnumerate(const PassInfo *Info) {
1117 StringRef PassArg = Info->getPassArgument();
1118 StringRef PassName = Info->getPassName();
1119 if (!PassArg.empty()) {
1120 // These unsigned->signed casts could theoretically overflow, but
1121 // realistically never will (and even if, the result is implementation
1122 // defined rather plain UB).
1123 printf("%15.*s - %.*s\n", (int)PassArg.size(), PassArg.data(),
1124 (int)PassName.size(), PassName.data());
1129 PassRegistry *PR = PassRegistry::getPassRegistry();
1130 PR->enumerateWith(&Listener);
1133 extern "C" void LLVMRustAddAlwaysInlinePass(LLVMPassManagerBuilderRef PMBR,
1134 bool AddLifetimes) {
1135 unwrap(PMBR)->Inliner = llvm::createAlwaysInlinerLegacyPass(AddLifetimes);
1138 extern "C" void LLVMRustRunRestrictionPass(LLVMModuleRef M, char **Symbols,
1140 llvm::legacy::PassManager passes;
1142 auto PreserveFunctions = [=](const GlobalValue &GV) {
1143 for (size_t I = 0; I < Len; I++) {
1144 if (GV.getName() == Symbols[I]) {
1151 passes.add(llvm::createInternalizePass(PreserveFunctions));
1153 passes.run(*unwrap(M));
1156 extern "C" void LLVMRustMarkAllFunctionsNounwind(LLVMModuleRef M) {
1157 for (Module::iterator GV = unwrap(M)->begin(), E = unwrap(M)->end(); GV != E;
1159 GV->setDoesNotThrow();
1160 Function *F = dyn_cast<Function>(GV);
1164 for (Function::iterator B = F->begin(), BE = F->end(); B != BE; ++B) {
1165 for (BasicBlock::iterator I = B->begin(), IE = B->end(); I != IE; ++I) {
1166 if (isa<InvokeInst>(I)) {
1167 InvokeInst *CI = cast<InvokeInst>(I);
1168 CI->setDoesNotThrow();
1176 LLVMRustSetDataLayoutFromTargetMachine(LLVMModuleRef Module,
1177 LLVMTargetMachineRef TMR) {
1178 TargetMachine *Target = unwrap(TMR);
1179 unwrap(Module)->setDataLayout(Target->createDataLayout());
1182 extern "C" void LLVMRustSetModulePICLevel(LLVMModuleRef M) {
1183 unwrap(M)->setPICLevel(PICLevel::Level::BigPIC);
1186 extern "C" void LLVMRustSetModulePIELevel(LLVMModuleRef M) {
1187 unwrap(M)->setPIELevel(PIELevel::Level::Large);
1190 extern "C" void LLVMRustSetModuleCodeModel(LLVMModuleRef M,
1191 LLVMRustCodeModel Model) {
1192 auto CM = fromRust(Model);
1195 unwrap(M)->setCodeModel(*CM);
1198 // Here you'll find an implementation of ThinLTO as used by the Rust compiler
1199 // right now. This ThinLTO support is only enabled on "recent ish" versions of
1200 // LLVM, and otherwise it's just blanket rejected from other compilers.
1202 // Most of this implementation is straight copied from LLVM. At the time of
1203 // this writing it wasn't *quite* suitable to reuse more code from upstream
1204 // for our purposes, but we should strive to upstream this support once it's
1205 // ready to go! I figure we may want a bit of testing locally first before
1206 // sending this upstream to LLVM. I hear though they're quite eager to receive
1207 // feedback like this!
1209 // If you're reading this code and wondering "what in the world" or you're
1210 // working "good lord by LLVM upgrade is *still* failing due to these bindings"
1211 // then fear not! (ok maybe fear a little). All code here is mostly based
1212 // on `lib/LTO/ThinLTOCodeGenerator.cpp` in LLVM.
1214 // You'll find that the general layout here roughly corresponds to the `run`
1215 // method in that file as well as `ProcessThinLTOModule`. Functions are
1216 // specifically commented below as well, but if you're updating this code
1217 // or otherwise trying to understand it, the LLVM source will be useful in
1218 // interpreting the mysteries within.
1220 // Otherwise I'll apologize in advance, it probably requires a relatively
1221 // significant investment on your part to "truly understand" what's going on
1222 // here. Not saying I do myself, but it took me awhile staring at LLVM's source
1223 // and various online resources about ThinLTO to make heads or tails of all
1226 // This is a shared data structure which *must* be threadsafe to share
1227 // read-only amongst threads. This also corresponds basically to the arguments
1228 // of the `ProcessThinLTOModule` function in the LLVM source.
1229 struct LLVMRustThinLTOData {
1230 // The combined index that is the global analysis over all modules we're
1231 // performing ThinLTO for. This is mostly managed by LLVM.
1232 ModuleSummaryIndex Index;
1234 // All modules we may look at, stored as in-memory serialized versions. This
1235 // is later used when inlining to ensure we can extract any module to inline
1237 StringMap<MemoryBufferRef> ModuleMap;
1239 // A set that we manage of everything we *don't* want internalized. Note that
1240 // this includes all transitive references right now as well, but it may not
1242 DenseSet<GlobalValue::GUID> GUIDPreservedSymbols;
1244 // Not 100% sure what these are, but they impact what's internalized and
1245 // what's inlined across modules, I believe.
1246 StringMap<FunctionImporter::ImportMapTy> ImportLists;
1247 StringMap<FunctionImporter::ExportSetTy> ExportLists;
1248 StringMap<GVSummaryMapTy> ModuleToDefinedGVSummaries;
1249 StringMap<std::map<GlobalValue::GUID, GlobalValue::LinkageTypes>> ResolvedODR;
1251 LLVMRustThinLTOData() : Index(/* HaveGVs = */ false) {}
1254 // Just an argument to the `LLVMRustCreateThinLTOData` function below.
1255 struct LLVMRustThinLTOModule {
1256 const char *identifier;
1261 // This is copied from `lib/LTO/ThinLTOCodeGenerator.cpp`, not sure what it
1263 static const GlobalValueSummary *
1264 getFirstDefinitionForLinker(const GlobalValueSummaryList &GVSummaryList) {
1265 auto StrongDefForLinker = llvm::find_if(
1266 GVSummaryList, [](const std::unique_ptr<GlobalValueSummary> &Summary) {
1267 auto Linkage = Summary->linkage();
1268 return !GlobalValue::isAvailableExternallyLinkage(Linkage) &&
1269 !GlobalValue::isWeakForLinker(Linkage);
1271 if (StrongDefForLinker != GVSummaryList.end())
1272 return StrongDefForLinker->get();
1274 auto FirstDefForLinker = llvm::find_if(
1275 GVSummaryList, [](const std::unique_ptr<GlobalValueSummary> &Summary) {
1276 auto Linkage = Summary->linkage();
1277 return !GlobalValue::isAvailableExternallyLinkage(Linkage);
1279 if (FirstDefForLinker == GVSummaryList.end())
1281 return FirstDefForLinker->get();
1284 // The main entry point for creating the global ThinLTO analysis. The structure
1285 // here is basically the same as before threads are spawned in the `run`
1286 // function of `lib/LTO/ThinLTOCodeGenerator.cpp`.
1287 extern "C" LLVMRustThinLTOData*
1288 LLVMRustCreateThinLTOData(LLVMRustThinLTOModule *modules,
1290 const char **preserved_symbols,
1292 auto Ret = std::make_unique<LLVMRustThinLTOData>();
1294 // Load each module's summary and merge it into one combined index
1295 for (int i = 0; i < num_modules; i++) {
1296 auto module = &modules[i];
1297 StringRef buffer(module->data, module->len);
1298 MemoryBufferRef mem_buffer(buffer, module->identifier);
1300 Ret->ModuleMap[module->identifier] = mem_buffer;
1302 if (Error Err = readModuleSummaryIndex(mem_buffer, Ret->Index, i)) {
1303 LLVMRustSetLastError(toString(std::move(Err)).c_str());
1308 // Collect for each module the list of function it defines (GUID -> Summary)
1309 Ret->Index.collectDefinedGVSummariesPerModule(Ret->ModuleToDefinedGVSummaries);
1311 // Convert the preserved symbols set from string to GUID, this is then needed
1312 // for internalization.
1313 for (int i = 0; i < num_symbols; i++) {
1314 auto GUID = GlobalValue::getGUID(preserved_symbols[i]);
1315 Ret->GUIDPreservedSymbols.insert(GUID);
1318 // Collect the import/export lists for all modules from the call-graph in the
1321 // This is copied from `lib/LTO/ThinLTOCodeGenerator.cpp`
1322 auto deadIsPrevailing = [&](GlobalValue::GUID G) {
1323 return PrevailingType::Unknown;
1325 // We don't have a complete picture in our use of ThinLTO, just our immediate
1326 // crate, so we need `ImportEnabled = false` to limit internalization.
1327 // Otherwise, we sometimes lose `static` values -- see #60184.
1328 computeDeadSymbolsWithConstProp(Ret->Index, Ret->GUIDPreservedSymbols,
1329 deadIsPrevailing, /* ImportEnabled = */ false);
1330 ComputeCrossModuleImport(
1332 Ret->ModuleToDefinedGVSummaries,
1337 // Resolve LinkOnce/Weak symbols, this has to be computed early be cause it
1338 // impacts the caching.
1340 // This is copied from `lib/LTO/ThinLTOCodeGenerator.cpp` with some of this
1341 // being lifted from `lib/LTO/LTO.cpp` as well
1342 DenseMap<GlobalValue::GUID, const GlobalValueSummary *> PrevailingCopy;
1343 for (auto &I : Ret->Index) {
1344 if (I.second.SummaryList.size() > 1)
1345 PrevailingCopy[I.first] = getFirstDefinitionForLinker(I.second.SummaryList);
1347 auto isPrevailing = [&](GlobalValue::GUID GUID, const GlobalValueSummary *S) {
1348 const auto &Prevailing = PrevailingCopy.find(GUID);
1349 if (Prevailing == PrevailingCopy.end())
1351 return Prevailing->second == S;
1353 auto recordNewLinkage = [&](StringRef ModuleIdentifier,
1354 GlobalValue::GUID GUID,
1355 GlobalValue::LinkageTypes NewLinkage) {
1356 Ret->ResolvedODR[ModuleIdentifier][GUID] = NewLinkage;
1359 #if LLVM_VERSION_GE(13,0)
1360 // Uses FromPrevailing visibility scheme which works for many binary
1361 // formats. We probably could and should use ELF visibility scheme for many of
1362 // our targets, however.
1364 thinLTOResolvePrevailingInIndex(conf, Ret->Index, isPrevailing, recordNewLinkage,
1365 Ret->GUIDPreservedSymbols);
1367 thinLTOResolvePrevailingInIndex(Ret->Index, isPrevailing, recordNewLinkage,
1368 Ret->GUIDPreservedSymbols);
1370 // Here we calculate an `ExportedGUIDs` set for use in the `isExported`
1371 // callback below. This callback below will dictate the linkage for all
1372 // summaries in the index, and we basically just only want to ensure that dead
1373 // symbols are internalized. Otherwise everything that's already external
1374 // linkage will stay as external, and internal will stay as internal.
1375 std::set<GlobalValue::GUID> ExportedGUIDs;
1376 for (auto &List : Ret->Index) {
1377 for (auto &GVS: List.second.SummaryList) {
1378 if (GlobalValue::isLocalLinkage(GVS->linkage()))
1380 auto GUID = GVS->getOriginalName();
1381 if (GVS->flags().Live)
1382 ExportedGUIDs.insert(GUID);
1385 auto isExported = [&](StringRef ModuleIdentifier, ValueInfo VI) {
1386 const auto &ExportList = Ret->ExportLists.find(ModuleIdentifier);
1387 return (ExportList != Ret->ExportLists.end() &&
1388 ExportList->second.count(VI)) ||
1389 ExportedGUIDs.count(VI.getGUID());
1391 thinLTOInternalizeAndPromoteInIndex(Ret->Index, isExported, isPrevailing);
1393 return Ret.release();
1397 LLVMRustFreeThinLTOData(LLVMRustThinLTOData *Data) {
1401 // Below are the various passes that happen *per module* when doing ThinLTO.
1403 // In other words, these are the functions that are all run concurrently
1404 // with one another, one per module. The passes here correspond to the analysis
1405 // passes in `lib/LTO/ThinLTOCodeGenerator.cpp`, currently found in the
1406 // `ProcessThinLTOModule` function. Here they're split up into separate steps
1407 // so rustc can save off the intermediate bytecode between each step.
1410 clearDSOLocalOnDeclarations(Module &Mod, TargetMachine &TM) {
1411 // When linking an ELF shared object, dso_local should be dropped. We
1412 // conservatively do this for -fpic.
1413 bool ClearDSOLocalOnDeclarations =
1414 TM.getTargetTriple().isOSBinFormatELF() &&
1415 TM.getRelocationModel() != Reloc::Static &&
1416 Mod.getPIELevel() == PIELevel::Default;
1417 return ClearDSOLocalOnDeclarations;
1421 LLVMRustPrepareThinLTORename(const LLVMRustThinLTOData *Data, LLVMModuleRef M,
1422 LLVMTargetMachineRef TM) {
1423 Module &Mod = *unwrap(M);
1424 TargetMachine &Target = *unwrap(TM);
1426 bool ClearDSOLocal = clearDSOLocalOnDeclarations(Mod, Target);
1427 bool error = renameModuleForThinLTO(Mod, Data->Index, ClearDSOLocal);
1430 LLVMRustSetLastError("renameModuleForThinLTO failed");
1437 LLVMRustPrepareThinLTOResolveWeak(const LLVMRustThinLTOData *Data, LLVMModuleRef M) {
1438 Module &Mod = *unwrap(M);
1439 const auto &DefinedGlobals = Data->ModuleToDefinedGVSummaries.lookup(Mod.getModuleIdentifier());
1440 #if LLVM_VERSION_GE(14, 0)
1441 thinLTOFinalizeInModule(Mod, DefinedGlobals, /*PropagateAttrs=*/true);
1443 thinLTOResolvePrevailingInModule(Mod, DefinedGlobals);
1449 LLVMRustPrepareThinLTOInternalize(const LLVMRustThinLTOData *Data, LLVMModuleRef M) {
1450 Module &Mod = *unwrap(M);
1451 const auto &DefinedGlobals = Data->ModuleToDefinedGVSummaries.lookup(Mod.getModuleIdentifier());
1452 thinLTOInternalizeModule(Mod, DefinedGlobals);
1457 LLVMRustPrepareThinLTOImport(const LLVMRustThinLTOData *Data, LLVMModuleRef M,
1458 LLVMTargetMachineRef TM) {
1459 Module &Mod = *unwrap(M);
1460 TargetMachine &Target = *unwrap(TM);
1462 const auto &ImportList = Data->ImportLists.lookup(Mod.getModuleIdentifier());
1463 auto Loader = [&](StringRef Identifier) {
1464 const auto &Memory = Data->ModuleMap.lookup(Identifier);
1465 auto &Context = Mod.getContext();
1466 auto MOrErr = getLazyBitcodeModule(Memory, Context, true, true);
1471 // The rest of this closure is a workaround for
1472 // https://bugs.llvm.org/show_bug.cgi?id=38184 where during ThinLTO imports
1473 // we accidentally import wasm custom sections into different modules,
1474 // duplicating them by in the final output artifact.
1476 // The issue is worked around here by manually removing the
1477 // `wasm.custom_sections` named metadata node from any imported module. This
1478 // we know isn't used by any optimization pass so there's no need for it to
1481 // Note that the metadata is currently lazily loaded, so we materialize it
1482 // here before looking up if there's metadata inside. The `FunctionImporter`
1483 // will immediately materialize metadata anyway after an import, so this
1484 // shouldn't be a perf hit.
1485 if (Error Err = (*MOrErr)->materializeMetadata()) {
1486 Expected<std::unique_ptr<Module>> Ret(std::move(Err));
1490 auto *WasmCustomSections = (*MOrErr)->getNamedMetadata("wasm.custom_sections");
1491 if (WasmCustomSections)
1492 WasmCustomSections->eraseFromParent();
1496 bool ClearDSOLocal = clearDSOLocalOnDeclarations(Mod, Target);
1497 FunctionImporter Importer(Data->Index, Loader, ClearDSOLocal);
1498 Expected<bool> Result = Importer.importFunctions(Mod, ImportList);
1500 LLVMRustSetLastError(toString(Result.takeError()).c_str());
1506 extern "C" typedef void (*LLVMRustModuleNameCallback)(void*, // payload
1507 const char*, // importing module name
1508 const char*); // imported module name
1510 // Calls `module_name_callback` for each module import done by ThinLTO.
1511 // The callback is provided with regular null-terminated C strings.
1513 LLVMRustGetThinLTOModules(const LLVMRustThinLTOData *data,
1514 LLVMRustModuleNameCallback module_name_callback,
1515 void* callback_payload) {
1516 for (const auto& importing_module : data->ImportLists) {
1517 const std::string importing_module_id = importing_module.getKey().str();
1518 const auto& imports = importing_module.getValue();
1519 for (const auto& imported_module : imports) {
1520 const std::string imported_module_id = imported_module.getKey().str();
1521 module_name_callback(callback_payload,
1522 importing_module_id.c_str(),
1523 imported_module_id.c_str());
1528 // This struct and various functions are sort of a hack right now, but the
1529 // problem is that we've got in-memory LLVM modules after we generate and
1530 // optimize all codegen-units for one compilation in rustc. To be compatible
1531 // with the LTO support above we need to serialize the modules plus their
1532 // ThinLTO summary into memory.
1534 // This structure is basically an owned version of a serialize module, with
1535 // a ThinLTO summary attached.
1536 struct LLVMRustThinLTOBuffer {
1540 extern "C" LLVMRustThinLTOBuffer*
1541 LLVMRustThinLTOBufferCreate(LLVMModuleRef M) {
1542 auto Ret = std::make_unique<LLVMRustThinLTOBuffer>();
1544 raw_string_ostream OS(Ret->data);
1546 legacy::PassManager PM;
1547 PM.add(createWriteThinLTOBitcodePass(OS));
1551 return Ret.release();
1555 LLVMRustThinLTOBufferFree(LLVMRustThinLTOBuffer *Buffer) {
1559 extern "C" const void*
1560 LLVMRustThinLTOBufferPtr(const LLVMRustThinLTOBuffer *Buffer) {
1561 return Buffer->data.data();
1565 LLVMRustThinLTOBufferLen(const LLVMRustThinLTOBuffer *Buffer) {
1566 return Buffer->data.length();
1569 // This is what we used to parse upstream bitcode for actual ThinLTO
1570 // processing. We'll call this once per module optimized through ThinLTO, and
1571 // it'll be called concurrently on many threads.
1572 extern "C" LLVMModuleRef
1573 LLVMRustParseBitcodeForLTO(LLVMContextRef Context,
1576 const char *identifier) {
1577 StringRef Data(data, len);
1578 MemoryBufferRef Buffer(Data, identifier);
1579 unwrap(Context)->enableDebugTypeODRUniquing();
1580 Expected<std::unique_ptr<Module>> SrcOrError =
1581 parseBitcodeFile(Buffer, *unwrap(Context));
1583 LLVMRustSetLastError(toString(SrcOrError.takeError()).c_str());
1586 return wrap(std::move(*SrcOrError).release());
1589 // Find the bitcode section in the object file data and return it as a slice.
1590 // Fail if the bitcode section is present but empty.
1592 // On success, the return value is the pointer to the start of the slice and
1593 // `out_len` is filled with the (non-zero) length. On failure, the return value
1594 // is `nullptr` and `out_len` is set to zero.
1595 extern "C" const char*
1596 LLVMRustGetBitcodeSliceFromObjectData(const char *data,
1601 StringRef Data(data, len);
1602 MemoryBufferRef Buffer(Data, ""); // The id is unused.
1604 Expected<MemoryBufferRef> BitcodeOrError =
1605 object::IRObjectFile::findBitcodeInMemBuffer(Buffer);
1606 if (!BitcodeOrError) {
1607 LLVMRustSetLastError(toString(BitcodeOrError.takeError()).c_str());
1611 *out_len = BitcodeOrError->getBufferSize();
1612 return BitcodeOrError->getBufferStart();
1615 // Rewrite all `DICompileUnit` pointers to the `DICompileUnit` specified. See
1616 // the comment in `back/lto.rs` for why this exists.
1618 LLVMRustLTOGetDICompileUnit(LLVMModuleRef Mod,
1620 DICompileUnit **B) {
1621 Module *M = unwrap(Mod);
1622 DICompileUnit **Cur = A;
1623 DICompileUnit **Next = B;
1624 for (DICompileUnit *CU : M->debug_compile_units()) {
1633 // Rewrite all `DICompileUnit` pointers to the `DICompileUnit` specified. See
1634 // the comment in `back/lto.rs` for why this exists.
1636 LLVMRustLTOPatchDICompileUnit(LLVMModuleRef Mod, DICompileUnit *Unit) {
1637 Module *M = unwrap(Mod);
1639 // If the original source module didn't have a `DICompileUnit` then try to
1640 // merge all the existing compile units. If there aren't actually any though
1641 // then there's not much for us to do so return.
1642 if (Unit == nullptr) {
1643 for (DICompileUnit *CU : M->debug_compile_units()) {
1647 if (Unit == nullptr)
1651 // Use LLVM's built-in `DebugInfoFinder` to find a bunch of debuginfo and
1652 // process it recursively. Note that we used to specifically iterate over
1653 // instructions to ensure we feed everything into it, but `processModule`
1654 // started doing this the same way in LLVM 7 (commit d769eb36ab2b8).
1655 DebugInfoFinder Finder;
1656 Finder.processModule(*M);
1658 // After we've found all our debuginfo, rewrite all subprograms to point to
1659 // the same `DICompileUnit`.
1660 for (auto &F : Finder.subprograms()) {
1661 F->replaceUnit(Unit);
1664 // Erase any other references to other `DICompileUnit` instances, the verifier
1665 // will later ensure that we don't actually have any other stale references to
1667 auto *MD = M->getNamedMetadata("llvm.dbg.cu");
1668 MD->clearOperands();
1669 MD->addOperand(Unit);
1672 // Computes the LTO cache key for the provided 'ModId' in the given 'Data',
1673 // storing the result in 'KeyOut'.
1674 // Currently, this cache key is a SHA-1 hash of anything that could affect
1675 // the result of optimizing this module (e.g. module imports, exports, liveness
1676 // of access globals, etc).
1677 // The precise details are determined by LLVM in `computeLTOCacheKey`, which is
1678 // used during the normal linker-plugin incremental thin-LTO process.
1680 LLVMRustComputeLTOCacheKey(RustStringRef KeyOut, const char *ModId, LLVMRustThinLTOData *Data) {
1681 SmallString<40> Key;
1682 llvm::lto::Config conf;
1683 const auto &ImportList = Data->ImportLists.lookup(ModId);
1684 const auto &ExportList = Data->ExportLists.lookup(ModId);
1685 const auto &ResolvedODR = Data->ResolvedODR.lookup(ModId);
1686 const auto &DefinedGlobals = Data->ModuleToDefinedGVSummaries.lookup(ModId);
1687 std::set<GlobalValue::GUID> CfiFunctionDefs;
1688 std::set<GlobalValue::GUID> CfiFunctionDecls;
1690 // Based on the 'InProcessThinBackend' constructor in LLVM
1691 for (auto &Name : Data->Index.cfiFunctionDefs())
1692 CfiFunctionDefs.insert(
1693 GlobalValue::getGUID(GlobalValue::dropLLVMManglingEscape(Name)));
1694 for (auto &Name : Data->Index.cfiFunctionDecls())
1695 CfiFunctionDecls.insert(
1696 GlobalValue::getGUID(GlobalValue::dropLLVMManglingEscape(Name)));
1698 llvm::computeLTOCacheKey(Key, conf, Data->Index, ModId,
1699 ImportList, ExportList, ResolvedODR, DefinedGlobals, CfiFunctionDefs, CfiFunctionDecls
1702 LLVMRustStringWriteImpl(KeyOut, Key.c_str(), Key.size());