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_MIPS
205 #define SUBTARGET_MIPS SUBTARGET(Mips)
207 #define SUBTARGET_MIPS
210 #ifdef LLVM_COMPONENT_POWERPC
211 #define SUBTARGET_PPC SUBTARGET(PPC)
213 #define SUBTARGET_PPC
216 #ifdef LLVM_COMPONENT_SYSTEMZ
217 #define SUBTARGET_SYSTEMZ SUBTARGET(SystemZ)
219 #define SUBTARGET_SYSTEMZ
222 #ifdef LLVM_COMPONENT_MSP430
223 #define SUBTARGET_MSP430 SUBTARGET(MSP430)
225 #define SUBTARGET_MSP430
228 #ifdef LLVM_COMPONENT_RISCV
229 #define SUBTARGET_RISCV SUBTARGET(RISCV)
231 #define SUBTARGET_RISCV
234 #ifdef LLVM_COMPONENT_SPARC
235 #define SUBTARGET_SPARC SUBTARGET(Sparc)
237 #define SUBTARGET_SPARC
240 #ifdef LLVM_COMPONENT_HEXAGON
241 #define SUBTARGET_HEXAGON SUBTARGET(Hexagon)
243 #define SUBTARGET_HEXAGON
246 #define GEN_SUBTARGETS \
259 #define SUBTARGET(x) \
261 extern const SubtargetFeatureKV x##FeatureKV[]; \
262 extern const SubtargetFeatureKV x##SubTypeKV[]; \
268 extern "C" bool LLVMRustHasFeature(LLVMTargetMachineRef TM,
269 const char *Feature) {
270 TargetMachine *Target = unwrap(TM);
271 const MCSubtargetInfo *MCInfo = Target->getMCSubtargetInfo();
272 return MCInfo->checkFeatures(std::string("+") + Feature);
275 enum class LLVMRustCodeModel {
284 static Optional<CodeModel::Model> fromRust(LLVMRustCodeModel Model) {
286 case LLVMRustCodeModel::Tiny:
287 return CodeModel::Tiny;
288 case LLVMRustCodeModel::Small:
289 return CodeModel::Small;
290 case LLVMRustCodeModel::Kernel:
291 return CodeModel::Kernel;
292 case LLVMRustCodeModel::Medium:
293 return CodeModel::Medium;
294 case LLVMRustCodeModel::Large:
295 return CodeModel::Large;
296 case LLVMRustCodeModel::None:
299 report_fatal_error("Bad CodeModel.");
303 enum class LLVMRustCodeGenOptLevel {
310 static CodeGenOpt::Level fromRust(LLVMRustCodeGenOptLevel Level) {
312 case LLVMRustCodeGenOptLevel::None:
313 return CodeGenOpt::None;
314 case LLVMRustCodeGenOptLevel::Less:
315 return CodeGenOpt::Less;
316 case LLVMRustCodeGenOptLevel::Default:
317 return CodeGenOpt::Default;
318 case LLVMRustCodeGenOptLevel::Aggressive:
319 return CodeGenOpt::Aggressive;
321 report_fatal_error("Bad CodeGenOptLevel.");
325 enum class LLVMRustPassBuilderOptLevel {
334 static PassBuilder::OptimizationLevel fromRust(LLVMRustPassBuilderOptLevel Level) {
336 case LLVMRustPassBuilderOptLevel::O0:
337 return PassBuilder::OptimizationLevel::O0;
338 case LLVMRustPassBuilderOptLevel::O1:
339 return PassBuilder::OptimizationLevel::O1;
340 case LLVMRustPassBuilderOptLevel::O2:
341 return PassBuilder::OptimizationLevel::O2;
342 case LLVMRustPassBuilderOptLevel::O3:
343 return PassBuilder::OptimizationLevel::O3;
344 case LLVMRustPassBuilderOptLevel::Os:
345 return PassBuilder::OptimizationLevel::Os;
346 case LLVMRustPassBuilderOptLevel::Oz:
347 return PassBuilder::OptimizationLevel::Oz;
349 report_fatal_error("Bad PassBuilderOptLevel.");
353 enum class LLVMRustRelocModel {
362 static Reloc::Model fromRust(LLVMRustRelocModel RustReloc) {
364 case LLVMRustRelocModel::Static:
365 return Reloc::Static;
366 case LLVMRustRelocModel::PIC:
368 case LLVMRustRelocModel::DynamicNoPic:
369 return Reloc::DynamicNoPIC;
370 case LLVMRustRelocModel::ROPI:
372 case LLVMRustRelocModel::RWPI:
374 case LLVMRustRelocModel::ROPIRWPI:
375 return Reloc::ROPI_RWPI;
377 report_fatal_error("Bad RelocModel.");
381 /// getLongestEntryLength - Return the length of the longest entry in the table.
382 template<typename KV>
383 static size_t getLongestEntryLength(ArrayRef<KV> Table) {
385 for (auto &I : Table)
386 MaxLen = std::max(MaxLen, std::strlen(I.Key));
390 extern "C" void LLVMRustPrintTargetCPUs(LLVMTargetMachineRef TM) {
391 const TargetMachine *Target = unwrap(TM);
392 const MCSubtargetInfo *MCInfo = Target->getMCSubtargetInfo();
393 const Triple::ArchType HostArch = Triple(sys::getProcessTriple()).getArch();
394 const Triple::ArchType TargetArch = Target->getTargetTriple().getArch();
395 const ArrayRef<SubtargetSubTypeKV> CPUTable = MCInfo->getCPUTable();
396 unsigned MaxCPULen = getLongestEntryLength(CPUTable);
398 printf("Available CPUs for this target:\n");
399 if (HostArch == TargetArch) {
400 const StringRef HostCPU = sys::getHostCPUName();
401 printf(" %-*s - Select the CPU of the current host (currently %.*s).\n",
402 MaxCPULen, "native", (int)HostCPU.size(), HostCPU.data());
404 for (auto &CPU : CPUTable)
405 printf(" %-*s\n", MaxCPULen, CPU.Key);
409 extern "C" size_t LLVMRustGetTargetFeaturesCount(LLVMTargetMachineRef TM) {
410 const TargetMachine *Target = unwrap(TM);
411 const MCSubtargetInfo *MCInfo = Target->getMCSubtargetInfo();
412 const ArrayRef<SubtargetFeatureKV> FeatTable = MCInfo->getFeatureTable();
413 return FeatTable.size();
416 extern "C" void LLVMRustGetTargetFeature(LLVMTargetMachineRef TM, size_t Index,
417 const char** Feature, const char** Desc) {
418 const TargetMachine *Target = unwrap(TM);
419 const MCSubtargetInfo *MCInfo = Target->getMCSubtargetInfo();
420 const ArrayRef<SubtargetFeatureKV> FeatTable = MCInfo->getFeatureTable();
421 const SubtargetFeatureKV Feat = FeatTable[Index];
428 extern "C" void LLVMRustPrintTargetCPUs(LLVMTargetMachineRef) {
429 printf("Target CPU help is not supported by this LLVM version.\n\n");
432 extern "C" size_t LLVMRustGetTargetFeaturesCount(LLVMTargetMachineRef) {
436 extern "C" void LLVMRustGetTargetFeature(LLVMTargetMachineRef, const char**, const char**) {}
439 extern "C" const char* LLVMRustGetHostCPUName(size_t *len) {
440 StringRef Name = sys::getHostCPUName();
445 extern "C" LLVMTargetMachineRef LLVMRustCreateTargetMachine(
446 const char *TripleStr, const char *CPU, const char *Feature,
447 const char *ABIStr, LLVMRustCodeModel RustCM, LLVMRustRelocModel RustReloc,
448 LLVMRustCodeGenOptLevel RustOptLevel, bool UseSoftFloat,
449 bool FunctionSections,
451 bool TrapUnreachable,
454 bool EmitStackSizeSection,
455 bool RelaxELFRelocations,
457 const char *SplitDwarfFile) {
459 auto OptLevel = fromRust(RustOptLevel);
460 auto RM = fromRust(RustReloc);
461 auto CM = fromRust(RustCM);
464 Triple Trip(Triple::normalize(TripleStr));
465 const llvm::Target *TheTarget =
466 TargetRegistry::lookupTarget(Trip.getTriple(), Error);
467 if (TheTarget == nullptr) {
468 LLVMRustSetLastError(Error.c_str());
472 TargetOptions Options;
474 Options.FloatABIType = FloatABI::Default;
476 Options.FloatABIType = FloatABI::Soft;
478 Options.DataSections = DataSections;
479 Options.FunctionSections = FunctionSections;
480 Options.MCOptions.AsmVerbose = AsmComments;
481 Options.MCOptions.PreserveAsmComments = AsmComments;
482 Options.MCOptions.ABIName = ABIStr;
483 if (SplitDwarfFile) {
484 Options.MCOptions.SplitDwarfFile = SplitDwarfFile;
486 Options.RelaxELFRelocations = RelaxELFRelocations;
487 Options.UseInitArray = UseInitArray;
489 if (TrapUnreachable) {
490 // Tell LLVM to codegen `unreachable` into an explicit trap instruction.
491 // This limits the extent of possible undefined behavior in some cases, as
492 // it prevents control flow from "falling through" into whatever code
493 // happens to be laid out next in memory.
494 Options.TrapUnreachable = true;
498 Options.ThreadModel = ThreadModel::Single;
501 Options.EmitStackSizeSection = EmitStackSizeSection;
503 TargetMachine *TM = TheTarget->createTargetMachine(
504 Trip.getTriple(), CPU, Feature, Options, RM, CM, OptLevel);
508 extern "C" void LLVMRustDisposeTargetMachine(LLVMTargetMachineRef TM) {
512 extern "C" void LLVMRustConfigurePassManagerBuilder(
513 LLVMPassManagerBuilderRef PMBR, LLVMRustCodeGenOptLevel OptLevel,
514 bool MergeFunctions, bool SLPVectorize, bool LoopVectorize, bool PrepareForThinLTO,
515 const char* PGOGenPath, const char* PGOUsePath) {
516 unwrap(PMBR)->MergeFunctions = MergeFunctions;
517 unwrap(PMBR)->SLPVectorize = SLPVectorize;
518 unwrap(PMBR)->OptLevel = fromRust(OptLevel);
519 unwrap(PMBR)->LoopVectorize = LoopVectorize;
520 unwrap(PMBR)->PrepareForThinLTO = PrepareForThinLTO;
524 unwrap(PMBR)->EnablePGOInstrGen = true;
525 unwrap(PMBR)->PGOInstrGen = PGOGenPath;
529 unwrap(PMBR)->PGOInstrUse = PGOUsePath;
533 // Unfortunately, the LLVM C API doesn't provide a way to set the `LibraryInfo`
534 // field of a PassManagerBuilder, we expose our own method of doing so.
535 extern "C" void LLVMRustAddBuilderLibraryInfo(LLVMPassManagerBuilderRef PMBR,
537 bool DisableSimplifyLibCalls) {
538 Triple TargetTriple(unwrap(M)->getTargetTriple());
539 TargetLibraryInfoImpl *TLI = new TargetLibraryInfoImpl(TargetTriple);
540 if (DisableSimplifyLibCalls)
541 TLI->disableAllFunctions();
542 unwrap(PMBR)->LibraryInfo = TLI;
545 // Unfortunately, the LLVM C API doesn't provide a way to create the
546 // TargetLibraryInfo pass, so we use this method to do so.
547 extern "C" void LLVMRustAddLibraryInfo(LLVMPassManagerRef PMR, LLVMModuleRef M,
548 bool DisableSimplifyLibCalls) {
549 Triple TargetTriple(unwrap(M)->getTargetTriple());
550 TargetLibraryInfoImpl TLII(TargetTriple);
551 if (DisableSimplifyLibCalls)
552 TLII.disableAllFunctions();
553 unwrap(PMR)->add(new TargetLibraryInfoWrapperPass(TLII));
556 // Unfortunately, the LLVM C API doesn't provide an easy way of iterating over
557 // all the functions in a module, so we do that manually here. You'll find
558 // similar code in clang's BackendUtil.cpp file.
559 extern "C" void LLVMRustRunFunctionPassManager(LLVMPassManagerRef PMR,
561 llvm::legacy::FunctionPassManager *P =
562 unwrap<llvm::legacy::FunctionPassManager>(PMR);
563 P->doInitialization();
565 // Upgrade all calls to old intrinsics first.
566 for (Module::iterator I = unwrap(M)->begin(), E = unwrap(M)->end(); I != E;)
567 UpgradeCallsToIntrinsic(&*I++); // must be post-increment, as we remove
569 for (Module::iterator I = unwrap(M)->begin(), E = unwrap(M)->end(); I != E;
571 if (!I->isDeclaration())
577 extern "C" void LLVMRustSetLLVMOptions(int Argc, char **Argv) {
578 // Initializing the command-line options more than once is not allowed. So,
579 // check if they've already been initialized. (This could happen if we're
580 // being called from rustpkg, for example). If the arguments change, then
581 // that's just kinda unfortunate.
582 static bool Initialized = false;
586 cl::ParseCommandLineOptions(Argc, Argv);
589 enum class LLVMRustFileType {
594 static CodeGenFileType fromRust(LLVMRustFileType Type) {
596 case LLVMRustFileType::AssemblyFile:
597 return CGFT_AssemblyFile;
598 case LLVMRustFileType::ObjectFile:
599 return CGFT_ObjectFile;
601 report_fatal_error("Bad FileType.");
605 extern "C" LLVMRustResult
606 LLVMRustWriteOutputFile(LLVMTargetMachineRef Target, LLVMPassManagerRef PMR,
607 LLVMModuleRef M, const char *Path, const char *DwoPath,
608 LLVMRustFileType RustFileType) {
609 llvm::legacy::PassManager *PM = unwrap<llvm::legacy::PassManager>(PMR);
610 auto FileType = fromRust(RustFileType);
612 std::string ErrorInfo;
614 raw_fd_ostream OS(Path, EC, sys::fs::OF_None);
616 ErrorInfo = EC.message();
617 if (ErrorInfo != "") {
618 LLVMRustSetLastError(ErrorInfo.c_str());
619 return LLVMRustResult::Failure;
622 buffer_ostream BOS(OS);
624 raw_fd_ostream DOS(DwoPath, EC, sys::fs::OF_None);
627 ErrorInfo = EC.message();
628 if (ErrorInfo != "") {
629 LLVMRustSetLastError(ErrorInfo.c_str());
630 return LLVMRustResult::Failure;
632 buffer_ostream DBOS(DOS);
633 unwrap(Target)->addPassesToEmitFile(*PM, BOS, &DBOS, FileType, false);
636 unwrap(Target)->addPassesToEmitFile(*PM, BOS, nullptr, FileType, false);
640 // Apparently `addPassesToEmitFile` adds a pointer to our on-the-stack output
641 // stream (OS), so the only real safe place to delete this is here? Don't we
642 // wish this was written in Rust?
643 LLVMDisposePassManager(PMR);
644 return LLVMRustResult::Success;
647 extern "C" typedef void (*LLVMRustSelfProfileBeforePassCallback)(void*, // LlvmSelfProfiler
648 const char*, // pass name
649 const char*); // IR name
650 extern "C" typedef void (*LLVMRustSelfProfileAfterPassCallback)(void*); // LlvmSelfProfiler
652 std::string LLVMRustwrappedIrGetName(const llvm::Any &WrappedIr) {
653 if (any_isa<const Module *>(WrappedIr))
654 return any_cast<const Module *>(WrappedIr)->getName().str();
655 if (any_isa<const Function *>(WrappedIr))
656 return any_cast<const Function *>(WrappedIr)->getName().str();
657 if (any_isa<const Loop *>(WrappedIr))
658 return any_cast<const Loop *>(WrappedIr)->getName().str();
659 if (any_isa<const LazyCallGraph::SCC *>(WrappedIr))
660 return any_cast<const LazyCallGraph::SCC *>(WrappedIr)->getName();
665 void LLVMSelfProfileInitializeCallbacks(
666 PassInstrumentationCallbacks& PIC, void* LlvmSelfProfiler,
667 LLVMRustSelfProfileBeforePassCallback BeforePassCallback,
668 LLVMRustSelfProfileAfterPassCallback AfterPassCallback) {
669 #if LLVM_VERSION_GE(12, 0)
670 PIC.registerBeforeNonSkippedPassCallback([LlvmSelfProfiler, BeforePassCallback](
671 StringRef Pass, llvm::Any Ir) {
672 std::string PassName = Pass.str();
673 std::string IrName = LLVMRustwrappedIrGetName(Ir);
674 BeforePassCallback(LlvmSelfProfiler, PassName.c_str(), IrName.c_str());
677 PIC.registerAfterPassCallback(
678 [LlvmSelfProfiler, AfterPassCallback](StringRef Pass, llvm::Any IR,
679 const PreservedAnalyses &Preserved) {
680 AfterPassCallback(LlvmSelfProfiler);
683 PIC.registerAfterPassInvalidatedCallback(
684 [LlvmSelfProfiler, AfterPassCallback](StringRef Pass, const PreservedAnalyses &Preserved) {
685 AfterPassCallback(LlvmSelfProfiler);
688 PIC.registerBeforePassCallback([LlvmSelfProfiler, BeforePassCallback](
689 StringRef Pass, llvm::Any Ir) {
690 std::string PassName = Pass.str();
691 std::string IrName = LLVMRustwrappedIrGetName(Ir);
692 BeforePassCallback(LlvmSelfProfiler, PassName.c_str(), IrName.c_str());
696 PIC.registerAfterPassCallback(
697 [LlvmSelfProfiler, AfterPassCallback](StringRef Pass, llvm::Any Ir) {
698 AfterPassCallback(LlvmSelfProfiler);
701 PIC.registerAfterPassInvalidatedCallback(
702 [LlvmSelfProfiler, AfterPassCallback](StringRef Pass) {
703 AfterPassCallback(LlvmSelfProfiler);
707 PIC.registerBeforeAnalysisCallback([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());
714 PIC.registerAfterAnalysisCallback(
715 [LlvmSelfProfiler, AfterPassCallback](StringRef Pass, llvm::Any Ir) {
716 AfterPassCallback(LlvmSelfProfiler);
720 enum class LLVMRustOptStage {
728 struct LLVMRustSanitizerOptions {
729 bool SanitizeAddress;
730 bool SanitizeAddressRecover;
732 bool SanitizeMemoryRecover;
733 int SanitizeMemoryTrackOrigins;
735 bool SanitizeHWAddress;
736 bool SanitizeHWAddressRecover;
739 extern "C" LLVMRustResult
740 LLVMRustOptimizeWithNewPassManager(
741 LLVMModuleRef ModuleRef,
742 LLVMTargetMachineRef TMRef,
743 LLVMRustPassBuilderOptLevel OptLevelRust,
744 LLVMRustOptStage OptStage,
745 bool NoPrepopulatePasses, bool VerifyIR, bool UseThinLTOBuffers,
746 bool MergeFunctions, bool UnrollLoops, bool SLPVectorize, bool LoopVectorize,
747 bool DisableSimplifyLibCalls, bool EmitLifetimeMarkers,
748 LLVMRustSanitizerOptions *SanitizerOptions,
749 const char *PGOGenPath, const char *PGOUsePath,
750 bool InstrumentCoverage, bool InstrumentGCOV,
751 void* LlvmSelfProfiler,
752 LLVMRustSelfProfileBeforePassCallback BeforePassCallback,
753 LLVMRustSelfProfileAfterPassCallback AfterPassCallback,
754 const char *ExtraPasses, size_t ExtraPassesLen) {
755 Module *TheModule = unwrap(ModuleRef);
756 TargetMachine *TM = unwrap(TMRef);
757 PassBuilder::OptimizationLevel OptLevel = fromRust(OptLevelRust);
760 PipelineTuningOptions PTO;
761 PTO.LoopUnrolling = UnrollLoops;
762 PTO.LoopInterleaving = UnrollLoops;
763 PTO.LoopVectorization = LoopVectorize;
764 PTO.SLPVectorization = SLPVectorize;
765 #if LLVM_VERSION_GE(12, 0)
766 PTO.MergeFunctions = MergeFunctions;
768 // MergeFunctions is not supported by NewPM in older LLVM versions.
769 (void) MergeFunctions;
772 // FIXME: We may want to expose this as an option.
773 bool DebugPassManager = false;
775 PassInstrumentationCallbacks PIC;
776 #if LLVM_VERSION_GE(12, 0)
777 StandardInstrumentations SI(DebugPassManager);
779 StandardInstrumentations SI;
781 SI.registerCallbacks(PIC);
783 if (LlvmSelfProfiler){
784 LLVMSelfProfileInitializeCallbacks(PIC,LlvmSelfProfiler,BeforePassCallback,AfterPassCallback);
787 Optional<PGOOptions> PGOOpt;
790 PGOOpt = PGOOptions(PGOGenPath, "", "", PGOOptions::IRInstr);
791 } else if (PGOUsePath) {
793 PGOOpt = PGOOptions(PGOUsePath, "", "", PGOOptions::IRUse);
796 #if LLVM_VERSION_GE(12, 0) && !LLVM_VERSION_GE(13,0)
797 PassBuilder PB(DebugPassManager, TM, PTO, PGOOpt, &PIC);
799 PassBuilder PB(TM, PTO, PGOOpt, &PIC);
802 #if LLVM_VERSION_GE(13, 0)
803 LoopAnalysisManager LAM;
804 FunctionAnalysisManager FAM;
805 CGSCCAnalysisManager CGAM;
806 ModuleAnalysisManager MAM;
808 LoopAnalysisManager LAM(DebugPassManager);
809 FunctionAnalysisManager FAM(DebugPassManager);
810 CGSCCAnalysisManager CGAM(DebugPassManager);
811 ModuleAnalysisManager MAM(DebugPassManager);
814 FAM.registerPass([&] { return PB.buildDefaultAAPipeline(); });
816 Triple TargetTriple(TheModule->getTargetTriple());
817 std::unique_ptr<TargetLibraryInfoImpl> TLII(new TargetLibraryInfoImpl(TargetTriple));
818 if (DisableSimplifyLibCalls)
819 TLII->disableAllFunctions();
820 FAM.registerPass([&] { return TargetLibraryAnalysis(*TLII); });
822 PB.registerModuleAnalyses(MAM);
823 PB.registerCGSCCAnalyses(CGAM);
824 PB.registerFunctionAnalyses(FAM);
825 PB.registerLoopAnalyses(LAM);
826 PB.crossRegisterProxies(LAM, FAM, CGAM, MAM);
828 // We manually collect pipeline callbacks so we can apply them at O0, where the
829 // PassBuilder does not create a pipeline.
830 std::vector<std::function<void(ModulePassManager &, PassBuilder::OptimizationLevel)>>
831 PipelineStartEPCallbacks;
832 #if LLVM_VERSION_GE(11, 0)
833 std::vector<std::function<void(ModulePassManager &, PassBuilder::OptimizationLevel)>>
834 OptimizerLastEPCallbacks;
836 std::vector<std::function<void(FunctionPassManager &, PassBuilder::OptimizationLevel)>>
837 OptimizerLastEPCallbacks;
841 PipelineStartEPCallbacks.push_back(
842 [VerifyIR](ModulePassManager &MPM, PassBuilder::OptimizationLevel Level) {
843 MPM.addPass(VerifierPass());
848 if (InstrumentGCOV) {
849 PipelineStartEPCallbacks.push_back(
850 [](ModulePassManager &MPM, PassBuilder::OptimizationLevel Level) {
851 MPM.addPass(GCOVProfilerPass(GCOVOptions::getDefault()));
856 if (InstrumentCoverage) {
857 PipelineStartEPCallbacks.push_back(
858 [](ModulePassManager &MPM, PassBuilder::OptimizationLevel Level) {
859 InstrProfOptions Options;
860 MPM.addPass(InstrProfiling(Options, false));
865 if (SanitizerOptions) {
866 if (SanitizerOptions->SanitizeMemory) {
867 MemorySanitizerOptions Options(
868 SanitizerOptions->SanitizeMemoryTrackOrigins,
869 SanitizerOptions->SanitizeMemoryRecover,
870 /*CompileKernel=*/false);
871 #if LLVM_VERSION_GE(11, 0)
872 OptimizerLastEPCallbacks.push_back(
873 [Options](ModulePassManager &MPM, PassBuilder::OptimizationLevel Level) {
874 MPM.addPass(MemorySanitizerPass(Options));
875 MPM.addPass(createModuleToFunctionPassAdaptor(MemorySanitizerPass(Options)));
879 PipelineStartEPCallbacks.push_back(
880 [Options](ModulePassManager &MPM, PassBuilder::OptimizationLevel Level) {
881 MPM.addPass(MemorySanitizerPass(Options));
884 OptimizerLastEPCallbacks.push_back(
885 [Options](FunctionPassManager &FPM, PassBuilder::OptimizationLevel Level) {
886 FPM.addPass(MemorySanitizerPass(Options));
892 if (SanitizerOptions->SanitizeThread) {
893 #if LLVM_VERSION_GE(11, 0)
894 OptimizerLastEPCallbacks.push_back(
895 [](ModulePassManager &MPM, PassBuilder::OptimizationLevel Level) {
896 MPM.addPass(ThreadSanitizerPass());
897 MPM.addPass(createModuleToFunctionPassAdaptor(ThreadSanitizerPass()));
901 PipelineStartEPCallbacks.push_back(
902 [](ModulePassManager &MPM, PassBuilder::OptimizationLevel Level) {
903 MPM.addPass(ThreadSanitizerPass());
906 OptimizerLastEPCallbacks.push_back(
907 [](FunctionPassManager &FPM, PassBuilder::OptimizationLevel Level) {
908 FPM.addPass(ThreadSanitizerPass());
914 if (SanitizerOptions->SanitizeAddress) {
915 #if LLVM_VERSION_GE(11, 0)
916 OptimizerLastEPCallbacks.push_back(
917 [SanitizerOptions](ModulePassManager &MPM, PassBuilder::OptimizationLevel Level) {
918 MPM.addPass(RequireAnalysisPass<ASanGlobalsMetadataAnalysis, Module>());
919 MPM.addPass(ModuleAddressSanitizerPass(
920 /*CompileKernel=*/false, SanitizerOptions->SanitizeAddressRecover));
921 MPM.addPass(createModuleToFunctionPassAdaptor(AddressSanitizerPass(
922 /*CompileKernel=*/false, SanitizerOptions->SanitizeAddressRecover,
923 /*UseAfterScope=*/true)));
927 PipelineStartEPCallbacks.push_back(
928 [&](ModulePassManager &MPM, PassBuilder::OptimizationLevel Level) {
929 MPM.addPass(RequireAnalysisPass<ASanGlobalsMetadataAnalysis, Module>());
932 OptimizerLastEPCallbacks.push_back(
933 [SanitizerOptions](FunctionPassManager &FPM, PassBuilder::OptimizationLevel Level) {
934 FPM.addPass(AddressSanitizerPass(
935 /*CompileKernel=*/false, SanitizerOptions->SanitizeAddressRecover,
936 /*UseAfterScope=*/true));
939 PipelineStartEPCallbacks.push_back(
940 [SanitizerOptions](ModulePassManager &MPM, PassBuilder::OptimizationLevel Level) {
941 MPM.addPass(ModuleAddressSanitizerPass(
942 /*CompileKernel=*/false, SanitizerOptions->SanitizeAddressRecover));
947 if (SanitizerOptions->SanitizeHWAddress) {
948 #if LLVM_VERSION_GE(11, 0)
949 OptimizerLastEPCallbacks.push_back(
950 [SanitizerOptions](ModulePassManager &MPM, PassBuilder::OptimizationLevel Level) {
951 MPM.addPass(HWAddressSanitizerPass(
952 /*CompileKernel=*/false, SanitizerOptions->SanitizeHWAddressRecover));
956 PipelineStartEPCallbacks.push_back(
957 [SanitizerOptions](ModulePassManager &MPM, PassBuilder::OptimizationLevel Level) {
958 MPM.addPass(HWAddressSanitizerPass(
959 /*CompileKernel=*/false, SanitizerOptions->SanitizeHWAddressRecover));
966 #if LLVM_VERSION_GE(13, 0)
967 ModulePassManager MPM;
969 ModulePassManager MPM(DebugPassManager);
971 bool NeedThinLTOBufferPasses = UseThinLTOBuffers;
972 if (!NoPrepopulatePasses) {
973 if (OptLevel == PassBuilder::OptimizationLevel::O0) {
974 #if LLVM_VERSION_GE(12, 0)
975 for (const auto &C : PipelineStartEPCallbacks)
976 PB.registerPipelineStartEPCallback(C);
977 for (const auto &C : OptimizerLastEPCallbacks)
978 PB.registerOptimizerLastEPCallback(C);
980 // Pass false as we manually schedule ThinLTOBufferPasses below.
981 MPM = PB.buildO0DefaultPipeline(OptLevel, /* PreLinkLTO */ false);
983 for (const auto &C : PipelineStartEPCallbacks)
986 # if LLVM_VERSION_GE(11, 0)
987 for (const auto &C : OptimizerLastEPCallbacks)
990 if (!OptimizerLastEPCallbacks.empty()) {
991 FunctionPassManager FPM(DebugPassManager);
992 for (const auto &C : OptimizerLastEPCallbacks)
994 MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
998 MPM.addPass(AlwaysInlinerPass(EmitLifetimeMarkers));
1001 PB.addPGOInstrPassesForO0(
1002 MPM, DebugPassManager, PGOOpt->Action == PGOOptions::IRInstr,
1003 /*IsCS=*/false, PGOOpt->ProfileFile, PGOOpt->ProfileRemappingFile);
1007 #if LLVM_VERSION_GE(12, 0)
1008 for (const auto &C : PipelineStartEPCallbacks)
1009 PB.registerPipelineStartEPCallback(C);
1011 for (const auto &C : PipelineStartEPCallbacks)
1012 PB.registerPipelineStartEPCallback([C, OptLevel](ModulePassManager &MPM) {
1016 if (OptStage != LLVMRustOptStage::PreLinkThinLTO) {
1017 for (const auto &C : OptimizerLastEPCallbacks)
1018 PB.registerOptimizerLastEPCallback(C);
1022 case LLVMRustOptStage::PreLinkNoLTO:
1023 MPM = PB.buildPerModuleDefaultPipeline(OptLevel, DebugPassManager);
1025 case LLVMRustOptStage::PreLinkThinLTO:
1026 #if LLVM_VERSION_GE(12, 0)
1027 MPM = PB.buildThinLTOPreLinkDefaultPipeline(OptLevel);
1028 // The ThinLTOPreLink pipeline already includes ThinLTOBuffer passes. However, callback
1029 // passes may still run afterwards. This means we need to run the buffer passes again.
1030 // FIXME: In LLVM 13, the ThinLTOPreLink pipeline also runs OptimizerLastEPCallbacks
1031 // before the RequiredLTOPreLinkPasses, in which case we can remove these hacks.
1032 if (OptimizerLastEPCallbacks.empty())
1033 NeedThinLTOBufferPasses = false;
1035 MPM = PB.buildThinLTOPreLinkDefaultPipeline(OptLevel, DebugPassManager);
1037 #if LLVM_VERSION_GE(11, 0)
1038 for (const auto &C : OptimizerLastEPCallbacks)
1041 if (!OptimizerLastEPCallbacks.empty()) {
1042 FunctionPassManager FPM(DebugPassManager);
1043 for (const auto &C : OptimizerLastEPCallbacks)
1045 MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
1049 case LLVMRustOptStage::PreLinkFatLTO:
1050 #if LLVM_VERSION_GE(12, 0)
1051 MPM = PB.buildLTOPreLinkDefaultPipeline(OptLevel);
1052 NeedThinLTOBufferPasses = false;
1054 MPM = PB.buildLTOPreLinkDefaultPipeline(OptLevel, DebugPassManager);
1057 case LLVMRustOptStage::ThinLTO:
1058 // FIXME: Does it make sense to pass the ModuleSummaryIndex?
1059 // It only seems to be needed for C++ specific optimizations.
1060 #if LLVM_VERSION_GE(12, 0)
1061 MPM = PB.buildThinLTODefaultPipeline(OptLevel, nullptr);
1063 MPM = PB.buildThinLTODefaultPipeline(OptLevel, DebugPassManager, nullptr);
1066 case LLVMRustOptStage::FatLTO:
1067 #if LLVM_VERSION_GE(12, 0)
1068 MPM = PB.buildLTODefaultPipeline(OptLevel, nullptr);
1070 MPM = PB.buildLTODefaultPipeline(OptLevel, DebugPassManager, nullptr);
1077 if (ExtraPassesLen) {
1078 if (auto Err = PB.parsePassPipeline(MPM, StringRef(ExtraPasses, ExtraPassesLen))) {
1079 std::string ErrMsg = toString(std::move(Err));
1080 LLVMRustSetLastError(ErrMsg.c_str());
1081 return LLVMRustResult::Failure;
1085 if (NeedThinLTOBufferPasses) {
1086 MPM.addPass(CanonicalizeAliasesPass());
1087 MPM.addPass(NameAnonGlobalPass());
1090 // Upgrade all calls to old intrinsics first.
1091 for (Module::iterator I = TheModule->begin(), E = TheModule->end(); I != E;)
1092 UpgradeCallsToIntrinsic(&*I++); // must be post-increment, as we remove
1094 MPM.run(*TheModule, MAM);
1095 return LLVMRustResult::Success;
1098 // Callback to demangle function name
1100 // * name to be demangled
1103 // * output buffer len
1104 // Returns len of demangled string, or 0 if demangle failed.
1105 typedef size_t (*DemangleFn)(const char*, size_t, char*, size_t);
1110 class RustAssemblyAnnotationWriter : public AssemblyAnnotationWriter {
1111 DemangleFn Demangle;
1112 std::vector<char> Buf;
1115 RustAssemblyAnnotationWriter(DemangleFn Demangle) : Demangle(Demangle) {}
1117 // Return empty string if demangle failed
1118 // or if name does not need to be demangled
1119 StringRef CallDemangle(StringRef name) {
1124 if (Buf.size() < name.size() * 2) {
1125 // Semangled name usually shorter than mangled,
1126 // but allocate twice as much memory just in case
1127 Buf.resize(name.size() * 2);
1130 auto R = Demangle(name.data(), name.size(), Buf.data(), Buf.size());
1136 auto Demangled = StringRef(Buf.data(), R);
1137 if (Demangled == name) {
1138 // Do not print anything if demangled name is equal to mangled.
1145 void emitFunctionAnnot(const Function *F,
1146 formatted_raw_ostream &OS) override {
1147 StringRef Demangled = CallDemangle(F->getName());
1148 if (Demangled.empty()) {
1152 OS << "; " << Demangled << "\n";
1155 void emitInstructionAnnot(const Instruction *I,
1156 formatted_raw_ostream &OS) override {
1159 if (const CallInst *CI = dyn_cast<CallInst>(I)) {
1161 Value = CI->getCalledOperand();
1162 } else if (const InvokeInst* II = dyn_cast<InvokeInst>(I)) {
1164 Value = II->getCalledOperand();
1166 // Could demangle more operations, e. g.
1167 // `store %place, @function`.
1171 if (!Value->hasName()) {
1175 StringRef Demangled = CallDemangle(Value->getName());
1176 if (Demangled.empty()) {
1180 OS << "; " << Name << " " << Demangled << "\n";
1186 extern "C" LLVMRustResult
1187 LLVMRustPrintModule(LLVMModuleRef M, const char *Path, DemangleFn Demangle) {
1188 std::string ErrorInfo;
1190 raw_fd_ostream OS(Path, EC, sys::fs::OF_None);
1192 ErrorInfo = EC.message();
1193 if (ErrorInfo != "") {
1194 LLVMRustSetLastError(ErrorInfo.c_str());
1195 return LLVMRustResult::Failure;
1198 RustAssemblyAnnotationWriter AAW(Demangle);
1199 formatted_raw_ostream FOS(OS);
1200 unwrap(M)->print(FOS, &AAW);
1202 return LLVMRustResult::Success;
1205 extern "C" void LLVMRustPrintPasses() {
1206 LLVMInitializePasses();
1207 struct MyListener : PassRegistrationListener {
1208 void passEnumerate(const PassInfo *Info) {
1209 StringRef PassArg = Info->getPassArgument();
1210 StringRef PassName = Info->getPassName();
1211 if (!PassArg.empty()) {
1212 // These unsigned->signed casts could theoretically overflow, but
1213 // realistically never will (and even if, the result is implementation
1214 // defined rather plain UB).
1215 printf("%15.*s - %.*s\n", (int)PassArg.size(), PassArg.data(),
1216 (int)PassName.size(), PassName.data());
1221 PassRegistry *PR = PassRegistry::getPassRegistry();
1222 PR->enumerateWith(&Listener);
1225 extern "C" void LLVMRustAddAlwaysInlinePass(LLVMPassManagerBuilderRef PMBR,
1226 bool AddLifetimes) {
1227 unwrap(PMBR)->Inliner = llvm::createAlwaysInlinerLegacyPass(AddLifetimes);
1230 extern "C" void LLVMRustRunRestrictionPass(LLVMModuleRef M, char **Symbols,
1232 llvm::legacy::PassManager passes;
1234 auto PreserveFunctions = [=](const GlobalValue &GV) {
1235 for (size_t I = 0; I < Len; I++) {
1236 if (GV.getName() == Symbols[I]) {
1243 passes.add(llvm::createInternalizePass(PreserveFunctions));
1245 passes.run(*unwrap(M));
1248 extern "C" void LLVMRustMarkAllFunctionsNounwind(LLVMModuleRef M) {
1249 for (Module::iterator GV = unwrap(M)->begin(), E = unwrap(M)->end(); GV != E;
1251 GV->setDoesNotThrow();
1252 Function *F = dyn_cast<Function>(GV);
1256 for (Function::iterator B = F->begin(), BE = F->end(); B != BE; ++B) {
1257 for (BasicBlock::iterator I = B->begin(), IE = B->end(); I != IE; ++I) {
1258 if (isa<InvokeInst>(I)) {
1259 InvokeInst *CI = cast<InvokeInst>(I);
1260 CI->setDoesNotThrow();
1268 LLVMRustSetDataLayoutFromTargetMachine(LLVMModuleRef Module,
1269 LLVMTargetMachineRef TMR) {
1270 TargetMachine *Target = unwrap(TMR);
1271 unwrap(Module)->setDataLayout(Target->createDataLayout());
1274 extern "C" void LLVMRustSetModulePICLevel(LLVMModuleRef M) {
1275 unwrap(M)->setPICLevel(PICLevel::Level::BigPIC);
1278 extern "C" void LLVMRustSetModulePIELevel(LLVMModuleRef M) {
1279 unwrap(M)->setPIELevel(PIELevel::Level::Large);
1282 extern "C" void LLVMRustSetModuleCodeModel(LLVMModuleRef M,
1283 LLVMRustCodeModel Model) {
1284 auto CM = fromRust(Model);
1287 unwrap(M)->setCodeModel(*CM);
1290 // Here you'll find an implementation of ThinLTO as used by the Rust compiler
1291 // right now. This ThinLTO support is only enabled on "recent ish" versions of
1292 // LLVM, and otherwise it's just blanket rejected from other compilers.
1294 // Most of this implementation is straight copied from LLVM. At the time of
1295 // this writing it wasn't *quite* suitable to reuse more code from upstream
1296 // for our purposes, but we should strive to upstream this support once it's
1297 // ready to go! I figure we may want a bit of testing locally first before
1298 // sending this upstream to LLVM. I hear though they're quite eager to receive
1299 // feedback like this!
1301 // If you're reading this code and wondering "what in the world" or you're
1302 // working "good lord by LLVM upgrade is *still* failing due to these bindings"
1303 // then fear not! (ok maybe fear a little). All code here is mostly based
1304 // on `lib/LTO/ThinLTOCodeGenerator.cpp` in LLVM.
1306 // You'll find that the general layout here roughly corresponds to the `run`
1307 // method in that file as well as `ProcessThinLTOModule`. Functions are
1308 // specifically commented below as well, but if you're updating this code
1309 // or otherwise trying to understand it, the LLVM source will be useful in
1310 // interpreting the mysteries within.
1312 // Otherwise I'll apologize in advance, it probably requires a relatively
1313 // significant investment on your part to "truly understand" what's going on
1314 // here. Not saying I do myself, but it took me awhile staring at LLVM's source
1315 // and various online resources about ThinLTO to make heads or tails of all
1318 // This is a shared data structure which *must* be threadsafe to share
1319 // read-only amongst threads. This also corresponds basically to the arguments
1320 // of the `ProcessThinLTOModule` function in the LLVM source.
1321 struct LLVMRustThinLTOData {
1322 // The combined index that is the global analysis over all modules we're
1323 // performing ThinLTO for. This is mostly managed by LLVM.
1324 ModuleSummaryIndex Index;
1326 // All modules we may look at, stored as in-memory serialized versions. This
1327 // is later used when inlining to ensure we can extract any module to inline
1329 StringMap<MemoryBufferRef> ModuleMap;
1331 // A set that we manage of everything we *don't* want internalized. Note that
1332 // this includes all transitive references right now as well, but it may not
1334 DenseSet<GlobalValue::GUID> GUIDPreservedSymbols;
1336 // Not 100% sure what these are, but they impact what's internalized and
1337 // what's inlined across modules, I believe.
1338 StringMap<FunctionImporter::ImportMapTy> ImportLists;
1339 StringMap<FunctionImporter::ExportSetTy> ExportLists;
1340 StringMap<GVSummaryMapTy> ModuleToDefinedGVSummaries;
1341 StringMap<std::map<GlobalValue::GUID, GlobalValue::LinkageTypes>> ResolvedODR;
1343 LLVMRustThinLTOData() : Index(/* HaveGVs = */ false) {}
1346 // Just an argument to the `LLVMRustCreateThinLTOData` function below.
1347 struct LLVMRustThinLTOModule {
1348 const char *identifier;
1353 // This is copied from `lib/LTO/ThinLTOCodeGenerator.cpp`, not sure what it
1355 static const GlobalValueSummary *
1356 getFirstDefinitionForLinker(const GlobalValueSummaryList &GVSummaryList) {
1357 auto StrongDefForLinker = llvm::find_if(
1358 GVSummaryList, [](const std::unique_ptr<GlobalValueSummary> &Summary) {
1359 auto Linkage = Summary->linkage();
1360 return !GlobalValue::isAvailableExternallyLinkage(Linkage) &&
1361 !GlobalValue::isWeakForLinker(Linkage);
1363 if (StrongDefForLinker != GVSummaryList.end())
1364 return StrongDefForLinker->get();
1366 auto FirstDefForLinker = llvm::find_if(
1367 GVSummaryList, [](const std::unique_ptr<GlobalValueSummary> &Summary) {
1368 auto Linkage = Summary->linkage();
1369 return !GlobalValue::isAvailableExternallyLinkage(Linkage);
1371 if (FirstDefForLinker == GVSummaryList.end())
1373 return FirstDefForLinker->get();
1376 // The main entry point for creating the global ThinLTO analysis. The structure
1377 // here is basically the same as before threads are spawned in the `run`
1378 // function of `lib/LTO/ThinLTOCodeGenerator.cpp`.
1379 extern "C" LLVMRustThinLTOData*
1380 LLVMRustCreateThinLTOData(LLVMRustThinLTOModule *modules,
1382 const char **preserved_symbols,
1384 auto Ret = std::make_unique<LLVMRustThinLTOData>();
1386 // Load each module's summary and merge it into one combined index
1387 for (int i = 0; i < num_modules; i++) {
1388 auto module = &modules[i];
1389 StringRef buffer(module->data, module->len);
1390 MemoryBufferRef mem_buffer(buffer, module->identifier);
1392 Ret->ModuleMap[module->identifier] = mem_buffer;
1394 if (Error Err = readModuleSummaryIndex(mem_buffer, Ret->Index, i)) {
1395 LLVMRustSetLastError(toString(std::move(Err)).c_str());
1400 // Collect for each module the list of function it defines (GUID -> Summary)
1401 Ret->Index.collectDefinedGVSummariesPerModule(Ret->ModuleToDefinedGVSummaries);
1403 // Convert the preserved symbols set from string to GUID, this is then needed
1404 // for internalization.
1405 for (int i = 0; i < num_symbols; i++) {
1406 auto GUID = GlobalValue::getGUID(preserved_symbols[i]);
1407 Ret->GUIDPreservedSymbols.insert(GUID);
1410 // Collect the import/export lists for all modules from the call-graph in the
1413 // This is copied from `lib/LTO/ThinLTOCodeGenerator.cpp`
1414 auto deadIsPrevailing = [&](GlobalValue::GUID G) {
1415 return PrevailingType::Unknown;
1417 // We don't have a complete picture in our use of ThinLTO, just our immediate
1418 // crate, so we need `ImportEnabled = false` to limit internalization.
1419 // Otherwise, we sometimes lose `static` values -- see #60184.
1420 computeDeadSymbolsWithConstProp(Ret->Index, Ret->GUIDPreservedSymbols,
1421 deadIsPrevailing, /* ImportEnabled = */ false);
1422 ComputeCrossModuleImport(
1424 Ret->ModuleToDefinedGVSummaries,
1429 // Resolve LinkOnce/Weak symbols, this has to be computed early be cause it
1430 // impacts the caching.
1432 // This is copied from `lib/LTO/ThinLTOCodeGenerator.cpp` with some of this
1433 // being lifted from `lib/LTO/LTO.cpp` as well
1434 DenseMap<GlobalValue::GUID, const GlobalValueSummary *> PrevailingCopy;
1435 for (auto &I : Ret->Index) {
1436 if (I.second.SummaryList.size() > 1)
1437 PrevailingCopy[I.first] = getFirstDefinitionForLinker(I.second.SummaryList);
1439 auto isPrevailing = [&](GlobalValue::GUID GUID, const GlobalValueSummary *S) {
1440 const auto &Prevailing = PrevailingCopy.find(GUID);
1441 if (Prevailing == PrevailingCopy.end())
1443 return Prevailing->second == S;
1445 auto recordNewLinkage = [&](StringRef ModuleIdentifier,
1446 GlobalValue::GUID GUID,
1447 GlobalValue::LinkageTypes NewLinkage) {
1448 Ret->ResolvedODR[ModuleIdentifier][GUID] = NewLinkage;
1451 #if LLVM_VERSION_GE(13,0)
1452 // Uses FromPrevailing visibility scheme which works for many binary
1453 // formats. We probably could and should use ELF visibility scheme for many of
1454 // our targets, however.
1456 thinLTOResolvePrevailingInIndex(conf, Ret->Index, isPrevailing, recordNewLinkage,
1457 Ret->GUIDPreservedSymbols);
1459 thinLTOResolvePrevailingInIndex(Ret->Index, isPrevailing, recordNewLinkage,
1460 Ret->GUIDPreservedSymbols);
1462 // Here we calculate an `ExportedGUIDs` set for use in the `isExported`
1463 // callback below. This callback below will dictate the linkage for all
1464 // summaries in the index, and we basically just only want to ensure that dead
1465 // symbols are internalized. Otherwise everything that's already external
1466 // linkage will stay as external, and internal will stay as internal.
1467 std::set<GlobalValue::GUID> ExportedGUIDs;
1468 for (auto &List : Ret->Index) {
1469 for (auto &GVS: List.second.SummaryList) {
1470 if (GlobalValue::isLocalLinkage(GVS->linkage()))
1472 auto GUID = GVS->getOriginalName();
1473 if (GVS->flags().Live)
1474 ExportedGUIDs.insert(GUID);
1477 auto isExported = [&](StringRef ModuleIdentifier, ValueInfo VI) {
1478 const auto &ExportList = Ret->ExportLists.find(ModuleIdentifier);
1479 return (ExportList != Ret->ExportLists.end() &&
1480 ExportList->second.count(VI)) ||
1481 ExportedGUIDs.count(VI.getGUID());
1483 thinLTOInternalizeAndPromoteInIndex(Ret->Index, isExported, isPrevailing);
1485 return Ret.release();
1489 LLVMRustFreeThinLTOData(LLVMRustThinLTOData *Data) {
1493 // Below are the various passes that happen *per module* when doing ThinLTO.
1495 // In other words, these are the functions that are all run concurrently
1496 // with one another, one per module. The passes here correspond to the analysis
1497 // passes in `lib/LTO/ThinLTOCodeGenerator.cpp`, currently found in the
1498 // `ProcessThinLTOModule` function. Here they're split up into separate steps
1499 // so rustc can save off the intermediate bytecode between each step.
1501 #if LLVM_VERSION_GE(11, 0)
1503 clearDSOLocalOnDeclarations(Module &Mod, TargetMachine &TM) {
1504 // When linking an ELF shared object, dso_local should be dropped. We
1505 // conservatively do this for -fpic.
1506 bool ClearDSOLocalOnDeclarations =
1507 TM.getTargetTriple().isOSBinFormatELF() &&
1508 TM.getRelocationModel() != Reloc::Static &&
1509 Mod.getPIELevel() == PIELevel::Default;
1510 return ClearDSOLocalOnDeclarations;
1515 LLVMRustPrepareThinLTORename(const LLVMRustThinLTOData *Data, LLVMModuleRef M,
1516 LLVMTargetMachineRef TM) {
1517 Module &Mod = *unwrap(M);
1518 TargetMachine &Target = *unwrap(TM);
1520 #if LLVM_VERSION_GE(11, 0)
1521 bool ClearDSOLocal = clearDSOLocalOnDeclarations(Mod, Target);
1522 bool error = renameModuleForThinLTO(Mod, Data->Index, ClearDSOLocal);
1524 bool error = renameModuleForThinLTO(Mod, Data->Index);
1528 LLVMRustSetLastError("renameModuleForThinLTO failed");
1535 LLVMRustPrepareThinLTOResolveWeak(const LLVMRustThinLTOData *Data, LLVMModuleRef M) {
1536 Module &Mod = *unwrap(M);
1537 const auto &DefinedGlobals = Data->ModuleToDefinedGVSummaries.lookup(Mod.getModuleIdentifier());
1538 thinLTOResolvePrevailingInModule(Mod, DefinedGlobals);
1543 LLVMRustPrepareThinLTOInternalize(const LLVMRustThinLTOData *Data, LLVMModuleRef M) {
1544 Module &Mod = *unwrap(M);
1545 const auto &DefinedGlobals = Data->ModuleToDefinedGVSummaries.lookup(Mod.getModuleIdentifier());
1546 thinLTOInternalizeModule(Mod, DefinedGlobals);
1551 LLVMRustPrepareThinLTOImport(const LLVMRustThinLTOData *Data, LLVMModuleRef M,
1552 LLVMTargetMachineRef TM) {
1553 Module &Mod = *unwrap(M);
1554 TargetMachine &Target = *unwrap(TM);
1556 const auto &ImportList = Data->ImportLists.lookup(Mod.getModuleIdentifier());
1557 auto Loader = [&](StringRef Identifier) {
1558 const auto &Memory = Data->ModuleMap.lookup(Identifier);
1559 auto &Context = Mod.getContext();
1560 auto MOrErr = getLazyBitcodeModule(Memory, Context, true, true);
1565 // The rest of this closure is a workaround for
1566 // https://bugs.llvm.org/show_bug.cgi?id=38184 where during ThinLTO imports
1567 // we accidentally import wasm custom sections into different modules,
1568 // duplicating them by in the final output artifact.
1570 // The issue is worked around here by manually removing the
1571 // `wasm.custom_sections` named metadata node from any imported module. This
1572 // we know isn't used by any optimization pass so there's no need for it to
1575 // Note that the metadata is currently lazily loaded, so we materialize it
1576 // here before looking up if there's metadata inside. The `FunctionImporter`
1577 // will immediately materialize metadata anyway after an import, so this
1578 // shouldn't be a perf hit.
1579 if (Error Err = (*MOrErr)->materializeMetadata()) {
1580 Expected<std::unique_ptr<Module>> Ret(std::move(Err));
1584 auto *WasmCustomSections = (*MOrErr)->getNamedMetadata("wasm.custom_sections");
1585 if (WasmCustomSections)
1586 WasmCustomSections->eraseFromParent();
1590 #if LLVM_VERSION_GE(11, 0)
1591 bool ClearDSOLocal = clearDSOLocalOnDeclarations(Mod, Target);
1592 FunctionImporter Importer(Data->Index, Loader, ClearDSOLocal);
1594 FunctionImporter Importer(Data->Index, Loader);
1596 Expected<bool> Result = Importer.importFunctions(Mod, ImportList);
1598 LLVMRustSetLastError(toString(Result.takeError()).c_str());
1604 extern "C" typedef void (*LLVMRustModuleNameCallback)(void*, // payload
1605 const char*, // importing module name
1606 const char*); // imported module name
1608 // Calls `module_name_callback` for each module import done by ThinLTO.
1609 // The callback is provided with regular null-terminated C strings.
1611 LLVMRustGetThinLTOModules(const LLVMRustThinLTOData *data,
1612 LLVMRustModuleNameCallback module_name_callback,
1613 void* callback_payload) {
1614 for (const auto& importing_module : data->ImportLists) {
1615 const std::string importing_module_id = importing_module.getKey().str();
1616 const auto& imports = importing_module.getValue();
1617 for (const auto& imported_module : imports) {
1618 const std::string imported_module_id = imported_module.getKey().str();
1619 module_name_callback(callback_payload,
1620 importing_module_id.c_str(),
1621 imported_module_id.c_str());
1626 // This struct and various functions are sort of a hack right now, but the
1627 // problem is that we've got in-memory LLVM modules after we generate and
1628 // optimize all codegen-units for one compilation in rustc. To be compatible
1629 // with the LTO support above we need to serialize the modules plus their
1630 // ThinLTO summary into memory.
1632 // This structure is basically an owned version of a serialize module, with
1633 // a ThinLTO summary attached.
1634 struct LLVMRustThinLTOBuffer {
1638 extern "C" LLVMRustThinLTOBuffer*
1639 LLVMRustThinLTOBufferCreate(LLVMModuleRef M) {
1640 auto Ret = std::make_unique<LLVMRustThinLTOBuffer>();
1642 raw_string_ostream OS(Ret->data);
1644 legacy::PassManager PM;
1645 PM.add(createWriteThinLTOBitcodePass(OS));
1649 return Ret.release();
1653 LLVMRustThinLTOBufferFree(LLVMRustThinLTOBuffer *Buffer) {
1657 extern "C" const void*
1658 LLVMRustThinLTOBufferPtr(const LLVMRustThinLTOBuffer *Buffer) {
1659 return Buffer->data.data();
1663 LLVMRustThinLTOBufferLen(const LLVMRustThinLTOBuffer *Buffer) {
1664 return Buffer->data.length();
1667 // This is what we used to parse upstream bitcode for actual ThinLTO
1668 // processing. We'll call this once per module optimized through ThinLTO, and
1669 // it'll be called concurrently on many threads.
1670 extern "C" LLVMModuleRef
1671 LLVMRustParseBitcodeForLTO(LLVMContextRef Context,
1674 const char *identifier) {
1675 StringRef Data(data, len);
1676 MemoryBufferRef Buffer(Data, identifier);
1677 unwrap(Context)->enableDebugTypeODRUniquing();
1678 Expected<std::unique_ptr<Module>> SrcOrError =
1679 parseBitcodeFile(Buffer, *unwrap(Context));
1681 LLVMRustSetLastError(toString(SrcOrError.takeError()).c_str());
1684 return wrap(std::move(*SrcOrError).release());
1687 // Find the bitcode section in the object file data and return it as a slice.
1688 // Fail if the bitcode section is present but empty.
1690 // On success, the return value is the pointer to the start of the slice and
1691 // `out_len` is filled with the (non-zero) length. On failure, the return value
1692 // is `nullptr` and `out_len` is set to zero.
1693 extern "C" const char*
1694 LLVMRustGetBitcodeSliceFromObjectData(const char *data,
1699 StringRef Data(data, len);
1700 MemoryBufferRef Buffer(Data, ""); // The id is unused.
1702 Expected<MemoryBufferRef> BitcodeOrError =
1703 object::IRObjectFile::findBitcodeInMemBuffer(Buffer);
1704 if (!BitcodeOrError) {
1705 LLVMRustSetLastError(toString(BitcodeOrError.takeError()).c_str());
1709 *out_len = BitcodeOrError->getBufferSize();
1710 return BitcodeOrError->getBufferStart();
1713 // Rewrite all `DICompileUnit` pointers to the `DICompileUnit` specified. See
1714 // the comment in `back/lto.rs` for why this exists.
1716 LLVMRustThinLTOGetDICompileUnit(LLVMModuleRef Mod,
1718 DICompileUnit **B) {
1719 Module *M = unwrap(Mod);
1720 DICompileUnit **Cur = A;
1721 DICompileUnit **Next = B;
1722 for (DICompileUnit *CU : M->debug_compile_units()) {
1731 // Rewrite all `DICompileUnit` pointers to the `DICompileUnit` specified. See
1732 // the comment in `back/lto.rs` for why this exists.
1734 LLVMRustThinLTOPatchDICompileUnit(LLVMModuleRef Mod, DICompileUnit *Unit) {
1735 Module *M = unwrap(Mod);
1737 // If the original source module didn't have a `DICompileUnit` then try to
1738 // merge all the existing compile units. If there aren't actually any though
1739 // then there's not much for us to do so return.
1740 if (Unit == nullptr) {
1741 for (DICompileUnit *CU : M->debug_compile_units()) {
1745 if (Unit == nullptr)
1749 // Use LLVM's built-in `DebugInfoFinder` to find a bunch of debuginfo and
1750 // process it recursively. Note that we used to specifically iterate over
1751 // instructions to ensure we feed everything into it, but `processModule`
1752 // started doing this the same way in LLVM 7 (commit d769eb36ab2b8).
1753 DebugInfoFinder Finder;
1754 Finder.processModule(*M);
1756 // After we've found all our debuginfo, rewrite all subprograms to point to
1757 // the same `DICompileUnit`.
1758 for (auto &F : Finder.subprograms()) {
1759 F->replaceUnit(Unit);
1762 // Erase any other references to other `DICompileUnit` instances, the verifier
1763 // will later ensure that we don't actually have any other stale references to
1765 auto *MD = M->getNamedMetadata("llvm.dbg.cu");
1766 MD->clearOperands();
1767 MD->addOperand(Unit);
1770 // Computes the LTO cache key for the provided 'ModId' in the given 'Data',
1771 // storing the result in 'KeyOut'.
1772 // Currently, this cache key is a SHA-1 hash of anything that could affect
1773 // the result of optimizing this module (e.g. module imports, exports, liveness
1774 // of access globals, etc).
1775 // The precise details are determined by LLVM in `computeLTOCacheKey`, which is
1776 // used during the normal linker-plugin incremental thin-LTO process.
1778 LLVMRustComputeLTOCacheKey(RustStringRef KeyOut, const char *ModId, LLVMRustThinLTOData *Data) {
1779 SmallString<40> Key;
1780 llvm::lto::Config conf;
1781 const auto &ImportList = Data->ImportLists.lookup(ModId);
1782 const auto &ExportList = Data->ExportLists.lookup(ModId);
1783 const auto &ResolvedODR = Data->ResolvedODR.lookup(ModId);
1784 const auto &DefinedGlobals = Data->ModuleToDefinedGVSummaries.lookup(ModId);
1785 std::set<GlobalValue::GUID> CfiFunctionDefs;
1786 std::set<GlobalValue::GUID> CfiFunctionDecls;
1788 // Based on the 'InProcessThinBackend' constructor in LLVM
1789 for (auto &Name : Data->Index.cfiFunctionDefs())
1790 CfiFunctionDefs.insert(
1791 GlobalValue::getGUID(GlobalValue::dropLLVMManglingEscape(Name)));
1792 for (auto &Name : Data->Index.cfiFunctionDecls())
1793 CfiFunctionDecls.insert(
1794 GlobalValue::getGUID(GlobalValue::dropLLVMManglingEscape(Name)));
1796 llvm::computeLTOCacheKey(Key, conf, Data->Index, ModId,
1797 ImportList, ExportList, ResolvedODR, DefinedGlobals, CfiFunctionDefs, CfiFunctionDecls
1800 LLVMRustStringWriteImpl(KeyOut, Key.c_str(), Key.size());