about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc_trans/trans/base.rs5
-rw-r--r--src/librustc_trans/trans/build.rs9
-rw-r--r--src/librustc_trans/trans/cleanup.rs4
-rw-r--r--src/librustc_trans/trans/common.rs119
-rw-r--r--src/librustc_trans/trans/mir/block.rs199
-rw-r--r--src/librustc_trans/trans/mir/constant.rs15
-rw-r--r--src/librustc_trans/trans/mir/did.rs12
-rw-r--r--src/librustc_trans/trans/mir/lvalue.rs63
-rw-r--r--src/librustc_trans/trans/mir/mod.rs47
-rw-r--r--src/librustc_trans/trans/mir/operand.rs33
-rw-r--r--src/librustc_trans/trans/mir/rvalue.rs336
-rw-r--r--src/librustc_trans/trans/mir/statement.rs8
12 files changed, 515 insertions, 335 deletions
diff --git a/src/librustc_trans/trans/base.rs b/src/librustc_trans/trans/base.rs
index 2fc585c7c79..57e69a0efa9 100644
--- a/src/librustc_trans/trans/base.rs
+++ b/src/librustc_trans/trans/base.rs
@@ -988,7 +988,7 @@ pub fn wants_msvc_seh(sess: &Session) -> bool {
 }
 
 pub fn avoid_invoke(bcx: Block) -> bool {
-    bcx.sess().no_landing_pads() || bcx.lpad.borrow().is_some()
+    bcx.sess().no_landing_pads() || bcx.lpad().is_some()
 }
 
 pub fn need_invoke(bcx: Block) -> bool {
@@ -1616,6 +1616,7 @@ pub fn new_fn_ctxt<'a, 'tcx>(ccx: &'a CrateContext<'a, 'tcx>,
         param_substs: param_substs,
         span: sp,
         block_arena: block_arena,
+        lpad_arena: TypedArena::new(),
         ccx: ccx,
         debug_context: debug_context,
         scopes: RefCell::new(Vec::new()),
@@ -2003,7 +2004,7 @@ pub fn trans_closure<'a, 'b, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
     let mut bcx = init_function(&fcx, false, output_type);
 
     if attributes.iter().any(|item| item.check_name("rustc_mir")) {
-        mir::trans_mir(bcx);
+        mir::trans_mir(bcx.build());
         fcx.cleanup();
         return;
     }
diff --git a/src/librustc_trans/trans/build.rs b/src/librustc_trans/trans/build.rs
index e501855b5d5..ce541c8d411 100644
--- a/src/librustc_trans/trans/build.rs
+++ b/src/librustc_trans/trans/build.rs
@@ -150,8 +150,7 @@ pub fn Invoke(cx: Block,
            cx.val_to_string(fn_),
            args.iter().map(|a| cx.val_to_string(*a)).collect::<Vec<String>>().join(", "));
     debug_loc.apply(cx.fcx);
-    let lpad = cx.lpad.borrow();
-    let bundle = lpad.as_ref().and_then(|b| b.bundle());
+    let bundle = cx.lpad().and_then(|b| b.bundle());
     B(cx).invoke(fn_, args, then, catch, bundle, attributes)
 }
 
@@ -916,8 +915,7 @@ pub fn Call(cx: Block,
         return _UndefReturn(cx, fn_);
     }
     debug_loc.apply(cx.fcx);
-    let lpad = cx.lpad.borrow();
-    let bundle = lpad.as_ref().and_then(|b| b.bundle());
+    let bundle = cx.lpad.get().and_then(|b| b.bundle());
     B(cx).call(fn_, args, bundle, attributes)
 }
 
@@ -932,8 +930,7 @@ pub fn CallWithConv(cx: Block,
         return _UndefReturn(cx, fn_);
     }
     debug_loc.apply(cx.fcx);
-    let lpad = cx.lpad.borrow();
-    let bundle = lpad.as_ref().and_then(|b| b.bundle());
+    let bundle = cx.lpad.get().and_then(|b| b.bundle());
     B(cx).call_with_conv(fn_, args, conv, bundle, attributes)
 }
 
diff --git a/src/librustc_trans/trans/cleanup.rs b/src/librustc_trans/trans/cleanup.rs
index 7c98868dfe7..683d5e0ead4 100644
--- a/src/librustc_trans/trans/cleanup.rs
+++ b/src/librustc_trans/trans/cleanup.rs
@@ -1054,11 +1054,11 @@ impl EarlyExitLabel {
         match *self {
             UnwindExit(UnwindKind::CleanupPad(..)) => {
                 let pad = build::CleanupPad(bcx, None, &[]);
-                *bcx.lpad.borrow_mut() = Some(LandingPad::msvc(pad));
+                bcx.lpad.set(Some(bcx.fcx.lpad_arena.alloc(LandingPad::msvc(pad))));
                 UnwindExit(UnwindKind::CleanupPad(pad))
             }
             UnwindExit(UnwindKind::LandingPad) => {
-                *bcx.lpad.borrow_mut() = Some(LandingPad::gnu());
+                bcx.lpad.set(Some(bcx.fcx.lpad_arena.alloc(LandingPad::gnu())));
                 *self
             }
             label => label,
diff --git a/src/librustc_trans/trans/common.rs b/src/librustc_trans/trans/common.rs
index 303fc17ce81..ec33046e5d9 100644
--- a/src/librustc_trans/trans/common.rs
+++ b/src/librustc_trans/trans/common.rs
@@ -26,6 +26,7 @@ use middle::lang_items::LangItem;
 use middle::subst::{self, Substs};
 use trans::base;
 use trans::build;
+use trans::builder::Builder;
 use trans::callee;
 use trans::cleanup;
 use trans::consts;
@@ -45,6 +46,7 @@ use util::nodemap::{FnvHashMap, NodeMap};
 
 use arena::TypedArena;
 use libc::{c_uint, c_char};
+use std::ops::Deref;
 use std::ffi::CString;
 use std::cell::{Cell, RefCell};
 use std::vec::Vec;
@@ -365,6 +367,9 @@ pub struct FunctionContext<'a, 'tcx: 'a> {
     // The arena that blocks are allocated from.
     pub block_arena: &'a TypedArena<BlockS<'a, 'tcx>>,
 
+    // The arena that landing pads are allocated from.
+    pub lpad_arena: TypedArena<LandingPad>,
+
     // This function's enclosing crate context.
     pub ccx: &'a CrateContext<'a, 'tcx>,
 
@@ -582,7 +587,7 @@ pub struct BlockS<'blk, 'tcx: 'blk> {
 
     // If this block part of a landing pad, then this is `Some` indicating what
     // kind of landing pad its in, otherwise this is none.
-    pub lpad: RefCell<Option<LandingPad>>,
+    pub lpad: Cell<Option<&'blk LandingPad>>,
 
     // AST node-id associated with this block, if any. Used for
     // debugging purposes only.
@@ -604,7 +609,7 @@ impl<'blk, 'tcx> BlockS<'blk, 'tcx> {
             llbb: llbb,
             terminated: Cell::new(false),
             unreachable: Cell::new(false),
-            lpad: RefCell::new(None),
+            lpad: Cell::new(None),
             opt_node_id: opt_node_id,
             fcx: fcx
         })
@@ -613,11 +618,18 @@ impl<'blk, 'tcx> BlockS<'blk, 'tcx> {
     pub fn ccx(&self) -> &'blk CrateContext<'blk, 'tcx> {
         self.fcx.ccx
     }
+    pub fn fcx(&self) -> &'blk FunctionContext<'blk, 'tcx> {
+        self.fcx
+    }
     pub fn tcx(&self) -> &'blk ty::ctxt<'tcx> {
         self.fcx.ccx.tcx()
     }
     pub fn sess(&self) -> &'blk Session { self.fcx.ccx.sess() }
 
+    pub fn lpad(&self) -> Option<&'blk LandingPad> {
+        self.lpad.get()
+    }
+
     pub fn mir(&self) -> &'blk Mir<'tcx> {
         self.fcx.mir()
     }
@@ -659,6 +671,109 @@ impl<'blk, 'tcx> BlockS<'blk, 'tcx> {
                                          self.fcx.param_substs,
                                          value)
     }
+
+    pub fn build(&'blk self) -> BlockAndBuilder<'blk, 'tcx> {
+        BlockAndBuilder::new(self, OwnedBuilder::new_with_ccx(self.ccx()))
+    }
+}
+
+pub struct OwnedBuilder<'blk, 'tcx: 'blk> {
+    builder: Builder<'blk, 'tcx>
+}
+
+impl<'blk, 'tcx> OwnedBuilder<'blk, 'tcx> {
+    pub fn new_with_ccx(ccx: &'blk CrateContext<'blk, 'tcx>) -> Self {
+        // Create a fresh builder from the crate context.
+        let llbuilder = unsafe {
+            llvm::LLVMCreateBuilderInContext(ccx.llcx())
+        };
+        OwnedBuilder {
+            builder: Builder {
+                llbuilder: llbuilder,
+                ccx: ccx,
+            }
+        }
+    }
+}
+
+impl<'blk, 'tcx> Drop for OwnedBuilder<'blk, 'tcx> {
+    fn drop(&mut self) {
+        unsafe {
+            llvm::LLVMDisposeBuilder(self.builder.llbuilder);
+        }
+    }
+}
+
+pub struct BlockAndBuilder<'blk, 'tcx: 'blk> {
+    bcx: Block<'blk, 'tcx>,
+    owned_builder: OwnedBuilder<'blk, 'tcx>,
+}
+
+impl<'blk, 'tcx> BlockAndBuilder<'blk, 'tcx> {
+    pub fn new(bcx: Block<'blk, 'tcx>, owned_builder: OwnedBuilder<'blk, 'tcx>) -> Self {
+        // Set the builder's position to this block's end.
+        owned_builder.builder.position_at_end(bcx.llbb);
+        BlockAndBuilder {
+            bcx: bcx,
+            owned_builder: owned_builder,
+        }
+    }
+
+    pub fn with_block<F, R>(&self, f: F) -> R
+        where F: FnOnce(Block<'blk, 'tcx>) -> R
+    {
+        let result = f(self.bcx);
+        self.position_at_end(self.bcx.llbb);
+        result
+    }
+
+    pub fn map_block<F>(self, f: F) -> Self
+        where F: FnOnce(Block<'blk, 'tcx>) -> Block<'blk, 'tcx>
+    {
+        let BlockAndBuilder { bcx, owned_builder } = self;
+        let bcx = f(bcx);
+        BlockAndBuilder::new(bcx, owned_builder)
+    }
+
+    // Methods delegated to bcx
+
+    pub fn ccx(&self) -> &'blk CrateContext<'blk, 'tcx> {
+        self.bcx.ccx()
+    }
+    pub fn fcx(&self) -> &'blk FunctionContext<'blk, 'tcx> {
+        self.bcx.fcx()
+    }
+    pub fn tcx(&self) -> &'blk ty::ctxt<'tcx> {
+        self.bcx.tcx()
+    }
+    pub fn sess(&self) -> &'blk Session {
+        self.bcx.sess()
+    }
+
+    pub fn llbb(&self) -> BasicBlockRef {
+        self.bcx.llbb
+    }
+
+    pub fn mir(&self) -> &'blk Mir<'tcx> {
+        self.bcx.mir()
+    }
+
+    pub fn val_to_string(&self, val: ValueRef) -> String {
+        self.bcx.val_to_string(val)
+    }
+
+    pub fn monomorphize<T>(&self, value: &T) -> T
+        where T: TypeFoldable<'tcx>
+    {
+        self.bcx.monomorphize(value)
+    }
+}
+
+impl<'blk, 'tcx> Deref for BlockAndBuilder<'blk, 'tcx> {
+    type Target = Builder<'blk, 'tcx>;
+    fn deref(&self) -> &Self::Target {
+        &self.owned_builder.builder
+    }
 }
 
 /// A structure representing an active landing pad for the duration of a basic
diff --git a/src/librustc_trans/trans/mir/block.rs b/src/librustc_trans/trans/mir/block.rs
index 5be585c4189..b3b8214a9a7 100644
--- a/src/librustc_trans/trans/mir/block.rs
+++ b/src/librustc_trans/trans/mir/block.rs
@@ -16,7 +16,7 @@ use trans::adt;
 use trans::attributes;
 use trans::base;
 use trans::build;
-use trans::common::{self, Block, LandingPad};
+use trans::common::{self, Block, BlockAndBuilder};
 use trans::debuginfo::DebugLoc;
 use trans::Disr;
 use trans::foreign;
@@ -42,94 +42,98 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
 
         match *data.terminator() {
             mir::Terminator::Goto { target } => {
-                build::Br(bcx, self.llblock(target), DebugLoc::None)
+                bcx.br(self.llblock(target));
             }
 
             mir::Terminator::If { ref cond, targets: (true_bb, false_bb) } => {
-                let cond = self.trans_operand(bcx, cond);
+                let cond = self.trans_operand(&bcx, cond);
                 let lltrue = self.llblock(true_bb);
                 let llfalse = self.llblock(false_bb);
-                build::CondBr(bcx, cond.immediate(), lltrue, llfalse, DebugLoc::None);
+                bcx.cond_br(cond.immediate(), lltrue, llfalse);
             }
 
             mir::Terminator::Switch { ref discr, ref adt_def, ref targets } => {
-                let discr_lvalue = self.trans_lvalue(bcx, discr);
+                let discr_lvalue = self.trans_lvalue(&bcx, discr);
                 let ty = discr_lvalue.ty.to_ty(bcx.tcx());
                 let repr = adt::represent_type(bcx.ccx(), ty);
-                let discr = adt::trans_get_discr(bcx, &repr, discr_lvalue.llval,
-                                                 None, true);
+                let discr = bcx.with_block(|bcx|
+                    adt::trans_get_discr(bcx, &repr, discr_lvalue.llval, None, true)
+                );
 
                 // The else branch of the Switch can't be hit, so branch to an unreachable
                 // instruction so LLVM knows that
                 let unreachable_blk = self.unreachable_block();
-                let switch = build::Switch(bcx, discr, unreachable_blk.llbb, targets.len());
+                let switch = bcx.switch(discr, unreachable_blk.llbb, targets.len());
                 assert_eq!(adt_def.variants.len(), targets.len());
                 for (adt_variant, target) in adt_def.variants.iter().zip(targets) {
-                    let llval = adt::trans_case(bcx, &*repr, Disr::from(adt_variant.disr_val));
+                    let llval = bcx.with_block(|bcx|
+                        adt::trans_case(bcx, &*repr, Disr::from(adt_variant.disr_val))
+                    );
                     let llbb = self.llblock(*target);
-
                     build::AddCase(switch, llval, llbb)
                 }
             }
 
             mir::Terminator::SwitchInt { ref discr, switch_ty, ref values, ref targets } => {
                 let (otherwise, targets) = targets.split_last().unwrap();
-                let discr = build::Load(bcx, self.trans_lvalue(bcx, discr).llval);
-                let switch = build::Switch(bcx, discr, self.llblock(*otherwise), values.len());
+                let discr = bcx.load(self.trans_lvalue(&bcx, discr).llval);
+                let switch = bcx.switch(discr, self.llblock(*otherwise), values.len());
                 for (value, target) in values.iter().zip(targets) {
-                    let llval = self.trans_constval(bcx, value, switch_ty).immediate();
+                    let llval = self.trans_constval(&bcx, value, switch_ty).immediate();
                     let llbb = self.llblock(*target);
                     build::AddCase(switch, llval, llbb)
                 }
             }
 
             mir::Terminator::Resume => {
-                let ps = self.get_personality_slot(bcx);
-                let lp = build::Load(bcx, ps);
-                base::call_lifetime_end(bcx, ps);
-                base::trans_unwind_resume(bcx, lp);
+                let ps = self.get_personality_slot(&bcx);
+                let lp = bcx.load(ps);
+                bcx.with_block(|bcx| {
+                    base::call_lifetime_end(bcx, ps);
+                    base::trans_unwind_resume(bcx, lp);
+                });
             }
 
             mir::Terminator::Return => {
                 let return_ty = bcx.monomorphize(&self.mir.return_ty);
-                base::build_return_block(bcx.fcx, bcx, return_ty, DebugLoc::None);
+                bcx.with_block(|bcx| {
+                    base::build_return_block(bcx.fcx, bcx, return_ty, DebugLoc::None);
+                })
             }
 
             mir::Terminator::Drop { ref value, target, unwind } => {
-                let lvalue = self.trans_lvalue(bcx, value);
+                let lvalue = self.trans_lvalue(&bcx, value);
                 let ty = lvalue.ty.to_ty(bcx.tcx());
                 // Double check for necessity to drop
                 if !glue::type_needs_drop(bcx.tcx(), ty) {
-                    build::Br(bcx, self.llblock(target), DebugLoc::None);
+                    bcx.br(self.llblock(target));
                     return;
                 }
                 let drop_fn = glue::get_drop_glue(bcx.ccx(), ty);
                 let drop_ty = glue::get_drop_glue_type(bcx.ccx(), ty);
                 let llvalue = if drop_ty != ty {
-                    build::PointerCast(bcx, lvalue.llval,
-                                       type_of::type_of(bcx.ccx(), drop_ty).ptr_to())
+                    bcx.pointercast(lvalue.llval, type_of::type_of(bcx.ccx(), drop_ty).ptr_to())
                 } else {
                     lvalue.llval
                 };
                 if let Some(unwind) = unwind {
                     let uwbcx = self.bcx(unwind);
                     let unwind = self.make_landing_pad(uwbcx);
-                    build::Invoke(bcx,
-                                  drop_fn,
-                                  &[llvalue],
-                                  self.llblock(target),
-                                  unwind.llbb,
-                                  None,
-                                  DebugLoc::None);
+                    bcx.invoke(drop_fn,
+                               &[llvalue],
+                               self.llblock(target),
+                               unwind.llbb(),
+                               None,
+                               None);
                 } else {
-                    build::Call(bcx, drop_fn, &[llvalue], None, DebugLoc::None);
-                    build::Br(bcx, self.llblock(target), DebugLoc::None);
+                    bcx.call(drop_fn, &[llvalue], None, None);
+                    bcx.br(self.llblock(target));
                 }
             }
 
             mir::Terminator::Call { ref func, ref args, ref destination, ref cleanup } => {
                 // Create the callee. This will always be a fn ptr and hence a kind of scalar.
-                let callee = self.trans_operand(bcx, func);
+                let callee = self.trans_operand(&bcx, func);
                 let attrs = attributes::from_fn_type(bcx.ccx(), callee.ty);
                 let debugloc = DebugLoc::None;
                 // The arguments we'll be passing. Plus one to account for outptr, if used.
@@ -149,7 +153,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
 
                 // Prepare the return value destination
                 let (ret_dest_ty, must_copy_dest) = if let Some((ref d, _)) = *destination {
-                    let dest = self.trans_lvalue(bcx, d);
+                    let dest = self.trans_lvalue(&bcx, d);
                     let ret_ty = dest.ty.to_ty(bcx.tcx());
                     if !is_foreign && type_of::return_uses_outptr(bcx.ccx(), ret_ty) {
                         llargs.push(dest.llval);
@@ -163,7 +167,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
 
                 // Process the rest of the args.
                 for arg in args {
-                    let operand = self.trans_operand(bcx, arg);
+                    let operand = self.trans_operand(&bcx, arg);
                     match operand.val {
                         Ref(llval) | Immediate(llval) => llargs.push(llval),
                         FatPtr(b, e) => {
@@ -176,38 +180,37 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
                     }
                 }
 
+                let avoid_invoke = bcx.with_block(|bcx| base::avoid_invoke(bcx));
                 // Many different ways to call a function handled here
-                match (is_foreign, base::avoid_invoke(bcx), cleanup, destination) {
+                match (is_foreign, avoid_invoke, cleanup, destination) {
                     // The two cases below are the only ones to use LLVM’s `invoke`.
                     (false, false, &Some(cleanup), &None) => {
                         let cleanup = self.bcx(cleanup);
                         let landingpad = self.make_landing_pad(cleanup);
                         let unreachable_blk = self.unreachable_block();
-                        build::Invoke(bcx,
-                                      callee.immediate(),
-                                      &llargs[..],
-                                      unreachable_blk.llbb,
-                                      landingpad.llbb,
-                                      Some(attrs),
-                                      debugloc);
+                        bcx.invoke(callee.immediate(),
+                                   &llargs[..],
+                                   unreachable_blk.llbb,
+                                   landingpad.llbb(),
+                                   None,
+                                   Some(attrs));
                     },
                     (false, false, &Some(cleanup), &Some((_, success))) => {
                         let cleanup = self.bcx(cleanup);
                         let landingpad = self.make_landing_pad(cleanup);
                         let (target, postinvoke) = if must_copy_dest {
-                            (bcx.fcx.new_block("", None), Some(self.bcx(success)))
+                            (bcx.fcx().new_block("", None).build(), Some(self.bcx(success)))
                         } else {
                             (self.bcx(success), None)
                         };
-                        let invokeret = build::Invoke(bcx,
-                                                      callee.immediate(),
-                                                      &llargs[..],
-                                                      target.llbb,
-                                                      landingpad.llbb,
-                                                      Some(attrs),
-                                                      debugloc);
+                        let invokeret = bcx.invoke(callee.immediate(),
+                                                   &llargs[..],
+                                                   target.llbb(),
+                                                   landingpad.llbb(),
+                                                   None,
+                                                   Some(attrs));
                         if let Some(postinvoketarget) = postinvoke {
-                            // We translate the copy into a temoprary block. The temporary block is
+                            // We translate the copy into a temporary block. The temporary block is
                             // necessary because the current block has already been terminated (by
                             // `invoke`) and we cannot really translate into the target block
                             // because:
@@ -233,40 +236,45 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
                             //                               ; immediate precedesors
                             let (ret_dest, ret_ty) = ret_dest_ty
                                 .expect("return destination and type not set");
-                            base::store_ty(target, invokeret, ret_dest.llval, ret_ty);
-                            build::Br(target, postinvoketarget.llbb, debugloc);
+                            target.with_block(|target| {
+                                base::store_ty(target, invokeret, ret_dest.llval, ret_ty);
+                            });
+                            target.br(postinvoketarget.llbb());
                         }
                     },
                     (false, _, _, &None) => {
-                        build::Call(bcx, callee.immediate(), &llargs[..], Some(attrs), debugloc);
-                        build::Unreachable(bcx);
+                        bcx.call(callee.immediate(), &llargs[..], None, Some(attrs));
+                        bcx.unreachable();
                     }
                     (false, _, _, &Some((_, target))) => {
-                        let llret = build::Call(bcx,
-                                                callee.immediate(),
-                                                &llargs[..],
-                                                Some(attrs),
-                                                debugloc);
+                        let llret = bcx.call(callee.immediate(),
+                                             &llargs[..],
+                                             None,
+                                             Some(attrs));
                         if must_copy_dest {
                             let (ret_dest, ret_ty) = ret_dest_ty
                                 .expect("return destination and type not set");
-                            base::store_ty(bcx, llret, ret_dest.llval, ret_ty);
+                            bcx.with_block(|bcx| {
+                                base::store_ty(bcx, llret, ret_dest.llval, ret_ty);
+                            });
                         }
-                        build::Br(bcx, self.llblock(target), debugloc);
+                        bcx.br(self.llblock(target));
                     }
                     // Foreign functions
                     (true, _, _, destination) => {
                         let (dest, _) = ret_dest_ty
                             .expect("return destination is not set");
-                        bcx = foreign::trans_native_call(bcx,
-                                                   callee.ty,
-                                                   callee.immediate(),
-                                                   dest.llval,
-                                                   &llargs[..],
-                                                   arg_tys,
-                                                   debugloc);
+                        bcx = bcx.map_block(|bcx| {
+                            foreign::trans_native_call(bcx,
+                                                       callee.ty,
+                                                       callee.immediate(),
+                                                       dest.llval,
+                                                       &llargs[..],
+                                                       arg_tys,
+                                                       debugloc)
+                        });
                         if let Some((_, target)) = *destination {
-                            build::Br(bcx, self.llblock(target), debugloc);
+                            bcx.br(self.llblock(target));
                         }
                     },
                 }
@@ -274,48 +282,49 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
         }
     }
 
-    fn get_personality_slot(&mut self, bcx: Block<'bcx, 'tcx>) -> ValueRef {
+    fn get_personality_slot(&mut self, bcx: &BlockAndBuilder<'bcx, 'tcx>) -> ValueRef {
         let ccx = bcx.ccx();
         if let Some(slot) = self.llpersonalityslot {
             slot
         } else {
             let llretty = Type::struct_(ccx, &[Type::i8p(ccx), Type::i32(ccx)], false);
-            let slot = base::alloca(bcx, llretty, "personalityslot");
-            self.llpersonalityslot = Some(slot);
-            base::call_lifetime_start(bcx, slot);
-            slot
+            bcx.with_block(|bcx| {
+                let slot = base::alloca(bcx, llretty, "personalityslot");
+                self.llpersonalityslot = Some(slot);
+                base::call_lifetime_start(bcx, slot);
+                slot
+            })
         }
     }
 
-    fn make_landing_pad(&mut self, cleanup: Block<'bcx, 'tcx>) -> Block<'bcx, 'tcx> {
-        let bcx = cleanup.fcx.new_block("cleanup", None);
+    fn make_landing_pad(&mut self,
+                        cleanup: BlockAndBuilder<'bcx, 'tcx>)
+                        -> BlockAndBuilder<'bcx, 'tcx>
+    {
         // FIXME(#30941) this doesn't handle msvc-style exceptions
-        *bcx.lpad.borrow_mut() = Some(LandingPad::gnu());
+        let bcx = self.fcx.new_block("cleanup", None).build();
         let ccx = bcx.ccx();
-        let llpersonality = bcx.fcx.eh_personality();
+        let llpersonality = self.fcx.eh_personality();
         let llretty = Type::struct_(ccx, &[Type::i8p(ccx), Type::i32(ccx)], false);
-        let llretval = build::LandingPad(bcx, llretty, llpersonality, 1);
-        build::SetCleanup(bcx, llretval);
-        let slot = self.get_personality_slot(bcx);
-        build::Store(bcx, llretval, slot);
-        build::Br(bcx, cleanup.llbb, DebugLoc::None);
+        let llretval = bcx.landing_pad(llretty, llpersonality, 1, self.fcx.llfn);
+        bcx.set_cleanup(llretval);
+        let slot = self.get_personality_slot(&bcx);
+        bcx.store(llretval, slot);
+        bcx.br(cleanup.llbb());
         bcx
     }
 
     fn unreachable_block(&mut self) -> Block<'bcx, 'tcx> {
-        match self.unreachable_block {
-            Some(b) => b,
-            None => {
-                let bl = self.fcx.new_block("unreachable", None);
-                build::Unreachable(bl);
-                self.unreachable_block = Some(bl);
-                bl
-            }
-        }
+        self.unreachable_block.unwrap_or_else(|| {
+            let bl = self.fcx.new_block("unreachable", None);
+            bl.build().unreachable();
+            self.unreachable_block = Some(bl);
+            bl
+        })
     }
 
-    fn bcx(&self, bb: mir::BasicBlock) -> Block<'bcx, 'tcx> {
-        self.blocks[bb.index()]
+    fn bcx(&self, bb: mir::BasicBlock) -> BlockAndBuilder<'bcx, 'tcx> {
+        self.blocks[bb.index()].build()
     }
 
     fn llblock(&self, bb: mir::BasicBlock) -> BasicBlockRef {
diff --git a/src/librustc_trans/trans/mir/constant.rs b/src/librustc_trans/trans/mir/constant.rs
index 3b763599f77..7f03069385f 100644
--- a/src/librustc_trans/trans/mir/constant.rs
+++ b/src/librustc_trans/trans/mir/constant.rs
@@ -14,7 +14,8 @@ use middle::subst::Substs;
 use middle::ty::{Ty, TypeFoldable};
 use rustc::middle::const_eval::ConstVal;
 use rustc::mir::repr as mir;
-use trans::common::{self, Block, C_bool, C_bytes, C_floating_f64, C_integral, C_str_slice};
+use trans::common::{self, BlockAndBuilder, C_bool, C_bytes, C_floating_f64, C_integral,
+                    C_str_slice};
 use trans::consts;
 use trans::expr;
 use trans::type_of;
@@ -25,13 +26,13 @@ use super::MirContext;
 
 impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
     pub fn trans_constval(&mut self,
-                          bcx: Block<'bcx, 'tcx>,
+                          bcx: &BlockAndBuilder<'bcx, 'tcx>,
                           cv: &ConstVal,
                           ty: Ty<'tcx>)
                           -> OperandRef<'tcx>
     {
         let ccx = bcx.ccx();
-        let val = self.trans_constval_inner(bcx, cv, ty, bcx.fcx.param_substs);
+        let val = self.trans_constval_inner(bcx, cv, ty, bcx.fcx().param_substs);
         let val = if common::type_is_immediate(ccx, ty) {
             OperandValue::Immediate(val)
         } else if common::type_is_fat_ptr(bcx.tcx(), ty) {
@@ -52,7 +53,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
 
     /// Translate ConstVal into a bare LLVM ValueRef.
     fn trans_constval_inner(&mut self,
-                            bcx: common::Block<'bcx, 'tcx>,
+                            bcx: &BlockAndBuilder<'bcx, 'tcx>,
                             cv: &ConstVal,
                             ty: Ty<'tcx>,
                             param_substs: &'tcx Substs<'tcx>)
@@ -70,7 +71,9 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
             ConstVal::Struct(id) | ConstVal::Tuple(id) |
             ConstVal::Array(id, _) | ConstVal::Repeat(id, _) => {
                 let expr = bcx.tcx().map.expect_expr(id);
-                expr::trans(bcx, expr).datum.val
+                bcx.with_block(|bcx| {
+                    expr::trans(bcx, expr).datum.val
+                })
             },
             ConstVal::Function(did) =>
                 self.trans_fn_ref(bcx, ty, param_substs, did).immediate()
@@ -78,7 +81,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
     }
 
     pub fn trans_constant(&mut self,
-                          bcx: Block<'bcx, 'tcx>,
+                          bcx: &BlockAndBuilder<'bcx, 'tcx>,
                           constant: &mir::Constant<'tcx>)
                           -> OperandRef<'tcx>
     {
diff --git a/src/librustc_trans/trans/mir/did.rs b/src/librustc_trans/trans/mir/did.rs
index e433776bef2..36bbbce7ec4 100644
--- a/src/librustc_trans/trans/mir/did.rs
+++ b/src/librustc_trans/trans/mir/did.rs
@@ -18,7 +18,7 @@ use rustc::middle::const_eval;
 use rustc::middle::def_id::DefId;
 use rustc::middle::traits;
 use rustc::mir::repr::ItemKind;
-use trans::common::{Block, fulfill_obligation};
+use trans::common::{BlockAndBuilder, fulfill_obligation};
 use trans::base;
 use trans::closure;
 use trans::expr;
@@ -32,7 +32,7 @@ use super::operand::{OperandRef, OperandValue};
 impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
     /// Translate reference to item.
     pub fn trans_item_ref(&mut self,
-                          bcx: Block<'bcx, 'tcx>,
+                          bcx: &BlockAndBuilder<'bcx, 'tcx>,
                           ty: Ty<'tcx>,
                           kind: ItemKind,
                           substs: &'tcx Substs<'tcx>,
@@ -53,7 +53,9 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
                             .expect("def was const, but lookup_const_by_id failed");
                 // FIXME: this is falling back to translating from HIR. This is not easy to fix,
                 // because we would have somehow adapt const_eval to work on MIR rather than HIR.
-                let d = expr::trans(bcx, expr);
+                let d = bcx.with_block(|bcx| {
+                    expr::trans(bcx, expr)
+                });
                 OperandRef::from_rvalue_datum(d.datum.to_rvalue_datum(d.bcx, "").datum)
             }
         }
@@ -66,7 +68,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
     ///
     /// This is an adaptation of callee::trans_fn_ref_with_substs.
     pub fn trans_fn_ref(&mut self,
-                        bcx: Block<'bcx, 'tcx>,
+                        bcx: &BlockAndBuilder<'bcx, 'tcx>,
                         ty: Ty<'tcx>,
                         substs: &'tcx Substs<'tcx>,
                         did: DefId)
@@ -101,7 +103,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
     ///
     /// This is an adaptation of meth::trans_static_method_callee
     pub fn trans_trait_method(&mut self,
-                              bcx: Block<'bcx, 'tcx>,
+                              bcx: &BlockAndBuilder<'bcx, 'tcx>,
                               ty: Ty<'tcx>,
                               method_id: DefId,
                               trait_id: DefId,
diff --git a/src/librustc_trans/trans/mir/lvalue.rs b/src/librustc_trans/trans/mir/lvalue.rs
index d994f1ea7b0..002584f51c6 100644
--- a/src/librustc_trans/trans/mir/lvalue.rs
+++ b/src/librustc_trans/trans/mir/lvalue.rs
@@ -14,9 +14,7 @@ use rustc::mir::repr as mir;
 use rustc::mir::tcx::LvalueTy;
 use trans::adt;
 use trans::base;
-use trans::build;
-use trans::common::{self, Block};
-use trans::debuginfo::DebugLoc;
+use trans::common::{self, BlockAndBuilder};
 use trans::machine;
 use trans::type_of;
 use llvm;
@@ -43,20 +41,20 @@ impl<'tcx> LvalueRef<'tcx> {
         LvalueRef { llval: llval, llextra: ptr::null_mut(), ty: lvalue_ty }
     }
 
-    pub fn alloca<'bcx>(bcx: Block<'bcx, 'tcx>,
+    pub fn alloca<'bcx>(bcx: &BlockAndBuilder<'bcx, 'tcx>,
                         ty: Ty<'tcx>,
                         name: &str)
                         -> LvalueRef<'tcx>
     {
         assert!(!ty.has_erasable_regions());
-        let lltemp = base::alloc_ty(bcx, ty, name);
+        let lltemp = bcx.with_block(|bcx| base::alloc_ty(bcx, ty, name));
         LvalueRef::new_sized(lltemp, LvalueTy::from_ty(ty))
     }
 }
 
 impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
     pub fn lvalue_len(&mut self,
-                      bcx: Block<'bcx, 'tcx>,
+                      bcx: &BlockAndBuilder<'bcx, 'tcx>,
                       lvalue: LvalueRef<'tcx>)
                       -> ValueRef {
         match lvalue.ty.to_ty(bcx.tcx()).sty {
@@ -70,13 +68,13 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
     }
 
     pub fn trans_lvalue(&mut self,
-                        bcx: Block<'bcx, 'tcx>,
+                        bcx: &BlockAndBuilder<'bcx, 'tcx>,
                         lvalue: &mir::Lvalue<'tcx>)
                         -> LvalueRef<'tcx> {
         debug!("trans_lvalue(lvalue={:?})", lvalue);
 
-        let fcx = bcx.fcx;
-        let ccx = fcx.ccx;
+        let fcx = bcx.fcx();
+        let ccx = bcx.ccx();
         let tcx = bcx.tcx();
         match *lvalue {
             mir::Lvalue::Var(index) => self.vars[index as usize],
@@ -97,7 +95,9 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
                 let fn_return_ty = bcx.monomorphize(&self.mir.return_ty);
                 let return_ty = fn_return_ty.unwrap();
                 let llval = if !common::return_type_is_void(bcx.ccx(), return_ty) {
-                    fcx.get_ret_slot(bcx, fn_return_ty, "")
+                    bcx.with_block(|bcx| {
+                        fcx.get_ret_slot(bcx, fn_return_ty, "")
+                    })
                 } else {
                     // This is a void return; that is, there’s no place to store the value and
                     // there cannot really be one (or storing into it doesn’t make sense, anyway).
@@ -117,12 +117,14 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
                 let (llprojected, llextra) = match projection.elem {
                     mir::ProjectionElem::Deref => {
                         let base_ty = tr_base.ty.to_ty(tcx);
-                        if common::type_is_sized(tcx, projected_ty.to_ty(tcx)) {
-                            (base::load_ty(bcx, tr_base.llval, base_ty),
-                             ptr::null_mut())
-                        } else {
-                            base::load_fat_ptr(bcx, tr_base.llval, base_ty)
-                        }
+                        bcx.with_block(|bcx| {
+                            if common::type_is_sized(tcx, projected_ty.to_ty(tcx)) {
+                                (base::load_ty(bcx, tr_base.llval, base_ty),
+                                 ptr::null_mut())
+                            } else {
+                                base::load_fat_ptr(bcx, tr_base.llval, base_ty)
+                            }
+                        })
                     }
                     mir::ProjectionElem::Field(ref field) => {
                         let base_ty = tr_base.ty.to_ty(tcx);
@@ -138,18 +140,21 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
                         } else {
                             adt::MaybeSizedValue::unsized_(tr_base.llval, tr_base.llextra)
                         };
-                        (adt::trans_field_ptr(bcx, &base_repr, base, Disr(discr), field.index()),
-                         if is_sized {
-                             ptr::null_mut()
-                         } else {
-                             tr_base.llextra
-                         })
+                        let llprojected = bcx.with_block(|bcx| {
+                            adt::trans_field_ptr(bcx, &base_repr, base, Disr(discr), field.index())
+                        });
+                        let llextra = if is_sized {
+                            ptr::null_mut()
+                        } else {
+                            tr_base.llextra
+                        };
+                        (llprojected, llextra)
                     }
                     mir::ProjectionElem::Index(ref index) => {
                         let index = self.trans_operand(bcx, index);
                         let llindex = self.prepare_index(bcx, index.immediate());
                         let zero = common::C_uint(bcx.ccx(), 0u64);
-                        (build::InBoundsGEP(bcx, tr_base.llval, &[zero, llindex]),
+                        (bcx.inbounds_gep(tr_base.llval, &[zero, llindex]),
                          ptr::null_mut())
                     }
                     mir::ProjectionElem::ConstantIndex { offset,
@@ -158,7 +163,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
                         let lloffset = common::C_u32(bcx.ccx(), offset);
                         let llindex = self.prepare_index(bcx, lloffset);
                         let zero = common::C_uint(bcx.ccx(), 0u64);
-                        (build::InBoundsGEP(bcx, tr_base.llval, &[zero, llindex]),
+                        (bcx.inbounds_gep(tr_base.llval, &[zero, llindex]),
                          ptr::null_mut())
                     }
                     mir::ProjectionElem::ConstantIndex { offset,
@@ -166,10 +171,10 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
                                                          min_length: _ } => {
                         let lloffset = common::C_u32(bcx.ccx(), offset);
                         let lllen = self.lvalue_len(bcx, tr_base);
-                        let llindex = build::Sub(bcx, lllen, lloffset, DebugLoc::None);
+                        let llindex = bcx.sub(lllen, lloffset);
                         let llindex = self.prepare_index(bcx, llindex);
                         let zero = common::C_uint(bcx.ccx(), 0u64);
-                        (build::InBoundsGEP(bcx, tr_base.llval, &[zero, llindex]),
+                        (bcx.inbounds_gep(tr_base.llval, &[zero, llindex]),
                          ptr::null_mut())
                     }
                     mir::ProjectionElem::Downcast(..) => {
@@ -190,7 +195,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
     ///
     /// nmatsakis: is this still necessary? Not sure.
     fn prepare_index(&mut self,
-                     bcx: Block<'bcx, 'tcx>,
+                     bcx: &BlockAndBuilder<'bcx, 'tcx>,
                      llindex: ValueRef)
                      -> ValueRef
     {
@@ -198,9 +203,9 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
         let index_size = machine::llbitsize_of_real(bcx.ccx(), common::val_ty(llindex));
         let int_size = machine::llbitsize_of_real(bcx.ccx(), ccx.int_type());
         if index_size < int_size {
-            build::ZExt(bcx, llindex, ccx.int_type())
+            bcx.zext(llindex, ccx.int_type())
         } else if index_size > int_size {
-            build::Trunc(bcx, llindex, ccx.int_type())
+            bcx.trunc(llindex, ccx.int_type())
         } else {
             llindex
         }
diff --git a/src/librustc_trans/trans/mir/mod.rs b/src/librustc_trans/trans/mir/mod.rs
index b19ecc45a4e..972340e7f5a 100644
--- a/src/librustc_trans/trans/mir/mod.rs
+++ b/src/librustc_trans/trans/mir/mod.rs
@@ -13,9 +13,7 @@ use llvm::{self, ValueRef};
 use rustc::mir::repr as mir;
 use rustc::mir::tcx::LvalueTy;
 use trans::base;
-use trans::build;
-use trans::common::{self, Block, LandingPad};
-use trans::debuginfo::DebugLoc;
+use trans::common::{self, Block, BlockAndBuilder};
 use trans::expr;
 use trans::type_of;
 
@@ -79,26 +77,28 @@ enum TempRef<'tcx> {
 
 ///////////////////////////////////////////////////////////////////////////
 
-pub fn trans_mir<'bcx, 'tcx>(bcx: Block<'bcx, 'tcx>) {
-    let fcx = bcx.fcx;
+pub fn trans_mir<'bcx, 'tcx>(bcx: BlockAndBuilder<'bcx, 'tcx>) {
+    let fcx = bcx.fcx();
     let mir = bcx.mir();
 
     let mir_blocks = bcx.mir().all_basic_blocks();
 
     // Analyze the temps to determine which must be lvalues
     // FIXME
-    let lvalue_temps = analyze::lvalue_temps(bcx, mir);
+    let lvalue_temps = bcx.with_block(|bcx| {
+      analyze::lvalue_temps(bcx, mir)
+    });
 
     // Allocate variable and temp allocas
     let vars = mir.var_decls.iter()
                             .map(|decl| (bcx.monomorphize(&decl.ty), decl.name))
-                            .map(|(mty, name)| LvalueRef::alloca(bcx, mty, &name.as_str()))
+                            .map(|(mty, name)| LvalueRef::alloca(&bcx, mty, &name.as_str()))
                             .collect();
     let temps = mir.temp_decls.iter()
                               .map(|decl| bcx.monomorphize(&decl.ty))
                               .enumerate()
                               .map(|(i, mty)| if lvalue_temps.contains(i) {
-                                  TempRef::Lvalue(LvalueRef::alloca(bcx,
+                                  TempRef::Lvalue(LvalueRef::alloca(&bcx,
                                                                     mty,
                                                                     &format!("temp{:?}", i)))
                               } else {
@@ -108,24 +108,20 @@ pub fn trans_mir<'bcx, 'tcx>(bcx: Block<'bcx, 'tcx>) {
                                   TempRef::Operand(None)
                               })
                               .collect();
-    let args = arg_value_refs(bcx, mir);
+    let args = arg_value_refs(&bcx, mir);
 
     // Allocate a `Block` for every basic block
     let block_bcxs: Vec<Block<'bcx,'tcx>> =
         mir_blocks.iter()
                   .map(|&bb|{
-                      let bcx = fcx.new_block(&format!("{:?}", bb), None);
                       // FIXME(#30941) this doesn't handle msvc-style exceptions
-                      if mir.basic_block_data(bb).is_cleanup {
-                          *bcx.lpad.borrow_mut() = Some(LandingPad::gnu())
-                      }
-                      bcx
+                      fcx.new_block(&format!("{:?}", bb), None)
                   })
                   .collect();
 
     // Branch to the START block
     let start_bcx = block_bcxs[mir::START_BLOCK.index()];
-    build::Br(bcx, start_bcx.llbb, DebugLoc::None);
+    bcx.br(start_bcx.llbb);
 
     let mut mircx = MirContext {
         mir: mir,
@@ -147,11 +143,11 @@ pub fn trans_mir<'bcx, 'tcx>(bcx: Block<'bcx, 'tcx>) {
 /// Produce, for each argument, a `ValueRef` pointing at the
 /// argument's value. As arguments are lvalues, these are always
 /// indirect.
-fn arg_value_refs<'bcx, 'tcx>(bcx: Block<'bcx, 'tcx>,
+fn arg_value_refs<'bcx, 'tcx>(bcx: &BlockAndBuilder<'bcx, 'tcx>,
                               mir: &mir::Mir<'tcx>)
                               -> Vec<LvalueRef<'tcx>> {
     // FIXME tupled_args? I think I'd rather that mapping is done in MIR land though
-    let fcx = bcx.fcx;
+    let fcx = bcx.fcx();
     let tcx = bcx.tcx();
     let mut idx = fcx.arg_offset() as c_uint;
     mir.arg_decls
@@ -174,18 +170,23 @@ fn arg_value_refs<'bcx, 'tcx>(bcx: Block<'bcx, 'tcx>,
                let lldata = llvm::get_param(fcx.llfn, idx);
                let llextra = llvm::get_param(fcx.llfn, idx + 1);
                idx += 2;
-               let lltemp = base::alloc_ty(bcx, arg_ty, &format!("arg{}", arg_index));
-               build::Store(bcx, lldata, expr::get_dataptr(bcx, lltemp));
-               build::Store(bcx, llextra, expr::get_meta(bcx, lltemp));
+               let (lltemp, dataptr, meta) = bcx.with_block(|bcx| {
+                   let lltemp = base::alloc_ty(bcx, arg_ty, &format!("arg{}", arg_index));
+                   (lltemp, expr::get_dataptr(bcx, lltemp), expr::get_meta(bcx, lltemp))
+               });
+               bcx.store(lldata, dataptr);
+               bcx.store(llextra, meta);
                lltemp
            } else {
                // otherwise, arg is passed by value, so make a
                // temporary and store it there
                let llarg = llvm::get_param(fcx.llfn, idx);
                idx += 1;
-               let lltemp = base::alloc_ty(bcx, arg_ty, &format!("arg{}", arg_index));
-               base::store_ty(bcx, llarg, lltemp, arg_ty);
-               lltemp
+               bcx.with_block(|bcx| {
+                   let lltemp = base::alloc_ty(bcx, arg_ty, &format!("arg{}", arg_index));
+                   base::store_ty(bcx, llarg, lltemp, arg_ty);
+                   lltemp
+               })
            };
            LvalueRef::new_sized(llval, LvalueTy::from_ty(arg_ty))
        })
diff --git a/src/librustc_trans/trans/mir/operand.rs b/src/librustc_trans/trans/mir/operand.rs
index 114e78b05bd..d0eaaeef057 100644
--- a/src/librustc_trans/trans/mir/operand.rs
+++ b/src/librustc_trans/trans/mir/operand.rs
@@ -12,7 +12,7 @@ use llvm::ValueRef;
 use rustc::middle::ty::{Ty, TypeFoldable};
 use rustc::mir::repr as mir;
 use trans::base;
-use trans::common::{self, Block};
+use trans::common::{self, Block, BlockAndBuilder};
 use trans::datum;
 
 use super::{MirContext, TempRef};
@@ -37,8 +37,9 @@ pub enum OperandValue {
 ///
 /// NOTE: unless you know a value's type exactly, you should not
 /// generate LLVM opcodes acting on it and instead act via methods,
-/// to avoid nasty edge cases. In particular, using `build::Store`
-/// directly is sure to cause problems - use `store_operand` instead.
+/// to avoid nasty edge cases. In particular, using `Builder.store`
+/// directly is sure to cause problems -- use `MirContext.store_operand`
+/// instead.
 #[derive(Copy, Clone)]
 pub struct OperandRef<'tcx> {
     // The value.
@@ -58,7 +59,7 @@ impl<'tcx> OperandRef<'tcx> {
         }
     }
 
-    pub fn repr<'bcx>(self, bcx: Block<'bcx, 'tcx>) -> String {
+    pub fn repr<'bcx>(self, bcx: &BlockAndBuilder<'bcx, 'tcx>) -> String {
         match self.val {
             OperandValue::Ref(r) => {
                 format!("OperandRef(Ref({}) @ {:?})",
@@ -90,7 +91,7 @@ impl<'tcx> OperandRef<'tcx> {
 
 impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
     pub fn trans_operand(&mut self,
-                         bcx: Block<'bcx, 'tcx>,
+                         bcx: &BlockAndBuilder<'bcx, 'tcx>,
                          operand: &mir::Operand<'tcx>)
                          -> OperandRef<'tcx>
     {
@@ -124,10 +125,14 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
                        ty);
                 let val = match datum::appropriate_rvalue_mode(bcx.ccx(), ty) {
                     datum::ByValue => {
-                        OperandValue::Immediate(base::load_ty(bcx, tr_lvalue.llval, ty))
+                        bcx.with_block(|bcx| {
+                            OperandValue::Immediate(base::load_ty(bcx, tr_lvalue.llval, ty))
+                        })
                     }
                     datum::ByRef if common::type_is_fat_ptr(bcx.tcx(), ty) => {
-                        let (lldata, llextra) = base::load_fat_ptr(bcx, tr_lvalue.llval, ty);
+                        let (lldata, llextra) = bcx.with_block(|bcx| {
+                            base::load_fat_ptr(bcx, tr_lvalue.llval, ty)
+                        });
                         OperandValue::FatPtr(lldata, llextra)
                     }
                     datum::ByRef => OperandValue::Ref(tr_lvalue.llval)
@@ -148,7 +153,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
     }
 
     pub fn trans_operand_into(&mut self,
-                              bcx: Block<'bcx, 'tcx>,
+                              bcx: &BlockAndBuilder<'bcx, 'tcx>,
                               lldest: ValueRef,
                               operand: &mir::Operand<'tcx>)
     {
@@ -164,11 +169,21 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
     }
 
     pub fn store_operand(&mut self,
-                         bcx: Block<'bcx, 'tcx>,
+                         bcx: &BlockAndBuilder<'bcx, 'tcx>,
                          lldest: ValueRef,
                          operand: OperandRef<'tcx>)
     {
         debug!("store_operand: operand={}", operand.repr(bcx));
+        bcx.with_block(|bcx| {
+            self.store_operand_direct(bcx, lldest, operand)
+        })
+    }
+
+    pub fn store_operand_direct(&mut self,
+                                bcx: Block<'bcx, 'tcx>,
+                                lldest: ValueRef,
+                                operand: OperandRef<'tcx>)
+    {
         // Avoid generating stores of zero-sized values, because the only way to have a zero-sized
         // value is through `undef`, and store itself is useless.
         if common::type_is_zero_size(bcx.ccx(), operand.ty) {
diff --git a/src/librustc_trans/trans/mir/rvalue.rs b/src/librustc_trans/trans/mir/rvalue.rs
index e280eff34c8..ab0c299af05 100644
--- a/src/librustc_trans/trans/mir/rvalue.rs
+++ b/src/librustc_trans/trans/mir/rvalue.rs
@@ -15,8 +15,7 @@ use rustc::mir::repr as mir;
 
 use trans::asm;
 use trans::base;
-use trans::build;
-use trans::common::{self, Block, Result};
+use trans::common::{self, BlockAndBuilder, Result};
 use trans::debuginfo::DebugLoc;
 use trans::declare;
 use trans::expr;
@@ -33,10 +32,10 @@ use super::lvalue::LvalueRef;
 
 impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
     pub fn trans_rvalue(&mut self,
-                        bcx: Block<'bcx, 'tcx>,
+                        bcx: BlockAndBuilder<'bcx, 'tcx>,
                         dest: LvalueRef<'tcx>,
                         rvalue: &mir::Rvalue<'tcx>)
-                        -> Block<'bcx, 'tcx>
+                        -> BlockAndBuilder<'bcx, 'tcx>
     {
         debug!("trans_rvalue(dest.llval={}, rvalue={:?})",
                bcx.val_to_string(dest.llval),
@@ -44,7 +43,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
 
         match *rvalue {
             mir::Rvalue::Use(ref operand) => {
-                self.trans_operand_into(bcx, dest.llval, operand);
+                self.trans_operand_into(&bcx, dest.llval, operand);
                 bcx
             }
 
@@ -53,7 +52,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
                     // into-coerce of a thin pointer to a fat pointer - just
                     // use the operand path.
                     let (bcx, temp) = self.trans_rvalue_operand(bcx, rvalue);
-                    self.store_operand(bcx, dest.llval, temp);
+                    self.store_operand(&bcx, dest.llval, temp);
                     return bcx;
                 }
 
@@ -61,39 +60,43 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
                 // this to be eliminated by MIR translation, but
                 // `CoerceUnsized` can be passed by a where-clause,
                 // so the (generic) MIR may not be able to expand it.
-                let operand = self.trans_operand(bcx, operand);
-                match operand.val {
-                    OperandValue::FatPtr(..) => unreachable!(),
-                    OperandValue::Immediate(llval) => {
-                        // unsize from an immediate structure. We don't
-                        // really need a temporary alloca here, but
-                        // avoiding it would require us to have
-                        // `coerce_unsized_into` use extractvalue to
-                        // index into the struct, and this case isn't
-                        // important enough for it.
-                        debug!("trans_rvalue: creating ugly alloca");
-                        let lltemp = base::alloc_ty(bcx, operand.ty, "__unsize_temp");
-                        base::store_ty(bcx, llval, lltemp, operand.ty);
-                        base::coerce_unsized_into(bcx,
-                                                  lltemp, operand.ty,
-                                                  dest.llval, cast_ty);
-                    }
-                    OperandValue::Ref(llref) => {
-                        base::coerce_unsized_into(bcx,
-                                                  llref, operand.ty,
-                                                  dest.llval, cast_ty);
+                let operand = self.trans_operand(&bcx, operand);
+                bcx.with_block(|bcx| {
+                    match operand.val {
+                        OperandValue::FatPtr(..) => unreachable!(),
+                        OperandValue::Immediate(llval) => {
+                            // unsize from an immediate structure. We don't
+                            // really need a temporary alloca here, but
+                            // avoiding it would require us to have
+                            // `coerce_unsized_into` use extractvalue to
+                            // index into the struct, and this case isn't
+                            // important enough for it.
+                            debug!("trans_rvalue: creating ugly alloca");
+                            let lltemp = base::alloc_ty(bcx, operand.ty, "__unsize_temp");
+                            base::store_ty(bcx, llval, lltemp, operand.ty);
+                            base::coerce_unsized_into(bcx,
+                                                      lltemp, operand.ty,
+                                                      dest.llval, cast_ty);
+                        }
+                        OperandValue::Ref(llref) => {
+                            base::coerce_unsized_into(bcx,
+                                                      llref, operand.ty,
+                                                      dest.llval, cast_ty);
+                        }
                     }
-                }
+                });
                 bcx
             }
 
             mir::Rvalue::Repeat(ref elem, ref count) => {
-                let elem = self.trans_operand(bcx, elem);
-                let size = self.trans_constval(bcx, &count.value, count.ty).immediate();
-                let base = expr::get_dataptr(bcx, dest.llval);
-                tvec::iter_vec_raw(bcx, base, elem.ty, size, |bcx, llslot, _| {
-                    self.store_operand(bcx, llslot, elem);
-                    bcx
+                let elem = self.trans_operand(&bcx, elem);
+                let size = self.trans_constval(&bcx, &count.value, count.ty).immediate();
+                bcx.map_block(|block| {
+                    let base = expr::get_dataptr(block, dest.llval);
+                    tvec::iter_vec_raw(block, base, elem.ty, size, |block, llslot, _| {
+                        self.store_operand_direct(block, llslot, elem);
+                        block
+                    })
                 })
             }
 
@@ -102,27 +105,31 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
                     mir::AggregateKind::Adt(adt_def, index, _) => {
                         let repr = adt::represent_type(bcx.ccx(), dest.ty.to_ty(bcx.tcx()));
                         let disr = Disr::from(adt_def.variants[index].disr_val);
-                        adt::trans_set_discr(bcx, &*repr, dest.llval, Disr::from(disr));
+                        bcx.with_block(|bcx| {
+                            adt::trans_set_discr(bcx, &*repr, dest.llval, Disr::from(disr));
+                        });
                         for (i, operand) in operands.iter().enumerate() {
-                            let op = self.trans_operand(bcx, operand);
+                            let op = self.trans_operand(&bcx, operand);
                             // Do not generate stores and GEPis for zero-sized fields.
                             if !common::type_is_zero_size(bcx.ccx(), op.ty) {
                                 let val = adt::MaybeSizedValue::sized(dest.llval);
-                                let lldest_i = adt::trans_field_ptr(bcx, &*repr, val, disr, i);
-                                self.store_operand(bcx, lldest_i, op);
+                                let lldest_i = bcx.with_block(|bcx| {
+                                    adt::trans_field_ptr(bcx, &*repr, val, disr, i)
+                                });
+                                self.store_operand(&bcx, lldest_i, op);
                             }
                         }
                     },
                     _ => {
                         for (i, operand) in operands.iter().enumerate() {
-                            let op = self.trans_operand(bcx, operand);
+                            let op = self.trans_operand(&bcx, operand);
                             // Do not generate stores and GEPis for zero-sized fields.
                             if !common::type_is_zero_size(bcx.ccx(), op.ty) {
                                 // Note: perhaps this should be StructGep, but
                                 // note that in some cases the values here will
                                 // not be structs but arrays.
-                                let dest = build::GEPi(bcx, dest.llval, &[0, i]);
-                                self.store_operand(bcx, dest, op);
+                                let dest = bcx.gepi(dest.llval, &[0, i]);
+                                self.store_operand(&bcx, dest, op);
                             }
                         }
                     }
@@ -132,49 +139,54 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
 
             mir::Rvalue::Slice { ref input, from_start, from_end } => {
                 let ccx = bcx.ccx();
-                let input = self.trans_lvalue(bcx, input);
-                let (llbase, lllen) = tvec::get_base_and_len(bcx,
-                                                             input.llval,
-                                                             input.ty.to_ty(bcx.tcx()));
-                let llbase1 = build::GEPi(bcx, llbase, &[from_start]);
+                let input = self.trans_lvalue(&bcx, input);
+                let (llbase, lllen) = bcx.with_block(|bcx| {
+                    tvec::get_base_and_len(bcx,
+                                           input.llval,
+                                           input.ty.to_ty(bcx.tcx()))
+                });
+                let llbase1 = bcx.gepi(llbase, &[from_start]);
                 let adj = common::C_uint(ccx, from_start + from_end);
-                let lllen1 = build::Sub(bcx, lllen, adj, DebugLoc::None);
-                let lladdrdest = expr::get_dataptr(bcx, dest.llval);
-                build::Store(bcx, llbase1, lladdrdest);
-                let llmetadest = expr::get_meta(bcx, dest.llval);
-                build::Store(bcx, lllen1, llmetadest);
+                let lllen1 = bcx.sub(lllen, adj);
+                let (lladdrdest, llmetadest) = bcx.with_block(|bcx| {
+                    (expr::get_dataptr(bcx, dest.llval), expr::get_meta(bcx, dest.llval))
+                });
+                bcx.store(llbase1, lladdrdest);
+                bcx.store(lllen1, llmetadest);
                 bcx
             }
 
             mir::Rvalue::InlineAsm(ref inline_asm) => {
-                asm::trans_inline_asm(bcx, inline_asm)
+                bcx.map_block(|bcx| {
+                    asm::trans_inline_asm(bcx, inline_asm)
+                })
             }
 
             _ => {
                 assert!(rvalue_creates_operand(rvalue));
                 let (bcx, temp) = self.trans_rvalue_operand(bcx, rvalue);
-                self.store_operand(bcx, dest.llval, temp);
+                self.store_operand(&bcx, dest.llval, temp);
                 bcx
             }
         }
     }
 
     pub fn trans_rvalue_operand(&mut self,
-                                bcx: Block<'bcx, 'tcx>,
+                                bcx: BlockAndBuilder<'bcx, 'tcx>,
                                 rvalue: &mir::Rvalue<'tcx>)
-                                -> (Block<'bcx, 'tcx>, OperandRef<'tcx>)
+                                -> (BlockAndBuilder<'bcx, 'tcx>, OperandRef<'tcx>)
     {
         assert!(rvalue_creates_operand(rvalue), "cannot trans {:?} to operand", rvalue);
 
         match *rvalue {
             mir::Rvalue::Use(ref operand) => {
-                let operand = self.trans_operand(bcx, operand);
+                let operand = self.trans_operand(&bcx, operand);
                 (bcx, operand)
             }
 
             mir::Rvalue::Cast(ref kind, ref operand, cast_ty) => {
-                let operand = self.trans_operand(bcx, operand);
-                debug!("cast operand is {}", operand.repr(bcx));
+                let operand = self.trans_operand(&bcx, operand);
+                debug!("cast operand is {}", operand.repr(&bcx));
                 let cast_ty = bcx.monomorphize(&cast_ty);
 
                 let val = match *kind {
@@ -199,15 +211,16 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
                             }
                             OperandValue::Immediate(lldata) => {
                                 // "standard" unsize
-                                let (lldata, llextra) =
+                                let (lldata, llextra) = bcx.with_block(|bcx| {
                                     base::unsize_thin_ptr(bcx, lldata,
-                                                          operand.ty, cast_ty);
+                                                          operand.ty, cast_ty)
+                                });
                                 OperandValue::FatPtr(lldata, llextra)
                             }
                             OperandValue::Ref(_) => {
                                 bcx.sess().bug(
                                     &format!("by-ref operand {} in trans_rvalue_operand",
-                                             operand.repr(bcx)));
+                                             operand.repr(&bcx)));
                             }
                         }
                     }
@@ -220,8 +233,9 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
                         let (llval, ll_t_in, signed) = if let CastTy::Int(IntTy::CEnum) = r_t_in {
                             let repr = adt::represent_type(bcx.ccx(), operand.ty);
                             let llval = operand.immediate();
-                            let discr = adt::trans_get_discr(bcx, &*repr, llval,
-                                                             None, true);
+                            let discr = bcx.with_block(|bcx| {
+                                adt::trans_get_discr(bcx, &*repr, llval, None, true)
+                            });
                             (discr, common::val_ty(discr), adt::is_discr_signed(&*repr))
                         } else {
                             (operand.immediate(), ll_t_in, operand.ty.is_signed())
@@ -232,22 +246,22 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
                                 let srcsz = ll_t_in.int_width();
                                 let dstsz = ll_t_out.int_width();
                                 if srcsz == dstsz {
-                                    build::BitCast(bcx, llval, ll_t_out)
+                                    bcx.bitcast(llval, ll_t_out)
                                 } else if srcsz > dstsz {
-                                    build::Trunc(bcx, llval, ll_t_out)
+                                    bcx.trunc(llval, ll_t_out)
                                 } else if signed {
-                                    build::SExt(bcx, llval, ll_t_out)
+                                    bcx.sext(llval, ll_t_out)
                                 } else {
-                                    build::ZExt(bcx, llval, ll_t_out)
+                                    bcx.zext(llval, ll_t_out)
                                 }
                             }
                             (CastTy::Float, CastTy::Float) => {
                                 let srcsz = ll_t_in.float_width();
                                 let dstsz = ll_t_out.float_width();
                                 if dstsz > srcsz {
-                                    build::FPExt(bcx, llval, ll_t_out)
+                                    bcx.fpext(llval, ll_t_out)
                                 } else if srcsz > dstsz {
-                                    build::FPTrunc(bcx, llval, ll_t_out)
+                                    bcx.fptrunc(llval, ll_t_out)
                                 } else {
                                     llval
                                 }
@@ -255,20 +269,20 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
                             (CastTy::Ptr(_), CastTy::Ptr(_)) |
                             (CastTy::FnPtr, CastTy::Ptr(_)) |
                             (CastTy::RPtr(_), CastTy::Ptr(_)) =>
-                                build::PointerCast(bcx, llval, ll_t_out),
+                                bcx.pointercast(llval, ll_t_out),
                             (CastTy::Ptr(_), CastTy::Int(_)) |
                             (CastTy::FnPtr, CastTy::Int(_)) =>
-                                build::PtrToInt(bcx, llval, ll_t_out),
+                                bcx.ptrtoint(llval, ll_t_out),
                             (CastTy::Int(_), CastTy::Ptr(_)) =>
-                                build::IntToPtr(bcx, llval, ll_t_out),
+                                bcx.inttoptr(llval, ll_t_out),
                             (CastTy::Int(_), CastTy::Float) if signed =>
-                                build::SIToFP(bcx, llval, ll_t_out),
+                                bcx.sitofp(llval, ll_t_out),
                             (CastTy::Int(_), CastTy::Float) =>
-                                build::UIToFP(bcx, llval, ll_t_out),
+                                bcx.uitofp(llval, ll_t_out),
                             (CastTy::Float, CastTy::Int(IntTy::I)) =>
-                                build::FPToSI(bcx, llval, ll_t_out),
+                                bcx.fptosi(llval, ll_t_out),
                             (CastTy::Float, CastTy::Int(_)) =>
-                                build::FPToUI(bcx, llval, ll_t_out),
+                                bcx.fptoui(llval, ll_t_out),
                             _ => bcx.ccx().sess().bug(
                                 &format!("unsupported cast: {:?} to {:?}", operand.ty, cast_ty)
                             )
@@ -282,13 +296,13 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
                             if common::type_is_fat_ptr(bcx.tcx(), cast_ty) {
                                 let ll_cft = ll_cast_ty.field_types();
                                 let ll_fft = ll_from_ty.field_types();
-                                let data_cast = build::PointerCast(bcx, data_ptr, ll_cft[0]);
+                                let data_cast = bcx.pointercast(data_ptr, ll_cft[0]);
                                 assert_eq!(ll_cft[1].kind(), ll_fft[1].kind());
                                 OperandValue::FatPtr(data_cast, meta_ptr)
                             } else { // cast to thin-ptr
                                 // Cast of fat-ptr to thin-ptr is an extraction of data-ptr and
                                 // pointer-cast of that pointer to desired pointer type.
-                                let llval = build::PointerCast(bcx, data_ptr, ll_cast_ty);
+                                let llval = bcx.pointercast(data_ptr, ll_cast_ty);
                                 OperandValue::Immediate(llval)
                             }
                         } else {
@@ -296,14 +310,15 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
                         }
                     }
                 };
-                (bcx, OperandRef {
+                let operand = OperandRef {
                     val: val,
                     ty: cast_ty
-                })
+                };
+                (bcx, operand)
             }
 
             mir::Rvalue::Ref(_, bk, ref lvalue) => {
-                let tr_lvalue = self.trans_lvalue(bcx, lvalue);
+                let tr_lvalue = self.trans_lvalue(&bcx, lvalue);
 
                 let ty = tr_lvalue.ty.to_ty(bcx.tcx());
                 let ref_ty = bcx.tcx().mk_ref(
@@ -313,66 +328,70 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
 
                 // Note: lvalues are indirect, so storing the `llval` into the
                 // destination effectively creates a reference.
-                if common::type_is_sized(bcx.tcx(), ty) {
-                    (bcx, OperandRef {
+                let operand = if common::type_is_sized(bcx.tcx(), ty) {
+                    OperandRef {
                         val: OperandValue::Immediate(tr_lvalue.llval),
                         ty: ref_ty,
-                    })
+                    }
                 } else {
-                    (bcx, OperandRef {
+                    OperandRef {
                         val: OperandValue::FatPtr(tr_lvalue.llval,
                                                   tr_lvalue.llextra),
                         ty: ref_ty,
-                    })
-                }
+                    }
+                };
+                (bcx, operand)
             }
 
             mir::Rvalue::Len(ref lvalue) => {
-                let tr_lvalue = self.trans_lvalue(bcx, lvalue);
-                (bcx, OperandRef {
-                    val: OperandValue::Immediate(self.lvalue_len(bcx, tr_lvalue)),
+                let tr_lvalue = self.trans_lvalue(&bcx, lvalue);
+                let operand = OperandRef {
+                    val: OperandValue::Immediate(self.lvalue_len(&bcx, tr_lvalue)),
                     ty: bcx.tcx().types.usize,
-                })
+                };
+                (bcx, operand)
             }
 
             mir::Rvalue::BinaryOp(op, ref lhs, ref rhs) => {
-                let lhs = self.trans_operand(bcx, lhs);
-                let rhs = self.trans_operand(bcx, rhs);
+                let lhs = self.trans_operand(&bcx, lhs);
+                let rhs = self.trans_operand(&bcx, rhs);
                 let llresult = if common::type_is_fat_ptr(bcx.tcx(), lhs.ty) {
                     match (lhs.val, rhs.val) {
                         (OperandValue::FatPtr(lhs_addr, lhs_extra),
                          OperandValue::FatPtr(rhs_addr, rhs_extra)) => {
-                            base::compare_fat_ptrs(bcx,
-                                                   lhs_addr, lhs_extra,
-                                                   rhs_addr, rhs_extra,
-                                                   lhs.ty, op.to_hir_binop(),
-                                                   DebugLoc::None)
+                            bcx.with_block(|bcx| {
+                                base::compare_fat_ptrs(bcx,
+                                                       lhs_addr, lhs_extra,
+                                                       rhs_addr, rhs_extra,
+                                                       lhs.ty, op.to_hir_binop(),
+                                                       DebugLoc::None)
+                            })
                         }
                         _ => unreachable!()
                     }
 
                 } else {
-                    self.trans_scalar_binop(bcx, op,
+                    self.trans_scalar_binop(&bcx, op,
                                             lhs.immediate(), rhs.immediate(),
-                                            lhs.ty, DebugLoc::None)
+                                            lhs.ty)
                 };
-                (bcx, OperandRef {
+                let operand = OperandRef {
                     val: OperandValue::Immediate(llresult),
                     ty: self.mir.binop_ty(bcx.tcx(), op, lhs.ty, rhs.ty),
-                })
+                };
+                (bcx, operand)
             }
 
             mir::Rvalue::UnaryOp(op, ref operand) => {
-                let operand = self.trans_operand(bcx, operand);
+                let operand = self.trans_operand(&bcx, operand);
                 let lloperand = operand.immediate();
                 let is_float = operand.ty.is_fp();
-                let debug_loc = DebugLoc::None;
                 let llval = match op {
-                    mir::UnOp::Not => build::Not(bcx, lloperand, debug_loc),
+                    mir::UnOp::Not => bcx.not(lloperand),
                     mir::UnOp::Neg => if is_float {
-                        build::FNeg(bcx, lloperand, debug_loc)
+                        bcx.fneg(lloperand)
                     } else {
-                        build::Neg(bcx, lloperand, debug_loc)
+                        bcx.neg(lloperand)
                     }
                 };
                 (bcx, OperandRef {
@@ -389,16 +408,22 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
                 let llalign = common::C_uint(bcx.ccx(), align);
                 let llty_ptr = llty.ptr_to();
                 let box_ty = bcx.tcx().mk_box(content_ty);
-                let Result { bcx, val: llval } = base::malloc_raw_dyn(bcx,
-                                                                      llty_ptr,
-                                                                      box_ty,
-                                                                      llsize,
-                                                                      llalign,
-                                                                      DebugLoc::None);
-                (bcx, OperandRef {
-                    val: OperandValue::Immediate(llval),
+                let mut llval = None;
+                let bcx = bcx.map_block(|bcx| {
+                    let Result { bcx, val } = base::malloc_raw_dyn(bcx,
+                                                                   llty_ptr,
+                                                                   box_ty,
+                                                                   llsize,
+                                                                   llalign,
+                                                                   DebugLoc::None);
+                    llval = Some(val);
+                    bcx
+                });
+                let operand = OperandRef {
+                    val: OperandValue::Immediate(llval.unwrap()),
                     ty: box_ty,
-                })
+                };
+                (bcx, operand)
             }
 
             mir::Rvalue::Repeat(..) |
@@ -411,36 +436,35 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
     }
 
     pub fn trans_scalar_binop(&mut self,
-                              bcx: Block<'bcx, 'tcx>,
+                              bcx: &BlockAndBuilder<'bcx, 'tcx>,
                               op: mir::BinOp,
                               lhs: ValueRef,
                               rhs: ValueRef,
-                              input_ty: Ty<'tcx>,
-                              debug_loc: DebugLoc) -> ValueRef {
+                              input_ty: Ty<'tcx>) -> ValueRef {
         let is_float = input_ty.is_fp();
         let is_signed = input_ty.is_signed();
         match op {
             mir::BinOp::Add => if is_float {
-                build::FAdd(bcx, lhs, rhs, debug_loc)
+                bcx.fadd(lhs, rhs)
             } else {
-                build::Add(bcx, lhs, rhs, debug_loc)
+                bcx.add(lhs, rhs)
             },
             mir::BinOp::Sub => if is_float {
-                build::FSub(bcx, lhs, rhs, debug_loc)
+                bcx.fsub(lhs, rhs)
             } else {
-                build::Sub(bcx, lhs, rhs, debug_loc)
+                bcx.sub(lhs, rhs)
             },
             mir::BinOp::Mul => if is_float {
-                build::FMul(bcx, lhs, rhs, debug_loc)
+                bcx.fmul(lhs, rhs)
             } else {
-                build::Mul(bcx, lhs, rhs, debug_loc)
+                bcx.mul(lhs, rhs)
             },
             mir::BinOp::Div => if is_float {
-                build::FDiv(bcx, lhs, rhs, debug_loc)
+                bcx.fdiv(lhs, rhs)
             } else if is_signed {
-                build::SDiv(bcx, lhs, rhs, debug_loc)
+                bcx.sdiv(lhs, rhs)
             } else {
-                build::UDiv(bcx, lhs, rhs, debug_loc)
+                bcx.udiv(lhs, rhs)
             },
             mir::BinOp::Rem => if is_float {
                 // LLVM currently always lowers the `frem` instructions appropriate
@@ -471,39 +495,47 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
                     let llfn = declare::declare_cfn(bcx.ccx(), "fmod", fty,
                                                     tcx.types.f64);
                     if input_ty == tcx.types.f32 {
-                        let lllhs = build::FPExt(bcx, lhs, f64t);
-                        let llrhs = build::FPExt(bcx, rhs, f64t);
-                        let llres = build::Call(bcx, llfn, &[lllhs, llrhs],
-                                                None, debug_loc);
-                        build::FPTrunc(bcx, llres, Type::f32(bcx.ccx()))
+                        let lllhs = bcx.fpext(lhs, f64t);
+                        let llrhs = bcx.fpext(rhs, f64t);
+                        let llres = bcx.call(llfn, &[lllhs, llrhs], None, None);
+                        bcx.fptrunc(llres, Type::f32(bcx.ccx()))
                     } else {
-                        build::Call(bcx, llfn, &[lhs, rhs],
-                                    None, debug_loc)
+                        bcx.call(llfn, &[lhs, rhs], None, None)
                     }
                 } else {
-                    build::FRem(bcx, lhs, rhs, debug_loc)
+                    bcx.frem(lhs, rhs)
                 }
             } else if is_signed {
-                build::SRem(bcx, lhs, rhs, debug_loc)
+                bcx.srem(lhs, rhs)
             } else {
-                build::URem(bcx, lhs, rhs, debug_loc)
+                bcx.urem(lhs, rhs)
             },
-            mir::BinOp::BitOr => build::Or(bcx, lhs, rhs, debug_loc),
-            mir::BinOp::BitAnd => build::And(bcx, lhs, rhs, debug_loc),
-            mir::BinOp::BitXor => build::Xor(bcx, lhs, rhs, debug_loc),
-            mir::BinOp::Shl => common::build_unchecked_lshift(bcx,
-                                                              lhs,
-                                                              rhs,
-                                                              debug_loc),
-            mir::BinOp::Shr => common::build_unchecked_rshift(bcx,
-                                                              input_ty,
-                                                              lhs,
-                                                              rhs,
-                                                              debug_loc),
+            mir::BinOp::BitOr => bcx.or(lhs, rhs),
+            mir::BinOp::BitAnd => bcx.and(lhs, rhs),
+            mir::BinOp::BitXor => bcx.xor(lhs, rhs),
+            mir::BinOp::Shl => {
+                bcx.with_block(|bcx| {
+                    common::build_unchecked_lshift(bcx,
+                                                   lhs,
+                                                   rhs,
+                                                   DebugLoc::None)
+                })
+            }
+            mir::BinOp::Shr => {
+                bcx.with_block(|bcx| {
+                    common::build_unchecked_rshift(bcx,
+                                                   input_ty,
+                                                   lhs,
+                                                   rhs,
+                                                   DebugLoc::None)
+                })
+            }
             mir::BinOp::Eq | mir::BinOp::Lt | mir::BinOp::Gt |
             mir::BinOp::Ne | mir::BinOp::Le | mir::BinOp::Ge => {
-                base::compare_scalar_types(bcx, lhs, rhs, input_ty,
-                                           op.to_hir_binop(), debug_loc)
+                bcx.with_block(|bcx| {
+                    base::compare_scalar_types(bcx, lhs, rhs, input_ty,
+                                               op.to_hir_binop(), DebugLoc::None)
+                })
             }
         }
     }
diff --git a/src/librustc_trans/trans/mir/statement.rs b/src/librustc_trans/trans/mir/statement.rs
index fc888564737..0307fd649c8 100644
--- a/src/librustc_trans/trans/mir/statement.rs
+++ b/src/librustc_trans/trans/mir/statement.rs
@@ -9,16 +9,16 @@
 // except according to those terms.
 
 use rustc::mir::repr as mir;
-use trans::common::Block;
+use trans::common::BlockAndBuilder;
 
 use super::MirContext;
 use super::TempRef;
 
 impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
     pub fn trans_statement(&mut self,
-                           bcx: Block<'bcx, 'tcx>,
+                           bcx: BlockAndBuilder<'bcx, 'tcx>,
                            statement: &mir::Statement<'tcx>)
-                           -> Block<'bcx, 'tcx> {
+                           -> BlockAndBuilder<'bcx, 'tcx> {
         debug!("trans_statement(statement={:?})", statement);
 
         match statement.kind {
@@ -43,7 +43,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
                         }
                     }
                     _ => {
-                        let tr_dest = self.trans_lvalue(bcx, lvalue);
+                        let tr_dest = self.trans_lvalue(&bcx, lvalue);
                         self.trans_rvalue(bcx, tr_dest, rvalue)
                     }
                 }