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)
57 #if LLVM_VERSION_LT(11, 0)
58 DEFINE_STDCXX_CONVERSION_FUNCTIONS(PassManagerBuilder,
59 LLVMPassManagerBuilderRef)
62 extern "C" void LLVMInitializePasses() {
63 PassRegistry &Registry = *PassRegistry::getPassRegistry();
64 initializeCore(Registry);
65 initializeCodeGen(Registry);
66 initializeScalarOpts(Registry);
67 initializeVectorization(Registry);
68 initializeIPO(Registry);
69 initializeAnalysis(Registry);
70 initializeTransformUtils(Registry);
71 initializeInstCombine(Registry);
72 initializeInstrumentation(Registry);
73 initializeTarget(Registry);
76 extern "C" void LLVMTimeTraceProfilerInitialize() {
77 timeTraceProfilerInitialize(
78 /* TimeTraceGranularity */ 0,
79 /* ProcName */ "rustc");
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 TrapUnreachable,
472 bool EmitStackSizeSection,
473 bool RelaxELFRelocations,
475 const char *SplitDwarfFile) {
477 auto OptLevel = fromRust(RustOptLevel);
478 auto RM = fromRust(RustReloc);
479 auto CM = fromRust(RustCM);
482 Triple Trip(Triple::normalize(TripleStr));
483 const llvm::Target *TheTarget =
484 TargetRegistry::lookupTarget(Trip.getTriple(), Error);
485 if (TheTarget == nullptr) {
486 LLVMRustSetLastError(Error.c_str());
490 TargetOptions Options;
492 Options.FloatABIType = FloatABI::Default;
494 Options.FloatABIType = FloatABI::Soft;
496 Options.DataSections = DataSections;
497 Options.FunctionSections = FunctionSections;
498 Options.MCOptions.AsmVerbose = AsmComments;
499 Options.MCOptions.PreserveAsmComments = AsmComments;
500 Options.MCOptions.ABIName = ABIStr;
501 if (SplitDwarfFile) {
502 Options.MCOptions.SplitDwarfFile = SplitDwarfFile;
504 Options.RelaxELFRelocations = RelaxELFRelocations;
505 Options.UseInitArray = UseInitArray;
507 if (TrapUnreachable) {
508 // Tell LLVM to codegen `unreachable` into an explicit trap instruction.
509 // This limits the extent of possible undefined behavior in some cases, as
510 // it prevents control flow from "falling through" into whatever code
511 // happens to be laid out next in memory.
512 Options.TrapUnreachable = true;
516 Options.ThreadModel = ThreadModel::Single;
519 Options.EmitStackSizeSection = EmitStackSizeSection;
521 TargetMachine *TM = TheTarget->createTargetMachine(
522 Trip.getTriple(), CPU, Feature, Options, RM, CM, OptLevel);
526 extern "C" void LLVMRustDisposeTargetMachine(LLVMTargetMachineRef TM) {
530 extern "C" void LLVMRustConfigurePassManagerBuilder(
531 LLVMPassManagerBuilderRef PMBR, LLVMRustCodeGenOptLevel OptLevel,
532 bool MergeFunctions, bool SLPVectorize, bool LoopVectorize, bool PrepareForThinLTO,
533 const char* PGOGenPath, const char* PGOUsePath, const char* PGOSampleUsePath) {
534 unwrap(PMBR)->MergeFunctions = MergeFunctions;
535 unwrap(PMBR)->SLPVectorize = SLPVectorize;
536 unwrap(PMBR)->OptLevel = fromRust(OptLevel);
537 unwrap(PMBR)->LoopVectorize = LoopVectorize;
538 unwrap(PMBR)->PrepareForThinLTO = PrepareForThinLTO;
541 assert(!PGOUsePath && !PGOSampleUsePath);
542 unwrap(PMBR)->EnablePGOInstrGen = true;
543 unwrap(PMBR)->PGOInstrGen = PGOGenPath;
544 } else if (PGOUsePath) {
545 assert(!PGOSampleUsePath);
546 unwrap(PMBR)->PGOInstrUse = PGOUsePath;
547 } else if (PGOSampleUsePath) {
548 unwrap(PMBR)->PGOSampleUse = PGOSampleUsePath;
552 // Unfortunately, the LLVM C API doesn't provide a way to set the `LibraryInfo`
553 // field of a PassManagerBuilder, we expose our own method of doing so.
554 extern "C" void LLVMRustAddBuilderLibraryInfo(LLVMPassManagerBuilderRef PMBR,
556 bool DisableSimplifyLibCalls) {
557 Triple TargetTriple(unwrap(M)->getTargetTriple());
558 TargetLibraryInfoImpl *TLI = new TargetLibraryInfoImpl(TargetTriple);
559 if (DisableSimplifyLibCalls)
560 TLI->disableAllFunctions();
561 unwrap(PMBR)->LibraryInfo = TLI;
564 // Unfortunately, the LLVM C API doesn't provide a way to create the
565 // TargetLibraryInfo pass, so we use this method to do so.
566 extern "C" void LLVMRustAddLibraryInfo(LLVMPassManagerRef PMR, LLVMModuleRef M,
567 bool DisableSimplifyLibCalls) {
568 Triple TargetTriple(unwrap(M)->getTargetTriple());
569 TargetLibraryInfoImpl TLII(TargetTriple);
570 if (DisableSimplifyLibCalls)
571 TLII.disableAllFunctions();
572 unwrap(PMR)->add(new TargetLibraryInfoWrapperPass(TLII));
575 // Unfortunately, the LLVM C API doesn't provide an easy way of iterating over
576 // all the functions in a module, so we do that manually here. You'll find
577 // similar code in clang's BackendUtil.cpp file.
578 extern "C" void LLVMRustRunFunctionPassManager(LLVMPassManagerRef PMR,
580 llvm::legacy::FunctionPassManager *P =
581 unwrap<llvm::legacy::FunctionPassManager>(PMR);
582 P->doInitialization();
584 // Upgrade all calls to old intrinsics first.
585 for (Module::iterator I = unwrap(M)->begin(), E = unwrap(M)->end(); I != E;)
586 UpgradeCallsToIntrinsic(&*I++); // must be post-increment, as we remove
588 for (Module::iterator I = unwrap(M)->begin(), E = unwrap(M)->end(); I != E;
590 if (!I->isDeclaration())
596 extern "C" void LLVMRustSetLLVMOptions(int Argc, char **Argv) {
597 // Initializing the command-line options more than once is not allowed. So,
598 // check if they've already been initialized. (This could happen if we're
599 // being called from rustpkg, for example). If the arguments change, then
600 // that's just kinda unfortunate.
601 static bool Initialized = false;
605 cl::ParseCommandLineOptions(Argc, Argv);
608 enum class LLVMRustFileType {
613 static CodeGenFileType fromRust(LLVMRustFileType Type) {
615 case LLVMRustFileType::AssemblyFile:
616 return CGFT_AssemblyFile;
617 case LLVMRustFileType::ObjectFile:
618 return CGFT_ObjectFile;
620 report_fatal_error("Bad FileType.");
624 extern "C" LLVMRustResult
625 LLVMRustWriteOutputFile(LLVMTargetMachineRef Target, LLVMPassManagerRef PMR,
626 LLVMModuleRef M, const char *Path, const char *DwoPath,
627 LLVMRustFileType RustFileType) {
628 llvm::legacy::PassManager *PM = unwrap<llvm::legacy::PassManager>(PMR);
629 auto FileType = fromRust(RustFileType);
631 std::string ErrorInfo;
633 raw_fd_ostream OS(Path, EC, sys::fs::OF_None);
635 ErrorInfo = EC.message();
636 if (ErrorInfo != "") {
637 LLVMRustSetLastError(ErrorInfo.c_str());
638 return LLVMRustResult::Failure;
641 buffer_ostream BOS(OS);
643 raw_fd_ostream DOS(DwoPath, EC, sys::fs::OF_None);
646 ErrorInfo = EC.message();
647 if (ErrorInfo != "") {
648 LLVMRustSetLastError(ErrorInfo.c_str());
649 return LLVMRustResult::Failure;
651 buffer_ostream DBOS(DOS);
652 unwrap(Target)->addPassesToEmitFile(*PM, BOS, &DBOS, FileType, false);
655 unwrap(Target)->addPassesToEmitFile(*PM, BOS, nullptr, FileType, false);
659 // Apparently `addPassesToEmitFile` adds a pointer to our on-the-stack output
660 // stream (OS), so the only real safe place to delete this is here? Don't we
661 // wish this was written in Rust?
662 LLVMDisposePassManager(PMR);
663 return LLVMRustResult::Success;
666 extern "C" typedef void (*LLVMRustSelfProfileBeforePassCallback)(void*, // LlvmSelfProfiler
667 const char*, // pass name
668 const char*); // IR name
669 extern "C" typedef void (*LLVMRustSelfProfileAfterPassCallback)(void*); // LlvmSelfProfiler
671 std::string LLVMRustwrappedIrGetName(const llvm::Any &WrappedIr) {
672 if (any_isa<const Module *>(WrappedIr))
673 return any_cast<const Module *>(WrappedIr)->getName().str();
674 if (any_isa<const Function *>(WrappedIr))
675 return any_cast<const Function *>(WrappedIr)->getName().str();
676 if (any_isa<const Loop *>(WrappedIr))
677 return any_cast<const Loop *>(WrappedIr)->getName().str();
678 if (any_isa<const LazyCallGraph::SCC *>(WrappedIr))
679 return any_cast<const LazyCallGraph::SCC *>(WrappedIr)->getName();
684 void LLVMSelfProfileInitializeCallbacks(
685 PassInstrumentationCallbacks& PIC, void* LlvmSelfProfiler,
686 LLVMRustSelfProfileBeforePassCallback BeforePassCallback,
687 LLVMRustSelfProfileAfterPassCallback AfterPassCallback) {
688 #if LLVM_VERSION_GE(12, 0)
689 PIC.registerBeforeNonSkippedPassCallback([LlvmSelfProfiler, BeforePassCallback](
690 StringRef Pass, llvm::Any Ir) {
691 std::string PassName = Pass.str();
692 std::string IrName = LLVMRustwrappedIrGetName(Ir);
693 BeforePassCallback(LlvmSelfProfiler, PassName.c_str(), IrName.c_str());
696 PIC.registerAfterPassCallback(
697 [LlvmSelfProfiler, AfterPassCallback](StringRef Pass, llvm::Any IR,
698 const PreservedAnalyses &Preserved) {
699 AfterPassCallback(LlvmSelfProfiler);
702 PIC.registerAfterPassInvalidatedCallback(
703 [LlvmSelfProfiler, AfterPassCallback](StringRef Pass, const PreservedAnalyses &Preserved) {
704 AfterPassCallback(LlvmSelfProfiler);
707 PIC.registerBeforePassCallback([LlvmSelfProfiler, BeforePassCallback](
708 StringRef Pass, llvm::Any Ir) {
709 std::string PassName = Pass.str();
710 std::string IrName = LLVMRustwrappedIrGetName(Ir);
711 BeforePassCallback(LlvmSelfProfiler, PassName.c_str(), IrName.c_str());
715 PIC.registerAfterPassCallback(
716 [LlvmSelfProfiler, AfterPassCallback](StringRef Pass, llvm::Any Ir) {
717 AfterPassCallback(LlvmSelfProfiler);
720 PIC.registerAfterPassInvalidatedCallback(
721 [LlvmSelfProfiler, AfterPassCallback](StringRef Pass) {
722 AfterPassCallback(LlvmSelfProfiler);
726 PIC.registerBeforeAnalysisCallback([LlvmSelfProfiler, BeforePassCallback](
727 StringRef Pass, llvm::Any Ir) {
728 std::string PassName = Pass.str();
729 std::string IrName = LLVMRustwrappedIrGetName(Ir);
730 BeforePassCallback(LlvmSelfProfiler, PassName.c_str(), IrName.c_str());
733 PIC.registerAfterAnalysisCallback(
734 [LlvmSelfProfiler, AfterPassCallback](StringRef Pass, llvm::Any Ir) {
735 AfterPassCallback(LlvmSelfProfiler);
739 enum class LLVMRustOptStage {
747 struct LLVMRustSanitizerOptions {
748 bool SanitizeAddress;
749 bool SanitizeAddressRecover;
751 bool SanitizeMemoryRecover;
752 int SanitizeMemoryTrackOrigins;
754 bool SanitizeHWAddress;
755 bool SanitizeHWAddressRecover;
758 extern "C" LLVMRustResult
759 LLVMRustOptimizeWithNewPassManager(
760 LLVMModuleRef ModuleRef,
761 LLVMTargetMachineRef TMRef,
762 LLVMRustPassBuilderOptLevel OptLevelRust,
763 LLVMRustOptStage OptStage,
764 bool NoPrepopulatePasses, bool VerifyIR, bool UseThinLTOBuffers,
765 bool MergeFunctions, bool UnrollLoops, bool SLPVectorize, bool LoopVectorize,
766 bool DisableSimplifyLibCalls, bool EmitLifetimeMarkers,
767 LLVMRustSanitizerOptions *SanitizerOptions,
768 const char *PGOGenPath, const char *PGOUsePath,
769 bool InstrumentCoverage, bool InstrumentGCOV,
770 const char *PGOSampleUsePath, bool DebugInfoForProfiling,
771 void* LlvmSelfProfiler,
772 LLVMRustSelfProfileBeforePassCallback BeforePassCallback,
773 LLVMRustSelfProfileAfterPassCallback AfterPassCallback,
774 const char *ExtraPasses, size_t ExtraPassesLen) {
775 Module *TheModule = unwrap(ModuleRef);
776 TargetMachine *TM = unwrap(TMRef);
777 OptimizationLevel OptLevel = fromRust(OptLevelRust);
780 PipelineTuningOptions PTO;
781 PTO.LoopUnrolling = UnrollLoops;
782 PTO.LoopInterleaving = UnrollLoops;
783 PTO.LoopVectorization = LoopVectorize;
784 PTO.SLPVectorization = SLPVectorize;
785 #if LLVM_VERSION_GE(12, 0)
786 PTO.MergeFunctions = MergeFunctions;
788 // MergeFunctions is not supported by NewPM in older LLVM versions.
789 (void) MergeFunctions;
792 // FIXME: We may want to expose this as an option.
793 bool DebugPassManager = false;
795 PassInstrumentationCallbacks PIC;
796 #if LLVM_VERSION_GE(12, 0)
797 StandardInstrumentations SI(DebugPassManager);
799 StandardInstrumentations SI;
801 SI.registerCallbacks(PIC);
803 if (LlvmSelfProfiler){
804 LLVMSelfProfileInitializeCallbacks(PIC,LlvmSelfProfiler,BeforePassCallback,AfterPassCallback);
807 Optional<PGOOptions> PGOOpt;
809 assert(!PGOUsePath && !PGOSampleUsePath);
810 PGOOpt = PGOOptions(PGOGenPath, "", "", PGOOptions::IRInstr,
811 PGOOptions::NoCSAction, DebugInfoForProfiling);
812 } else if (PGOUsePath) {
813 assert(!PGOSampleUsePath);
814 PGOOpt = PGOOptions(PGOUsePath, "", "", PGOOptions::IRUse,
815 PGOOptions::NoCSAction, DebugInfoForProfiling);
816 } else if (PGOSampleUsePath) {
817 PGOOpt = PGOOptions(PGOSampleUsePath, "", "", PGOOptions::SampleUse,
818 PGOOptions::NoCSAction, DebugInfoForProfiling);
819 } else if (DebugInfoForProfiling) {
820 PGOOpt = PGOOptions("", "", "", PGOOptions::NoAction,
821 PGOOptions::NoCSAction, DebugInfoForProfiling);
824 #if LLVM_VERSION_GE(12, 0) && !LLVM_VERSION_GE(13,0)
825 PassBuilder PB(DebugPassManager, TM, PTO, PGOOpt, &PIC);
827 PassBuilder PB(TM, PTO, PGOOpt, &PIC);
830 #if LLVM_VERSION_GE(13, 0)
831 LoopAnalysisManager LAM;
832 FunctionAnalysisManager FAM;
833 CGSCCAnalysisManager CGAM;
834 ModuleAnalysisManager MAM;
836 LoopAnalysisManager LAM(DebugPassManager);
837 FunctionAnalysisManager FAM(DebugPassManager);
838 CGSCCAnalysisManager CGAM(DebugPassManager);
839 ModuleAnalysisManager MAM(DebugPassManager);
842 FAM.registerPass([&] { return PB.buildDefaultAAPipeline(); });
844 Triple TargetTriple(TheModule->getTargetTriple());
845 std::unique_ptr<TargetLibraryInfoImpl> TLII(new TargetLibraryInfoImpl(TargetTriple));
846 if (DisableSimplifyLibCalls)
847 TLII->disableAllFunctions();
848 FAM.registerPass([&] { return TargetLibraryAnalysis(*TLII); });
850 PB.registerModuleAnalyses(MAM);
851 PB.registerCGSCCAnalyses(CGAM);
852 PB.registerFunctionAnalyses(FAM);
853 PB.registerLoopAnalyses(LAM);
854 PB.crossRegisterProxies(LAM, FAM, CGAM, MAM);
856 // We manually collect pipeline callbacks so we can apply them at O0, where the
857 // PassBuilder does not create a pipeline.
858 std::vector<std::function<void(ModulePassManager &, OptimizationLevel)>>
859 PipelineStartEPCallbacks;
860 #if LLVM_VERSION_GE(11, 0)
861 std::vector<std::function<void(ModulePassManager &, OptimizationLevel)>>
862 OptimizerLastEPCallbacks;
864 std::vector<std::function<void(FunctionPassManager &, OptimizationLevel)>>
865 OptimizerLastEPCallbacks;
869 PipelineStartEPCallbacks.push_back(
870 [VerifyIR](ModulePassManager &MPM, OptimizationLevel Level) {
871 MPM.addPass(VerifierPass());
876 if (InstrumentGCOV) {
877 PipelineStartEPCallbacks.push_back(
878 [](ModulePassManager &MPM, OptimizationLevel Level) {
879 MPM.addPass(GCOVProfilerPass(GCOVOptions::getDefault()));
884 if (InstrumentCoverage) {
885 PipelineStartEPCallbacks.push_back(
886 [](ModulePassManager &MPM, OptimizationLevel Level) {
887 InstrProfOptions Options;
888 MPM.addPass(InstrProfiling(Options, false));
893 if (SanitizerOptions) {
894 if (SanitizerOptions->SanitizeMemory) {
895 MemorySanitizerOptions Options(
896 SanitizerOptions->SanitizeMemoryTrackOrigins,
897 SanitizerOptions->SanitizeMemoryRecover,
898 /*CompileKernel=*/false);
899 #if LLVM_VERSION_GE(11, 0)
900 OptimizerLastEPCallbacks.push_back(
901 [Options](ModulePassManager &MPM, OptimizationLevel Level) {
902 #if LLVM_VERSION_GE(14, 0)
903 MPM.addPass(ModuleMemorySanitizerPass(Options));
905 MPM.addPass(MemorySanitizerPass(Options));
907 MPM.addPass(createModuleToFunctionPassAdaptor(MemorySanitizerPass(Options)));
911 PipelineStartEPCallbacks.push_back(
912 [Options](ModulePassManager &MPM, OptimizationLevel Level) {
913 MPM.addPass(MemorySanitizerPass(Options));
916 OptimizerLastEPCallbacks.push_back(
917 [Options](FunctionPassManager &FPM, OptimizationLevel Level) {
918 FPM.addPass(MemorySanitizerPass(Options));
924 if (SanitizerOptions->SanitizeThread) {
925 #if LLVM_VERSION_GE(11, 0)
926 OptimizerLastEPCallbacks.push_back(
927 [](ModulePassManager &MPM, OptimizationLevel Level) {
928 #if LLVM_VERSION_GE(14, 0)
929 MPM.addPass(ModuleThreadSanitizerPass());
931 MPM.addPass(ThreadSanitizerPass());
933 MPM.addPass(createModuleToFunctionPassAdaptor(ThreadSanitizerPass()));
937 PipelineStartEPCallbacks.push_back(
938 [](ModulePassManager &MPM, OptimizationLevel Level) {
939 MPM.addPass(ThreadSanitizerPass());
942 OptimizerLastEPCallbacks.push_back(
943 [](FunctionPassManager &FPM, OptimizationLevel Level) {
944 FPM.addPass(ThreadSanitizerPass());
950 if (SanitizerOptions->SanitizeAddress) {
951 #if LLVM_VERSION_GE(11, 0)
952 OptimizerLastEPCallbacks.push_back(
953 [SanitizerOptions](ModulePassManager &MPM, OptimizationLevel Level) {
954 MPM.addPass(RequireAnalysisPass<ASanGlobalsMetadataAnalysis, Module>());
955 MPM.addPass(ModuleAddressSanitizerPass(
956 /*CompileKernel=*/false, SanitizerOptions->SanitizeAddressRecover));
957 #if LLVM_VERSION_GE(14, 0)
958 AddressSanitizerOptions opts(/*CompileKernel=*/false,
959 SanitizerOptions->SanitizeAddressRecover,
960 /*UseAfterScope=*/true,
961 AsanDetectStackUseAfterReturnMode::Runtime);
962 MPM.addPass(createModuleToFunctionPassAdaptor(AddressSanitizerPass(opts)));
964 MPM.addPass(createModuleToFunctionPassAdaptor(AddressSanitizerPass(
965 /*CompileKernel=*/false, SanitizerOptions->SanitizeAddressRecover,
966 /*UseAfterScope=*/true)));
971 PipelineStartEPCallbacks.push_back(
972 [&](ModulePassManager &MPM, OptimizationLevel Level) {
973 MPM.addPass(RequireAnalysisPass<ASanGlobalsMetadataAnalysis, Module>());
976 OptimizerLastEPCallbacks.push_back(
977 [SanitizerOptions](FunctionPassManager &FPM, OptimizationLevel Level) {
978 FPM.addPass(AddressSanitizerPass(
979 /*CompileKernel=*/false, SanitizerOptions->SanitizeAddressRecover,
980 /*UseAfterScope=*/true));
983 PipelineStartEPCallbacks.push_back(
984 [SanitizerOptions](ModulePassManager &MPM, OptimizationLevel Level) {
985 MPM.addPass(ModuleAddressSanitizerPass(
986 /*CompileKernel=*/false, SanitizerOptions->SanitizeAddressRecover));
991 if (SanitizerOptions->SanitizeHWAddress) {
992 #if LLVM_VERSION_GE(11, 0)
993 OptimizerLastEPCallbacks.push_back(
994 [SanitizerOptions](ModulePassManager &MPM, OptimizationLevel Level) {
995 #if LLVM_VERSION_GE(14, 0)
996 HWAddressSanitizerOptions opts(
997 /*CompileKernel=*/false, SanitizerOptions->SanitizeHWAddressRecover,
998 /*DisableOptimization=*/false);
999 MPM.addPass(HWAddressSanitizerPass(opts));
1001 MPM.addPass(HWAddressSanitizerPass(
1002 /*CompileKernel=*/false, SanitizerOptions->SanitizeHWAddressRecover));
1007 PipelineStartEPCallbacks.push_back(
1008 [SanitizerOptions](ModulePassManager &MPM, OptimizationLevel Level) {
1009 MPM.addPass(HWAddressSanitizerPass(
1010 /*CompileKernel=*/false, SanitizerOptions->SanitizeHWAddressRecover));
1017 #if LLVM_VERSION_GE(13, 0)
1018 ModulePassManager MPM;
1020 ModulePassManager MPM(DebugPassManager);
1022 bool NeedThinLTOBufferPasses = UseThinLTOBuffers;
1023 if (!NoPrepopulatePasses) {
1024 // The pre-link pipelines don't support O0 and require using budilO0DefaultPipeline() instead.
1025 // At the same time, the LTO pipelines do support O0 and using them is required.
1026 bool IsLTO = OptStage == LLVMRustOptStage::ThinLTO || OptStage == LLVMRustOptStage::FatLTO;
1027 if (OptLevel == OptimizationLevel::O0 && !IsLTO) {
1028 #if LLVM_VERSION_GE(12, 0)
1029 for (const auto &C : PipelineStartEPCallbacks)
1030 PB.registerPipelineStartEPCallback(C);
1031 for (const auto &C : OptimizerLastEPCallbacks)
1032 PB.registerOptimizerLastEPCallback(C);
1034 // Pass false as we manually schedule ThinLTOBufferPasses below.
1035 MPM = PB.buildO0DefaultPipeline(OptLevel, /* PreLinkLTO */ false);
1037 for (const auto &C : PipelineStartEPCallbacks)
1040 # if LLVM_VERSION_GE(11, 0)
1041 for (const auto &C : OptimizerLastEPCallbacks)
1044 if (!OptimizerLastEPCallbacks.empty()) {
1045 FunctionPassManager FPM(DebugPassManager);
1046 for (const auto &C : OptimizerLastEPCallbacks)
1048 MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
1052 MPM.addPass(AlwaysInlinerPass(EmitLifetimeMarkers));
1055 PB.addPGOInstrPassesForO0(
1056 MPM, DebugPassManager, PGOOpt->Action == PGOOptions::IRInstr,
1057 /*IsCS=*/false, PGOOpt->ProfileFile, PGOOpt->ProfileRemappingFile);
1061 #if LLVM_VERSION_GE(12, 0)
1062 for (const auto &C : PipelineStartEPCallbacks)
1063 PB.registerPipelineStartEPCallback(C);
1065 for (const auto &C : PipelineStartEPCallbacks)
1066 PB.registerPipelineStartEPCallback([C, OptLevel](ModulePassManager &MPM) {
1070 if (OptStage != LLVMRustOptStage::PreLinkThinLTO) {
1071 for (const auto &C : OptimizerLastEPCallbacks)
1072 PB.registerOptimizerLastEPCallback(C);
1076 case LLVMRustOptStage::PreLinkNoLTO:
1077 MPM = PB.buildPerModuleDefaultPipeline(OptLevel, DebugPassManager);
1079 case LLVMRustOptStage::PreLinkThinLTO:
1080 #if LLVM_VERSION_GE(12, 0)
1081 MPM = PB.buildThinLTOPreLinkDefaultPipeline(OptLevel);
1082 // The ThinLTOPreLink pipeline already includes ThinLTOBuffer passes. However, callback
1083 // passes may still run afterwards. This means we need to run the buffer passes again.
1084 // FIXME: In LLVM 13, the ThinLTOPreLink pipeline also runs OptimizerLastEPCallbacks
1085 // before the RequiredLTOPreLinkPasses, in which case we can remove these hacks.
1086 if (OptimizerLastEPCallbacks.empty())
1087 NeedThinLTOBufferPasses = false;
1089 MPM = PB.buildThinLTOPreLinkDefaultPipeline(OptLevel, DebugPassManager);
1091 #if LLVM_VERSION_GE(11, 0)
1092 for (const auto &C : OptimizerLastEPCallbacks)
1095 if (!OptimizerLastEPCallbacks.empty()) {
1096 FunctionPassManager FPM(DebugPassManager);
1097 for (const auto &C : OptimizerLastEPCallbacks)
1099 MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
1103 case LLVMRustOptStage::PreLinkFatLTO:
1104 #if LLVM_VERSION_GE(12, 0)
1105 MPM = PB.buildLTOPreLinkDefaultPipeline(OptLevel);
1106 NeedThinLTOBufferPasses = false;
1108 MPM = PB.buildLTOPreLinkDefaultPipeline(OptLevel, DebugPassManager);
1111 case LLVMRustOptStage::ThinLTO:
1112 // FIXME: Does it make sense to pass the ModuleSummaryIndex?
1113 // It only seems to be needed for C++ specific optimizations.
1114 #if LLVM_VERSION_GE(12, 0)
1115 MPM = PB.buildThinLTODefaultPipeline(OptLevel, nullptr);
1117 MPM = PB.buildThinLTODefaultPipeline(OptLevel, DebugPassManager, nullptr);
1120 case LLVMRustOptStage::FatLTO:
1121 #if LLVM_VERSION_GE(12, 0)
1122 MPM = PB.buildLTODefaultPipeline(OptLevel, nullptr);
1124 MPM = PB.buildLTODefaultPipeline(OptLevel, DebugPassManager, nullptr);
1131 if (ExtraPassesLen) {
1132 if (auto Err = PB.parsePassPipeline(MPM, StringRef(ExtraPasses, ExtraPassesLen))) {
1133 std::string ErrMsg = toString(std::move(Err));
1134 LLVMRustSetLastError(ErrMsg.c_str());
1135 return LLVMRustResult::Failure;
1139 if (NeedThinLTOBufferPasses) {
1140 MPM.addPass(CanonicalizeAliasesPass());
1141 MPM.addPass(NameAnonGlobalPass());
1144 // Upgrade all calls to old intrinsics first.
1145 for (Module::iterator I = TheModule->begin(), E = TheModule->end(); I != E;)
1146 UpgradeCallsToIntrinsic(&*I++); // must be post-increment, as we remove
1148 MPM.run(*TheModule, MAM);
1149 return LLVMRustResult::Success;
1152 // Callback to demangle function name
1154 // * name to be demangled
1157 // * output buffer len
1158 // Returns len of demangled string, or 0 if demangle failed.
1159 typedef size_t (*DemangleFn)(const char*, size_t, char*, size_t);
1164 class RustAssemblyAnnotationWriter : public AssemblyAnnotationWriter {
1165 DemangleFn Demangle;
1166 std::vector<char> Buf;
1169 RustAssemblyAnnotationWriter(DemangleFn Demangle) : Demangle(Demangle) {}
1171 // Return empty string if demangle failed
1172 // or if name does not need to be demangled
1173 StringRef CallDemangle(StringRef name) {
1178 if (Buf.size() < name.size() * 2) {
1179 // Semangled name usually shorter than mangled,
1180 // but allocate twice as much memory just in case
1181 Buf.resize(name.size() * 2);
1184 auto R = Demangle(name.data(), name.size(), Buf.data(), Buf.size());
1190 auto Demangled = StringRef(Buf.data(), R);
1191 if (Demangled == name) {
1192 // Do not print anything if demangled name is equal to mangled.
1199 void emitFunctionAnnot(const Function *F,
1200 formatted_raw_ostream &OS) override {
1201 StringRef Demangled = CallDemangle(F->getName());
1202 if (Demangled.empty()) {
1206 OS << "; " << Demangled << "\n";
1209 void emitInstructionAnnot(const Instruction *I,
1210 formatted_raw_ostream &OS) override {
1213 if (const CallInst *CI = dyn_cast<CallInst>(I)) {
1215 Value = CI->getCalledOperand();
1216 } else if (const InvokeInst* II = dyn_cast<InvokeInst>(I)) {
1218 Value = II->getCalledOperand();
1220 // Could demangle more operations, e. g.
1221 // `store %place, @function`.
1225 if (!Value->hasName()) {
1229 StringRef Demangled = CallDemangle(Value->getName());
1230 if (Demangled.empty()) {
1234 OS << "; " << Name << " " << Demangled << "\n";
1240 extern "C" LLVMRustResult
1241 LLVMRustPrintModule(LLVMModuleRef M, const char *Path, DemangleFn Demangle) {
1242 std::string ErrorInfo;
1244 raw_fd_ostream OS(Path, EC, sys::fs::OF_None);
1246 ErrorInfo = EC.message();
1247 if (ErrorInfo != "") {
1248 LLVMRustSetLastError(ErrorInfo.c_str());
1249 return LLVMRustResult::Failure;
1252 RustAssemblyAnnotationWriter AAW(Demangle);
1253 formatted_raw_ostream FOS(OS);
1254 unwrap(M)->print(FOS, &AAW);
1256 return LLVMRustResult::Success;
1259 extern "C" void LLVMRustPrintPasses() {
1260 LLVMInitializePasses();
1261 struct MyListener : PassRegistrationListener {
1262 void passEnumerate(const PassInfo *Info) {
1263 StringRef PassArg = Info->getPassArgument();
1264 StringRef PassName = Info->getPassName();
1265 if (!PassArg.empty()) {
1266 // These unsigned->signed casts could theoretically overflow, but
1267 // realistically never will (and even if, the result is implementation
1268 // defined rather plain UB).
1269 printf("%15.*s - %.*s\n", (int)PassArg.size(), PassArg.data(),
1270 (int)PassName.size(), PassName.data());
1275 PassRegistry *PR = PassRegistry::getPassRegistry();
1276 PR->enumerateWith(&Listener);
1279 extern "C" void LLVMRustAddAlwaysInlinePass(LLVMPassManagerBuilderRef PMBR,
1280 bool AddLifetimes) {
1281 unwrap(PMBR)->Inliner = llvm::createAlwaysInlinerLegacyPass(AddLifetimes);
1284 extern "C" void LLVMRustRunRestrictionPass(LLVMModuleRef M, char **Symbols,
1286 llvm::legacy::PassManager passes;
1288 auto PreserveFunctions = [=](const GlobalValue &GV) {
1289 for (size_t I = 0; I < Len; I++) {
1290 if (GV.getName() == Symbols[I]) {
1297 passes.add(llvm::createInternalizePass(PreserveFunctions));
1299 passes.run(*unwrap(M));
1302 extern "C" void LLVMRustMarkAllFunctionsNounwind(LLVMModuleRef M) {
1303 for (Module::iterator GV = unwrap(M)->begin(), E = unwrap(M)->end(); GV != E;
1305 GV->setDoesNotThrow();
1306 Function *F = dyn_cast<Function>(GV);
1310 for (Function::iterator B = F->begin(), BE = F->end(); B != BE; ++B) {
1311 for (BasicBlock::iterator I = B->begin(), IE = B->end(); I != IE; ++I) {
1312 if (isa<InvokeInst>(I)) {
1313 InvokeInst *CI = cast<InvokeInst>(I);
1314 CI->setDoesNotThrow();
1322 LLVMRustSetDataLayoutFromTargetMachine(LLVMModuleRef Module,
1323 LLVMTargetMachineRef TMR) {
1324 TargetMachine *Target = unwrap(TMR);
1325 unwrap(Module)->setDataLayout(Target->createDataLayout());
1328 extern "C" void LLVMRustSetModulePICLevel(LLVMModuleRef M) {
1329 unwrap(M)->setPICLevel(PICLevel::Level::BigPIC);
1332 extern "C" void LLVMRustSetModulePIELevel(LLVMModuleRef M) {
1333 unwrap(M)->setPIELevel(PIELevel::Level::Large);
1336 extern "C" void LLVMRustSetModuleCodeModel(LLVMModuleRef M,
1337 LLVMRustCodeModel Model) {
1338 auto CM = fromRust(Model);
1341 unwrap(M)->setCodeModel(*CM);
1344 // Here you'll find an implementation of ThinLTO as used by the Rust compiler
1345 // right now. This ThinLTO support is only enabled on "recent ish" versions of
1346 // LLVM, and otherwise it's just blanket rejected from other compilers.
1348 // Most of this implementation is straight copied from LLVM. At the time of
1349 // this writing it wasn't *quite* suitable to reuse more code from upstream
1350 // for our purposes, but we should strive to upstream this support once it's
1351 // ready to go! I figure we may want a bit of testing locally first before
1352 // sending this upstream to LLVM. I hear though they're quite eager to receive
1353 // feedback like this!
1355 // If you're reading this code and wondering "what in the world" or you're
1356 // working "good lord by LLVM upgrade is *still* failing due to these bindings"
1357 // then fear not! (ok maybe fear a little). All code here is mostly based
1358 // on `lib/LTO/ThinLTOCodeGenerator.cpp` in LLVM.
1360 // You'll find that the general layout here roughly corresponds to the `run`
1361 // method in that file as well as `ProcessThinLTOModule`. Functions are
1362 // specifically commented below as well, but if you're updating this code
1363 // or otherwise trying to understand it, the LLVM source will be useful in
1364 // interpreting the mysteries within.
1366 // Otherwise I'll apologize in advance, it probably requires a relatively
1367 // significant investment on your part to "truly understand" what's going on
1368 // here. Not saying I do myself, but it took me awhile staring at LLVM's source
1369 // and various online resources about ThinLTO to make heads or tails of all
1372 // This is a shared data structure which *must* be threadsafe to share
1373 // read-only amongst threads. This also corresponds basically to the arguments
1374 // of the `ProcessThinLTOModule` function in the LLVM source.
1375 struct LLVMRustThinLTOData {
1376 // The combined index that is the global analysis over all modules we're
1377 // performing ThinLTO for. This is mostly managed by LLVM.
1378 ModuleSummaryIndex Index;
1380 // All modules we may look at, stored as in-memory serialized versions. This
1381 // is later used when inlining to ensure we can extract any module to inline
1383 StringMap<MemoryBufferRef> ModuleMap;
1385 // A set that we manage of everything we *don't* want internalized. Note that
1386 // this includes all transitive references right now as well, but it may not
1388 DenseSet<GlobalValue::GUID> GUIDPreservedSymbols;
1390 // Not 100% sure what these are, but they impact what's internalized and
1391 // what's inlined across modules, I believe.
1392 StringMap<FunctionImporter::ImportMapTy> ImportLists;
1393 StringMap<FunctionImporter::ExportSetTy> ExportLists;
1394 StringMap<GVSummaryMapTy> ModuleToDefinedGVSummaries;
1395 StringMap<std::map<GlobalValue::GUID, GlobalValue::LinkageTypes>> ResolvedODR;
1397 LLVMRustThinLTOData() : Index(/* HaveGVs = */ false) {}
1400 // Just an argument to the `LLVMRustCreateThinLTOData` function below.
1401 struct LLVMRustThinLTOModule {
1402 const char *identifier;
1407 // This is copied from `lib/LTO/ThinLTOCodeGenerator.cpp`, not sure what it
1409 static const GlobalValueSummary *
1410 getFirstDefinitionForLinker(const GlobalValueSummaryList &GVSummaryList) {
1411 auto StrongDefForLinker = llvm::find_if(
1412 GVSummaryList, [](const std::unique_ptr<GlobalValueSummary> &Summary) {
1413 auto Linkage = Summary->linkage();
1414 return !GlobalValue::isAvailableExternallyLinkage(Linkage) &&
1415 !GlobalValue::isWeakForLinker(Linkage);
1417 if (StrongDefForLinker != GVSummaryList.end())
1418 return StrongDefForLinker->get();
1420 auto FirstDefForLinker = llvm::find_if(
1421 GVSummaryList, [](const std::unique_ptr<GlobalValueSummary> &Summary) {
1422 auto Linkage = Summary->linkage();
1423 return !GlobalValue::isAvailableExternallyLinkage(Linkage);
1425 if (FirstDefForLinker == GVSummaryList.end())
1427 return FirstDefForLinker->get();
1430 // The main entry point for creating the global ThinLTO analysis. The structure
1431 // here is basically the same as before threads are spawned in the `run`
1432 // function of `lib/LTO/ThinLTOCodeGenerator.cpp`.
1433 extern "C" LLVMRustThinLTOData*
1434 LLVMRustCreateThinLTOData(LLVMRustThinLTOModule *modules,
1436 const char **preserved_symbols,
1438 auto Ret = std::make_unique<LLVMRustThinLTOData>();
1440 // Load each module's summary and merge it into one combined index
1441 for (int i = 0; i < num_modules; i++) {
1442 auto module = &modules[i];
1443 StringRef buffer(module->data, module->len);
1444 MemoryBufferRef mem_buffer(buffer, module->identifier);
1446 Ret->ModuleMap[module->identifier] = mem_buffer;
1448 if (Error Err = readModuleSummaryIndex(mem_buffer, Ret->Index, i)) {
1449 LLVMRustSetLastError(toString(std::move(Err)).c_str());
1454 // Collect for each module the list of function it defines (GUID -> Summary)
1455 Ret->Index.collectDefinedGVSummariesPerModule(Ret->ModuleToDefinedGVSummaries);
1457 // Convert the preserved symbols set from string to GUID, this is then needed
1458 // for internalization.
1459 for (int i = 0; i < num_symbols; i++) {
1460 auto GUID = GlobalValue::getGUID(preserved_symbols[i]);
1461 Ret->GUIDPreservedSymbols.insert(GUID);
1464 // Collect the import/export lists for all modules from the call-graph in the
1467 // This is copied from `lib/LTO/ThinLTOCodeGenerator.cpp`
1468 auto deadIsPrevailing = [&](GlobalValue::GUID G) {
1469 return PrevailingType::Unknown;
1471 // We don't have a complete picture in our use of ThinLTO, just our immediate
1472 // crate, so we need `ImportEnabled = false` to limit internalization.
1473 // Otherwise, we sometimes lose `static` values -- see #60184.
1474 computeDeadSymbolsWithConstProp(Ret->Index, Ret->GUIDPreservedSymbols,
1475 deadIsPrevailing, /* ImportEnabled = */ false);
1476 ComputeCrossModuleImport(
1478 Ret->ModuleToDefinedGVSummaries,
1483 // Resolve LinkOnce/Weak symbols, this has to be computed early be cause it
1484 // impacts the caching.
1486 // This is copied from `lib/LTO/ThinLTOCodeGenerator.cpp` with some of this
1487 // being lifted from `lib/LTO/LTO.cpp` as well
1488 DenseMap<GlobalValue::GUID, const GlobalValueSummary *> PrevailingCopy;
1489 for (auto &I : Ret->Index) {
1490 if (I.second.SummaryList.size() > 1)
1491 PrevailingCopy[I.first] = getFirstDefinitionForLinker(I.second.SummaryList);
1493 auto isPrevailing = [&](GlobalValue::GUID GUID, const GlobalValueSummary *S) {
1494 const auto &Prevailing = PrevailingCopy.find(GUID);
1495 if (Prevailing == PrevailingCopy.end())
1497 return Prevailing->second == S;
1499 auto recordNewLinkage = [&](StringRef ModuleIdentifier,
1500 GlobalValue::GUID GUID,
1501 GlobalValue::LinkageTypes NewLinkage) {
1502 Ret->ResolvedODR[ModuleIdentifier][GUID] = NewLinkage;
1505 #if LLVM_VERSION_GE(13,0)
1506 // Uses FromPrevailing visibility scheme which works for many binary
1507 // formats. We probably could and should use ELF visibility scheme for many of
1508 // our targets, however.
1510 thinLTOResolvePrevailingInIndex(conf, Ret->Index, isPrevailing, recordNewLinkage,
1511 Ret->GUIDPreservedSymbols);
1513 thinLTOResolvePrevailingInIndex(Ret->Index, isPrevailing, recordNewLinkage,
1514 Ret->GUIDPreservedSymbols);
1516 // Here we calculate an `ExportedGUIDs` set for use in the `isExported`
1517 // callback below. This callback below will dictate the linkage for all
1518 // summaries in the index, and we basically just only want to ensure that dead
1519 // symbols are internalized. Otherwise everything that's already external
1520 // linkage will stay as external, and internal will stay as internal.
1521 std::set<GlobalValue::GUID> ExportedGUIDs;
1522 for (auto &List : Ret->Index) {
1523 for (auto &GVS: List.second.SummaryList) {
1524 if (GlobalValue::isLocalLinkage(GVS->linkage()))
1526 auto GUID = GVS->getOriginalName();
1527 if (GVS->flags().Live)
1528 ExportedGUIDs.insert(GUID);
1531 auto isExported = [&](StringRef ModuleIdentifier, ValueInfo VI) {
1532 const auto &ExportList = Ret->ExportLists.find(ModuleIdentifier);
1533 return (ExportList != Ret->ExportLists.end() &&
1534 ExportList->second.count(VI)) ||
1535 ExportedGUIDs.count(VI.getGUID());
1537 thinLTOInternalizeAndPromoteInIndex(Ret->Index, isExported, isPrevailing);
1539 return Ret.release();
1543 LLVMRustFreeThinLTOData(LLVMRustThinLTOData *Data) {
1547 // Below are the various passes that happen *per module* when doing ThinLTO.
1549 // In other words, these are the functions that are all run concurrently
1550 // with one another, one per module. The passes here correspond to the analysis
1551 // passes in `lib/LTO/ThinLTOCodeGenerator.cpp`, currently found in the
1552 // `ProcessThinLTOModule` function. Here they're split up into separate steps
1553 // so rustc can save off the intermediate bytecode between each step.
1555 #if LLVM_VERSION_GE(11, 0)
1557 clearDSOLocalOnDeclarations(Module &Mod, TargetMachine &TM) {
1558 // When linking an ELF shared object, dso_local should be dropped. We
1559 // conservatively do this for -fpic.
1560 bool ClearDSOLocalOnDeclarations =
1561 TM.getTargetTriple().isOSBinFormatELF() &&
1562 TM.getRelocationModel() != Reloc::Static &&
1563 Mod.getPIELevel() == PIELevel::Default;
1564 return ClearDSOLocalOnDeclarations;
1569 LLVMRustPrepareThinLTORename(const LLVMRustThinLTOData *Data, LLVMModuleRef M,
1570 LLVMTargetMachineRef TM) {
1571 Module &Mod = *unwrap(M);
1572 TargetMachine &Target = *unwrap(TM);
1574 #if LLVM_VERSION_GE(11, 0)
1575 bool ClearDSOLocal = clearDSOLocalOnDeclarations(Mod, Target);
1576 bool error = renameModuleForThinLTO(Mod, Data->Index, ClearDSOLocal);
1578 bool error = renameModuleForThinLTO(Mod, Data->Index);
1582 LLVMRustSetLastError("renameModuleForThinLTO failed");
1589 LLVMRustPrepareThinLTOResolveWeak(const LLVMRustThinLTOData *Data, LLVMModuleRef M) {
1590 Module &Mod = *unwrap(M);
1591 const auto &DefinedGlobals = Data->ModuleToDefinedGVSummaries.lookup(Mod.getModuleIdentifier());
1592 #if LLVM_VERSION_GE(14, 0)
1593 thinLTOFinalizeInModule(Mod, DefinedGlobals, /*PropagateAttrs=*/true);
1595 thinLTOResolvePrevailingInModule(Mod, DefinedGlobals);
1601 LLVMRustPrepareThinLTOInternalize(const LLVMRustThinLTOData *Data, LLVMModuleRef M) {
1602 Module &Mod = *unwrap(M);
1603 const auto &DefinedGlobals = Data->ModuleToDefinedGVSummaries.lookup(Mod.getModuleIdentifier());
1604 thinLTOInternalizeModule(Mod, DefinedGlobals);
1609 LLVMRustPrepareThinLTOImport(const LLVMRustThinLTOData *Data, LLVMModuleRef M,
1610 LLVMTargetMachineRef TM) {
1611 Module &Mod = *unwrap(M);
1612 TargetMachine &Target = *unwrap(TM);
1614 const auto &ImportList = Data->ImportLists.lookup(Mod.getModuleIdentifier());
1615 auto Loader = [&](StringRef Identifier) {
1616 const auto &Memory = Data->ModuleMap.lookup(Identifier);
1617 auto &Context = Mod.getContext();
1618 auto MOrErr = getLazyBitcodeModule(Memory, Context, true, true);
1623 // The rest of this closure is a workaround for
1624 // https://bugs.llvm.org/show_bug.cgi?id=38184 where during ThinLTO imports
1625 // we accidentally import wasm custom sections into different modules,
1626 // duplicating them by in the final output artifact.
1628 // The issue is worked around here by manually removing the
1629 // `wasm.custom_sections` named metadata node from any imported module. This
1630 // we know isn't used by any optimization pass so there's no need for it to
1633 // Note that the metadata is currently lazily loaded, so we materialize it
1634 // here before looking up if there's metadata inside. The `FunctionImporter`
1635 // will immediately materialize metadata anyway after an import, so this
1636 // shouldn't be a perf hit.
1637 if (Error Err = (*MOrErr)->materializeMetadata()) {
1638 Expected<std::unique_ptr<Module>> Ret(std::move(Err));
1642 auto *WasmCustomSections = (*MOrErr)->getNamedMetadata("wasm.custom_sections");
1643 if (WasmCustomSections)
1644 WasmCustomSections->eraseFromParent();
1648 #if LLVM_VERSION_GE(11, 0)
1649 bool ClearDSOLocal = clearDSOLocalOnDeclarations(Mod, Target);
1650 FunctionImporter Importer(Data->Index, Loader, ClearDSOLocal);
1652 FunctionImporter Importer(Data->Index, Loader);
1654 Expected<bool> Result = Importer.importFunctions(Mod, ImportList);
1656 LLVMRustSetLastError(toString(Result.takeError()).c_str());
1662 extern "C" typedef void (*LLVMRustModuleNameCallback)(void*, // payload
1663 const char*, // importing module name
1664 const char*); // imported module name
1666 // Calls `module_name_callback` for each module import done by ThinLTO.
1667 // The callback is provided with regular null-terminated C strings.
1669 LLVMRustGetThinLTOModules(const LLVMRustThinLTOData *data,
1670 LLVMRustModuleNameCallback module_name_callback,
1671 void* callback_payload) {
1672 for (const auto& importing_module : data->ImportLists) {
1673 const std::string importing_module_id = importing_module.getKey().str();
1674 const auto& imports = importing_module.getValue();
1675 for (const auto& imported_module : imports) {
1676 const std::string imported_module_id = imported_module.getKey().str();
1677 module_name_callback(callback_payload,
1678 importing_module_id.c_str(),
1679 imported_module_id.c_str());
1684 // This struct and various functions are sort of a hack right now, but the
1685 // problem is that we've got in-memory LLVM modules after we generate and
1686 // optimize all codegen-units for one compilation in rustc. To be compatible
1687 // with the LTO support above we need to serialize the modules plus their
1688 // ThinLTO summary into memory.
1690 // This structure is basically an owned version of a serialize module, with
1691 // a ThinLTO summary attached.
1692 struct LLVMRustThinLTOBuffer {
1696 extern "C" LLVMRustThinLTOBuffer*
1697 LLVMRustThinLTOBufferCreate(LLVMModuleRef M) {
1698 auto Ret = std::make_unique<LLVMRustThinLTOBuffer>();
1700 raw_string_ostream OS(Ret->data);
1702 legacy::PassManager PM;
1703 PM.add(createWriteThinLTOBitcodePass(OS));
1707 return Ret.release();
1711 LLVMRustThinLTOBufferFree(LLVMRustThinLTOBuffer *Buffer) {
1715 extern "C" const void*
1716 LLVMRustThinLTOBufferPtr(const LLVMRustThinLTOBuffer *Buffer) {
1717 return Buffer->data.data();
1721 LLVMRustThinLTOBufferLen(const LLVMRustThinLTOBuffer *Buffer) {
1722 return Buffer->data.length();
1725 // This is what we used to parse upstream bitcode for actual ThinLTO
1726 // processing. We'll call this once per module optimized through ThinLTO, and
1727 // it'll be called concurrently on many threads.
1728 extern "C" LLVMModuleRef
1729 LLVMRustParseBitcodeForLTO(LLVMContextRef Context,
1732 const char *identifier) {
1733 StringRef Data(data, len);
1734 MemoryBufferRef Buffer(Data, identifier);
1735 unwrap(Context)->enableDebugTypeODRUniquing();
1736 Expected<std::unique_ptr<Module>> SrcOrError =
1737 parseBitcodeFile(Buffer, *unwrap(Context));
1739 LLVMRustSetLastError(toString(SrcOrError.takeError()).c_str());
1742 return wrap(std::move(*SrcOrError).release());
1745 // Find the bitcode section in the object file data and return it as a slice.
1746 // Fail if the bitcode section is present but empty.
1748 // On success, the return value is the pointer to the start of the slice and
1749 // `out_len` is filled with the (non-zero) length. On failure, the return value
1750 // is `nullptr` and `out_len` is set to zero.
1751 extern "C" const char*
1752 LLVMRustGetBitcodeSliceFromObjectData(const char *data,
1757 StringRef Data(data, len);
1758 MemoryBufferRef Buffer(Data, ""); // The id is unused.
1760 Expected<MemoryBufferRef> BitcodeOrError =
1761 object::IRObjectFile::findBitcodeInMemBuffer(Buffer);
1762 if (!BitcodeOrError) {
1763 LLVMRustSetLastError(toString(BitcodeOrError.takeError()).c_str());
1767 *out_len = BitcodeOrError->getBufferSize();
1768 return BitcodeOrError->getBufferStart();
1771 // Rewrite all `DICompileUnit` pointers to the `DICompileUnit` specified. See
1772 // the comment in `back/lto.rs` for why this exists.
1774 LLVMRustLTOGetDICompileUnit(LLVMModuleRef Mod,
1776 DICompileUnit **B) {
1777 Module *M = unwrap(Mod);
1778 DICompileUnit **Cur = A;
1779 DICompileUnit **Next = B;
1780 for (DICompileUnit *CU : M->debug_compile_units()) {
1789 // Rewrite all `DICompileUnit` pointers to the `DICompileUnit` specified. See
1790 // the comment in `back/lto.rs` for why this exists.
1792 LLVMRustLTOPatchDICompileUnit(LLVMModuleRef Mod, DICompileUnit *Unit) {
1793 Module *M = unwrap(Mod);
1795 // If the original source module didn't have a `DICompileUnit` then try to
1796 // merge all the existing compile units. If there aren't actually any though
1797 // then there's not much for us to do so return.
1798 if (Unit == nullptr) {
1799 for (DICompileUnit *CU : M->debug_compile_units()) {
1803 if (Unit == nullptr)
1807 // Use LLVM's built-in `DebugInfoFinder` to find a bunch of debuginfo and
1808 // process it recursively. Note that we used to specifically iterate over
1809 // instructions to ensure we feed everything into it, but `processModule`
1810 // started doing this the same way in LLVM 7 (commit d769eb36ab2b8).
1811 DebugInfoFinder Finder;
1812 Finder.processModule(*M);
1814 // After we've found all our debuginfo, rewrite all subprograms to point to
1815 // the same `DICompileUnit`.
1816 for (auto &F : Finder.subprograms()) {
1817 F->replaceUnit(Unit);
1820 // Erase any other references to other `DICompileUnit` instances, the verifier
1821 // will later ensure that we don't actually have any other stale references to
1823 auto *MD = M->getNamedMetadata("llvm.dbg.cu");
1824 MD->clearOperands();
1825 MD->addOperand(Unit);
1828 // Computes the LTO cache key for the provided 'ModId' in the given 'Data',
1829 // storing the result in 'KeyOut'.
1830 // Currently, this cache key is a SHA-1 hash of anything that could affect
1831 // the result of optimizing this module (e.g. module imports, exports, liveness
1832 // of access globals, etc).
1833 // The precise details are determined by LLVM in `computeLTOCacheKey`, which is
1834 // used during the normal linker-plugin incremental thin-LTO process.
1836 LLVMRustComputeLTOCacheKey(RustStringRef KeyOut, const char *ModId, LLVMRustThinLTOData *Data) {
1837 SmallString<40> Key;
1838 llvm::lto::Config conf;
1839 const auto &ImportList = Data->ImportLists.lookup(ModId);
1840 const auto &ExportList = Data->ExportLists.lookup(ModId);
1841 const auto &ResolvedODR = Data->ResolvedODR.lookup(ModId);
1842 const auto &DefinedGlobals = Data->ModuleToDefinedGVSummaries.lookup(ModId);
1843 std::set<GlobalValue::GUID> CfiFunctionDefs;
1844 std::set<GlobalValue::GUID> CfiFunctionDecls;
1846 // Based on the 'InProcessThinBackend' constructor in LLVM
1847 for (auto &Name : Data->Index.cfiFunctionDefs())
1848 CfiFunctionDefs.insert(
1849 GlobalValue::getGUID(GlobalValue::dropLLVMManglingEscape(Name)));
1850 for (auto &Name : Data->Index.cfiFunctionDecls())
1851 CfiFunctionDecls.insert(
1852 GlobalValue::getGUID(GlobalValue::dropLLVMManglingEscape(Name)));
1854 llvm::computeLTOCacheKey(Key, conf, Data->Index, ModId,
1855 ImportList, ExportList, ResolvedODR, DefinedGlobals, CfiFunctionDefs, CfiFunctionDecls
1858 LLVMRustStringWriteImpl(KeyOut, Key.c_str(), Key.size());