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