Remove global Builder
This commit is contained in:
parent
e0ccc81bbf
commit
28f511cfbd
3 changed files with 99 additions and 106 deletions
|
|
@ -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>) {
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue