]> git.lizzy.rs Git - rust.git/blob - src/librustc/back/passes.rs
Add ToCStr method .with_c_str()
[rust.git] / src / librustc / back / passes.rs
1 // Copyright 2012-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 use std::c_str::ToCStr;
12 use std::io;
13
14 use driver::session::{OptLevel, No, Less, Aggressive};
15 use driver::session::{Session};
16 use lib::llvm::{PassRef, ModuleRef,PassManagerRef,TargetDataRef};
17 use lib::llvm::llvm;
18 use lib;
19
20 pub struct PassManager {
21     priv llpm: PassManagerRef
22 }
23
24 impl Drop for PassManager {
25     fn drop(&self) {
26         unsafe {
27             llvm::LLVMDisposePassManager(self.llpm);
28         }
29     }
30 }
31
32 impl PassManager {
33     pub fn new(td: TargetDataRef) -> PassManager {
34         unsafe {
35             let pm = PassManager {
36                 llpm: llvm::LLVMCreatePassManager()
37             };
38             llvm::LLVMAddTargetData(td, pm.llpm);
39
40             return pm;
41         }
42     }
43
44     pub fn add_pass(&mut self, pass:PassRef) {
45         unsafe {
46             llvm::LLVMAddPass(self.llpm, pass);
47         }
48     }
49
50     pub fn add_pass_from_name(&mut self, name:&str) {
51         let pass = create_pass(name).unwrap();
52         self.add_pass(pass);
53     }
54
55     pub fn run(&self, md:ModuleRef) -> bool {
56         unsafe {
57             llvm::LLVMRunPassManager(self.llpm, md) == lib::llvm::True
58         }
59     }
60 }
61
62 pub fn create_standard_passes(level: OptLevel) -> ~[~str] {
63     let mut passes = ~[];
64
65     // mostly identical to clang 3.3, all differences are documented with comments
66
67     if level != No {
68         passes.push(~"targetlibinfo");
69         passes.push(~"no-aa");
70         // "tbaa" omitted, we don't emit clang-style type-based alias analysis information
71         passes.push(~"basicaa");
72         passes.push(~"globalopt");
73         passes.push(~"ipsccp");
74         passes.push(~"deadargelim");
75         passes.push(~"instcombine");
76         passes.push(~"simplifycfg");
77     }
78
79     passes.push(~"basiccg");
80
81     if level != No {
82         passes.push(~"prune-eh");
83     }
84
85     passes.push(~"inline-cost");
86
87     if level == No || level == Less {
88         passes.push(~"always-inline");
89     } else {
90         passes.push(~"inline");
91     }
92
93     if level != No {
94         passes.push(~"functionattrs");
95         if level == Aggressive {
96             passes.push(~"argpromotion");
97         }
98         passes.push(~"sroa");
99         passes.push(~"domtree");
100         passes.push(~"early-cse");
101         passes.push(~"lazy-value-info");
102         passes.push(~"jump-threading");
103         passes.push(~"correlated-propagation");
104         passes.push(~"simplifycfg");
105         passes.push(~"instcombine");
106         passes.push(~"tailcallelim");
107         passes.push(~"simplifycfg");
108         passes.push(~"reassociate");
109         passes.push(~"domtree");
110         passes.push(~"loops");
111         passes.push(~"loop-simplify");
112         passes.push(~"lcssa");
113         passes.push(~"loop-rotate");
114         passes.push(~"licm");
115         passes.push(~"lcssa");
116         passes.push(~"loop-unswitch");
117         passes.push(~"instcombine");
118         passes.push(~"scalar-evolution");
119         passes.push(~"loop-simplify");
120         passes.push(~"lcssa");
121         passes.push(~"indvars");
122         passes.push(~"loop-idiom");
123         passes.push(~"loop-deletion");
124         if level == Aggressive {
125             passes.push(~"loop-simplify");
126             passes.push(~"lcssa");
127             passes.push(~"loop-vectorize");
128             passes.push(~"loop-simplify");
129             passes.push(~"lcssa");
130             passes.push(~"scalar-evolution");
131             passes.push(~"loop-simplify");
132             passes.push(~"lcssa");
133         }
134         if level != Less {
135             passes.push(~"loop-unroll");
136             passes.push(~"memdep");
137             passes.push(~"gvn");
138         }
139         passes.push(~"memdep");
140         passes.push(~"memcpyopt");
141         passes.push(~"sccp");
142         passes.push(~"instcombine");
143         passes.push(~"lazy-value-info");
144         passes.push(~"jump-threading");
145         passes.push(~"correlated-propagation");
146         passes.push(~"domtree");
147         passes.push(~"memdep");
148         passes.push(~"dse");
149         passes.push(~"adce");
150         passes.push(~"simplifycfg");
151         passes.push(~"instcombine");
152         // clang does `strip-dead-prototypes` here, since it does not emit them
153     }
154
155     // rustc emits dead prototypes, so always ask LLVM to strip them
156     passes.push(~"strip-dead-prototypes");
157
158     if level != Less {
159         passes.push(~"globaldce");
160         passes.push(~"constmerge");
161     }
162
163     passes
164 }
165
166 pub fn populate_pass_manager(sess: Session, pm: &mut PassManager, pass_list:&[~str]) {
167     for nm in pass_list.iter() {
168         match create_pass(*nm) {
169             Some(p) => pm.add_pass(p),
170             None    => sess.warn(fmt!("Unknown pass %s", *nm))
171         }
172     }
173 }
174
175 pub fn create_pass(name:&str) -> Option<PassRef> {
176     do name.with_c_str |s| {
177         unsafe {
178             let p = llvm::LLVMCreatePass(s);
179             if p.is_null() {
180                 None
181             } else {
182                 Some(p)
183             }
184         }
185     }
186 }
187
188 pub fn list_passes() {
189     io::println("\nAvailable Passes:");
190
191     io::println("\nAnalysis Passes:");
192     for &(name, desc) in analysis_passes.iter() {
193         printfln!("    %-30s -- %s", name, desc);
194     }
195     io::println("\nTransformation Passes:");
196     for &(name, desc) in transform_passes.iter() {
197         printfln!("    %-30s -- %s", name, desc);
198     }
199     io::println("\nUtility Passes:");
200     for &(name, desc) in utility_passes.iter() {
201         printfln!("    %-30s -- %s", name, desc);
202     }
203 }
204
205 /** Analysis Passes */
206 pub static analysis_passes : &'static [(&'static str, &'static str)] = &'static [
207     ("aa-eval",                         "Exhausive Alias Analysis Precision Evaluator"),
208     ("asan",                            "AddressSanitizer"),
209     ("basicaa",                         "Basic Alias Analysis"),
210     ("basiccg",                         "Basic CallGraph Construction"),
211     ("block-freq",                      "Block Frequency Analysis"),
212     ("cost-model",                      "Cost Model Analysis"),
213     ("count-aa",                        "Count Alias Analysis Query Responses"),
214     ("da",                              "Dependence Analysis"),
215     ("debug-aa",                        "AA Use Debugger"),
216     ("domfrontier",                     "Dominance Frontier Construction"),
217     ("domtree",                         "Dominator Tree Construction"),
218     ("globalsmodref-aa",                "Simple mod/ref analysis for globals"),
219     ("instcount",                       "Count the various types of Instructions"),
220     ("intervals",                       "Interval Partition Construction"),
221     ("iv-users",                        "Induction Variable Users"),
222     ("lazy-value-info",                 "Lazy Value Information Analysis"),
223     ("libcall-aa",                      "LibCall Alias Analysis"),
224     ("lint",                            "Statically lint-check LLVM IR"),
225     ("loops",                           "Natural Loop Information"),
226     ("memdep",                          "Memory Dependence Analysis"),
227     ("module-debuginfo",                "Decodes module-level debug info"),
228     ("profile-estimator",               "Estimate profiling information"),
229     ("profile-loader",                  "Load profile information from llvmprof.out"),
230     ("profile-verifier",                "Verify profiling information"),
231     ("regions",                         "Detect single entry single exit regions"),
232     ("scalar-evolution",                "Scalar Evolution Analysis"),
233     ("scev-aa",                         "Scalar Evolution-based Alias Analysis"),
234     ("tbaa",                            "Type-Based Alias Analysis"),
235     ("tsan",                            "ThreadSanitizer"),
236 ];
237
238 /** Transformation Passes */
239 pub static transform_passes : &'static [(&'static str, &'static str)] = &'static [
240     ("adce",                            "Aggressive Dead Code Elimination"),
241     ("always-inline",                   "Inliner for #[inline] functions"),
242     ("argpromotion",                    "Promote 'by reference' arguments to scalars"),
243     ("bb-vectorize",                    "Basic-Block Vectorization"),
244     ("block-placement",                 "Profile Guided Basic Block Placement"),
245     ("bounds-checking",                 "Run-time bounds checking"),
246     ("break-crit-edges",                "Break critical edges in CFG"),
247     ("codegenprepare",                  "Optimize for code generation"),
248     ("constmerge",                      "Merge Duplicate Global Constants"),
249     ("constprop",                       "Simple constant propagation"),
250     ("correlated-propagation",          "Value Propagation"),
251     ("da",                              "Data Layout"),
252     ("dce",                             "Dead Code Elimination"),
253     ("deadargelim",                     "Dead Argument Elimination"),
254     ("die",                             "Dead Instruction Elimination"),
255     ("dse",                             "Dead Store Elimination"),
256     ("early-cse",                       "Early CSE"),
257     ("functionattrs",                   "Deduce function attributes"),
258     ("globaldce",                       "Dead Global Elimination"),
259     ("globalopt",                       "Global Variable Optimizer"),
260     ("gvn",                             "Global Value Numbering"),
261     ("indvars",                         "Canonicalize Induction Variables"),
262     ("inline",                          "Function Integration/Inlining"),
263     ("insert-edge-profiling",           "Insert instrumentation for edge profiling"),
264     ("insert-gcov-profiling",           "Insert instrumentation for GCOV profiling"),
265     ("insert-optimal-edge-profiling",   "Insert optimal instrumentation for edge profiling"),
266     ("instcombine",                     "Combine redundant instructions"),
267     ("instsimplify",                    "Remove redundant instructions"),
268     ("ipconstprop",                     "Interprocedural constant propagation"),
269     ("ipsccp",                          "Interprocedural Sparse Conditional Constant Propagation"),
270     ("jump-threading",                  "Jump Threading"),
271     ("lcssa",                           "Loop-Closed SSA Form Pass"),
272     ("licm",                            "Loop Invariant Code Motion"),
273     ("loop-deletion",                   "Delete dead loops"),
274     ("loop-extract",                    "Extract loops into new functions"),
275     ("loop-extract-single",             "Extract at most one loop into a new function"),
276     ("loop-idiom",                      "Recognise loop idioms"),
277     ("loop-instsimplify",               "Simplify instructions in loops"),
278     ("loop-reduce",                     "Loop Strength Reduction"),
279     ("loop-rotate",                     "Rotate Loops"),
280     ("loop-simplify",                   "Canonicalize natural loops"),
281     ("loop-unroll",                     "Unroll loops"),
282     ("loop-unswitch",                   "Unswitch loops"),
283     ("loop-vectorize",                  "Loop Vectorization"),
284     ("lower-expect",                    "Lower 'expect' Intrinsics"),
285     ("mem2reg",                         "Promote Memory to Register"),
286     ("memcpyopt",                       "MemCpy Optimization"),
287     ("mergefunc",                       "Merge Functions"),
288     ("mergereturn",                     "Unify function exit nodes"),
289     ("partial-inliner",                 "Partial Inliner"),
290     ("prune-eh",                        "Remove unused exception handling info"),
291     ("reassociate",                     "Reassociate expressions"),
292     ("reg2mem",                         "Demote all values to stack slots"),
293     ("scalarrepl",                      "Scalar Replacement of Aggregates (DT)"),
294     ("scalarrepl-ssa",                  "Scalar Replacement of Aggregates (SSAUp)"),
295     ("sccp",                            "Sparse Conditional Constant Propagation"),
296     ("simplify-libcalls",               "Simplify well-known library calls"),
297     ("simplifycfg",                     "Simplify the CFG"),
298     ("sink",                            "Code sinking"),
299     ("strip",                           "Strip all symbols from a module"),
300     ("strip-dead-debug-info",           "Strip debug info for unused symbols"),
301     ("strip-dead-prototypes",           "Strip Unused Function Prototypes"),
302     ("strip-debug-declare",             "Strip all llvm.dbg.declare intrinsics"),
303     ("strip-nondebug",                  "Strip all symbols, except dbg symbols, from a module"),
304     ("sroa",                            "Scalar Replacement of Aggregates"),
305     ("tailcallelim",                    "Tail Call Elimination"),
306 ];
307
308 /** Utility Passes */
309 static utility_passes : &'static [(&'static str, &'static str)] = &'static [
310     ("instnamer",                       "Assign names to anonymous instructions"),
311     ("verify",                          "Module Verifier"),
312 ];
313
314 #[test]
315 fn passes_exist() {
316     let mut failed = ~[];
317     unsafe { llvm::LLVMInitializePasses(); }
318     for &(name,_) in analysis_passes.iter() {
319         let pass = create_pass(name);
320         if !pass.is_some() {
321             failed.push(name);
322         } else {
323             unsafe { llvm::LLVMDestroyPass(pass.unwrap()) }
324         }
325     }
326     for &(name,_) in transform_passes.iter() {
327         let pass = create_pass(name);
328         if !pass.is_some() {
329             failed.push(name);
330         } else {
331             unsafe { llvm::LLVMDestroyPass(pass.unwrap()) }
332         }
333     }
334     for &(name,_) in utility_passes.iter() {
335         let pass = create_pass(name);
336         if !pass.is_some() {
337             failed.push(name);
338         } else {
339             unsafe { llvm::LLVMDestroyPass(pass.unwrap()) }
340         }
341     }
342
343     if failed.len() > 0 {
344         io::println("Some passes don't exist:");
345         for &n in failed.iter() {
346             printfln!("    %s", n);
347         }
348         fail!();
349     }
350 }