pub fn trans_closure<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                               decl: &hir::FnDecl,
                               body: &hir::Block,
                               llfndecl: ValueRef,
                               instance: Instance<'tcx>,
                               inlined_id: ast::NodeId,
                               sig: &ty::FnSig<'tcx>,
                               abi: Abi,
                               closure_env: closure::ClosureEnv) {
    ccx.stats().n_closures.set(ccx.stats().n_closures.get() + 1);

    let _icx = push_ctxt("trans_closure");
    if !ccx.sess().no_landing_pads() {
        attributes::emit_uwtable(llfndecl, true);
    }

    // this is an info! to allow collecting monomorphization statistics
    // and to allow finding the last function before LLVM aborts from
    // release builds.
    info!("trans_closure(..., {})", instance);

    let fn_ty = FnType::new(ccx, abi, sig, &[]);

    let (arena, fcx): (TypedArena<_>, FunctionContext);
    arena = TypedArena::new();
    fcx = FunctionContext::new(ccx,
                               llfndecl,
                               fn_ty,
                               Some((instance, sig, abi, inlined_id)),
                               &arena);

    if fcx.mir.is_some() {
        return mir::trans_mir(&fcx);
    }

    debuginfo::fill_scope_map_for_function(&fcx, decl, body, inlined_id);

    // cleanup scope for the incoming arguments
    let fn_cleanup_debug_loc = debuginfo::get_cleanup_debug_loc_for_ast_node(
        ccx, inlined_id, body.span, true);
    let arg_scope = fcx.push_custom_cleanup_scope_with_debug_loc(fn_cleanup_debug_loc);

    // Set up arguments to the function.
    debug!("trans_closure: function: {:?}", Value(fcx.llfn));
    let bcx = fcx.bind_args(&decl.inputs, abi, inlined_id, closure_env, arg_scope);

    // Up until here, IR instructions for this function have explicitly not been annotated with
    // source code location, so we don't step into call setup code. From here on, source location
    // emitting should be enabled.
    debuginfo::start_emitting_source_locations(&fcx);

    let dest = if fcx.fn_ty.ret.is_ignore() {
        expr::Ignore
    } else {
        expr::SaveIn(fcx.get_ret_slot(bcx, "iret_slot"))
    };

    // This call to trans_block is the place where we bridge between
    // translation calls that don't have a return value (trans_crate,
    // trans_mod, trans_item, et cetera) and those that do
    // (trans_block, trans_expr, et cetera).
    let mut bcx = controlflow::trans_block(bcx, body, dest);

    match dest {
        expr::SaveIn(slot) if fcx.needs_ret_allocas => {
            Store(bcx, slot, fcx.llretslotptr.get().unwrap());
        }
        _ => {}
    }

    match fcx.llreturn.get() {
        Some(_) => {
            Br(bcx, fcx.return_exit_block(), DebugLoc::None);
            fcx.pop_custom_cleanup_scope(arg_scope);
        }
        None => {
            // Microoptimization writ large: avoid creating a separate
            // llreturn basic block
            bcx = fcx.pop_and_trans_custom_cleanup_scope(bcx, arg_scope);
        }
    };

    // Put return block after all other blocks.
    // This somewhat improves single-stepping experience in debugger.
    unsafe {
        let llreturn = fcx.llreturn.get();
        if let Some(llreturn) = llreturn {
            llvm::LLVMMoveBasicBlockAfter(llreturn, bcx.llbb);
        }
    }

    // Insert the mandatory first few basic blocks before lltop.
    fcx.finish(bcx, fn_cleanup_debug_loc.debug_loc());
}
/// Builds an LLVM function out of a source function.
///
/// If the function closes over its environment a closure will be returned.
Builds an LLVM function out of a source function.
If the function closes over its environment a closure will be returned.
Builds an LLVM function out of a source function . If the function closes over its environment a closure will be returned .
pub fn trans_closure<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                               decl: &hir::FnDecl,
                               body: &hir::Block,
                               llfndecl: ValueRef,
                               instance: Instance<'tcx>,
                               inlined_id: ast::NodeId,
                               sig: &ty::FnSig<'tcx>,
                               abi: Abi,
                               closure_env: closure::ClosureEnv) {
    ccx.stats().n_closures.set(ccx.stats().n_closures.get() + 1);
    let _icx = push_ctxt("trans_closure");
    if !ccx.sess().no_landing_pads() {
        attributes::emit_uwtable(llfndecl, true);
    }
    // this is an info! to allow collecting monomorphization statistics
    // and to allow finding the last function before LLVM aborts from
    // release builds.
    info!("trans_closure(..., {})", instance);
    let fn_ty = FnType::new(ccx, abi, sig, &[]);
    let (arena, fcx): (TypedArena<_>, FunctionContext);
    arena = TypedArena::new();
    fcx = FunctionContext::new(ccx,
                               llfndecl,
                               fn_ty,
                               Some((instance, sig, abi, inlined_id)),
                               &arena);
    if fcx.mir.is_some() {
        return mir::trans_mir(&fcx);
    }
    debuginfo::fill_scope_map_for_function(&fcx, decl, body, inlined_id);
    // cleanup scope for the incoming arguments
    let fn_cleanup_debug_loc = debuginfo::get_cleanup_debug_loc_for_ast_node(
        ccx, inlined_id, body.span, true);
    let arg_scope = fcx.push_custom_cleanup_scope_with_debug_loc(fn_cleanup_debug_loc);
    // Set up arguments to the function.
    debug!("trans_closure: function: {:?}", Value(fcx.llfn));
    let bcx = fcx.bind_args(&decl.inputs, abi, inlined_id, closure_env, arg_scope);
    // Up until here, IR instructions for this function have explicitly not been annotated with
    // source code location, so we don't step into call setup code. From here on, source location
    // emitting should be enabled.
    debuginfo::start_emitting_source_locations(&fcx);
    let dest = if fcx.fn_ty.ret.is_ignore() {
        expr::Ignore
    } else {
        expr::SaveIn(fcx.get_ret_slot(bcx, "iret_slot"))
    };
    // This call to trans_block is the place where we bridge between
    // translation calls that don't have a return value (trans_crate,
    // trans_mod, trans_item, et cetera) and those that do
    // (trans_block, trans_expr, et cetera).
    let mut bcx = controlflow::trans_block(bcx, body, dest);
    match dest {
        expr::SaveIn(slot) if fcx.needs_ret_allocas => {
            Store(bcx, slot, fcx.llretslotptr.get().unwrap());
        }
        _ => {}
    }
    match fcx.llreturn.get() {
        Some(_) => {
            Br(bcx, fcx.return_exit_block(), DebugLoc::None);
            fcx.pop_custom_cleanup_scope(arg_scope);
        }
        None => {
            // Microoptimization writ large: avoid creating a separate
            // llreturn basic block
            bcx = fcx.pop_and_trans_custom_cleanup_scope(bcx, arg_scope);
        }
    };
    // Put return block after all other blocks.
    // This somewhat improves single-stepping experience in debugger.
    unsafe {
        let llreturn = fcx.llreturn.get();
        if let Some(llreturn) = llreturn {
            llvm::LLVMMoveBasicBlockAfter(llreturn, bcx.llbb);
        }
    }
    // Insert the mandatory first few basic blocks before lltop.
    fcx.finish(bcx, fn_cleanup_debug_loc.debug_loc());
}
pub fn trans_closure < ' a , ' tcx > ( ccx : & CrateContext < ' a , ' tcx > , decl : & hir :: FnDecl , body : & hir :: Block , llfndecl : ValueRef , instance : Instance < ' tcx > , inlined_id : ast :: NodeId , sig : & ty :: FnSig < ' tcx > , abi : Abi , closure_env : closure :: ClosureEnv ) { ccx . stats ( ) . n_closures . set ( ccx . stats ( ) . n_closures . get ( ) + 1 ) ; let _icx = push_ctxt ( " " ) ; if ! ccx . sess ( ) . no_landing_pads ( ) { attributes :: emit_uwtable ( llfndecl , true ) ; } // this is an info! to allow collecting monomorphization statistics // and to allow finding the last function before LLVM aborts from // release builds. info ! ( " " instance ) ; let fn_ty = FnType :: new ( ccx , abi , sig , & [ ] ) ; let ( arena , fcx ) : ( TypedArena < _ > , FunctionContext ) ; arena = TypedArena :: new ( ) ; fcx = FunctionContext :: new ( ccx , llfndecl , fn_ty , Some ( ( instance , sig , abi , inlined_id ) ) , & arena ) ; if fcx . mir . is_some ( ) { return mir :: trans_mir ( & fcx ) ; } debuginfo :: fill_scope_map_for_function ( & fcx , decl , body , inlined_id ) ; // cleanup scope for the incoming arguments let fn_cleanup_debug_loc = debuginfo :: get_cleanup_debug_loc_for_ast_node ( ccx , inlined_id , body . span , true ) ; let arg_scope = fcx . push_custom_cleanup_scope_with_debug_loc ( fn_cleanup_debug_loc ) ; // Set up arguments to the function. debug ! ( " " Value ( fcx llfn ) ) ; let bcx = fcx . bind_args ( & decl . inputs , abi , inlined_id , closure_env , arg_scope ) ; // Up until here, IR instructions for this function have explicitly not been annotated with // source code location, so we don't step into call setup code. From here on, source location // emitting should be enabled. debuginfo :: start_emitting_source_locations ( & fcx ) ; let dest = if fcx . fn_ty . ret . is_ignore ( ) { expr :: Ignore } else { expr :: SaveIn ( fcx . get_ret_slot ( bcx , " " ) ) } ; // This call to trans_block is the place where we bridge between // translation calls that don't have a return value (trans_crate, // trans_mod, trans_item, et cetera) and those that do // (trans_block, trans_expr, et cetera). let mut bcx = controlflow :: trans_block ( bcx , body , dest ) ; match dest { expr :: SaveIn ( slot ) if fcx . needs_ret_allocas => { Store ( bcx , slot , fcx . llretslotptr . get ( ) . unwrap ( ) ) ; } _ => { } } match fcx . llreturn . get ( ) { Some ( _ ) => { Br ( bcx , fcx . return_exit_block ( ) , DebugLoc :: None ) ; fcx . pop_custom_cleanup_scope ( arg_scope ) ; } None => { // Microoptimization writ large: avoid creating a separate // llreturn basic block bcx = fcx . pop_and_trans_custom_cleanup_scope ( bcx , arg_scope ) ; } } ; // Put return block after all other blocks. // This somewhat improves single-stepping experience in debugger. unsafe { let llreturn = fcx . llreturn . get ( ) ; if let Some ( llreturn ) = llreturn { llvm :: LLVMMoveBasicBlockAfter ( llreturn , bcx . llbb ) ; } } // Insert the mandatory first few basic blocks before lltop. fcx . finish ( bcx , fn_cleanup_debug_loc . debug_loc ( ) ) ; }
Builds an LLVM function out of a source function.
Builds an LLVM function out of a source function .
ccx
&CrateContext<'a, 'tcx>
decl
&hir::FnDecl
body
&hir::Block
llfndecl
ValueRef
instance
Instance<'tcx>
inlined_id
ast::NodeId
sig
&ty::FnSig<'tcx>
abi
Abi
closure_env
closure::ClosureEnv
ccx
&CrateContext<'a, 'tcx>
decl
&hir::FnDecl
body
&hir::Block
llfndecl
ValueRef
instance
Instance<'tcx>
inlined_id
ast::NodeId
sig
&ty::FnSig<'tcx>
abi
Abi
closure_env
closure::ClosureEnv