]> git.lizzy.rs Git - rust.git/blob - src/rustllvm/PassWrapper.cpp
auto merge of #13711 : alexcrichton/rust/snapshots, r=brson
[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/Target/TargetLibraryInfo.h"
17 #include "llvm/Transforms/IPO/PassManagerBuilder.h"
18
19 #include "llvm-c/Transforms/PassManagerBuilder.h"
20
21 using namespace llvm;
22
23 extern cl::opt<bool> EnableARMEHABI;
24
25 typedef struct LLVMOpaquePass *LLVMPassRef;
26 typedef struct LLVMOpaqueTargetMachine *LLVMTargetMachineRef;
27
28 DEFINE_STDCXX_CONVERSION_FUNCTIONS(Pass, LLVMPassRef)
29 DEFINE_STDCXX_CONVERSION_FUNCTIONS(TargetMachine, LLVMTargetMachineRef)
30 DEFINE_STDCXX_CONVERSION_FUNCTIONS(PassManagerBuilder, LLVMPassManagerBuilderRef)
31
32 extern "C" void
33 LLVMInitializePasses() {
34   PassRegistry &Registry = *PassRegistry::getPassRegistry();
35   initializeCore(Registry);
36   initializeCodeGen(Registry);
37   initializeScalarOpts(Registry);
38   initializeVectorization(Registry);
39   initializeIPO(Registry);
40   initializeAnalysis(Registry);
41   initializeIPA(Registry);
42   initializeTransformUtils(Registry);
43   initializeInstCombine(Registry);
44   initializeInstrumentation(Registry);
45   initializeTarget(Registry);
46 }
47
48 extern "C" bool
49 LLVMRustAddPass(LLVMPassManagerRef PM, const char *PassName) {
50     PassManagerBase *pm = unwrap(PM);
51
52     StringRef SR(PassName);
53     PassRegistry *PR = PassRegistry::getPassRegistry();
54
55     const PassInfo *PI = PR->getPassInfo(SR);
56     if (PI) {
57         pm->add(PI->createPass());
58         return true;
59     }
60     return false;
61 }
62
63 extern "C" LLVMTargetMachineRef
64 LLVMRustCreateTargetMachine(const char *triple,
65                             const char *cpu,
66                             const char *feature,
67                             CodeModel::Model CM,
68                             Reloc::Model RM,
69                             CodeGenOpt::Level OptLevel,
70                             bool EnableSegmentedStacks,
71                             bool UseSoftFloat,
72                             bool NoFramePointerElim) {
73     std::string Error;
74     Triple Trip(Triple::normalize(triple));
75     const llvm::Target *TheTarget = TargetRegistry::lookupTarget(Trip.getTriple(),
76                                                                  Error);
77     if (TheTarget == NULL) {
78         LLVMRustSetLastError(Error.c_str());
79         return NULL;
80     }
81
82     TargetOptions Options;
83     Options.NoFramePointerElim = NoFramePointerElim;
84 #if LLVM_VERSION_MINOR < 5
85     Options.EnableSegmentedStacks = EnableSegmentedStacks;
86 #endif
87     Options.FloatABIType = FloatABI::Default;
88     Options.UseSoftFloat = UseSoftFloat;
89     if (UseSoftFloat) {
90         Options.FloatABIType = FloatABI::Soft;
91     }
92
93     TargetMachine *TM = TheTarget->createTargetMachine(Trip.getTriple(),
94                                                        cpu,
95                                                        feature,
96                                                        Options,
97                                                        RM,
98                                                        CM,
99                                                        OptLevel);
100     return wrap(TM);
101 }
102
103 extern "C" void
104 LLVMRustDisposeTargetMachine(LLVMTargetMachineRef TM) {
105     delete unwrap(TM);
106 }
107
108 // Unfortunately, LLVM doesn't expose a C API to add the corresponding analysis
109 // passes for a target to a pass manager. We export that functionality through
110 // this function.
111 extern "C" void
112 LLVMRustAddAnalysisPasses(LLVMTargetMachineRef TM,
113                           LLVMPassManagerRef PMR,
114                           LLVMModuleRef M) {
115     PassManagerBase *PM = unwrap(PMR);
116 #if LLVM_VERSION_MINOR >= 5
117     PM->add(new DataLayoutPass(unwrap(M)));
118 #else
119     PM->add(new DataLayout(unwrap(M)));
120 #endif
121     unwrap(TM)->addAnalysisPasses(*PM);
122 }
123
124 // Unfortunately, the LLVM C API doesn't provide a way to set the `LibraryInfo`
125 // field of a PassManagerBuilder, we expose our own method of doing so.
126 extern "C" void
127 LLVMRustAddBuilderLibraryInfo(LLVMPassManagerBuilderRef PMB, LLVMModuleRef M) {
128     Triple TargetTriple(unwrap(M)->getTargetTriple());
129     unwrap(PMB)->LibraryInfo = new TargetLibraryInfo(TargetTriple);
130 }
131
132 // Unfortunately, the LLVM C API doesn't provide a way to create the
133 // TargetLibraryInfo pass, so we use this method to do so.
134 extern "C" void
135 LLVMRustAddLibraryInfo(LLVMPassManagerRef PMB, LLVMModuleRef M) {
136     Triple TargetTriple(unwrap(M)->getTargetTriple());
137     unwrap(PMB)->add(new TargetLibraryInfo(TargetTriple));
138 }
139
140 // Unfortunately, the LLVM C API doesn't provide an easy way of iterating over
141 // all the functions in a module, so we do that manually here. You'll find
142 // similar code in clang's BackendUtil.cpp file.
143 extern "C" void
144 LLVMRustRunFunctionPassManager(LLVMPassManagerRef PM, LLVMModuleRef M) {
145     FunctionPassManager *P = unwrap<FunctionPassManager>(PM);
146     P->doInitialization();
147     for (Module::iterator I = unwrap(M)->begin(),
148          E = unwrap(M)->end(); I != E; ++I)
149         if (!I->isDeclaration())
150             P->run(*I);
151     P->doFinalization();
152 }
153
154 extern "C" void
155 LLVMRustSetLLVMOptions(int Argc, char **Argv) {
156     // Initializing the command-line options more than once is not allowed. So,
157     // check if they've already been initialized.  (This could happen if we're
158     // being called from rustpkg, for example). If the arguments change, then
159     // that's just kinda unfortunate.
160     static bool initialized = false;
161     if (initialized) return;
162     initialized = true;
163     cl::ParseCommandLineOptions(Argc, Argv);
164 }
165
166 extern "C" bool
167 LLVMRustWriteOutputFile(LLVMTargetMachineRef Target,
168                         LLVMPassManagerRef PMR,
169                         LLVMModuleRef M,
170                         const char *path,
171                         TargetMachine::CodeGenFileType FileType) {
172   PassManager *PM = unwrap<PassManager>(PMR);
173
174   std::string ErrorInfo;
175 #if LLVM_VERSION_MINOR >= 4
176   raw_fd_ostream OS(path, ErrorInfo, sys::fs::F_None);
177 #else
178   raw_fd_ostream OS(path, ErrorInfo, raw_fd_ostream::F_Binary);
179 #endif
180   if (ErrorInfo != "") {
181     LLVMRustSetLastError(ErrorInfo.c_str());
182     return false;
183   }
184   formatted_raw_ostream FOS(OS);
185
186   unwrap(Target)->addPassesToEmitFile(*PM, FOS, FileType, false);
187   PM->run(*unwrap(M));
188   return true;
189 }
190
191 extern "C" void
192 LLVMRustPrintModule(LLVMPassManagerRef PMR,
193                     LLVMModuleRef M,
194                     const char* path) {
195   PassManager *PM = unwrap<PassManager>(PMR);
196   std::string ErrorInfo;
197
198 #if LLVM_VERSION_MINOR >= 4
199   raw_fd_ostream OS(path, ErrorInfo, sys::fs::F_None);
200 #else
201   raw_fd_ostream OS(path, ErrorInfo, raw_fd_ostream::F_Binary);
202 #endif
203
204   formatted_raw_ostream FOS(OS);
205
206 #if LLVM_VERSION_MINOR >= 5
207   PM->add(createPrintModulePass(FOS));
208 #else
209   PM->add(createPrintModulePass(&FOS));
210 #endif
211
212   PM->run(*unwrap(M));
213 }
214
215 extern "C" void
216 LLVMRustPrintPasses() {
217     LLVMInitializePasses();
218     struct MyListener : PassRegistrationListener {
219         void passEnumerate(const PassInfo *info) {
220             if (info->getPassArgument() && *info->getPassArgument()) {
221                 printf("%15s - %s\n", info->getPassArgument(),
222                        info->getPassName());
223             }
224         }
225     } listener;
226
227     PassRegistry *PR = PassRegistry::getPassRegistry();
228     PR->enumerateWith(&listener);
229 }
230
231 extern "C" void
232 LLVMRustAddAlwaysInlinePass(LLVMPassManagerBuilderRef PMB, bool AddLifetimes) {
233     unwrap(PMB)->Inliner = createAlwaysInlinerPass(AddLifetimes);
234 }
235
236 extern "C" void
237 LLVMRustRunRestrictionPass(LLVMModuleRef M, char **symbols, size_t len) {
238     PassManager passes;
239     ArrayRef<const char*> ref(symbols, len);
240     passes.add(llvm::createInternalizePass(ref));
241     passes.run(*unwrap(M));
242 }
243
244 extern "C" void
245 LLVMRustMarkAllFunctionsNounwind(LLVMModuleRef M) {
246     for (Module::iterator GV = unwrap(M)->begin(),
247          E = unwrap(M)->end(); GV != E; ++GV) {
248         GV->setDoesNotThrow();
249         Function *F = dyn_cast<Function>(GV);
250         if (F == NULL)
251             continue;
252
253         for (Function::iterator B = F->begin(), BE = F->end(); B != BE; ++B) {
254             for (BasicBlock::iterator I = B->begin(), IE = B->end();
255                  I != IE; ++I) {
256                 if (isa<InvokeInst>(I)) {
257                     InvokeInst *CI = cast<InvokeInst>(I);
258                     CI->setDoesNotThrow();
259                 }
260             }
261         }
262     }
263 }