]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
New upstream version 1.68.2+dfsg1
[rustc.git] / compiler / rustc_llvm / llvm-wrapper / PassWrapper.cpp
CommitLineData
1a4d82fc
JJ
1#include <stdio.h>
2
041b39d2 3#include <vector>
ff7c6d11 4#include <set>
041b39d2 5
1b1a35ee 6#include "LLVMWrapper.h"
970d7e83 7
6a06907d 8#include "llvm/Analysis/AliasAnalysis.h"
62682a34
SL
9#include "llvm/Analysis/TargetLibraryInfo.h"
10#include "llvm/Analysis/TargetTransformInfo.h"
0731742a 11#include "llvm/CodeGen/TargetSubtargetInfo.h"
dfeec247 12#include "llvm/InitializePasses.h"
5bcae85e 13#include "llvm/IR/AutoUpgrade.h"
041b39d2 14#include "llvm/IR/AssemblyAnnotationWriter.h"
0731742a 15#include "llvm/IR/IntrinsicInst.h"
74b04a01 16#include "llvm/IR/Verifier.h"
f9f354fc
XL
17#include "llvm/Object/ObjectFile.h"
18#include "llvm/Object/IRObjectFile.h"
74b04a01 19#include "llvm/Passes/PassBuilder.h"
a2a8927a 20#include "llvm/Passes/PassPlugin.h"
74b04a01 21#include "llvm/Passes/StandardInstrumentations.h"
32a655c1
SL
22#include "llvm/Support/CBindingWrapping.h"
23#include "llvm/Support/FileSystem.h"
24#include "llvm/Support/Host.h"
3c0e092e
XL
25#if LLVM_VERSION_LT(14, 0)
26#include "llvm/Support/TargetRegistry.h"
27#else
28#include "llvm/MC/TargetRegistry.h"
29#endif
c1a9b12d 30#include "llvm/Target/TargetMachine.h"
1a4d82fc 31#include "llvm/Transforms/IPO/PassManagerBuilder.h"
476ff2be 32#include "llvm/Transforms/IPO/AlwaysInliner.h"
ea8adc8c 33#include "llvm/Transforms/IPO/FunctionImport.h"
2b03887a 34#include "llvm/Transforms/IPO/Internalize.h"
f2b60f7d 35#include "llvm/Transforms/IPO/ThinLTOBitcodeWriter.h"
c295e0f8 36#include "llvm/Transforms/Utils/AddDiscriminators.h"
ea8adc8c
XL
37#include "llvm/Transforms/Utils/FunctionImportUtils.h"
38#include "llvm/LTO/LTO.h"
2b03887a 39#include "llvm/Bitcode/BitcodeWriter.h"
1a4d82fc 40#include "llvm-c/Transforms/PassManagerBuilder.h"
970d7e83 41
60c5eb7d 42#include "llvm/Transforms/Instrumentation.h"
60c5eb7d 43#include "llvm/Transforms/Instrumentation/AddressSanitizer.h"
74b04a01 44#include "llvm/Support/TimeProfiler.h"
17df50a5
XL
45#include "llvm/Transforms/Instrumentation/GCOVProfiler.h"
46#include "llvm/Transforms/Instrumentation/InstrProfiling.h"
60c5eb7d
XL
47#include "llvm/Transforms/Instrumentation/ThreadSanitizer.h"
48#include "llvm/Transforms/Instrumentation/MemorySanitizer.h"
6a06907d 49#include "llvm/Transforms/Instrumentation/HWAddressSanitizer.h"
74b04a01 50#include "llvm/Transforms/Utils/CanonicalizeAliases.h"
74b04a01 51#include "llvm/Transforms/Utils/NameAnonGlobals.h"
c295e0f8 52#include "llvm/Transforms/Utils.h"
60c5eb7d 53
1a4d82fc 54using namespace llvm;
970d7e83 55
1a4d82fc
JJ
56typedef struct LLVMOpaquePass *LLVMPassRef;
57typedef struct LLVMOpaqueTargetMachine *LLVMTargetMachineRef;
58
59DEFINE_STDCXX_CONVERSION_FUNCTIONS(Pass, LLVMPassRef)
60DEFINE_STDCXX_CONVERSION_FUNCTIONS(TargetMachine, LLVMTargetMachineRef)
970d7e83 61
32a655c1 62extern "C" void LLVMInitializePasses() {
970d7e83
LB
63 PassRegistry &Registry = *PassRegistry::getPassRegistry();
64 initializeCore(Registry);
65 initializeCodeGen(Registry);
66 initializeScalarOpts(Registry);
67 initializeVectorization(Registry);
68 initializeIPO(Registry);
69 initializeAnalysis(Registry);
970d7e83
LB
70 initializeTransformUtils(Registry);
71 initializeInstCombine(Registry);
2b03887a 72#if LLVM_VERSION_LT(16, 0)
970d7e83 73 initializeInstrumentation(Registry);
2b03887a 74#endif
970d7e83
LB
75 initializeTarget(Registry);
76}
77
74b04a01 78extern "C" void LLVMTimeTraceProfilerInitialize() {
ba9703b0
XL
79 timeTraceProfilerInitialize(
80 /* TimeTraceGranularity */ 0,
81 /* ProcName */ "rustc");
74b04a01
XL
82}
83
3c0e092e
XL
84extern "C" void LLVMTimeTraceProfilerFinishThread() {
85 timeTraceProfilerFinishThread();
86}
87
74b04a01 88extern "C" void LLVMTimeTraceProfilerFinish(const char* FileName) {
74b04a01
XL
89 StringRef FN(FileName);
90 std::error_code EC;
91 raw_fd_ostream OS(FN, EC, sys::fs::CD_CreateAlways);
92
93 timeTraceProfilerWrite(OS);
94 timeTraceProfilerCleanup();
74b04a01
XL
95}
96
a7813a04
XL
97#ifdef LLVM_COMPONENT_X86
98#define SUBTARGET_X86 SUBTARGET(X86)
99#else
100#define SUBTARGET_X86
101#endif
102
103#ifdef LLVM_COMPONENT_ARM
104#define SUBTARGET_ARM SUBTARGET(ARM)
105#else
106#define SUBTARGET_ARM
107#endif
108
109#ifdef LLVM_COMPONENT_AARCH64
110#define SUBTARGET_AARCH64 SUBTARGET(AArch64)
111#else
112#define SUBTARGET_AARCH64
113#endif
114
f035d41b
XL
115#ifdef LLVM_COMPONENT_AVR
116#define SUBTARGET_AVR SUBTARGET(AVR)
117#else
118#define SUBTARGET_AVR
119#endif
120
c295e0f8
XL
121#ifdef LLVM_COMPONENT_M68k
122#define SUBTARGET_M68K SUBTARGET(M68k)
123#else
124#define SUBTARGET_M68K
125#endif
126
a7813a04
XL
127#ifdef LLVM_COMPONENT_MIPS
128#define SUBTARGET_MIPS SUBTARGET(Mips)
129#else
130#define SUBTARGET_MIPS
131#endif
132
133#ifdef LLVM_COMPONENT_POWERPC
134#define SUBTARGET_PPC SUBTARGET(PPC)
135#else
136#define SUBTARGET_PPC
137#endif
138
9e0c209e
SL
139#ifdef LLVM_COMPONENT_SYSTEMZ
140#define SUBTARGET_SYSTEMZ SUBTARGET(SystemZ)
141#else
142#define SUBTARGET_SYSTEMZ
143#endif
144
476ff2be
SL
145#ifdef LLVM_COMPONENT_MSP430
146#define SUBTARGET_MSP430 SUBTARGET(MSP430)
147#else
148#define SUBTARGET_MSP430
149#endif
150
b7449926
XL
151#ifdef LLVM_COMPONENT_RISCV
152#define SUBTARGET_RISCV SUBTARGET(RISCV)
153#else
154#define SUBTARGET_RISCV
155#endif
156
32a655c1
SL
157#ifdef LLVM_COMPONENT_SPARC
158#define SUBTARGET_SPARC SUBTARGET(Sparc)
159#else
160#define SUBTARGET_SPARC
161#endif
162
7cac9316
XL
163#ifdef LLVM_COMPONENT_HEXAGON
164#define SUBTARGET_HEXAGON SUBTARGET(Hexagon)
165#else
166#define SUBTARGET_HEXAGON
167#endif
168
32a655c1
SL
169#define GEN_SUBTARGETS \
170 SUBTARGET_X86 \
171 SUBTARGET_ARM \
172 SUBTARGET_AARCH64 \
f035d41b 173 SUBTARGET_AVR \
c295e0f8 174 SUBTARGET_M68K \
32a655c1
SL
175 SUBTARGET_MIPS \
176 SUBTARGET_PPC \
177 SUBTARGET_SYSTEMZ \
178 SUBTARGET_MSP430 \
7cac9316 179 SUBTARGET_SPARC \
b7449926
XL
180 SUBTARGET_HEXAGON \
181 SUBTARGET_RISCV \
32a655c1
SL
182
183#define SUBTARGET(x) \
184 namespace llvm { \
185 extern const SubtargetFeatureKV x##FeatureKV[]; \
186 extern const SubtargetFeatureKV x##SubTypeKV[]; \
a7813a04
XL
187 }
188
189GEN_SUBTARGETS
190#undef SUBTARGET
191
32a655c1
SL
192extern "C" bool LLVMRustHasFeature(LLVMTargetMachineRef TM,
193 const char *Feature) {
194 TargetMachine *Target = unwrap(TM);
195 const MCSubtargetInfo *MCInfo = Target->getMCSubtargetInfo();
0531ce1d 196 return MCInfo->checkFeatures(std::string("+") + Feature);
a7813a04
XL
197}
198
5bcae85e 199enum class LLVMRustCodeModel {
f9f354fc 200 Tiny,
32a655c1
SL
201 Small,
202 Kernel,
203 Medium,
204 Large,
2c00a5a8 205 None,
5bcae85e
SL
206};
207
487cf647
FG
208#if LLVM_VERSION_LT(16, 0)
209static Optional<CodeModel::Model>
210#else
211static std::optional<CodeModel::Model>
212#endif
213fromRust(LLVMRustCodeModel Model) {
32a655c1 214 switch (Model) {
f9f354fc
XL
215 case LLVMRustCodeModel::Tiny:
216 return CodeModel::Tiny;
32a655c1
SL
217 case LLVMRustCodeModel::Small:
218 return CodeModel::Small;
219 case LLVMRustCodeModel::Kernel:
220 return CodeModel::Kernel;
221 case LLVMRustCodeModel::Medium:
222 return CodeModel::Medium;
223 case LLVMRustCodeModel::Large:
224 return CodeModel::Large;
f9f354fc 225 case LLVMRustCodeModel::None:
9c376795 226#if LLVM_VERSION_LT(16, 0)
f9f354fc 227 return None;
9c376795
FG
228#else
229 return std::nullopt;
230#endif
32a655c1 231 default:
ff7c6d11 232 report_fatal_error("Bad CodeModel.");
5bcae85e
SL
233 }
234}
235
236enum class LLVMRustCodeGenOptLevel {
32a655c1
SL
237 None,
238 Less,
239 Default,
240 Aggressive,
5bcae85e
SL
241};
242
32a655c1
SL
243static CodeGenOpt::Level fromRust(LLVMRustCodeGenOptLevel Level) {
244 switch (Level) {
245 case LLVMRustCodeGenOptLevel::None:
246 return CodeGenOpt::None;
247 case LLVMRustCodeGenOptLevel::Less:
248 return CodeGenOpt::Less;
249 case LLVMRustCodeGenOptLevel::Default:
250 return CodeGenOpt::Default;
251 case LLVMRustCodeGenOptLevel::Aggressive:
252 return CodeGenOpt::Aggressive;
253 default:
ff7c6d11 254 report_fatal_error("Bad CodeGenOptLevel.");
5bcae85e
SL
255 }
256}
257
74b04a01
XL
258enum class LLVMRustPassBuilderOptLevel {
259 O0,
260 O1,
261 O2,
262 O3,
263 Os,
264 Oz,
265};
266
94222f64
XL
267#if LLVM_VERSION_LT(14,0)
268using OptimizationLevel = PassBuilder::OptimizationLevel;
269#endif
270
271static OptimizationLevel fromRust(LLVMRustPassBuilderOptLevel Level) {
74b04a01
XL
272 switch (Level) {
273 case LLVMRustPassBuilderOptLevel::O0:
94222f64 274 return OptimizationLevel::O0;
74b04a01 275 case LLVMRustPassBuilderOptLevel::O1:
94222f64 276 return OptimizationLevel::O1;
74b04a01 277 case LLVMRustPassBuilderOptLevel::O2:
94222f64 278 return OptimizationLevel::O2;
74b04a01 279 case LLVMRustPassBuilderOptLevel::O3:
94222f64 280 return OptimizationLevel::O3;
74b04a01 281 case LLVMRustPassBuilderOptLevel::Os:
94222f64 282 return OptimizationLevel::Os;
74b04a01 283 case LLVMRustPassBuilderOptLevel::Oz:
94222f64 284 return OptimizationLevel::Oz;
74b04a01
XL
285 default:
286 report_fatal_error("Bad PassBuilderOptLevel.");
287 }
288}
289
f9f354fc 290enum class LLVMRustRelocModel {
7cac9316
XL
291 Static,
292 PIC,
293 DynamicNoPic,
294 ROPI,
295 RWPI,
296 ROPIRWPI,
297};
298
f9f354fc 299static Reloc::Model fromRust(LLVMRustRelocModel RustReloc) {
7cac9316 300 switch (RustReloc) {
f9f354fc 301 case LLVMRustRelocModel::Static:
7cac9316 302 return Reloc::Static;
f9f354fc 303 case LLVMRustRelocModel::PIC:
7cac9316 304 return Reloc::PIC_;
f9f354fc 305 case LLVMRustRelocModel::DynamicNoPic:
7cac9316 306 return Reloc::DynamicNoPIC;
f9f354fc 307 case LLVMRustRelocModel::ROPI:
7cac9316 308 return Reloc::ROPI;
f9f354fc 309 case LLVMRustRelocModel::RWPI:
7cac9316 310 return Reloc::RWPI;
f9f354fc 311 case LLVMRustRelocModel::ROPIRWPI:
7cac9316 312 return Reloc::ROPI_RWPI;
7cac9316 313 }
ff7c6d11 314 report_fatal_error("Bad RelocModel.");
7cac9316
XL
315}
316
a1dfa0c6 317#ifdef LLVM_RUSTLLVM
5bcae85e 318/// getLongestEntryLength - Return the length of the longest entry in the table.
416331ca
XL
319template<typename KV>
320static size_t getLongestEntryLength(ArrayRef<KV> Table) {
5bcae85e
SL
321 size_t MaxLen = 0;
322 for (auto &I : Table)
323 MaxLen = std::max(MaxLen, std::strlen(I.Key));
324 return MaxLen;
325}
326
32a655c1
SL
327extern "C" void LLVMRustPrintTargetCPUs(LLVMTargetMachineRef TM) {
328 const TargetMachine *Target = unwrap(TM);
329 const MCSubtargetInfo *MCInfo = Target->getMCSubtargetInfo();
ea8adc8c
XL
330 const Triple::ArchType HostArch = Triple(sys::getProcessTriple()).getArch();
331 const Triple::ArchType TargetArch = Target->getTargetTriple().getArch();
416331ca 332 const ArrayRef<SubtargetSubTypeKV> CPUTable = MCInfo->getCPUTable();
32a655c1
SL
333 unsigned MaxCPULen = getLongestEntryLength(CPUTable);
334
335 printf("Available CPUs for this target:\n");
ea8adc8c
XL
336 if (HostArch == TargetArch) {
337 const StringRef HostCPU = sys::getHostCPUName();
338 printf(" %-*s - Select the CPU of the current host (currently %.*s).\n",
339 MaxCPULen, "native", (int)HostCPU.size(), HostCPU.data());
340 }
32a655c1 341 for (auto &CPU : CPUTable)
416331ca 342 printf(" %-*s\n", MaxCPULen, CPU.Key);
32a655c1 343 printf("\n");
5bcae85e
SL
344}
345
cdc7bbd5 346extern "C" size_t LLVMRustGetTargetFeaturesCount(LLVMTargetMachineRef TM) {
32a655c1
SL
347 const TargetMachine *Target = unwrap(TM);
348 const MCSubtargetInfo *MCInfo = Target->getMCSubtargetInfo();
349 const ArrayRef<SubtargetFeatureKV> FeatTable = MCInfo->getFeatureTable();
cdc7bbd5
XL
350 return FeatTable.size();
351}
32a655c1 352
cdc7bbd5
XL
353extern "C" void LLVMRustGetTargetFeature(LLVMTargetMachineRef TM, size_t Index,
354 const char** Feature, const char** Desc) {
355 const TargetMachine *Target = unwrap(TM);
356 const MCSubtargetInfo *MCInfo = Target->getMCSubtargetInfo();
357 const ArrayRef<SubtargetFeatureKV> FeatTable = MCInfo->getFeatureTable();
358 const SubtargetFeatureKV Feat = FeatTable[Index];
359 *Feature = Feat.Key;
360 *Desc = Feat.Desc;
5bcae85e
SL
361}
362
363#else
364
32a655c1
SL
365extern "C" void LLVMRustPrintTargetCPUs(LLVMTargetMachineRef) {
366 printf("Target CPU help is not supported by this LLVM version.\n\n");
5bcae85e
SL
367}
368
cdc7bbd5
XL
369extern "C" size_t LLVMRustGetTargetFeaturesCount(LLVMTargetMachineRef) {
370 return 0;
5bcae85e 371}
cdc7bbd5
XL
372
373extern "C" void LLVMRustGetTargetFeature(LLVMTargetMachineRef, const char**, const char**) {}
5bcae85e
SL
374#endif
375
b7449926
XL
376extern "C" const char* LLVMRustGetHostCPUName(size_t *len) {
377 StringRef Name = sys::getHostCPUName();
378 *len = Name.size();
379 return Name.data();
380}
381
32a655c1
SL
382extern "C" LLVMTargetMachineRef LLVMRustCreateTargetMachine(
383 const char *TripleStr, const char *CPU, const char *Feature,
f9f354fc 384 const char *ABIStr, LLVMRustCodeModel RustCM, LLVMRustRelocModel RustReloc,
32a655c1 385 LLVMRustCodeGenOptLevel RustOptLevel, bool UseSoftFloat,
f9f354fc 386 bool FunctionSections,
abe05a73 387 bool DataSections,
3c0e092e 388 bool UniqueSectionNames,
abe05a73 389 bool TrapUnreachable,
b7449926 390 bool Singlethread,
0bf4aa26 391 bool AsmComments,
60c5eb7d 392 bool EmitStackSizeSection,
f9f354fc 393 bool RelaxELFRelocations,
fc512014
XL
394 bool UseInitArray,
395 const char *SplitDwarfFile) {
5bcae85e 396
32a655c1 397 auto OptLevel = fromRust(RustOptLevel);
7cac9316 398 auto RM = fromRust(RustReloc);
f9f354fc 399 auto CM = fromRust(RustCM);
5bcae85e 400
32a655c1
SL
401 std::string Error;
402 Triple Trip(Triple::normalize(TripleStr));
403 const llvm::Target *TheTarget =
404 TargetRegistry::lookupTarget(Trip.getTriple(), Error);
405 if (TheTarget == nullptr) {
406 LLVMRustSetLastError(Error.c_str());
407 return nullptr;
408 }
1a4d82fc 409
32a655c1 410 TargetOptions Options;
5bcae85e 411
32a655c1
SL
412 Options.FloatABIType = FloatABI::Default;
413 if (UseSoftFloat) {
414 Options.FloatABIType = FloatABI::Soft;
415 }
416 Options.DataSections = DataSections;
417 Options.FunctionSections = FunctionSections;
3c0e092e 418 Options.UniqueSectionNames = UniqueSectionNames;
b7449926
XL
419 Options.MCOptions.AsmVerbose = AsmComments;
420 Options.MCOptions.PreserveAsmComments = AsmComments;
60c5eb7d 421 Options.MCOptions.ABIName = ABIStr;
fc512014
XL
422 if (SplitDwarfFile) {
423 Options.MCOptions.SplitDwarfFile = SplitDwarfFile;
424 }
60c5eb7d 425 Options.RelaxELFRelocations = RelaxELFRelocations;
f9f354fc 426 Options.UseInitArray = UseInitArray;
32a655c1 427
abe05a73 428 if (TrapUnreachable) {
94b46f34 429 // Tell LLVM to codegen `unreachable` into an explicit trap instruction.
abe05a73
XL
430 // This limits the extent of possible undefined behavior in some cases, as
431 // it prevents control flow from "falling through" into whatever code
432 // happens to be laid out next in memory.
433 Options.TrapUnreachable = true;
434 }
435
436 if (Singlethread) {
437 Options.ThreadModel = ThreadModel::Single;
438 }
439
0bf4aa26
XL
440 Options.EmitStackSizeSection = EmitStackSizeSection;
441
32a655c1 442 TargetMachine *TM = TheTarget->createTargetMachine(
b7449926 443 Trip.getTriple(), CPU, Feature, Options, RM, CM, OptLevel);
32a655c1 444 return wrap(TM);
1a4d82fc
JJ
445}
446
32a655c1
SL
447extern "C" void LLVMRustDisposeTargetMachine(LLVMTargetMachineRef TM) {
448 delete unwrap(TM);
1a4d82fc
JJ
449}
450
1a4d82fc
JJ
451// Unfortunately, the LLVM C API doesn't provide a way to create the
452// TargetLibraryInfo pass, so we use this method to do so.
32a655c1
SL
453extern "C" void LLVMRustAddLibraryInfo(LLVMPassManagerRef PMR, LLVMModuleRef M,
454 bool DisableSimplifyLibCalls) {
455 Triple TargetTriple(unwrap(M)->getTargetTriple());
456 TargetLibraryInfoImpl TLII(TargetTriple);
457 if (DisableSimplifyLibCalls)
458 TLII.disableAllFunctions();
459 unwrap(PMR)->add(new TargetLibraryInfoWrapperPass(TLII));
1a4d82fc
JJ
460}
461
32a655c1
SL
462extern "C" void LLVMRustSetLLVMOptions(int Argc, char **Argv) {
463 // Initializing the command-line options more than once is not allowed. So,
9c376795 464 // check if they've already been initialized. (This could happen if we're
32a655c1
SL
465 // being called from rustpkg, for example). If the arguments change, then
466 // that's just kinda unfortunate.
467 static bool Initialized = false;
468 if (Initialized)
469 return;
470 Initialized = true;
471 cl::ParseCommandLineOptions(Argc, Argv);
1a4d82fc
JJ
472}
473
5bcae85e 474enum class LLVMRustFileType {
32a655c1
SL
475 AssemblyFile,
476 ObjectFile,
5bcae85e
SL
477};
478
dfeec247
XL
479static CodeGenFileType fromRust(LLVMRustFileType Type) {
480 switch (Type) {
481 case LLVMRustFileType::AssemblyFile:
482 return CGFT_AssemblyFile;
483 case LLVMRustFileType::ObjectFile:
484 return CGFT_ObjectFile;
485 default:
486 report_fatal_error("Bad FileType.");
487 }
488}
5bcae85e
SL
489
490extern "C" LLVMRustResult
32a655c1 491LLVMRustWriteOutputFile(LLVMTargetMachineRef Target, LLVMPassManagerRef PMR,
fc512014 492 LLVMModuleRef M, const char *Path, const char *DwoPath,
32a655c1 493 LLVMRustFileType RustFileType) {
5bcae85e 494 llvm::legacy::PassManager *PM = unwrap<llvm::legacy::PassManager>(PMR);
32a655c1 495 auto FileType = fromRust(RustFileType);
1a4d82fc
JJ
496
497 std::string ErrorInfo;
1a4d82fc 498 std::error_code EC;
17df50a5 499 raw_fd_ostream OS(Path, EC, sys::fs::OF_None);
1a4d82fc
JJ
500 if (EC)
501 ErrorInfo = EC.message();
1a4d82fc
JJ
502 if (ErrorInfo != "") {
503 LLVMRustSetLastError(ErrorInfo.c_str());
5bcae85e 504 return LLVMRustResult::Failure;
1a4d82fc 505 }
1a4d82fc 506
b7449926 507 buffer_ostream BOS(OS);
fc512014 508 if (DwoPath) {
17df50a5 509 raw_fd_ostream DOS(DwoPath, EC, sys::fs::OF_None);
fc512014
XL
510 EC.clear();
511 if (EC)
512 ErrorInfo = EC.message();
513 if (ErrorInfo != "") {
514 LLVMRustSetLastError(ErrorInfo.c_str());
515 return LLVMRustResult::Failure;
516 }
517 buffer_ostream DBOS(DOS);
518 unwrap(Target)->addPassesToEmitFile(*PM, BOS, &DBOS, FileType, false);
519 PM->run(*unwrap(M));
520 } else {
521 unwrap(Target)->addPassesToEmitFile(*PM, BOS, nullptr, FileType, false);
522 PM->run(*unwrap(M));
523 }
62682a34 524
b039eaaf 525 // Apparently `addPassesToEmitFile` adds a pointer to our on-the-stack output
62682a34
SL
526 // stream (OS), so the only real safe place to delete this is here? Don't we
527 // wish this was written in Rust?
60c5eb7d 528 LLVMDisposePassManager(PMR);
5bcae85e 529 return LLVMRustResult::Success;
1a4d82fc
JJ
530}
531
74b04a01
XL
532extern "C" typedef void (*LLVMRustSelfProfileBeforePassCallback)(void*, // LlvmSelfProfiler
533 const char*, // pass name
534 const char*); // IR name
535extern "C" typedef void (*LLVMRustSelfProfileAfterPassCallback)(void*); // LlvmSelfProfiler
536
74b04a01
XL
537std::string LLVMRustwrappedIrGetName(const llvm::Any &WrappedIr) {
538 if (any_isa<const Module *>(WrappedIr))
539 return any_cast<const Module *>(WrappedIr)->getName().str();
540 if (any_isa<const Function *>(WrappedIr))
541 return any_cast<const Function *>(WrappedIr)->getName().str();
542 if (any_isa<const Loop *>(WrappedIr))
543 return any_cast<const Loop *>(WrappedIr)->getName().str();
544 if (any_isa<const LazyCallGraph::SCC *>(WrappedIr))
545 return any_cast<const LazyCallGraph::SCC *>(WrappedIr)->getName();
546 return "<UNKNOWN>";
547}
548
549
550void LLVMSelfProfileInitializeCallbacks(
551 PassInstrumentationCallbacks& PIC, void* LlvmSelfProfiler,
552 LLVMRustSelfProfileBeforePassCallback BeforePassCallback,
553 LLVMRustSelfProfileAfterPassCallback AfterPassCallback) {
6a06907d
XL
554 PIC.registerBeforeNonSkippedPassCallback([LlvmSelfProfiler, BeforePassCallback](
555 StringRef Pass, llvm::Any Ir) {
556 std::string PassName = Pass.str();
557 std::string IrName = LLVMRustwrappedIrGetName(Ir);
558 BeforePassCallback(LlvmSelfProfiler, PassName.c_str(), IrName.c_str());
559 });
560
561 PIC.registerAfterPassCallback(
562 [LlvmSelfProfiler, AfterPassCallback](StringRef Pass, llvm::Any IR,
563 const PreservedAnalyses &Preserved) {
564 AfterPassCallback(LlvmSelfProfiler);
565 });
566
567 PIC.registerAfterPassInvalidatedCallback(
568 [LlvmSelfProfiler, AfterPassCallback](StringRef Pass, const PreservedAnalyses &Preserved) {
569 AfterPassCallback(LlvmSelfProfiler);
570 });
74b04a01
XL
571
572 PIC.registerBeforeAnalysisCallback([LlvmSelfProfiler, BeforePassCallback](
573 StringRef Pass, llvm::Any Ir) {
574 std::string PassName = Pass.str();
575 std::string IrName = LLVMRustwrappedIrGetName(Ir);
576 BeforePassCallback(LlvmSelfProfiler, PassName.c_str(), IrName.c_str());
577 });
578
579 PIC.registerAfterAnalysisCallback(
580 [LlvmSelfProfiler, AfterPassCallback](StringRef Pass, llvm::Any Ir) {
581 AfterPassCallback(LlvmSelfProfiler);
582 });
583}
74b04a01
XL
584
585enum class LLVMRustOptStage {
586 PreLinkNoLTO,
587 PreLinkThinLTO,
588 PreLinkFatLTO,
589 ThinLTO,
590 FatLTO,
591};
592
593struct LLVMRustSanitizerOptions {
f035d41b
XL
594 bool SanitizeAddress;
595 bool SanitizeAddressRecover;
74b04a01 596 bool SanitizeMemory;
f035d41b
XL
597 bool SanitizeMemoryRecover;
598 int SanitizeMemoryTrackOrigins;
74b04a01 599 bool SanitizeThread;
6a06907d
XL
600 bool SanitizeHWAddress;
601 bool SanitizeHWAddressRecover;
74b04a01
XL
602};
603
17df50a5 604extern "C" LLVMRustResult
2b03887a 605LLVMRustOptimize(
74b04a01
XL
606 LLVMModuleRef ModuleRef,
607 LLVMTargetMachineRef TMRef,
608 LLVMRustPassBuilderOptLevel OptLevelRust,
609 LLVMRustOptStage OptStage,
610 bool NoPrepopulatePasses, bool VerifyIR, bool UseThinLTOBuffers,
611 bool MergeFunctions, bool UnrollLoops, bool SLPVectorize, bool LoopVectorize,
f9f354fc 612 bool DisableSimplifyLibCalls, bool EmitLifetimeMarkers,
74b04a01
XL
613 LLVMRustSanitizerOptions *SanitizerOptions,
614 const char *PGOGenPath, const char *PGOUsePath,
f2b60f7d
FG
615 bool InstrumentCoverage, const char *InstrProfileOutput,
616 bool InstrumentGCOV,
c295e0f8 617 const char *PGOSampleUsePath, bool DebugInfoForProfiling,
74b04a01
XL
618 void* LlvmSelfProfiler,
619 LLVMRustSelfProfileBeforePassCallback BeforePassCallback,
17df50a5 620 LLVMRustSelfProfileAfterPassCallback AfterPassCallback,
a2a8927a
XL
621 const char *ExtraPasses, size_t ExtraPassesLen,
622 const char *LLVMPlugins, size_t LLVMPluginsLen) {
74b04a01
XL
623 Module *TheModule = unwrap(ModuleRef);
624 TargetMachine *TM = unwrap(TMRef);
94222f64 625 OptimizationLevel OptLevel = fromRust(OptLevelRust);
74b04a01 626
74b04a01
XL
627
628 PipelineTuningOptions PTO;
629 PTO.LoopUnrolling = UnrollLoops;
630 PTO.LoopInterleaving = UnrollLoops;
631 PTO.LoopVectorization = LoopVectorize;
632 PTO.SLPVectorization = SLPVectorize;
6a06907d 633 PTO.MergeFunctions = MergeFunctions;
6a06907d
XL
634
635 // FIXME: We may want to expose this as an option.
636 bool DebugPassManager = false;
74b04a01
XL
637
638 PassInstrumentationCallbacks PIC;
487cf647 639#if LLVM_VERSION_LT(16, 0)
6a06907d 640 StandardInstrumentations SI(DebugPassManager);
487cf647
FG
641#else
642 StandardInstrumentations SI(TheModule->getContext(), DebugPassManager);
643#endif
74b04a01
XL
644 SI.registerCallbacks(PIC);
645
646 if (LlvmSelfProfiler){
647 LLVMSelfProfileInitializeCallbacks(PIC,LlvmSelfProfiler,BeforePassCallback,AfterPassCallback);
648 }
649
487cf647 650#if LLVM_VERSION_LT(16, 0)
74b04a01 651 Optional<PGOOptions> PGOOpt;
487cf647
FG
652#else
653 std::optional<PGOOptions> PGOOpt;
654#endif
74b04a01 655 if (PGOGenPath) {
c295e0f8
XL
656 assert(!PGOUsePath && !PGOSampleUsePath);
657 PGOOpt = PGOOptions(PGOGenPath, "", "", PGOOptions::IRInstr,
658 PGOOptions::NoCSAction, DebugInfoForProfiling);
74b04a01 659 } else if (PGOUsePath) {
c295e0f8
XL
660 assert(!PGOSampleUsePath);
661 PGOOpt = PGOOptions(PGOUsePath, "", "", PGOOptions::IRUse,
662 PGOOptions::NoCSAction, DebugInfoForProfiling);
663 } else if (PGOSampleUsePath) {
664 PGOOpt = PGOOptions(PGOSampleUsePath, "", "", PGOOptions::SampleUse,
665 PGOOptions::NoCSAction, DebugInfoForProfiling);
666 } else if (DebugInfoForProfiling) {
667 PGOOpt = PGOOptions("", "", "", PGOOptions::NoAction,
668 PGOOptions::NoCSAction, DebugInfoForProfiling);
74b04a01
XL
669 }
670
3c0e092e 671 PassBuilder PB(TM, PTO, PGOOpt, &PIC);
17df50a5
XL
672 LoopAnalysisManager LAM;
673 FunctionAnalysisManager FAM;
674 CGSCCAnalysisManager CGAM;
675 ModuleAnalysisManager MAM;
74b04a01
XL
676
677 FAM.registerPass([&] { return PB.buildDefaultAAPipeline(); });
678
679 Triple TargetTriple(TheModule->getTargetTriple());
680 std::unique_ptr<TargetLibraryInfoImpl> TLII(new TargetLibraryInfoImpl(TargetTriple));
681 if (DisableSimplifyLibCalls)
682 TLII->disableAllFunctions();
683 FAM.registerPass([&] { return TargetLibraryAnalysis(*TLII); });
684
685 PB.registerModuleAnalyses(MAM);
686 PB.registerCGSCCAnalyses(CGAM);
687 PB.registerFunctionAnalyses(FAM);
688 PB.registerLoopAnalyses(LAM);
689 PB.crossRegisterProxies(LAM, FAM, CGAM, MAM);
690
691 // We manually collect pipeline callbacks so we can apply them at O0, where the
692 // PassBuilder does not create a pipeline.
94222f64 693 std::vector<std::function<void(ModulePassManager &, OptimizationLevel)>>
6a06907d 694 PipelineStartEPCallbacks;
94222f64 695 std::vector<std::function<void(ModulePassManager &, OptimizationLevel)>>
f035d41b 696 OptimizerLastEPCallbacks;
74b04a01
XL
697
698 if (VerifyIR) {
6a06907d 699 PipelineStartEPCallbacks.push_back(
94222f64 700 [VerifyIR](ModulePassManager &MPM, OptimizationLevel Level) {
74b04a01 701 MPM.addPass(VerifierPass());
6a06907d
XL
702 }
703 );
74b04a01
XL
704 }
705
17df50a5
XL
706 if (InstrumentGCOV) {
707 PipelineStartEPCallbacks.push_back(
94222f64 708 [](ModulePassManager &MPM, OptimizationLevel Level) {
17df50a5
XL
709 MPM.addPass(GCOVProfilerPass(GCOVOptions::getDefault()));
710 }
711 );
712 }
713
714 if (InstrumentCoverage) {
715 PipelineStartEPCallbacks.push_back(
f2b60f7d 716 [InstrProfileOutput](ModulePassManager &MPM, OptimizationLevel Level) {
17df50a5 717 InstrProfOptions Options;
f2b60f7d
FG
718 if (InstrProfileOutput) {
719 Options.InstrProfileOutput = InstrProfileOutput;
720 }
17df50a5
XL
721 MPM.addPass(InstrProfiling(Options, false));
722 }
723 );
724 }
725
74b04a01
XL
726 if (SanitizerOptions) {
727 if (SanitizerOptions->SanitizeMemory) {
f2b60f7d
FG
728#if LLVM_VERSION_GE(14, 0)
729 MemorySanitizerOptions Options(
730 SanitizerOptions->SanitizeMemoryTrackOrigins,
731 SanitizerOptions->SanitizeMemoryRecover,
732 /*CompileKernel=*/false,
733 /*EagerChecks=*/true);
734#else
74b04a01
XL
735 MemorySanitizerOptions Options(
736 SanitizerOptions->SanitizeMemoryTrackOrigins,
f035d41b 737 SanitizerOptions->SanitizeMemoryRecover,
74b04a01 738 /*CompileKernel=*/false);
f2b60f7d 739#endif
f035d41b 740 OptimizerLastEPCallbacks.push_back(
94222f64 741 [Options](ModulePassManager &MPM, OptimizationLevel Level) {
f2b60f7d 742#if LLVM_VERSION_GE(14, 0) && LLVM_VERSION_LT(16, 0)
c295e0f8
XL
743 MPM.addPass(ModuleMemorySanitizerPass(Options));
744#else
f035d41b 745 MPM.addPass(MemorySanitizerPass(Options));
c295e0f8 746#endif
f2b60f7d 747#if LLVM_VERSION_LT(16, 0)
f035d41b 748 MPM.addPass(createModuleToFunctionPassAdaptor(MemorySanitizerPass(Options)));
f2b60f7d 749#endif
f035d41b
XL
750 }
751 );
74b04a01
XL
752 }
753
754 if (SanitizerOptions->SanitizeThread) {
f035d41b 755 OptimizerLastEPCallbacks.push_back(
94222f64 756 [](ModulePassManager &MPM, OptimizationLevel Level) {
c295e0f8
XL
757#if LLVM_VERSION_GE(14, 0)
758 MPM.addPass(ModuleThreadSanitizerPass());
759#else
f035d41b 760 MPM.addPass(ThreadSanitizerPass());
c295e0f8 761#endif
f035d41b
XL
762 MPM.addPass(createModuleToFunctionPassAdaptor(ThreadSanitizerPass()));
763 }
764 );
74b04a01
XL
765 }
766
767 if (SanitizerOptions->SanitizeAddress) {
f035d41b 768 OptimizerLastEPCallbacks.push_back(
94222f64 769 [SanitizerOptions](ModulePassManager &MPM, OptimizationLevel Level) {
064997fb 770#if LLVM_VERSION_LT(15, 0)
f035d41b 771 MPM.addPass(RequireAnalysisPass<ASanGlobalsMetadataAnalysis, Module>());
064997fb 772#endif
94222f64 773#if LLVM_VERSION_GE(14, 0)
3c0e092e
XL
774 AddressSanitizerOptions opts = AddressSanitizerOptions{
775 /*CompileKernel=*/false,
776 SanitizerOptions->SanitizeAddressRecover,
777 /*UseAfterScope=*/true,
778 AsanDetectStackUseAfterReturnMode::Runtime,
779 };
f2b60f7d 780#if LLVM_VERSION_LT(16, 0)
3c0e092e 781 MPM.addPass(ModuleAddressSanitizerPass(opts));
f2b60f7d
FG
782#else
783 MPM.addPass(AddressSanitizerPass(opts));
784#endif
94222f64 785#else
3c0e092e
XL
786 MPM.addPass(ModuleAddressSanitizerPass(
787 /*CompileKernel=*/false, SanitizerOptions->SanitizeAddressRecover));
f035d41b
XL
788 MPM.addPass(createModuleToFunctionPassAdaptor(AddressSanitizerPass(
789 /*CompileKernel=*/false, SanitizerOptions->SanitizeAddressRecover,
790 /*UseAfterScope=*/true)));
94222f64 791#endif
f035d41b
XL
792 }
793 );
6a06907d
XL
794 }
795 if (SanitizerOptions->SanitizeHWAddress) {
6a06907d 796 OptimizerLastEPCallbacks.push_back(
94222f64
XL
797 [SanitizerOptions](ModulePassManager &MPM, OptimizationLevel Level) {
798#if LLVM_VERSION_GE(14, 0)
799 HWAddressSanitizerOptions opts(
800 /*CompileKernel=*/false, SanitizerOptions->SanitizeHWAddressRecover,
801 /*DisableOptimization=*/false);
802 MPM.addPass(HWAddressSanitizerPass(opts));
803#else
6a06907d
XL
804 MPM.addPass(HWAddressSanitizerPass(
805 /*CompileKernel=*/false, SanitizerOptions->SanitizeHWAddressRecover));
94222f64 806#endif
6a06907d
XL
807 }
808 );
74b04a01
XL
809 }
810 }
811
a2a8927a
XL
812 if (LLVMPluginsLen) {
813 auto PluginsStr = StringRef(LLVMPlugins, LLVMPluginsLen);
814 SmallVector<StringRef> Plugins;
815 PluginsStr.split(Plugins, ',', -1, false);
816 for (auto PluginPath: Plugins) {
817 auto Plugin = PassPlugin::Load(PluginPath.str());
818 if (!Plugin) {
819 LLVMRustSetLastError(("Failed to load pass plugin" + PluginPath.str()).c_str());
487cf647 820 return LLVMRustResult::Failure;
a2a8927a
XL
821 }
822 Plugin->registerPassBuilderCallbacks(PB);
823 }
824 }
825
17df50a5 826 ModulePassManager MPM;
6a06907d 827 bool NeedThinLTOBufferPasses = UseThinLTOBuffers;
74b04a01 828 if (!NoPrepopulatePasses) {
c295e0f8
XL
829 // The pre-link pipelines don't support O0 and require using budilO0DefaultPipeline() instead.
830 // At the same time, the LTO pipelines do support O0 and using them is required.
831 bool IsLTO = OptStage == LLVMRustOptStage::ThinLTO || OptStage == LLVMRustOptStage::FatLTO;
832 if (OptLevel == OptimizationLevel::O0 && !IsLTO) {
74b04a01 833 for (const auto &C : PipelineStartEPCallbacks)
6a06907d
XL
834 PB.registerPipelineStartEPCallback(C);
835 for (const auto &C : OptimizerLastEPCallbacks)
836 PB.registerOptimizerLastEPCallback(C);
74b04a01 837
6a06907d
XL
838 // Pass false as we manually schedule ThinLTOBufferPasses below.
839 MPM = PB.buildO0DefaultPipeline(OptLevel, /* PreLinkLTO */ false);
74b04a01
XL
840 } else {
841 for (const auto &C : PipelineStartEPCallbacks)
842 PB.registerPipelineStartEPCallback(C);
843 if (OptStage != LLVMRustOptStage::PreLinkThinLTO) {
844 for (const auto &C : OptimizerLastEPCallbacks)
845 PB.registerOptimizerLastEPCallback(C);
846 }
847
848 switch (OptStage) {
849 case LLVMRustOptStage::PreLinkNoLTO:
850 MPM = PB.buildPerModuleDefaultPipeline(OptLevel, DebugPassManager);
851 break;
852 case LLVMRustOptStage::PreLinkThinLTO:
6a06907d
XL
853 MPM = PB.buildThinLTOPreLinkDefaultPipeline(OptLevel);
854 // The ThinLTOPreLink pipeline already includes ThinLTOBuffer passes. However, callback
855 // passes may still run afterwards. This means we need to run the buffer passes again.
856 // FIXME: In LLVM 13, the ThinLTOPreLink pipeline also runs OptimizerLastEPCallbacks
857 // before the RequiredLTOPreLinkPasses, in which case we can remove these hacks.
858 if (OptimizerLastEPCallbacks.empty())
859 NeedThinLTOBufferPasses = false;
f035d41b
XL
860 for (const auto &C : OptimizerLastEPCallbacks)
861 C(MPM, OptLevel);
74b04a01
XL
862 break;
863 case LLVMRustOptStage::PreLinkFatLTO:
6a06907d
XL
864 MPM = PB.buildLTOPreLinkDefaultPipeline(OptLevel);
865 NeedThinLTOBufferPasses = false;
74b04a01
XL
866 break;
867 case LLVMRustOptStage::ThinLTO:
868 // FIXME: Does it make sense to pass the ModuleSummaryIndex?
869 // It only seems to be needed for C++ specific optimizations.
6a06907d 870 MPM = PB.buildThinLTODefaultPipeline(OptLevel, nullptr);
74b04a01
XL
871 break;
872 case LLVMRustOptStage::FatLTO:
6a06907d 873 MPM = PB.buildLTODefaultPipeline(OptLevel, nullptr);
74b04a01
XL
874 break;
875 }
876 }
04454e1e
FG
877 } else {
878 // We're not building any of the default pipelines but we still want to
879 // add the verifier, instrumentation, etc passes if they were requested
880 for (const auto &C : PipelineStartEPCallbacks)
881 C(MPM, OptLevel);
882 for (const auto &C : OptimizerLastEPCallbacks)
883 C(MPM, OptLevel);
74b04a01
XL
884 }
885
17df50a5
XL
886 if (ExtraPassesLen) {
887 if (auto Err = PB.parsePassPipeline(MPM, StringRef(ExtraPasses, ExtraPassesLen))) {
888 std::string ErrMsg = toString(std::move(Err));
889 LLVMRustSetLastError(ErrMsg.c_str());
890 return LLVMRustResult::Failure;
891 }
892 }
893
6a06907d 894 if (NeedThinLTOBufferPasses) {
74b04a01
XL
895 MPM.addPass(CanonicalizeAliasesPass());
896 MPM.addPass(NameAnonGlobalPass());
897 }
898
899 // Upgrade all calls to old intrinsics first.
900 for (Module::iterator I = TheModule->begin(), E = TheModule->end(); I != E;)
901 UpgradeCallsToIntrinsic(&*I++); // must be post-increment, as we remove
902
903 MPM.run(*TheModule, MAM);
17df50a5 904 return LLVMRustResult::Success;
74b04a01 905}
041b39d2
XL
906
907// Callback to demangle function name
908// Parameters:
909// * name to be demangled
910// * name len
911// * output buffer
912// * output buffer len
913// Returns len of demangled string, or 0 if demangle failed.
914typedef size_t (*DemangleFn)(const char*, size_t, char*, size_t);
915
916
917namespace {
918
919class RustAssemblyAnnotationWriter : public AssemblyAnnotationWriter {
920 DemangleFn Demangle;
921 std::vector<char> Buf;
922
923public:
924 RustAssemblyAnnotationWriter(DemangleFn Demangle) : Demangle(Demangle) {}
925
926 // Return empty string if demangle failed
927 // or if name does not need to be demangled
928 StringRef CallDemangle(StringRef name) {
929 if (!Demangle) {
930 return StringRef();
931 }
932
933 if (Buf.size() < name.size() * 2) {
934 // Semangled name usually shorter than mangled,
935 // but allocate twice as much memory just in case
936 Buf.resize(name.size() * 2);
937 }
938
939 auto R = Demangle(name.data(), name.size(), Buf.data(), Buf.size());
940 if (!R) {
941 // Demangle failed.
942 return StringRef();
943 }
944
945 auto Demangled = StringRef(Buf.data(), R);
946 if (Demangled == name) {
947 // Do not print anything if demangled name is equal to mangled.
948 return StringRef();
949 }
950
951 return Demangled;
952 }
953
954 void emitFunctionAnnot(const Function *F,
955 formatted_raw_ostream &OS) override {
956 StringRef Demangled = CallDemangle(F->getName());
957 if (Demangled.empty()) {
958 return;
959 }
960
961 OS << "; " << Demangled << "\n";
962 }
963
964 void emitInstructionAnnot(const Instruction *I,
965 formatted_raw_ostream &OS) override {
966 const char *Name;
967 const Value *Value;
968 if (const CallInst *CI = dyn_cast<CallInst>(I)) {
969 Name = "call";
f035d41b 970 Value = CI->getCalledOperand();
041b39d2
XL
971 } else if (const InvokeInst* II = dyn_cast<InvokeInst>(I)) {
972 Name = "invoke";
f035d41b 973 Value = II->getCalledOperand();
041b39d2
XL
974 } else {
975 // Could demangle more operations, e. g.
976 // `store %place, @function`.
977 return;
978 }
979
980 if (!Value->hasName()) {
981 return;
982 }
983
984 StringRef Demangled = CallDemangle(Value->getName());
985 if (Demangled.empty()) {
986 return;
987 }
988
989 OS << "; " << Name << " " << Demangled << "\n";
990 }
991};
992
041b39d2
XL
993} // namespace
994
532ac7d7 995extern "C" LLVMRustResult
60c5eb7d 996LLVMRustPrintModule(LLVMModuleRef M, const char *Path, DemangleFn Demangle) {
1a4d82fc 997 std::string ErrorInfo;
1a4d82fc 998 std::error_code EC;
17df50a5 999 raw_fd_ostream OS(Path, EC, sys::fs::OF_None);
1a4d82fc
JJ
1000 if (EC)
1001 ErrorInfo = EC.message();
532ac7d7
XL
1002 if (ErrorInfo != "") {
1003 LLVMRustSetLastError(ErrorInfo.c_str());
1004 return LLVMRustResult::Failure;
1005 }
1a4d82fc 1006
60c5eb7d 1007 RustAssemblyAnnotationWriter AAW(Demangle);
1a4d82fc 1008 formatted_raw_ostream FOS(OS);
60c5eb7d 1009 unwrap(M)->print(FOS, &AAW);
532ac7d7
XL
1010
1011 return LLVMRustResult::Success;
1a4d82fc
JJ
1012}
1013
32a655c1
SL
1014extern "C" void LLVMRustPrintPasses() {
1015 LLVMInitializePasses();
1016 struct MyListener : PassRegistrationListener {
1017 void passEnumerate(const PassInfo *Info) {
32a655c1
SL
1018 StringRef PassArg = Info->getPassArgument();
1019 StringRef PassName = Info->getPassName();
1020 if (!PassArg.empty()) {
1021 // These unsigned->signed casts could theoretically overflow, but
1022 // realistically never will (and even if, the result is implementation
1023 // defined rather plain UB).
1024 printf("%15.*s - %.*s\n", (int)PassArg.size(), PassArg.data(),
1025 (int)PassName.size(), PassName.data());
1026 }
32a655c1
SL
1027 }
1028 } Listener;
1a4d82fc 1029
32a655c1
SL
1030 PassRegistry *PR = PassRegistry::getPassRegistry();
1031 PR->enumerateWith(&Listener);
970d7e83
LB
1032}
1033
32a655c1
SL
1034extern "C" void LLVMRustRunRestrictionPass(LLVMModuleRef M, char **Symbols,
1035 size_t Len) {
32a655c1
SL
1036 auto PreserveFunctions = [=](const GlobalValue &GV) {
1037 for (size_t I = 0; I < Len; I++) {
1038 if (GV.getName() == Symbols[I]) {
1039 return true;
1040 }
1041 }
1042 return false;
1043 };
5bcae85e 1044
2b03887a 1045 internalizeModule(*unwrap(M), PreserveFunctions);
1a4d82fc
JJ
1046}
1047
c1a9b12d
SL
1048extern "C" void
1049LLVMRustSetDataLayoutFromTargetMachine(LLVMModuleRef Module,
1050 LLVMTargetMachineRef TMR) {
32a655c1
SL
1051 TargetMachine *Target = unwrap(TMR);
1052 unwrap(Module)->setDataLayout(Target->createDataLayout());
c1a9b12d
SL
1053}
1054
60c5eb7d
XL
1055extern "C" void LLVMRustSetModulePICLevel(LLVMModuleRef M) {
1056 unwrap(M)->setPICLevel(PICLevel::Level::BigPIC);
1057}
1058
32a655c1 1059extern "C" void LLVMRustSetModulePIELevel(LLVMModuleRef M) {
32a655c1 1060 unwrap(M)->setPIELevel(PIELevel::Level::Large);
5bcae85e 1061}
ea8adc8c 1062
6a06907d
XL
1063extern "C" void LLVMRustSetModuleCodeModel(LLVMModuleRef M,
1064 LLVMRustCodeModel Model) {
1065 auto CM = fromRust(Model);
2b03887a 1066 if (!CM)
6a06907d
XL
1067 return;
1068 unwrap(M)->setCodeModel(*CM);
1069}
1070
ea8adc8c
XL
1071// Here you'll find an implementation of ThinLTO as used by the Rust compiler
1072// right now. This ThinLTO support is only enabled on "recent ish" versions of
1073// LLVM, and otherwise it's just blanket rejected from other compilers.
1074//
1075// Most of this implementation is straight copied from LLVM. At the time of
1076// this writing it wasn't *quite* suitable to reuse more code from upstream
1077// for our purposes, but we should strive to upstream this support once it's
1078// ready to go! I figure we may want a bit of testing locally first before
1079// sending this upstream to LLVM. I hear though they're quite eager to receive
1080// feedback like this!
1081//
1082// If you're reading this code and wondering "what in the world" or you're
1083// working "good lord by LLVM upgrade is *still* failing due to these bindings"
1084// then fear not! (ok maybe fear a little). All code here is mostly based
1085// on `lib/LTO/ThinLTOCodeGenerator.cpp` in LLVM.
1086//
1087// You'll find that the general layout here roughly corresponds to the `run`
1088// method in that file as well as `ProcessThinLTOModule`. Functions are
1089// specifically commented below as well, but if you're updating this code
1090// or otherwise trying to understand it, the LLVM source will be useful in
1091// interpreting the mysteries within.
1092//
1093// Otherwise I'll apologize in advance, it probably requires a relatively
1094// significant investment on your part to "truly understand" what's going on
1095// here. Not saying I do myself, but it took me awhile staring at LLVM's source
1096// and various online resources about ThinLTO to make heads or tails of all
1097// this.
1098
ea8adc8c
XL
1099// This is a shared data structure which *must* be threadsafe to share
1100// read-only amongst threads. This also corresponds basically to the arguments
1101// of the `ProcessThinLTOModule` function in the LLVM source.
1102struct LLVMRustThinLTOData {
1103 // The combined index that is the global analysis over all modules we're
1104 // performing ThinLTO for. This is mostly managed by LLVM.
1105 ModuleSummaryIndex Index;
1106
1107 // All modules we may look at, stored as in-memory serialized versions. This
1108 // is later used when inlining to ensure we can extract any module to inline
1109 // from.
1110 StringMap<MemoryBufferRef> ModuleMap;
1111
1112 // A set that we manage of everything we *don't* want internalized. Note that
1113 // this includes all transitive references right now as well, but it may not
1114 // always!
1115 DenseSet<GlobalValue::GUID> GUIDPreservedSymbols;
1116
1117 // Not 100% sure what these are, but they impact what's internalized and
1118 // what's inlined across modules, I believe.
1119 StringMap<FunctionImporter::ImportMapTy> ImportLists;
1120 StringMap<FunctionImporter::ExportSetTy> ExportLists;
1121 StringMap<GVSummaryMapTy> ModuleToDefinedGVSummaries;
29967ef6 1122 StringMap<std::map<GlobalValue::GUID, GlobalValue::LinkageTypes>> ResolvedODR;
2c00a5a8 1123
9fa01778 1124 LLVMRustThinLTOData() : Index(/* HaveGVs = */ false) {}
ea8adc8c
XL
1125};
1126
1127// Just an argument to the `LLVMRustCreateThinLTOData` function below.
1128struct LLVMRustThinLTOModule {
1129 const char *identifier;
1130 const char *data;
1131 size_t len;
1132};
1133
1134// This is copied from `lib/LTO/ThinLTOCodeGenerator.cpp`, not sure what it
1135// does.
1136static const GlobalValueSummary *
1137getFirstDefinitionForLinker(const GlobalValueSummaryList &GVSummaryList) {
1138 auto StrongDefForLinker = llvm::find_if(
1139 GVSummaryList, [](const std::unique_ptr<GlobalValueSummary> &Summary) {
1140 auto Linkage = Summary->linkage();
1141 return !GlobalValue::isAvailableExternallyLinkage(Linkage) &&
1142 !GlobalValue::isWeakForLinker(Linkage);
1143 });
1144 if (StrongDefForLinker != GVSummaryList.end())
1145 return StrongDefForLinker->get();
1146
1147 auto FirstDefForLinker = llvm::find_if(
1148 GVSummaryList, [](const std::unique_ptr<GlobalValueSummary> &Summary) {
1149 auto Linkage = Summary->linkage();
1150 return !GlobalValue::isAvailableExternallyLinkage(Linkage);
1151 });
1152 if (FirstDefForLinker == GVSummaryList.end())
1153 return nullptr;
1154 return FirstDefForLinker->get();
1155}
1156
ea8adc8c
XL
1157// The main entry point for creating the global ThinLTO analysis. The structure
1158// here is basically the same as before threads are spawned in the `run`
1159// function of `lib/LTO/ThinLTOCodeGenerator.cpp`.
1160extern "C" LLVMRustThinLTOData*
1161LLVMRustCreateThinLTOData(LLVMRustThinLTOModule *modules,
1162 int num_modules,
1163 const char **preserved_symbols,
1164 int num_symbols) {
dfeec247 1165 auto Ret = std::make_unique<LLVMRustThinLTOData>();
ea8adc8c
XL
1166
1167 // Load each module's summary and merge it into one combined index
1168 for (int i = 0; i < num_modules; i++) {
1169 auto module = &modules[i];
1170 StringRef buffer(module->data, module->len);
1171 MemoryBufferRef mem_buffer(buffer, module->identifier);
1172
1173 Ret->ModuleMap[module->identifier] = mem_buffer;
1174
abe05a73
XL
1175 if (Error Err = readModuleSummaryIndex(mem_buffer, Ret->Index, i)) {
1176 LLVMRustSetLastError(toString(std::move(Err)).c_str());
1177 return nullptr;
1178 }
ea8adc8c
XL
1179 }
1180
1181 // Collect for each module the list of function it defines (GUID -> Summary)
1182 Ret->Index.collectDefinedGVSummariesPerModule(Ret->ModuleToDefinedGVSummaries);
1183
1184 // Convert the preserved symbols set from string to GUID, this is then needed
ff7c6d11 1185 // for internalization.
ea8adc8c 1186 for (int i = 0; i < num_symbols; i++) {
ff7c6d11
XL
1187 auto GUID = GlobalValue::getGUID(preserved_symbols[i]);
1188 Ret->GUIDPreservedSymbols.insert(GUID);
ea8adc8c
XL
1189 }
1190
1191 // Collect the import/export lists for all modules from the call-graph in the
1192 // combined index
1193 //
1194 // This is copied from `lib/LTO/ThinLTOCodeGenerator.cpp`
2c00a5a8
XL
1195 auto deadIsPrevailing = [&](GlobalValue::GUID G) {
1196 return PrevailingType::Unknown;
1197 };
48663c56
XL
1198 // We don't have a complete picture in our use of ThinLTO, just our immediate
1199 // crate, so we need `ImportEnabled = false` to limit internalization.
1200 // Otherwise, we sometimes lose `static` values -- see #60184.
9fa01778 1201 computeDeadSymbolsWithConstProp(Ret->Index, Ret->GUIDPreservedSymbols,
48663c56 1202 deadIsPrevailing, /* ImportEnabled = */ false);
ea8adc8c
XL
1203 ComputeCrossModuleImport(
1204 Ret->Index,
1205 Ret->ModuleToDefinedGVSummaries,
1206 Ret->ImportLists,
1207 Ret->ExportLists
1208 );
1209
1210 // Resolve LinkOnce/Weak symbols, this has to be computed early be cause it
1211 // impacts the caching.
1212 //
ff7c6d11
XL
1213 // This is copied from `lib/LTO/ThinLTOCodeGenerator.cpp` with some of this
1214 // being lifted from `lib/LTO/LTO.cpp` as well
ea8adc8c
XL
1215 DenseMap<GlobalValue::GUID, const GlobalValueSummary *> PrevailingCopy;
1216 for (auto &I : Ret->Index) {
abe05a73
XL
1217 if (I.second.SummaryList.size() > 1)
1218 PrevailingCopy[I.first] = getFirstDefinitionForLinker(I.second.SummaryList);
ea8adc8c
XL
1219 }
1220 auto isPrevailing = [&](GlobalValue::GUID GUID, const GlobalValueSummary *S) {
1221 const auto &Prevailing = PrevailingCopy.find(GUID);
1222 if (Prevailing == PrevailingCopy.end())
1223 return true;
1224 return Prevailing->second == S;
1225 };
1226 auto recordNewLinkage = [&](StringRef ModuleIdentifier,
1227 GlobalValue::GUID GUID,
1228 GlobalValue::LinkageTypes NewLinkage) {
29967ef6 1229 Ret->ResolvedODR[ModuleIdentifier][GUID] = NewLinkage;
ea8adc8c 1230 };
fc512014 1231
cdc7bbd5
XL
1232 // Uses FromPrevailing visibility scheme which works for many binary
1233 // formats. We probably could and should use ELF visibility scheme for many of
1234 // our targets, however.
1235 lto::Config conf;
1236 thinLTOResolvePrevailingInIndex(conf, Ret->Index, isPrevailing, recordNewLinkage,
1237 Ret->GUIDPreservedSymbols);
f2b60f7d 1238
ff7c6d11
XL
1239 // Here we calculate an `ExportedGUIDs` set for use in the `isExported`
1240 // callback below. This callback below will dictate the linkage for all
1241 // summaries in the index, and we basically just only want to ensure that dead
1242 // symbols are internalized. Otherwise everything that's already external
1243 // linkage will stay as external, and internal will stay as internal.
1244 std::set<GlobalValue::GUID> ExportedGUIDs;
1245 for (auto &List : Ret->Index) {
ff7c6d11 1246 for (auto &GVS: List.second.SummaryList) {
ff7c6d11
XL
1247 if (GlobalValue::isLocalLinkage(GVS->linkage()))
1248 continue;
1249 auto GUID = GVS->getOriginalName();
ff7c6d11 1250 if (GVS->flags().Live)
ff7c6d11
XL
1251 ExportedGUIDs.insert(GUID);
1252 }
1253 }
dfeec247
XL
1254 auto isExported = [&](StringRef ModuleIdentifier, ValueInfo VI) {
1255 const auto &ExportList = Ret->ExportLists.find(ModuleIdentifier);
1256 return (ExportList != Ret->ExportLists.end() &&
1257 ExportList->second.count(VI)) ||
1258 ExportedGUIDs.count(VI.getGUID());
1259 };
1260 thinLTOInternalizeAndPromoteInIndex(Ret->Index, isExported, isPrevailing);
ea8adc8c
XL
1261
1262 return Ret.release();
1263}
1264
1265extern "C" void
1266LLVMRustFreeThinLTOData(LLVMRustThinLTOData *Data) {
1267 delete Data;
1268}
1269
1270// Below are the various passes that happen *per module* when doing ThinLTO.
1271//
1272// In other words, these are the functions that are all run concurrently
1273// with one another, one per module. The passes here correspond to the analysis
1274// passes in `lib/LTO/ThinLTOCodeGenerator.cpp`, currently found in the
1275// `ProcessThinLTOModule` function. Here they're split up into separate steps
1276// so rustc can save off the intermediate bytecode between each step.
1277
f035d41b
XL
1278static bool
1279clearDSOLocalOnDeclarations(Module &Mod, TargetMachine &TM) {
1280 // When linking an ELF shared object, dso_local should be dropped. We
1281 // conservatively do this for -fpic.
1282 bool ClearDSOLocalOnDeclarations =
1283 TM.getTargetTriple().isOSBinFormatELF() &&
1284 TM.getRelocationModel() != Reloc::Static &&
1285 Mod.getPIELevel() == PIELevel::Default;
1286 return ClearDSOLocalOnDeclarations;
1287}
f035d41b 1288
ea8adc8c 1289extern "C" bool
f035d41b
XL
1290LLVMRustPrepareThinLTORename(const LLVMRustThinLTOData *Data, LLVMModuleRef M,
1291 LLVMTargetMachineRef TM) {
ea8adc8c 1292 Module &Mod = *unwrap(M);
f035d41b
XL
1293 TargetMachine &Target = *unwrap(TM);
1294
f035d41b
XL
1295 bool ClearDSOLocal = clearDSOLocalOnDeclarations(Mod, Target);
1296 bool error = renameModuleForThinLTO(Mod, Data->Index, ClearDSOLocal);
f035d41b
XL
1297
1298 if (error) {
ea8adc8c
XL
1299 LLVMRustSetLastError("renameModuleForThinLTO failed");
1300 return false;
1301 }
1302 return true;
1303}
1304
1305extern "C" bool
1306LLVMRustPrepareThinLTOResolveWeak(const LLVMRustThinLTOData *Data, LLVMModuleRef M) {
1307 Module &Mod = *unwrap(M);
1308 const auto &DefinedGlobals = Data->ModuleToDefinedGVSummaries.lookup(Mod.getModuleIdentifier());
c295e0f8
XL
1309#if LLVM_VERSION_GE(14, 0)
1310 thinLTOFinalizeInModule(Mod, DefinedGlobals, /*PropagateAttrs=*/true);
1311#else
a1dfa0c6 1312 thinLTOResolvePrevailingInModule(Mod, DefinedGlobals);
c295e0f8 1313#endif
ea8adc8c
XL
1314 return true;
1315}
1316
1317extern "C" bool
1318LLVMRustPrepareThinLTOInternalize(const LLVMRustThinLTOData *Data, LLVMModuleRef M) {
1319 Module &Mod = *unwrap(M);
1320 const auto &DefinedGlobals = Data->ModuleToDefinedGVSummaries.lookup(Mod.getModuleIdentifier());
1321 thinLTOInternalizeModule(Mod, DefinedGlobals);
1322 return true;
1323}
1324
1325extern "C" bool
f035d41b
XL
1326LLVMRustPrepareThinLTOImport(const LLVMRustThinLTOData *Data, LLVMModuleRef M,
1327 LLVMTargetMachineRef TM) {
ea8adc8c 1328 Module &Mod = *unwrap(M);
f035d41b 1329 TargetMachine &Target = *unwrap(TM);
8faf50e0 1330
ea8adc8c
XL
1331 const auto &ImportList = Data->ImportLists.lookup(Mod.getModuleIdentifier());
1332 auto Loader = [&](StringRef Identifier) {
1333 const auto &Memory = Data->ModuleMap.lookup(Identifier);
1334 auto &Context = Mod.getContext();
8faf50e0
XL
1335 auto MOrErr = getLazyBitcodeModule(Memory, Context, true, true);
1336
1337 if (!MOrErr)
b7449926 1338 return MOrErr;
8faf50e0
XL
1339
1340 // The rest of this closure is a workaround for
1341 // https://bugs.llvm.org/show_bug.cgi?id=38184 where during ThinLTO imports
1342 // we accidentally import wasm custom sections into different modules,
1343 // duplicating them by in the final output artifact.
1344 //
1345 // The issue is worked around here by manually removing the
1346 // `wasm.custom_sections` named metadata node from any imported module. This
1347 // we know isn't used by any optimization pass so there's no need for it to
1348 // be imported.
1349 //
1350 // Note that the metadata is currently lazily loaded, so we materialize it
1351 // here before looking up if there's metadata inside. The `FunctionImporter`
1352 // will immediately materialize metadata anyway after an import, so this
1353 // shouldn't be a perf hit.
1354 if (Error Err = (*MOrErr)->materializeMetadata()) {
1355 Expected<std::unique_ptr<Module>> Ret(std::move(Err));
b7449926 1356 return Ret;
8faf50e0
XL
1357 }
1358
1359 auto *WasmCustomSections = (*MOrErr)->getNamedMetadata("wasm.custom_sections");
1360 if (WasmCustomSections)
1361 WasmCustomSections->eraseFromParent();
1362
b7449926 1363 return MOrErr;
ea8adc8c 1364 };
f035d41b
XL
1365 bool ClearDSOLocal = clearDSOLocalOnDeclarations(Mod, Target);
1366 FunctionImporter Importer(Data->Index, Loader, ClearDSOLocal);
ea8adc8c
XL
1367 Expected<bool> Result = Importer.importFunctions(Mod, ImportList);
1368 if (!Result) {
1369 LLVMRustSetLastError(toString(Result.takeError()).c_str());
1370 return false;
1371 }
1372 return true;
1373}
1374
1375// This struct and various functions are sort of a hack right now, but the
1376// problem is that we've got in-memory LLVM modules after we generate and
1377// optimize all codegen-units for one compilation in rustc. To be compatible
1378// with the LTO support above we need to serialize the modules plus their
1379// ThinLTO summary into memory.
1380//
1381// This structure is basically an owned version of a serialize module, with
1382// a ThinLTO summary attached.
1383struct LLVMRustThinLTOBuffer {
1384 std::string data;
1385};
1386
1387extern "C" LLVMRustThinLTOBuffer*
064997fb 1388LLVMRustThinLTOBufferCreate(LLVMModuleRef M, bool is_thin) {
dfeec247 1389 auto Ret = std::make_unique<LLVMRustThinLTOBuffer>();
ea8adc8c
XL
1390 {
1391 raw_string_ostream OS(Ret->data);
1392 {
064997fb 1393 if (is_thin) {
f2b60f7d
FG
1394 PassBuilder PB;
1395 LoopAnalysisManager LAM;
1396 FunctionAnalysisManager FAM;
1397 CGSCCAnalysisManager CGAM;
1398 ModuleAnalysisManager MAM;
1399 PB.registerModuleAnalyses(MAM);
1400 PB.registerCGSCCAnalyses(CGAM);
1401 PB.registerFunctionAnalyses(FAM);
1402 PB.registerLoopAnalyses(LAM);
1403 PB.crossRegisterProxies(LAM, FAM, CGAM, MAM);
1404 ModulePassManager MPM;
1405 MPM.addPass(ThinLTOBitcodeWriterPass(OS, nullptr));
1406 MPM.run(*unwrap(M), MAM);
064997fb 1407 } else {
2b03887a 1408 WriteBitcodeToFile(*unwrap(M), OS);
064997fb 1409 }
ea8adc8c
XL
1410 }
1411 }
1412 return Ret.release();
1413}
1414
1415extern "C" void
1416LLVMRustThinLTOBufferFree(LLVMRustThinLTOBuffer *Buffer) {
1417 delete Buffer;
1418}
1419
1420extern "C" const void*
1421LLVMRustThinLTOBufferPtr(const LLVMRustThinLTOBuffer *Buffer) {
1422 return Buffer->data.data();
1423}
1424
1425extern "C" size_t
1426LLVMRustThinLTOBufferLen(const LLVMRustThinLTOBuffer *Buffer) {
1427 return Buffer->data.length();
1428}
1429
1430// This is what we used to parse upstream bitcode for actual ThinLTO
9c376795 1431// processing. We'll call this once per module optimized through ThinLTO, and
ea8adc8c
XL
1432// it'll be called concurrently on many threads.
1433extern "C" LLVMModuleRef
9fa01778
XL
1434LLVMRustParseBitcodeForLTO(LLVMContextRef Context,
1435 const char *data,
1436 size_t len,
1437 const char *identifier) {
ea8adc8c
XL
1438 StringRef Data(data, len);
1439 MemoryBufferRef Buffer(Data, identifier);
1440 unwrap(Context)->enableDebugTypeODRUniquing();
1441 Expected<std::unique_ptr<Module>> SrcOrError =
1442 parseBitcodeFile(Buffer, *unwrap(Context));
1443 if (!SrcOrError) {
1444 LLVMRustSetLastError(toString(SrcOrError.takeError()).c_str());
1445 return nullptr;
1446 }
1447 return wrap(std::move(*SrcOrError).release());
1448}
1449
f9f354fc
XL
1450// Find the bitcode section in the object file data and return it as a slice.
1451// Fail if the bitcode section is present but empty.
1452//
1453// On success, the return value is the pointer to the start of the slice and
1454// `out_len` is filled with the (non-zero) length. On failure, the return value
1455// is `nullptr` and `out_len` is set to zero.
1456extern "C" const char*
1457LLVMRustGetBitcodeSliceFromObjectData(const char *data,
1458 size_t len,
1459 size_t *out_len) {
1460 *out_len = 0;
1461
1462 StringRef Data(data, len);
1463 MemoryBufferRef Buffer(Data, ""); // The id is unused.
1464
1465 Expected<MemoryBufferRef> BitcodeOrError =
1466 object::IRObjectFile::findBitcodeInMemBuffer(Buffer);
1467 if (!BitcodeOrError) {
1468 LLVMRustSetLastError(toString(BitcodeOrError.takeError()).c_str());
1469 return nullptr;
1470 }
1471
1472 *out_len = BitcodeOrError->getBufferSize();
1473 return BitcodeOrError->getBufferStart();
1474}
1475
ff7c6d11
XL
1476// Rewrite all `DICompileUnit` pointers to the `DICompileUnit` specified. See
1477// the comment in `back/lto.rs` for why this exists.
1478extern "C" void
064997fb 1479LLVMRustThinLTOGetDICompileUnit(LLVMModuleRef Mod,
ff7c6d11
XL
1480 DICompileUnit **A,
1481 DICompileUnit **B) {
1482 Module *M = unwrap(Mod);
1483 DICompileUnit **Cur = A;
1484 DICompileUnit **Next = B;
1485 for (DICompileUnit *CU : M->debug_compile_units()) {
1486 *Cur = CU;
1487 Cur = Next;
1488 Next = nullptr;
1489 if (Cur == nullptr)
1490 break;
1491 }
1492}
1493
1494// Rewrite all `DICompileUnit` pointers to the `DICompileUnit` specified. See
1495// the comment in `back/lto.rs` for why this exists.
1496extern "C" void
064997fb 1497LLVMRustThinLTOPatchDICompileUnit(LLVMModuleRef Mod, DICompileUnit *Unit) {
ff7c6d11
XL
1498 Module *M = unwrap(Mod);
1499
1500 // If the original source module didn't have a `DICompileUnit` then try to
1501 // merge all the existing compile units. If there aren't actually any though
1502 // then there's not much for us to do so return.
1503 if (Unit == nullptr) {
1504 for (DICompileUnit *CU : M->debug_compile_units()) {
1505 Unit = CU;
1506 break;
1507 }
1508 if (Unit == nullptr)
1509 return;
1510 }
1511
1512 // Use LLVM's built-in `DebugInfoFinder` to find a bunch of debuginfo and
f035d41b
XL
1513 // process it recursively. Note that we used to specifically iterate over
1514 // instructions to ensure we feed everything into it, but `processModule`
1515 // started doing this the same way in LLVM 7 (commit d769eb36ab2b8).
ff7c6d11
XL
1516 DebugInfoFinder Finder;
1517 Finder.processModule(*M);
ff7c6d11
XL
1518
1519 // After we've found all our debuginfo, rewrite all subprograms to point to
1520 // the same `DICompileUnit`.
1521 for (auto &F : Finder.subprograms()) {
1522 F->replaceUnit(Unit);
1523 }
1524
1525 // Erase any other references to other `DICompileUnit` instances, the verifier
1526 // will later ensure that we don't actually have any other stale references to
1527 // worry about.
1528 auto *MD = M->getNamedMetadata("llvm.dbg.cu");
1529 MD->clearOperands();
1530 MD->addOperand(Unit);
1531}
29967ef6
XL
1532
1533// Computes the LTO cache key for the provided 'ModId' in the given 'Data',
1534// storing the result in 'KeyOut'.
1535// Currently, this cache key is a SHA-1 hash of anything that could affect
1536// the result of optimizing this module (e.g. module imports, exports, liveness
1537// of access globals, etc).
1538// The precise details are determined by LLVM in `computeLTOCacheKey`, which is
1539// used during the normal linker-plugin incremental thin-LTO process.
1540extern "C" void
1541LLVMRustComputeLTOCacheKey(RustStringRef KeyOut, const char *ModId, LLVMRustThinLTOData *Data) {
1542 SmallString<40> Key;
1543 llvm::lto::Config conf;
1544 const auto &ImportList = Data->ImportLists.lookup(ModId);
1545 const auto &ExportList = Data->ExportLists.lookup(ModId);
1546 const auto &ResolvedODR = Data->ResolvedODR.lookup(ModId);
1547 const auto &DefinedGlobals = Data->ModuleToDefinedGVSummaries.lookup(ModId);
1548 std::set<GlobalValue::GUID> CfiFunctionDefs;
1549 std::set<GlobalValue::GUID> CfiFunctionDecls;
1550
1551 // Based on the 'InProcessThinBackend' constructor in LLVM
1552 for (auto &Name : Data->Index.cfiFunctionDefs())
1553 CfiFunctionDefs.insert(
1554 GlobalValue::getGUID(GlobalValue::dropLLVMManglingEscape(Name)));
1555 for (auto &Name : Data->Index.cfiFunctionDecls())
1556 CfiFunctionDecls.insert(
1557 GlobalValue::getGUID(GlobalValue::dropLLVMManglingEscape(Name)));
1558
1559 llvm::computeLTOCacheKey(Key, conf, Data->Index, ModId,
1560 ImportList, ExportList, ResolvedODR, DefinedGlobals, CfiFunctionDefs, CfiFunctionDecls
1561 );
1562
1563 LLVMRustStringWriteImpl(KeyOut, Key.c_str(), Key.size());
1564}