提交 0676c3bf 编写于 作者: J Jorge Aparicio

librustc_trans: use unboxed closures

上级 0d4d8b9b
......@@ -488,8 +488,12 @@ unsafe fn optimize_and_codegen(cgcx: &CodegenContext,
// pass manager passed to the closure should be ensured to not
// escape the closure itself, and the manager should only be
// used once.
unsafe fn with_codegen(tm: TargetMachineRef, llmod: ModuleRef,
no_builtins: bool, f: |PassManagerRef|) {
unsafe fn with_codegen<F>(tm: TargetMachineRef,
llmod: ModuleRef,
no_builtins: bool,
f: F) where
F: FnOnce(PassManagerRef),
{
let cpm = llvm::LLVMCreatePassManager();
llvm::LLVMRustAddAnalysisPasses(tm, cpm, llmod);
llvm::LLVMRustAddLibraryInfo(cpm, llmod, no_builtins);
......
......@@ -79,7 +79,9 @@ struct DxrVisitor<'l, 'tcx: 'l> {
}
impl <'l, 'tcx> DxrVisitor<'l, 'tcx> {
fn nest(&mut self, scope_id: NodeId, f: |&mut DxrVisitor<'l, 'tcx>|) {
fn nest<F>(&mut self, scope_id: NodeId, f: F) where
F: FnOnce(&mut DxrVisitor<'l, 'tcx>),
{
let parent_scope = self.cur_scope;
self.cur_scope = scope_id;
f(self);
......
......@@ -1578,14 +1578,15 @@ pub fn store_for_loop_binding<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
bind_irrefutable_pat(bcx, pat, llvalue, body_scope)
}
fn mk_binding_alloca<'blk, 'tcx, A>(bcx: Block<'blk, 'tcx>,
p_id: ast::NodeId,
ident: &ast::Ident,
cleanup_scope: cleanup::ScopeId,
arg: A,
populate: |A, Block<'blk, 'tcx>, ValueRef, Ty<'tcx>|
-> Block<'blk, 'tcx>)
-> Block<'blk, 'tcx> {
fn mk_binding_alloca<'blk, 'tcx, A, F>(bcx: Block<'blk, 'tcx>,
p_id: ast::NodeId,
ident: &ast::Ident,
cleanup_scope: cleanup::ScopeId,
arg: A,
populate: F)
-> Block<'blk, 'tcx> where
F: FnOnce(A, Block<'blk, 'tcx>, ValueRef, Ty<'tcx>) -> Block<'blk, 'tcx>,
{
let var_ty = node_id_type(bcx, p_id);
// Allocate memory on stack for the binding.
......
......@@ -858,10 +858,13 @@ pub fn struct_field_ptr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, st: &Struct<'tcx>, v
GEPi(bcx, val, &[0, ix])
}
pub fn fold_variants<'blk, 'tcx>(
bcx: Block<'blk, 'tcx>, r: &Repr<'tcx>, value: ValueRef,
f: |Block<'blk, 'tcx>, &Struct<'tcx>, ValueRef| -> Block<'blk, 'tcx>)
-> Block<'blk, 'tcx> {
pub fn fold_variants<'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>,
r: &Repr<'tcx>,
value: ValueRef,
mut f: F)
-> Block<'blk, 'tcx> where
F: FnMut(Block<'blk, 'tcx>, &Struct<'tcx>, ValueRef) -> Block<'blk, 'tcx>,
{
let fcx = bcx.fcx;
match *r {
Univariant(ref st, _) => {
......
......@@ -107,9 +107,11 @@
RefCell::new(None)
})
pub fn with_insn_ctxt(blk: |&[&'static str]|) {
TASK_LOCAL_INSN_KEY.with(|slot| {
slot.borrow().as_ref().map(|s| blk(s.as_slice()));
pub fn with_insn_ctxt<F>(blk: F) where
F: FnOnce(&[&'static str]),
{
TASK_LOCAL_INSN_KEY.with(move |slot| {
slot.borrow().as_ref().map(move |s| blk(s.as_slice()));
})
}
......@@ -841,12 +843,15 @@ pub fn cast_shift_const_rhs(op: ast::BinOp,
|a, b| unsafe { llvm::LLVMConstZExt(a, b.to_ref()) })
}
pub fn cast_shift_rhs(op: ast::BinOp,
lhs: ValueRef,
rhs: ValueRef,
trunc: |ValueRef, Type| -> ValueRef,
zext: |ValueRef, Type| -> ValueRef)
-> ValueRef {
pub fn cast_shift_rhs<F, G>(op: ast::BinOp,
lhs: ValueRef,
rhs: ValueRef,
trunc: F,
zext: G)
-> ValueRef where
F: FnOnce(ValueRef, Type) -> ValueRef,
G: FnOnce(ValueRef, Type) -> ValueRef,
{
// Shifts may have any size int on the rhs
unsafe {
if ast_util::is_shift_binop(op) {
......@@ -1101,10 +1106,12 @@ pub fn raw_block<'blk, 'tcx>(fcx: &'blk FunctionContext<'blk, 'tcx>,
common::BlockS::new(llbb, is_lpad, None, fcx)
}
pub fn with_cond<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
val: ValueRef,
f: |Block<'blk, 'tcx>| -> Block<'blk, 'tcx>)
-> Block<'blk, 'tcx> {
pub fn with_cond<'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>,
val: ValueRef,
f: F)
-> Block<'blk, 'tcx> where
F: FnOnce(Block<'blk, 'tcx>) -> Block<'blk, 'tcx>,
{
let _icx = push_ctxt("with_cond");
let fcx = bcx.fcx;
let next_cx = fcx.new_temp_block("next");
......
......@@ -342,11 +342,13 @@ pub fn compute_abi_info(ccx: &CrateContext,
atys: &[Type],
rty: Type,
ret_def: bool) -> FnType {
fn x86_64_ty(ccx: &CrateContext,
ty: Type,
is_mem_cls: |cls: &[RegClass]| -> bool,
ind_attr: Attribute)
-> ArgType {
fn x86_64_ty<F>(ccx: &CrateContext,
ty: Type,
is_mem_cls: F,
ind_attr: Attribute)
-> ArgType where
F: FnOnce(&[RegClass]) -> bool,
{
if !ty.is_reg_ty() {
let cls = classify_ty(ty);
if is_mem_cls(cls.as_slice()) {
......
......@@ -781,15 +781,15 @@ pub fn trans_lang_call<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
///
/// For non-lang items, `dest` is always Some, and hence the result is written into memory
/// somewhere. Nonetheless we return the actual return value of the function.
pub fn trans_call_inner<'a, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
call_info: Option<NodeInfo>,
callee_ty: Ty<'tcx>,
get_callee: |bcx: Block<'blk, 'tcx>,
arg_cleanup_scope: cleanup::ScopeId|
-> Callee<'blk, 'tcx>,
args: CallArgs<'a, 'tcx>,
dest: Option<expr::Dest>)
-> Result<'blk, 'tcx> {
pub fn trans_call_inner<'a, 'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>,
call_info: Option<NodeInfo>,
callee_ty: Ty<'tcx>,
get_callee: F,
args: CallArgs<'a, 'tcx>,
dest: Option<expr::Dest>)
-> Result<'blk, 'tcx> where
F: FnOnce(Block<'blk, 'tcx>, cleanup::ScopeId) -> Callee<'blk, 'tcx>,
{
// Introduce a temporary cleanup scope that will contain cleanups
// for the arguments while they are being evaluated. The purpose
// this cleanup is to ensure that, should a panic occur while
......
......@@ -527,7 +527,7 @@ fn pop_scope(&self) -> CleanupScope<'blk, 'tcx> {
self.scopes.borrow_mut().pop().unwrap()
}
fn top_scope<R>(&self, f: |&CleanupScope<'blk, 'tcx>| -> R) -> R {
fn top_scope<R, F>(&self, f: F) -> R where F: FnOnce(&CleanupScope<'blk, 'tcx>) -> R {
f(self.scopes.borrow().last().unwrap())
}
......@@ -1145,5 +1145,5 @@ fn trans_cleanups_to_exit_scope(&'blk self,
fn scopes_len(&self) -> uint;
fn push_scope(&self, scope: CleanupScope<'blk, 'tcx>);
fn pop_scope(&self) -> CleanupScope<'blk, 'tcx>;
fn top_scope<R>(&self, f: |&CleanupScope<'blk, 'tcx>| -> R) -> R;
fn top_scope<R, F>(&self, f: F) -> R where F: FnOnce(&CleanupScope<'blk, 'tcx>) -> R;
}
......@@ -113,15 +113,16 @@ pub fn immediate_rvalue_bcx<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
/// it. The memory will be dropped upon exit from `scope`. The callback `populate` should
/// initialize the memory. If `zero` is true, the space will be zeroed when it is allocated; this
/// is not necessary unless `bcx` does not dominate the end of `scope`.
pub fn lvalue_scratch_datum<'blk, 'tcx, A>(bcx: Block<'blk, 'tcx>,
ty: Ty<'tcx>,
name: &str,
zero: bool,
scope: cleanup::ScopeId,
arg: A,
populate: |A, Block<'blk, 'tcx>, ValueRef|
-> Block<'blk, 'tcx>)
-> DatumBlock<'blk, 'tcx, Lvalue> {
pub fn lvalue_scratch_datum<'blk, 'tcx, A, F>(bcx: Block<'blk, 'tcx>,
ty: Ty<'tcx>,
name: &str,
zero: bool,
scope: cleanup::ScopeId,
arg: A,
populate: F)
-> DatumBlock<'blk, 'tcx, Lvalue> where
F: FnOnce(A, Block<'blk, 'tcx>, ValueRef) -> Block<'blk, 'tcx>,
{
let scratch = if zero {
alloca_zeroed(bcx, ty, name)
} else {
......@@ -339,10 +340,10 @@ pub fn to_appropriate_datum<'blk>(self, bcx: Block<'blk, 'tcx>)
/// here since we can `match self.kind` rather than having to implement
/// generic methods in `KindOps`.)
impl<'tcx> Datum<'tcx, Expr> {
fn match_kind<R>(self,
if_lvalue: |Datum<'tcx, Lvalue>| -> R,
if_rvalue: |Datum<'tcx, Rvalue>| -> R)
-> R {
fn match_kind<R, F, G>(self, if_lvalue: F, if_rvalue: G) -> R where
F: FnOnce(Datum<'tcx, Lvalue>) -> R,
G: FnOnce(Datum<'tcx, Rvalue>) -> R,
{
let Datum { val, ty, kind } = self;
match kind {
LvalueExpr => if_lvalue(Datum::new(val, ty, Lvalue)),
......@@ -455,9 +456,11 @@ pub fn to_llref(self) -> ValueRef {
// datum may also be unsized _without the size information_. It is the
// callers responsibility to package the result in some way to make a valid
// datum in that case (e.g., by making a fat pointer or opened pair).
pub fn get_element<'blk>(&self, bcx: Block<'blk, 'tcx>, ty: Ty<'tcx>,
gep: |ValueRef| -> ValueRef)
-> Datum<'tcx, Lvalue> {
pub fn get_element<'blk, F>(&self, bcx: Block<'blk, 'tcx>, ty: Ty<'tcx>,
gep: F)
-> Datum<'tcx, Lvalue> where
F: FnOnce(ValueRef) -> ValueRef,
{
let val = match self.ty.sty {
_ if ty::type_is_sized(bcx.tcx(), self.ty) => gep(self.val),
ty::ty_open(_) => {
......
......@@ -3212,13 +3212,13 @@ struct ScopeStackEntry {
});
// local helper functions for walking the AST.
fn with_new_scope(cx: &CrateContext,
scope_span: Span,
scope_stack: &mut Vec<ScopeStackEntry> ,
scope_map: &mut NodeMap<DIScope>,
inner_walk: |&CrateContext,
&mut Vec<ScopeStackEntry> ,
&mut NodeMap<DIScope>|) {
fn with_new_scope<F>(cx: &CrateContext,
scope_span: Span,
scope_stack: &mut Vec<ScopeStackEntry> ,
scope_map: &mut NodeMap<DIScope>,
inner_walk: F) where
F: FnOnce(&CrateContext, &mut Vec<ScopeStackEntry>, &mut NodeMap<DIScope>),
{
// Create a new lexical scope and push it onto the stack
let loc = cx.sess().codemap().lookup_char_pos(scope_span.lo);
let file_metadata = file_metadata(cx, loc.file.name.as_slice());
......
......@@ -295,6 +295,7 @@ fn ref_ptr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
// into a type to be destructed. If we want to end up with a Box pointer,
// then mk_ty should make a Box pointer (T -> Box<T>), if we want a
// borrowed reference then it should be T -> &T.
// FIXME(#19596) unbox `mk_ty`
fn unsized_info<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
kind: &ty::UnsizeKind<'tcx>,
id: ast::NodeId,
......@@ -341,27 +342,30 @@ fn unsize_expr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
debug!("dest_ty={}", unsized_ty.repr(bcx.tcx()));
// Closures for extracting and manipulating the data and payload parts of
// the fat pointer.
let base = match k {
&ty::UnsizeStruct(..) =>
|bcx, val| PointerCast(bcx,
val,
type_of::type_of(bcx.ccx(), unsized_ty).ptr_to()),
&ty::UnsizeLength(..) =>
|bcx, val| GEPi(bcx, val, &[0u, 0u]),
&ty::UnsizeVtable(..) =>
|_bcx, val| PointerCast(bcx, val, Type::i8p(bcx.ccx()))
};
let info = |bcx, _val| unsized_info(bcx,
k,
expr.id,
datum_ty,
|t| ty::mk_rptr(tcx,
ty::ReStatic,
ty::mt{
ty: t,
mutbl: ast::MutImmutable
}));
into_fat_ptr(bcx, expr, datum, dest_ty, base, info)
let info = |: bcx, _val| unsized_info(bcx,
k,
expr.id,
datum_ty,
|t| ty::mk_rptr(tcx,
ty::ReStatic,
ty::mt{
ty: t,
mutbl: ast::MutImmutable
}));
match *k {
ty::UnsizeStruct(..) =>
into_fat_ptr(bcx, expr, datum, dest_ty, |bcx, val| {
PointerCast(bcx, val, type_of::type_of(bcx.ccx(), unsized_ty).ptr_to())
}, info),
ty::UnsizeLength(..) =>
into_fat_ptr(bcx, expr, datum, dest_ty, |bcx, val| {
GEPi(bcx, val, &[0u, 0u])
}, info),
ty::UnsizeVtable(..) =>
into_fat_ptr(bcx, expr, datum, dest_ty, |_bcx, val| {
PointerCast(bcx, val, Type::i8p(bcx.ccx()))
}, info),
}
}
fn ref_fat_ptr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
......@@ -370,18 +374,21 @@ fn ref_fat_ptr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
-> DatumBlock<'blk, 'tcx, Expr> {
let tcx = bcx.tcx();
let dest_ty = ty::close_type(tcx, datum.ty);
let base = |bcx, val| Load(bcx, get_dataptr(bcx, val));
let len = |bcx, val| Load(bcx, get_len(bcx, val));
let base = |: bcx, val| Load(bcx, get_dataptr(bcx, val));
let len = |: bcx, val| Load(bcx, get_len(bcx, val));
into_fat_ptr(bcx, expr, datum, dest_ty, base, len)
}
fn into_fat_ptr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
expr: &ast::Expr,
datum: Datum<'tcx, Expr>,
dest_ty: Ty<'tcx>,
base: |Block<'blk, 'tcx>, ValueRef| -> ValueRef,
info: |Block<'blk, 'tcx>, ValueRef| -> ValueRef)
-> DatumBlock<'blk, 'tcx, Expr> {
fn into_fat_ptr<'blk, 'tcx, F, G>(bcx: Block<'blk, 'tcx>,
expr: &ast::Expr,
datum: Datum<'tcx, Expr>,
dest_ty: Ty<'tcx>,
base: F,
info: G)
-> DatumBlock<'blk, 'tcx, Expr> where
F: FnOnce(Block<'blk, 'tcx>, ValueRef) -> ValueRef,
G: FnOnce(Block<'blk, 'tcx>, ValueRef) -> ValueRef,
{
let mut bcx = bcx;
// Arrange cleanup
......@@ -659,17 +666,19 @@ fn trans_datum_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
}
}
fn trans_field<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
base: &ast::Expr,
get_idx: |&'blk ty::ctxt<'tcx>, &[ty::field<'tcx>]| -> uint)
-> DatumBlock<'blk, 'tcx, Expr> {
fn trans_field<'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>,
base: &ast::Expr,
get_idx: F)
-> DatumBlock<'blk, 'tcx, Expr> where
F: FnOnce(&'blk ty::ctxt<'tcx>, &[ty::field<'tcx>]) -> uint,
{
let mut bcx = bcx;
let _icx = push_ctxt("trans_rec_field");
let base_datum = unpack_datum!(bcx, trans_to_lvalue(bcx, base, "field"));
let bare_ty = ty::unopen_type(base_datum.ty);
let repr = adt::represent_type(bcx.ccx(), bare_ty);
with_field_tys(bcx.tcx(), bare_ty, None, |discr, field_tys| {
with_field_tys(bcx.tcx(), bare_ty, None, move |discr, field_tys| {
let ix = get_idx(bcx.tcx(), field_tys);
let d = base_datum.get_element(
bcx,
......@@ -1254,11 +1263,13 @@ pub fn trans_local_var<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
/// Helper for enumerating the field types of structs, enums, or records. The optional node ID here
/// is the node ID of the path identifying the enum variant in use. If none, this cannot possibly
/// an enum variant (so, if it is and `node_id_opt` is none, this function panics).
pub fn with_field_tys<'tcx, R>(tcx: &ty::ctxt<'tcx>,
ty: Ty<'tcx>,
node_id_opt: Option<ast::NodeId>,
op: |ty::Disr, (&[ty::field<'tcx>])| -> R)
-> R {
pub fn with_field_tys<'tcx, R, F>(tcx: &ty::ctxt<'tcx>,
ty: Ty<'tcx>,
node_id_opt: Option<ast::NodeId>,
op: F)
-> R where
F: FnOnce(ty::Disr, &[ty::field<'tcx>]) -> R,
{
match ty.sty {
ty::ty_struct(did, ref substs) => {
op(0, struct_fields(tcx, did, substs).as_slice())
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册