]> git.proxmox.com Git - rustc.git/blob - src/rustllvm/PassWrapper.cpp
Imported Upstream version 1.3.0+dfsg1
[rustc.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 #if LLVM_VERSION_MINOR >= 7
19 #include "llvm/Analysis/TargetLibraryInfo.h"
20 #include "llvm/Analysis/TargetTransformInfo.h"
21 #else
22 #include "llvm/Target/TargetLibraryInfo.h"
23 #endif
24 #include "llvm/Target/TargetMachine.h"
25 #include "llvm/Target/TargetSubtargetInfo.h"
26 #include "llvm/Transforms/IPO/PassManagerBuilder.h"
27
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, LLVMPassManagerBuilderRef)
42
43 extern "C" void
44 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 initializeIPA(Registry);
53 initializeTransformUtils(Registry);
54 initializeInstCombine(Registry);
55 initializeInstrumentation(Registry);
56 initializeTarget(Registry);
57 }
58
59 extern "C" bool
60 LLVMRustAddPass(LLVMPassManagerRef PM, const char *PassName) {
61 PassManagerBase *pm = unwrap(PM);
62
63 StringRef SR(PassName);
64 PassRegistry *PR = PassRegistry::getPassRegistry();
65
66 const PassInfo *PI = PR->getPassInfo(SR);
67 if (PI) {
68 pm->add(PI->createPass());
69 return true;
70 }
71 return false;
72 }
73
74 extern "C" LLVMTargetMachineRef
75 LLVMRustCreateTargetMachine(const char *triple,
76 const char *cpu,
77 const char *feature,
78 CodeModel::Model CM,
79 Reloc::Model RM,
80 CodeGenOpt::Level OptLevel,
81 bool EnableSegmentedStacks,
82 bool UseSoftFloat,
83 bool PositionIndependentExecutable,
84 bool FunctionSections,
85 bool DataSections) {
86 std::string Error;
87 Triple Trip(Triple::normalize(triple));
88 const llvm::Target *TheTarget = TargetRegistry::lookupTarget(Trip.getTriple(),
89 Error);
90 if (TheTarget == NULL) {
91 LLVMRustSetLastError(Error.c_str());
92 return NULL;
93 }
94
95 StringRef real_cpu = cpu;
96 if (real_cpu == "native") {
97 real_cpu = sys::getHostCPUName();
98 }
99
100 TargetOptions Options;
101 Options.PositionIndependentExecutable = PositionIndependentExecutable;
102 Options.FloatABIType = FloatABI::Default;
103 if (UseSoftFloat) {
104 Options.FloatABIType = FloatABI::Soft;
105 }
106 Options.DataSections = DataSections;
107 Options.FunctionSections = FunctionSections;
108
109 TargetMachine *TM = TheTarget->createTargetMachine(Trip.getTriple(),
110 real_cpu,
111 feature,
112 Options,
113 RM,
114 CM,
115 OptLevel);
116 return wrap(TM);
117 }
118
119 extern "C" void
120 LLVMRustDisposeTargetMachine(LLVMTargetMachineRef TM) {
121 delete unwrap(TM);
122 }
123
124 // Unfortunately, LLVM doesn't expose a C API to add the corresponding analysis
125 // passes for a target to a pass manager. We export that functionality through
126 // this function.
127 extern "C" void
128 LLVMRustAddAnalysisPasses(LLVMTargetMachineRef TM,
129 LLVMPassManagerRef PMR,
130 LLVMModuleRef M) {
131 PassManagerBase *PM = unwrap(PMR);
132 #if LLVM_VERSION_MINOR >= 7
133 PM->add(createTargetTransformInfoWrapperPass(
134 unwrap(TM)->getTargetIRAnalysis()));
135 #else
136 #if LLVM_VERSION_MINOR == 6
137 PM->add(new DataLayoutPass());
138 #else
139 PM->add(new DataLayoutPass(unwrap(M)));
140 #endif
141 unwrap(TM)->addAnalysisPasses(*PM);
142 #endif
143 }
144
145 extern "C" void
146 LLVMRustConfigurePassManagerBuilder(LLVMPassManagerBuilderRef PMB,
147 CodeGenOpt::Level OptLevel,
148 bool MergeFunctions,
149 bool SLPVectorize,
150 bool LoopVectorize) {
151 #if LLVM_VERSION_MINOR >= 6
152 // Ignore mergefunc for now as enabling it causes crashes.
153 //unwrap(PMB)->MergeFunctions = MergeFunctions;
154 #endif
155 unwrap(PMB)->SLPVectorize = SLPVectorize;
156 unwrap(PMB)->OptLevel = OptLevel;
157 unwrap(PMB)->LoopVectorize = LoopVectorize;
158 }
159
160 // Unfortunately, the LLVM C API doesn't provide a way to set the `LibraryInfo`
161 // field of a PassManagerBuilder, we expose our own method of doing so.
162 extern "C" void
163 LLVMRustAddBuilderLibraryInfo(LLVMPassManagerBuilderRef PMB,
164 LLVMModuleRef M,
165 bool DisableSimplifyLibCalls) {
166 Triple TargetTriple(unwrap(M)->getTargetTriple());
167 #if LLVM_VERSION_MINOR >= 7
168 TargetLibraryInfoImpl *TLI = new TargetLibraryInfoImpl(TargetTriple);
169 #else
170 TargetLibraryInfo *TLI = new TargetLibraryInfo(TargetTriple);
171 #endif
172 if (DisableSimplifyLibCalls)
173 TLI->disableAllFunctions();
174 unwrap(PMB)->LibraryInfo = TLI;
175 }
176
177 // Unfortunately, the LLVM C API doesn't provide a way to create the
178 // TargetLibraryInfo pass, so we use this method to do so.
179 extern "C" void
180 LLVMRustAddLibraryInfo(LLVMPassManagerRef PMB,
181 LLVMModuleRef M,
182 bool DisableSimplifyLibCalls) {
183 Triple TargetTriple(unwrap(M)->getTargetTriple());
184 #if LLVM_VERSION_MINOR >= 7
185 TargetLibraryInfoImpl TLII(TargetTriple);
186 if (DisableSimplifyLibCalls)
187 TLII.disableAllFunctions();
188 unwrap(PMB)->add(new TargetLibraryInfoWrapperPass(TLII));
189 #else
190 TargetLibraryInfo *TLI = new TargetLibraryInfo(TargetTriple);
191 if (DisableSimplifyLibCalls)
192 TLI->disableAllFunctions();
193 unwrap(PMB)->add(TLI);
194 #endif
195 }
196
197 // Unfortunately, the LLVM C API doesn't provide an easy way of iterating over
198 // all the functions in a module, so we do that manually here. You'll find
199 // similar code in clang's BackendUtil.cpp file.
200 extern "C" void
201 LLVMRustRunFunctionPassManager(LLVMPassManagerRef PM, LLVMModuleRef M) {
202 FunctionPassManager *P = unwrap<FunctionPassManager>(PM);
203 P->doInitialization();
204 for (Module::iterator I = unwrap(M)->begin(),
205 E = unwrap(M)->end(); I != E; ++I)
206 if (!I->isDeclaration())
207 P->run(*I);
208 P->doFinalization();
209 }
210
211 extern "C" void
212 LLVMRustSetLLVMOptions(int Argc, char **Argv) {
213 // Initializing the command-line options more than once is not allowed. So,
214 // check if they've already been initialized. (This could happen if we're
215 // being called from rustpkg, for example). If the arguments change, then
216 // that's just kinda unfortunate.
217 static bool initialized = false;
218 if (initialized) return;
219 initialized = true;
220 cl::ParseCommandLineOptions(Argc, Argv);
221 }
222
223 extern "C" bool
224 LLVMRustWriteOutputFile(LLVMTargetMachineRef Target,
225 LLVMPassManagerRef PMR,
226 LLVMModuleRef M,
227 const char *path,
228 TargetMachine::CodeGenFileType FileType) {
229 PassManager *PM = unwrap<PassManager>(PMR);
230
231 std::string ErrorInfo;
232 #if LLVM_VERSION_MINOR >= 6
233 std::error_code EC;
234 raw_fd_ostream OS(path, EC, sys::fs::F_None);
235 if (EC)
236 ErrorInfo = EC.message();
237 #else
238 raw_fd_ostream OS(path, ErrorInfo, sys::fs::F_None);
239 #endif
240 if (ErrorInfo != "") {
241 LLVMRustSetLastError(ErrorInfo.c_str());
242 return false;
243 }
244
245 #if LLVM_VERSION_MINOR >= 7
246 unwrap(Target)->addPassesToEmitFile(*PM, OS, FileType, false);
247 #else
248 formatted_raw_ostream FOS(OS);
249 unwrap(Target)->addPassesToEmitFile(*PM, FOS, FileType, false);
250 #endif
251 PM->run(*unwrap(M));
252
253 // Apparently `addPassesToEmitFile` adds an pointer to our on-the-stack output
254 // stream (OS), so the only real safe place to delete this is here? Don't we
255 // wish this was written in Rust?
256 delete PM;
257 return true;
258 }
259
260 extern "C" void
261 LLVMRustPrintModule(LLVMPassManagerRef PMR,
262 LLVMModuleRef M,
263 const char* path) {
264 PassManager *PM = unwrap<PassManager>(PMR);
265 std::string ErrorInfo;
266
267 #if LLVM_VERSION_MINOR >= 6
268 std::error_code EC;
269 raw_fd_ostream OS(path, EC, sys::fs::F_None);
270 if (EC)
271 ErrorInfo = EC.message();
272 #else
273 raw_fd_ostream OS(path, ErrorInfo, sys::fs::F_None);
274 #endif
275
276 formatted_raw_ostream FOS(OS);
277
278 PM->add(createPrintModulePass(FOS));
279
280 PM->run(*unwrap(M));
281 }
282
283 extern "C" void
284 LLVMRustPrintPasses() {
285 LLVMInitializePasses();
286 struct MyListener : PassRegistrationListener {
287 void passEnumerate(const PassInfo *info) {
288 if (info->getPassArgument() && *info->getPassArgument()) {
289 printf("%15s - %s\n", info->getPassArgument(),
290 info->getPassName());
291 }
292 }
293 } listener;
294
295 PassRegistry *PR = PassRegistry::getPassRegistry();
296 PR->enumerateWith(&listener);
297 }
298
299 extern "C" void
300 LLVMRustAddAlwaysInlinePass(LLVMPassManagerBuilderRef PMB, bool AddLifetimes) {
301 unwrap(PMB)->Inliner = createAlwaysInlinerPass(AddLifetimes);
302 }
303
304 extern "C" void
305 LLVMRustRunRestrictionPass(LLVMModuleRef M, char **symbols, size_t len) {
306 PassManager passes;
307 ArrayRef<const char*> ref(symbols, len);
308 passes.add(llvm::createInternalizePass(ref));
309 passes.run(*unwrap(M));
310 }
311
312 extern "C" void
313 LLVMRustMarkAllFunctionsNounwind(LLVMModuleRef M) {
314 for (Module::iterator GV = unwrap(M)->begin(),
315 E = unwrap(M)->end(); GV != E; ++GV) {
316 GV->setDoesNotThrow();
317 Function *F = dyn_cast<Function>(GV);
318 if (F == NULL)
319 continue;
320
321 for (Function::iterator B = F->begin(), BE = F->end(); B != BE; ++B) {
322 for (BasicBlock::iterator I = B->begin(), IE = B->end();
323 I != IE; ++I) {
324 if (isa<InvokeInst>(I)) {
325 InvokeInst *CI = cast<InvokeInst>(I);
326 CI->setDoesNotThrow();
327 }
328 }
329 }
330 }
331 }
332
333 extern "C" void
334 LLVMRustSetDataLayoutFromTargetMachine(LLVMModuleRef Module,
335 LLVMTargetMachineRef TMR) {
336 TargetMachine *Target = unwrap(TMR);
337 #if LLVM_VERSION_MINOR >= 7
338 if (const DataLayout *DL = Target->getDataLayout())
339 unwrap(Module)->setDataLayout(*DL);
340 #elif LLVM_VERSION_MINOR >= 6
341 if (const DataLayout *DL = Target->getSubtargetImpl()->getDataLayout())
342 unwrap(Module)->setDataLayout(DL);
343 #else
344 if (const DataLayout *DL = Target->getDataLayout())
345 unwrap(Module)->setDataLayout(DL);
346 #endif
347 }
348
349 extern "C" LLVMTargetDataRef
350 LLVMRustGetModuleDataLayout(LLVMModuleRef M) {
351 #if LLVM_VERSION_MINOR >= 7
352 return wrap(&unwrap(M)->getDataLayout());
353 #else
354 return wrap(unwrap(M)->getDataLayout());
355 #endif
356 }