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 #include "llvm/Target/TargetMachine.h"
25 #include "llvm/Transforms/IPO/PassManagerBuilder.h"
26 #include "llvm/Transforms/IPO/AlwaysInliner.h"
27 #include "llvm/Transforms/IPO/FunctionImport.h"
28 #include "llvm/Transforms/Utils/FunctionImportUtils.h"
29 #include "llvm/LTO/LTO.h"
30 #include "llvm-c/Transforms/PassManagerBuilder.h"
32 #include "llvm/Transforms/Instrumentation.h"
33 #include "llvm/Transforms/Instrumentation/AddressSanitizer.h"
34 #include "llvm/Support/TimeProfiler.h"
35 #include "llvm/Transforms/Instrumentation/GCOVProfiler.h"
36 #include "llvm/Transforms/Instrumentation/InstrProfiling.h"
37 #include "llvm/Transforms/Instrumentation/ThreadSanitizer.h"
38 #include "llvm/Transforms/Instrumentation/MemorySanitizer.h"
39 #include "llvm/Transforms/Instrumentation/HWAddressSanitizer.h"
40 #include "llvm/Transforms/Utils/CanonicalizeAliases.h"
41 #include "llvm/Transforms/Utils/NameAnonGlobals.h"
45 typedef struct LLVMOpaquePass *LLVMPassRef;
46 typedef struct LLVMOpaqueTargetMachine *LLVMTargetMachineRef;
48 DEFINE_STDCXX_CONVERSION_FUNCTIONS(Pass, LLVMPassRef)
49 DEFINE_STDCXX_CONVERSION_FUNCTIONS(TargetMachine, LLVMTargetMachineRef)
50 #if LLVM_VERSION_LT(11, 0)
51 DEFINE_STDCXX_CONVERSION_FUNCTIONS(PassManagerBuilder,
52 LLVMPassManagerBuilderRef)
55 extern "C" void LLVMInitializePasses() {
56 PassRegistry &Registry = *PassRegistry::getPassRegistry();
57 initializeCore(Registry);
58 initializeCodeGen(Registry);
59 initializeScalarOpts(Registry);
60 initializeVectorization(Registry);
61 initializeIPO(Registry);
62 initializeAnalysis(Registry);
63 initializeTransformUtils(Registry);
64 initializeInstCombine(Registry);
65 initializeInstrumentation(Registry);
66 initializeTarget(Registry);
69 extern "C" void LLVMTimeTraceProfilerInitialize() {
70 timeTraceProfilerInitialize(
71 /* TimeTraceGranularity */ 0,
72 /* ProcName */ "rustc");
75 extern "C" void LLVMTimeTraceProfilerFinish(const char* FileName) {
76 StringRef FN(FileName);
78 raw_fd_ostream OS(FN, EC, sys::fs::CD_CreateAlways);
80 timeTraceProfilerWrite(OS);
81 timeTraceProfilerCleanup();
84 enum class LLVMRustPassKind {
90 static LLVMRustPassKind toRust(PassKind Kind) {
93 return LLVMRustPassKind::Function;
95 return LLVMRustPassKind::Module;
97 return LLVMRustPassKind::Other;
101 extern "C" LLVMPassRef LLVMRustFindAndCreatePass(const char *PassName) {
102 StringRef SR(PassName);
103 PassRegistry *PR = PassRegistry::getPassRegistry();
105 const PassInfo *PI = PR->getPassInfo(SR);
107 return wrap(PI->createPass());
112 extern "C" LLVMPassRef LLVMRustCreateAddressSanitizerFunctionPass(bool Recover) {
113 const bool CompileKernel = false;
114 const bool UseAfterScope = true;
116 return wrap(createAddressSanitizerFunctionPass(CompileKernel, Recover, UseAfterScope));
119 extern "C" LLVMPassRef LLVMRustCreateModuleAddressSanitizerPass(bool Recover) {
120 const bool CompileKernel = false;
122 return wrap(createModuleAddressSanitizerLegacyPassPass(CompileKernel, Recover));
125 extern "C" LLVMPassRef LLVMRustCreateMemorySanitizerPass(int TrackOrigins, bool Recover) {
126 const bool CompileKernel = false;
128 return wrap(createMemorySanitizerLegacyPassPass(
129 MemorySanitizerOptions{TrackOrigins, Recover, CompileKernel}));
132 extern "C" LLVMPassRef LLVMRustCreateThreadSanitizerPass() {
133 return wrap(createThreadSanitizerLegacyPassPass());
136 extern "C" LLVMPassRef LLVMRustCreateHWAddressSanitizerPass(bool Recover) {
137 const bool CompileKernel = false;
139 return wrap(createHWAddressSanitizerLegacyPassPass(CompileKernel, Recover));
142 extern "C" LLVMRustPassKind LLVMRustPassKind(LLVMPassRef RustPass) {
144 Pass *Pass = unwrap(RustPass);
145 return toRust(Pass->getPassKind());
148 extern "C" void LLVMRustAddPass(LLVMPassManagerRef PMR, LLVMPassRef RustPass) {
150 Pass *Pass = unwrap(RustPass);
151 PassManagerBase *PMB = unwrap(PMR);
156 void LLVMRustPassManagerBuilderPopulateThinLTOPassManager(
157 LLVMPassManagerBuilderRef PMBR,
158 LLVMPassManagerRef PMR
160 unwrap(PMBR)->populateThinLTOPassManager(*unwrap(PMR));
164 void LLVMRustAddLastExtensionPasses(
165 LLVMPassManagerBuilderRef PMBR, LLVMPassRef *Passes, size_t NumPasses) {
166 auto AddExtensionPasses = [Passes, NumPasses](
167 const PassManagerBuilder &Builder, PassManagerBase &PM) {
168 for (size_t I = 0; I < NumPasses; I++) {
169 PM.add(unwrap(Passes[I]));
172 // Add the passes to both of the pre-finalization extension points,
173 // so they are run for optimized and non-optimized builds.
174 unwrap(PMBR)->addExtension(PassManagerBuilder::EP_OptimizerLast,
176 unwrap(PMBR)->addExtension(PassManagerBuilder::EP_EnabledOnOptLevel0,
180 #ifdef LLVM_COMPONENT_X86
181 #define SUBTARGET_X86 SUBTARGET(X86)
183 #define SUBTARGET_X86
186 #ifdef LLVM_COMPONENT_ARM
187 #define SUBTARGET_ARM SUBTARGET(ARM)
189 #define SUBTARGET_ARM
192 #ifdef LLVM_COMPONENT_AARCH64
193 #define SUBTARGET_AARCH64 SUBTARGET(AArch64)
195 #define SUBTARGET_AARCH64
198 #ifdef LLVM_COMPONENT_AVR
199 #define SUBTARGET_AVR SUBTARGET(AVR)
201 #define SUBTARGET_AVR
204 #ifdef LLVM_COMPONENT_M68k
205 #define SUBTARGET_M68K SUBTARGET(M68k)
207 #define SUBTARGET_M68K
210 #ifdef LLVM_COMPONENT_MIPS
211 #define SUBTARGET_MIPS SUBTARGET(Mips)
213 #define SUBTARGET_MIPS
216 #ifdef LLVM_COMPONENT_POWERPC
217 #define SUBTARGET_PPC SUBTARGET(PPC)
219 #define SUBTARGET_PPC
222 #ifdef LLVM_COMPONENT_SYSTEMZ
223 #define SUBTARGET_SYSTEMZ SUBTARGET(SystemZ)
225 #define SUBTARGET_SYSTEMZ
228 #ifdef LLVM_COMPONENT_MSP430
229 #define SUBTARGET_MSP430 SUBTARGET(MSP430)
231 #define SUBTARGET_MSP430
234 #ifdef LLVM_COMPONENT_RISCV
235 #define SUBTARGET_RISCV SUBTARGET(RISCV)
237 #define SUBTARGET_RISCV
240 #ifdef LLVM_COMPONENT_SPARC
241 #define SUBTARGET_SPARC SUBTARGET(Sparc)
243 #define SUBTARGET_SPARC
246 #ifdef LLVM_COMPONENT_HEXAGON
247 #define SUBTARGET_HEXAGON SUBTARGET(Hexagon)
249 #define SUBTARGET_HEXAGON
252 #define GEN_SUBTARGETS \
266 #define SUBTARGET(x) \
268 extern const SubtargetFeatureKV x##FeatureKV[]; \
269 extern const SubtargetFeatureKV x##SubTypeKV[]; \
275 extern "C" bool LLVMRustHasFeature(LLVMTargetMachineRef TM,
276 const char *Feature) {
277 TargetMachine *Target = unwrap(TM);
278 const MCSubtargetInfo *MCInfo = Target->getMCSubtargetInfo();
279 return MCInfo->checkFeatures(std::string("+") + Feature);
282 enum class LLVMRustCodeModel {
291 static Optional<CodeModel::Model> fromRust(LLVMRustCodeModel Model) {
293 case LLVMRustCodeModel::Tiny:
294 return CodeModel::Tiny;
295 case LLVMRustCodeModel::Small:
296 return CodeModel::Small;
297 case LLVMRustCodeModel::Kernel:
298 return CodeModel::Kernel;
299 case LLVMRustCodeModel::Medium:
300 return CodeModel::Medium;
301 case LLVMRustCodeModel::Large:
302 return CodeModel::Large;
303 case LLVMRustCodeModel::None:
306 report_fatal_error("Bad CodeModel.");
310 enum class LLVMRustCodeGenOptLevel {
317 static CodeGenOpt::Level fromRust(LLVMRustCodeGenOptLevel Level) {
319 case LLVMRustCodeGenOptLevel::None:
320 return CodeGenOpt::None;
321 case LLVMRustCodeGenOptLevel::Less:
322 return CodeGenOpt::Less;
323 case LLVMRustCodeGenOptLevel::Default:
324 return CodeGenOpt::Default;
325 case LLVMRustCodeGenOptLevel::Aggressive:
326 return CodeGenOpt::Aggressive;
328 report_fatal_error("Bad CodeGenOptLevel.");
332 enum class LLVMRustPassBuilderOptLevel {
341 #if LLVM_VERSION_LT(14,0)
342 using OptimizationLevel = PassBuilder::OptimizationLevel;
345 static OptimizationLevel fromRust(LLVMRustPassBuilderOptLevel Level) {
347 case LLVMRustPassBuilderOptLevel::O0:
348 return OptimizationLevel::O0;
349 case LLVMRustPassBuilderOptLevel::O1:
350 return OptimizationLevel::O1;
351 case LLVMRustPassBuilderOptLevel::O2:
352 return OptimizationLevel::O2;
353 case LLVMRustPassBuilderOptLevel::O3:
354 return OptimizationLevel::O3;
355 case LLVMRustPassBuilderOptLevel::Os:
356 return OptimizationLevel::Os;
357 case LLVMRustPassBuilderOptLevel::Oz:
358 return OptimizationLevel::Oz;
360 report_fatal_error("Bad PassBuilderOptLevel.");
364 enum class LLVMRustRelocModel {
373 static Reloc::Model fromRust(LLVMRustRelocModel RustReloc) {
375 case LLVMRustRelocModel::Static:
376 return Reloc::Static;
377 case LLVMRustRelocModel::PIC:
379 case LLVMRustRelocModel::DynamicNoPic:
380 return Reloc::DynamicNoPIC;
381 case LLVMRustRelocModel::ROPI:
383 case LLVMRustRelocModel::RWPI:
385 case LLVMRustRelocModel::ROPIRWPI:
386 return Reloc::ROPI_RWPI;
388 report_fatal_error("Bad RelocModel.");
392 /// getLongestEntryLength - Return the length of the longest entry in the table.
393 template<typename KV>
394 static size_t getLongestEntryLength(ArrayRef<KV> Table) {
396 for (auto &I : Table)
397 MaxLen = std::max(MaxLen, std::strlen(I.Key));
401 extern "C" void LLVMRustPrintTargetCPUs(LLVMTargetMachineRef TM) {
402 const TargetMachine *Target = unwrap(TM);
403 const MCSubtargetInfo *MCInfo = Target->getMCSubtargetInfo();
404 const Triple::ArchType HostArch = Triple(sys::getProcessTriple()).getArch();
405 const Triple::ArchType TargetArch = Target->getTargetTriple().getArch();
406 const ArrayRef<SubtargetSubTypeKV> CPUTable = MCInfo->getCPUTable();
407 unsigned MaxCPULen = getLongestEntryLength(CPUTable);
409 printf("Available CPUs for this target:\n");
410 if (HostArch == TargetArch) {
411 const StringRef HostCPU = sys::getHostCPUName();
412 printf(" %-*s - Select the CPU of the current host (currently %.*s).\n",
413 MaxCPULen, "native", (int)HostCPU.size(), HostCPU.data());
415 for (auto &CPU : CPUTable)
416 printf(" %-*s\n", MaxCPULen, CPU.Key);
420 extern "C" size_t LLVMRustGetTargetFeaturesCount(LLVMTargetMachineRef TM) {
421 const TargetMachine *Target = unwrap(TM);
422 const MCSubtargetInfo *MCInfo = Target->getMCSubtargetInfo();
423 const ArrayRef<SubtargetFeatureKV> FeatTable = MCInfo->getFeatureTable();
424 return FeatTable.size();
427 extern "C" void LLVMRustGetTargetFeature(LLVMTargetMachineRef TM, size_t Index,
428 const char** Feature, const char** Desc) {
429 const TargetMachine *Target = unwrap(TM);
430 const MCSubtargetInfo *MCInfo = Target->getMCSubtargetInfo();
431 const ArrayRef<SubtargetFeatureKV> FeatTable = MCInfo->getFeatureTable();
432 const SubtargetFeatureKV Feat = FeatTable[Index];
439 extern "C" void LLVMRustPrintTargetCPUs(LLVMTargetMachineRef) {
440 printf("Target CPU help is not supported by this LLVM version.\n\n");
443 extern "C" size_t LLVMRustGetTargetFeaturesCount(LLVMTargetMachineRef) {
447 extern "C" void LLVMRustGetTargetFeature(LLVMTargetMachineRef, const char**, const char**) {}
450 extern "C" const char* LLVMRustGetHostCPUName(size_t *len) {
451 StringRef Name = sys::getHostCPUName();
456 extern "C" LLVMTargetMachineRef LLVMRustCreateTargetMachine(
457 const char *TripleStr, const char *CPU, const char *Feature,
458 const char *ABIStr, LLVMRustCodeModel RustCM, LLVMRustRelocModel RustReloc,
459 LLVMRustCodeGenOptLevel RustOptLevel, bool UseSoftFloat,
460 bool FunctionSections,
462 bool TrapUnreachable,
465 bool EmitStackSizeSection,
466 bool RelaxELFRelocations,
468 const char *SplitDwarfFile) {
470 auto OptLevel = fromRust(RustOptLevel);
471 auto RM = fromRust(RustReloc);
472 auto CM = fromRust(RustCM);
475 Triple Trip(Triple::normalize(TripleStr));
476 const llvm::Target *TheTarget =
477 TargetRegistry::lookupTarget(Trip.getTriple(), Error);
478 if (TheTarget == nullptr) {
479 LLVMRustSetLastError(Error.c_str());
483 TargetOptions Options;
485 Options.FloatABIType = FloatABI::Default;
487 Options.FloatABIType = FloatABI::Soft;
489 Options.DataSections = DataSections;
490 Options.FunctionSections = FunctionSections;
491 Options.MCOptions.AsmVerbose = AsmComments;
492 Options.MCOptions.PreserveAsmComments = AsmComments;
493 Options.MCOptions.ABIName = ABIStr;
494 if (SplitDwarfFile) {
495 Options.MCOptions.SplitDwarfFile = SplitDwarfFile;
497 Options.RelaxELFRelocations = RelaxELFRelocations;
498 Options.UseInitArray = UseInitArray;
500 if (TrapUnreachable) {
501 // Tell LLVM to codegen `unreachable` into an explicit trap instruction.
502 // This limits the extent of possible undefined behavior in some cases, as
503 // it prevents control flow from "falling through" into whatever code
504 // happens to be laid out next in memory.
505 Options.TrapUnreachable = true;
509 Options.ThreadModel = ThreadModel::Single;
512 Options.EmitStackSizeSection = EmitStackSizeSection;
514 TargetMachine *TM = TheTarget->createTargetMachine(
515 Trip.getTriple(), CPU, Feature, Options, RM, CM, OptLevel);
519 extern "C" void LLVMRustDisposeTargetMachine(LLVMTargetMachineRef TM) {
523 extern "C" void LLVMRustConfigurePassManagerBuilder(
524 LLVMPassManagerBuilderRef PMBR, LLVMRustCodeGenOptLevel OptLevel,
525 bool MergeFunctions, bool SLPVectorize, bool LoopVectorize, bool PrepareForThinLTO,
526 const char* PGOGenPath, const char* PGOUsePath) {
527 unwrap(PMBR)->MergeFunctions = MergeFunctions;
528 unwrap(PMBR)->SLPVectorize = SLPVectorize;
529 unwrap(PMBR)->OptLevel = fromRust(OptLevel);
530 unwrap(PMBR)->LoopVectorize = LoopVectorize;
531 unwrap(PMBR)->PrepareForThinLTO = PrepareForThinLTO;
535 unwrap(PMBR)->EnablePGOInstrGen = true;
536 unwrap(PMBR)->PGOInstrGen = PGOGenPath;
540 unwrap(PMBR)->PGOInstrUse = PGOUsePath;
544 // Unfortunately, the LLVM C API doesn't provide a way to set the `LibraryInfo`
545 // field of a PassManagerBuilder, we expose our own method of doing so.
546 extern "C" void LLVMRustAddBuilderLibraryInfo(LLVMPassManagerBuilderRef PMBR,
548 bool DisableSimplifyLibCalls) {
549 Triple TargetTriple(unwrap(M)->getTargetTriple());
550 TargetLibraryInfoImpl *TLI = new TargetLibraryInfoImpl(TargetTriple);
551 if (DisableSimplifyLibCalls)
552 TLI->disableAllFunctions();
553 unwrap(PMBR)->LibraryInfo = TLI;
556 // Unfortunately, the LLVM C API doesn't provide a way to create the
557 // TargetLibraryInfo pass, so we use this method to do so.
558 extern "C" void LLVMRustAddLibraryInfo(LLVMPassManagerRef PMR, LLVMModuleRef M,
559 bool DisableSimplifyLibCalls) {
560 Triple TargetTriple(unwrap(M)->getTargetTriple());
561 TargetLibraryInfoImpl TLII(TargetTriple);
562 if (DisableSimplifyLibCalls)
563 TLII.disableAllFunctions();
564 unwrap(PMR)->add(new TargetLibraryInfoWrapperPass(TLII));
567 // Unfortunately, the LLVM C API doesn't provide an easy way of iterating over
568 // all the functions in a module, so we do that manually here. You'll find
569 // similar code in clang's BackendUtil.cpp file.
570 extern "C" void LLVMRustRunFunctionPassManager(LLVMPassManagerRef PMR,
572 llvm::legacy::FunctionPassManager *P =
573 unwrap<llvm::legacy::FunctionPassManager>(PMR);
574 P->doInitialization();
576 // Upgrade all calls to old intrinsics first.
577 for (Module::iterator I = unwrap(M)->begin(), E = unwrap(M)->end(); I != E;)
578 UpgradeCallsToIntrinsic(&*I++); // must be post-increment, as we remove
580 for (Module::iterator I = unwrap(M)->begin(), E = unwrap(M)->end(); I != E;
582 if (!I->isDeclaration())
588 extern "C" void LLVMRustSetLLVMOptions(int Argc, char **Argv) {
589 // Initializing the command-line options more than once is not allowed. So,
590 // check if they've already been initialized. (This could happen if we're
591 // being called from rustpkg, for example). If the arguments change, then
592 // that's just kinda unfortunate.
593 static bool Initialized = false;
597 cl::ParseCommandLineOptions(Argc, Argv);
600 enum class LLVMRustFileType {
605 static CodeGenFileType fromRust(LLVMRustFileType Type) {
607 case LLVMRustFileType::AssemblyFile:
608 return CGFT_AssemblyFile;
609 case LLVMRustFileType::ObjectFile:
610 return CGFT_ObjectFile;
612 report_fatal_error("Bad FileType.");
616 extern "C" LLVMRustResult
617 LLVMRustWriteOutputFile(LLVMTargetMachineRef Target, LLVMPassManagerRef PMR,
618 LLVMModuleRef M, const char *Path, const char *DwoPath,
619 LLVMRustFileType RustFileType) {
620 llvm::legacy::PassManager *PM = unwrap<llvm::legacy::PassManager>(PMR);
621 auto FileType = fromRust(RustFileType);
623 std::string ErrorInfo;
625 raw_fd_ostream OS(Path, EC, sys::fs::OF_None);
627 ErrorInfo = EC.message();
628 if (ErrorInfo != "") {
629 LLVMRustSetLastError(ErrorInfo.c_str());
630 return LLVMRustResult::Failure;
633 buffer_ostream BOS(OS);
635 raw_fd_ostream DOS(DwoPath, EC, sys::fs::OF_None);
638 ErrorInfo = EC.message();
639 if (ErrorInfo != "") {
640 LLVMRustSetLastError(ErrorInfo.c_str());
641 return LLVMRustResult::Failure;
643 buffer_ostream DBOS(DOS);
644 unwrap(Target)->addPassesToEmitFile(*PM, BOS, &DBOS, FileType, false);
647 unwrap(Target)->addPassesToEmitFile(*PM, BOS, nullptr, FileType, false);
651 // Apparently `addPassesToEmitFile` adds a pointer to our on-the-stack output
652 // stream (OS), so the only real safe place to delete this is here? Don't we
653 // wish this was written in Rust?
654 LLVMDisposePassManager(PMR);
655 return LLVMRustResult::Success;
658 extern "C" typedef void (*LLVMRustSelfProfileBeforePassCallback)(void*, // LlvmSelfProfiler
659 const char*, // pass name
660 const char*); // IR name
661 extern "C" typedef void (*LLVMRustSelfProfileAfterPassCallback)(void*); // LlvmSelfProfiler
663 std::string LLVMRustwrappedIrGetName(const llvm::Any &WrappedIr) {
664 if (any_isa<const Module *>(WrappedIr))
665 return any_cast<const Module *>(WrappedIr)->getName().str();
666 if (any_isa<const Function *>(WrappedIr))
667 return any_cast<const Function *>(WrappedIr)->getName().str();
668 if (any_isa<const Loop *>(WrappedIr))
669 return any_cast<const Loop *>(WrappedIr)->getName().str();
670 if (any_isa<const LazyCallGraph::SCC *>(WrappedIr))
671 return any_cast<const LazyCallGraph::SCC *>(WrappedIr)->getName();
676 void LLVMSelfProfileInitializeCallbacks(
677 PassInstrumentationCallbacks& PIC, void* LlvmSelfProfiler,
678 LLVMRustSelfProfileBeforePassCallback BeforePassCallback,
679 LLVMRustSelfProfileAfterPassCallback AfterPassCallback) {
680 #if LLVM_VERSION_GE(12, 0)
681 PIC.registerBeforeNonSkippedPassCallback([LlvmSelfProfiler, BeforePassCallback](
682 StringRef Pass, llvm::Any Ir) {
683 std::string PassName = Pass.str();
684 std::string IrName = LLVMRustwrappedIrGetName(Ir);
685 BeforePassCallback(LlvmSelfProfiler, PassName.c_str(), IrName.c_str());
688 PIC.registerAfterPassCallback(
689 [LlvmSelfProfiler, AfterPassCallback](StringRef Pass, llvm::Any IR,
690 const PreservedAnalyses &Preserved) {
691 AfterPassCallback(LlvmSelfProfiler);
694 PIC.registerAfterPassInvalidatedCallback(
695 [LlvmSelfProfiler, AfterPassCallback](StringRef Pass, const PreservedAnalyses &Preserved) {
696 AfterPassCallback(LlvmSelfProfiler);
699 PIC.registerBeforePassCallback([LlvmSelfProfiler, BeforePassCallback](
700 StringRef Pass, llvm::Any Ir) {
701 std::string PassName = Pass.str();
702 std::string IrName = LLVMRustwrappedIrGetName(Ir);
703 BeforePassCallback(LlvmSelfProfiler, PassName.c_str(), IrName.c_str());
707 PIC.registerAfterPassCallback(
708 [LlvmSelfProfiler, AfterPassCallback](StringRef Pass, llvm::Any Ir) {
709 AfterPassCallback(LlvmSelfProfiler);
712 PIC.registerAfterPassInvalidatedCallback(
713 [LlvmSelfProfiler, AfterPassCallback](StringRef Pass) {
714 AfterPassCallback(LlvmSelfProfiler);
718 PIC.registerBeforeAnalysisCallback([LlvmSelfProfiler, BeforePassCallback](
719 StringRef Pass, llvm::Any Ir) {
720 std::string PassName = Pass.str();
721 std::string IrName = LLVMRustwrappedIrGetName(Ir);
722 BeforePassCallback(LlvmSelfProfiler, PassName.c_str(), IrName.c_str());
725 PIC.registerAfterAnalysisCallback(
726 [LlvmSelfProfiler, AfterPassCallback](StringRef Pass, llvm::Any Ir) {
727 AfterPassCallback(LlvmSelfProfiler);
731 enum class LLVMRustOptStage {
739 struct LLVMRustSanitizerOptions {
740 bool SanitizeAddress;
741 bool SanitizeAddressRecover;
743 bool SanitizeMemoryRecover;
744 int SanitizeMemoryTrackOrigins;
746 bool SanitizeHWAddress;
747 bool SanitizeHWAddressRecover;
750 extern "C" LLVMRustResult
751 LLVMRustOptimizeWithNewPassManager(
752 LLVMModuleRef ModuleRef,
753 LLVMTargetMachineRef TMRef,
754 LLVMRustPassBuilderOptLevel OptLevelRust,
755 LLVMRustOptStage OptStage,
756 bool NoPrepopulatePasses, bool VerifyIR, bool UseThinLTOBuffers,
757 bool MergeFunctions, bool UnrollLoops, bool SLPVectorize, bool LoopVectorize,
758 bool DisableSimplifyLibCalls, bool EmitLifetimeMarkers,
759 LLVMRustSanitizerOptions *SanitizerOptions,
760 const char *PGOGenPath, const char *PGOUsePath,
761 bool InstrumentCoverage, bool InstrumentGCOV,
762 void* LlvmSelfProfiler,
763 LLVMRustSelfProfileBeforePassCallback BeforePassCallback,
764 LLVMRustSelfProfileAfterPassCallback AfterPassCallback,
765 const char *ExtraPasses, size_t ExtraPassesLen) {
766 Module *TheModule = unwrap(ModuleRef);
767 TargetMachine *TM = unwrap(TMRef);
768 OptimizationLevel OptLevel = fromRust(OptLevelRust);
771 PipelineTuningOptions PTO;
772 PTO.LoopUnrolling = UnrollLoops;
773 PTO.LoopInterleaving = UnrollLoops;
774 PTO.LoopVectorization = LoopVectorize;
775 PTO.SLPVectorization = SLPVectorize;
776 #if LLVM_VERSION_GE(12, 0)
777 PTO.MergeFunctions = MergeFunctions;
779 // MergeFunctions is not supported by NewPM in older LLVM versions.
780 (void) MergeFunctions;
783 // FIXME: We may want to expose this as an option.
784 bool DebugPassManager = false;
786 PassInstrumentationCallbacks PIC;
787 #if LLVM_VERSION_GE(12, 0)
788 StandardInstrumentations SI(DebugPassManager);
790 StandardInstrumentations SI;
792 SI.registerCallbacks(PIC);
794 if (LlvmSelfProfiler){
795 LLVMSelfProfileInitializeCallbacks(PIC,LlvmSelfProfiler,BeforePassCallback,AfterPassCallback);
798 Optional<PGOOptions> PGOOpt;
801 PGOOpt = PGOOptions(PGOGenPath, "", "", PGOOptions::IRInstr);
802 } else if (PGOUsePath) {
804 PGOOpt = PGOOptions(PGOUsePath, "", "", PGOOptions::IRUse);
807 #if LLVM_VERSION_GE(12, 0) && !LLVM_VERSION_GE(13,0)
808 PassBuilder PB(DebugPassManager, TM, PTO, PGOOpt, &PIC);
810 PassBuilder PB(TM, PTO, PGOOpt, &PIC);
813 #if LLVM_VERSION_GE(13, 0)
814 LoopAnalysisManager LAM;
815 FunctionAnalysisManager FAM;
816 CGSCCAnalysisManager CGAM;
817 ModuleAnalysisManager MAM;
819 LoopAnalysisManager LAM(DebugPassManager);
820 FunctionAnalysisManager FAM(DebugPassManager);
821 CGSCCAnalysisManager CGAM(DebugPassManager);
822 ModuleAnalysisManager MAM(DebugPassManager);
825 FAM.registerPass([&] { return PB.buildDefaultAAPipeline(); });
827 Triple TargetTriple(TheModule->getTargetTriple());
828 std::unique_ptr<TargetLibraryInfoImpl> TLII(new TargetLibraryInfoImpl(TargetTriple));
829 if (DisableSimplifyLibCalls)
830 TLII->disableAllFunctions();
831 FAM.registerPass([&] { return TargetLibraryAnalysis(*TLII); });
833 PB.registerModuleAnalyses(MAM);
834 PB.registerCGSCCAnalyses(CGAM);
835 PB.registerFunctionAnalyses(FAM);
836 PB.registerLoopAnalyses(LAM);
837 PB.crossRegisterProxies(LAM, FAM, CGAM, MAM);
839 // We manually collect pipeline callbacks so we can apply them at O0, where the
840 // PassBuilder does not create a pipeline.
841 std::vector<std::function<void(ModulePassManager &, OptimizationLevel)>>
842 PipelineStartEPCallbacks;
843 #if LLVM_VERSION_GE(11, 0)
844 std::vector<std::function<void(ModulePassManager &, OptimizationLevel)>>
845 OptimizerLastEPCallbacks;
847 std::vector<std::function<void(FunctionPassManager &, OptimizationLevel)>>
848 OptimizerLastEPCallbacks;
852 PipelineStartEPCallbacks.push_back(
853 [VerifyIR](ModulePassManager &MPM, OptimizationLevel Level) {
854 MPM.addPass(VerifierPass());
859 if (InstrumentGCOV) {
860 PipelineStartEPCallbacks.push_back(
861 [](ModulePassManager &MPM, OptimizationLevel Level) {
862 MPM.addPass(GCOVProfilerPass(GCOVOptions::getDefault()));
867 if (InstrumentCoverage) {
868 PipelineStartEPCallbacks.push_back(
869 [](ModulePassManager &MPM, OptimizationLevel Level) {
870 InstrProfOptions Options;
871 MPM.addPass(InstrProfiling(Options, false));
876 if (SanitizerOptions) {
877 if (SanitizerOptions->SanitizeMemory) {
878 MemorySanitizerOptions Options(
879 SanitizerOptions->SanitizeMemoryTrackOrigins,
880 SanitizerOptions->SanitizeMemoryRecover,
881 /*CompileKernel=*/false);
882 #if LLVM_VERSION_GE(11, 0)
883 OptimizerLastEPCallbacks.push_back(
884 [Options](ModulePassManager &MPM, OptimizationLevel Level) {
885 #if LLVM_VERSION_GE(14, 0)
886 MPM.addPass(ModuleMemorySanitizerPass(Options));
888 MPM.addPass(MemorySanitizerPass(Options));
890 MPM.addPass(createModuleToFunctionPassAdaptor(MemorySanitizerPass(Options)));
894 PipelineStartEPCallbacks.push_back(
895 [Options](ModulePassManager &MPM, OptimizationLevel Level) {
896 MPM.addPass(MemorySanitizerPass(Options));
899 OptimizerLastEPCallbacks.push_back(
900 [Options](FunctionPassManager &FPM, OptimizationLevel Level) {
901 FPM.addPass(MemorySanitizerPass(Options));
907 if (SanitizerOptions->SanitizeThread) {
908 #if LLVM_VERSION_GE(11, 0)
909 OptimizerLastEPCallbacks.push_back(
910 [](ModulePassManager &MPM, OptimizationLevel Level) {
911 #if LLVM_VERSION_GE(14, 0)
912 MPM.addPass(ModuleThreadSanitizerPass());
914 MPM.addPass(ThreadSanitizerPass());
916 MPM.addPass(createModuleToFunctionPassAdaptor(ThreadSanitizerPass()));
920 PipelineStartEPCallbacks.push_back(
921 [](ModulePassManager &MPM, OptimizationLevel Level) {
922 MPM.addPass(ThreadSanitizerPass());
925 OptimizerLastEPCallbacks.push_back(
926 [](FunctionPassManager &FPM, OptimizationLevel Level) {
927 FPM.addPass(ThreadSanitizerPass());
933 if (SanitizerOptions->SanitizeAddress) {
934 #if LLVM_VERSION_GE(11, 0)
935 OptimizerLastEPCallbacks.push_back(
936 [SanitizerOptions](ModulePassManager &MPM, OptimizationLevel Level) {
937 MPM.addPass(RequireAnalysisPass<ASanGlobalsMetadataAnalysis, Module>());
938 MPM.addPass(ModuleAddressSanitizerPass(
939 /*CompileKernel=*/false, SanitizerOptions->SanitizeAddressRecover));
940 #if LLVM_VERSION_GE(14, 0)
941 AddressSanitizerOptions opts(/*CompileKernel=*/false,
942 SanitizerOptions->SanitizeAddressRecover,
943 /*UseAfterScope=*/true,
944 AsanDetectStackUseAfterReturnMode::Runtime);
945 MPM.addPass(createModuleToFunctionPassAdaptor(AddressSanitizerPass(opts)));
947 MPM.addPass(createModuleToFunctionPassAdaptor(AddressSanitizerPass(
948 /*CompileKernel=*/false, SanitizerOptions->SanitizeAddressRecover,
949 /*UseAfterScope=*/true)));
954 PipelineStartEPCallbacks.push_back(
955 [&](ModulePassManager &MPM, OptimizationLevel Level) {
956 MPM.addPass(RequireAnalysisPass<ASanGlobalsMetadataAnalysis, Module>());
959 OptimizerLastEPCallbacks.push_back(
960 [SanitizerOptions](FunctionPassManager &FPM, OptimizationLevel Level) {
961 FPM.addPass(AddressSanitizerPass(
962 /*CompileKernel=*/false, SanitizerOptions->SanitizeAddressRecover,
963 /*UseAfterScope=*/true));
966 PipelineStartEPCallbacks.push_back(
967 [SanitizerOptions](ModulePassManager &MPM, OptimizationLevel Level) {
968 MPM.addPass(ModuleAddressSanitizerPass(
969 /*CompileKernel=*/false, SanitizerOptions->SanitizeAddressRecover));
974 if (SanitizerOptions->SanitizeHWAddress) {
975 #if LLVM_VERSION_GE(11, 0)
976 OptimizerLastEPCallbacks.push_back(
977 [SanitizerOptions](ModulePassManager &MPM, OptimizationLevel Level) {
978 #if LLVM_VERSION_GE(14, 0)
979 HWAddressSanitizerOptions opts(
980 /*CompileKernel=*/false, SanitizerOptions->SanitizeHWAddressRecover,
981 /*DisableOptimization=*/false);
982 MPM.addPass(HWAddressSanitizerPass(opts));
984 MPM.addPass(HWAddressSanitizerPass(
985 /*CompileKernel=*/false, SanitizerOptions->SanitizeHWAddressRecover));
990 PipelineStartEPCallbacks.push_back(
991 [SanitizerOptions](ModulePassManager &MPM, OptimizationLevel Level) {
992 MPM.addPass(HWAddressSanitizerPass(
993 /*CompileKernel=*/false, SanitizerOptions->SanitizeHWAddressRecover));
1000 #if LLVM_VERSION_GE(13, 0)
1001 ModulePassManager MPM;
1003 ModulePassManager MPM(DebugPassManager);
1005 bool NeedThinLTOBufferPasses = UseThinLTOBuffers;
1006 if (!NoPrepopulatePasses) {
1007 // The pre-link pipelines don't support O0 and require using budilO0DefaultPipeline() instead.
1008 // At the same time, the LTO pipelines do support O0 and using them is required.
1009 bool IsLTO = OptStage == LLVMRustOptStage::ThinLTO || OptStage == LLVMRustOptStage::FatLTO;
1010 if (OptLevel == OptimizationLevel::O0 && !IsLTO) {
1011 #if LLVM_VERSION_GE(12, 0)
1012 for (const auto &C : PipelineStartEPCallbacks)
1013 PB.registerPipelineStartEPCallback(C);
1014 for (const auto &C : OptimizerLastEPCallbacks)
1015 PB.registerOptimizerLastEPCallback(C);
1017 // Pass false as we manually schedule ThinLTOBufferPasses below.
1018 MPM = PB.buildO0DefaultPipeline(OptLevel, /* PreLinkLTO */ false);
1020 for (const auto &C : PipelineStartEPCallbacks)
1023 # if LLVM_VERSION_GE(11, 0)
1024 for (const auto &C : OptimizerLastEPCallbacks)
1027 if (!OptimizerLastEPCallbacks.empty()) {
1028 FunctionPassManager FPM(DebugPassManager);
1029 for (const auto &C : OptimizerLastEPCallbacks)
1031 MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
1035 MPM.addPass(AlwaysInlinerPass(EmitLifetimeMarkers));
1038 PB.addPGOInstrPassesForO0(
1039 MPM, DebugPassManager, PGOOpt->Action == PGOOptions::IRInstr,
1040 /*IsCS=*/false, PGOOpt->ProfileFile, PGOOpt->ProfileRemappingFile);
1044 #if LLVM_VERSION_GE(12, 0)
1045 for (const auto &C : PipelineStartEPCallbacks)
1046 PB.registerPipelineStartEPCallback(C);
1048 for (const auto &C : PipelineStartEPCallbacks)
1049 PB.registerPipelineStartEPCallback([C, OptLevel](ModulePassManager &MPM) {
1053 if (OptStage != LLVMRustOptStage::PreLinkThinLTO) {
1054 for (const auto &C : OptimizerLastEPCallbacks)
1055 PB.registerOptimizerLastEPCallback(C);
1059 case LLVMRustOptStage::PreLinkNoLTO:
1060 MPM = PB.buildPerModuleDefaultPipeline(OptLevel, DebugPassManager);
1062 case LLVMRustOptStage::PreLinkThinLTO:
1063 #if LLVM_VERSION_GE(12, 0)
1064 MPM = PB.buildThinLTOPreLinkDefaultPipeline(OptLevel);
1065 // The ThinLTOPreLink pipeline already includes ThinLTOBuffer passes. However, callback
1066 // passes may still run afterwards. This means we need to run the buffer passes again.
1067 // FIXME: In LLVM 13, the ThinLTOPreLink pipeline also runs OptimizerLastEPCallbacks
1068 // before the RequiredLTOPreLinkPasses, in which case we can remove these hacks.
1069 if (OptimizerLastEPCallbacks.empty())
1070 NeedThinLTOBufferPasses = false;
1072 MPM = PB.buildThinLTOPreLinkDefaultPipeline(OptLevel, DebugPassManager);
1074 #if LLVM_VERSION_GE(11, 0)
1075 for (const auto &C : OptimizerLastEPCallbacks)
1078 if (!OptimizerLastEPCallbacks.empty()) {
1079 FunctionPassManager FPM(DebugPassManager);
1080 for (const auto &C : OptimizerLastEPCallbacks)
1082 MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
1086 case LLVMRustOptStage::PreLinkFatLTO:
1087 #if LLVM_VERSION_GE(12, 0)
1088 MPM = PB.buildLTOPreLinkDefaultPipeline(OptLevel);
1089 NeedThinLTOBufferPasses = false;
1091 MPM = PB.buildLTOPreLinkDefaultPipeline(OptLevel, DebugPassManager);
1094 case LLVMRustOptStage::ThinLTO:
1095 // FIXME: Does it make sense to pass the ModuleSummaryIndex?
1096 // It only seems to be needed for C++ specific optimizations.
1097 #if LLVM_VERSION_GE(12, 0)
1098 MPM = PB.buildThinLTODefaultPipeline(OptLevel, nullptr);
1100 MPM = PB.buildThinLTODefaultPipeline(OptLevel, DebugPassManager, nullptr);
1103 case LLVMRustOptStage::FatLTO:
1104 #if LLVM_VERSION_GE(12, 0)
1105 MPM = PB.buildLTODefaultPipeline(OptLevel, nullptr);
1107 MPM = PB.buildLTODefaultPipeline(OptLevel, DebugPassManager, nullptr);
1114 if (ExtraPassesLen) {
1115 if (auto Err = PB.parsePassPipeline(MPM, StringRef(ExtraPasses, ExtraPassesLen))) {
1116 std::string ErrMsg = toString(std::move(Err));
1117 LLVMRustSetLastError(ErrMsg.c_str());
1118 return LLVMRustResult::Failure;
1122 if (NeedThinLTOBufferPasses) {
1123 MPM.addPass(CanonicalizeAliasesPass());
1124 MPM.addPass(NameAnonGlobalPass());
1127 // Upgrade all calls to old intrinsics first.
1128 for (Module::iterator I = TheModule->begin(), E = TheModule->end(); I != E;)
1129 UpgradeCallsToIntrinsic(&*I++); // must be post-increment, as we remove
1131 MPM.run(*TheModule, MAM);
1132 return LLVMRustResult::Success;
1135 // Callback to demangle function name
1137 // * name to be demangled
1140 // * output buffer len
1141 // Returns len of demangled string, or 0 if demangle failed.
1142 typedef size_t (*DemangleFn)(const char*, size_t, char*, size_t);
1147 class RustAssemblyAnnotationWriter : public AssemblyAnnotationWriter {
1148 DemangleFn Demangle;
1149 std::vector<char> Buf;
1152 RustAssemblyAnnotationWriter(DemangleFn Demangle) : Demangle(Demangle) {}
1154 // Return empty string if demangle failed
1155 // or if name does not need to be demangled
1156 StringRef CallDemangle(StringRef name) {
1161 if (Buf.size() < name.size() * 2) {
1162 // Semangled name usually shorter than mangled,
1163 // but allocate twice as much memory just in case
1164 Buf.resize(name.size() * 2);
1167 auto R = Demangle(name.data(), name.size(), Buf.data(), Buf.size());
1173 auto Demangled = StringRef(Buf.data(), R);
1174 if (Demangled == name) {
1175 // Do not print anything if demangled name is equal to mangled.
1182 void emitFunctionAnnot(const Function *F,
1183 formatted_raw_ostream &OS) override {
1184 StringRef Demangled = CallDemangle(F->getName());
1185 if (Demangled.empty()) {
1189 OS << "; " << Demangled << "\n";
1192 void emitInstructionAnnot(const Instruction *I,
1193 formatted_raw_ostream &OS) override {
1196 if (const CallInst *CI = dyn_cast<CallInst>(I)) {
1198 Value = CI->getCalledOperand();
1199 } else if (const InvokeInst* II = dyn_cast<InvokeInst>(I)) {
1201 Value = II->getCalledOperand();
1203 // Could demangle more operations, e. g.
1204 // `store %place, @function`.
1208 if (!Value->hasName()) {
1212 StringRef Demangled = CallDemangle(Value->getName());
1213 if (Demangled.empty()) {
1217 OS << "; " << Name << " " << Demangled << "\n";
1223 extern "C" LLVMRustResult
1224 LLVMRustPrintModule(LLVMModuleRef M, const char *Path, DemangleFn Demangle) {
1225 std::string ErrorInfo;
1227 raw_fd_ostream OS(Path, EC, sys::fs::OF_None);
1229 ErrorInfo = EC.message();
1230 if (ErrorInfo != "") {
1231 LLVMRustSetLastError(ErrorInfo.c_str());
1232 return LLVMRustResult::Failure;
1235 RustAssemblyAnnotationWriter AAW(Demangle);
1236 formatted_raw_ostream FOS(OS);
1237 unwrap(M)->print(FOS, &AAW);
1239 return LLVMRustResult::Success;
1242 extern "C" void LLVMRustPrintPasses() {
1243 LLVMInitializePasses();
1244 struct MyListener : PassRegistrationListener {
1245 void passEnumerate(const PassInfo *Info) {
1246 StringRef PassArg = Info->getPassArgument();
1247 StringRef PassName = Info->getPassName();
1248 if (!PassArg.empty()) {
1249 // These unsigned->signed casts could theoretically overflow, but
1250 // realistically never will (and even if, the result is implementation
1251 // defined rather plain UB).
1252 printf("%15.*s - %.*s\n", (int)PassArg.size(), PassArg.data(),
1253 (int)PassName.size(), PassName.data());
1258 PassRegistry *PR = PassRegistry::getPassRegistry();
1259 PR->enumerateWith(&Listener);
1262 extern "C" void LLVMRustAddAlwaysInlinePass(LLVMPassManagerBuilderRef PMBR,
1263 bool AddLifetimes) {
1264 unwrap(PMBR)->Inliner = llvm::createAlwaysInlinerLegacyPass(AddLifetimes);
1267 extern "C" void LLVMRustRunRestrictionPass(LLVMModuleRef M, char **Symbols,
1269 llvm::legacy::PassManager passes;
1271 auto PreserveFunctions = [=](const GlobalValue &GV) {
1272 for (size_t I = 0; I < Len; I++) {
1273 if (GV.getName() == Symbols[I]) {
1280 passes.add(llvm::createInternalizePass(PreserveFunctions));
1282 passes.run(*unwrap(M));
1285 extern "C" void LLVMRustMarkAllFunctionsNounwind(LLVMModuleRef M) {
1286 for (Module::iterator GV = unwrap(M)->begin(), E = unwrap(M)->end(); GV != E;
1288 GV->setDoesNotThrow();
1289 Function *F = dyn_cast<Function>(GV);
1293 for (Function::iterator B = F->begin(), BE = F->end(); B != BE; ++B) {
1294 for (BasicBlock::iterator I = B->begin(), IE = B->end(); I != IE; ++I) {
1295 if (isa<InvokeInst>(I)) {
1296 InvokeInst *CI = cast<InvokeInst>(I);
1297 CI->setDoesNotThrow();
1305 LLVMRustSetDataLayoutFromTargetMachine(LLVMModuleRef Module,
1306 LLVMTargetMachineRef TMR) {
1307 TargetMachine *Target = unwrap(TMR);
1308 unwrap(Module)->setDataLayout(Target->createDataLayout());
1311 extern "C" void LLVMRustSetModulePICLevel(LLVMModuleRef M) {
1312 unwrap(M)->setPICLevel(PICLevel::Level::BigPIC);
1315 extern "C" void LLVMRustSetModulePIELevel(LLVMModuleRef M) {
1316 unwrap(M)->setPIELevel(PIELevel::Level::Large);
1319 extern "C" void LLVMRustSetModuleCodeModel(LLVMModuleRef M,
1320 LLVMRustCodeModel Model) {
1321 auto CM = fromRust(Model);
1324 unwrap(M)->setCodeModel(*CM);
1327 // Here you'll find an implementation of ThinLTO as used by the Rust compiler
1328 // right now. This ThinLTO support is only enabled on "recent ish" versions of
1329 // LLVM, and otherwise it's just blanket rejected from other compilers.
1331 // Most of this implementation is straight copied from LLVM. At the time of
1332 // this writing it wasn't *quite* suitable to reuse more code from upstream
1333 // for our purposes, but we should strive to upstream this support once it's
1334 // ready to go! I figure we may want a bit of testing locally first before
1335 // sending this upstream to LLVM. I hear though they're quite eager to receive
1336 // feedback like this!
1338 // If you're reading this code and wondering "what in the world" or you're
1339 // working "good lord by LLVM upgrade is *still* failing due to these bindings"
1340 // then fear not! (ok maybe fear a little). All code here is mostly based
1341 // on `lib/LTO/ThinLTOCodeGenerator.cpp` in LLVM.
1343 // You'll find that the general layout here roughly corresponds to the `run`
1344 // method in that file as well as `ProcessThinLTOModule`. Functions are
1345 // specifically commented below as well, but if you're updating this code
1346 // or otherwise trying to understand it, the LLVM source will be useful in
1347 // interpreting the mysteries within.
1349 // Otherwise I'll apologize in advance, it probably requires a relatively
1350 // significant investment on your part to "truly understand" what's going on
1351 // here. Not saying I do myself, but it took me awhile staring at LLVM's source
1352 // and various online resources about ThinLTO to make heads or tails of all
1355 // This is a shared data structure which *must* be threadsafe to share
1356 // read-only amongst threads. This also corresponds basically to the arguments
1357 // of the `ProcessThinLTOModule` function in the LLVM source.
1358 struct LLVMRustThinLTOData {
1359 // The combined index that is the global analysis over all modules we're
1360 // performing ThinLTO for. This is mostly managed by LLVM.
1361 ModuleSummaryIndex Index;
1363 // All modules we may look at, stored as in-memory serialized versions. This
1364 // is later used when inlining to ensure we can extract any module to inline
1366 StringMap<MemoryBufferRef> ModuleMap;
1368 // A set that we manage of everything we *don't* want internalized. Note that
1369 // this includes all transitive references right now as well, but it may not
1371 DenseSet<GlobalValue::GUID> GUIDPreservedSymbols;
1373 // Not 100% sure what these are, but they impact what's internalized and
1374 // what's inlined across modules, I believe.
1375 StringMap<FunctionImporter::ImportMapTy> ImportLists;
1376 StringMap<FunctionImporter::ExportSetTy> ExportLists;
1377 StringMap<GVSummaryMapTy> ModuleToDefinedGVSummaries;
1378 StringMap<std::map<GlobalValue::GUID, GlobalValue::LinkageTypes>> ResolvedODR;
1380 LLVMRustThinLTOData() : Index(/* HaveGVs = */ false) {}
1383 // Just an argument to the `LLVMRustCreateThinLTOData` function below.
1384 struct LLVMRustThinLTOModule {
1385 const char *identifier;
1390 // This is copied from `lib/LTO/ThinLTOCodeGenerator.cpp`, not sure what it
1392 static const GlobalValueSummary *
1393 getFirstDefinitionForLinker(const GlobalValueSummaryList &GVSummaryList) {
1394 auto StrongDefForLinker = llvm::find_if(
1395 GVSummaryList, [](const std::unique_ptr<GlobalValueSummary> &Summary) {
1396 auto Linkage = Summary->linkage();
1397 return !GlobalValue::isAvailableExternallyLinkage(Linkage) &&
1398 !GlobalValue::isWeakForLinker(Linkage);
1400 if (StrongDefForLinker != GVSummaryList.end())
1401 return StrongDefForLinker->get();
1403 auto FirstDefForLinker = llvm::find_if(
1404 GVSummaryList, [](const std::unique_ptr<GlobalValueSummary> &Summary) {
1405 auto Linkage = Summary->linkage();
1406 return !GlobalValue::isAvailableExternallyLinkage(Linkage);
1408 if (FirstDefForLinker == GVSummaryList.end())
1410 return FirstDefForLinker->get();
1413 // The main entry point for creating the global ThinLTO analysis. The structure
1414 // here is basically the same as before threads are spawned in the `run`
1415 // function of `lib/LTO/ThinLTOCodeGenerator.cpp`.
1416 extern "C" LLVMRustThinLTOData*
1417 LLVMRustCreateThinLTOData(LLVMRustThinLTOModule *modules,
1419 const char **preserved_symbols,
1421 auto Ret = std::make_unique<LLVMRustThinLTOData>();
1423 // Load each module's summary and merge it into one combined index
1424 for (int i = 0; i < num_modules; i++) {
1425 auto module = &modules[i];
1426 StringRef buffer(module->data, module->len);
1427 MemoryBufferRef mem_buffer(buffer, module->identifier);
1429 Ret->ModuleMap[module->identifier] = mem_buffer;
1431 if (Error Err = readModuleSummaryIndex(mem_buffer, Ret->Index, i)) {
1432 LLVMRustSetLastError(toString(std::move(Err)).c_str());
1437 // Collect for each module the list of function it defines (GUID -> Summary)
1438 Ret->Index.collectDefinedGVSummariesPerModule(Ret->ModuleToDefinedGVSummaries);
1440 // Convert the preserved symbols set from string to GUID, this is then needed
1441 // for internalization.
1442 for (int i = 0; i < num_symbols; i++) {
1443 auto GUID = GlobalValue::getGUID(preserved_symbols[i]);
1444 Ret->GUIDPreservedSymbols.insert(GUID);
1447 // Collect the import/export lists for all modules from the call-graph in the
1450 // This is copied from `lib/LTO/ThinLTOCodeGenerator.cpp`
1451 auto deadIsPrevailing = [&](GlobalValue::GUID G) {
1452 return PrevailingType::Unknown;
1454 // We don't have a complete picture in our use of ThinLTO, just our immediate
1455 // crate, so we need `ImportEnabled = false` to limit internalization.
1456 // Otherwise, we sometimes lose `static` values -- see #60184.
1457 computeDeadSymbolsWithConstProp(Ret->Index, Ret->GUIDPreservedSymbols,
1458 deadIsPrevailing, /* ImportEnabled = */ false);
1459 ComputeCrossModuleImport(
1461 Ret->ModuleToDefinedGVSummaries,
1466 // Resolve LinkOnce/Weak symbols, this has to be computed early be cause it
1467 // impacts the caching.
1469 // This is copied from `lib/LTO/ThinLTOCodeGenerator.cpp` with some of this
1470 // being lifted from `lib/LTO/LTO.cpp` as well
1471 DenseMap<GlobalValue::GUID, const GlobalValueSummary *> PrevailingCopy;
1472 for (auto &I : Ret->Index) {
1473 if (I.second.SummaryList.size() > 1)
1474 PrevailingCopy[I.first] = getFirstDefinitionForLinker(I.second.SummaryList);
1476 auto isPrevailing = [&](GlobalValue::GUID GUID, const GlobalValueSummary *S) {
1477 const auto &Prevailing = PrevailingCopy.find(GUID);
1478 if (Prevailing == PrevailingCopy.end())
1480 return Prevailing->second == S;
1482 auto recordNewLinkage = [&](StringRef ModuleIdentifier,
1483 GlobalValue::GUID GUID,
1484 GlobalValue::LinkageTypes NewLinkage) {
1485 Ret->ResolvedODR[ModuleIdentifier][GUID] = NewLinkage;
1488 #if LLVM_VERSION_GE(13,0)
1489 // Uses FromPrevailing visibility scheme which works for many binary
1490 // formats. We probably could and should use ELF visibility scheme for many of
1491 // our targets, however.
1493 thinLTOResolvePrevailingInIndex(conf, Ret->Index, isPrevailing, recordNewLinkage,
1494 Ret->GUIDPreservedSymbols);
1496 thinLTOResolvePrevailingInIndex(Ret->Index, isPrevailing, recordNewLinkage,
1497 Ret->GUIDPreservedSymbols);
1499 // Here we calculate an `ExportedGUIDs` set for use in the `isExported`
1500 // callback below. This callback below will dictate the linkage for all
1501 // summaries in the index, and we basically just only want to ensure that dead
1502 // symbols are internalized. Otherwise everything that's already external
1503 // linkage will stay as external, and internal will stay as internal.
1504 std::set<GlobalValue::GUID> ExportedGUIDs;
1505 for (auto &List : Ret->Index) {
1506 for (auto &GVS: List.second.SummaryList) {
1507 if (GlobalValue::isLocalLinkage(GVS->linkage()))
1509 auto GUID = GVS->getOriginalName();
1510 if (GVS->flags().Live)
1511 ExportedGUIDs.insert(GUID);
1514 auto isExported = [&](StringRef ModuleIdentifier, ValueInfo VI) {
1515 const auto &ExportList = Ret->ExportLists.find(ModuleIdentifier);
1516 return (ExportList != Ret->ExportLists.end() &&
1517 ExportList->second.count(VI)) ||
1518 ExportedGUIDs.count(VI.getGUID());
1520 thinLTOInternalizeAndPromoteInIndex(Ret->Index, isExported, isPrevailing);
1522 return Ret.release();
1526 LLVMRustFreeThinLTOData(LLVMRustThinLTOData *Data) {
1530 // Below are the various passes that happen *per module* when doing ThinLTO.
1532 // In other words, these are the functions that are all run concurrently
1533 // with one another, one per module. The passes here correspond to the analysis
1534 // passes in `lib/LTO/ThinLTOCodeGenerator.cpp`, currently found in the
1535 // `ProcessThinLTOModule` function. Here they're split up into separate steps
1536 // so rustc can save off the intermediate bytecode between each step.
1538 #if LLVM_VERSION_GE(11, 0)
1540 clearDSOLocalOnDeclarations(Module &Mod, TargetMachine &TM) {
1541 // When linking an ELF shared object, dso_local should be dropped. We
1542 // conservatively do this for -fpic.
1543 bool ClearDSOLocalOnDeclarations =
1544 TM.getTargetTriple().isOSBinFormatELF() &&
1545 TM.getRelocationModel() != Reloc::Static &&
1546 Mod.getPIELevel() == PIELevel::Default;
1547 return ClearDSOLocalOnDeclarations;
1552 LLVMRustPrepareThinLTORename(const LLVMRustThinLTOData *Data, LLVMModuleRef M,
1553 LLVMTargetMachineRef TM) {
1554 Module &Mod = *unwrap(M);
1555 TargetMachine &Target = *unwrap(TM);
1557 #if LLVM_VERSION_GE(11, 0)
1558 bool ClearDSOLocal = clearDSOLocalOnDeclarations(Mod, Target);
1559 bool error = renameModuleForThinLTO(Mod, Data->Index, ClearDSOLocal);
1561 bool error = renameModuleForThinLTO(Mod, Data->Index);
1565 LLVMRustSetLastError("renameModuleForThinLTO failed");
1572 LLVMRustPrepareThinLTOResolveWeak(const LLVMRustThinLTOData *Data, LLVMModuleRef M) {
1573 Module &Mod = *unwrap(M);
1574 const auto &DefinedGlobals = Data->ModuleToDefinedGVSummaries.lookup(Mod.getModuleIdentifier());
1575 thinLTOResolvePrevailingInModule(Mod, DefinedGlobals);
1580 LLVMRustPrepareThinLTOInternalize(const LLVMRustThinLTOData *Data, LLVMModuleRef M) {
1581 Module &Mod = *unwrap(M);
1582 const auto &DefinedGlobals = Data->ModuleToDefinedGVSummaries.lookup(Mod.getModuleIdentifier());
1583 thinLTOInternalizeModule(Mod, DefinedGlobals);
1588 LLVMRustPrepareThinLTOImport(const LLVMRustThinLTOData *Data, LLVMModuleRef M,
1589 LLVMTargetMachineRef TM) {
1590 Module &Mod = *unwrap(M);
1591 TargetMachine &Target = *unwrap(TM);
1593 const auto &ImportList = Data->ImportLists.lookup(Mod.getModuleIdentifier());
1594 auto Loader = [&](StringRef Identifier) {
1595 const auto &Memory = Data->ModuleMap.lookup(Identifier);
1596 auto &Context = Mod.getContext();
1597 auto MOrErr = getLazyBitcodeModule(Memory, Context, true, true);
1602 // The rest of this closure is a workaround for
1603 // https://bugs.llvm.org/show_bug.cgi?id=38184 where during ThinLTO imports
1604 // we accidentally import wasm custom sections into different modules,
1605 // duplicating them by in the final output artifact.
1607 // The issue is worked around here by manually removing the
1608 // `wasm.custom_sections` named metadata node from any imported module. This
1609 // we know isn't used by any optimization pass so there's no need for it to
1612 // Note that the metadata is currently lazily loaded, so we materialize it
1613 // here before looking up if there's metadata inside. The `FunctionImporter`
1614 // will immediately materialize metadata anyway after an import, so this
1615 // shouldn't be a perf hit.
1616 if (Error Err = (*MOrErr)->materializeMetadata()) {
1617 Expected<std::unique_ptr<Module>> Ret(std::move(Err));
1621 auto *WasmCustomSections = (*MOrErr)->getNamedMetadata("wasm.custom_sections");
1622 if (WasmCustomSections)
1623 WasmCustomSections->eraseFromParent();
1627 #if LLVM_VERSION_GE(11, 0)
1628 bool ClearDSOLocal = clearDSOLocalOnDeclarations(Mod, Target);
1629 FunctionImporter Importer(Data->Index, Loader, ClearDSOLocal);
1631 FunctionImporter Importer(Data->Index, Loader);
1633 Expected<bool> Result = Importer.importFunctions(Mod, ImportList);
1635 LLVMRustSetLastError(toString(Result.takeError()).c_str());
1641 extern "C" typedef void (*LLVMRustModuleNameCallback)(void*, // payload
1642 const char*, // importing module name
1643 const char*); // imported module name
1645 // Calls `module_name_callback` for each module import done by ThinLTO.
1646 // The callback is provided with regular null-terminated C strings.
1648 LLVMRustGetThinLTOModules(const LLVMRustThinLTOData *data,
1649 LLVMRustModuleNameCallback module_name_callback,
1650 void* callback_payload) {
1651 for (const auto& importing_module : data->ImportLists) {
1652 const std::string importing_module_id = importing_module.getKey().str();
1653 const auto& imports = importing_module.getValue();
1654 for (const auto& imported_module : imports) {
1655 const std::string imported_module_id = imported_module.getKey().str();
1656 module_name_callback(callback_payload,
1657 importing_module_id.c_str(),
1658 imported_module_id.c_str());
1663 // This struct and various functions are sort of a hack right now, but the
1664 // problem is that we've got in-memory LLVM modules after we generate and
1665 // optimize all codegen-units for one compilation in rustc. To be compatible
1666 // with the LTO support above we need to serialize the modules plus their
1667 // ThinLTO summary into memory.
1669 // This structure is basically an owned version of a serialize module, with
1670 // a ThinLTO summary attached.
1671 struct LLVMRustThinLTOBuffer {
1675 extern "C" LLVMRustThinLTOBuffer*
1676 LLVMRustThinLTOBufferCreate(LLVMModuleRef M) {
1677 auto Ret = std::make_unique<LLVMRustThinLTOBuffer>();
1679 raw_string_ostream OS(Ret->data);
1681 legacy::PassManager PM;
1682 PM.add(createWriteThinLTOBitcodePass(OS));
1686 return Ret.release();
1690 LLVMRustThinLTOBufferFree(LLVMRustThinLTOBuffer *Buffer) {
1694 extern "C" const void*
1695 LLVMRustThinLTOBufferPtr(const LLVMRustThinLTOBuffer *Buffer) {
1696 return Buffer->data.data();
1700 LLVMRustThinLTOBufferLen(const LLVMRustThinLTOBuffer *Buffer) {
1701 return Buffer->data.length();
1704 // This is what we used to parse upstream bitcode for actual ThinLTO
1705 // processing. We'll call this once per module optimized through ThinLTO, and
1706 // it'll be called concurrently on many threads.
1707 extern "C" LLVMModuleRef
1708 LLVMRustParseBitcodeForLTO(LLVMContextRef Context,
1711 const char *identifier) {
1712 StringRef Data(data, len);
1713 MemoryBufferRef Buffer(Data, identifier);
1714 unwrap(Context)->enableDebugTypeODRUniquing();
1715 Expected<std::unique_ptr<Module>> SrcOrError =
1716 parseBitcodeFile(Buffer, *unwrap(Context));
1718 LLVMRustSetLastError(toString(SrcOrError.takeError()).c_str());
1721 return wrap(std::move(*SrcOrError).release());
1724 // Find the bitcode section in the object file data and return it as a slice.
1725 // Fail if the bitcode section is present but empty.
1727 // On success, the return value is the pointer to the start of the slice and
1728 // `out_len` is filled with the (non-zero) length. On failure, the return value
1729 // is `nullptr` and `out_len` is set to zero.
1730 extern "C" const char*
1731 LLVMRustGetBitcodeSliceFromObjectData(const char *data,
1736 StringRef Data(data, len);
1737 MemoryBufferRef Buffer(Data, ""); // The id is unused.
1739 Expected<MemoryBufferRef> BitcodeOrError =
1740 object::IRObjectFile::findBitcodeInMemBuffer(Buffer);
1741 if (!BitcodeOrError) {
1742 LLVMRustSetLastError(toString(BitcodeOrError.takeError()).c_str());
1746 *out_len = BitcodeOrError->getBufferSize();
1747 return BitcodeOrError->getBufferStart();
1750 // Rewrite all `DICompileUnit` pointers to the `DICompileUnit` specified. See
1751 // the comment in `back/lto.rs` for why this exists.
1753 LLVMRustLTOGetDICompileUnit(LLVMModuleRef Mod,
1755 DICompileUnit **B) {
1756 Module *M = unwrap(Mod);
1757 DICompileUnit **Cur = A;
1758 DICompileUnit **Next = B;
1759 for (DICompileUnit *CU : M->debug_compile_units()) {
1768 // Rewrite all `DICompileUnit` pointers to the `DICompileUnit` specified. See
1769 // the comment in `back/lto.rs` for why this exists.
1771 LLVMRustLTOPatchDICompileUnit(LLVMModuleRef Mod, DICompileUnit *Unit) {
1772 Module *M = unwrap(Mod);
1774 // If the original source module didn't have a `DICompileUnit` then try to
1775 // merge all the existing compile units. If there aren't actually any though
1776 // then there's not much for us to do so return.
1777 if (Unit == nullptr) {
1778 for (DICompileUnit *CU : M->debug_compile_units()) {
1782 if (Unit == nullptr)
1786 // Use LLVM's built-in `DebugInfoFinder` to find a bunch of debuginfo and
1787 // process it recursively. Note that we used to specifically iterate over
1788 // instructions to ensure we feed everything into it, but `processModule`
1789 // started doing this the same way in LLVM 7 (commit d769eb36ab2b8).
1790 DebugInfoFinder Finder;
1791 Finder.processModule(*M);
1793 // After we've found all our debuginfo, rewrite all subprograms to point to
1794 // the same `DICompileUnit`.
1795 for (auto &F : Finder.subprograms()) {
1796 F->replaceUnit(Unit);
1799 // Erase any other references to other `DICompileUnit` instances, the verifier
1800 // will later ensure that we don't actually have any other stale references to
1802 auto *MD = M->getNamedMetadata("llvm.dbg.cu");
1803 MD->clearOperands();
1804 MD->addOperand(Unit);
1807 // Computes the LTO cache key for the provided 'ModId' in the given 'Data',
1808 // storing the result in 'KeyOut'.
1809 // Currently, this cache key is a SHA-1 hash of anything that could affect
1810 // the result of optimizing this module (e.g. module imports, exports, liveness
1811 // of access globals, etc).
1812 // The precise details are determined by LLVM in `computeLTOCacheKey`, which is
1813 // used during the normal linker-plugin incremental thin-LTO process.
1815 LLVMRustComputeLTOCacheKey(RustStringRef KeyOut, const char *ModId, LLVMRustThinLTOData *Data) {
1816 SmallString<40> Key;
1817 llvm::lto::Config conf;
1818 const auto &ImportList = Data->ImportLists.lookup(ModId);
1819 const auto &ExportList = Data->ExportLists.lookup(ModId);
1820 const auto &ResolvedODR = Data->ResolvedODR.lookup(ModId);
1821 const auto &DefinedGlobals = Data->ModuleToDefinedGVSummaries.lookup(ModId);
1822 std::set<GlobalValue::GUID> CfiFunctionDefs;
1823 std::set<GlobalValue::GUID> CfiFunctionDecls;
1825 // Based on the 'InProcessThinBackend' constructor in LLVM
1826 for (auto &Name : Data->Index.cfiFunctionDefs())
1827 CfiFunctionDefs.insert(
1828 GlobalValue::getGUID(GlobalValue::dropLLVMManglingEscape(Name)));
1829 for (auto &Name : Data->Index.cfiFunctionDecls())
1830 CfiFunctionDecls.insert(
1831 GlobalValue::getGUID(GlobalValue::dropLLVMManglingEscape(Name)));
1833 llvm::computeLTOCacheKey(Key, conf, Data->Index, ModId,
1834 ImportList, ExportList, ResolvedODR, DefinedGlobals, CfiFunctionDefs, CfiFunctionDecls
1837 LLVMRustStringWriteImpl(KeyOut, Key.c_str(), Key.size());