about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc/lib/llvm.rs2
-rw-r--r--src/librustc/middle/trans/base.rs91
-rw-r--r--src/librustc/middle/trans/build.rs8
-rw-r--r--src/librustc/middle/trans/closure.rs21
-rw-r--r--src/librustc/middle/trans/common.rs23
-rw-r--r--src/librustc/middle/trans/foreign.rs34
-rw-r--r--src/librustc/middle/trans/glue.rs7
-rw-r--r--src/librustc/middle/trans/reflect.rs4
-rw-r--r--src/rustllvm/rustllvm.def.in1
9 files changed, 79 insertions, 112 deletions
diff --git a/src/librustc/lib/llvm.rs b/src/librustc/lib/llvm.rs
index 05992c431da..d1a9e387d00 100644
--- a/src/librustc/lib/llvm.rs
+++ b/src/librustc/lib/llvm.rs
@@ -984,6 +984,8 @@ pub mod llvm {
         pub unsafe fn LLVMGetNextInstruction(Inst: ValueRef) -> ValueRef;
         #[fast_ffi]
         pub unsafe fn LLVMGetPreviousInstruction(Inst: ValueRef) -> ValueRef;
+        #[fast_ffi]
+        pub unsafe fn LLVMInstructionEraseFromParent(Inst: ValueRef);
 
         /* Operations on call sites */
         #[fast_ffi]
diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs
index 5536fa6daa7..2512b6e3ece 100644
--- a/src/librustc/middle/trans/base.rs
+++ b/src/librustc/middle/trans/base.rs
@@ -41,7 +41,7 @@ use middle::trans::_match;
 use middle::trans::adt;
 use middle::trans::base;
 use middle::trans::build::*;
-use middle::trans::builder::noname;
+use middle::trans::builder::{Builder, noname};
 use middle::trans::callee;
 use middle::trans::common::*;
 use middle::trans::consts;
@@ -1503,11 +1503,12 @@ pub fn memcpy_ty(bcx: block, dst: ValueRef, src: ValueRef, t: ty::t) {
 }
 
 pub fn zero_mem(cx: block, llptr: ValueRef, t: ty::t) {
+    if cx.unreachable { return; }
     let _icx = push_ctxt("zero_mem");
     let bcx = cx;
     let ccx = cx.ccx();
     let llty = type_of::type_of(ccx, t);
-    memzero(bcx, llptr, llty);
+    memzero(&B(bcx), llptr, llty);
 }
 
 // Always use this function instead of storing a zero constant to the memory
@@ -1515,9 +1516,9 @@ pub fn zero_mem(cx: block, llptr: ValueRef, t: ty::t) {
 // allocation for large data structures, and the generated code will be
 // awful. (A telltale sign of this is large quantities of
 // `mov [byte ptr foo],0` in the generated code.)
-pub fn memzero(cx: block, llptr: ValueRef, ty: Type) {
+pub fn memzero(b: &Builder, llptr: ValueRef, ty: Type) {
     let _icx = push_ctxt("memzero");
-    let ccx = cx.ccx();
+    let ccx = b.ccx;
 
     let intrinsic_key = match ccx.sess.targ_cfg.arch {
         X86 | Arm | Mips => "llvm.memset.p0i8.i32",
@@ -1525,12 +1526,12 @@ pub fn memzero(cx: block, llptr: ValueRef, ty: Type) {
     };
 
     let llintrinsicfn = ccx.intrinsics.get_copy(&intrinsic_key);
-    let llptr = PointerCast(cx, llptr, Type::i8().ptr_to());
+    let llptr = b.pointercast(llptr, Type::i8().ptr_to());
     let llzeroval = C_u8(0);
-    let size = IntCast(cx, machine::llsize_of(ccx, ty), ccx.int_type);
+    let size = machine::llsize_of(ccx, ty);
     let align = C_i32(llalign_of_min(ccx, ty) as i32);
     let volatile = C_i1(false);
-    Call(cx, llintrinsicfn, [llptr, llzeroval, size, align, volatile]);
+    b.call(llintrinsicfn, [llptr, llzeroval, size, align, volatile]);
 }
 
 pub fn alloc_ty(bcx: block, t: ty::t, name: &str) -> ValueRef {
@@ -1553,9 +1554,12 @@ pub fn alloca_maybe_zeroed(cx: block, ty: Type, name: &str, zero: bool) -> Value
             return llvm::LLVMGetUndef(ty.ptr_to().to_ref());
         }
     }
-    let initcx = base::raw_block(cx.fcx, false, cx.fcx.get_llstaticallocas());
-    let p = Alloca(initcx, ty, name);
-    if zero { memzero(initcx, p, ty); }
+    let p = Alloca(cx, ty, name);
+    if zero {
+        let b = cx.fcx.ccx.builder();
+        b.position_before(cx.fcx.alloca_insert_pt.get());
+        memzero(&b, p, ty);
+    }
     p
 }
 
@@ -1566,7 +1570,7 @@ pub fn arrayalloca(cx: block, ty: Type, v: ValueRef) -> ValueRef {
             return llvm::LLVMGetUndef(ty.to_ref());
         }
     }
-    return ArrayAlloca(base::raw_block(cx.fcx, false, cx.fcx.get_llstaticallocas()), ty, v);
+    return ArrayAlloca(cx, ty, v);
 }
 
 pub struct BasicBlocks {
@@ -1597,8 +1601,8 @@ pub fn make_return_pointer(fcx: fn_ctxt, output_type: ty::t) -> ValueRef {
             llvm::LLVMGetParam(fcx.llfn, 0)
         } else {
             let lloutputtype = type_of::type_of(fcx.ccx, output_type);
-            alloca(raw_block(fcx, false, fcx.get_llstaticallocas()), lloutputtype,
-                   "__make_return_pointer")
+            let bcx = fcx.entry_bcx.get();
+            Alloca(bcx, lloutputtype, "__make_return_pointer")
         }
     }
 }
@@ -1616,6 +1620,7 @@ pub fn new_fn_ctxt_w_id(ccx: @mut CrateContext,
                         output_type: ty::t,
                         skip_retptr: bool,
                         param_substs: Option<@param_substs>,
+                        opt_node_info: Option<NodeInfo>,
                         sp: Option<span>)
                      -> fn_ctxt {
     for param_substs.iter().advance |p| { p.validate(); }
@@ -1639,8 +1644,8 @@ pub fn new_fn_ctxt_w_id(ccx: @mut CrateContext,
               llvm::LLVMGetUndef(Type::i8p().to_ref())
           },
           llretptr: None,
-          llstaticallocas: None,
-          llloadenv: None,
+          entry_bcx: None,
+          alloca_insert_pt: None,
           llreturn: None,
           llself: None,
           personality: None,
@@ -1658,6 +1663,15 @@ pub fn new_fn_ctxt_w_id(ccx: @mut CrateContext,
     fcx.llenv = unsafe {
           llvm::LLVMGetParam(llfndecl, fcx.env_arg_pos() as c_uint)
     };
+
+    unsafe {
+        let entry_bcx = top_scope_block(fcx, opt_node_info);
+        Load(entry_bcx, C_null(Type::i8p()));
+
+        fcx.entry_bcx = Some(entry_bcx);
+        fcx.alloca_insert_pt = Some(llvm::LLVMGetFirstInstruction(entry_bcx.llbb));
+    }
+
     if !ty::type_is_nil(substd_output_type) && !(is_immediate && skip_retptr) {
         fcx.llretptr = Some(make_return_pointer(fcx, substd_output_type));
     }
@@ -1670,7 +1684,7 @@ pub fn new_fn_ctxt(ccx: @mut CrateContext,
                    output_type: ty::t,
                    sp: Option<span>)
                 -> fn_ctxt {
-    new_fn_ctxt_w_id(ccx, path, llfndecl, -1, output_type, false, None, sp)
+    new_fn_ctxt_w_id(ccx, path, llfndecl, -1, output_type, false, None, None, sp)
 }
 
 // NB: must keep 4 fns in sync:
@@ -1785,9 +1799,8 @@ pub fn copy_args_to_allocas(fcx: fn_ctxt,
 
 // Ties up the llstaticallocas -> llloadenv -> lltop edges,
 // and builds the return block.
-pub fn finish_fn(fcx: fn_ctxt, lltop: BasicBlockRef, last_bcx: block) {
+pub fn finish_fn(fcx: fn_ctxt, last_bcx: block) {
     let _icx = push_ctxt("finish_fn");
-    tie_up_header_blocks(fcx, lltop);
 
     let ret_cx = match fcx.llreturn {
         Some(llreturn) => {
@@ -1799,6 +1812,7 @@ pub fn finish_fn(fcx: fn_ctxt, lltop: BasicBlockRef, last_bcx: block) {
         None => last_bcx
     };
     build_return_block(fcx, ret_cx);
+    fcx.cleanup();
 }
 
 // Builds the return block for a function.
@@ -1811,29 +1825,6 @@ pub fn build_return_block(fcx: fn_ctxt, ret_cx: block) {
     }
 }
 
-pub fn tie_up_header_blocks(fcx: fn_ctxt, lltop: BasicBlockRef) {
-    let _icx = push_ctxt("tie_up_header_blocks");
-    let llnext = match fcx.llloadenv {
-        Some(ll) => {
-            unsafe {
-                llvm::LLVMMoveBasicBlockBefore(ll, lltop);
-            }
-            Br(raw_block(fcx, false, ll), lltop);
-            ll
-        }
-        None => lltop
-    };
-    match fcx.llstaticallocas {
-        Some(ll) => {
-            unsafe {
-                llvm::LLVMMoveBasicBlockBefore(ll, llnext);
-            }
-            Br(raw_block(fcx, false, ll), llnext);
-        }
-        None => ()
-    }
-}
-
 pub enum self_arg { impl_self(ty::t, ty::SelfMode), no_self, }
 
 // trans_closure: Builds an LLVM function out of a source function.
@@ -1866,6 +1857,7 @@ pub fn trans_closure(ccx: @mut CrateContext,
                                output_type,
                                false,
                                param_substs,
+                               body.info(),
                                Some(body.span));
     let raw_llargs = create_llargs_for_fn_args(fcx, self_arg, decl.inputs);
 
@@ -1877,9 +1869,8 @@ pub fn trans_closure(ccx: @mut CrateContext,
 
     // Create the first basic block in the function and keep a handle on it to
     //  pass to finish_fn later.
-    let bcx_top = top_scope_block(fcx, body.info());
+    let bcx_top = fcx.entry_bcx.get();
     let mut bcx = bcx_top;
-    let lltop = bcx.llbb;
     let block_ty = node_id_type(bcx, body.id);
 
     let arg_tys = ty::ty_fn_args(node_id_type(bcx, id));
@@ -1915,7 +1906,7 @@ pub fn trans_closure(ccx: @mut CrateContext,
     }
 
     // Insert the mandatory first few basic blocks before lltop.
-    finish_fn(fcx, lltop, bcx);
+    finish_fn(fcx, bcx);
 }
 
 // trans_fn: creates an LLVM function corresponding to a source language
@@ -2085,12 +2076,12 @@ pub fn trans_enum_variant_or_tuple_like_struct<A:IdAndTy>(
                                result_ty,
                                false,
                                param_substs,
+                               None,
                                None);
 
     let raw_llargs = create_llargs_for_fn_args(fcx, no_self, fn_args);
 
-    let bcx = top_scope_block(fcx, None);
-    let lltop = bcx.llbb;
+    let bcx = fcx.entry_bcx.get();
     let arg_tys = ty::ty_fn_args(ctor_ty);
 
     insert_synthetic_type_entries(bcx, fn_args, arg_tys);
@@ -2108,7 +2099,7 @@ pub fn trans_enum_variant_or_tuple_like_struct<A:IdAndTy>(
         let arg_ty = arg_tys[i];
         memcpy_ty(bcx, lldestptr, llarg, arg_ty);
     }
-    finish_fn(fcx, lltop, bcx);
+    finish_fn(fcx, bcx);
 }
 
 pub fn trans_enum_def(ccx: @mut CrateContext, enum_definition: &ast::enum_def,
@@ -2336,9 +2327,7 @@ pub fn create_entry_wrapper(ccx: @mut CrateContext,
         // be updated if this assertion starts to fail.
         assert!(fcx.has_immediate_return_value);
 
-        let bcx = top_scope_block(fcx, None);
-        let lltop = bcx.llbb;
-
+        let bcx = fcx.entry_bcx.get();
         // Call main.
         let llenvarg = unsafe {
             let env_arg = fcx.env_arg_pos();
@@ -2347,7 +2336,7 @@ pub fn create_entry_wrapper(ccx: @mut CrateContext,
         let args = ~[llenvarg];
         Call(bcx, main_llfn, args);
 
-        finish_fn(fcx, lltop, bcx);
+        finish_fn(fcx, bcx);
         return llfdecl;
     }
 
diff --git a/src/librustc/middle/trans/build.rs b/src/librustc/middle/trans/build.rs
index 7861f658f53..a8c7efb2ad4 100644
--- a/src/librustc/middle/trans/build.rs
+++ b/src/librustc/middle/trans/build.rs
@@ -318,14 +318,18 @@ pub fn ArrayMalloc(cx: block, Ty: Type, Val: ValueRef) -> ValueRef {
 pub fn Alloca(cx: block, Ty: Type, name: &str) -> ValueRef {
     unsafe {
         if cx.unreachable { return llvm::LLVMGetUndef(Ty.ptr_to().to_ref()); }
-        B(cx).alloca(Ty, name)
+        let b = cx.fcx.ccx.builder();
+        b.position_before(cx.fcx.alloca_insert_pt.get());
+        b.alloca(Ty, name)
     }
 }
 
 pub fn ArrayAlloca(cx: block, Ty: Type, Val: ValueRef) -> ValueRef {
     unsafe {
         if cx.unreachable { return llvm::LLVMGetUndef(Ty.ptr_to().to_ref()); }
-        B(cx).array_alloca(Ty, Val)
+        let b = cx.fcx.ccx.builder();
+        b.position_before(cx.fcx.alloca_insert_pt.get());
+        b.array_alloca(Ty, Val)
     }
 }
 
diff --git a/src/librustc/middle/trans/closure.rs b/src/librustc/middle/trans/closure.rs
index 7507f19ec20..cdde96393a1 100644
--- a/src/librustc/middle/trans/closure.rs
+++ b/src/librustc/middle/trans/closure.rs
@@ -11,7 +11,7 @@
 
 use back::abi;
 use back::link::{mangle_internal_name_by_path_and_seq};
-use lib::llvm::{llvm, ValueRef};
+use lib::llvm::ValueRef;
 use middle::moves;
 use middle::trans::base::*;
 use middle::trans::build::*;
@@ -25,7 +25,6 @@ use util::ppaux::ty_to_str;
 
 use middle::trans::type_::Type;
 
-use std::str;
 use std::vec;
 use syntax::ast;
 use syntax::ast_map::path_name;
@@ -331,23 +330,7 @@ pub fn load_environment(fcx: fn_ctxt,
         return;
     }
 
-    let llloadenv = match fcx.llloadenv {
-        Some(ll) => ll,
-        None => {
-            let ll =
-                str::as_c_str("load_env",
-                              |buf|
-                              unsafe {
-                                llvm::LLVMAppendBasicBlockInContext(fcx.ccx.llcx,
-                                                                    fcx.llfn,
-                                                                    buf)
-                              });
-            fcx.llloadenv = Some(ll);
-            ll
-        }
-    };
-
-    let bcx = raw_block(fcx, false, llloadenv);
+    let bcx = fcx.entry_bcx.get();
 
     // Load a pointer to the closure data, skipping over the box header:
     let llcdata = opaque_box_body(bcx, cdata_ty, fcx.llenv);
diff --git a/src/librustc/middle/trans/common.rs b/src/librustc/middle/trans/common.rs
index d90614ebc02..f53f15a83d7 100644
--- a/src/librustc/middle/trans/common.rs
+++ b/src/librustc/middle/trans/common.rs
@@ -174,17 +174,14 @@ pub struct fn_ctxt_ {
     // always be Some.
     llretptr: Option<ValueRef>,
 
+    entry_bcx: Option<block>,
+
     // These elements: "hoisted basic blocks" containing
     // administrative activities that have to happen in only one place in
     // the function, due to LLVM's quirks.
-    // A block for all the function's static allocas, so that LLVM
-    // will coalesce them into a single alloca call.
-    llstaticallocas: Option<BasicBlockRef>,
-    // A block containing code that copies incoming arguments to space
-    // already allocated by code in one of the llallocas blocks.
-    // (LLVM requires that arguments be copied to local allocas before
-    // allowing most any operation to be performed on them.)
-    llloadenv: Option<BasicBlockRef>,
+    // A marker for the place where we want to insert the function's static
+    // allocas, so that LLVM will coalesce them into a single alloca call.
+    alloca_insert_pt: Option<ValueRef>,
     llreturn: Option<BasicBlockRef>,
     // The 'self' value currently in use in this function, if there
     // is one.
@@ -252,12 +249,12 @@ impl fn_ctxt_ {
         }
     }
 
-    pub fn get_llstaticallocas(&mut self) -> BasicBlockRef {
-        if self.llstaticallocas.is_none() {
-            self.llstaticallocas = Some(base::mk_staticallocas_basic_block(self.llfn));
+    pub fn cleanup(&mut self) {
+        unsafe {
+            llvm::LLVMInstructionEraseFromParent(self.alloca_insert_pt.get());
         }
-
-        self.llstaticallocas.get()
+        // Remove the cycle between fcx and bcx, so memory can be freed
+        self.entry_bcx = None;
     }
 
     pub fn get_llreturn(&mut self) -> BasicBlockRef {
diff --git a/src/librustc/middle/trans/foreign.rs b/src/librustc/middle/trans/foreign.rs
index 355e2f57b2c..08fbfdee9ea 100644
--- a/src/librustc/middle/trans/foreign.rs
+++ b/src/librustc/middle/trans/foreign.rs
@@ -149,8 +149,7 @@ fn build_shim_fn_(ccx: @mut CrateContext,
 
     // Declare the body of the shim function:
     let fcx = new_fn_ctxt(ccx, ~[], llshimfn, tys.fn_sig.output, None);
-    let bcx = top_scope_block(fcx, None);
-    let lltop = bcx.llbb;
+    let bcx = fcx.entry_bcx.get();
 
     let llargbundle = get_param(llshimfn, 0u);
     let llargvals = arg_builder(bcx, tys, llargbundle);
@@ -162,13 +161,12 @@ fn build_shim_fn_(ccx: @mut CrateContext,
 
     // Don't finish up the function in the usual way, because this doesn't
     // follow the normal Rust calling conventions.
-    tie_up_header_blocks(fcx, lltop);
-
     let ret_cx = match fcx.llreturn {
         Some(llreturn) => raw_block(fcx, false, llreturn),
         None => bcx
     };
     RetVoid(ret_cx);
+    fcx.cleanup();
 
     return llshimfn;
 }
@@ -192,19 +190,15 @@ fn build_wrap_fn_(ccx: @mut CrateContext,
                   ret_builder: wrap_ret_builder) {
     let _icx = push_ctxt("foreign::build_wrap_fn_");
     let fcx = new_fn_ctxt(ccx, ~[], llwrapfn, tys.fn_sig.output, None);
+    let bcx = fcx.entry_bcx.get();
 
     // Patch up the return type if it's not immediate and we're returning via
     // the C ABI.
     if needs_c_return && !ty::type_is_immediate(ccx.tcx, tys.fn_sig.output) {
         let lloutputtype = type_of::type_of(fcx.ccx, tys.fn_sig.output);
-        fcx.llretptr = Some(alloca(raw_block(fcx, false, fcx.get_llstaticallocas()),
-                                   lloutputtype,
-                                   ""));
+        fcx.llretptr = Some(alloca(bcx, lloutputtype, ""));
     }
 
-    let bcx = top_scope_block(fcx, None);
-    let lltop = bcx.llbb;
-
     // Allocate the struct and write the arguments into it.
     let llargbundle = alloca(bcx, tys.bundle_ty, "__llargbundle");
     arg_builder(bcx, tys, llwrapfn, llargbundle);
@@ -215,10 +209,6 @@ fn build_wrap_fn_(ccx: @mut CrateContext,
     Call(bcx, shim_upcall, [llrawargbundle, llshimfnptr]);
     ret_builder(bcx, tys, llargbundle);
 
-    // Perform a custom version of `finish_fn`. First, tie up the header
-    // blocks.
-    tie_up_header_blocks(fcx, lltop);
-
     // Then return according to the C ABI.
     let return_context = match fcx.llreturn {
         Some(llreturn) => raw_block(fcx, false, llreturn),
@@ -239,6 +229,7 @@ fn build_wrap_fn_(ccx: @mut CrateContext,
         let llretptr = BitCast(return_context, fcx.llretptr.get(), return_type.ptr_to());
         Ret(return_context, Load(return_context, llretptr));
     }
+    fcx.cleanup();
 }
 
 // For each foreign function F, we generate a wrapper function W and a shim
@@ -430,8 +421,7 @@ pub fn trans_foreign_mod(ccx: @mut CrateContext,
         debug!("build_direct_fn(%s)", link_name(ccx, item));
 
         let fcx = new_fn_ctxt(ccx, ~[], decl, tys.fn_sig.output, None);
-        let bcx = top_scope_block(fcx, None);
-        let lltop = bcx.llbb;
+        let bcx = fcx.entry_bcx.get();
         let llbasefn = base_fn(ccx, link_name(ccx, item), tys, cc);
         let ty = ty::lookup_item_type(ccx.tcx,
                                       ast_util::local_def(item.id)).ty;
@@ -443,7 +433,7 @@ pub fn trans_foreign_mod(ccx: @mut CrateContext,
         if !ty::type_is_nil(ret_ty) && !ty::type_is_bot(ret_ty) {
             Store(bcx, retval, fcx.llretptr.get());
         }
-        finish_fn(fcx, lltop, bcx);
+        finish_fn(fcx, bcx);
     }
 
     // FIXME (#2535): this is very shaky and probably gets ABIs wrong all
@@ -456,8 +446,7 @@ pub fn trans_foreign_mod(ccx: @mut CrateContext,
         debug!("build_fast_ffi_fn(%s)", link_name(ccx, item));
 
         let fcx = new_fn_ctxt(ccx, ~[], decl, tys.fn_sig.output, None);
-        let bcx = top_scope_block(fcx, None);
-        let lltop = bcx.llbb;
+        let bcx = fcx.entry_bcx.get();
         let llbasefn = base_fn(ccx, link_name(ccx, item), tys, cc);
         set_no_inline(fcx.llfn);
         set_fixed_stack_segment(fcx.llfn);
@@ -471,7 +460,7 @@ pub fn trans_foreign_mod(ccx: @mut CrateContext,
         if !ty::type_is_nil(ret_ty) && !ty::type_is_bot(ret_ty) {
             Store(bcx, retval, fcx.llretptr.get());
         }
-        finish_fn(fcx, lltop, bcx);
+        finish_fn(fcx, bcx);
     }
 
     fn build_wrap_fn(ccx: @mut CrateContext,
@@ -619,6 +608,7 @@ pub fn trans_intrinsic(ccx: @mut CrateContext,
                                output_type,
                                true,
                                Some(substs),
+                               None,
                                Some(item.span));
 
     set_always_inline(fcx.llfn);
@@ -628,7 +618,7 @@ pub fn trans_intrinsic(ccx: @mut CrateContext,
         set_fixed_stack_segment(fcx.llfn);
     }
 
-    let mut bcx = top_scope_block(fcx, None);
+    let mut bcx = fcx.entry_bcx.get();
     let first_real_arg = fcx.arg_pos(0u);
 
     let nm = ccx.sess.str_of(item.ident);
@@ -694,6 +684,7 @@ pub fn trans_intrinsic(ccx: @mut CrateContext,
             }
         }
 
+        fcx.cleanup();
         return;
     }
 
@@ -942,6 +933,7 @@ pub fn trans_intrinsic(ccx: @mut CrateContext,
             ccx.sess.span_bug(item.span, "unknown intrinsic");
         }
     }
+    fcx.cleanup();
 }
 
 /**
diff --git a/src/librustc/middle/trans/glue.rs b/src/librustc/middle/trans/glue.rs
index 4a2072364e9..d3f5b9844c9 100644
--- a/src/librustc/middle/trans/glue.rs
+++ b/src/librustc/middle/trans/glue.rs
@@ -615,7 +615,7 @@ pub fn make_take_glue(bcx: block, v: ValueRef, t: ty::t) -> block {
             // Zero out the struct
             unsafe {
                 let ty = Type::from_ref(llvm::LLVMTypeOf(v));
-                memzero(bcx, v, ty);
+                memzero(&B(bcx), v, ty);
             }
 
           }
@@ -707,13 +707,12 @@ pub fn make_generic_glue_inner(ccx: @mut CrateContext,
     // llfn is expected be declared to take a parameter of the appropriate
     // type, so we don't need to explicitly cast the function parameter.
 
-    let bcx = top_scope_block(fcx, None);
-    let lltop = bcx.llbb;
+    let bcx = fcx.entry_bcx.get();
     let rawptr0_arg = fcx.arg_pos(0u);
     let llrawptr0 = unsafe { llvm::LLVMGetParam(llfn, rawptr0_arg as c_uint) };
     let bcx = helper(bcx, llrawptr0, t);
 
-    finish_fn(fcx, lltop, bcx);
+    finish_fn(fcx, bcx);
 
     return llfn;
 }
diff --git a/src/librustc/middle/trans/reflect.rs b/src/librustc/middle/trans/reflect.rs
index 49f9f4481b9..6df1df454ff 100644
--- a/src/librustc/middle/trans/reflect.rs
+++ b/src/librustc/middle/trans/reflect.rs
@@ -303,7 +303,7 @@ impl Reflector {
                     //
                     llvm::LLVMGetParam(llfdecl, fcx.arg_pos(0u) as c_uint)
                 };
-                let mut bcx = top_scope_block(fcx, None);
+                let mut bcx = fcx.entry_bcx.get();
                 let arg = BitCast(bcx, arg, llptrty);
                 let ret = adt::trans_get_discr(bcx, repr, arg);
                 Store(bcx, ret, fcx.llretptr.get());
@@ -311,7 +311,7 @@ impl Reflector {
                     Some(llreturn) => cleanup_and_Br(bcx, bcx, llreturn),
                     None => bcx = cleanup_block(bcx, Some(bcx.llbb))
                 };
-                finish_fn(fcx, bcx.llbb, bcx);
+                finish_fn(fcx, bcx);
                 llfdecl
             };
 
diff --git a/src/rustllvm/rustllvm.def.in b/src/rustllvm/rustllvm.def.in
index 5b6c3ed2f52..48888760fc6 100644
--- a/src/rustllvm/rustllvm.def.in
+++ b/src/rustllvm/rustllvm.def.in
@@ -409,6 +409,7 @@ LLVMInsertBasicBlock
 LLVMInsertBasicBlockInContext
 LLVMInsertIntoBuilder
 LLVMInsertIntoBuilderWithName
+LLVMInstructionEraseFromParent
 LLVMInt16Type
 LLVMInt16TypeInContext
 LLVMInt1Type