]> git.proxmox.com Git - rustc.git/blame - src/rustllvm/PassWrapper.cpp
New upstream version 1.32.0+dfsg1
[rustc.git] / src / rustllvm / PassWrapper.cpp
CommitLineData
970d7e83
LB
1// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
2// file at the top-level directory of this distribution and at
3// http://rust-lang.org/COPYRIGHT.
4//
5// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8// option. This file may not be copied, modified, or distributed
9// except according to those terms.
10
1a4d82fc
JJ
11#include <stdio.h>
12
041b39d2 13#include <vector>
ff7c6d11 14#include <set>
041b39d2 15
970d7e83
LB
16#include "rustllvm.h"
17
62682a34
SL
18#include "llvm/Analysis/TargetLibraryInfo.h"
19#include "llvm/Analysis/TargetTransformInfo.h"
5bcae85e 20#include "llvm/IR/AutoUpgrade.h"
041b39d2 21#include "llvm/IR/AssemblyAnnotationWriter.h"
32a655c1
SL
22#include "llvm/Support/CBindingWrapping.h"
23#include "llvm/Support/FileSystem.h"
24#include "llvm/Support/Host.h"
c1a9b12d 25#include "llvm/Target/TargetMachine.h"
1a4d82fc 26#include "llvm/Transforms/IPO/PassManagerBuilder.h"
970d7e83 27
2c00a5a8
XL
28#if LLVM_VERSION_GE(6, 0)
29#include "llvm/CodeGen/TargetSubtargetInfo.h"
30#include "llvm/IR/IntrinsicInst.h"
31#else
32#include "llvm/Target/TargetSubtargetInfo.h"
33#endif
34
476ff2be 35#include "llvm/Transforms/IPO/AlwaysInliner.h"
ea8adc8c
XL
36#include "llvm/Transforms/IPO/FunctionImport.h"
37#include "llvm/Transforms/Utils/FunctionImportUtils.h"
38#include "llvm/LTO/LTO.h"
62682a34 39
1a4d82fc 40#include "llvm-c/Transforms/PassManagerBuilder.h"
970d7e83 41
1a4d82fc 42using namespace llvm;
62682a34 43using namespace llvm::legacy;
970d7e83 44
1a4d82fc 45extern cl::opt<bool> EnableARMEHABI;
970d7e83 46
1a4d82fc
JJ
47typedef struct LLVMOpaquePass *LLVMPassRef;
48typedef struct LLVMOpaqueTargetMachine *LLVMTargetMachineRef;
49
50DEFINE_STDCXX_CONVERSION_FUNCTIONS(Pass, LLVMPassRef)
51DEFINE_STDCXX_CONVERSION_FUNCTIONS(TargetMachine, LLVMTargetMachineRef)
32a655c1
SL
52DEFINE_STDCXX_CONVERSION_FUNCTIONS(PassManagerBuilder,
53 LLVMPassManagerBuilderRef)
970d7e83 54
32a655c1 55extern "C" void LLVMInitializePasses() {
970d7e83
LB
56 PassRegistry &Registry = *PassRegistry::getPassRegistry();
57 initializeCore(Registry);
58 initializeCodeGen(Registry);
59 initializeScalarOpts(Registry);
60 initializeVectorization(Registry);
61 initializeIPO(Registry);
62 initializeAnalysis(Registry);
970d7e83
LB
63 initializeTransformUtils(Registry);
64 initializeInstCombine(Registry);
65 initializeInstrumentation(Registry);
66 initializeTarget(Registry);
67}
68
5bcae85e
SL
69enum class LLVMRustPassKind {
70 Other,
7453a54e
SL
71 Function,
72 Module,
7453a54e
SL
73};
74
32a655c1
SL
75static LLVMRustPassKind toRust(PassKind Kind) {
76 switch (Kind) {
5bcae85e 77 case PT_Function:
32a655c1 78 return LLVMRustPassKind::Function;
5bcae85e 79 case PT_Module:
32a655c1 80 return LLVMRustPassKind::Module;
5bcae85e 81 default:
32a655c1 82 return LLVMRustPassKind::Other;
5bcae85e
SL
83 }
84}
85
32a655c1
SL
86extern "C" LLVMPassRef LLVMRustFindAndCreatePass(const char *PassName) {
87 StringRef SR(PassName);
88 PassRegistry *PR = PassRegistry::getPassRegistry();
970d7e83 89
32a655c1
SL
90 const PassInfo *PI = PR->getPassInfo(SR);
91 if (PI) {
92 return wrap(PI->createPass());
93 }
94 return nullptr;
7453a54e
SL
95}
96
32a655c1
SL
97extern "C" LLVMRustPassKind LLVMRustPassKind(LLVMPassRef RustPass) {
98 assert(RustPass);
99 Pass *Pass = unwrap(RustPass);
100 return toRust(Pass->getPassKind());
7453a54e
SL
101}
102
32a655c1
SL
103extern "C" void LLVMRustAddPass(LLVMPassManagerRef PMR, LLVMPassRef RustPass) {
104 assert(RustPass);
105 Pass *Pass = unwrap(RustPass);
106 PassManagerBase *PMB = unwrap(PMR);
107 PMB->add(Pass);
1a4d82fc
JJ
108}
109
ea8adc8c 110extern "C"
a1dfa0c6 111void LLVMRustPassManagerBuilderPopulateThinLTOPassManager(
ea8adc8c
XL
112 LLVMPassManagerBuilderRef PMBR,
113 LLVMPassManagerRef PMR
114) {
ea8adc8c 115 unwrap(PMBR)->populateThinLTOPassManager(*unwrap(PMR));
ea8adc8c
XL
116}
117
a7813a04
XL
118#ifdef LLVM_COMPONENT_X86
119#define SUBTARGET_X86 SUBTARGET(X86)
120#else
121#define SUBTARGET_X86
122#endif
123
124#ifdef LLVM_COMPONENT_ARM
125#define SUBTARGET_ARM SUBTARGET(ARM)
126#else
127#define SUBTARGET_ARM
128#endif
129
130#ifdef LLVM_COMPONENT_AARCH64
131#define SUBTARGET_AARCH64 SUBTARGET(AArch64)
132#else
133#define SUBTARGET_AARCH64
134#endif
135
136#ifdef LLVM_COMPONENT_MIPS
137#define SUBTARGET_MIPS SUBTARGET(Mips)
138#else
139#define SUBTARGET_MIPS
140#endif
141
142#ifdef LLVM_COMPONENT_POWERPC
143#define SUBTARGET_PPC SUBTARGET(PPC)
144#else
145#define SUBTARGET_PPC
146#endif
147
9e0c209e
SL
148#ifdef LLVM_COMPONENT_SYSTEMZ
149#define SUBTARGET_SYSTEMZ SUBTARGET(SystemZ)
150#else
151#define SUBTARGET_SYSTEMZ
152#endif
153
476ff2be
SL
154#ifdef LLVM_COMPONENT_MSP430
155#define SUBTARGET_MSP430 SUBTARGET(MSP430)
156#else
157#define SUBTARGET_MSP430
158#endif
159
b7449926
XL
160#ifdef LLVM_COMPONENT_RISCV
161#define SUBTARGET_RISCV SUBTARGET(RISCV)
162#else
163#define SUBTARGET_RISCV
164#endif
165
32a655c1
SL
166#ifdef LLVM_COMPONENT_SPARC
167#define SUBTARGET_SPARC SUBTARGET(Sparc)
168#else
169#define SUBTARGET_SPARC
170#endif
171
7cac9316
XL
172#ifdef LLVM_COMPONENT_HEXAGON
173#define SUBTARGET_HEXAGON SUBTARGET(Hexagon)
174#else
175#define SUBTARGET_HEXAGON
176#endif
177
32a655c1
SL
178#define GEN_SUBTARGETS \
179 SUBTARGET_X86 \
180 SUBTARGET_ARM \
181 SUBTARGET_AARCH64 \
182 SUBTARGET_MIPS \
183 SUBTARGET_PPC \
184 SUBTARGET_SYSTEMZ \
185 SUBTARGET_MSP430 \
7cac9316 186 SUBTARGET_SPARC \
b7449926
XL
187 SUBTARGET_HEXAGON \
188 SUBTARGET_RISCV \
32a655c1
SL
189
190#define SUBTARGET(x) \
191 namespace llvm { \
192 extern const SubtargetFeatureKV x##FeatureKV[]; \
193 extern const SubtargetFeatureKV x##SubTypeKV[]; \
a7813a04
XL
194 }
195
196GEN_SUBTARGETS
197#undef SUBTARGET
198
32a655c1
SL
199extern "C" bool LLVMRustHasFeature(LLVMTargetMachineRef TM,
200 const char *Feature) {
0531ce1d 201#if LLVM_VERSION_GE(6, 0)
32a655c1
SL
202 TargetMachine *Target = unwrap(TM);
203 const MCSubtargetInfo *MCInfo = Target->getMCSubtargetInfo();
0531ce1d
XL
204 return MCInfo->checkFeatures(std::string("+") + Feature);
205#else
3b2f2976 206 return false;
0531ce1d 207#endif
a7813a04
XL
208}
209
5bcae85e 210enum class LLVMRustCodeModel {
32a655c1 211 Other,
32a655c1
SL
212 Small,
213 Kernel,
214 Medium,
215 Large,
2c00a5a8 216 None,
5bcae85e
SL
217};
218
32a655c1
SL
219static CodeModel::Model fromRust(LLVMRustCodeModel Model) {
220 switch (Model) {
32a655c1
SL
221 case LLVMRustCodeModel::Small:
222 return CodeModel::Small;
223 case LLVMRustCodeModel::Kernel:
224 return CodeModel::Kernel;
225 case LLVMRustCodeModel::Medium:
226 return CodeModel::Medium;
227 case LLVMRustCodeModel::Large:
228 return CodeModel::Large;
229 default:
ff7c6d11 230 report_fatal_error("Bad CodeModel.");
5bcae85e
SL
231 }
232}
233
234enum class LLVMRustCodeGenOptLevel {
32a655c1
SL
235 Other,
236 None,
237 Less,
238 Default,
239 Aggressive,
5bcae85e
SL
240};
241
32a655c1
SL
242static CodeGenOpt::Level fromRust(LLVMRustCodeGenOptLevel Level) {
243 switch (Level) {
244 case LLVMRustCodeGenOptLevel::None:
245 return CodeGenOpt::None;
246 case LLVMRustCodeGenOptLevel::Less:
247 return CodeGenOpt::Less;
248 case LLVMRustCodeGenOptLevel::Default:
249 return CodeGenOpt::Default;
250 case LLVMRustCodeGenOptLevel::Aggressive:
251 return CodeGenOpt::Aggressive;
252 default:
ff7c6d11 253 report_fatal_error("Bad CodeGenOptLevel.");
5bcae85e
SL
254 }
255}
256
7cac9316
XL
257enum class LLVMRustRelocMode {
258 Default,
259 Static,
260 PIC,
261 DynamicNoPic,
262 ROPI,
263 RWPI,
264 ROPIRWPI,
265};
266
7cac9316 267static Optional<Reloc::Model> fromRust(LLVMRustRelocMode RustReloc) {
7cac9316
XL
268 switch (RustReloc) {
269 case LLVMRustRelocMode::Default:
7cac9316 270 return None;
7cac9316
XL
271 case LLVMRustRelocMode::Static:
272 return Reloc::Static;
273 case LLVMRustRelocMode::PIC:
274 return Reloc::PIC_;
275 case LLVMRustRelocMode::DynamicNoPic:
276 return Reloc::DynamicNoPIC;
7cac9316
XL
277 case LLVMRustRelocMode::ROPI:
278 return Reloc::ROPI;
279 case LLVMRustRelocMode::RWPI:
280 return Reloc::RWPI;
281 case LLVMRustRelocMode::ROPIRWPI:
282 return Reloc::ROPI_RWPI;
7cac9316 283 }
ff7c6d11 284 report_fatal_error("Bad RelocModel.");
7cac9316
XL
285}
286
a1dfa0c6 287#ifdef LLVM_RUSTLLVM
5bcae85e
SL
288/// getLongestEntryLength - Return the length of the longest entry in the table.
289///
290static size_t getLongestEntryLength(ArrayRef<SubtargetFeatureKV> Table) {
291 size_t MaxLen = 0;
292 for (auto &I : Table)
293 MaxLen = std::max(MaxLen, std::strlen(I.Key));
294 return MaxLen;
295}
296
32a655c1
SL
297extern "C" void LLVMRustPrintTargetCPUs(LLVMTargetMachineRef TM) {
298 const TargetMachine *Target = unwrap(TM);
299 const MCSubtargetInfo *MCInfo = Target->getMCSubtargetInfo();
ea8adc8c
XL
300 const Triple::ArchType HostArch = Triple(sys::getProcessTriple()).getArch();
301 const Triple::ArchType TargetArch = Target->getTargetTriple().getArch();
32a655c1
SL
302 const ArrayRef<SubtargetFeatureKV> CPUTable = MCInfo->getCPUTable();
303 unsigned MaxCPULen = getLongestEntryLength(CPUTable);
304
305 printf("Available CPUs for this target:\n");
ea8adc8c
XL
306 if (HostArch == TargetArch) {
307 const StringRef HostCPU = sys::getHostCPUName();
308 printf(" %-*s - Select the CPU of the current host (currently %.*s).\n",
309 MaxCPULen, "native", (int)HostCPU.size(), HostCPU.data());
310 }
32a655c1
SL
311 for (auto &CPU : CPUTable)
312 printf(" %-*s - %s.\n", MaxCPULen, CPU.Key, CPU.Desc);
313 printf("\n");
5bcae85e
SL
314}
315
32a655c1
SL
316extern "C" void LLVMRustPrintTargetFeatures(LLVMTargetMachineRef TM) {
317 const TargetMachine *Target = unwrap(TM);
318 const MCSubtargetInfo *MCInfo = Target->getMCSubtargetInfo();
319 const ArrayRef<SubtargetFeatureKV> FeatTable = MCInfo->getFeatureTable();
320 unsigned MaxFeatLen = getLongestEntryLength(FeatTable);
321
322 printf("Available features for this target:\n");
323 for (auto &Feature : FeatTable)
324 printf(" %-*s - %s.\n", MaxFeatLen, Feature.Key, Feature.Desc);
325 printf("\n");
326
327 printf("Use +feature to enable a feature, or -feature to disable it.\n"
328 "For example, rustc -C -target-cpu=mycpu -C "
329 "target-feature=+feature1,-feature2\n\n");
5bcae85e
SL
330}
331
332#else
333
32a655c1
SL
334extern "C" void LLVMRustPrintTargetCPUs(LLVMTargetMachineRef) {
335 printf("Target CPU help is not supported by this LLVM version.\n\n");
5bcae85e
SL
336}
337
32a655c1
SL
338extern "C" void LLVMRustPrintTargetFeatures(LLVMTargetMachineRef) {
339 printf("Target features help is not supported by this LLVM version.\n\n");
5bcae85e
SL
340}
341#endif
342
b7449926
XL
343extern "C" const char* LLVMRustGetHostCPUName(size_t *len) {
344 StringRef Name = sys::getHostCPUName();
345 *len = Name.size();
346 return Name.data();
347}
348
32a655c1
SL
349extern "C" LLVMTargetMachineRef LLVMRustCreateTargetMachine(
350 const char *TripleStr, const char *CPU, const char *Feature,
7cac9316 351 LLVMRustCodeModel RustCM, LLVMRustRelocMode RustReloc,
32a655c1
SL
352 LLVMRustCodeGenOptLevel RustOptLevel, bool UseSoftFloat,
353 bool PositionIndependentExecutable, bool FunctionSections,
abe05a73
XL
354 bool DataSections,
355 bool TrapUnreachable,
b7449926 356 bool Singlethread,
0bf4aa26
XL
357 bool AsmComments,
358 bool EmitStackSizeSection) {
5bcae85e 359
32a655c1 360 auto OptLevel = fromRust(RustOptLevel);
7cac9316 361 auto RM = fromRust(RustReloc);
5bcae85e 362
32a655c1
SL
363 std::string Error;
364 Triple Trip(Triple::normalize(TripleStr));
365 const llvm::Target *TheTarget =
366 TargetRegistry::lookupTarget(Trip.getTriple(), Error);
367 if (TheTarget == nullptr) {
368 LLVMRustSetLastError(Error.c_str());
369 return nullptr;
370 }
1a4d82fc 371
32a655c1 372 TargetOptions Options;
5bcae85e 373
32a655c1
SL
374 Options.FloatABIType = FloatABI::Default;
375 if (UseSoftFloat) {
376 Options.FloatABIType = FloatABI::Soft;
377 }
378 Options.DataSections = DataSections;
379 Options.FunctionSections = FunctionSections;
b7449926
XL
380 Options.MCOptions.AsmVerbose = AsmComments;
381 Options.MCOptions.PreserveAsmComments = AsmComments;
32a655c1 382
abe05a73 383 if (TrapUnreachable) {
94b46f34 384 // Tell LLVM to codegen `unreachable` into an explicit trap instruction.
abe05a73
XL
385 // This limits the extent of possible undefined behavior in some cases, as
386 // it prevents control flow from "falling through" into whatever code
387 // happens to be laid out next in memory.
388 Options.TrapUnreachable = true;
389 }
390
391 if (Singlethread) {
392 Options.ThreadModel = ThreadModel::Single;
393 }
394
2c00a5a8 395#if LLVM_VERSION_GE(6, 0)
0bf4aa26
XL
396 Options.EmitStackSizeSection = EmitStackSizeSection;
397
2c00a5a8
XL
398 Optional<CodeModel::Model> CM;
399#else
400 CodeModel::Model CM = CodeModel::Model::Default;
401#endif
402 if (RustCM != LLVMRustCodeModel::None)
403 CM = fromRust(RustCM);
32a655c1 404 TargetMachine *TM = TheTarget->createTargetMachine(
b7449926 405 Trip.getTriple(), CPU, Feature, Options, RM, CM, OptLevel);
32a655c1 406 return wrap(TM);
1a4d82fc
JJ
407}
408
32a655c1
SL
409extern "C" void LLVMRustDisposeTargetMachine(LLVMTargetMachineRef TM) {
410 delete unwrap(TM);
1a4d82fc
JJ
411}
412
413// Unfortunately, LLVM doesn't expose a C API to add the corresponding analysis
414// passes for a target to a pass manager. We export that functionality through
415// this function.
32a655c1
SL
416extern "C" void LLVMRustAddAnalysisPasses(LLVMTargetMachineRef TM,
417 LLVMPassManagerRef PMR,
418 LLVMModuleRef M) {
419 PassManagerBase *PM = unwrap(PMR);
420 PM->add(
421 createTargetTransformInfoWrapperPass(unwrap(TM)->getTargetIRAnalysis()));
62682a34
SL
422}
423
32a655c1
SL
424extern "C" void LLVMRustConfigurePassManagerBuilder(
425 LLVMPassManagerBuilderRef PMBR, LLVMRustCodeGenOptLevel OptLevel,
94b46f34 426 bool MergeFunctions, bool SLPVectorize, bool LoopVectorize, bool PrepareForThinLTO,
0531ce1d 427 const char* PGOGenPath, const char* PGOUsePath) {
a1dfa0c6 428#if LLVM_VERSION_GE(7, 0)
94b46f34
XL
429 unwrap(PMBR)->MergeFunctions = MergeFunctions;
430#endif
32a655c1
SL
431 unwrap(PMBR)->SLPVectorize = SLPVectorize;
432 unwrap(PMBR)->OptLevel = fromRust(OptLevel);
433 unwrap(PMBR)->LoopVectorize = LoopVectorize;
94b46f34 434 unwrap(PMBR)->PrepareForThinLTO = PrepareForThinLTO;
0531ce1d 435
0531ce1d
XL
436 if (PGOGenPath) {
437 assert(!PGOUsePath);
438 unwrap(PMBR)->EnablePGOInstrGen = true;
439 unwrap(PMBR)->PGOInstrGen = PGOGenPath;
440 }
441 if (PGOUsePath) {
442 assert(!PGOGenPath);
443 unwrap(PMBR)->PGOInstrUse = PGOUsePath;
444 }
1a4d82fc
JJ
445}
446
447// Unfortunately, the LLVM C API doesn't provide a way to set the `LibraryInfo`
448// field of a PassManagerBuilder, we expose our own method of doing so.
32a655c1
SL
449extern "C" void LLVMRustAddBuilderLibraryInfo(LLVMPassManagerBuilderRef PMBR,
450 LLVMModuleRef M,
451 bool DisableSimplifyLibCalls) {
452 Triple TargetTriple(unwrap(M)->getTargetTriple());
453 TargetLibraryInfoImpl *TLI = new TargetLibraryInfoImpl(TargetTriple);
454 if (DisableSimplifyLibCalls)
455 TLI->disableAllFunctions();
456 unwrap(PMBR)->LibraryInfo = TLI;
1a4d82fc
JJ
457}
458
459// Unfortunately, the LLVM C API doesn't provide a way to create the
460// TargetLibraryInfo pass, so we use this method to do so.
32a655c1
SL
461extern "C" void LLVMRustAddLibraryInfo(LLVMPassManagerRef PMR, LLVMModuleRef M,
462 bool DisableSimplifyLibCalls) {
463 Triple TargetTriple(unwrap(M)->getTargetTriple());
464 TargetLibraryInfoImpl TLII(TargetTriple);
465 if (DisableSimplifyLibCalls)
466 TLII.disableAllFunctions();
467 unwrap(PMR)->add(new TargetLibraryInfoWrapperPass(TLII));
1a4d82fc
JJ
468}
469
470// Unfortunately, the LLVM C API doesn't provide an easy way of iterating over
471// all the functions in a module, so we do that manually here. You'll find
472// similar code in clang's BackendUtil.cpp file.
32a655c1
SL
473extern "C" void LLVMRustRunFunctionPassManager(LLVMPassManagerRef PMR,
474 LLVMModuleRef M) {
475 llvm::legacy::FunctionPassManager *P =
476 unwrap<llvm::legacy::FunctionPassManager>(PMR);
477 P->doInitialization();
478
479 // Upgrade all calls to old intrinsics first.
480 for (Module::iterator I = unwrap(M)->begin(), E = unwrap(M)->end(); I != E;)
481 UpgradeCallsToIntrinsic(&*I++); // must be post-increment, as we remove
482
483 for (Module::iterator I = unwrap(M)->begin(), E = unwrap(M)->end(); I != E;
484 ++I)
485 if (!I->isDeclaration())
486 P->run(*I);
487
488 P->doFinalization();
1a4d82fc
JJ
489}
490
32a655c1
SL
491extern "C" void LLVMRustSetLLVMOptions(int Argc, char **Argv) {
492 // Initializing the command-line options more than once is not allowed. So,
493 // check if they've already been initialized. (This could happen if we're
494 // being called from rustpkg, for example). If the arguments change, then
495 // that's just kinda unfortunate.
496 static bool Initialized = false;
497 if (Initialized)
498 return;
499 Initialized = true;
500 cl::ParseCommandLineOptions(Argc, Argv);
1a4d82fc
JJ
501}
502
5bcae85e 503enum class LLVMRustFileType {
32a655c1
SL
504 Other,
505 AssemblyFile,
506 ObjectFile,
5bcae85e
SL
507};
508
32a655c1
SL
509static TargetMachine::CodeGenFileType fromRust(LLVMRustFileType Type) {
510 switch (Type) {
511 case LLVMRustFileType::AssemblyFile:
512 return TargetMachine::CGFT_AssemblyFile;
513 case LLVMRustFileType::ObjectFile:
514 return TargetMachine::CGFT_ObjectFile;
515 default:
ff7c6d11 516 report_fatal_error("Bad FileType.");
5bcae85e
SL
517 }
518}
519
520extern "C" LLVMRustResult
32a655c1
SL
521LLVMRustWriteOutputFile(LLVMTargetMachineRef Target, LLVMPassManagerRef PMR,
522 LLVMModuleRef M, const char *Path,
523 LLVMRustFileType RustFileType) {
5bcae85e 524 llvm::legacy::PassManager *PM = unwrap<llvm::legacy::PassManager>(PMR);
32a655c1 525 auto FileType = fromRust(RustFileType);
1a4d82fc
JJ
526
527 std::string ErrorInfo;
1a4d82fc 528 std::error_code EC;
32a655c1 529 raw_fd_ostream OS(Path, EC, sys::fs::F_None);
1a4d82fc
JJ
530 if (EC)
531 ErrorInfo = EC.message();
1a4d82fc
JJ
532 if (ErrorInfo != "") {
533 LLVMRustSetLastError(ErrorInfo.c_str());
5bcae85e 534 return LLVMRustResult::Failure;
1a4d82fc 535 }
1a4d82fc 536
8faf50e0 537#if LLVM_VERSION_GE(7, 0)
b7449926
XL
538 buffer_ostream BOS(OS);
539 unwrap(Target)->addPassesToEmitFile(*PM, BOS, nullptr, FileType, false);
8faf50e0 540#else
62682a34 541 unwrap(Target)->addPassesToEmitFile(*PM, OS, FileType, false);
8faf50e0 542#endif
1a4d82fc 543 PM->run(*unwrap(M));
62682a34 544
b039eaaf 545 // Apparently `addPassesToEmitFile` adds a pointer to our on-the-stack output
62682a34
SL
546 // stream (OS), so the only real safe place to delete this is here? Don't we
547 // wish this was written in Rust?
548 delete PM;
5bcae85e 549 return LLVMRustResult::Success;
1a4d82fc
JJ
550}
551
041b39d2
XL
552
553// Callback to demangle function name
554// Parameters:
555// * name to be demangled
556// * name len
557// * output buffer
558// * output buffer len
559// Returns len of demangled string, or 0 if demangle failed.
560typedef size_t (*DemangleFn)(const char*, size_t, char*, size_t);
561
562
563namespace {
564
565class RustAssemblyAnnotationWriter : public AssemblyAnnotationWriter {
566 DemangleFn Demangle;
567 std::vector<char> Buf;
568
569public:
570 RustAssemblyAnnotationWriter(DemangleFn Demangle) : Demangle(Demangle) {}
571
572 // Return empty string if demangle failed
573 // or if name does not need to be demangled
574 StringRef CallDemangle(StringRef name) {
575 if (!Demangle) {
576 return StringRef();
577 }
578
579 if (Buf.size() < name.size() * 2) {
580 // Semangled name usually shorter than mangled,
581 // but allocate twice as much memory just in case
582 Buf.resize(name.size() * 2);
583 }
584
585 auto R = Demangle(name.data(), name.size(), Buf.data(), Buf.size());
586 if (!R) {
587 // Demangle failed.
588 return StringRef();
589 }
590
591 auto Demangled = StringRef(Buf.data(), R);
592 if (Demangled == name) {
593 // Do not print anything if demangled name is equal to mangled.
594 return StringRef();
595 }
596
597 return Demangled;
598 }
599
600 void emitFunctionAnnot(const Function *F,
601 formatted_raw_ostream &OS) override {
602 StringRef Demangled = CallDemangle(F->getName());
603 if (Demangled.empty()) {
604 return;
605 }
606
607 OS << "; " << Demangled << "\n";
608 }
609
610 void emitInstructionAnnot(const Instruction *I,
611 formatted_raw_ostream &OS) override {
612 const char *Name;
613 const Value *Value;
614 if (const CallInst *CI = dyn_cast<CallInst>(I)) {
615 Name = "call";
616 Value = CI->getCalledValue();
617 } else if (const InvokeInst* II = dyn_cast<InvokeInst>(I)) {
618 Name = "invoke";
619 Value = II->getCalledValue();
620 } else {
621 // Could demangle more operations, e. g.
622 // `store %place, @function`.
623 return;
624 }
625
626 if (!Value->hasName()) {
627 return;
628 }
629
630 StringRef Demangled = CallDemangle(Value->getName());
631 if (Demangled.empty()) {
632 return;
633 }
634
635 OS << "; " << Name << " " << Demangled << "\n";
636 }
637};
638
639class RustPrintModulePass : public ModulePass {
640 raw_ostream* OS;
641 DemangleFn Demangle;
642public:
643 static char ID;
644 RustPrintModulePass() : ModulePass(ID), OS(nullptr), Demangle(nullptr) {}
645 RustPrintModulePass(raw_ostream &OS, DemangleFn Demangle)
646 : ModulePass(ID), OS(&OS), Demangle(Demangle) {}
647
648 bool runOnModule(Module &M) override {
649 RustAssemblyAnnotationWriter AW(Demangle);
650
651 M.print(*OS, &AW, false);
652
653 return false;
654 }
655
656 void getAnalysisUsage(AnalysisUsage &AU) const override {
657 AU.setPreservesAll();
658 }
659
660 static StringRef name() { return "RustPrintModulePass"; }
661};
662
663} // namespace
664
665namespace llvm {
666 void initializeRustPrintModulePassPass(PassRegistry&);
667}
668
669char RustPrintModulePass::ID = 0;
670INITIALIZE_PASS(RustPrintModulePass, "print-rust-module",
671 "Print rust module to stderr", false, false)
672
32a655c1 673extern "C" void LLVMRustPrintModule(LLVMPassManagerRef PMR, LLVMModuleRef M,
041b39d2 674 const char *Path, DemangleFn Demangle) {
5bcae85e 675 llvm::legacy::PassManager *PM = unwrap<llvm::legacy::PassManager>(PMR);
1a4d82fc
JJ
676 std::string ErrorInfo;
677
1a4d82fc 678 std::error_code EC;
32a655c1 679 raw_fd_ostream OS(Path, EC, sys::fs::F_None);
1a4d82fc
JJ
680 if (EC)
681 ErrorInfo = EC.message();
1a4d82fc
JJ
682
683 formatted_raw_ostream FOS(OS);
684
041b39d2 685 PM->add(new RustPrintModulePass(FOS, Demangle));
1a4d82fc
JJ
686
687 PM->run(*unwrap(M));
688}
689
32a655c1
SL
690extern "C" void LLVMRustPrintPasses() {
691 LLVMInitializePasses();
692 struct MyListener : PassRegistrationListener {
693 void passEnumerate(const PassInfo *Info) {
32a655c1
SL
694 StringRef PassArg = Info->getPassArgument();
695 StringRef PassName = Info->getPassName();
696 if (!PassArg.empty()) {
697 // These unsigned->signed casts could theoretically overflow, but
698 // realistically never will (and even if, the result is implementation
699 // defined rather plain UB).
700 printf("%15.*s - %.*s\n", (int)PassArg.size(), PassArg.data(),
701 (int)PassName.size(), PassName.data());
702 }
32a655c1
SL
703 }
704 } Listener;
1a4d82fc 705
32a655c1
SL
706 PassRegistry *PR = PassRegistry::getPassRegistry();
707 PR->enumerateWith(&Listener);
970d7e83
LB
708}
709
32a655c1
SL
710extern "C" void LLVMRustAddAlwaysInlinePass(LLVMPassManagerBuilderRef PMBR,
711 bool AddLifetimes) {
32a655c1 712 unwrap(PMBR)->Inliner = llvm::createAlwaysInlinerLegacyPass(AddLifetimes);
1a4d82fc
JJ
713}
714
32a655c1
SL
715extern "C" void LLVMRustRunRestrictionPass(LLVMModuleRef M, char **Symbols,
716 size_t Len) {
717 llvm::legacy::PassManager passes;
5bcae85e 718
32a655c1
SL
719 auto PreserveFunctions = [=](const GlobalValue &GV) {
720 for (size_t I = 0; I < Len; I++) {
721 if (GV.getName() == Symbols[I]) {
722 return true;
723 }
724 }
725 return false;
726 };
5bcae85e 727
32a655c1 728 passes.add(llvm::createInternalizePass(PreserveFunctions));
5bcae85e 729
32a655c1 730 passes.run(*unwrap(M));
1a4d82fc
JJ
731}
732
32a655c1
SL
733extern "C" void LLVMRustMarkAllFunctionsNounwind(LLVMModuleRef M) {
734 for (Module::iterator GV = unwrap(M)->begin(), E = unwrap(M)->end(); GV != E;
735 ++GV) {
736 GV->setDoesNotThrow();
737 Function *F = dyn_cast<Function>(GV);
738 if (F == nullptr)
739 continue;
740
741 for (Function::iterator B = F->begin(), BE = F->end(); B != BE; ++B) {
742 for (BasicBlock::iterator I = B->begin(), IE = B->end(); I != IE; ++I) {
743 if (isa<InvokeInst>(I)) {
744 InvokeInst *CI = cast<InvokeInst>(I);
745 CI->setDoesNotThrow();
1a4d82fc 746 }
32a655c1 747 }
1a4d82fc 748 }
32a655c1 749 }
970d7e83 750}
c1a9b12d
SL
751
752extern "C" void
753LLVMRustSetDataLayoutFromTargetMachine(LLVMModuleRef Module,
754 LLVMTargetMachineRef TMR) {
32a655c1
SL
755 TargetMachine *Target = unwrap(TMR);
756 unwrap(Module)->setDataLayout(Target->createDataLayout());
c1a9b12d
SL
757}
758
32a655c1 759extern "C" void LLVMRustSetModulePIELevel(LLVMModuleRef M) {
32a655c1 760 unwrap(M)->setPIELevel(PIELevel::Level::Large);
5bcae85e 761}
ea8adc8c 762
ea8adc8c
XL
763// Here you'll find an implementation of ThinLTO as used by the Rust compiler
764// right now. This ThinLTO support is only enabled on "recent ish" versions of
765// LLVM, and otherwise it's just blanket rejected from other compilers.
766//
767// Most of this implementation is straight copied from LLVM. At the time of
768// this writing it wasn't *quite* suitable to reuse more code from upstream
769// for our purposes, but we should strive to upstream this support once it's
770// ready to go! I figure we may want a bit of testing locally first before
771// sending this upstream to LLVM. I hear though they're quite eager to receive
772// feedback like this!
773//
774// If you're reading this code and wondering "what in the world" or you're
775// working "good lord by LLVM upgrade is *still* failing due to these bindings"
776// then fear not! (ok maybe fear a little). All code here is mostly based
777// on `lib/LTO/ThinLTOCodeGenerator.cpp` in LLVM.
778//
779// You'll find that the general layout here roughly corresponds to the `run`
780// method in that file as well as `ProcessThinLTOModule`. Functions are
781// specifically commented below as well, but if you're updating this code
782// or otherwise trying to understand it, the LLVM source will be useful in
783// interpreting the mysteries within.
784//
785// Otherwise I'll apologize in advance, it probably requires a relatively
786// significant investment on your part to "truly understand" what's going on
787// here. Not saying I do myself, but it took me awhile staring at LLVM's source
788// and various online resources about ThinLTO to make heads or tails of all
789// this.
790
ea8adc8c
XL
791// This is a shared data structure which *must* be threadsafe to share
792// read-only amongst threads. This also corresponds basically to the arguments
793// of the `ProcessThinLTOModule` function in the LLVM source.
794struct LLVMRustThinLTOData {
795 // The combined index that is the global analysis over all modules we're
796 // performing ThinLTO for. This is mostly managed by LLVM.
797 ModuleSummaryIndex Index;
798
799 // All modules we may look at, stored as in-memory serialized versions. This
800 // is later used when inlining to ensure we can extract any module to inline
801 // from.
802 StringMap<MemoryBufferRef> ModuleMap;
803
804 // A set that we manage of everything we *don't* want internalized. Note that
805 // this includes all transitive references right now as well, but it may not
806 // always!
807 DenseSet<GlobalValue::GUID> GUIDPreservedSymbols;
808
809 // Not 100% sure what these are, but they impact what's internalized and
810 // what's inlined across modules, I believe.
811 StringMap<FunctionImporter::ImportMapTy> ImportLists;
812 StringMap<FunctionImporter::ExportSetTy> ExportLists;
813 StringMap<GVSummaryMapTy> ModuleToDefinedGVSummaries;
2c00a5a8
XL
814
815#if LLVM_VERSION_GE(7, 0)
816 LLVMRustThinLTOData() : Index(/* isPerformingAnalysis = */ false) {}
817#endif
ea8adc8c
XL
818};
819
820// Just an argument to the `LLVMRustCreateThinLTOData` function below.
821struct LLVMRustThinLTOModule {
822 const char *identifier;
823 const char *data;
824 size_t len;
825};
826
827// This is copied from `lib/LTO/ThinLTOCodeGenerator.cpp`, not sure what it
828// does.
829static const GlobalValueSummary *
830getFirstDefinitionForLinker(const GlobalValueSummaryList &GVSummaryList) {
831 auto StrongDefForLinker = llvm::find_if(
832 GVSummaryList, [](const std::unique_ptr<GlobalValueSummary> &Summary) {
833 auto Linkage = Summary->linkage();
834 return !GlobalValue::isAvailableExternallyLinkage(Linkage) &&
835 !GlobalValue::isWeakForLinker(Linkage);
836 });
837 if (StrongDefForLinker != GVSummaryList.end())
838 return StrongDefForLinker->get();
839
840 auto FirstDefForLinker = llvm::find_if(
841 GVSummaryList, [](const std::unique_ptr<GlobalValueSummary> &Summary) {
842 auto Linkage = Summary->linkage();
843 return !GlobalValue::isAvailableExternallyLinkage(Linkage);
844 });
845 if (FirstDefForLinker == GVSummaryList.end())
846 return nullptr;
847 return FirstDefForLinker->get();
848}
849
ea8adc8c
XL
850// The main entry point for creating the global ThinLTO analysis. The structure
851// here is basically the same as before threads are spawned in the `run`
852// function of `lib/LTO/ThinLTOCodeGenerator.cpp`.
853extern "C" LLVMRustThinLTOData*
854LLVMRustCreateThinLTOData(LLVMRustThinLTOModule *modules,
855 int num_modules,
856 const char **preserved_symbols,
857 int num_symbols) {
858 auto Ret = llvm::make_unique<LLVMRustThinLTOData>();
859
860 // Load each module's summary and merge it into one combined index
861 for (int i = 0; i < num_modules; i++) {
862 auto module = &modules[i];
863 StringRef buffer(module->data, module->len);
864 MemoryBufferRef mem_buffer(buffer, module->identifier);
865
866 Ret->ModuleMap[module->identifier] = mem_buffer;
867
abe05a73
XL
868 if (Error Err = readModuleSummaryIndex(mem_buffer, Ret->Index, i)) {
869 LLVMRustSetLastError(toString(std::move(Err)).c_str());
870 return nullptr;
871 }
ea8adc8c
XL
872 }
873
874 // Collect for each module the list of function it defines (GUID -> Summary)
875 Ret->Index.collectDefinedGVSummariesPerModule(Ret->ModuleToDefinedGVSummaries);
876
877 // Convert the preserved symbols set from string to GUID, this is then needed
ff7c6d11 878 // for internalization.
ea8adc8c 879 for (int i = 0; i < num_symbols; i++) {
ff7c6d11
XL
880 auto GUID = GlobalValue::getGUID(preserved_symbols[i]);
881 Ret->GUIDPreservedSymbols.insert(GUID);
ea8adc8c
XL
882 }
883
884 // Collect the import/export lists for all modules from the call-graph in the
885 // combined index
886 //
887 // This is copied from `lib/LTO/ThinLTOCodeGenerator.cpp`
2c00a5a8
XL
888#if LLVM_VERSION_GE(7, 0)
889 auto deadIsPrevailing = [&](GlobalValue::GUID G) {
890 return PrevailingType::Unknown;
891 };
892 computeDeadSymbols(Ret->Index, Ret->GUIDPreservedSymbols, deadIsPrevailing);
893#else
ea8adc8c 894 computeDeadSymbols(Ret->Index, Ret->GUIDPreservedSymbols);
2c00a5a8 895#endif
ea8adc8c
XL
896 ComputeCrossModuleImport(
897 Ret->Index,
898 Ret->ModuleToDefinedGVSummaries,
899 Ret->ImportLists,
900 Ret->ExportLists
901 );
902
903 // Resolve LinkOnce/Weak symbols, this has to be computed early be cause it
904 // impacts the caching.
905 //
ff7c6d11
XL
906 // This is copied from `lib/LTO/ThinLTOCodeGenerator.cpp` with some of this
907 // being lifted from `lib/LTO/LTO.cpp` as well
ea8adc8c
XL
908 StringMap<std::map<GlobalValue::GUID, GlobalValue::LinkageTypes>> ResolvedODR;
909 DenseMap<GlobalValue::GUID, const GlobalValueSummary *> PrevailingCopy;
910 for (auto &I : Ret->Index) {
abe05a73
XL
911 if (I.second.SummaryList.size() > 1)
912 PrevailingCopy[I.first] = getFirstDefinitionForLinker(I.second.SummaryList);
ea8adc8c
XL
913 }
914 auto isPrevailing = [&](GlobalValue::GUID GUID, const GlobalValueSummary *S) {
915 const auto &Prevailing = PrevailingCopy.find(GUID);
916 if (Prevailing == PrevailingCopy.end())
917 return true;
918 return Prevailing->second == S;
919 };
920 auto recordNewLinkage = [&](StringRef ModuleIdentifier,
921 GlobalValue::GUID GUID,
922 GlobalValue::LinkageTypes NewLinkage) {
923 ResolvedODR[ModuleIdentifier][GUID] = NewLinkage;
924 };
a1dfa0c6
XL
925#if LLVM_VERSION_GE(8, 0)
926 thinLTOResolvePrevailingInIndex(Ret->Index, isPrevailing, recordNewLinkage);
927#else
ea8adc8c 928 thinLTOResolveWeakForLinkerInIndex(Ret->Index, isPrevailing, recordNewLinkage);
a1dfa0c6 929#endif
ff7c6d11
XL
930
931 // Here we calculate an `ExportedGUIDs` set for use in the `isExported`
932 // callback below. This callback below will dictate the linkage for all
933 // summaries in the index, and we basically just only want to ensure that dead
934 // symbols are internalized. Otherwise everything that's already external
935 // linkage will stay as external, and internal will stay as internal.
936 std::set<GlobalValue::GUID> ExportedGUIDs;
937 for (auto &List : Ret->Index) {
ff7c6d11 938 for (auto &GVS: List.second.SummaryList) {
ff7c6d11
XL
939 if (GlobalValue::isLocalLinkage(GVS->linkage()))
940 continue;
941 auto GUID = GVS->getOriginalName();
ff7c6d11 942 if (GVS->flags().Live)
ff7c6d11
XL
943 ExportedGUIDs.insert(GUID);
944 }
945 }
ea8adc8c
XL
946 auto isExported = [&](StringRef ModuleIdentifier, GlobalValue::GUID GUID) {
947 const auto &ExportList = Ret->ExportLists.find(ModuleIdentifier);
948 return (ExportList != Ret->ExportLists.end() &&
949 ExportList->second.count(GUID)) ||
ff7c6d11 950 ExportedGUIDs.count(GUID);
ea8adc8c
XL
951 };
952 thinLTOInternalizeAndPromoteInIndex(Ret->Index, isExported);
953
954 return Ret.release();
955}
956
957extern "C" void
958LLVMRustFreeThinLTOData(LLVMRustThinLTOData *Data) {
959 delete Data;
960}
961
962// Below are the various passes that happen *per module* when doing ThinLTO.
963//
964// In other words, these are the functions that are all run concurrently
965// with one another, one per module. The passes here correspond to the analysis
966// passes in `lib/LTO/ThinLTOCodeGenerator.cpp`, currently found in the
967// `ProcessThinLTOModule` function. Here they're split up into separate steps
968// so rustc can save off the intermediate bytecode between each step.
969
970extern "C" bool
971LLVMRustPrepareThinLTORename(const LLVMRustThinLTOData *Data, LLVMModuleRef M) {
972 Module &Mod = *unwrap(M);
973 if (renameModuleForThinLTO(Mod, Data->Index)) {
974 LLVMRustSetLastError("renameModuleForThinLTO failed");
975 return false;
976 }
977 return true;
978}
979
980extern "C" bool
981LLVMRustPrepareThinLTOResolveWeak(const LLVMRustThinLTOData *Data, LLVMModuleRef M) {
982 Module &Mod = *unwrap(M);
983 const auto &DefinedGlobals = Data->ModuleToDefinedGVSummaries.lookup(Mod.getModuleIdentifier());
a1dfa0c6
XL
984#if LLVM_VERSION_GE(8, 0)
985 thinLTOResolvePrevailingInModule(Mod, DefinedGlobals);
986#else
ea8adc8c 987 thinLTOResolveWeakForLinkerModule(Mod, DefinedGlobals);
a1dfa0c6 988#endif
ea8adc8c
XL
989 return true;
990}
991
992extern "C" bool
993LLVMRustPrepareThinLTOInternalize(const LLVMRustThinLTOData *Data, LLVMModuleRef M) {
994 Module &Mod = *unwrap(M);
995 const auto &DefinedGlobals = Data->ModuleToDefinedGVSummaries.lookup(Mod.getModuleIdentifier());
996 thinLTOInternalizeModule(Mod, DefinedGlobals);
997 return true;
998}
999
1000extern "C" bool
1001LLVMRustPrepareThinLTOImport(const LLVMRustThinLTOData *Data, LLVMModuleRef M) {
1002 Module &Mod = *unwrap(M);
8faf50e0 1003
ea8adc8c
XL
1004 const auto &ImportList = Data->ImportLists.lookup(Mod.getModuleIdentifier());
1005 auto Loader = [&](StringRef Identifier) {
1006 const auto &Memory = Data->ModuleMap.lookup(Identifier);
1007 auto &Context = Mod.getContext();
8faf50e0
XL
1008 auto MOrErr = getLazyBitcodeModule(Memory, Context, true, true);
1009
1010 if (!MOrErr)
b7449926 1011 return MOrErr;
8faf50e0
XL
1012
1013 // The rest of this closure is a workaround for
1014 // https://bugs.llvm.org/show_bug.cgi?id=38184 where during ThinLTO imports
1015 // we accidentally import wasm custom sections into different modules,
1016 // duplicating them by in the final output artifact.
1017 //
1018 // The issue is worked around here by manually removing the
1019 // `wasm.custom_sections` named metadata node from any imported module. This
1020 // we know isn't used by any optimization pass so there's no need for it to
1021 // be imported.
1022 //
1023 // Note that the metadata is currently lazily loaded, so we materialize it
1024 // here before looking up if there's metadata inside. The `FunctionImporter`
1025 // will immediately materialize metadata anyway after an import, so this
1026 // shouldn't be a perf hit.
1027 if (Error Err = (*MOrErr)->materializeMetadata()) {
1028 Expected<std::unique_ptr<Module>> Ret(std::move(Err));
b7449926 1029 return Ret;
8faf50e0
XL
1030 }
1031
1032 auto *WasmCustomSections = (*MOrErr)->getNamedMetadata("wasm.custom_sections");
1033 if (WasmCustomSections)
1034 WasmCustomSections->eraseFromParent();
1035
b7449926 1036 return MOrErr;
ea8adc8c
XL
1037 };
1038 FunctionImporter Importer(Data->Index, Loader);
1039 Expected<bool> Result = Importer.importFunctions(Mod, ImportList);
1040 if (!Result) {
1041 LLVMRustSetLastError(toString(Result.takeError()).c_str());
1042 return false;
1043 }
1044 return true;
1045}
1046
b7449926
XL
1047extern "C" typedef void (*LLVMRustModuleNameCallback)(void*, // payload
1048 const char*, // importing module name
1049 const char*); // imported module name
1050
1051// Calls `module_name_callback` for each module import done by ThinLTO.
1052// The callback is provided with regular null-terminated C strings.
1053extern "C" void
1054LLVMRustGetThinLTOModuleImports(const LLVMRustThinLTOData *data,
1055 LLVMRustModuleNameCallback module_name_callback,
1056 void* callback_payload) {
1057 for (const auto& importing_module : data->ImportLists) {
1058 const std::string importing_module_id = importing_module.getKey().str();
1059 const auto& imports = importing_module.getValue();
1060 for (const auto& imported_module : imports) {
1061 const std::string imported_module_id = imported_module.getKey().str();
1062 module_name_callback(callback_payload,
1063 importing_module_id.c_str(),
1064 imported_module_id.c_str());
1065 }
1066 }
1067}
1068
ea8adc8c
XL
1069// This struct and various functions are sort of a hack right now, but the
1070// problem is that we've got in-memory LLVM modules after we generate and
1071// optimize all codegen-units for one compilation in rustc. To be compatible
1072// with the LTO support above we need to serialize the modules plus their
1073// ThinLTO summary into memory.
1074//
1075// This structure is basically an owned version of a serialize module, with
1076// a ThinLTO summary attached.
1077struct LLVMRustThinLTOBuffer {
1078 std::string data;
1079};
1080
1081extern "C" LLVMRustThinLTOBuffer*
1082LLVMRustThinLTOBufferCreate(LLVMModuleRef M) {
1083 auto Ret = llvm::make_unique<LLVMRustThinLTOBuffer>();
1084 {
1085 raw_string_ostream OS(Ret->data);
1086 {
1087 legacy::PassManager PM;
1088 PM.add(createWriteThinLTOBitcodePass(OS));
1089 PM.run(*unwrap(M));
1090 }
1091 }
1092 return Ret.release();
1093}
1094
1095extern "C" void
1096LLVMRustThinLTOBufferFree(LLVMRustThinLTOBuffer *Buffer) {
1097 delete Buffer;
1098}
1099
1100extern "C" const void*
1101LLVMRustThinLTOBufferPtr(const LLVMRustThinLTOBuffer *Buffer) {
1102 return Buffer->data.data();
1103}
1104
1105extern "C" size_t
1106LLVMRustThinLTOBufferLen(const LLVMRustThinLTOBuffer *Buffer) {
1107 return Buffer->data.length();
1108}
1109
1110// This is what we used to parse upstream bitcode for actual ThinLTO
1111// processing. We'll call this once per module optimized through ThinLTO, and
1112// it'll be called concurrently on many threads.
1113extern "C" LLVMModuleRef
1114LLVMRustParseBitcodeForThinLTO(LLVMContextRef Context,
1115 const char *data,
1116 size_t len,
1117 const char *identifier) {
1118 StringRef Data(data, len);
1119 MemoryBufferRef Buffer(Data, identifier);
1120 unwrap(Context)->enableDebugTypeODRUniquing();
1121 Expected<std::unique_ptr<Module>> SrcOrError =
1122 parseBitcodeFile(Buffer, *unwrap(Context));
1123 if (!SrcOrError) {
1124 LLVMRustSetLastError(toString(SrcOrError.takeError()).c_str());
1125 return nullptr;
1126 }
1127 return wrap(std::move(*SrcOrError).release());
1128}
1129
ff7c6d11
XL
1130// Rewrite all `DICompileUnit` pointers to the `DICompileUnit` specified. See
1131// the comment in `back/lto.rs` for why this exists.
1132extern "C" void
1133LLVMRustThinLTOGetDICompileUnit(LLVMModuleRef Mod,
1134 DICompileUnit **A,
1135 DICompileUnit **B) {
1136 Module *M = unwrap(Mod);
1137 DICompileUnit **Cur = A;
1138 DICompileUnit **Next = B;
1139 for (DICompileUnit *CU : M->debug_compile_units()) {
1140 *Cur = CU;
1141 Cur = Next;
1142 Next = nullptr;
1143 if (Cur == nullptr)
1144 break;
1145 }
1146}
1147
1148// Rewrite all `DICompileUnit` pointers to the `DICompileUnit` specified. See
1149// the comment in `back/lto.rs` for why this exists.
1150extern "C" void
1151LLVMRustThinLTOPatchDICompileUnit(LLVMModuleRef Mod, DICompileUnit *Unit) {
1152 Module *M = unwrap(Mod);
1153
1154 // If the original source module didn't have a `DICompileUnit` then try to
1155 // merge all the existing compile units. If there aren't actually any though
1156 // then there's not much for us to do so return.
1157 if (Unit == nullptr) {
1158 for (DICompileUnit *CU : M->debug_compile_units()) {
1159 Unit = CU;
1160 break;
1161 }
1162 if (Unit == nullptr)
1163 return;
1164 }
1165
1166 // Use LLVM's built-in `DebugInfoFinder` to find a bunch of debuginfo and
1167 // process it recursively. Note that we specifically iterate over instructions
1168 // to ensure we feed everything into it.
1169 DebugInfoFinder Finder;
1170 Finder.processModule(*M);
1171 for (Function &F : M->functions()) {
1172 for (auto &FI : F) {
1173 for (Instruction &BI : FI) {
1174 if (auto Loc = BI.getDebugLoc())
1175 Finder.processLocation(*M, Loc);
1176 if (auto DVI = dyn_cast<DbgValueInst>(&BI))
1177 Finder.processValue(*M, DVI);
1178 if (auto DDI = dyn_cast<DbgDeclareInst>(&BI))
1179 Finder.processDeclare(*M, DDI);
1180 }
1181 }
1182 }
1183
1184 // After we've found all our debuginfo, rewrite all subprograms to point to
1185 // the same `DICompileUnit`.
1186 for (auto &F : Finder.subprograms()) {
1187 F->replaceUnit(Unit);
1188 }
1189
1190 // Erase any other references to other `DICompileUnit` instances, the verifier
1191 // will later ensure that we don't actually have any other stale references to
1192 // worry about.
1193 auto *MD = M->getNamedMetadata("llvm.dbg.cu");
1194 MD->clearOperands();
1195 MD->addOperand(Unit);
1196}