]> git.lizzy.rs Git - rust.git/commitdiff
MIR: Add pass that erases all regions right before trans
authorMichael Woerister <michaelwoerister@posteo.net>
Mon, 16 Nov 2015 17:41:16 +0000 (18:41 +0100)
committerMichael Woerister <michaelwoerister@posteo.net>
Wed, 18 Nov 2015 16:26:24 +0000 (17:26 +0100)
src/librustc_driver/driver.rs
src/librustc_mir/transform/erase_regions.rs [new file with mode: 0644]
src/librustc_mir/transform/mod.rs
src/librustc_mir/transform/simplify_cfg.rs
src/librustc_trans/trans/mir/constant.rs
src/librustc_trans/trans/mir/lvalue.rs
src/librustc_trans/trans/mir/operand.rs
src/test/run-make/execution-engine/test.rs

index 2d7f5544402a227a1a2c19f65dc66971451d41bb..c284ce5551a8cc78c8c720a318896ceab9b4c3c4 100644 (file)
@@ -167,7 +167,7 @@ macro_rules! controller_entry_point{($point: ident, $tsess: expr, $make_state: e
                                             tcx.print_debug_stats();
                                         }
                                         let trans = phase_4_translate_to_llvm(tcx,
-                                                                              &mir_map,
+                                                                              mir_map,
                                                                               analysis);
 
                                         if log_enabled!(::log::INFO) {
@@ -849,7 +849,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
 /// Run the translation phase to LLVM, after which the AST and analysis can
 /// be discarded.
 pub fn phase_4_translate_to_llvm<'tcx>(tcx: &ty::ctxt<'tcx>,
-                                       mir_map: &MirMap<'tcx>,
+                                       mut mir_map: MirMap<'tcx>,
                                        analysis: ty::CrateAnalysis)
                                        -> trans::CrateTranslation {
     let time_passes = tcx.sess.time_passes();
@@ -858,10 +858,14 @@ pub fn phase_4_translate_to_llvm<'tcx>(tcx: &ty::ctxt<'tcx>,
          "resolving dependency formats",
          || dependency_format::calculate(&tcx.sess));
 
+    time(time_passes,
+         "erasing regions from MIR",
+         || mir::transform::erase_regions::erase_regions(tcx, &mut mir_map));
+
     // Option dance to work around the lack of stack once closures.
     time(time_passes,
          "translation",
-         move || trans::trans_crate(tcx, mir_map, analysis))
+         move || trans::trans_crate(tcx, &mir_map, analysis))
 }
 
 /// Run LLVM itself, producing a bitcode file, assembly file or object file
diff --git a/src/librustc_mir/transform/erase_regions.rs b/src/librustc_mir/transform/erase_regions.rs
new file mode 100644 (file)
index 0000000..e156fbf
--- /dev/null
@@ -0,0 +1,234 @@
+// Copyright 2015 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.
+
+//! This pass erases all early-bound regions from the types occuring in the MIR.
+//! We want to do this once just before trans, so trans does not have to take
+//! care erasing regions all over the place.
+
+use repr::*;
+use rustc::middle::ty;
+use transform::MirPass;
+use mir_map::MirMap;
+
+pub fn erase_regions<'tcx>(tcx: &ty::ctxt<'tcx>, mir_map: &mut MirMap<'tcx>) {
+    let mut eraser = EraseRegions::new(tcx);
+
+    for mir in mir_map.iter_mut().map(|(_, v)| v) {
+        eraser.run_on_mir(mir);
+    }
+}
+
+pub struct EraseRegions<'a, 'tcx: 'a> {
+    tcx: &'a ty::ctxt<'tcx>,
+}
+
+impl<'a, 'tcx> MirPass<'tcx> for EraseRegions<'a, 'tcx> {
+
+    fn run_on_mir(&mut self, mir: &mut Mir<'tcx>) {
+
+        for basic_block in &mut mir.basic_blocks {
+            self.erase_regions_basic_block(basic_block);
+        }
+
+        self.erase_regions_return_ty(&mut mir.return_ty);
+
+        self.erase_regions_tys(mir.var_decls.iter_mut().map(|d| &mut d.ty));
+        self.erase_regions_tys(mir.arg_decls.iter_mut().map(|d| &mut d.ty));
+        self.erase_regions_tys(mir.temp_decls.iter_mut().map(|d| &mut d.ty));
+    }
+}
+
+impl<'a, 'tcx> EraseRegions<'a, 'tcx> {
+
+    pub fn new(tcx: &'a ty::ctxt<'tcx>) -> EraseRegions<'a, 'tcx> {
+        EraseRegions {
+            tcx: tcx
+        }
+    }
+
+    fn erase_regions_basic_block(&mut self,
+                                 basic_block: &mut BasicBlockData<'tcx>) {
+        for statement in &mut basic_block.statements {
+            self.erase_regions_statement(statement);
+        }
+
+        self.erase_regions_terminator(&mut basic_block.terminator);
+    }
+
+    fn erase_regions_statement(&mut self,
+                               statement: &mut Statement<'tcx>) {
+        match statement.kind {
+            StatementKind::Assign(ref mut lvalue, ref mut rvalue) => {
+                self.erase_regions_lvalue(lvalue);
+                self.erase_regions_rvalue(rvalue);
+            }
+            StatementKind::Drop(_, ref mut lvalue) => {
+                self.erase_regions_lvalue(lvalue);
+            }
+        }
+    }
+
+    fn erase_regions_terminator(&mut self,
+                                terminator: &mut Terminator<'tcx>) {
+        match *terminator {
+            Terminator::Goto { .. } |
+            Terminator::Diverge |
+            Terminator::Return |
+            Terminator::Panic { .. } => {
+                /* nothing to do */
+            }
+            Terminator::If { ref mut cond, .. } => {
+                self.erase_regions_operand(cond);
+            }
+            Terminator::Switch { ref mut discr, .. } => {
+                self.erase_regions_lvalue(discr);
+            }
+            Terminator::SwitchInt {
+                ref mut discr,
+                ref mut switch_ty,
+                ..
+            } => {
+                self.erase_regions_lvalue(discr);
+                *switch_ty = self.tcx.erase_regions(switch_ty);
+            },
+            Terminator::Call {
+                data: CallData {
+                    ref mut destination,
+                    ref mut func,
+                    ref mut args
+                },
+                ..
+            } => {
+                self.erase_regions_lvalue(destination);
+                self.erase_regions_operand(func);
+                for arg in &mut *args {
+                    self.erase_regions_operand(arg);
+                }
+            }
+        }
+    }
+
+    fn erase_regions_operand(&mut self, operand: &mut Operand<'tcx>) {
+        match *operand {
+            Operand::Consume(ref mut lvalue) => {
+                self.erase_regions_lvalue(lvalue);
+            }
+            Operand::Constant(ref mut constant) => {
+                self.erase_regions_constant(constant);
+            }
+        }
+    }
+
+    fn erase_regions_lvalue(&mut self, lvalue: &mut Lvalue<'tcx>) {
+        match *lvalue {
+            Lvalue::Var(_)        |
+            Lvalue::Temp(_)       |
+            Lvalue::Arg(_)        |
+            Lvalue::Static(_)     |
+            Lvalue::ReturnPointer => {}
+            Lvalue::Projection(ref mut lvalue_projection) => {
+                self.erase_regions_lvalue(&mut lvalue_projection.base);
+                match lvalue_projection.elem {
+                    ProjectionElem::Deref              |
+                    ProjectionElem::Field(_)           |
+                    ProjectionElem::Downcast(..)       |
+                    ProjectionElem::ConstantIndex {..} => { /* nothing to do */ }
+                    ProjectionElem::Index(ref mut index) => {
+                        self.erase_regions_operand(index);
+                    }
+                }
+            }
+        }
+    }
+
+    fn erase_regions_rvalue(&mut self, rvalue: &mut Rvalue<'tcx>) {
+        match *rvalue {
+            Rvalue::Use(ref mut operand) => {
+                self.erase_regions_operand(operand)
+            }
+            Rvalue::Repeat(ref mut operand, ref mut constant) => {
+                self.erase_regions_operand(operand);
+                self.erase_regions_constant(constant);
+            }
+            Rvalue::Ref(ref mut region, _, ref mut lvalue) => {
+                *region = ty::ReStatic;
+                self.erase_regions_lvalue(lvalue);
+            }
+            Rvalue::Len(ref mut lvalue) => self.erase_regions_lvalue(lvalue),
+            Rvalue::Cast(_, ref mut operand, ref mut ty) => {
+                self.erase_regions_operand(operand);
+                *ty = self.tcx.erase_regions(ty);
+            }
+            Rvalue::BinaryOp(_, ref mut operand1, ref mut operand2) => {
+                self.erase_regions_operand(operand1);
+                self.erase_regions_operand(operand2);
+            }
+            Rvalue::UnaryOp(_, ref mut operand) => {
+                self.erase_regions_operand(operand);
+            }
+            Rvalue::Box(ref mut ty) => *ty = self.tcx.erase_regions(ty),
+            Rvalue::Aggregate(ref mut aggregate_kind, ref mut operands) => {
+                match *aggregate_kind {
+                    AggregateKind::Vec   |
+                    AggregateKind::Tuple => {},
+                    AggregateKind::Adt(_, _, ref mut substs) => {
+                        let erased = self.tcx.erase_regions(*substs);
+                        *substs = self.tcx.mk_substs(erased);
+                    }
+                    AggregateKind::Closure(def_id, ref mut closure_substs) => {
+                        let cloned = Box::new(closure_substs.clone());
+                        let ty = self.tcx.mk_closure_from_closure_substs(def_id,
+                                                                         cloned);
+                        let erased = self.tcx.erase_regions(&ty);
+                        *closure_substs = match erased.sty {
+                            ty::TyClosure(_, ref closure_substs) => &*closure_substs,
+                            _ => unreachable!()
+                        };
+                    }
+                }
+                for operand in &mut *operands {
+                    self.erase_regions_operand(operand);
+                }
+            }
+            Rvalue::Slice { ref mut input, .. } => {
+                self.erase_regions_lvalue(input);
+            }
+            Rvalue::InlineAsm(_) => {},
+        }
+    }
+
+    fn erase_regions_constant(&mut self, constant: &mut Constant<'tcx>) {
+        constant.ty = self.tcx.erase_regions(&constant.ty);
+        match constant.literal {
+            Literal::Item { ref mut substs, .. } => {
+                *substs = self.tcx.mk_substs(self.tcx.erase_regions(substs));
+            }
+            Literal::Value { .. } => { /* nothing to do */ }
+        }
+    }
+
+    fn erase_regions_return_ty(&mut self, fn_output: &mut ty::FnOutput<'tcx>) {
+        match *fn_output {
+            ty::FnConverging(ref mut ty) => {
+                *ty = self.tcx.erase_regions(ty);
+            },
+            ty::FnDiverging => {}
+        }
+    }
+
+    fn erase_regions_tys<'b, T>(&mut self, tys: T)
+        where T: Iterator<Item = &'b mut ty::Ty<'tcx>>,
+              'tcx: 'b
+    {
+        for ty in tys {
+            *ty = self.tcx.erase_regions(ty);
+        }
+    }
+}
index bee6d4d7ddda8f77d37851c6dd792038f451392d..9bec934143fa5350749393890924bf8e25ccbdfe 100644 (file)
@@ -9,10 +9,11 @@
 // except according to those terms.
 
 pub mod simplify_cfg;
+pub mod erase_regions;
 mod util;
 
 use repr::Mir;
 
-pub trait MirPass {
-    fn run_on_mir(&mut self, mir: &mut Mir);
+pub trait MirPass<'tcx> {
+    fn run_on_mir(&mut self, mir: &mut Mir<'tcx>);
 }
index 71dd2f077fec20cb1e714503322cabe9213a8835..ee9dcbf12037ce7daf6b50135479050013640018 100644 (file)
@@ -120,8 +120,8 @@ fn simplify_branches(&self, mir: &mut Mir) -> bool {
     }
 }
 
-impl MirPass for SimplifyCfg {
-    fn run_on_mir(&mut self, mir: &mut Mir) {
+impl<'tcx> MirPass<'tcx> for SimplifyCfg {
+    fn run_on_mir(&mut self, mir: &mut Mir<'tcx>) {
         let mut changed = true;
         while changed {
             changed = self.simplify_branches(mir);
index 8c0d8b10bfe47a8f26d8de942530ed839f5277d0..9af5bb433185042ce86b315c0513fe8a748a33da 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use middle::ty::Ty;
+use middle::ty::{Ty, HasTypeFlags};
 use rustc::middle::const_eval::ConstVal;
 use rustc_mir::repr as mir;
 use trans::consts::{self, TrueConst};
@@ -63,6 +63,9 @@ pub fn trans_constval(&mut self,
                 unimplemented!()
             }
         };
+
+        assert!(!ty.has_erasable_regions());
+
         OperandRef {
             ty: ty,
             val: val
index ff80451d2b1665d379adab88b9051833cd83362c..1f39a2aa04870db8be0382779f95d1378f085bd9 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 use llvm::ValueRef;
-use rustc::middle::ty::{self, Ty};
+use rustc::middle::ty::{self, Ty, HasTypeFlags};
 use rustc_mir::repr as mir;
 use rustc_mir::tcx::LvalueTy;
 use trans::adt;
@@ -45,6 +45,7 @@ pub fn alloca<'bcx>(bcx: Block<'bcx, 'tcx>,
                         name: &str)
                         -> LvalueRef<'tcx>
     {
+        assert!(!ty.has_erasable_regions());
         let lltemp = base::alloc_ty(bcx, ty, name);
         LvalueRef::new_sized(lltemp, LvalueTy::from_ty(ty))
     }
index 63abdfe2dd9176c46fa3695e9c475936725817d7..75d7b574382b30c6b4ca9f8098a16546c19646d9 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 use llvm::ValueRef;
-use rustc::middle::ty::Ty;
+use rustc::middle::ty::{Ty, HasTypeFlags};
 use rustc_mir::repr as mir;
 use trans::base;
 use trans::common::{self, Block};
@@ -122,6 +122,9 @@ pub fn trans_operand(&mut self,
                     }
                     datum::ByRef => OperandValue::Ref(tr_lvalue.llval)
                 };
+
+                assert!(!ty.has_erasable_regions());
+
                 OperandRef {
                     val: val,
                     ty: ty
index f2dd155595ac46bb4bf7b5faa8741829458feadc..8ca64e866a044e2018f0f0f095063bb76b9f014f 100644 (file)
@@ -231,7 +231,7 @@ fn compile_program(input: &str, sysroot: PathBuf)
         driver::phase_3_run_analysis_passes(
             &sess, ast_map, &arenas, &id, MakeGlobMap::No, |tcx, mir_map, analysis| {
 
-            let trans = driver::phase_4_translate_to_llvm(tcx, &mir_map, analysis);
+            let trans = driver::phase_4_translate_to_llvm(tcx, mir_map, analysis);
 
             let crates = tcx.sess.cstore.get_used_crates(RequireDynamic);