/// Creates lvalue datums for each of the incoming function arguments,
/// matches all argument patterns against them to produce bindings,
/// and returns the entry block (see FunctionContext::init).
Creates lvalue datums for each of the incoming function arguments,
matches all argument patterns against them to produce bindings,
and returns the entry block .
Creates lvalue datums for each of the incoming function arguments matches all argument patterns against them to produce bindings and returns the entry block .
fn bind_args(&'blk self,
                 args: &[hir::Arg],
                 abi: Abi,
                 id: ast::NodeId,
                 closure_env: closure::ClosureEnv,
                 arg_scope: cleanup::CustomScopeIndex)
                 -> Block<'blk, 'tcx> {
        let _icx = push_ctxt("FunctionContext::bind_args");
        let fn_did = self.ccx.tcx().map.local_def_id(id);
        let mut bcx = self.init(false, Some(fn_did));
        let arg_scope_id = cleanup::CustomScope(arg_scope);
        let mut idx = 0;
        let mut llarg_idx = self.fn_ty.ret.is_indirect() as usize;
        let has_tupled_arg = match closure_env {
            closure::ClosureEnv::NotClosure => abi == Abi::RustCall,
            closure::ClosureEnv::Closure(..) => {
                closure_env.load(bcx, arg_scope_id);
                let env_arg = &self.fn_ty.args[idx];
                idx += 1;
                if env_arg.pad.is_some() {
                    llarg_idx += 1;
                }
                if !env_arg.is_ignore() {
                    llarg_idx += 1;
                }
                false
            }
        };
        let tupled_arg_id = if has_tupled_arg {
            args[args.len() - 1].id
        } else {
            ast::DUMMY_NODE_ID
        };
        // Return an array wrapping the ValueRefs that we get from `get_param` for
        // each argument into datums.
        //
        // For certain mode/type combinations, the raw llarg values are passed
        // by value.  However, within the fn body itself, we want to always
        // have all locals and arguments be by-ref so that we can cancel the
        // cleanup and for better interaction with LLVM's debug info.  So, if
        // the argument would be passed by value, we store it into an alloca.
        // This alloca should be optimized away by LLVM's mem-to-reg pass in
        // the event it's not truly needed.
        let uninit_reason = InitAlloca::Uninit("fn_arg populate dominates dtor");
        for hir_arg in args {
            let arg_ty = node_id_type(bcx, hir_arg.id);
            let arg_datum = if hir_arg.id != tupled_arg_id {
                let arg = &self.fn_ty.args[idx];
                idx += 1;
                if arg.is_indirect() && bcx.sess().opts.debuginfo != FullDebugInfo {
                    // Don't copy an indirect argument to an alloca, the caller
                    // already put it in a temporary alloca and gave it up, unless
                    // we emit extra-debug-info, which requires local allocas :(.
                    let llarg = get_param(self.llfn, llarg_idx as c_uint);
                    llarg_idx += 1;
                    self.schedule_lifetime_end(arg_scope_id, llarg);
                    self.schedule_drop_mem(arg_scope_id, llarg, arg_ty, None);
                    datum::Datum::new(llarg,
                                      arg_ty,
                                      datum::Lvalue::new("FunctionContext::bind_args"))
                } else {
                    unpack_datum!(bcx, datum::lvalue_scratch_datum(bcx, arg_ty, "",
                                                                   uninit_reason,
                                                                   arg_scope_id, |bcx, dst| {
                        debug!("FunctionContext::bind_args: {:?}: {:?}", hir_arg, arg_ty);
                        let b = &bcx.build();
                        if common::type_is_fat_ptr(bcx.tcx(), arg_ty) {
                            let meta = &self.fn_ty.args[idx];
                            idx += 1;
                            arg.store_fn_arg(b, &mut llarg_idx, expr::get_dataptr(bcx, dst));
                            meta.store_fn_arg(b, &mut llarg_idx, expr::get_meta(bcx, dst));
                        } else {
                            arg.store_fn_arg(b, &mut llarg_idx, dst);
                        }
                        bcx
                    }))
                }
            } else {
                // FIXME(pcwalton): Reduce the amount of code bloat this is responsible for.
                let tupled_arg_tys = match arg_ty.sty {
                    ty::TyTuple(ref tys) => tys,
                    _ => bug!("last argument of `rust-call` fn isn't a tuple?!")
                };
                unpack_datum!(bcx, datum::lvalue_scratch_datum(bcx,
                                                            arg_ty,
                                                            "tupled_args",
                                                            uninit_reason,
                                                            arg_scope_id,
                                                            |bcx, llval| {
                    debug!("FunctionContext::bind_args: tupled {:?}: {:?}", hir_arg, arg_ty);
                    for (j, &tupled_arg_ty) in tupled_arg_tys.iter().enumerate() {
                        let dst = StructGEP(bcx, llval, j);
                        let arg = &self.fn_ty.args[idx];
                        idx += 1;
                        let b = &bcx.build();
                        if common::type_is_fat_ptr(bcx.tcx(), tupled_arg_ty) {
                            let meta = &self.fn_ty.args[idx];
                            idx += 1;
                            arg.store_fn_arg(b, &mut llarg_idx, expr::get_dataptr(bcx, dst));
                            meta.store_fn_arg(b, &mut llarg_idx, expr::get_meta(bcx, dst));
                        } else {
                            arg.store_fn_arg(b, &mut llarg_idx, dst);
                        }
                    }
                    bcx
                }))
            };
            let pat = &hir_arg.pat;
            bcx = if let Some(name) = simple_name(pat) {
                // Generate nicer LLVM for the common case of fn a pattern
                // like `x: T`
                set_value_name(arg_datum.val, &bcx.name(name));
                self.lllocals.borrow_mut().insert(pat.id, arg_datum);
                bcx
            } else {
                // General path. Copy out the values that are used in the
                // pattern.
                _match::bind_irrefutable_pat(bcx, pat, arg_datum.match_input(), arg_scope_id)
            };
            debuginfo::create_argument_metadata(bcx, hir_arg);
        }
        bcx
    }
fn bind_args ( & ' blk self , args : & [ hir :: Arg ] , abi : Abi , id : ast :: NodeId , closure_env : closure :: ClosureEnv , arg_scope : cleanup :: CustomScopeIndex ) -> Block < ' blk , ' tcx > { let _icx = push_ctxt ( " " ) ; let fn_did = self . ccx . tcx ( ) . map . local_def_id ( id ) ; let mut bcx = self . init ( false , Some ( fn_did ) ) ; let arg_scope_id = cleanup :: CustomScope ( arg_scope ) ; let mut idx = 0 ; let mut llarg_idx = self . fn_ty . ret . is_indirect ( ) as usize ; let has_tupled_arg = match closure_env { closure :: ClosureEnv :: NotClosure => abi == Abi :: RustCall , closure :: ClosureEnv :: Closure ( .. ) => { closure_env . load ( bcx , arg_scope_id ) ; let env_arg = & self . fn_ty . args [ idx ] ; idx += 1 ; if env_arg . pad . is_some ( ) { llarg_idx += 1 ; } if ! env_arg . is_ignore ( ) { llarg_idx += 1 ; } false } } ; let tupled_arg_id = if has_tupled_arg { args [ args . len ( ) - 1 ] . id } else { ast :: DUMMY_NODE_ID } ; // Return an array wrapping the ValueRefs that we get from `get_param` for // each argument into datums. // // For certain mode/type combinations, the raw llarg values are passed // by value.  However, within the fn body itself, we want to always // have all locals and arguments be by-ref so that we can cancel the // cleanup and for better interaction with LLVM's debug info.  So, if // the argument would be passed by value, we store it into an alloca. // This alloca should be optimized away by LLVM's mem-to-reg pass in // the event it's not truly needed. let uninit_reason = InitAlloca :: Uninit ( " " ) ; for hir_arg in args { let arg_ty = node_id_type ( bcx , hir_arg . id ) ; let arg_datum = if hir_arg . id != tupled_arg_id { let arg = & self . fn_ty . args [ idx ] ; idx += 1 ; if arg . is_indirect ( ) && bcx . sess ( ) . opts . debuginfo != FullDebugInfo { // Don't copy an indirect argument to an alloca, the caller // already put it in a temporary alloca and gave it up, unless // we emit extra-debug-info, which requires local allocas :(. let llarg = get_param ( self . llfn , llarg_idx as c_uint ) ; llarg_idx += 1 ; self . schedule_lifetime_end ( arg_scope_id , llarg ) ; self . schedule_drop_mem ( arg_scope_id , llarg , arg_ty , None ) ; datum :: Datum :: new ( llarg , arg_ty , datum :: Lvalue :: new ( " " ) ) } else { unpack_datum ! ( bcx datum lvalue_scratch_datum ( bcx arg_ty " " uninit_reason arg_scope_id bcx dst { debug ( " " hir_arg arg_ty ) let b bcx build ( ) if common type_is_fat_ptr ( bcx tcx ( ) arg_ty ) { let meta self fn_ty args [ idx ] idx 1 arg store_fn_arg ( b mut llarg_idx expr get_dataptr ( bcx dst ) ) meta store_fn_arg ( b mut llarg_idx expr get_meta ( bcx dst ) ) } else { arg store_fn_arg ( b mut llarg_idx dst ) } bcx } ) ) } } else { // FIXME(pcwalton): Reduce the amount of code bloat this is responsible for. let tupled_arg_tys = match arg_ty . sty { ty :: TyTuple ( ref tys ) => tys , _ => bug ! ( " " ) } ; unpack_datum ! ( bcx datum lvalue_scratch_datum ( bcx arg_ty " " uninit_reason arg_scope_id bcx llval { debug ( " " hir_arg arg_ty ) for ( j tupled_arg_ty ) in tupled_arg_tys iter ( ) enumerate ( ) { let dst StructGEP ( bcx llval j ) let arg self fn_ty args [ idx ] idx 1 let b bcx build ( ) if common type_is_fat_ptr ( bcx tcx ( ) tupled_arg_ty ) { let meta self fn_ty args [ idx ] idx 1 arg store_fn_arg ( b mut llarg_idx expr get_dataptr ( bcx dst ) ) meta store_fn_arg ( b mut llarg_idx expr get_meta ( bcx dst ) ) } else { arg store_fn_arg ( b mut llarg_idx dst ) } } bcx } ) ) } ; let pat = & hir_arg . pat ; bcx = if let Some ( name ) = simple_name ( pat ) { // Generate nicer LLVM for the common case of fn a pattern // like `x: T` set_value_name ( arg_datum . val , & bcx . name ( name ) ) ; self . lllocals . borrow_mut ( ) . insert ( pat . id , arg_datum ) ; bcx } else { // General path. Copy out the values that are used in the // pattern. _match :: bind_irrefutable_pat ( bcx , pat , arg_datum . match_input ( ) , arg_scope_id ) } ; debuginfo :: create_argument_metadata ( bcx , hir_arg ) ; } bcx }
Creates lvalue datums for each of the incoming function arguments,
matches all argument patterns against them to produce bindings,
and returns the entry block (see FunctionContext::init).
Creates lvalue datums for each of the incoming function arguments matches all argument patterns against them to produce bindings and returns the entry block ( see FunctionContext :: init ) .
&'blk self
args
&[hir::Arg]
abi
Abi
id
ast::NodeId
closure_env
closure::ClosureEnv
arg_scope
cleanup::CustomScopeIndex