about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorMark-Simulacrum <mark.simulacrum@gmail.com>2016-12-16 08:28:20 -0700
committerMark Simulacrum <mark.simulacrum@gmail.com>2016-12-20 20:02:52 -0700
commit28f511cfbd9faaec4cc54ea002b43bacb3da497c (patch)
tree578c7aeb0c4f8dc39e58b2fe9627d1ecec6eed3b /src
parente0ccc81bbf0069bf968a741594dd81338cf98ac3 (diff)
downloadrust-28f511cfbd9faaec4cc54ea002b43bacb3da497c.tar.gz
rust-28f511cfbd9faaec4cc54ea002b43bacb3da497c.zip
Remove global Builder
Diffstat (limited to 'src')
-rw-r--r--src/librustc_trans/base.rs96
-rw-r--r--src/librustc_trans/common.rs104
-rw-r--r--src/librustc_trans/context.rs5
3 files changed, 99 insertions, 106 deletions
diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs
index 06a368e896c..4f346f8897e 100644
--- a/src/librustc_trans/base.rs
+++ b/src/librustc_trans/base.rs
@@ -53,7 +53,7 @@ use builder::{Builder, noname};
 use callee::{Callee};
 use common::{BlockAndBuilder, C_bool, C_bytes_in_context, C_i32, C_uint};
 use collector::{self, TransItemCollectionMode};
-use common::{C_null, C_struct_in_context, C_u64, C_u8, C_undef};
+use common::{C_struct_in_context, C_u64, C_u8, C_undef};
 use common::{CrateContext, FunctionContext};
 use common::{fulfill_obligation};
 use common::{type_is_zero_size, val_ty};
@@ -77,10 +77,9 @@ use value::Value;
 use Disr;
 use util::nodemap::{NodeSet, FxHashMap, FxHashSet};
 
-use arena::TypedArena;
 use libc::c_uint;
 use std::ffi::{CStr, CString};
-use std::cell::{Cell, RefCell};
+use std::cell::RefCell;
 use std::ptr;
 use std::rc::Rc;
 use std::str;
@@ -655,97 +654,6 @@ pub fn alloca(cx: &BlockAndBuilder, ty: Type, name: &str) -> ValueRef {
 }
 
 impl<'blk, 'tcx> FunctionContext<'blk, 'tcx> {
-    /// Create a function context for the given function.
-    /// Beware that you must call `fcx.init` or `fcx.bind_args`
-    /// before doing anything with the returned function context.
-    pub fn new(ccx: &'blk CrateContext<'blk, 'tcx>,
-               llfndecl: ValueRef,
-               fn_ty: FnType,
-               definition: Option<(Instance<'tcx>, &ty::FnSig<'tcx>, Abi)>)
-               -> FunctionContext<'blk, 'tcx> {
-        let (param_substs, def_id) = match definition {
-            Some((instance, ..)) => {
-                common::validate_substs(instance.substs);
-                (instance.substs, Some(instance.def))
-            }
-            None => (ccx.tcx().intern_substs(&[]), None)
-        };
-
-        let local_id = def_id.and_then(|id| ccx.tcx().map.as_local_node_id(id));
-
-        debug!("FunctionContext::new({})",
-               definition.map_or(String::new(), |d| d.0.to_string()));
-
-        let no_debug = if let Some(id) = local_id {
-            ccx.tcx().map.attrs(id)
-               .iter().any(|item| item.check_name("no_debug"))
-        } else if let Some(def_id) = def_id {
-            ccx.sess().cstore.item_attrs(def_id)
-               .iter().any(|item| item.check_name("no_debug"))
-        } else {
-            false
-        };
-
-        let mir = def_id.map(|id| ccx.tcx().item_mir(id));
-
-        let debug_context = if let (false, Some((instance, sig, abi)), &Some(ref mir)) =
-                (no_debug, definition, &mir) {
-            debuginfo::create_function_debug_context(ccx, instance, sig, abi, llfndecl, mir)
-        } else {
-            debuginfo::empty_function_debug_context(ccx)
-        };
-
-        FunctionContext {
-            mir: mir,
-            llfn: llfndecl,
-            llretslotptr: Cell::new(None),
-            param_env: ccx.tcx().empty_parameter_environment(),
-            alloca_insert_pt: Cell::new(None),
-            landingpad_alloca: Cell::new(None),
-            fn_ty: fn_ty,
-            param_substs: param_substs,
-            span: None,
-            funclet_arena: TypedArena::new(),
-            ccx: ccx,
-            debug_context: debug_context,
-        }
-    }
-
-    /// Performs setup on a newly created function, creating the entry
-    /// scope block and allocating space for the return pointer.
-    pub fn init(&'blk self, skip_retptr: bool) -> BlockAndBuilder<'blk, 'tcx> {
-        let entry_bcx = self.build_new_block("entry-block");
-
-        // Use a dummy instruction as the insertion point for all allocas.
-        // This is later removed in FunctionContext::cleanup.
-        self.alloca_insert_pt.set(Some(unsafe {
-            entry_bcx.load(C_null(Type::i8p(self.ccx)));
-            llvm::LLVMGetFirstInstruction(entry_bcx.llbb())
-        }));
-
-        if !self.fn_ty.ret.is_ignore() && !skip_retptr {
-            // We normally allocate the llretslotptr, unless we
-            // have been instructed to skip it for immediate return
-            // values, or there is nothing to return at all.
-
-            // We create an alloca to hold a pointer of type `ret.original_ty`
-            // which will hold the pointer to the right alloca which has the
-            // final ret value
-            let llty = self.fn_ty.ret.memory_ty(self.ccx);
-            // But if there are no nested returns, we skip the indirection
-            // and have a single retslot
-            let slot = if self.fn_ty.ret.is_indirect() {
-                get_param(self.llfn, 0)
-            } else {
-                self.alloca(llty, "sret_slot")
-            };
-
-            self.llretslotptr.set(Some(slot));
-        }
-
-        entry_bcx
-    }
-
     /// Ties up the llstaticallocas -> llloadenv -> lltop edges,
     /// and builds the return block.
     pub fn finish(&'blk self, ret_cx: &BlockAndBuilder<'blk, 'tcx>) {
diff --git a/src/librustc_trans/common.rs b/src/librustc_trans/common.rs
index 6306312c58e..e4c3d6497fd 100644
--- a/src/librustc_trans/common.rs
+++ b/src/librustc_trans/common.rs
@@ -15,7 +15,8 @@
 use session::Session;
 use llvm;
 use llvm::{ValueRef, BasicBlockRef, BuilderRef, ContextRef, TypeKind};
-use llvm::{True, False, Bool, OperandBundleDef};
+use llvm::{True, False, Bool, OperandBundleDef, get_param};
+use monomorphize::Instance;
 use rustc::hir::def::Def;
 use rustc::hir::def_id::DefId;
 use rustc::hir::map::DefPathData;
@@ -311,18 +312,109 @@ pub struct FunctionContext<'a, 'tcx: 'a> {
 
     // Used and maintained by the debuginfo module.
     pub debug_context: debuginfo::FunctionDebugContext,
+
+    owned_builder: OwnedBuilder<'a, 'tcx>,
 }
 
 impl<'a, 'tcx> FunctionContext<'a, 'tcx> {
+    /// Create a function context for the given function.
+    /// Beware that you must call `fcx.init` or `fcx.bind_args`
+    /// before doing anything with the returned function context.
+    pub fn new(ccx: &'a CrateContext<'a, 'tcx>,
+               llfndecl: ValueRef,
+               fn_ty: FnType,
+               definition: Option<(Instance<'tcx>, &ty::FnSig<'tcx>, Abi)>)
+               -> FunctionContext<'a, 'tcx> {
+        let (param_substs, def_id) = match definition {
+            Some((instance, ..)) => {
+                validate_substs(instance.substs);
+                (instance.substs, Some(instance.def))
+            }
+            None => (ccx.tcx().intern_substs(&[]), None)
+        };
+
+        let local_id = def_id.and_then(|id| ccx.tcx().map.as_local_node_id(id));
+
+        debug!("FunctionContext::new({})", definition.map_or(String::new(), |d| d.0.to_string()));
+
+        let no_debug = if let Some(id) = local_id {
+            ccx.tcx().map.attrs(id).iter().any(|item| item.check_name("no_debug"))
+        } else if let Some(def_id) = def_id {
+            ccx.sess().cstore.item_attrs(def_id).iter().any(|item| item.check_name("no_debug"))
+        } else {
+            false
+        };
+
+        let mir = def_id.map(|id| ccx.tcx().item_mir(id));
+
+        let debug_context = if let (false, Some((instance, sig, abi)), &Some(ref mir)) =
+                (no_debug, definition, &mir) {
+            debuginfo::create_function_debug_context(ccx, instance, sig, abi, llfndecl, mir)
+        } else {
+            debuginfo::empty_function_debug_context(ccx)
+        };
+
+        FunctionContext {
+            mir: mir,
+            llfn: llfndecl,
+            llretslotptr: Cell::new(None),
+            param_env: ccx.tcx().empty_parameter_environment(),
+            alloca_insert_pt: Cell::new(None),
+            landingpad_alloca: Cell::new(None),
+            fn_ty: fn_ty,
+            param_substs: param_substs,
+            span: None,
+            funclet_arena: TypedArena::new(),
+            ccx: ccx,
+            debug_context: debug_context,
+            owned_builder: OwnedBuilder::new_with_ccx(ccx),
+        }
+    }
+
+    /// Performs setup on a newly created function, creating the entry
+    /// scope block and allocating space for the return pointer.
+    pub fn init(&'a self, skip_retptr: bool) -> BlockAndBuilder<'a, 'tcx> {
+        let entry_bcx = self.build_new_block("entry-block");
+
+        // Use a dummy instruction as the insertion point for all allocas.
+        // This is later removed in FunctionContext::cleanup.
+        self.alloca_insert_pt.set(Some(unsafe {
+            entry_bcx.load(C_null(Type::i8p(self.ccx)));
+            llvm::LLVMGetFirstInstruction(entry_bcx.llbb())
+        }));
+
+        self.owned_builder.builder.position_at_start(entry_bcx.llbb());
+
+        if !self.fn_ty.ret.is_ignore() && !skip_retptr {
+            // We normally allocate the llretslotptr, unless we
+            // have been instructed to skip it for immediate return
+            // values, or there is nothing to return at all.
+
+            // We create an alloca to hold a pointer of type `ret.original_ty`
+            // which will hold the pointer to the right alloca which has the
+            // final ret value
+            let llty = self.fn_ty.ret.memory_ty(self.ccx);
+            // But if there are no nested returns, we skip the indirection
+            // and have a single retslot
+            let slot = if self.fn_ty.ret.is_indirect() {
+                get_param(self.llfn, 0)
+            } else {
+                self.alloca(llty, "sret_slot")
+            };
+
+            self.llretslotptr.set(Some(slot));
+        }
+
+        entry_bcx
+    }
+
     pub fn mir(&self) -> Ref<'tcx, Mir<'tcx>> {
         self.mir.as_ref().map(Ref::clone).expect("fcx.mir was empty")
     }
 
     pub fn cleanup(&self) {
         unsafe {
-            llvm::LLVMInstructionEraseFromParent(self.alloca_insert_pt
-                                                     .get()
-                                                     .unwrap());
+            llvm::LLVMInstructionEraseFromParent(self.alloca_insert_pt.get().unwrap());
         }
     }
 
@@ -431,9 +523,7 @@ impl<'a, 'tcx> FunctionContext<'a, 'tcx> {
     }
 
     pub fn alloca(&self, ty: Type, name: &str) -> ValueRef {
-        let b = self.ccx.builder();
-        b.position_before(self.alloca_insert_pt.get().unwrap());
-        b.alloca(ty, name)
+        self.owned_builder.builder.alloca(ty, name)
     }
 }
 
diff --git a/src/librustc_trans/context.rs b/src/librustc_trans/context.rs
index 6435b20eeaa..4f524af2945 100644
--- a/src/librustc_trans/context.rs
+++ b/src/librustc_trans/context.rs
@@ -17,7 +17,6 @@ use rustc::hir::def::ExportMap;
 use rustc::hir::def_id::DefId;
 use rustc::traits;
 use base;
-use builder::Builder;
 use common::BuilderRef_res;
 use debuginfo;
 use declare;
@@ -731,10 +730,6 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> {
         &self.shared.tcx.sess
     }
 
-    pub fn builder<'a>(&'a self) -> Builder<'a, 'tcx> {
-        Builder::new(self)
-    }
-
     pub fn raw_builder<'a>(&'a self) -> BuilderRef {
         self.local().builder.b
     }