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