about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/librustc/back/link.rs70
-rw-r--r--src/librustc/back/passes.rs154
-rw-r--r--src/librustc/driver/session.rs5
-rw-r--r--src/librustc/lib/llvm.rs221
-rw-r--r--src/librustc/rustc.rc1
-rw-r--r--src/rustllvm/PassWrapper.cpp160
-rw-r--r--src/rustllvm/RustWrapper.cpp48
-rw-r--r--src/rustllvm/rustllvm.def.in99
-rw-r--r--src/rustllvm/rustllvm.h57
9 files changed, 717 insertions, 98 deletions
diff --git a/src/librustc/back/link.rs b/src/librustc/back/link.rs
index b7e33d7c68d..51d60437868 100644
--- a/src/librustc/back/link.rs
+++ b/src/librustc/back/link.rs
@@ -180,9 +180,11 @@ pub mod write {
     use driver::session::Session;
     use driver::session;
     use lib::llvm::llvm;
-    use lib::llvm::{False, ModuleRef, mk_pass_manager, mk_target_data};
+    use lib::llvm::{ModuleRef, mk_pass_manager, mk_target_data};
     use lib;
 
+    use back::passes;
+
     use core::libc::{c_int, c_uint};
     use core::path::Path;
     use core::run;
@@ -202,16 +204,12 @@ pub mod write {
         unsafe {
             let opts = sess.opts;
             if sess.time_llvm_passes() { llvm::LLVMRustEnableTimePasses(); }
-            let mut pm = mk_pass_manager();
             let td = mk_target_data(sess.targ_cfg.target_strs.data_layout);
+            let pm = mk_pass_manager();
             llvm::LLVMAddTargetData(td.lltd, pm.llpm);
-            // FIXME (#2812): run the linter here also, once there are llvm-c
-            // bindings for it.
 
             // Generate a pre-optimization intermediate file if -save-temps
             // was specified.
-
-
             if opts.save_temps {
                 match output_type {
                   output_type_bitcode => {
@@ -230,50 +228,22 @@ pub mod write {
                   }
                 }
             }
-            if !sess.no_verify() { llvm::LLVMAddVerifierPass(pm.llpm); }
-            // FIXME (#2396): This is mostly a copy of the bits of opt's -O2
-            // that are available in the C api.
-            // Also: We might want to add optimization levels like -O1, -O2,
-            // -Os, etc
-            // Also: Should we expose and use the pass lists used by the opt
-            // tool?
-
-            if opts.optimize != session::No {
-                let fpm = mk_pass_manager();
-                llvm::LLVMAddTargetData(td.lltd, fpm.llpm);
-
-                let FPMB = llvm::LLVMPassManagerBuilderCreate();
-                llvm::LLVMPassManagerBuilderSetOptLevel(FPMB, 2u as c_uint);
-                llvm::LLVMPassManagerBuilderPopulateFunctionPassManager(
-                    FPMB, fpm.llpm);
-                llvm::LLVMPassManagerBuilderDispose(FPMB);
-
-                llvm::LLVMRunPassManager(fpm.llpm, llmod);
-                let mut threshold = 225;
-                if opts.optimize == session::Aggressive { threshold = 275; }
-
-                let MPMB = llvm::LLVMPassManagerBuilderCreate();
-                llvm::LLVMPassManagerBuilderSetOptLevel(MPMB,
-                                                        opts.optimize as
-                                                            c_uint);
-                llvm::LLVMPassManagerBuilderSetSizeLevel(MPMB, False);
-                llvm::LLVMPassManagerBuilderSetDisableUnitAtATime(MPMB,
-                                                                  False);
-                llvm::LLVMPassManagerBuilderSetDisableUnrollLoops(MPMB,
-                                                                  False);
-                llvm::LLVMPassManagerBuilderSetDisableSimplifyLibCalls(MPMB,
-                                                                       False);
-
-                if threshold != 0u {
-                    llvm::LLVMPassManagerBuilderUseInlinerWithThreshold
-                        (MPMB, threshold as c_uint);
-                }
-                llvm::LLVMPassManagerBuilderPopulateModulePassManager(
-                    MPMB, pm.llpm);
 
-                llvm::LLVMPassManagerBuilderDispose(MPMB);
+            let mut mpm = passes::PassManager::new(td.lltd);
+
+            if !sess.no_verify() {
+                mpm.addPass(llvm::LLVMCreateVerifierPass());
             }
-            if !sess.no_verify() { llvm::LLVMAddVerifierPass(pm.llpm); }
+
+            if sess.lint_llvm() {
+                mpm.addPass(llvm::LLVMCreateLintPass());
+            }
+
+            passes::populatePassManager(&mut mpm, opts.optimize);
+
+            debug!("Running Module Optimization Pass");
+            mpm.run(llmod);
+
             if is_object_or_assembly_or_exe(output_type) || opts.jit {
                 let LLVMOptNone       = 0 as c_int; // -O0
                 let LLVMOptLess       = 1 as c_int; // -O1
@@ -312,12 +282,9 @@ pub mod write {
                     // Always output the bitcode file with --save-temps
 
                     let filename = output.with_filetype("opt.bc");
-                    llvm::LLVMRunPassManager(pm.llpm, llmod);
                     str::as_c_str(filename.to_str(), |buf| {
                         llvm::LLVMWriteBitcodeToFile(llmod, buf)
                     });
-                    pm = mk_pass_manager();
-
                     // Save the assembly file if -S is used
                     if output_type == output_type_assembly {
                         WriteOutputFile(
@@ -377,7 +344,6 @@ pub mod write {
             } else {
                 // If only a bitcode file is asked for by using the
                 // '--emit-llvm' flag, then output it here
-                llvm::LLVMRunPassManager(pm.llpm, llmod);
                 str::as_c_str(output.to_str(),
                             |buf| llvm::LLVMWriteBitcodeToFile(llmod, buf) );
             }
diff --git a/src/librustc/back/passes.rs b/src/librustc/back/passes.rs
new file mode 100644
index 00000000000..ba4170fde56
--- /dev/null
+++ b/src/librustc/back/passes.rs
@@ -0,0 +1,154 @@
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use core::prelude::*;
+
+use driver::session;
+use lib::llvm::{PassRef, ModuleRef,PassManagerRef,TargetDataRef};
+use lib::llvm::llvm;
+use lib;
+
+pub struct PassManager {
+    priv llpm: PassManagerRef
+}
+
+impl Drop for PassManager {
+    fn finalize(&self) {
+        unsafe {
+            llvm::LLVMDisposePassManager(self.llpm);
+        }
+    }
+}
+
+impl PassManager {
+    pub fn new(td: TargetDataRef) -> PassManager {
+        unsafe {
+            let pm = PassManager {
+                llpm: llvm::LLVMCreatePassManager()
+            };
+            llvm::LLVMAddTargetData(td, pm.llpm);
+
+            return pm;
+        }
+    }
+
+    pub fn addPass(&mut self, pass:PassRef) {
+        unsafe {
+            llvm::LLVMAddPass(self.llpm, pass);
+        }
+    }
+
+    pub fn run(&self, md:ModuleRef) -> bool {
+        unsafe {
+            llvm::LLVMRunPassManager(self.llpm, md) == lib::llvm::True
+        }
+    }
+}
+
+
+pub fn populatePassManager(pm: &mut PassManager, level:session::OptLevel) {
+    unsafe {
+        // We add a lot of normally-unused prototypes, so always strip them
+        // straight away, later passes will get rid of any that are optimized
+        // away
+        pm.addPass(llvm::LLVMCreateStripDeadPrototypesPass());
+        if level == session::No {
+            pm.addPass(llvm::LLVMCreateAlwaysInlinerPass());
+
+            return;
+        }
+
+        //NOTE: Add library info
+
+        pm.addPass(llvm::LLVMCreateTypeBasedAliasAnalysisPass());
+        pm.addPass(llvm::LLVMCreateBasicAliasAnalysisPass());
+
+        pm.addPass(llvm::LLVMCreateSROAPass());
+        pm.addPass(llvm::LLVMCreateEarlyCSEPass());
+        pm.addPass(llvm::LLVMCreateLowerExpectIntrinsicPass());
+
+        pm.addPass(llvm::LLVMCreateGlobalOptimizerPass());
+        pm.addPass(llvm::LLVMCreateIPSCCPPass());
+        pm.addPass(llvm::LLVMCreateDeadArgEliminationPass());
+        pm.addPass(llvm::LLVMCreateInstructionCombiningPass());
+        pm.addPass(llvm::LLVMCreateCFGSimplificationPass());
+
+        pm.addPass(llvm::LLVMCreatePruneEHPass());
+
+        if level == session::Aggressive {
+            // Do this before inlining, since inlining might
+            // make minor changes to functions that mean they
+            // can't be merged, despite being almost identical
+            pm.addPass(llvm::LLVMCreateMergeFunctionsPass());
+        }
+
+        match level {
+            session::Less       => pm.addPass(llvm::LLVMCreateFunctionInliningPass(200)),
+            session::Default    => pm.addPass(llvm::LLVMCreateFunctionInliningPass(225)),
+            session::Aggressive => pm.addPass(llvm::LLVMCreateFunctionInliningPass(275)),
+            session::No         => ()
+        }
+
+        pm.addPass(llvm::LLVMCreateFunctionAttrsPass());
+
+        if level == session::Aggressive {
+            pm.addPass(llvm::LLVMCreateArgumentPromotionPass());
+        }
+
+        pm.addPass(llvm::LLVMCreateEarlyCSEPass());
+        pm.addPass(llvm::LLVMCreateSimplifyLibCallsPass());
+        pm.addPass(llvm::LLVMCreateJumpThreadingPass());
+        pm.addPass(llvm::LLVMCreateCorrelatedValuePropagationPass());
+        pm.addPass(llvm::LLVMCreateCFGSimplificationPass());
+        pm.addPass(llvm::LLVMCreateInstructionCombiningPass());
+
+        pm.addPass(llvm::LLVMCreateTailCallEliminationPass());
+        pm.addPass(llvm::LLVMCreateCFGSimplificationPass());
+        pm.addPass(llvm::LLVMCreateReassociatePass());
+        pm.addPass(llvm::LLVMCreateLoopRotatePass());
+        pm.addPass(llvm::LLVMCreateLICMPass());
+
+        pm.addPass(llvm::LLVMCreateInstructionCombiningPass());
+        pm.addPass(llvm::LLVMCreateIndVarSimplifyPass());
+        pm.addPass(llvm::LLVMCreateLoopIdiomPass());
+        pm.addPass(llvm::LLVMCreateLoopDeletionPass());
+
+        if level == session::Aggressive {
+            pm.addPass(llvm::LLVMCreateLoopVectorizePass());
+        }
+        pm.addPass(llvm::LLVMCreateLoopUnrollPass());
+
+        if level != session::Less {
+            pm.addPass(llvm::LLVMCreateGVNPass());
+        }
+        pm.addPass(llvm::LLVMCreateMemCpyOptPass());
+        pm.addPass(llvm::LLVMCreateSCCPPass());
+
+        pm.addPass(llvm::LLVMCreateInstructionCombiningPass());
+        pm.addPass(llvm::LLVMCreateJumpThreadingPass());
+        pm.addPass(llvm::LLVMCreateCorrelatedValuePropagationPass());
+        pm.addPass(llvm::LLVMCreateDeadStoreEliminationPass());
+
+        pm.addPass(llvm::LLVMCreateBBVectorizePass());
+        pm.addPass(llvm::LLVMCreateInstructionCombiningPass());
+        pm.addPass(llvm::LLVMCreateEarlyCSEPass());
+
+        pm.addPass(llvm::LLVMCreateLoopUnrollPass());
+
+        pm.addPass(llvm::LLVMCreateAggressiveDCEPass());
+        pm.addPass(llvm::LLVMCreateCFGSimplificationPass());
+        pm.addPass(llvm::LLVMCreateInstructionSimplifierPass());
+
+        if level != session::Less {
+            pm.addPass(llvm::LLVMCreateGlobalDCEPass());
+            pm.addPass(llvm::LLVMCreateConstantMergePass());
+        }
+    }
+}
diff --git a/src/librustc/driver/session.rs b/src/librustc/driver/session.rs
index ae49446c5b3..3f2467948a2 100644
--- a/src/librustc/driver/session.rs
+++ b/src/librustc/driver/session.rs
@@ -69,6 +69,7 @@ pub static extra_debug_info: uint = 1 << 21;
 pub static statik: uint = 1 << 22;
 pub static print_link_args: uint = 1 << 23;
 pub static no_debug_borrows: uint = 1 << 24;
+pub static lint_llvm : uint = 1 << 25;
 
 pub fn debugging_opts_map() -> ~[(~str, ~str, uint)] {
     ~[(~"verbose", ~"in general, enable more debug printouts", verbose),
@@ -107,6 +108,9 @@ pub fn debugging_opts_map() -> ~[(~str, ~str, uint)] {
      (~"no-debug-borrows",
       ~"do not show where borrow checks fail",
       no_debug_borrows),
+     (~"lint-llvm",
+      ~"Run the LLVM lint pass on the pre-optimization IR",
+      lint_llvm),
     ]
 }
 
@@ -265,6 +269,7 @@ pub impl Session_ {
     fn meta_stats(@self) -> bool { self.debugging_opt(meta_stats) }
     fn asm_comments(@self) -> bool { self.debugging_opt(asm_comments) }
     fn no_verify(@self) -> bool { self.debugging_opt(no_verify) }
+    fn lint_llvm(@self) -> bool { self.debugging_opt(lint_llvm) }
     fn trace(@self) -> bool { self.debugging_opt(trace) }
     fn coherence(@self) -> bool { self.debugging_opt(coherence) }
     fn borrowck_stats(@self) -> bool { self.debugging_opt(borrowck_stats) }
diff --git a/src/librustc/lib/llvm.rs b/src/librustc/lib/llvm.rs
index 7a1a3cf77aa..fc655ed1370 100644
--- a/src/librustc/lib/llvm.rs
+++ b/src/librustc/lib/llvm.rs
@@ -215,13 +215,15 @@ pub enum ObjectFile_opaque {}
 pub type ObjectFileRef = *ObjectFile_opaque;
 pub enum SectionIterator_opaque {}
 pub type SectionIteratorRef = *SectionIterator_opaque;
+pub enum Pass_opaque {}
+pub type PassRef = *Pass_opaque;
 
 pub mod llvm {
     use super::{AtomicBinOp, AtomicOrdering, BasicBlockRef};
     use super::{Bool, BuilderRef, ContextRef, MemoryBufferRef, ModuleRef};
     use super::{ObjectFileRef, Opcode, PassManagerRef, PassManagerBuilderRef};
     use super::{SectionIteratorRef, TargetDataRef, TypeKind, TypeRef, UseRef};
-    use super::{ValueRef};
+    use super::{ValueRef,PassRef};
 
     use core::libc::{c_char, c_int, c_longlong, c_ushort, c_uint, c_ulonglong};
 
@@ -1654,14 +1656,34 @@ pub mod llvm {
         /** Creates a pass manager. */
         #[fast_ffi]
         pub unsafe fn LLVMCreatePassManager() -> PassManagerRef;
+        /** Creates a function-by-function pass manager */
+        #[fast_ffi]
+        pub unsafe fn LLVMCreateFunctionPassManagerForModule(M:ModuleRef) -> PassManagerRef;
+
         /** Disposes a pass manager. */
         #[fast_ffi]
         pub unsafe fn LLVMDisposePassManager(PM: PassManagerRef);
+
         /** Runs a pass manager on a module. */
         #[fast_ffi]
         pub unsafe fn LLVMRunPassManager(PM: PassManagerRef,
                                          M: ModuleRef) -> Bool;
 
+        /** Runs the function passes on the provided function. */
+        #[fast_ffi]
+        pub unsafe fn LLVMRunFunctionPassManager(FPM:PassManagerRef, F:ValueRef) -> Bool;
+
+        /** Initializes all the function passes scheduled in the manager */
+        #[fast_ffi]
+        pub unsafe fn LLVMInitializeFunctionPassManager(FPM:PassManagerRef) -> Bool;
+
+        /** Finalizes all the function passes scheduled in the manager */
+        #[fast_ffi]
+        pub unsafe fn LLVMFinalizeFunctionPassManager(FPM:PassManagerRef) -> Bool;
+
+        #[fast_ffi]
+        pub unsafe fn LLVMAddPass(PM:PassManagerRef,P:PassRef);
+
         /** Adds a verification pass. */
         #[fast_ffi]
         pub unsafe fn LLVMAddVerifierPass(PM: PassManagerRef);
@@ -1903,6 +1925,203 @@ pub mod llvm {
                                     Constraints: *c_char, SideEffects: Bool,
                                     AlignStack: Bool, Dialect: c_uint)
                                  -> ValueRef;
+
+        // LLVM Passes
+
+        #[fast_ffi]
+        pub fn LLVMCreateStripSymbolsPass() -> PassRef;
+        #[fast_ffi]
+        pub fn LLVMCreateStripNonDebugSymbolsPass() -> PassRef;
+        #[fast_ffi]
+        pub fn LLVMCreateStripDebugDeclarePass() -> PassRef;
+        #[fast_ffi]
+        pub fn LLVMCreateStripDeadDebugInfoPass() -> PassRef;
+        #[fast_ffi]
+        pub fn LLVMCreateConstantMergePass() -> PassRef;
+        #[fast_ffi]
+        pub fn LLVMCreateGlobalOptimizerPass() -> PassRef;
+        #[fast_ffi]
+        pub fn LLVMCreateGlobalDCEPass() -> PassRef;
+        #[fast_ffi]
+        pub fn LLVMCreateAlwaysInlinerPass() -> PassRef;
+        #[fast_ffi]
+        pub fn LLVMCreatePruneEHPass() -> PassRef;
+        #[fast_ffi]
+        pub fn LLVMCreateInternalizePass() -> PassRef;
+        #[fast_ffi]
+        pub fn LLVMCreateDeadArgEliminationPass() -> PassRef;
+        #[fast_ffi]
+        pub fn LLVMCreateDeadArgHackingPass() -> PassRef;
+        #[fast_ffi]
+        pub fn LLVMCreateArgumentPromotionPass() -> PassRef;
+        #[fast_ffi]
+        pub fn LLVMCreateIPConstantPropagationPass() -> PassRef;
+        #[fast_ffi]
+        pub fn LLVMCreateIPSCCPPass() -> PassRef;
+        #[fast_ffi]
+        pub fn LLVMCreateLoopExtractorPass() -> PassRef;
+        #[fast_ffi]
+        pub fn LLVMCreateSingleLoopExtractorPass() -> PassRef;
+        #[fast_ffi]
+        pub fn LLVMCreateBlockExtractorPass() -> PassRef;
+        #[fast_ffi]
+        pub fn LLVMCreateStripDeadPrototypesPass() -> PassRef;
+        #[fast_ffi]
+        pub fn LLVMCreateFunctionAttrsPass() -> PassRef;
+        #[fast_ffi]
+        pub fn LLVMCreateMergeFunctionsPass() -> PassRef;
+        #[fast_ffi]
+        pub fn LLVMCreatePartialInliningPass() -> PassRef;
+        #[fast_ffi]
+        pub fn LLVMCreateMetaRenamerPass() -> PassRef;
+        #[fast_ffi]
+        pub fn LLVMCreateBarrierNoopPass() -> PassRef;
+        #[fast_ffi]
+        pub fn LLVMCreateFunctionInliningPass(Threshold:c_int) -> PassRef;
+        #[fast_ffi]
+        pub fn LLVMCreateEdgeProfilerPass() -> PassRef;
+        #[fast_ffi]
+        pub fn LLVMCreateOptimalEdgeProfilerPass() -> PassRef;
+        #[fast_ffi]
+        pub fn LLVMCreatePathProfilerPass() -> PassRef;
+        #[fast_ffi]
+        pub fn LLVMCreateGCOVProfilerPass() -> PassRef;
+        #[fast_ffi]
+        pub fn LLVMCreateBoundsCheckingPass() -> PassRef;
+        #[fast_ffi]
+        pub fn LLVMCreateConstantPropagationPass() -> PassRef;
+        #[fast_ffi]
+        pub fn LLVMCreateSCCPPass() -> PassRef;
+        #[fast_ffi]
+        pub fn LLVMCreateDeadInstEliminationPass() -> PassRef;
+        #[fast_ffi]
+        pub fn LLVMCreateDeadCodeEliminationPass() -> PassRef;
+        #[fast_ffi]
+        pub fn LLVMCreateDeadStoreEliminationPass() -> PassRef;
+        #[fast_ffi]
+        pub fn LLVMCreateAggressiveDCEPass() -> PassRef;
+        #[fast_ffi]
+        pub fn LLVMCreateSROAPass() -> PassRef;
+        #[fast_ffi]
+        pub fn LLVMCreateScalarReplAggregatesPass() -> PassRef;
+        #[fast_ffi]
+        pub fn LLVMCreateIndVarSimplifyPass() -> PassRef;
+        #[fast_ffi]
+        pub fn LLVMCreateInstructionCombiningPass() -> PassRef;
+        #[fast_ffi]
+        pub fn LLVMCreateLICMPass() -> PassRef;
+        #[fast_ffi]
+        pub fn LLVMCreateLoopStrengthReducePass() -> PassRef;
+        #[fast_ffi]
+        pub fn LLVMCreateGlobalMergePass() -> PassRef;
+        #[fast_ffi]
+        pub fn LLVMCreateLoopUnswitchPass() -> PassRef;
+        #[fast_ffi]
+        pub fn LLVMCreateLoopInstSimplifyPass() -> PassRef;
+        #[fast_ffi]
+        pub fn LLVMCreateLoopUnrollPass() -> PassRef;
+        #[fast_ffi]
+        pub fn LLVMCreateLoopRotatePass() -> PassRef;
+        #[fast_ffi]
+        pub fn LLVMCreateLoopIdiomPass() -> PassRef;
+        #[fast_ffi]
+        pub fn LLVMCreatePromoteMemoryToRegisterPass() -> PassRef;
+        #[fast_ffi]
+        pub fn LLVMCreateDemoteRegisterToMemoryPass() -> PassRef;
+        #[fast_ffi]
+        pub fn LLVMCreateReassociatePass() -> PassRef;
+        #[fast_ffi]
+        pub fn LLVMCreateJumpThreadingPass() -> PassRef;
+        #[fast_ffi]
+        pub fn LLVMCreateCFGSimplificationPass() -> PassRef;
+        #[fast_ffi]
+        pub fn LLVMCreateBreakCriticalEdgesPass() -> PassRef;
+        #[fast_ffi]
+        pub fn LLVMCreateLoopSimplifyPass() -> PassRef;
+        #[fast_ffi]
+        pub fn LLVMCreateTailCallEliminationPass() -> PassRef;
+        #[fast_ffi]
+        pub fn LLVMCreateLowerSwitchPass() -> PassRef;
+        #[fast_ffi]
+        pub fn LLVMCreateLowerInvokePass() -> PassRef;
+        #[fast_ffi]
+        pub fn LLVMCreateBlockPlacementPass() -> PassRef;
+        #[fast_ffi]
+        pub fn LLVMCreateLCSSAPass() -> PassRef;
+        #[fast_ffi]
+        pub fn LLVMCreateEarlyCSEPass() -> PassRef;
+        #[fast_ffi]
+        pub fn LLVMCreateGVNPass() -> PassRef;
+        #[fast_ffi]
+        pub fn LLVMCreateMemCpyOptPass() -> PassRef;
+        #[fast_ffi]
+        pub fn LLVMCreateLoopDeletionPass() -> PassRef;
+        #[fast_ffi]
+        pub fn LLVMCreateSimplifyLibCallsPass() -> PassRef;
+        #[fast_ffi]
+        pub fn LLVMCreateCodeGenPreparePass() -> PassRef;
+        #[fast_ffi]
+        pub fn LLVMCreateInstructionNamerPass() -> PassRef;
+        #[fast_ffi]
+        pub fn LLVMCreateSinkingPass() -> PassRef;
+        #[fast_ffi]
+        pub fn LLVMCreateLowerAtomicPass() -> PassRef;
+        #[fast_ffi]
+        pub fn LLVMCreateCorrelatedValuePropagationPass() -> PassRef;
+        #[fast_ffi]
+        pub fn LLVMCreateInstructionSimplifierPass() -> PassRef;
+        #[fast_ffi]
+        pub fn LLVMCreateLowerExpectIntrinsicPass() -> PassRef;
+        #[fast_ffi]
+        pub fn LLVMCreateBBVectorizePass() -> PassRef;
+        #[fast_ffi]
+        pub fn LLVMCreateLoopVectorizePass() -> PassRef;
+        #[fast_ffi]
+        pub fn LLVMCreateGlobalsModRefPass() -> PassRef;
+        #[fast_ffi]
+        pub fn LLVMCreateAliasAnalysisCounterPass() -> PassRef;
+        #[fast_ffi]
+        pub fn LLVMCreateAAEvalPass() -> PassRef;
+        #[fast_ffi]
+        pub fn LLVMCreateNoAAPass() -> PassRef;
+        #[fast_ffi]
+        pub fn LLVMCreateBasicAliasAnalysisPass() -> PassRef;
+        #[fast_ffi]
+        pub fn LLVMCreateScalarEvolutionAliasAnalysisPass() -> PassRef;
+        #[fast_ffi]
+        pub fn LLVMCreateTypeBasedAliasAnalysisPass() -> PassRef;
+        #[fast_ffi]
+        pub fn LLVMCreateProfileLoaderPass() -> PassRef;
+        #[fast_ffi]
+        pub fn LLVMCreateProfileMetadataLoaderPass() -> PassRef;
+        #[fast_ffi]
+        pub fn LLVMCreateNoProfileInfoPass() -> PassRef;
+        #[fast_ffi]
+        pub fn LLVMCreateProfileEstimatorPass() -> PassRef;
+        #[fast_ffi]
+        pub fn LLVMCreateProfileVerifierPass() -> PassRef;
+        #[fast_ffi]
+        pub fn LLVMCreatePathProfileLoaderPass() -> PassRef;
+        #[fast_ffi]
+        pub fn LLVMCreateNoPathProfileInfoPass() -> PassRef;
+        #[fast_ffi]
+        pub fn LLVMCreatePathProfileVerifierPass() -> PassRef;
+        #[fast_ffi]
+        pub fn LLVMCreateLazyValueInfoPass() -> PassRef;
+        #[fast_ffi]
+        pub fn LLVMCreateDependenceAnalysisPass() -> PassRef;
+        #[fast_ffi]
+        pub fn LLVMCreateCostModelAnalysisPass() -> PassRef;
+        #[fast_ffi]
+        pub fn LLVMCreateInstCountPass() -> PassRef;
+        #[fast_ffi]
+        pub fn LLVMCreateRegionInfoPass() -> PassRef;
+        #[fast_ffi]
+        pub fn LLVMCreateModuleDebugInfoPrinterPass() -> PassRef;
+        #[fast_ffi]
+        pub fn LLVMCreateLintPass() -> PassRef;
+        #[fast_ffi]
+        pub fn LLVMCreateVerifierPass() -> PassRef;
     }
 }
 
diff --git a/src/librustc/rustc.rc b/src/librustc/rustc.rc
index 629310b1213..cca194a7773 100644
--- a/src/librustc/rustc.rc
+++ b/src/librustc/rustc.rc
@@ -128,6 +128,7 @@ pub mod back {
     pub mod x86_64;
     pub mod rpath;
     pub mod target_strs;
+    pub mod passes;
 }
 
 #[path = "metadata/mod.rs"]
diff --git a/src/rustllvm/PassWrapper.cpp b/src/rustllvm/PassWrapper.cpp
new file mode 100644
index 00000000000..fd17dfb4cf8
--- /dev/null
+++ b/src/rustllvm/PassWrapper.cpp
@@ -0,0 +1,160 @@
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#include "rustllvm.h"
+
+using namespace llvm;
+
+// Pass conversion fns
+typedef struct LLVMOpaquePass *LLVMPassRef;
+
+inline Pass *unwrap(LLVMPassRef P) {
+    return reinterpret_cast<Pass*>(P);
+}
+
+inline LLVMPassRef wrap(const Pass *P) {
+    return reinterpret_cast<LLVMPassRef>(const_cast<Pass*>(P));
+}
+
+template<typename T>
+inline T *unwrap(LLVMPassRef P) {
+    T *Q = (T*)unwrap(P);
+    assert(Q && "Invalid cast!");
+    return Q;
+}
+
+#define WRAP_PASS(name)                             \
+    extern "C" LLVMPassRef LLVMCreate##name##Pass() {      \
+        return wrap(llvm::create##name##Pass());    \
+    }
+
+extern "C" void LLVMAddPass(LLVMPassManagerRef PM, LLVMPassRef P) {
+    PassManagerBase * pm = unwrap(PM);
+    Pass * p = unwrap(P);
+
+    pm->add(p);
+}
+
+////////////////
+// Transforms //
+// /////////////
+
+// IPO Passes
+WRAP_PASS(StripSymbols)
+WRAP_PASS(StripNonDebugSymbols)
+WRAP_PASS(StripDebugDeclare)
+WRAP_PASS(StripDeadDebugInfo)
+WRAP_PASS(ConstantMerge)
+WRAP_PASS(GlobalOptimizer)
+WRAP_PASS(GlobalDCE)
+WRAP_PASS(AlwaysInliner)
+WRAP_PASS(PruneEH)
+WRAP_PASS(Internalize)
+WRAP_PASS(DeadArgElimination)
+WRAP_PASS(DeadArgHacking)
+WRAP_PASS(ArgumentPromotion)
+WRAP_PASS(IPConstantPropagation)
+WRAP_PASS(IPSCCP)
+WRAP_PASS(LoopExtractor)
+WRAP_PASS(SingleLoopExtractor)
+WRAP_PASS(BlockExtractor)
+WRAP_PASS(StripDeadPrototypes)
+WRAP_PASS(FunctionAttrs)
+WRAP_PASS(MergeFunctions)
+WRAP_PASS(PartialInlining)
+WRAP_PASS(MetaRenamer)
+WRAP_PASS(BarrierNoop)
+
+extern "C" LLVMPassRef LLVMCreateFunctionInliningPass(int Threshold) {
+    return wrap(llvm::createFunctionInliningPass(Threshold));
+}
+
+// Instrumentation Passes
+WRAP_PASS(EdgeProfiler)
+WRAP_PASS(OptimalEdgeProfiler)
+WRAP_PASS(PathProfiler)
+WRAP_PASS(GCOVProfiler)
+WRAP_PASS(BoundsChecking)
+
+// Scalar Passes
+WRAP_PASS(ConstantPropagation)
+WRAP_PASS(SCCP)
+WRAP_PASS(DeadInstElimination)
+WRAP_PASS(DeadCodeElimination)
+WRAP_PASS(DeadStoreElimination)
+WRAP_PASS(AggressiveDCE)
+WRAP_PASS(SROA)
+WRAP_PASS(ScalarReplAggregates)
+WRAP_PASS(IndVarSimplify)
+WRAP_PASS(InstructionCombining)
+WRAP_PASS(LICM)
+WRAP_PASS(LoopStrengthReduce)
+WRAP_PASS(GlobalMerge)
+WRAP_PASS(LoopUnswitch)
+WRAP_PASS(LoopInstSimplify)
+WRAP_PASS(LoopUnroll)
+WRAP_PASS(LoopRotate)
+WRAP_PASS(LoopIdiom)
+WRAP_PASS(PromoteMemoryToRegister)
+WRAP_PASS(DemoteRegisterToMemory)
+WRAP_PASS(Reassociate)
+WRAP_PASS(JumpThreading)
+WRAP_PASS(CFGSimplification)
+WRAP_PASS(BreakCriticalEdges)
+WRAP_PASS(LoopSimplify)
+WRAP_PASS(TailCallElimination)
+WRAP_PASS(LowerSwitch)
+WRAP_PASS(LowerInvoke)
+WRAP_PASS(BlockPlacement)
+WRAP_PASS(LCSSA)
+WRAP_PASS(EarlyCSE)
+WRAP_PASS(GVN)
+WRAP_PASS(MemCpyOpt)
+WRAP_PASS(LoopDeletion)
+WRAP_PASS(SimplifyLibCalls)
+WRAP_PASS(CodeGenPrepare)
+WRAP_PASS(InstructionNamer)
+WRAP_PASS(Sinking)
+WRAP_PASS(LowerAtomic)
+WRAP_PASS(CorrelatedValuePropagation)
+WRAP_PASS(InstructionSimplifier)
+WRAP_PASS(LowerExpectIntrinsic)
+
+// Vectorize Passes
+WRAP_PASS(BBVectorize)
+WRAP_PASS(LoopVectorize)
+
+//////////////
+// Analyses //
+//////////////
+
+WRAP_PASS(GlobalsModRef)
+WRAP_PASS(AliasAnalysisCounter)
+WRAP_PASS(AAEval)
+WRAP_PASS(NoAA)
+WRAP_PASS(BasicAliasAnalysis)
+WRAP_PASS(ScalarEvolutionAliasAnalysis)
+WRAP_PASS(TypeBasedAliasAnalysis)
+WRAP_PASS(ProfileLoader)
+WRAP_PASS(ProfileMetadataLoader)
+WRAP_PASS(NoProfileInfo)
+WRAP_PASS(ProfileEstimator)
+WRAP_PASS(ProfileVerifier)
+WRAP_PASS(PathProfileLoader)
+WRAP_PASS(NoPathProfileInfo)
+WRAP_PASS(PathProfileVerifier)
+WRAP_PASS(LazyValueInfo)
+WRAP_PASS(DependenceAnalysis)
+WRAP_PASS(CostModelAnalysis)
+WRAP_PASS(InstCount)
+WRAP_PASS(RegionInfo)
+WRAP_PASS(ModuleDebugInfoPrinter)
+WRAP_PASS(Lint)
+WRAP_PASS(Verifier)
diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp
index cff448b6a1a..4ee5df28d24 100644
--- a/src/rustllvm/RustWrapper.cpp
+++ b/src/rustllvm/RustWrapper.cpp
@@ -1,4 +1,4 @@
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#include "rustllvm.h"
+
 //===----------------------------------------------------------------------===
 //
 // This file defines alternate interfaces to core functions that are more
@@ -15,50 +17,6 @@
 //
 //===----------------------------------------------------------------------===
 
-#include "llvm/IR/InlineAsm.h"
-#include "llvm/IR/LLVMContext.h"
-#include "llvm/Linker.h"
-#include "llvm/PassManager.h"
-#include "llvm/IR/InlineAsm.h"
-#include "llvm/IR/LLVMContext.h"
-#include "llvm/Analysis/Verifier.h"
-#include "llvm/Analysis/Passes.h"
-#include "llvm/ADT/Triple.h"
-#include "llvm/ADT/DenseSet.h"
-#include "llvm/Assembly/Parser.h"
-#include "llvm/Assembly/PrintModulePass.h"
-#include "llvm/Support/CommandLine.h"
-#include "llvm/Support/FormattedStream.h"
-#include "llvm/Support/Timer.h"
-#include "llvm/Support/raw_ostream.h"
-#include "llvm/Support/TargetSelect.h"
-#include "llvm/Support/TargetRegistry.h"
-#include "llvm/Support/SourceMgr.h"
-#include "llvm/Support/Host.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/DynamicLibrary.h"
-#include "llvm/Support/Memory.h"
-#include "llvm/ExecutionEngine/ExecutionEngine.h"
-#include "llvm/ExecutionEngine/JIT.h"
-#include "llvm/ExecutionEngine/JITMemoryManager.h"
-#include "llvm/ExecutionEngine/MCJIT.h"
-#include "llvm/ExecutionEngine/Interpreter.h"
-#include "llvm/Target/TargetMachine.h"
-#include "llvm/Target/TargetOptions.h"
-#include "llvm/Transforms/Scalar.h"
-#include "llvm/Transforms/IPO.h"
-#include "llvm-c/Core.h"
-#include "llvm-c/BitReader.h"
-#include "llvm-c/Object.h"
-
-// Used by RustMCJITMemoryManager::getPointerToNamedFunction()
-// to get around glibc issues. See the function for more information.
-#ifdef __linux__
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-#endif
-
 using namespace llvm;
 using namespace llvm::sys;
 
diff --git a/src/rustllvm/rustllvm.def.in b/src/rustllvm/rustllvm.def.in
index dd5dc7102d1..1e1c07fd99c 100644
--- a/src/rustllvm/rustllvm.def.in
+++ b/src/rustllvm/rustllvm.def.in
@@ -584,3 +584,102 @@ LLVMConstNamedStruct
 LLVMStructCreateNamed
 LLVMStructSetBody
 LLVMInlineAsm
+LLVMAddPass
+
+LLVMCreateStripSymbolsPass
+LLVMCreateStripNonDebugSymbolsPass
+LLVMCreateStripDebugDeclarePass
+LLVMCreateStripDeadDebugInfoPass
+LLVMCreateConstantMergePass
+LLVMCreateGlobalOptimizerPass
+LLVMCreateGlobalDCEPass
+LLVMCreateAlwaysInlinerPass
+LLVMCreatePruneEHPass
+LLVMCreateInternalizePass
+LLVMCreateDeadArgEliminationPass
+LLVMCreateDeadArgHackingPass
+LLVMCreateArgumentPromotionPass
+LLVMCreateIPConstantPropagationPass
+LLVMCreateIPSCCPPass
+LLVMCreateLoopExtractorPass
+LLVMCreateSingleLoopExtractorPass
+LLVMCreateBlockExtractorPass
+LLVMCreateStripDeadPrototypesPass
+LLVMCreateFunctionAttrsPass
+LLVMCreateMergeFunctionsPass
+LLVMCreatePartialInliningPass
+LLVMCreateMetaRenamerPass
+LLVMCreateBarrierNoopPass
+LLVMCreateFunctionInliningPass
+LLVMCreateEdgeProfilerPass
+LLVMCreateOptimalEdgeProfilerPass
+LLVMCreatePathProfilerPass
+LLVMCreateGCOVProfilerPass
+LLVMCreateBoundsCheckingPass
+LLVMCreateConstantPropagationPass
+LLVMCreateSCCPPass
+LLVMCreateDeadInstEliminationPass
+LLVMCreateDeadCodeEliminationPass
+LLVMCreateDeadStoreEliminationPass
+LLVMCreateAggressiveDCEPass
+LLVMCreateSROAPass
+LLVMCreateScalarReplAggregatesPass
+LLVMCreateIndVarSimplifyPass
+LLVMCreateInstructionCombiningPass
+LLVMCreateLICMPass
+LLVMCreateLoopStrengthReducePass
+LLVMCreateGlobalMergePass
+LLVMCreateLoopUnswitchPass
+LLVMCreateLoopInstSimplifyPass
+LLVMCreateLoopUnrollPass
+LLVMCreateLoopRotatePass
+LLVMCreateLoopIdiomPass
+LLVMCreatePromoteMemoryToRegisterPass
+LLVMCreateDemoteRegisterToMemoryPass
+LLVMCreateReassociatePass
+LLVMCreateJumpThreadingPass
+LLVMCreateCFGSimplificationPass
+LLVMCreateBreakCriticalEdgesPass
+LLVMCreateLoopSimplifyPass
+LLVMCreateTailCallEliminationPass
+LLVMCreateLowerSwitchPass
+LLVMCreateLowerInvokePass
+LLVMCreateBlockPlacementPass
+LLVMCreateLCSSAPass
+LLVMCreateEarlyCSEPass
+LLVMCreateGVNPass
+LLVMCreateMemCpyOptPass
+LLVMCreateLoopDeletionPass
+LLVMCreateSimplifyLibCallsPass
+LLVMCreateCodeGenPreparePass
+LLVMCreateInstructionNamerPass
+LLVMCreateSinkingPass
+LLVMCreateLowerAtomicPass
+LLVMCreateCorrelatedValuePropagationPass
+LLVMCreateInstructionSimplifierPass
+LLVMCreateLowerExpectIntrinsicPass
+LLVMCreateBBVectorizePass
+LLVMCreateLoopVectorizePass
+LLVMCreateGlobalsModRefPass
+LLVMCreateAliasAnalysisCounterPass
+LLVMCreateAAEvalPass
+LLVMCreateNoAAPass
+LLVMCreateBasicAliasAnalysisPass
+LLVMCreateScalarEvolutionAliasAnalysisPass
+LLVMCreateTypeBasedAliasAnalysisPass
+LLVMCreateProfileLoaderPass
+LLVMCreateProfileMetadataLoaderPass
+LLVMCreateNoProfileInfoPass
+LLVMCreateProfileEstimatorPass
+LLVMCreateProfileVerifierPass
+LLVMCreatePathProfileLoaderPass
+LLVMCreateNoPathProfileInfoPass
+LLVMCreatePathProfileVerifierPass
+LLVMCreateLazyValueInfoPass
+LLVMCreateDependenceAnalysisPass
+LLVMCreateCostModelAnalysisPass
+LLVMCreateInstCountPass
+LLVMCreateRegionInfoPass
+LLVMCreateModuleDebugInfoPrinterPass
+LLVMCreateLintPass
+LLVMCreateVerifierPass
diff --git a/src/rustllvm/rustllvm.h b/src/rustllvm/rustllvm.h
new file mode 100644
index 00000000000..1c8842f7b4a
--- /dev/null
+++ b/src/rustllvm/rustllvm.h
@@ -0,0 +1,57 @@
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#include "llvm/IR/InlineAsm.h"
+#include "llvm/IR/LLVMContext.h"
+#include "llvm/Linker.h"
+#include "llvm/PassManager.h"
+#include "llvm/IR/InlineAsm.h"
+#include "llvm/IR/LLVMContext.h"
+#include "llvm/Analysis/Verifier.h"
+#include "llvm/Analysis/Passes.h"
+#include "llvm/Analysis/Lint.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/ADT/DenseSet.h"
+#include "llvm/Assembly/Parser.h"
+#include "llvm/Assembly/PrintModulePass.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/FormattedStream.h"
+#include "llvm/Support/Timer.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/TargetSelect.h"
+#include "llvm/Support/TargetRegistry.h"
+#include "llvm/Support/SourceMgr.h"
+#include "llvm/Support/Host.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/DynamicLibrary.h"
+#include "llvm/Support/Memory.h"
+#include "llvm/ExecutionEngine/ExecutionEngine.h"
+#include "llvm/ExecutionEngine/JIT.h"
+#include "llvm/ExecutionEngine/JITMemoryManager.h"
+#include "llvm/ExecutionEngine/MCJIT.h"
+#include "llvm/ExecutionEngine/Interpreter.h"
+#include "llvm/Target/TargetMachine.h"
+#include "llvm/Target/TargetOptions.h"
+#include "llvm/Transforms/Scalar.h"
+#include "llvm/Transforms/IPO.h"
+#include "llvm/Transforms/Instrumentation.h"
+#include "llvm/Transforms/Vectorize.h"
+#include "llvm-c/Core.h"
+#include "llvm-c/BitReader.h"
+#include "llvm-c/Object.h"
+
+// Used by RustMCJITMemoryManager::getPointerToNamedFunction()
+// to get around glibc issues. See the function for more information.
+#ifdef __linux__
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#endif
+