6 #include "LLVMWrapper.h"
8 #include "llvm/Analysis/AliasAnalysis.h"
9 #include "llvm/Analysis/TargetLibraryInfo.h"
10 #include "llvm/Analysis/TargetTransformInfo.h"
11 #include "llvm/CodeGen/TargetSubtargetInfo.h"
12 #include "llvm/InitializePasses.h"
13 #include "llvm/IR/AutoUpgrade.h"
14 #include "llvm/IR/AssemblyAnnotationWriter.h"
15 #include "llvm/IR/IntrinsicInst.h"
16 #include "llvm/IR/Verifier.h"
17 #include "llvm/Object/ObjectFile.h"
18 #include "llvm/Object/IRObjectFile.h"
19 #include "llvm/Passes/PassBuilder.h"
20 #include "llvm/Passes/PassPlugin.h"
21 #include "llvm/Passes/StandardInstrumentations.h"
22 #include "llvm/Support/CBindingWrapping.h"
23 #include "llvm/Support/FileSystem.h"
24 #include "llvm/Support/Host.h"
25 #if LLVM_VERSION_LT(14, 0)
26 #include "llvm/Support/TargetRegistry.h"
28 #include "llvm/MC/TargetRegistry.h"
30 #include "llvm/Target/TargetMachine.h"
31 #include "llvm/Transforms/IPO/PassManagerBuilder.h"
32 #include "llvm/Transforms/IPO/AlwaysInliner.h"
33 #include "llvm/Transforms/IPO/FunctionImport.h"
34 #include "llvm/Transforms/Utils/AddDiscriminators.h"
35 #include "llvm/Transforms/Utils/FunctionImportUtils.h"
36 #include "llvm/LTO/LTO.h"
37 #include "llvm/Bitcode/BitcodeWriterPass.h"
38 #include "llvm-c/Transforms/PassManagerBuilder.h"
40 #include "llvm/Transforms/Instrumentation.h"
41 #include "llvm/Transforms/Instrumentation/AddressSanitizer.h"
42 #include "llvm/Support/TimeProfiler.h"
43 #include "llvm/Transforms/Instrumentation/GCOVProfiler.h"
44 #include "llvm/Transforms/Instrumentation/InstrProfiling.h"
45 #include "llvm/Transforms/Instrumentation/ThreadSanitizer.h"
46 #include "llvm/Transforms/Instrumentation/MemorySanitizer.h"
47 #include "llvm/Transforms/Instrumentation/HWAddressSanitizer.h"
48 #include "llvm/Transforms/Utils/CanonicalizeAliases.h"
49 #include "llvm/Transforms/Utils/NameAnonGlobals.h"
50 #include "llvm/Transforms/Utils.h"
54 typedef struct LLVMOpaquePass *LLVMPassRef;
55 typedef struct LLVMOpaqueTargetMachine *LLVMTargetMachineRef;
57 DEFINE_STDCXX_CONVERSION_FUNCTIONS(Pass, LLVMPassRef)
58 DEFINE_STDCXX_CONVERSION_FUNCTIONS(TargetMachine, LLVMTargetMachineRef)
60 extern "C" void LLVMInitializePasses() {
61 PassRegistry &Registry = *PassRegistry::getPassRegistry();
62 initializeCore(Registry);
63 initializeCodeGen(Registry);
64 initializeScalarOpts(Registry);
65 initializeVectorization(Registry);
66 initializeIPO(Registry);
67 initializeAnalysis(Registry);
68 initializeTransformUtils(Registry);
69 initializeInstCombine(Registry);
70 initializeInstrumentation(Registry);
71 initializeTarget(Registry);
74 extern "C" void LLVMTimeTraceProfilerInitialize() {
75 timeTraceProfilerInitialize(
76 /* TimeTraceGranularity */ 0,
77 /* ProcName */ "rustc");
80 extern "C" void LLVMTimeTraceProfilerFinishThread() {
81 timeTraceProfilerFinishThread();
84 extern "C" void LLVMTimeTraceProfilerFinish(const char* FileName) {
85 StringRef FN(FileName);
87 raw_fd_ostream OS(FN, EC, sys::fs::CD_CreateAlways);
89 timeTraceProfilerWrite(OS);
90 timeTraceProfilerCleanup();
93 enum class LLVMRustPassKind {
99 static LLVMRustPassKind toRust(PassKind Kind) {
102 return LLVMRustPassKind::Function;
104 return LLVMRustPassKind::Module;
106 return LLVMRustPassKind::Other;
110 extern "C" LLVMPassRef LLVMRustFindAndCreatePass(const char *PassName) {
111 #if LLVM_VERSION_LT(15, 0)
112 StringRef SR(PassName);
113 PassRegistry *PR = PassRegistry::getPassRegistry();
115 const PassInfo *PI = PR->getPassInfo(SR);
117 return wrap(PI->createPass());
121 report_fatal_error("Legacy PM not supported with LLVM 15");
125 extern "C" LLVMPassRef LLVMRustCreateAddressSanitizerFunctionPass(bool Recover) {
126 #if LLVM_VERSION_LT(15, 0)
127 const bool CompileKernel = false;
128 const bool UseAfterScope = true;
130 return wrap(createAddressSanitizerFunctionPass(CompileKernel, Recover, UseAfterScope));
132 report_fatal_error("Legacy PM not supported with LLVM 15");
136 extern "C" LLVMPassRef LLVMRustCreateModuleAddressSanitizerPass(bool Recover) {
137 #if LLVM_VERSION_LT(15, 0)
138 const bool CompileKernel = false;
140 return wrap(createModuleAddressSanitizerLegacyPassPass(CompileKernel, Recover));
142 report_fatal_error("Legacy PM not supported with LLVM 15");
146 extern "C" LLVMPassRef LLVMRustCreateMemorySanitizerPass(int TrackOrigins, bool Recover) {
147 #if LLVM_VERSION_LT(15, 0)
148 const bool CompileKernel = false;
150 return wrap(createMemorySanitizerLegacyPassPass(
151 MemorySanitizerOptions{TrackOrigins, Recover, CompileKernel}));
153 report_fatal_error("Legacy PM not supported with LLVM 15");
157 extern "C" LLVMPassRef LLVMRustCreateThreadSanitizerPass() {
158 #if LLVM_VERSION_LT(15, 0)
159 return wrap(createThreadSanitizerLegacyPassPass());
161 report_fatal_error("Legacy PM not supported with LLVM 15");
165 extern "C" LLVMPassRef LLVMRustCreateHWAddressSanitizerPass(bool Recover) {
166 #if LLVM_VERSION_LT(15, 0)
167 const bool CompileKernel = false;
169 return wrap(createHWAddressSanitizerLegacyPassPass(CompileKernel, Recover));
171 report_fatal_error("Legacy PM not supported with LLVM 15");
175 extern "C" LLVMRustPassKind LLVMRustPassKind(LLVMPassRef RustPass) {
177 Pass *Pass = unwrap(RustPass);
178 return toRust(Pass->getPassKind());
181 extern "C" void LLVMRustAddPass(LLVMPassManagerRef PMR, LLVMPassRef RustPass) {
182 #if LLVM_VERSION_LT(15, 0)
184 Pass *Pass = unwrap(RustPass);
185 PassManagerBase *PMB = unwrap(PMR);
188 report_fatal_error("Legacy PM not supported with LLVM 15");
192 extern "C" LLVMPassManagerBuilderRef LLVMRustPassManagerBuilderCreate() {
193 #if LLVM_VERSION_LT(15, 0)
194 return LLVMPassManagerBuilderCreate();
196 report_fatal_error("Legacy PM not supported with LLVM 15");
200 extern "C" void LLVMRustPassManagerBuilderDispose(LLVMPassManagerBuilderRef PMB) {
201 #if LLVM_VERSION_LT(15, 0)
202 LLVMPassManagerBuilderDispose(PMB);
204 report_fatal_error("Legacy PM not supported with LLVM 15");
208 extern "C" void LLVMRustPassManagerBuilderPopulateFunctionPassManager(
209 LLVMPassManagerBuilderRef PMB, LLVMPassManagerRef PM) {
210 #if LLVM_VERSION_LT(15, 0)
211 LLVMPassManagerBuilderPopulateFunctionPassManager(PMB, PM);
213 report_fatal_error("Legacy PM not supported with LLVM 15");
217 extern "C" void LLVMRustPassManagerBuilderPopulateModulePassManager(
218 LLVMPassManagerBuilderRef PMB, LLVMPassManagerRef PM) {
219 #if LLVM_VERSION_LT(15, 0)
220 LLVMPassManagerBuilderPopulateModulePassManager(PMB, PM);
222 report_fatal_error("Legacy PM not supported with LLVM 15");
226 extern "C" void LLVMRustPassManagerBuilderPopulateLTOPassManager(
227 LLVMPassManagerBuilderRef PMB, LLVMPassManagerRef PM, bool Internalize, bool RunInliner) {
228 #if LLVM_VERSION_LT(15, 0)
229 LLVMPassManagerBuilderPopulateLTOPassManager(PMB, PM, Internalize, RunInliner);
231 report_fatal_error("Legacy PM not supported with LLVM 15");
236 void LLVMRustPassManagerBuilderPopulateThinLTOPassManager(
237 LLVMPassManagerBuilderRef PMBR,
238 LLVMPassManagerRef PMR
240 #if LLVM_VERSION_LT(15, 0)
241 unwrap(PMBR)->populateThinLTOPassManager(*unwrap(PMR));
243 report_fatal_error("Legacy PM not supported with LLVM 15");
247 extern "C" void LLVMRustPassManagerBuilderUseInlinerWithThreshold(
248 LLVMPassManagerBuilderRef PMB, unsigned Threshold) {
249 #if LLVM_VERSION_LT(15, 0)
250 LLVMPassManagerBuilderUseInlinerWithThreshold(PMB, Threshold);
252 report_fatal_error("Legacy PM not supported with LLVM 15");
257 void LLVMRustAddLastExtensionPasses(
258 LLVMPassManagerBuilderRef PMBR, LLVMPassRef *Passes, size_t NumPasses) {
259 #if LLVM_VERSION_LT(15, 0)
260 auto AddExtensionPasses = [Passes, NumPasses](
261 const PassManagerBuilder &Builder, PassManagerBase &PM) {
262 for (size_t I = 0; I < NumPasses; I++) {
263 PM.add(unwrap(Passes[I]));
266 // Add the passes to both of the pre-finalization extension points,
267 // so they are run for optimized and non-optimized builds.
268 unwrap(PMBR)->addExtension(PassManagerBuilder::EP_OptimizerLast,
270 unwrap(PMBR)->addExtension(PassManagerBuilder::EP_EnabledOnOptLevel0,
273 report_fatal_error("Legacy PM not supported with LLVM 15");
277 #ifdef LLVM_COMPONENT_X86
278 #define SUBTARGET_X86 SUBTARGET(X86)
280 #define SUBTARGET_X86
283 #ifdef LLVM_COMPONENT_ARM
284 #define SUBTARGET_ARM SUBTARGET(ARM)
286 #define SUBTARGET_ARM
289 #ifdef LLVM_COMPONENT_AARCH64
290 #define SUBTARGET_AARCH64 SUBTARGET(AArch64)
292 #define SUBTARGET_AARCH64
295 #ifdef LLVM_COMPONENT_AVR
296 #define SUBTARGET_AVR SUBTARGET(AVR)
298 #define SUBTARGET_AVR
301 #ifdef LLVM_COMPONENT_M68k
302 #define SUBTARGET_M68K SUBTARGET(M68k)
304 #define SUBTARGET_M68K
307 #ifdef LLVM_COMPONENT_MIPS
308 #define SUBTARGET_MIPS SUBTARGET(Mips)
310 #define SUBTARGET_MIPS
313 #ifdef LLVM_COMPONENT_POWERPC
314 #define SUBTARGET_PPC SUBTARGET(PPC)
316 #define SUBTARGET_PPC
319 #ifdef LLVM_COMPONENT_SYSTEMZ
320 #define SUBTARGET_SYSTEMZ SUBTARGET(SystemZ)
322 #define SUBTARGET_SYSTEMZ
325 #ifdef LLVM_COMPONENT_MSP430
326 #define SUBTARGET_MSP430 SUBTARGET(MSP430)
328 #define SUBTARGET_MSP430
331 #ifdef LLVM_COMPONENT_RISCV
332 #define SUBTARGET_RISCV SUBTARGET(RISCV)
334 #define SUBTARGET_RISCV
337 #ifdef LLVM_COMPONENT_SPARC
338 #define SUBTARGET_SPARC SUBTARGET(Sparc)
340 #define SUBTARGET_SPARC
343 #ifdef LLVM_COMPONENT_HEXAGON
344 #define SUBTARGET_HEXAGON SUBTARGET(Hexagon)
346 #define SUBTARGET_HEXAGON
349 #define GEN_SUBTARGETS \
363 #define SUBTARGET(x) \
365 extern const SubtargetFeatureKV x##FeatureKV[]; \
366 extern const SubtargetFeatureKV x##SubTypeKV[]; \
372 extern "C" bool LLVMRustHasFeature(LLVMTargetMachineRef TM,
373 const char *Feature) {
374 TargetMachine *Target = unwrap(TM);
375 const MCSubtargetInfo *MCInfo = Target->getMCSubtargetInfo();
376 return MCInfo->checkFeatures(std::string("+") + Feature);
379 enum class LLVMRustCodeModel {
388 static Optional<CodeModel::Model> fromRust(LLVMRustCodeModel Model) {
390 case LLVMRustCodeModel::Tiny:
391 return CodeModel::Tiny;
392 case LLVMRustCodeModel::Small:
393 return CodeModel::Small;
394 case LLVMRustCodeModel::Kernel:
395 return CodeModel::Kernel;
396 case LLVMRustCodeModel::Medium:
397 return CodeModel::Medium;
398 case LLVMRustCodeModel::Large:
399 return CodeModel::Large;
400 case LLVMRustCodeModel::None:
403 report_fatal_error("Bad CodeModel.");
407 enum class LLVMRustCodeGenOptLevel {
414 static CodeGenOpt::Level fromRust(LLVMRustCodeGenOptLevel Level) {
416 case LLVMRustCodeGenOptLevel::None:
417 return CodeGenOpt::None;
418 case LLVMRustCodeGenOptLevel::Less:
419 return CodeGenOpt::Less;
420 case LLVMRustCodeGenOptLevel::Default:
421 return CodeGenOpt::Default;
422 case LLVMRustCodeGenOptLevel::Aggressive:
423 return CodeGenOpt::Aggressive;
425 report_fatal_error("Bad CodeGenOptLevel.");
429 enum class LLVMRustPassBuilderOptLevel {
438 #if LLVM_VERSION_LT(14,0)
439 using OptimizationLevel = PassBuilder::OptimizationLevel;
442 static OptimizationLevel fromRust(LLVMRustPassBuilderOptLevel Level) {
444 case LLVMRustPassBuilderOptLevel::O0:
445 return OptimizationLevel::O0;
446 case LLVMRustPassBuilderOptLevel::O1:
447 return OptimizationLevel::O1;
448 case LLVMRustPassBuilderOptLevel::O2:
449 return OptimizationLevel::O2;
450 case LLVMRustPassBuilderOptLevel::O3:
451 return OptimizationLevel::O3;
452 case LLVMRustPassBuilderOptLevel::Os:
453 return OptimizationLevel::Os;
454 case LLVMRustPassBuilderOptLevel::Oz:
455 return OptimizationLevel::Oz;
457 report_fatal_error("Bad PassBuilderOptLevel.");
461 enum class LLVMRustRelocModel {
470 static Reloc::Model fromRust(LLVMRustRelocModel RustReloc) {
472 case LLVMRustRelocModel::Static:
473 return Reloc::Static;
474 case LLVMRustRelocModel::PIC:
476 case LLVMRustRelocModel::DynamicNoPic:
477 return Reloc::DynamicNoPIC;
478 case LLVMRustRelocModel::ROPI:
480 case LLVMRustRelocModel::RWPI:
482 case LLVMRustRelocModel::ROPIRWPI:
483 return Reloc::ROPI_RWPI;
485 report_fatal_error("Bad RelocModel.");
489 /// getLongestEntryLength - Return the length of the longest entry in the table.
490 template<typename KV>
491 static size_t getLongestEntryLength(ArrayRef<KV> Table) {
493 for (auto &I : Table)
494 MaxLen = std::max(MaxLen, std::strlen(I.Key));
498 extern "C" void LLVMRustPrintTargetCPUs(LLVMTargetMachineRef TM) {
499 const TargetMachine *Target = unwrap(TM);
500 const MCSubtargetInfo *MCInfo = Target->getMCSubtargetInfo();
501 const Triple::ArchType HostArch = Triple(sys::getProcessTriple()).getArch();
502 const Triple::ArchType TargetArch = Target->getTargetTriple().getArch();
503 const ArrayRef<SubtargetSubTypeKV> CPUTable = MCInfo->getCPUTable();
504 unsigned MaxCPULen = getLongestEntryLength(CPUTable);
506 printf("Available CPUs for this target:\n");
507 if (HostArch == TargetArch) {
508 const StringRef HostCPU = sys::getHostCPUName();
509 printf(" %-*s - Select the CPU of the current host (currently %.*s).\n",
510 MaxCPULen, "native", (int)HostCPU.size(), HostCPU.data());
512 for (auto &CPU : CPUTable)
513 printf(" %-*s\n", MaxCPULen, CPU.Key);
517 extern "C" size_t LLVMRustGetTargetFeaturesCount(LLVMTargetMachineRef TM) {
518 const TargetMachine *Target = unwrap(TM);
519 const MCSubtargetInfo *MCInfo = Target->getMCSubtargetInfo();
520 const ArrayRef<SubtargetFeatureKV> FeatTable = MCInfo->getFeatureTable();
521 return FeatTable.size();
524 extern "C" void LLVMRustGetTargetFeature(LLVMTargetMachineRef TM, size_t Index,
525 const char** Feature, const char** Desc) {
526 const TargetMachine *Target = unwrap(TM);
527 const MCSubtargetInfo *MCInfo = Target->getMCSubtargetInfo();
528 const ArrayRef<SubtargetFeatureKV> FeatTable = MCInfo->getFeatureTable();
529 const SubtargetFeatureKV Feat = FeatTable[Index];
536 extern "C" void LLVMRustPrintTargetCPUs(LLVMTargetMachineRef) {
537 printf("Target CPU help is not supported by this LLVM version.\n\n");
540 extern "C" size_t LLVMRustGetTargetFeaturesCount(LLVMTargetMachineRef) {
544 extern "C" void LLVMRustGetTargetFeature(LLVMTargetMachineRef, const char**, const char**) {}
547 extern "C" const char* LLVMRustGetHostCPUName(size_t *len) {
548 StringRef Name = sys::getHostCPUName();
553 extern "C" LLVMTargetMachineRef LLVMRustCreateTargetMachine(
554 const char *TripleStr, const char *CPU, const char *Feature,
555 const char *ABIStr, LLVMRustCodeModel RustCM, LLVMRustRelocModel RustReloc,
556 LLVMRustCodeGenOptLevel RustOptLevel, bool UseSoftFloat,
557 bool FunctionSections,
559 bool UniqueSectionNames,
560 bool TrapUnreachable,
563 bool EmitStackSizeSection,
564 bool RelaxELFRelocations,
566 const char *SplitDwarfFile) {
568 auto OptLevel = fromRust(RustOptLevel);
569 auto RM = fromRust(RustReloc);
570 auto CM = fromRust(RustCM);
573 Triple Trip(Triple::normalize(TripleStr));
574 const llvm::Target *TheTarget =
575 TargetRegistry::lookupTarget(Trip.getTriple(), Error);
576 if (TheTarget == nullptr) {
577 LLVMRustSetLastError(Error.c_str());
581 TargetOptions Options;
583 Options.FloatABIType = FloatABI::Default;
585 Options.FloatABIType = FloatABI::Soft;
587 Options.DataSections = DataSections;
588 Options.FunctionSections = FunctionSections;
589 Options.UniqueSectionNames = UniqueSectionNames;
590 Options.MCOptions.AsmVerbose = AsmComments;
591 Options.MCOptions.PreserveAsmComments = AsmComments;
592 Options.MCOptions.ABIName = ABIStr;
593 if (SplitDwarfFile) {
594 Options.MCOptions.SplitDwarfFile = SplitDwarfFile;
596 Options.RelaxELFRelocations = RelaxELFRelocations;
597 Options.UseInitArray = UseInitArray;
599 if (TrapUnreachable) {
600 // Tell LLVM to codegen `unreachable` into an explicit trap instruction.
601 // This limits the extent of possible undefined behavior in some cases, as
602 // it prevents control flow from "falling through" into whatever code
603 // happens to be laid out next in memory.
604 Options.TrapUnreachable = true;
608 Options.ThreadModel = ThreadModel::Single;
611 Options.EmitStackSizeSection = EmitStackSizeSection;
613 TargetMachine *TM = TheTarget->createTargetMachine(
614 Trip.getTriple(), CPU, Feature, Options, RM, CM, OptLevel);
618 extern "C" void LLVMRustDisposeTargetMachine(LLVMTargetMachineRef TM) {
622 extern "C" void LLVMRustConfigurePassManagerBuilder(
623 LLVMPassManagerBuilderRef PMBR, LLVMRustCodeGenOptLevel OptLevel,
624 bool MergeFunctions, bool SLPVectorize, bool LoopVectorize, bool PrepareForThinLTO,
625 const char* PGOGenPath, const char* PGOUsePath, const char* PGOSampleUsePath,
627 #if LLVM_VERSION_LT(15, 0)
628 unwrap(PMBR)->MergeFunctions = MergeFunctions;
629 unwrap(PMBR)->SLPVectorize = SLPVectorize;
630 unwrap(PMBR)->OptLevel = fromRust(OptLevel);
631 unwrap(PMBR)->LoopVectorize = LoopVectorize;
632 unwrap(PMBR)->PrepareForThinLTO = PrepareForThinLTO;
633 unwrap(PMBR)->SizeLevel = SizeLevel;
634 unwrap(PMBR)->DisableUnrollLoops = SizeLevel != 0;
637 assert(!PGOUsePath && !PGOSampleUsePath);
638 unwrap(PMBR)->EnablePGOInstrGen = true;
639 unwrap(PMBR)->PGOInstrGen = PGOGenPath;
640 } else if (PGOUsePath) {
641 assert(!PGOSampleUsePath);
642 unwrap(PMBR)->PGOInstrUse = PGOUsePath;
643 } else if (PGOSampleUsePath) {
644 unwrap(PMBR)->PGOSampleUse = PGOSampleUsePath;
647 report_fatal_error("Legacy PM not supported with LLVM 15");
651 // Unfortunately, the LLVM C API doesn't provide a way to set the `LibraryInfo`
652 // field of a PassManagerBuilder, we expose our own method of doing so.
653 extern "C" void LLVMRustAddBuilderLibraryInfo(LLVMPassManagerBuilderRef PMBR,
655 bool DisableSimplifyLibCalls) {
656 Triple TargetTriple(unwrap(M)->getTargetTriple());
657 TargetLibraryInfoImpl *TLI = new TargetLibraryInfoImpl(TargetTriple);
658 if (DisableSimplifyLibCalls)
659 TLI->disableAllFunctions();
660 unwrap(PMBR)->LibraryInfo = TLI;
663 // Unfortunately, the LLVM C API doesn't provide a way to create the
664 // TargetLibraryInfo pass, so we use this method to do so.
665 extern "C" void LLVMRustAddLibraryInfo(LLVMPassManagerRef PMR, LLVMModuleRef M,
666 bool DisableSimplifyLibCalls) {
667 Triple TargetTriple(unwrap(M)->getTargetTriple());
668 TargetLibraryInfoImpl TLII(TargetTriple);
669 if (DisableSimplifyLibCalls)
670 TLII.disableAllFunctions();
671 unwrap(PMR)->add(new TargetLibraryInfoWrapperPass(TLII));
674 // Unfortunately, the LLVM C API doesn't provide an easy way of iterating over
675 // all the functions in a module, so we do that manually here. You'll find
676 // similar code in clang's BackendUtil.cpp file.
677 extern "C" void LLVMRustRunFunctionPassManager(LLVMPassManagerRef PMR,
679 llvm::legacy::FunctionPassManager *P =
680 unwrap<llvm::legacy::FunctionPassManager>(PMR);
681 P->doInitialization();
683 // Upgrade all calls to old intrinsics first.
684 for (Module::iterator I = unwrap(M)->begin(), E = unwrap(M)->end(); I != E;)
685 UpgradeCallsToIntrinsic(&*I++); // must be post-increment, as we remove
687 for (Module::iterator I = unwrap(M)->begin(), E = unwrap(M)->end(); I != E;
689 if (!I->isDeclaration())
695 extern "C" void LLVMRustSetLLVMOptions(int Argc, char **Argv) {
696 // Initializing the command-line options more than once is not allowed. So,
697 // check if they've already been initialized. (This could happen if we're
698 // being called from rustpkg, for example). If the arguments change, then
699 // that's just kinda unfortunate.
700 static bool Initialized = false;
704 cl::ParseCommandLineOptions(Argc, Argv);
707 enum class LLVMRustFileType {
712 static CodeGenFileType fromRust(LLVMRustFileType Type) {
714 case LLVMRustFileType::AssemblyFile:
715 return CGFT_AssemblyFile;
716 case LLVMRustFileType::ObjectFile:
717 return CGFT_ObjectFile;
719 report_fatal_error("Bad FileType.");
723 extern "C" LLVMRustResult
724 LLVMRustWriteOutputFile(LLVMTargetMachineRef Target, LLVMPassManagerRef PMR,
725 LLVMModuleRef M, const char *Path, const char *DwoPath,
726 LLVMRustFileType RustFileType) {
727 llvm::legacy::PassManager *PM = unwrap<llvm::legacy::PassManager>(PMR);
728 auto FileType = fromRust(RustFileType);
730 std::string ErrorInfo;
732 raw_fd_ostream OS(Path, EC, sys::fs::OF_None);
734 ErrorInfo = EC.message();
735 if (ErrorInfo != "") {
736 LLVMRustSetLastError(ErrorInfo.c_str());
737 return LLVMRustResult::Failure;
740 buffer_ostream BOS(OS);
742 raw_fd_ostream DOS(DwoPath, EC, sys::fs::OF_None);
745 ErrorInfo = EC.message();
746 if (ErrorInfo != "") {
747 LLVMRustSetLastError(ErrorInfo.c_str());
748 return LLVMRustResult::Failure;
750 buffer_ostream DBOS(DOS);
751 unwrap(Target)->addPassesToEmitFile(*PM, BOS, &DBOS, FileType, false);
754 unwrap(Target)->addPassesToEmitFile(*PM, BOS, nullptr, FileType, false);
758 // Apparently `addPassesToEmitFile` adds a pointer to our on-the-stack output
759 // stream (OS), so the only real safe place to delete this is here? Don't we
760 // wish this was written in Rust?
761 LLVMDisposePassManager(PMR);
762 return LLVMRustResult::Success;
765 extern "C" typedef void (*LLVMRustSelfProfileBeforePassCallback)(void*, // LlvmSelfProfiler
766 const char*, // pass name
767 const char*); // IR name
768 extern "C" typedef void (*LLVMRustSelfProfileAfterPassCallback)(void*); // LlvmSelfProfiler
770 std::string LLVMRustwrappedIrGetName(const llvm::Any &WrappedIr) {
771 if (any_isa<const Module *>(WrappedIr))
772 return any_cast<const Module *>(WrappedIr)->getName().str();
773 if (any_isa<const Function *>(WrappedIr))
774 return any_cast<const Function *>(WrappedIr)->getName().str();
775 if (any_isa<const Loop *>(WrappedIr))
776 return any_cast<const Loop *>(WrappedIr)->getName().str();
777 if (any_isa<const LazyCallGraph::SCC *>(WrappedIr))
778 return any_cast<const LazyCallGraph::SCC *>(WrappedIr)->getName();
783 void LLVMSelfProfileInitializeCallbacks(
784 PassInstrumentationCallbacks& PIC, void* LlvmSelfProfiler,
785 LLVMRustSelfProfileBeforePassCallback BeforePassCallback,
786 LLVMRustSelfProfileAfterPassCallback AfterPassCallback) {
787 PIC.registerBeforeNonSkippedPassCallback([LlvmSelfProfiler, BeforePassCallback](
788 StringRef Pass, llvm::Any Ir) {
789 std::string PassName = Pass.str();
790 std::string IrName = LLVMRustwrappedIrGetName(Ir);
791 BeforePassCallback(LlvmSelfProfiler, PassName.c_str(), IrName.c_str());
794 PIC.registerAfterPassCallback(
795 [LlvmSelfProfiler, AfterPassCallback](StringRef Pass, llvm::Any IR,
796 const PreservedAnalyses &Preserved) {
797 AfterPassCallback(LlvmSelfProfiler);
800 PIC.registerAfterPassInvalidatedCallback(
801 [LlvmSelfProfiler, AfterPassCallback](StringRef Pass, const PreservedAnalyses &Preserved) {
802 AfterPassCallback(LlvmSelfProfiler);
805 PIC.registerBeforeAnalysisCallback([LlvmSelfProfiler, BeforePassCallback](
806 StringRef Pass, llvm::Any Ir) {
807 std::string PassName = Pass.str();
808 std::string IrName = LLVMRustwrappedIrGetName(Ir);
809 BeforePassCallback(LlvmSelfProfiler, PassName.c_str(), IrName.c_str());
812 PIC.registerAfterAnalysisCallback(
813 [LlvmSelfProfiler, AfterPassCallback](StringRef Pass, llvm::Any Ir) {
814 AfterPassCallback(LlvmSelfProfiler);
818 enum class LLVMRustOptStage {
826 struct LLVMRustSanitizerOptions {
827 bool SanitizeAddress;
828 bool SanitizeAddressRecover;
830 bool SanitizeMemoryRecover;
831 int SanitizeMemoryTrackOrigins;
833 bool SanitizeHWAddress;
834 bool SanitizeHWAddressRecover;
837 extern "C" LLVMRustResult
838 LLVMRustOptimizeWithNewPassManager(
839 LLVMModuleRef ModuleRef,
840 LLVMTargetMachineRef TMRef,
841 LLVMRustPassBuilderOptLevel OptLevelRust,
842 LLVMRustOptStage OptStage,
843 bool NoPrepopulatePasses, bool VerifyIR, bool UseThinLTOBuffers,
844 bool MergeFunctions, bool UnrollLoops, bool SLPVectorize, bool LoopVectorize,
845 bool DisableSimplifyLibCalls, bool EmitLifetimeMarkers,
846 LLVMRustSanitizerOptions *SanitizerOptions,
847 const char *PGOGenPath, const char *PGOUsePath,
848 bool InstrumentCoverage, bool InstrumentGCOV,
849 const char *PGOSampleUsePath, bool DebugInfoForProfiling,
850 void* LlvmSelfProfiler,
851 LLVMRustSelfProfileBeforePassCallback BeforePassCallback,
852 LLVMRustSelfProfileAfterPassCallback AfterPassCallback,
853 const char *ExtraPasses, size_t ExtraPassesLen,
854 const char *LLVMPlugins, size_t LLVMPluginsLen) {
855 Module *TheModule = unwrap(ModuleRef);
856 TargetMachine *TM = unwrap(TMRef);
857 OptimizationLevel OptLevel = fromRust(OptLevelRust);
860 PipelineTuningOptions PTO;
861 PTO.LoopUnrolling = UnrollLoops;
862 PTO.LoopInterleaving = UnrollLoops;
863 PTO.LoopVectorization = LoopVectorize;
864 PTO.SLPVectorization = SLPVectorize;
865 PTO.MergeFunctions = MergeFunctions;
867 // FIXME: We may want to expose this as an option.
868 bool DebugPassManager = false;
870 PassInstrumentationCallbacks PIC;
871 StandardInstrumentations SI(DebugPassManager);
872 SI.registerCallbacks(PIC);
874 if (LlvmSelfProfiler){
875 LLVMSelfProfileInitializeCallbacks(PIC,LlvmSelfProfiler,BeforePassCallback,AfterPassCallback);
878 Optional<PGOOptions> PGOOpt;
880 assert(!PGOUsePath && !PGOSampleUsePath);
881 PGOOpt = PGOOptions(PGOGenPath, "", "", PGOOptions::IRInstr,
882 PGOOptions::NoCSAction, DebugInfoForProfiling);
883 } else if (PGOUsePath) {
884 assert(!PGOSampleUsePath);
885 PGOOpt = PGOOptions(PGOUsePath, "", "", PGOOptions::IRUse,
886 PGOOptions::NoCSAction, DebugInfoForProfiling);
887 } else if (PGOSampleUsePath) {
888 PGOOpt = PGOOptions(PGOSampleUsePath, "", "", PGOOptions::SampleUse,
889 PGOOptions::NoCSAction, DebugInfoForProfiling);
890 } else if (DebugInfoForProfiling) {
891 PGOOpt = PGOOptions("", "", "", PGOOptions::NoAction,
892 PGOOptions::NoCSAction, DebugInfoForProfiling);
895 #if LLVM_VERSION_GE(13, 0)
896 PassBuilder PB(TM, PTO, PGOOpt, &PIC);
897 LoopAnalysisManager LAM;
898 FunctionAnalysisManager FAM;
899 CGSCCAnalysisManager CGAM;
900 ModuleAnalysisManager MAM;
902 PassBuilder PB(DebugPassManager, TM, PTO, PGOOpt, &PIC);
903 LoopAnalysisManager LAM(DebugPassManager);
904 FunctionAnalysisManager FAM(DebugPassManager);
905 CGSCCAnalysisManager CGAM(DebugPassManager);
906 ModuleAnalysisManager MAM(DebugPassManager);
909 FAM.registerPass([&] { return PB.buildDefaultAAPipeline(); });
911 Triple TargetTriple(TheModule->getTargetTriple());
912 std::unique_ptr<TargetLibraryInfoImpl> TLII(new TargetLibraryInfoImpl(TargetTriple));
913 if (DisableSimplifyLibCalls)
914 TLII->disableAllFunctions();
915 FAM.registerPass([&] { return TargetLibraryAnalysis(*TLII); });
917 PB.registerModuleAnalyses(MAM);
918 PB.registerCGSCCAnalyses(CGAM);
919 PB.registerFunctionAnalyses(FAM);
920 PB.registerLoopAnalyses(LAM);
921 PB.crossRegisterProxies(LAM, FAM, CGAM, MAM);
923 // We manually collect pipeline callbacks so we can apply them at O0, where the
924 // PassBuilder does not create a pipeline.
925 std::vector<std::function<void(ModulePassManager &, OptimizationLevel)>>
926 PipelineStartEPCallbacks;
927 std::vector<std::function<void(ModulePassManager &, OptimizationLevel)>>
928 OptimizerLastEPCallbacks;
931 PipelineStartEPCallbacks.push_back(
932 [VerifyIR](ModulePassManager &MPM, OptimizationLevel Level) {
933 MPM.addPass(VerifierPass());
938 if (InstrumentGCOV) {
939 PipelineStartEPCallbacks.push_back(
940 [](ModulePassManager &MPM, OptimizationLevel Level) {
941 MPM.addPass(GCOVProfilerPass(GCOVOptions::getDefault()));
946 if (InstrumentCoverage) {
947 PipelineStartEPCallbacks.push_back(
948 [](ModulePassManager &MPM, OptimizationLevel Level) {
949 InstrProfOptions Options;
950 MPM.addPass(InstrProfiling(Options, false));
955 if (SanitizerOptions) {
956 if (SanitizerOptions->SanitizeMemory) {
957 MemorySanitizerOptions Options(
958 SanitizerOptions->SanitizeMemoryTrackOrigins,
959 SanitizerOptions->SanitizeMemoryRecover,
960 /*CompileKernel=*/false);
961 OptimizerLastEPCallbacks.push_back(
962 [Options](ModulePassManager &MPM, OptimizationLevel Level) {
963 #if LLVM_VERSION_GE(14, 0)
964 MPM.addPass(ModuleMemorySanitizerPass(Options));
966 MPM.addPass(MemorySanitizerPass(Options));
968 MPM.addPass(createModuleToFunctionPassAdaptor(MemorySanitizerPass(Options)));
973 if (SanitizerOptions->SanitizeThread) {
974 OptimizerLastEPCallbacks.push_back(
975 [](ModulePassManager &MPM, OptimizationLevel Level) {
976 #if LLVM_VERSION_GE(14, 0)
977 MPM.addPass(ModuleThreadSanitizerPass());
979 MPM.addPass(ThreadSanitizerPass());
981 MPM.addPass(createModuleToFunctionPassAdaptor(ThreadSanitizerPass()));
986 if (SanitizerOptions->SanitizeAddress) {
987 OptimizerLastEPCallbacks.push_back(
988 [SanitizerOptions](ModulePassManager &MPM, OptimizationLevel Level) {
989 #if LLVM_VERSION_LT(15, 0)
990 MPM.addPass(RequireAnalysisPass<ASanGlobalsMetadataAnalysis, Module>());
992 #if LLVM_VERSION_GE(14, 0)
993 AddressSanitizerOptions opts = AddressSanitizerOptions{
994 /*CompileKernel=*/false,
995 SanitizerOptions->SanitizeAddressRecover,
996 /*UseAfterScope=*/true,
997 AsanDetectStackUseAfterReturnMode::Runtime,
999 MPM.addPass(ModuleAddressSanitizerPass(opts));
1001 MPM.addPass(ModuleAddressSanitizerPass(
1002 /*CompileKernel=*/false, SanitizerOptions->SanitizeAddressRecover));
1003 MPM.addPass(createModuleToFunctionPassAdaptor(AddressSanitizerPass(
1004 /*CompileKernel=*/false, SanitizerOptions->SanitizeAddressRecover,
1005 /*UseAfterScope=*/true)));
1010 if (SanitizerOptions->SanitizeHWAddress) {
1011 OptimizerLastEPCallbacks.push_back(
1012 [SanitizerOptions](ModulePassManager &MPM, OptimizationLevel Level) {
1013 #if LLVM_VERSION_GE(14, 0)
1014 HWAddressSanitizerOptions opts(
1015 /*CompileKernel=*/false, SanitizerOptions->SanitizeHWAddressRecover,
1016 /*DisableOptimization=*/false);
1017 MPM.addPass(HWAddressSanitizerPass(opts));
1019 MPM.addPass(HWAddressSanitizerPass(
1020 /*CompileKernel=*/false, SanitizerOptions->SanitizeHWAddressRecover));
1027 if (LLVMPluginsLen) {
1028 auto PluginsStr = StringRef(LLVMPlugins, LLVMPluginsLen);
1029 SmallVector<StringRef> Plugins;
1030 PluginsStr.split(Plugins, ',', -1, false);
1031 for (auto PluginPath: Plugins) {
1032 auto Plugin = PassPlugin::Load(PluginPath.str());
1034 LLVMRustSetLastError(("Failed to load pass plugin" + PluginPath.str()).c_str());
1037 Plugin->registerPassBuilderCallbacks(PB);
1041 #if LLVM_VERSION_GE(13, 0)
1042 ModulePassManager MPM;
1044 ModulePassManager MPM(DebugPassManager);
1046 bool NeedThinLTOBufferPasses = UseThinLTOBuffers;
1047 if (!NoPrepopulatePasses) {
1048 // The pre-link pipelines don't support O0 and require using budilO0DefaultPipeline() instead.
1049 // At the same time, the LTO pipelines do support O0 and using them is required.
1050 bool IsLTO = OptStage == LLVMRustOptStage::ThinLTO || OptStage == LLVMRustOptStage::FatLTO;
1051 if (OptLevel == OptimizationLevel::O0 && !IsLTO) {
1052 for (const auto &C : PipelineStartEPCallbacks)
1053 PB.registerPipelineStartEPCallback(C);
1054 for (const auto &C : OptimizerLastEPCallbacks)
1055 PB.registerOptimizerLastEPCallback(C);
1057 // Pass false as we manually schedule ThinLTOBufferPasses below.
1058 MPM = PB.buildO0DefaultPipeline(OptLevel, /* PreLinkLTO */ false);
1060 for (const auto &C : PipelineStartEPCallbacks)
1061 PB.registerPipelineStartEPCallback(C);
1062 if (OptStage != LLVMRustOptStage::PreLinkThinLTO) {
1063 for (const auto &C : OptimizerLastEPCallbacks)
1064 PB.registerOptimizerLastEPCallback(C);
1068 case LLVMRustOptStage::PreLinkNoLTO:
1069 MPM = PB.buildPerModuleDefaultPipeline(OptLevel, DebugPassManager);
1071 case LLVMRustOptStage::PreLinkThinLTO:
1072 MPM = PB.buildThinLTOPreLinkDefaultPipeline(OptLevel);
1073 // The ThinLTOPreLink pipeline already includes ThinLTOBuffer passes. However, callback
1074 // passes may still run afterwards. This means we need to run the buffer passes again.
1075 // FIXME: In LLVM 13, the ThinLTOPreLink pipeline also runs OptimizerLastEPCallbacks
1076 // before the RequiredLTOPreLinkPasses, in which case we can remove these hacks.
1077 if (OptimizerLastEPCallbacks.empty())
1078 NeedThinLTOBufferPasses = false;
1079 for (const auto &C : OptimizerLastEPCallbacks)
1082 case LLVMRustOptStage::PreLinkFatLTO:
1083 MPM = PB.buildLTOPreLinkDefaultPipeline(OptLevel);
1084 NeedThinLTOBufferPasses = false;
1086 case LLVMRustOptStage::ThinLTO:
1087 // FIXME: Does it make sense to pass the ModuleSummaryIndex?
1088 // It only seems to be needed for C++ specific optimizations.
1089 MPM = PB.buildThinLTODefaultPipeline(OptLevel, nullptr);
1091 case LLVMRustOptStage::FatLTO:
1092 MPM = PB.buildLTODefaultPipeline(OptLevel, nullptr);
1097 // We're not building any of the default pipelines but we still want to
1098 // add the verifier, instrumentation, etc passes if they were requested
1099 for (const auto &C : PipelineStartEPCallbacks)
1101 for (const auto &C : OptimizerLastEPCallbacks)
1105 if (ExtraPassesLen) {
1106 if (auto Err = PB.parsePassPipeline(MPM, StringRef(ExtraPasses, ExtraPassesLen))) {
1107 std::string ErrMsg = toString(std::move(Err));
1108 LLVMRustSetLastError(ErrMsg.c_str());
1109 return LLVMRustResult::Failure;
1113 if (NeedThinLTOBufferPasses) {
1114 MPM.addPass(CanonicalizeAliasesPass());
1115 MPM.addPass(NameAnonGlobalPass());
1118 // Upgrade all calls to old intrinsics first.
1119 for (Module::iterator I = TheModule->begin(), E = TheModule->end(); I != E;)
1120 UpgradeCallsToIntrinsic(&*I++); // must be post-increment, as we remove
1122 MPM.run(*TheModule, MAM);
1123 return LLVMRustResult::Success;
1126 // Callback to demangle function name
1128 // * name to be demangled
1131 // * output buffer len
1132 // Returns len of demangled string, or 0 if demangle failed.
1133 typedef size_t (*DemangleFn)(const char*, size_t, char*, size_t);
1138 class RustAssemblyAnnotationWriter : public AssemblyAnnotationWriter {
1139 DemangleFn Demangle;
1140 std::vector<char> Buf;
1143 RustAssemblyAnnotationWriter(DemangleFn Demangle) : Demangle(Demangle) {}
1145 // Return empty string if demangle failed
1146 // or if name does not need to be demangled
1147 StringRef CallDemangle(StringRef name) {
1152 if (Buf.size() < name.size() * 2) {
1153 // Semangled name usually shorter than mangled,
1154 // but allocate twice as much memory just in case
1155 Buf.resize(name.size() * 2);
1158 auto R = Demangle(name.data(), name.size(), Buf.data(), Buf.size());
1164 auto Demangled = StringRef(Buf.data(), R);
1165 if (Demangled == name) {
1166 // Do not print anything if demangled name is equal to mangled.
1173 void emitFunctionAnnot(const Function *F,
1174 formatted_raw_ostream &OS) override {
1175 StringRef Demangled = CallDemangle(F->getName());
1176 if (Demangled.empty()) {
1180 OS << "; " << Demangled << "\n";
1183 void emitInstructionAnnot(const Instruction *I,
1184 formatted_raw_ostream &OS) override {
1187 if (const CallInst *CI = dyn_cast<CallInst>(I)) {
1189 Value = CI->getCalledOperand();
1190 } else if (const InvokeInst* II = dyn_cast<InvokeInst>(I)) {
1192 Value = II->getCalledOperand();
1194 // Could demangle more operations, e. g.
1195 // `store %place, @function`.
1199 if (!Value->hasName()) {
1203 StringRef Demangled = CallDemangle(Value->getName());
1204 if (Demangled.empty()) {
1208 OS << "; " << Name << " " << Demangled << "\n";
1214 extern "C" LLVMRustResult
1215 LLVMRustPrintModule(LLVMModuleRef M, const char *Path, DemangleFn Demangle) {
1216 std::string ErrorInfo;
1218 raw_fd_ostream OS(Path, EC, sys::fs::OF_None);
1220 ErrorInfo = EC.message();
1221 if (ErrorInfo != "") {
1222 LLVMRustSetLastError(ErrorInfo.c_str());
1223 return LLVMRustResult::Failure;
1226 RustAssemblyAnnotationWriter AAW(Demangle);
1227 formatted_raw_ostream FOS(OS);
1228 unwrap(M)->print(FOS, &AAW);
1230 return LLVMRustResult::Success;
1233 extern "C" void LLVMRustPrintPasses() {
1234 LLVMInitializePasses();
1235 struct MyListener : PassRegistrationListener {
1236 void passEnumerate(const PassInfo *Info) {
1237 StringRef PassArg = Info->getPassArgument();
1238 StringRef PassName = Info->getPassName();
1239 if (!PassArg.empty()) {
1240 // These unsigned->signed casts could theoretically overflow, but
1241 // realistically never will (and even if, the result is implementation
1242 // defined rather plain UB).
1243 printf("%15.*s - %.*s\n", (int)PassArg.size(), PassArg.data(),
1244 (int)PassName.size(), PassName.data());
1249 PassRegistry *PR = PassRegistry::getPassRegistry();
1250 PR->enumerateWith(&Listener);
1253 extern "C" void LLVMRustAddAlwaysInlinePass(LLVMPassManagerBuilderRef PMBR,
1254 bool AddLifetimes) {
1255 unwrap(PMBR)->Inliner = llvm::createAlwaysInlinerLegacyPass(AddLifetimes);
1258 extern "C" void LLVMRustRunRestrictionPass(LLVMModuleRef M, char **Symbols,
1260 llvm::legacy::PassManager passes;
1262 auto PreserveFunctions = [=](const GlobalValue &GV) {
1263 for (size_t I = 0; I < Len; I++) {
1264 if (GV.getName() == Symbols[I]) {
1271 passes.add(llvm::createInternalizePass(PreserveFunctions));
1273 passes.run(*unwrap(M));
1277 LLVMRustSetDataLayoutFromTargetMachine(LLVMModuleRef Module,
1278 LLVMTargetMachineRef TMR) {
1279 TargetMachine *Target = unwrap(TMR);
1280 unwrap(Module)->setDataLayout(Target->createDataLayout());
1283 extern "C" void LLVMRustSetModulePICLevel(LLVMModuleRef M) {
1284 unwrap(M)->setPICLevel(PICLevel::Level::BigPIC);
1287 extern "C" void LLVMRustSetModulePIELevel(LLVMModuleRef M) {
1288 unwrap(M)->setPIELevel(PIELevel::Level::Large);
1291 extern "C" void LLVMRustSetModuleCodeModel(LLVMModuleRef M,
1292 LLVMRustCodeModel Model) {
1293 auto CM = fromRust(Model);
1296 unwrap(M)->setCodeModel(*CM);
1299 // Here you'll find an implementation of ThinLTO as used by the Rust compiler
1300 // right now. This ThinLTO support is only enabled on "recent ish" versions of
1301 // LLVM, and otherwise it's just blanket rejected from other compilers.
1303 // Most of this implementation is straight copied from LLVM. At the time of
1304 // this writing it wasn't *quite* suitable to reuse more code from upstream
1305 // for our purposes, but we should strive to upstream this support once it's
1306 // ready to go! I figure we may want a bit of testing locally first before
1307 // sending this upstream to LLVM. I hear though they're quite eager to receive
1308 // feedback like this!
1310 // If you're reading this code and wondering "what in the world" or you're
1311 // working "good lord by LLVM upgrade is *still* failing due to these bindings"
1312 // then fear not! (ok maybe fear a little). All code here is mostly based
1313 // on `lib/LTO/ThinLTOCodeGenerator.cpp` in LLVM.
1315 // You'll find that the general layout here roughly corresponds to the `run`
1316 // method in that file as well as `ProcessThinLTOModule`. Functions are
1317 // specifically commented below as well, but if you're updating this code
1318 // or otherwise trying to understand it, the LLVM source will be useful in
1319 // interpreting the mysteries within.
1321 // Otherwise I'll apologize in advance, it probably requires a relatively
1322 // significant investment on your part to "truly understand" what's going on
1323 // here. Not saying I do myself, but it took me awhile staring at LLVM's source
1324 // and various online resources about ThinLTO to make heads or tails of all
1327 // This is a shared data structure which *must* be threadsafe to share
1328 // read-only amongst threads. This also corresponds basically to the arguments
1329 // of the `ProcessThinLTOModule` function in the LLVM source.
1330 struct LLVMRustThinLTOData {
1331 // The combined index that is the global analysis over all modules we're
1332 // performing ThinLTO for. This is mostly managed by LLVM.
1333 ModuleSummaryIndex Index;
1335 // All modules we may look at, stored as in-memory serialized versions. This
1336 // is later used when inlining to ensure we can extract any module to inline
1338 StringMap<MemoryBufferRef> ModuleMap;
1340 // A set that we manage of everything we *don't* want internalized. Note that
1341 // this includes all transitive references right now as well, but it may not
1343 DenseSet<GlobalValue::GUID> GUIDPreservedSymbols;
1345 // Not 100% sure what these are, but they impact what's internalized and
1346 // what's inlined across modules, I believe.
1347 StringMap<FunctionImporter::ImportMapTy> ImportLists;
1348 StringMap<FunctionImporter::ExportSetTy> ExportLists;
1349 StringMap<GVSummaryMapTy> ModuleToDefinedGVSummaries;
1350 StringMap<std::map<GlobalValue::GUID, GlobalValue::LinkageTypes>> ResolvedODR;
1352 LLVMRustThinLTOData() : Index(/* HaveGVs = */ false) {}
1355 // Just an argument to the `LLVMRustCreateThinLTOData` function below.
1356 struct LLVMRustThinLTOModule {
1357 const char *identifier;
1362 // This is copied from `lib/LTO/ThinLTOCodeGenerator.cpp`, not sure what it
1364 static const GlobalValueSummary *
1365 getFirstDefinitionForLinker(const GlobalValueSummaryList &GVSummaryList) {
1366 auto StrongDefForLinker = llvm::find_if(
1367 GVSummaryList, [](const std::unique_ptr<GlobalValueSummary> &Summary) {
1368 auto Linkage = Summary->linkage();
1369 return !GlobalValue::isAvailableExternallyLinkage(Linkage) &&
1370 !GlobalValue::isWeakForLinker(Linkage);
1372 if (StrongDefForLinker != GVSummaryList.end())
1373 return StrongDefForLinker->get();
1375 auto FirstDefForLinker = llvm::find_if(
1376 GVSummaryList, [](const std::unique_ptr<GlobalValueSummary> &Summary) {
1377 auto Linkage = Summary->linkage();
1378 return !GlobalValue::isAvailableExternallyLinkage(Linkage);
1380 if (FirstDefForLinker == GVSummaryList.end())
1382 return FirstDefForLinker->get();
1385 // The main entry point for creating the global ThinLTO analysis. The structure
1386 // here is basically the same as before threads are spawned in the `run`
1387 // function of `lib/LTO/ThinLTOCodeGenerator.cpp`.
1388 extern "C" LLVMRustThinLTOData*
1389 LLVMRustCreateThinLTOData(LLVMRustThinLTOModule *modules,
1391 const char **preserved_symbols,
1393 auto Ret = std::make_unique<LLVMRustThinLTOData>();
1395 // Load each module's summary and merge it into one combined index
1396 for (int i = 0; i < num_modules; i++) {
1397 auto module = &modules[i];
1398 StringRef buffer(module->data, module->len);
1399 MemoryBufferRef mem_buffer(buffer, module->identifier);
1401 Ret->ModuleMap[module->identifier] = mem_buffer;
1403 if (Error Err = readModuleSummaryIndex(mem_buffer, Ret->Index, i)) {
1404 LLVMRustSetLastError(toString(std::move(Err)).c_str());
1409 // Collect for each module the list of function it defines (GUID -> Summary)
1410 Ret->Index.collectDefinedGVSummariesPerModule(Ret->ModuleToDefinedGVSummaries);
1412 // Convert the preserved symbols set from string to GUID, this is then needed
1413 // for internalization.
1414 for (int i = 0; i < num_symbols; i++) {
1415 auto GUID = GlobalValue::getGUID(preserved_symbols[i]);
1416 Ret->GUIDPreservedSymbols.insert(GUID);
1419 // Collect the import/export lists for all modules from the call-graph in the
1422 // This is copied from `lib/LTO/ThinLTOCodeGenerator.cpp`
1423 auto deadIsPrevailing = [&](GlobalValue::GUID G) {
1424 return PrevailingType::Unknown;
1426 // We don't have a complete picture in our use of ThinLTO, just our immediate
1427 // crate, so we need `ImportEnabled = false` to limit internalization.
1428 // Otherwise, we sometimes lose `static` values -- see #60184.
1429 computeDeadSymbolsWithConstProp(Ret->Index, Ret->GUIDPreservedSymbols,
1430 deadIsPrevailing, /* ImportEnabled = */ false);
1431 ComputeCrossModuleImport(
1433 Ret->ModuleToDefinedGVSummaries,
1438 // Resolve LinkOnce/Weak symbols, this has to be computed early be cause it
1439 // impacts the caching.
1441 // This is copied from `lib/LTO/ThinLTOCodeGenerator.cpp` with some of this
1442 // being lifted from `lib/LTO/LTO.cpp` as well
1443 DenseMap<GlobalValue::GUID, const GlobalValueSummary *> PrevailingCopy;
1444 for (auto &I : Ret->Index) {
1445 if (I.second.SummaryList.size() > 1)
1446 PrevailingCopy[I.first] = getFirstDefinitionForLinker(I.second.SummaryList);
1448 auto isPrevailing = [&](GlobalValue::GUID GUID, const GlobalValueSummary *S) {
1449 const auto &Prevailing = PrevailingCopy.find(GUID);
1450 if (Prevailing == PrevailingCopy.end())
1452 return Prevailing->second == S;
1454 auto recordNewLinkage = [&](StringRef ModuleIdentifier,
1455 GlobalValue::GUID GUID,
1456 GlobalValue::LinkageTypes NewLinkage) {
1457 Ret->ResolvedODR[ModuleIdentifier][GUID] = NewLinkage;
1460 #if LLVM_VERSION_GE(13,0)
1461 // Uses FromPrevailing visibility scheme which works for many binary
1462 // formats. We probably could and should use ELF visibility scheme for many of
1463 // our targets, however.
1465 thinLTOResolvePrevailingInIndex(conf, Ret->Index, isPrevailing, recordNewLinkage,
1466 Ret->GUIDPreservedSymbols);
1468 thinLTOResolvePrevailingInIndex(Ret->Index, isPrevailing, recordNewLinkage,
1469 Ret->GUIDPreservedSymbols);
1471 // Here we calculate an `ExportedGUIDs` set for use in the `isExported`
1472 // callback below. This callback below will dictate the linkage for all
1473 // summaries in the index, and we basically just only want to ensure that dead
1474 // symbols are internalized. Otherwise everything that's already external
1475 // linkage will stay as external, and internal will stay as internal.
1476 std::set<GlobalValue::GUID> ExportedGUIDs;
1477 for (auto &List : Ret->Index) {
1478 for (auto &GVS: List.second.SummaryList) {
1479 if (GlobalValue::isLocalLinkage(GVS->linkage()))
1481 auto GUID = GVS->getOriginalName();
1482 if (GVS->flags().Live)
1483 ExportedGUIDs.insert(GUID);
1486 auto isExported = [&](StringRef ModuleIdentifier, ValueInfo VI) {
1487 const auto &ExportList = Ret->ExportLists.find(ModuleIdentifier);
1488 return (ExportList != Ret->ExportLists.end() &&
1489 ExportList->second.count(VI)) ||
1490 ExportedGUIDs.count(VI.getGUID());
1492 thinLTOInternalizeAndPromoteInIndex(Ret->Index, isExported, isPrevailing);
1494 return Ret.release();
1498 LLVMRustFreeThinLTOData(LLVMRustThinLTOData *Data) {
1502 // Below are the various passes that happen *per module* when doing ThinLTO.
1504 // In other words, these are the functions that are all run concurrently
1505 // with one another, one per module. The passes here correspond to the analysis
1506 // passes in `lib/LTO/ThinLTOCodeGenerator.cpp`, currently found in the
1507 // `ProcessThinLTOModule` function. Here they're split up into separate steps
1508 // so rustc can save off the intermediate bytecode between each step.
1511 clearDSOLocalOnDeclarations(Module &Mod, TargetMachine &TM) {
1512 // When linking an ELF shared object, dso_local should be dropped. We
1513 // conservatively do this for -fpic.
1514 bool ClearDSOLocalOnDeclarations =
1515 TM.getTargetTriple().isOSBinFormatELF() &&
1516 TM.getRelocationModel() != Reloc::Static &&
1517 Mod.getPIELevel() == PIELevel::Default;
1518 return ClearDSOLocalOnDeclarations;
1522 LLVMRustPrepareThinLTORename(const LLVMRustThinLTOData *Data, LLVMModuleRef M,
1523 LLVMTargetMachineRef TM) {
1524 Module &Mod = *unwrap(M);
1525 TargetMachine &Target = *unwrap(TM);
1527 bool ClearDSOLocal = clearDSOLocalOnDeclarations(Mod, Target);
1528 bool error = renameModuleForThinLTO(Mod, Data->Index, ClearDSOLocal);
1531 LLVMRustSetLastError("renameModuleForThinLTO failed");
1538 LLVMRustPrepareThinLTOResolveWeak(const LLVMRustThinLTOData *Data, LLVMModuleRef M) {
1539 Module &Mod = *unwrap(M);
1540 const auto &DefinedGlobals = Data->ModuleToDefinedGVSummaries.lookup(Mod.getModuleIdentifier());
1541 #if LLVM_VERSION_GE(14, 0)
1542 thinLTOFinalizeInModule(Mod, DefinedGlobals, /*PropagateAttrs=*/true);
1544 thinLTOResolvePrevailingInModule(Mod, DefinedGlobals);
1550 LLVMRustPrepareThinLTOInternalize(const LLVMRustThinLTOData *Data, LLVMModuleRef M) {
1551 Module &Mod = *unwrap(M);
1552 const auto &DefinedGlobals = Data->ModuleToDefinedGVSummaries.lookup(Mod.getModuleIdentifier());
1553 thinLTOInternalizeModule(Mod, DefinedGlobals);
1558 LLVMRustPrepareThinLTOImport(const LLVMRustThinLTOData *Data, LLVMModuleRef M,
1559 LLVMTargetMachineRef TM) {
1560 Module &Mod = *unwrap(M);
1561 TargetMachine &Target = *unwrap(TM);
1563 const auto &ImportList = Data->ImportLists.lookup(Mod.getModuleIdentifier());
1564 auto Loader = [&](StringRef Identifier) {
1565 const auto &Memory = Data->ModuleMap.lookup(Identifier);
1566 auto &Context = Mod.getContext();
1567 auto MOrErr = getLazyBitcodeModule(Memory, Context, true, true);
1572 // The rest of this closure is a workaround for
1573 // https://bugs.llvm.org/show_bug.cgi?id=38184 where during ThinLTO imports
1574 // we accidentally import wasm custom sections into different modules,
1575 // duplicating them by in the final output artifact.
1577 // The issue is worked around here by manually removing the
1578 // `wasm.custom_sections` named metadata node from any imported module. This
1579 // we know isn't used by any optimization pass so there's no need for it to
1582 // Note that the metadata is currently lazily loaded, so we materialize it
1583 // here before looking up if there's metadata inside. The `FunctionImporter`
1584 // will immediately materialize metadata anyway after an import, so this
1585 // shouldn't be a perf hit.
1586 if (Error Err = (*MOrErr)->materializeMetadata()) {
1587 Expected<std::unique_ptr<Module>> Ret(std::move(Err));
1591 auto *WasmCustomSections = (*MOrErr)->getNamedMetadata("wasm.custom_sections");
1592 if (WasmCustomSections)
1593 WasmCustomSections->eraseFromParent();
1597 bool ClearDSOLocal = clearDSOLocalOnDeclarations(Mod, Target);
1598 FunctionImporter Importer(Data->Index, Loader, ClearDSOLocal);
1599 Expected<bool> Result = Importer.importFunctions(Mod, ImportList);
1601 LLVMRustSetLastError(toString(Result.takeError()).c_str());
1607 extern "C" typedef void (*LLVMRustModuleNameCallback)(void*, // payload
1608 const char*, // importing module name
1609 const char*); // imported module name
1611 // Calls `module_name_callback` for each module import done by ThinLTO.
1612 // The callback is provided with regular null-terminated C strings.
1614 LLVMRustGetThinLTOModules(const LLVMRustThinLTOData *data,
1615 LLVMRustModuleNameCallback module_name_callback,
1616 void* callback_payload) {
1617 for (const auto& importing_module : data->ImportLists) {
1618 const std::string importing_module_id = importing_module.getKey().str();
1619 const auto& imports = importing_module.getValue();
1620 for (const auto& imported_module : imports) {
1621 const std::string imported_module_id = imported_module.getKey().str();
1622 module_name_callback(callback_payload,
1623 importing_module_id.c_str(),
1624 imported_module_id.c_str());
1629 // This struct and various functions are sort of a hack right now, but the
1630 // problem is that we've got in-memory LLVM modules after we generate and
1631 // optimize all codegen-units for one compilation in rustc. To be compatible
1632 // with the LTO support above we need to serialize the modules plus their
1633 // ThinLTO summary into memory.
1635 // This structure is basically an owned version of a serialize module, with
1636 // a ThinLTO summary attached.
1637 struct LLVMRustThinLTOBuffer {
1641 extern "C" LLVMRustThinLTOBuffer*
1642 LLVMRustThinLTOBufferCreate(LLVMModuleRef M, bool is_thin) {
1643 auto Ret = std::make_unique<LLVMRustThinLTOBuffer>();
1645 raw_string_ostream OS(Ret->data);
1647 legacy::PassManager PM;
1649 PM.add(createWriteThinLTOBitcodePass(OS));
1651 PM.add(createBitcodeWriterPass(OS));
1656 return Ret.release();
1660 LLVMRustThinLTOBufferFree(LLVMRustThinLTOBuffer *Buffer) {
1664 extern "C" const void*
1665 LLVMRustThinLTOBufferPtr(const LLVMRustThinLTOBuffer *Buffer) {
1666 return Buffer->data.data();
1670 LLVMRustThinLTOBufferLen(const LLVMRustThinLTOBuffer *Buffer) {
1671 return Buffer->data.length();
1674 // This is what we used to parse upstream bitcode for actual ThinLTO
1675 // processing. We'll call this once per module optimized through ThinLTO, and
1676 // it'll be called concurrently on many threads.
1677 extern "C" LLVMModuleRef
1678 LLVMRustParseBitcodeForLTO(LLVMContextRef Context,
1681 const char *identifier) {
1682 StringRef Data(data, len);
1683 MemoryBufferRef Buffer(Data, identifier);
1684 unwrap(Context)->enableDebugTypeODRUniquing();
1685 Expected<std::unique_ptr<Module>> SrcOrError =
1686 parseBitcodeFile(Buffer, *unwrap(Context));
1688 LLVMRustSetLastError(toString(SrcOrError.takeError()).c_str());
1691 return wrap(std::move(*SrcOrError).release());
1694 // Find the bitcode section in the object file data and return it as a slice.
1695 // Fail if the bitcode section is present but empty.
1697 // On success, the return value is the pointer to the start of the slice and
1698 // `out_len` is filled with the (non-zero) length. On failure, the return value
1699 // is `nullptr` and `out_len` is set to zero.
1700 extern "C" const char*
1701 LLVMRustGetBitcodeSliceFromObjectData(const char *data,
1706 StringRef Data(data, len);
1707 MemoryBufferRef Buffer(Data, ""); // The id is unused.
1709 Expected<MemoryBufferRef> BitcodeOrError =
1710 object::IRObjectFile::findBitcodeInMemBuffer(Buffer);
1711 if (!BitcodeOrError) {
1712 LLVMRustSetLastError(toString(BitcodeOrError.takeError()).c_str());
1716 *out_len = BitcodeOrError->getBufferSize();
1717 return BitcodeOrError->getBufferStart();
1720 // Rewrite all `DICompileUnit` pointers to the `DICompileUnit` specified. See
1721 // the comment in `back/lto.rs` for why this exists.
1723 LLVMRustThinLTOGetDICompileUnit(LLVMModuleRef Mod,
1725 DICompileUnit **B) {
1726 Module *M = unwrap(Mod);
1727 DICompileUnit **Cur = A;
1728 DICompileUnit **Next = B;
1729 for (DICompileUnit *CU : M->debug_compile_units()) {
1738 // Rewrite all `DICompileUnit` pointers to the `DICompileUnit` specified. See
1739 // the comment in `back/lto.rs` for why this exists.
1741 LLVMRustThinLTOPatchDICompileUnit(LLVMModuleRef Mod, DICompileUnit *Unit) {
1742 Module *M = unwrap(Mod);
1744 // If the original source module didn't have a `DICompileUnit` then try to
1745 // merge all the existing compile units. If there aren't actually any though
1746 // then there's not much for us to do so return.
1747 if (Unit == nullptr) {
1748 for (DICompileUnit *CU : M->debug_compile_units()) {
1752 if (Unit == nullptr)
1756 // Use LLVM's built-in `DebugInfoFinder` to find a bunch of debuginfo and
1757 // process it recursively. Note that we used to specifically iterate over
1758 // instructions to ensure we feed everything into it, but `processModule`
1759 // started doing this the same way in LLVM 7 (commit d769eb36ab2b8).
1760 DebugInfoFinder Finder;
1761 Finder.processModule(*M);
1763 // After we've found all our debuginfo, rewrite all subprograms to point to
1764 // the same `DICompileUnit`.
1765 for (auto &F : Finder.subprograms()) {
1766 F->replaceUnit(Unit);
1769 // Erase any other references to other `DICompileUnit` instances, the verifier
1770 // will later ensure that we don't actually have any other stale references to
1772 auto *MD = M->getNamedMetadata("llvm.dbg.cu");
1773 MD->clearOperands();
1774 MD->addOperand(Unit);
1777 // Computes the LTO cache key for the provided 'ModId' in the given 'Data',
1778 // storing the result in 'KeyOut'.
1779 // Currently, this cache key is a SHA-1 hash of anything that could affect
1780 // the result of optimizing this module (e.g. module imports, exports, liveness
1781 // of access globals, etc).
1782 // The precise details are determined by LLVM in `computeLTOCacheKey`, which is
1783 // used during the normal linker-plugin incremental thin-LTO process.
1785 LLVMRustComputeLTOCacheKey(RustStringRef KeyOut, const char *ModId, LLVMRustThinLTOData *Data) {
1786 SmallString<40> Key;
1787 llvm::lto::Config conf;
1788 const auto &ImportList = Data->ImportLists.lookup(ModId);
1789 const auto &ExportList = Data->ExportLists.lookup(ModId);
1790 const auto &ResolvedODR = Data->ResolvedODR.lookup(ModId);
1791 const auto &DefinedGlobals = Data->ModuleToDefinedGVSummaries.lookup(ModId);
1792 std::set<GlobalValue::GUID> CfiFunctionDefs;
1793 std::set<GlobalValue::GUID> CfiFunctionDecls;
1795 // Based on the 'InProcessThinBackend' constructor in LLVM
1796 for (auto &Name : Data->Index.cfiFunctionDefs())
1797 CfiFunctionDefs.insert(
1798 GlobalValue::getGUID(GlobalValue::dropLLVMManglingEscape(Name)));
1799 for (auto &Name : Data->Index.cfiFunctionDecls())
1800 CfiFunctionDecls.insert(
1801 GlobalValue::getGUID(GlobalValue::dropLLVMManglingEscape(Name)));
1803 llvm::computeLTOCacheKey(Key, conf, Data->Index, ModId,
1804 ImportList, ExportList, ResolvedODR, DefinedGlobals, CfiFunctionDefs, CfiFunctionDecls
1807 LLVMRustStringWriteImpl(KeyOut, Key.c_str(), Key.size());