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