]> git.lizzy.rs Git - rust.git/blob - src/rustllvm/PassWrapper.cpp
rustllvm: use LLVMMetadataRef
[rust.git] / src / rustllvm / PassWrapper.cpp
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
11 #include <stdio.h>
12
13 #include <vector>
14
15 #include "rustllvm.h"
16
17 #include "llvm/Analysis/TargetLibraryInfo.h"
18 #include "llvm/Analysis/TargetTransformInfo.h"
19 #include "llvm/IR/AutoUpgrade.h"
20 #include "llvm/IR/AssemblyAnnotationWriter.h"
21 #include "llvm/Support/CBindingWrapping.h"
22 #include "llvm/Support/FileSystem.h"
23 #include "llvm/Support/Host.h"
24 #include "llvm/Target/TargetMachine.h"
25 #include "llvm/Target/TargetSubtargetInfo.h"
26 #include "llvm/Transforms/IPO/PassManagerBuilder.h"
27
28 #if LLVM_VERSION_GE(4, 0)
29 #include "llvm/Transforms/IPO/AlwaysInliner.h"
30 #endif
31
32 #include "llvm-c/Transforms/PassManagerBuilder.h"
33
34 using namespace llvm;
35 using namespace llvm::legacy;
36
37 extern cl::opt<bool> EnableARMEHABI;
38
39 typedef struct LLVMOpaquePass *LLVMPassRef;
40 typedef struct LLVMOpaqueTargetMachine *LLVMTargetMachineRef;
41
42 DEFINE_STDCXX_CONVERSION_FUNCTIONS(Pass, LLVMPassRef)
43 DEFINE_STDCXX_CONVERSION_FUNCTIONS(TargetMachine, LLVMTargetMachineRef)
44 DEFINE_STDCXX_CONVERSION_FUNCTIONS(PassManagerBuilder,
45                                    LLVMPassManagerBuilderRef)
46
47 extern "C" void LLVMInitializePasses() {
48   PassRegistry &Registry = *PassRegistry::getPassRegistry();
49   initializeCore(Registry);
50   initializeCodeGen(Registry);
51   initializeScalarOpts(Registry);
52   initializeVectorization(Registry);
53   initializeIPO(Registry);
54   initializeAnalysis(Registry);
55 #if LLVM_VERSION_EQ(3, 7)
56   initializeIPA(Registry);
57 #endif
58   initializeTransformUtils(Registry);
59   initializeInstCombine(Registry);
60   initializeInstrumentation(Registry);
61   initializeTarget(Registry);
62 }
63
64 enum class LLVMRustPassKind {
65   Other,
66   Function,
67   Module,
68 };
69
70 static LLVMRustPassKind toRust(PassKind Kind) {
71   switch (Kind) {
72   case PT_Function:
73     return LLVMRustPassKind::Function;
74   case PT_Module:
75     return LLVMRustPassKind::Module;
76   default:
77     return LLVMRustPassKind::Other;
78   }
79 }
80
81 extern "C" LLVMPassRef LLVMRustFindAndCreatePass(const char *PassName) {
82   StringRef SR(PassName);
83   PassRegistry *PR = PassRegistry::getPassRegistry();
84
85   const PassInfo *PI = PR->getPassInfo(SR);
86   if (PI) {
87     return wrap(PI->createPass());
88   }
89   return nullptr;
90 }
91
92 extern "C" LLVMRustPassKind LLVMRustPassKind(LLVMPassRef RustPass) {
93   assert(RustPass);
94   Pass *Pass = unwrap(RustPass);
95   return toRust(Pass->getPassKind());
96 }
97
98 extern "C" void LLVMRustAddPass(LLVMPassManagerRef PMR, LLVMPassRef RustPass) {
99   assert(RustPass);
100   Pass *Pass = unwrap(RustPass);
101   PassManagerBase *PMB = unwrap(PMR);
102   PMB->add(Pass);
103 }
104
105 #ifdef LLVM_COMPONENT_X86
106 #define SUBTARGET_X86 SUBTARGET(X86)
107 #else
108 #define SUBTARGET_X86
109 #endif
110
111 #ifdef LLVM_COMPONENT_ARM
112 #define SUBTARGET_ARM SUBTARGET(ARM)
113 #else
114 #define SUBTARGET_ARM
115 #endif
116
117 #ifdef LLVM_COMPONENT_AARCH64
118 #define SUBTARGET_AARCH64 SUBTARGET(AArch64)
119 #else
120 #define SUBTARGET_AARCH64
121 #endif
122
123 #ifdef LLVM_COMPONENT_MIPS
124 #define SUBTARGET_MIPS SUBTARGET(Mips)
125 #else
126 #define SUBTARGET_MIPS
127 #endif
128
129 #ifdef LLVM_COMPONENT_POWERPC
130 #define SUBTARGET_PPC SUBTARGET(PPC)
131 #else
132 #define SUBTARGET_PPC
133 #endif
134
135 #ifdef LLVM_COMPONENT_SYSTEMZ
136 #define SUBTARGET_SYSTEMZ SUBTARGET(SystemZ)
137 #else
138 #define SUBTARGET_SYSTEMZ
139 #endif
140
141 #ifdef LLVM_COMPONENT_MSP430
142 #define SUBTARGET_MSP430 SUBTARGET(MSP430)
143 #else
144 #define SUBTARGET_MSP430
145 #endif
146
147 #ifdef LLVM_COMPONENT_SPARC
148 #define SUBTARGET_SPARC SUBTARGET(Sparc)
149 #else
150 #define SUBTARGET_SPARC
151 #endif
152
153 #ifdef LLVM_COMPONENT_HEXAGON
154 #define SUBTARGET_HEXAGON SUBTARGET(Hexagon)
155 #else
156 #define SUBTARGET_HEXAGON
157 #endif
158
159 #define GEN_SUBTARGETS                                                         \
160   SUBTARGET_X86                                                                \
161   SUBTARGET_ARM                                                                \
162   SUBTARGET_AARCH64                                                            \
163   SUBTARGET_MIPS                                                               \
164   SUBTARGET_PPC                                                                \
165   SUBTARGET_SYSTEMZ                                                            \
166   SUBTARGET_MSP430                                                             \
167   SUBTARGET_SPARC                                                              \
168   SUBTARGET_HEXAGON
169
170 #define SUBTARGET(x)                                                           \
171   namespace llvm {                                                             \
172   extern const SubtargetFeatureKV x##FeatureKV[];                              \
173   extern const SubtargetFeatureKV x##SubTypeKV[];                              \
174   }
175
176 GEN_SUBTARGETS
177 #undef SUBTARGET
178
179 extern "C" bool LLVMRustHasFeature(LLVMTargetMachineRef TM,
180                                    const char *Feature) {
181   TargetMachine *Target = unwrap(TM);
182   const MCSubtargetInfo *MCInfo = Target->getMCSubtargetInfo();
183   const FeatureBitset &Bits = MCInfo->getFeatureBits();
184   const llvm::SubtargetFeatureKV *FeatureEntry;
185
186 #define SUBTARGET(x)                                                           \
187   if (MCInfo->isCPUStringValid(x##SubTypeKV[0].Key)) {                         \
188     FeatureEntry = x##FeatureKV;                                               \
189   } else
190
191   GEN_SUBTARGETS { return false; }
192 #undef SUBTARGET
193
194   while (strcmp(Feature, FeatureEntry->Key) != 0)
195     FeatureEntry++;
196
197   return (Bits & FeatureEntry->Value) == FeatureEntry->Value;
198 }
199
200 enum class LLVMRustCodeModel {
201   Other,
202   Default,
203   JITDefault,
204   Small,
205   Kernel,
206   Medium,
207   Large,
208 };
209
210 static CodeModel::Model fromRust(LLVMRustCodeModel Model) {
211   switch (Model) {
212   case LLVMRustCodeModel::Default:
213     return CodeModel::Default;
214   case LLVMRustCodeModel::JITDefault:
215     return CodeModel::JITDefault;
216   case LLVMRustCodeModel::Small:
217     return CodeModel::Small;
218   case LLVMRustCodeModel::Kernel:
219     return CodeModel::Kernel;
220   case LLVMRustCodeModel::Medium:
221     return CodeModel::Medium;
222   case LLVMRustCodeModel::Large:
223     return CodeModel::Large;
224   default:
225     llvm_unreachable("Bad CodeModel.");
226   }
227 }
228
229 enum class LLVMRustCodeGenOptLevel {
230   Other,
231   None,
232   Less,
233   Default,
234   Aggressive,
235 };
236
237 static CodeGenOpt::Level fromRust(LLVMRustCodeGenOptLevel Level) {
238   switch (Level) {
239   case LLVMRustCodeGenOptLevel::None:
240     return CodeGenOpt::None;
241   case LLVMRustCodeGenOptLevel::Less:
242     return CodeGenOpt::Less;
243   case LLVMRustCodeGenOptLevel::Default:
244     return CodeGenOpt::Default;
245   case LLVMRustCodeGenOptLevel::Aggressive:
246     return CodeGenOpt::Aggressive;
247   default:
248     llvm_unreachable("Bad CodeGenOptLevel.");
249   }
250 }
251
252 enum class LLVMRustRelocMode {
253   Default,
254   Static,
255   PIC,
256   DynamicNoPic,
257   ROPI,
258   RWPI,
259   ROPIRWPI,
260 };
261
262 #if LLVM_VERSION_LE(3, 8)
263 static Reloc::Model fromRust(LLVMRustRelocMode RustReloc) {
264 #else
265 static Optional<Reloc::Model> fromRust(LLVMRustRelocMode RustReloc) {
266 #endif
267   switch (RustReloc) {
268   case LLVMRustRelocMode::Default:
269 #if LLVM_VERSION_LE(3, 8)
270     return Reloc::Default;
271 #else
272     return None;
273 #endif
274   case LLVMRustRelocMode::Static:
275     return Reloc::Static;
276   case LLVMRustRelocMode::PIC:
277     return Reloc::PIC_;
278   case LLVMRustRelocMode::DynamicNoPic:
279     return Reloc::DynamicNoPIC;
280 #if LLVM_VERSION_GE(4, 0)
281   case LLVMRustRelocMode::ROPI:
282     return Reloc::ROPI;
283   case LLVMRustRelocMode::RWPI:
284     return Reloc::RWPI;
285   case LLVMRustRelocMode::ROPIRWPI:
286     return Reloc::ROPI_RWPI;
287 #endif
288   default:
289     llvm_unreachable("Bad RelocModel.");
290   }
291 }
292
293 #if LLVM_RUSTLLVM
294 /// getLongestEntryLength - Return the length of the longest entry in the table.
295 ///
296 static size_t getLongestEntryLength(ArrayRef<SubtargetFeatureKV> Table) {
297   size_t MaxLen = 0;
298   for (auto &I : Table)
299     MaxLen = std::max(MaxLen, std::strlen(I.Key));
300   return MaxLen;
301 }
302
303 extern "C" void LLVMRustPrintTargetCPUs(LLVMTargetMachineRef TM) {
304   const TargetMachine *Target = unwrap(TM);
305   const MCSubtargetInfo *MCInfo = Target->getMCSubtargetInfo();
306   const ArrayRef<SubtargetFeatureKV> CPUTable = MCInfo->getCPUTable();
307   unsigned MaxCPULen = getLongestEntryLength(CPUTable);
308
309   printf("Available CPUs for this target:\n");
310   for (auto &CPU : CPUTable)
311     printf("    %-*s - %s.\n", MaxCPULen, CPU.Key, CPU.Desc);
312   printf("\n");
313 }
314
315 extern "C" void LLVMRustPrintTargetFeatures(LLVMTargetMachineRef TM) {
316   const TargetMachine *Target = unwrap(TM);
317   const MCSubtargetInfo *MCInfo = Target->getMCSubtargetInfo();
318   const ArrayRef<SubtargetFeatureKV> FeatTable = MCInfo->getFeatureTable();
319   unsigned MaxFeatLen = getLongestEntryLength(FeatTable);
320
321   printf("Available features for this target:\n");
322   for (auto &Feature : FeatTable)
323     printf("    %-*s - %s.\n", MaxFeatLen, Feature.Key, Feature.Desc);
324   printf("\n");
325
326   printf("Use +feature to enable a feature, or -feature to disable it.\n"
327          "For example, rustc -C -target-cpu=mycpu -C "
328          "target-feature=+feature1,-feature2\n\n");
329 }
330
331 #else
332
333 extern "C" void LLVMRustPrintTargetCPUs(LLVMTargetMachineRef) {
334   printf("Target CPU help is not supported by this LLVM version.\n\n");
335 }
336
337 extern "C" void LLVMRustPrintTargetFeatures(LLVMTargetMachineRef) {
338   printf("Target features help is not supported by this LLVM version.\n\n");
339 }
340 #endif
341
342 extern "C" LLVMTargetMachineRef LLVMRustCreateTargetMachine(
343     const char *TripleStr, const char *CPU, const char *Feature,
344     LLVMRustCodeModel RustCM, LLVMRustRelocMode RustReloc,
345     LLVMRustCodeGenOptLevel RustOptLevel, bool UseSoftFloat,
346     bool PositionIndependentExecutable, bool FunctionSections,
347     bool DataSections) {
348
349   auto CM = fromRust(RustCM);
350   auto OptLevel = fromRust(RustOptLevel);
351   auto RM = fromRust(RustReloc);
352
353   std::string Error;
354   Triple Trip(Triple::normalize(TripleStr));
355   const llvm::Target *TheTarget =
356       TargetRegistry::lookupTarget(Trip.getTriple(), Error);
357   if (TheTarget == nullptr) {
358     LLVMRustSetLastError(Error.c_str());
359     return nullptr;
360   }
361
362   StringRef RealCPU = CPU;
363   if (RealCPU == "native") {
364     RealCPU = sys::getHostCPUName();
365   }
366
367   TargetOptions Options;
368 #if LLVM_VERSION_LE(3, 8)
369   Options.PositionIndependentExecutable = PositionIndependentExecutable;
370 #endif
371
372   Options.FloatABIType = FloatABI::Default;
373   if (UseSoftFloat) {
374     Options.FloatABIType = FloatABI::Soft;
375   }
376   Options.DataSections = DataSections;
377   Options.FunctionSections = FunctionSections;
378
379   TargetMachine *TM = TheTarget->createTargetMachine(
380       Trip.getTriple(), RealCPU, Feature, Options, RM, CM, OptLevel);
381   return wrap(TM);
382 }
383
384 extern "C" void LLVMRustDisposeTargetMachine(LLVMTargetMachineRef TM) {
385   delete unwrap(TM);
386 }
387
388 // Unfortunately, LLVM doesn't expose a C API to add the corresponding analysis
389 // passes for a target to a pass manager. We export that functionality through
390 // this function.
391 extern "C" void LLVMRustAddAnalysisPasses(LLVMTargetMachineRef TM,
392                                           LLVMPassManagerRef PMR,
393                                           LLVMModuleRef M) {
394   PassManagerBase *PM = unwrap(PMR);
395   PM->add(
396       createTargetTransformInfoWrapperPass(unwrap(TM)->getTargetIRAnalysis()));
397 }
398
399 extern "C" void LLVMRustConfigurePassManagerBuilder(
400     LLVMPassManagerBuilderRef PMBR, LLVMRustCodeGenOptLevel OptLevel,
401     bool MergeFunctions, bool SLPVectorize, bool LoopVectorize) {
402   // Ignore mergefunc for now as enabling it causes crashes.
403   // unwrap(PMBR)->MergeFunctions = MergeFunctions;
404   unwrap(PMBR)->SLPVectorize = SLPVectorize;
405   unwrap(PMBR)->OptLevel = fromRust(OptLevel);
406   unwrap(PMBR)->LoopVectorize = LoopVectorize;
407 }
408
409 // Unfortunately, the LLVM C API doesn't provide a way to set the `LibraryInfo`
410 // field of a PassManagerBuilder, we expose our own method of doing so.
411 extern "C" void LLVMRustAddBuilderLibraryInfo(LLVMPassManagerBuilderRef PMBR,
412                                               LLVMModuleRef M,
413                                               bool DisableSimplifyLibCalls) {
414   Triple TargetTriple(unwrap(M)->getTargetTriple());
415   TargetLibraryInfoImpl *TLI = new TargetLibraryInfoImpl(TargetTriple);
416   if (DisableSimplifyLibCalls)
417     TLI->disableAllFunctions();
418   unwrap(PMBR)->LibraryInfo = TLI;
419 }
420
421 // Unfortunately, the LLVM C API doesn't provide a way to create the
422 // TargetLibraryInfo pass, so we use this method to do so.
423 extern "C" void LLVMRustAddLibraryInfo(LLVMPassManagerRef PMR, LLVMModuleRef M,
424                                        bool DisableSimplifyLibCalls) {
425   Triple TargetTriple(unwrap(M)->getTargetTriple());
426   TargetLibraryInfoImpl TLII(TargetTriple);
427   if (DisableSimplifyLibCalls)
428     TLII.disableAllFunctions();
429   unwrap(PMR)->add(new TargetLibraryInfoWrapperPass(TLII));
430 }
431
432 // Unfortunately, the LLVM C API doesn't provide an easy way of iterating over
433 // all the functions in a module, so we do that manually here. You'll find
434 // similar code in clang's BackendUtil.cpp file.
435 extern "C" void LLVMRustRunFunctionPassManager(LLVMPassManagerRef PMR,
436                                                LLVMModuleRef M) {
437   llvm::legacy::FunctionPassManager *P =
438       unwrap<llvm::legacy::FunctionPassManager>(PMR);
439   P->doInitialization();
440
441   // Upgrade all calls to old intrinsics first.
442   for (Module::iterator I = unwrap(M)->begin(), E = unwrap(M)->end(); I != E;)
443     UpgradeCallsToIntrinsic(&*I++); // must be post-increment, as we remove
444
445   for (Module::iterator I = unwrap(M)->begin(), E = unwrap(M)->end(); I != E;
446        ++I)
447     if (!I->isDeclaration())
448       P->run(*I);
449
450   P->doFinalization();
451 }
452
453 extern "C" void LLVMRustSetLLVMOptions(int Argc, char **Argv) {
454   // Initializing the command-line options more than once is not allowed. So,
455   // check if they've already been initialized.  (This could happen if we're
456   // being called from rustpkg, for example). If the arguments change, then
457   // that's just kinda unfortunate.
458   static bool Initialized = false;
459   if (Initialized)
460     return;
461   Initialized = true;
462   cl::ParseCommandLineOptions(Argc, Argv);
463 }
464
465 enum class LLVMRustFileType {
466   Other,
467   AssemblyFile,
468   ObjectFile,
469 };
470
471 static TargetMachine::CodeGenFileType fromRust(LLVMRustFileType Type) {
472   switch (Type) {
473   case LLVMRustFileType::AssemblyFile:
474     return TargetMachine::CGFT_AssemblyFile;
475   case LLVMRustFileType::ObjectFile:
476     return TargetMachine::CGFT_ObjectFile;
477   default:
478     llvm_unreachable("Bad FileType.");
479   }
480 }
481
482 extern "C" LLVMRustResult
483 LLVMRustWriteOutputFile(LLVMTargetMachineRef Target, LLVMPassManagerRef PMR,
484                         LLVMModuleRef M, const char *Path,
485                         LLVMRustFileType RustFileType) {
486   llvm::legacy::PassManager *PM = unwrap<llvm::legacy::PassManager>(PMR);
487   auto FileType = fromRust(RustFileType);
488
489   std::string ErrorInfo;
490   std::error_code EC;
491   raw_fd_ostream OS(Path, EC, sys::fs::F_None);
492   if (EC)
493     ErrorInfo = EC.message();
494   if (ErrorInfo != "") {
495     LLVMRustSetLastError(ErrorInfo.c_str());
496     return LLVMRustResult::Failure;
497   }
498
499   unwrap(Target)->addPassesToEmitFile(*PM, OS, FileType, false);
500   PM->run(*unwrap(M));
501
502   // Apparently `addPassesToEmitFile` adds a pointer to our on-the-stack output
503   // stream (OS), so the only real safe place to delete this is here? Don't we
504   // wish this was written in Rust?
505   delete PM;
506   return LLVMRustResult::Success;
507 }
508
509
510 // Callback to demangle function name
511 // Parameters:
512 // * name to be demangled
513 // * name len
514 // * output buffer
515 // * output buffer len
516 // Returns len of demangled string, or 0 if demangle failed.
517 typedef size_t (*DemangleFn)(const char*, size_t, char*, size_t);
518
519
520 namespace {
521
522 class RustAssemblyAnnotationWriter : public AssemblyAnnotationWriter {
523   DemangleFn Demangle;
524   std::vector<char> Buf;
525
526 public:
527   RustAssemblyAnnotationWriter(DemangleFn Demangle) : Demangle(Demangle) {}
528
529   // Return empty string if demangle failed
530   // or if name does not need to be demangled
531   StringRef CallDemangle(StringRef name) {
532     if (!Demangle) {
533       return StringRef();
534     }
535
536     if (Buf.size() < name.size() * 2) {
537       // Semangled name usually shorter than mangled,
538       // but allocate twice as much memory just in case
539       Buf.resize(name.size() * 2);
540     }
541
542     auto R = Demangle(name.data(), name.size(), Buf.data(), Buf.size());
543     if (!R) {
544       // Demangle failed.
545       return StringRef();
546     }
547
548     auto Demangled = StringRef(Buf.data(), R);
549     if (Demangled == name) {
550       // Do not print anything if demangled name is equal to mangled.
551       return StringRef();
552     }
553
554     return Demangled;
555   }
556
557   void emitFunctionAnnot(const Function *F,
558                          formatted_raw_ostream &OS) override {
559     StringRef Demangled = CallDemangle(F->getName());
560     if (Demangled.empty()) {
561         return;
562     }
563
564     OS << "; " << Demangled << "\n";
565   }
566
567   void emitInstructionAnnot(const Instruction *I,
568                             formatted_raw_ostream &OS) override {
569     const char *Name;
570     const Value *Value;
571     if (const CallInst *CI = dyn_cast<CallInst>(I)) {
572       Name = "call";
573       Value = CI->getCalledValue();
574     } else if (const InvokeInst* II = dyn_cast<InvokeInst>(I)) {
575       Name = "invoke";
576       Value = II->getCalledValue();
577     } else {
578       // Could demangle more operations, e. g.
579       // `store %place, @function`.
580       return;
581     }
582
583     if (!Value->hasName()) {
584       return;
585     }
586
587     StringRef Demangled = CallDemangle(Value->getName());
588     if (Demangled.empty()) {
589       return;
590     }
591
592     OS << "; " << Name << " " << Demangled << "\n";
593   }
594 };
595
596 class RustPrintModulePass : public ModulePass {
597   raw_ostream* OS;
598   DemangleFn Demangle;
599 public:
600   static char ID;
601   RustPrintModulePass() : ModulePass(ID), OS(nullptr), Demangle(nullptr) {}
602   RustPrintModulePass(raw_ostream &OS, DemangleFn Demangle)
603       : ModulePass(ID), OS(&OS), Demangle(Demangle) {}
604
605   bool runOnModule(Module &M) override {
606     RustAssemblyAnnotationWriter AW(Demangle);
607
608     M.print(*OS, &AW, false);
609
610     return false;
611   }
612
613   void getAnalysisUsage(AnalysisUsage &AU) const override {
614     AU.setPreservesAll();
615   }
616
617   static StringRef name() { return "RustPrintModulePass"; }
618 };
619
620 } // namespace
621
622 namespace llvm {
623   void initializeRustPrintModulePassPass(PassRegistry&);
624 }
625
626 char RustPrintModulePass::ID = 0;
627 INITIALIZE_PASS(RustPrintModulePass, "print-rust-module",
628                 "Print rust module to stderr", false, false)
629
630 extern "C" void LLVMRustPrintModule(LLVMPassManagerRef PMR, LLVMModuleRef M,
631                                     const char *Path, DemangleFn Demangle) {
632   llvm::legacy::PassManager *PM = unwrap<llvm::legacy::PassManager>(PMR);
633   std::string ErrorInfo;
634
635   std::error_code EC;
636   raw_fd_ostream OS(Path, EC, sys::fs::F_None);
637   if (EC)
638     ErrorInfo = EC.message();
639
640   formatted_raw_ostream FOS(OS);
641
642   PM->add(new RustPrintModulePass(FOS, Demangle));
643
644   PM->run(*unwrap(M));
645 }
646
647 extern "C" void LLVMRustPrintPasses() {
648   LLVMInitializePasses();
649   struct MyListener : PassRegistrationListener {
650     void passEnumerate(const PassInfo *Info) {
651 #if LLVM_VERSION_GE(4, 0)
652       StringRef PassArg = Info->getPassArgument();
653       StringRef PassName = Info->getPassName();
654       if (!PassArg.empty()) {
655         // These unsigned->signed casts could theoretically overflow, but
656         // realistically never will (and even if, the result is implementation
657         // defined rather plain UB).
658         printf("%15.*s - %.*s\n", (int)PassArg.size(), PassArg.data(),
659                (int)PassName.size(), PassName.data());
660       }
661 #else
662       if (Info->getPassArgument() && *Info->getPassArgument()) {
663         printf("%15s - %s\n", Info->getPassArgument(), Info->getPassName());
664       }
665 #endif
666     }
667   } Listener;
668
669   PassRegistry *PR = PassRegistry::getPassRegistry();
670   PR->enumerateWith(&Listener);
671 }
672
673 extern "C" void LLVMRustAddAlwaysInlinePass(LLVMPassManagerBuilderRef PMBR,
674                                             bool AddLifetimes) {
675 #if LLVM_VERSION_GE(4, 0)
676   unwrap(PMBR)->Inliner = llvm::createAlwaysInlinerLegacyPass(AddLifetimes);
677 #else
678   unwrap(PMBR)->Inliner = createAlwaysInlinerPass(AddLifetimes);
679 #endif
680 }
681
682 extern "C" void LLVMRustRunRestrictionPass(LLVMModuleRef M, char **Symbols,
683                                            size_t Len) {
684   llvm::legacy::PassManager passes;
685
686 #if LLVM_VERSION_LE(3, 8)
687   ArrayRef<const char *> Ref(Symbols, Len);
688   passes.add(llvm::createInternalizePass(Ref));
689 #else
690   auto PreserveFunctions = [=](const GlobalValue &GV) {
691     for (size_t I = 0; I < Len; I++) {
692       if (GV.getName() == Symbols[I]) {
693         return true;
694       }
695     }
696     return false;
697   };
698
699   passes.add(llvm::createInternalizePass(PreserveFunctions));
700 #endif
701
702   passes.run(*unwrap(M));
703 }
704
705 extern "C" void LLVMRustMarkAllFunctionsNounwind(LLVMModuleRef M) {
706   for (Module::iterator GV = unwrap(M)->begin(), E = unwrap(M)->end(); GV != E;
707        ++GV) {
708     GV->setDoesNotThrow();
709     Function *F = dyn_cast<Function>(GV);
710     if (F == nullptr)
711       continue;
712
713     for (Function::iterator B = F->begin(), BE = F->end(); B != BE; ++B) {
714       for (BasicBlock::iterator I = B->begin(), IE = B->end(); I != IE; ++I) {
715         if (isa<InvokeInst>(I)) {
716           InvokeInst *CI = cast<InvokeInst>(I);
717           CI->setDoesNotThrow();
718         }
719       }
720     }
721   }
722 }
723
724 extern "C" void
725 LLVMRustSetDataLayoutFromTargetMachine(LLVMModuleRef Module,
726                                        LLVMTargetMachineRef TMR) {
727   TargetMachine *Target = unwrap(TMR);
728   unwrap(Module)->setDataLayout(Target->createDataLayout());
729 }
730
731 extern "C" LLVMTargetDataRef LLVMRustGetModuleDataLayout(LLVMModuleRef M) {
732   return wrap(&unwrap(M)->getDataLayout());
733 }
734
735 extern "C" void LLVMRustSetModulePIELevel(LLVMModuleRef M) {
736 #if LLVM_VERSION_GE(3, 9)
737   unwrap(M)->setPIELevel(PIELevel::Level::Large);
738 #endif
739 }