diff --git a/src/librustc_llvm/lib.rs b/src/librustc_llvm/lib.rs index 6d36e457b3d..c4960c8d6a3 100644 --- a/src/librustc_llvm/lib.rs +++ b/src/librustc_llvm/lib.rs @@ -2252,6 +2252,18 @@ pub fn get_param(llfn: ValueRef, index: c_uint) -> ValueRef { } } +pub fn get_params(llfn: ValueRef) -> Vec { + unsafe { + let num_params = LLVMCountParams(llfn); + let mut params = Vec::with_capacity(num_params as usize); + for idx in 0..num_params { + params.push(LLVMGetParam(llfn, idx)); + } + + params + } +} + #[allow(missing_copy_implementations)] pub enum RustString_opaque {} pub type RustStringRef = *mut RustString_opaque; diff --git a/src/librustc_trans/trans/callee.rs b/src/librustc_trans/trans/callee.rs index 46f762a5195..10aea37f2e9 100644 --- a/src/librustc_trans/trans/callee.rs +++ b/src/librustc_trans/trans/callee.rs @@ -21,9 +21,7 @@ pub use self::CallArgs::*; use arena::TypedArena; use back::link; use session; -use llvm::ValueRef; -use llvm::get_param; -use llvm; +use llvm::{self, ValueRef, get_params}; use metadata::csearch; use middle::def; use middle::subst; @@ -343,19 +341,15 @@ pub fn trans_fn_pointer_shim<'a, 'tcx>( &block_arena); let mut bcx = init_function(&fcx, false, sig.output); + let llargs = get_params(fcx.llfn); + // the first argument (`self`) will be ptr to the the fn pointer let llfnpointer = if is_by_ref { - Load(bcx, get_param(fcx.llfn, fcx.arg_pos(0) as u32)) + Load(bcx, llargs[fcx.arg_pos(0)]) } else { - get_param(fcx.llfn, fcx.arg_pos(0) as u32) + llargs[fcx.arg_pos(0)] }; - // the remaining arguments will be the untupled values - let llargs: Vec<_> = - sig.inputs.iter() - .enumerate() - .map(|(i, _)| get_param(fcx.llfn, fcx.arg_pos(i+1) as u32)) - .collect(); assert!(!fcx.needs_ret_allocas); let dest = fcx.llretslotptr.get().map(|_| @@ -366,7 +360,7 @@ pub fn trans_fn_pointer_shim<'a, 'tcx>( DebugLoc::None, bare_fn_ty, |bcx, _| Callee { bcx: bcx, data: Fn(llfnpointer) }, - ArgVals(&llargs[..]), + ArgVals(&llargs[fcx.arg_pos(1)..]), dest).bcx; finish_fn(&fcx, bcx, sig.output, DebugLoc::None); diff --git a/src/librustc_trans/trans/closure.rs b/src/librustc_trans/trans/closure.rs index 91b0a6c0069..127fee222da 100644 --- a/src/librustc_trans/trans/closure.rs +++ b/src/librustc_trans/trans/closure.rs @@ -10,7 +10,7 @@ use arena::TypedArena; use back::link::{self, mangle_internal_name_by_path_and_seq}; -use llvm::{ValueRef, get_param}; +use llvm::{ValueRef, get_params}; use middle::mem_categorization::Typer; use trans::adt; use trans::attributes; @@ -405,11 +405,13 @@ fn trans_fn_once_adapter_shim<'a, 'tcx>( &block_arena); let mut bcx = init_function(&fcx, false, sig.output); + let llargs = get_params(fcx.llfn); + // the first argument (`self`) will be the (by value) closure env. let self_scope = fcx.push_custom_cleanup_scope(); let self_scope_id = CustomScope(self_scope); let rvalue_mode = datum::appropriate_rvalue_mode(ccx, closure_ty); - let llself = get_param(lloncefn, fcx.arg_pos(0) as u32); + let llself = llargs[fcx.arg_pos(0)]; let env_datum = Datum::new(llself, closure_ty, Rvalue::new(rvalue_mode)); let env_datum = unpack_datum!(bcx, env_datum.to_lvalue_datum_in_scope(bcx, "self", @@ -418,19 +420,6 @@ fn trans_fn_once_adapter_shim<'a, 'tcx>( debug!("trans_fn_once_adapter_shim: env_datum={}", bcx.val_to_string(env_datum.val)); - // the remaining arguments will be packed up in a tuple. - let input_tys = match sig.inputs[1].sty { - ty::TyTuple(ref tys) => &**tys, - _ => bcx.sess().bug(&format!("trans_fn_once_adapter_shim: not rust-call! \ - closure_def_id={:?}", - closure_def_id)) - }; - let llargs: Vec<_> = - input_tys.iter() - .enumerate() - .map(|(i, _)| get_param(lloncefn, fcx.arg_pos(i+1) as u32)) - .collect(); - let dest = fcx.llretslotptr.get().map( |_| expr::SaveIn(fcx.get_ret_slot(bcx, sig.output, "ret_slot"))); @@ -442,7 +431,7 @@ fn trans_fn_once_adapter_shim<'a, 'tcx>( DebugLoc::None, llref_fn_ty, |bcx, _| Callee { bcx: bcx, data: callee_data }, - ArgVals(&llargs), + ArgVals(&llargs[fcx.arg_pos(1)..]), dest).bcx; fcx.pop_custom_cleanup_scope(self_scope); diff --git a/src/librustc_trans/trans/meth.rs b/src/librustc_trans/trans/meth.rs index eca6eecff42..6955e03596f 100644 --- a/src/librustc_trans/trans/meth.rs +++ b/src/librustc_trans/trans/meth.rs @@ -11,7 +11,7 @@ use arena::TypedArena; use back::abi; use back::link; -use llvm::{ValueRef, get_param}; +use llvm::{ValueRef, get_params}; use metadata::csearch; use middle::subst::{Subst, Substs}; use middle::subst::VecPerParamSpace; @@ -611,43 +611,14 @@ pub fn trans_object_shim<'a, 'tcx>( &block_arena); let mut bcx = init_function(&fcx, false, sig.output); + let llargs = get_params(fcx.llfn); + // the first argument (`self`) will be a trait object - let llobject = get_param(fcx.llfn, fcx.arg_pos(0) as u32); + let llobject = llargs[fcx.arg_pos(0)]; debug!("trans_object_shim: llobject={}", bcx.val_to_string(llobject)); - // the remaining arguments will be, well, whatever they are - let input_tys = - match fty.abi { - RustCall => { - // unpack the tuple to extract the input type arguments: - match sig.inputs[1].sty { - ty::TyTuple(ref tys) => &**tys, - _ => { - bcx.sess().bug( - &format!("rust-call expects a tuple not {:?}", - sig.inputs[1])); - } - } - } - _ => { - // skip the self parameter: - &sig.inputs[1..] - } - }; - - let llargs: Vec<_> = - input_tys.iter() - .enumerate() - .map(|(i, _)| { - let llarg = get_param(fcx.llfn, fcx.arg_pos(i+1) as u32); - debug!("trans_object_shim: input #{} == {}", - i, bcx.val_to_string(llarg)); - llarg - }) - .collect(); - assert!(!fcx.needs_ret_allocas); let dest = @@ -669,7 +640,7 @@ pub fn trans_object_shim<'a, 'tcx>( method_bare_fn_ty, method_offset_in_vtable, llobject), - ArgVals(&llargs), + ArgVals(&llargs[fcx.arg_pos(1)..]), dest).bcx; finish_fn(&fcx, bcx, sig.output, DebugLoc::None);