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