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