From 67283eaad2f53e19ae963e2b0a04b65826568336 Mon Sep 17 00:00:00 2001 From: Tom Lee Date: Tue, 21 May 2013 23:17:04 -0700 Subject: [PATCH 1/4] Omit unused implicit argument if return type is immediate. --- src/librustc/middle/trans/base.rs | 89 ++++++++++++++-------------- src/librustc/middle/trans/cabi.rs | 3 +- src/librustc/middle/trans/callee.rs | 6 +- src/librustc/middle/trans/common.rs | 25 ++++++-- src/librustc/middle/trans/foreign.rs | 57 ++++++++++-------- src/librustc/middle/trans/glue.rs | 19 +++--- src/librustc/middle/trans/reflect.rs | 17 ++++-- src/librustc/middle/trans/type_of.rs | 9 +-- src/rt/rust_builtin.cpp | 8 +-- src/rt/rust_task.cpp | 6 +- src/rt/rust_type.h | 4 +- 11 files changed, 132 insertions(+), 111 deletions(-) diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index 90449e8a17aef..ed3ac5fadb4e2 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -1593,7 +1593,7 @@ pub fn new_fn_ctxt_w_id(ccx: @CrateContext, impl_id: Option, param_substs: Option<@param_substs>, sp: Option) - -> fn_ctxt { + -> (fn_ctxt, bool) { for param_substs.each |p| { p.validate(); } debug!("new_fn_ctxt_w_id(path=%s, id=%?, impl_id=%?, \ @@ -1611,11 +1611,13 @@ pub fn new_fn_ctxt_w_id(ccx: @CrateContext, ty::subst_tps(ccx.tcx, substs.tys, substs.self_ty, output_type) } }; - let is_immediate = ty::type_is_immediate(substd_output_type); + let imm = ty::type_is_immediate(substd_output_type); let fcx = @mut fn_ctxt_ { llfn: llfndecl, - llenv: unsafe { llvm::LLVMGetParam(llfndecl, 1u as c_uint) }, + llenv: unsafe { + llvm::LLVMGetParam(llfndecl, arg_env(imm) as c_uint) + }, llretptr: None, llstaticallocas: llbbs.sa, llloadenv: None, @@ -1623,7 +1625,7 @@ pub fn new_fn_ctxt_w_id(ccx: @CrateContext, llself: None, personality: None, loop_ret: None, - has_immediate_return_value: is_immediate, + has_immediate_return_value: imm, llargs: @mut HashMap::new(), lllocals: @mut HashMap::new(), llupvars: @mut HashMap::new(), @@ -1636,7 +1638,7 @@ pub fn new_fn_ctxt_w_id(ccx: @CrateContext, }; fcx.llretptr = Some(make_return_pointer(fcx, substd_output_type)); - fcx + (fcx, imm) } pub fn new_fn_ctxt(ccx: @CrateContext, @@ -1644,7 +1646,7 @@ pub fn new_fn_ctxt(ccx: @CrateContext, llfndecl: ValueRef, output_type: ty::t, sp: Option) - -> fn_ctxt { + -> (fn_ctxt, bool) { new_fn_ctxt_w_id(ccx, path, llfndecl, -1, output_type, None, None, sp) } @@ -1664,7 +1666,8 @@ pub fn new_fn_ctxt(ccx: @CrateContext, // field of the fn_ctxt with pub fn create_llargs_for_fn_args(cx: fn_ctxt, self_arg: self_arg, - args: &[ast::arg]) + args: &[ast::arg], + ret_imm: bool) -> ~[ValueRef] { let _icx = cx.insn_ctxt("create_llargs_for_fn_args"); @@ -1690,7 +1693,7 @@ pub fn create_llargs_for_fn_args(cx: fn_ctxt, // llvm::LLVMGetParam for each argument. vec::from_fn(args.len(), |i| { unsafe { - let arg_n = first_real_arg + i; + let arg_n = arg_pos(ret_imm, i); let arg = &args[i]; let llarg = llvm::LLVMGetParam(cx.llfn, arg_n as c_uint); @@ -1829,15 +1832,15 @@ pub fn trans_closure(ccx: @CrateContext, param_substs.repr(ccx.tcx)); // Set up arguments to the function. - let fcx = new_fn_ctxt_w_id(ccx, - path, - llfndecl, - id, - output_type, - impl_id, - param_substs, - Some(body.span)); - let raw_llargs = create_llargs_for_fn_args(fcx, self_arg, decl.inputs); + let (fcx, imm) = new_fn_ctxt_w_id(ccx, + path, + llfndecl, + id, + output_type, + impl_id, + param_substs, + Some(body.span)); + let raw_llargs = create_llargs_for_fn_args(fcx, self_arg, decl.inputs, imm); // Set the fixed stack segment flag if necessary. if attr::attrs_contains_name(attributes, "fixed_stack_segment") { @@ -1962,16 +1965,16 @@ pub fn trans_enum_variant(ccx: @CrateContext, ty_param_substs, None, ty::node_id_to_type(ccx.tcx, enum_id)); - let fcx = new_fn_ctxt_w_id(ccx, - ~[], - llfndecl, - variant.node.id, - enum_ty, - None, - param_substs, - None); - - let raw_llargs = create_llargs_for_fn_args(fcx, no_self, fn_args); + let (fcx, imm) = new_fn_ctxt_w_id(ccx, + ~[], + llfndecl, + variant.node.id, + enum_ty, + None, + param_substs, + None); + + let raw_llargs = create_llargs_for_fn_args(fcx, no_self, fn_args, imm); let bcx = top_scope_block(fcx, None), lltop = bcx.llbb; let arg_tys = ty::ty_fn_args(node_id_type(bcx, variant.node.id)); let bcx = copy_args_to_allocas(fcx, bcx, fn_args, raw_llargs, arg_tys); @@ -2041,16 +2044,16 @@ pub fn trans_tuple_struct(ccx: @CrateContext, ty_to_str(ccx.tcx, ctor_ty))) }; - let fcx = new_fn_ctxt_w_id(ccx, - ~[], - llfndecl, - ctor_id, - tup_ty, - None, - param_substs, - None); + let (fcx, imm) = new_fn_ctxt_w_id(ccx, + ~[], + llfndecl, + ctor_id, + tup_ty, + None, + param_substs, + None); - let raw_llargs = create_llargs_for_fn_args(fcx, no_self, fn_args); + let raw_llargs = create_llargs_for_fn_args(fcx, no_self, fn_args, imm); let bcx = top_scope_block(fcx, None); let lltop = bcx.llbb; @@ -2293,19 +2296,21 @@ pub fn create_entry_wrapper(ccx: @CrateContext, fn create_main(ccx: @CrateContext, main_llfn: ValueRef) -> ValueRef { let nt = ty::mk_nil(); + let llfty = type_of_fn(ccx, [], nt); let llfdecl = decl_fn(ccx.llmod, "_rust_main", lib::llvm::CCallConv, llfty); - let fcx = new_fn_ctxt(ccx, ~[], llfdecl, nt, None); + let (fcx, _) = new_fn_ctxt(ccx, ~[], llfdecl, nt, None); let bcx = top_scope_block(fcx, None); let lltop = bcx.llbb; // Call main. - let lloutputarg = C_null(T_ptr(T_i8())); - let llenvarg = unsafe { llvm::LLVMGetParam(llfdecl, 1 as c_uint) }; - let args = ~[lloutputarg, llenvarg]; + let llenvarg = unsafe { + llvm::LLVMGetParam(llfdecl, arg_env(true) as c_uint) + }; + let args = ~[llenvarg]; let llresult = Call(bcx, main_llfn, args); Store(bcx, llresult, fcx.llretptr.get()); @@ -2347,8 +2352,6 @@ pub fn create_entry_wrapper(ccx: @CrateContext, trans_external_path(ccx, start_def_id, start_fn_type); } - let retptr = llvm::LLVMBuildAlloca(bld, T_i8(), noname()); - let crate_map = ccx.crate_map; let opaque_crate_map = llvm::LLVMBuildPointerCast(bld, crate_map, @@ -2371,7 +2374,6 @@ pub fn create_entry_wrapper(ccx: @CrateContext, bld, rust_main, T_ptr(T_i8()), noname()); ~[ - retptr, C_null(T_opaque_box_ptr(ccx)), opaque_rust_main, llvm::LLVMGetParam(llfn, 0), @@ -2384,7 +2386,6 @@ pub fn create_entry_wrapper(ccx: @CrateContext, debug!("using user-defined start fn"); let args = { ~[ - retptr, C_null(T_opaque_box_ptr(ccx)), llvm::LLVMGetParam(llfn, 0 as c_uint), llvm::LLVMGetParam(llfn, 1 as c_uint), diff --git a/src/librustc/middle/trans/cabi.rs b/src/librustc/middle/trans/cabi.rs index c6f4d23041973..ecf9963b68a74 100644 --- a/src/librustc/middle/trans/cabi.rs +++ b/src/librustc/middle/trans/cabi.rs @@ -132,7 +132,8 @@ pub impl FnType { bcx: block, ret_ty: TypeRef, llwrapfn: ValueRef, - llargbundle: ValueRef) { + llargbundle: ValueRef, + ret_imm: bool) { let mut atys = /*bad*/copy self.arg_tys; let mut attrs = /*bad*/copy self.attrs; let mut j = 0u; diff --git a/src/librustc/middle/trans/callee.rs b/src/librustc/middle/trans/callee.rs index 3d4649bba4660..b710f33d6abb2 100644 --- a/src/librustc/middle/trans/callee.rs +++ b/src/librustc/middle/trans/callee.rs @@ -510,11 +510,7 @@ pub fn trans_call_inner(in_cx: block, let mut llargs = ~[]; - if ty::type_is_immediate(ret_ty) { - unsafe { - llargs.push(llvm::LLVMGetUndef(T_ptr(T_i8()))); - } - } else { + if !ty::type_is_immediate(ret_ty) { llargs.push(llretslot); } diff --git a/src/librustc/middle/trans/common.rs b/src/librustc/middle/trans/common.rs index be074cfc57a30..00b6797668398 100644 --- a/src/librustc/middle/trans/common.rs +++ b/src/librustc/middle/trans/common.rs @@ -660,8 +660,26 @@ pub fn mk_block(llbb: BasicBlockRef, parent: Option, kind: block_kind, @mut block_(llbb, parent, kind, is_lpad, node_info, fcx) } -// First two args are retptr, env -pub static first_real_arg: uint = 2u; +pub fn arg_pos(ret_imm: bool, arg: uint) -> uint { + if ret_imm { + arg + 1u + } else { + arg + 2u + } +} + +pub fn arg_out(ret_imm: bool) -> uint { + assert!(ret_imm); + 0u +} + +pub fn arg_env(ret_imm: bool) -> uint { + if !ret_imm { + 1u + } else { + 0u + } +} pub struct Result { bcx: block, @@ -962,8 +980,7 @@ pub fn T_tydesc(targ_cfg: @session::config) -> TypeRef { let tydescpp = T_ptr(T_ptr(tydesc)); let pvoid = T_ptr(T_i8()); let glue_fn_ty = - T_ptr(T_fn([T_ptr(T_nil()), T_ptr(T_nil()), tydescpp, - pvoid], T_void())); + T_ptr(T_fn([T_ptr(T_nil()), tydescpp, pvoid], T_void())); let int_type = T_int(targ_cfg); let elems = diff --git a/src/librustc/middle/trans/foreign.rs b/src/librustc/middle/trans/foreign.rs index b0560c40277b8..08e17a4d2ec26 100644 --- a/src/librustc/middle/trans/foreign.rs +++ b/src/librustc/middle/trans/foreign.rs @@ -150,9 +150,14 @@ fn build_shim_fn_(ccx: @CrateContext, ccx.llmod, shim_name, tys.shim_fn_ty); // Declare the body of the shim function: - let fcx = new_fn_ctxt(ccx, ~[], llshimfn, tys.fn_sig.output, None); + let (fcx, imm) = new_fn_ctxt(ccx, ~[], llshimfn, tys.fn_sig.output, None); let bcx = top_scope_block(fcx, None); let lltop = bcx.llbb; + + // + // FIXME [#6575] this seems to be making the assumption that the first + // implicit argument is always available? + // let llargbundle = get_param(llshimfn, 0u); let llargvals = arg_builder(bcx, tys, llargbundle); @@ -174,7 +179,8 @@ fn build_shim_fn_(ccx: @CrateContext, type wrap_arg_builder<'self> = &'self fn(bcx: block, tys: &ShimTypes, llwrapfn: ValueRef, - llargbundle: ValueRef); + llargbundle: ValueRef, + ret_imm: bool); type wrap_ret_builder<'self> = &'self fn(bcx: block, tys: &ShimTypes, @@ -189,7 +195,7 @@ fn build_wrap_fn_(ccx: @CrateContext, arg_builder: wrap_arg_builder, ret_builder: wrap_ret_builder) { let _icx = ccx.insn_ctxt("foreign::build_wrap_fn_"); - let fcx = new_fn_ctxt(ccx, ~[], llwrapfn, tys.fn_sig.output, None); + let (fcx, imm) = new_fn_ctxt(ccx, ~[], llwrapfn, tys.fn_sig.output, None); // Patch up the return type if it's not immediate and we're returning via // the C ABI. @@ -204,7 +210,7 @@ fn build_wrap_fn_(ccx: @CrateContext, // Allocate the struct and write the arguments into it. let llargbundle = alloca(bcx, tys.bundle_ty); - arg_builder(bcx, tys, llwrapfn, llargbundle); + arg_builder(bcx, tys, llwrapfn, llargbundle, imm); // Create call itself. let llshimfnptr = PointerCast(bcx, llshimfn, T_ptr(T_i8())); @@ -432,16 +438,16 @@ pub fn trans_foreign_mod(ccx: @CrateContext, cc: lib::llvm::CallConv) { debug!("build_direct_fn(%s)", *link_name(ccx, item)); - let fcx = new_fn_ctxt(ccx, ~[], decl, tys.fn_sig.output, None); + let (fcx, imm) = new_fn_ctxt(ccx, ~[], decl, tys.fn_sig.output, None); let bcx = top_scope_block(fcx, None), lltop = bcx.llbb; let llbasefn = base_fn(ccx, *link_name(ccx, item), tys, cc); let ty = ty::lookup_item_type(ccx.tcx, ast_util::local_def(item.id)).ty; + let ret_ty = ty::ty_fn_ret(ty); let args = vec::from_fn(ty::ty_fn_args(ty).len(), |i| { - get_param(decl, i + first_real_arg) + get_param(decl, arg_pos(imm, i)) }); let retval = Call(bcx, llbasefn, args); - let ret_ty = ty::ty_fn_ret(ty); if !ty::type_is_nil(ret_ty) && !ty::type_is_bot(ret_ty) { Store(bcx, retval, fcx.llretptr.get()); } @@ -458,18 +464,18 @@ pub fn trans_foreign_mod(ccx: @CrateContext, cc: lib::llvm::CallConv) { debug!("build_fast_ffi_fn(%s)", *link_name(ccx, item)); - let fcx = new_fn_ctxt(ccx, ~[], decl, tys.fn_sig.output, None); + let (fcx, imm) = new_fn_ctxt(ccx, ~[], decl, tys.fn_sig.output, None); let bcx = top_scope_block(fcx, None), lltop = bcx.llbb; let llbasefn = base_fn(ccx, *link_name(ccx, item), tys, cc); set_no_inline(fcx.llfn); set_fixed_stack_segment(fcx.llfn); let ty = ty::lookup_item_type(ccx.tcx, ast_util::local_def(item.id)).ty; + let ret_ty = ty::ty_fn_ret(ty); let args = vec::from_fn(ty::ty_fn_args(ty).len(), |i| { - get_param(decl, i + first_real_arg) + get_param(decl, arg_pos(imm, i)) }); let retval = Call(bcx, llbasefn, args); - let ret_ty = ty::ty_fn_ret(ty); if !ty::type_is_nil(ret_ty) && !ty::type_is_bot(ret_ty) { Store(bcx, retval, fcx.llretptr.get()); } @@ -508,13 +514,13 @@ pub fn trans_foreign_mod(ccx: @CrateContext, fn build_args(bcx: block, tys: &ShimTypes, llwrapfn: ValueRef, - llargbundle: ValueRef) { + llargbundle: ValueRef, + ret_imm: bool) { let _icx = bcx.insn_ctxt("foreign::wrap::build_args"); let ccx = bcx.ccx(); let n = tys.llsig.llarg_tys.len(); - let implicit_args = first_real_arg; // return + env for uint::range(0, n) |i| { - let mut llargval = get_param(llwrapfn, i + implicit_args); + let mut llargval = get_param(llwrapfn, arg_pos(ret_imm, i)); // In some cases, Rust will pass a pointer which the // native C type doesn't have. In that case, just @@ -552,14 +558,14 @@ pub fn trans_intrinsic(ccx: @CrateContext, let output_type = ty::ty_fn_ret(ty::node_id_to_type(ccx.tcx, item.id)); - let fcx = new_fn_ctxt_w_id(ccx, - path, - decl, - item.id, - output_type, - None, - Some(substs), - Some(item.span)); + let (fcx, imm) = new_fn_ctxt_w_id(ccx, + path, + decl, + item.id, + output_type, + None, + Some(substs), + Some(item.span)); // Set the fixed stack segment flag if necessary. if attr::attrs_contains_name(attributes, "fixed_stack_segment") { @@ -568,6 +574,7 @@ pub fn trans_intrinsic(ccx: @CrateContext, let mut bcx = top_scope_block(fcx, None); let lltop = bcx.llbb; + let first_real_arg = arg_pos(imm, 0u); match *ccx.sess.str_of(item.ident) { ~"atomic_cxchg" => { let old = AtomicCmpXchg(bcx, @@ -1269,8 +1276,6 @@ pub fn trans_foreign_fn(ccx: @CrateContext, if !ty::type_is_immediate(tys.fn_sig.output) { let llretptr = load_inbounds(bcx, llargbundle, [0u, n]); llargvals.push(llretptr); - } else { - llargvals.push(C_null(T_ptr(T_i8()))); } let llenvptr = C_null(T_opaque_box_ptr(bcx.ccx())); @@ -1351,12 +1356,14 @@ pub fn trans_foreign_fn(ccx: @CrateContext, fn build_args(bcx: block, tys: &ShimTypes, llwrapfn: ValueRef, - llargbundle: ValueRef) { + llargbundle: ValueRef, + ret_imm: bool) { let _icx = bcx.insn_ctxt("foreign::foreign::wrap::build_args"); tys.fn_ty.build_wrap_args(bcx, tys.llsig.llret_ty, llwrapfn, - llargbundle); + llargbundle, + ret_imm); } fn build_ret(bcx: block, tys: &ShimTypes, llargbundle: ValueRef) { diff --git a/src/librustc/middle/trans/glue.rs b/src/librustc/middle/trans/glue.rs index 2f48eda7edd26..29709cd553d5b 100644 --- a/src/librustc/middle/trans/glue.rs +++ b/src/librustc/middle/trans/glue.rs @@ -19,6 +19,7 @@ use back::link::*; use driver::session; use lib; use lib::llvm::{llvm, ValueRef, TypeRef, True}; +use lib::llvm::type_to_str; use middle::trans::adt; use middle::trans::base::*; use middle::trans::callee; @@ -381,8 +382,9 @@ pub fn call_tydesc_glue_full(bcx: block, } }; - Call(bcx, llfn, [C_null(T_ptr(T_nil())), C_null(T_ptr(T_nil())), - C_null(T_ptr(T_ptr(bcx.ccx().tydesc_type))), llrawptr]); + Call(bcx, llfn, [C_null(T_ptr(T_nil())), + C_null(T_ptr(T_ptr(bcx.ccx().tydesc_type))), + llrawptr]); } // See [Note-arg-mode] @@ -483,17 +485,16 @@ pub fn trans_struct_drop(bcx: block, }; // Class dtors have no explicit args, so the params should - // just consist of the output pointer and the environment - // (self) - assert_eq!(params.len(), 2); + // just consist of the environment (self) + assert_eq!(params.len(), 1); // Take a reference to the class (because it's using the Drop trait), // do so now. let llval = alloca(bcx, val_ty(v0)); Store(bcx, v0, llval); - let self_arg = PointerCast(bcx, llval, params[1]); - let args = ~[C_null(T_ptr(T_i8())), self_arg]; + let self_arg = PointerCast(bcx, llval, params[0]); + let args = ~[self_arg]; Call(bcx, dtor_addr, args); @@ -726,7 +727,7 @@ pub fn make_generic_glue_inner(ccx: @CrateContext, helper: glue_helper) -> ValueRef { let _icx = ccx.insn_ctxt("make_generic_glue_inner"); - let fcx = new_fn_ctxt(ccx, ~[], llfn, ty::mk_nil(), None); + let (fcx, imm) = new_fn_ctxt(ccx, ~[], llfn, ty::mk_nil(), None); lib::llvm::SetLinkage(llfn, lib::llvm::InternalLinkage); ccx.stats.n_glues_created += 1u; // All glue functions take values passed *by alias*; this is a @@ -739,7 +740,7 @@ pub fn make_generic_glue_inner(ccx: @CrateContext, let bcx = top_scope_block(fcx, None); let lltop = bcx.llbb; - let llrawptr0 = unsafe { llvm::LLVMGetParam(llfn, 3u as c_uint) }; + let llrawptr0 = unsafe { llvm::LLVMGetParam(llfn, arg_pos(true, 1u) as c_uint) }; helper(bcx, llrawptr0, t); finish_fn(fcx, lltop); return llfn; diff --git a/src/librustc/middle/trans/reflect.rs b/src/librustc/middle/trans/reflect.rs index b8d38cf7701bc..681b11423ddc3 100644 --- a/src/librustc/middle/trans/reflect.rs +++ b/src/librustc/middle/trans/reflect.rs @@ -287,13 +287,18 @@ pub impl Reflector { let llfty = type_of_fn(ccx, [opaqueptrty], ty::mk_int()); let llfdecl = decl_internal_cdecl_fn(ccx.llmod, sym, llfty); let arg = unsafe { - llvm::LLVMGetParam(llfdecl, first_real_arg as c_uint) + // + // we know the return type of llfdecl is an int here, so + // no need for a special check to see if the return type + // is immediate. + // + llvm::LLVMGetParam(llfdecl, arg_pos(true, 0u) as c_uint) }; - let fcx = new_fn_ctxt(ccx, - ~[], - llfdecl, - ty::mk_uint(), - None); + let (fcx, _) = new_fn_ctxt(ccx, + ~[], + llfdecl, + ty::mk_uint(), + None); let bcx = top_scope_block(fcx, None); let arg = BitCast(bcx, arg, llptrty); let ret = adt::trans_get_discr(bcx, repr, arg); diff --git a/src/librustc/middle/trans/type_of.rs b/src/librustc/middle/trans/type_of.rs index bddcb9a1d7377..e3c424f8e7ecf 100644 --- a/src/librustc/middle/trans/type_of.rs +++ b/src/librustc/middle/trans/type_of.rs @@ -46,9 +46,6 @@ pub fn type_of_fn(cx: @CrateContext, inputs: &[ty::t], output: ty::t) let lloutputtype = type_of(cx, output); if !output_is_immediate { atys.push(T_ptr(lloutputtype)); - } else { - // FIXME #6575: Eliminate this. - atys.push(T_ptr(T_i8())); } // Arg 1: Environment @@ -334,9 +331,7 @@ pub fn llvm_type_name(cx: @CrateContext, } pub fn type_of_dtor(ccx: @CrateContext, self_ty: ty::t) -> TypeRef { - T_fn([T_ptr(T_i8()), // output pointer - T_ptr(type_of(ccx, self_ty))], // self arg - T_nil()) + T_fn([T_ptr(type_of(ccx, self_ty))] /* self */, T_nil()) } pub fn type_of_rooted(ccx: @CrateContext, t: ty::t) -> TypeRef { @@ -349,5 +344,5 @@ pub fn type_of_rooted(ccx: @CrateContext, t: ty::t) -> TypeRef { pub fn type_of_glue_fn(ccx: @CrateContext, t: ty::t) -> TypeRef { let tydescpp = T_ptr(T_ptr(ccx.tydesc_type)); let llty = T_ptr(type_of(ccx, t)); - return T_fn([T_ptr(T_nil()), T_ptr(T_nil()), tydescpp, llty], T_nil()); + return T_fn([T_ptr(T_nil()), tydescpp, llty], T_nil()); } diff --git a/src/rt/rust_builtin.cpp b/src/rt/rust_builtin.cpp index a2f253550af16..99fd46737e02f 100644 --- a/src/rt/rust_builtin.cpp +++ b/src/rt/rust_builtin.cpp @@ -731,10 +731,10 @@ rust_task_deref(rust_task *task) { // Must call on rust stack. extern "C" CDECL void rust_call_tydesc_glue(void *root, size_t *tydesc, size_t glue_index) { - void (*glue_fn)(void *, void *, void *, void *) = - (void (*)(void *, void *, void *, void *))tydesc[glue_index]; + void (*glue_fn)(void *, void *, void *) = + (void (*)(void *, void *, void *))tydesc[glue_index]; if (glue_fn) - glue_fn(0, 0, 0, root); + glue_fn(0, 0, root); } // Don't run on the Rust stack! @@ -754,7 +754,7 @@ class raw_thread: public rust_thread { virtual void run() { record_sp_limit(0); - fn.f(NULL, fn.env, NULL); + fn.f(fn.env, NULL); } }; diff --git a/src/rt/rust_task.cpp b/src/rt/rust_task.cpp index 266c0652c6e59..28d36a4bf88bd 100644 --- a/src/rt/rust_task.cpp +++ b/src/rt/rust_task.cpp @@ -162,9 +162,7 @@ void task_start_wrapper(spawn_args *a) bool threw_exception = false; try { - // The first argument is the return pointer; as the task fn - // must have void return type, we can safely pass 0. - a->f(0, a->envptr, a->argptr); + a->f(a->envptr, a->argptr); } catch (rust_task *ex) { assert(ex == task && "Expected this task to be thrown for unwinding"); threw_exception = true; @@ -185,7 +183,7 @@ void task_start_wrapper(spawn_args *a) if(env) { // free the environment (which should be a unique closure). const type_desc *td = env->td; - td->drop_glue(NULL, NULL, NULL, box_body(env)); + td->drop_glue(NULL, NULL, box_body(env)); task->kernel->region()->free(env); } diff --git a/src/rt/rust_type.h b/src/rt/rust_type.h index ece0d48c3ae44..6d36d2c960a2d 100644 --- a/src/rt/rust_type.h +++ b/src/rt/rust_type.h @@ -21,11 +21,11 @@ struct rust_opaque_box; // - the main function: has a NULL environment, but uses the void* arg // - unique closures of type fn~(): have a non-NULL environment, but // no arguments (and hence the final void*) is harmless -typedef void (*CDECL spawn_fn)(void*, rust_opaque_box*, void *); +typedef void (*CDECL spawn_fn)(rust_opaque_box*, void *); struct type_desc; -typedef void CDECL (glue_fn)(void *, void *, const type_desc **, void *); +typedef void CDECL (glue_fn)(void *, const type_desc **, void *); // Corresponds to the boxed data in the @ region. The body follows the // header; you can obtain a ptr via box_body() below. From cddd274e4defa86820a7a4218f6f55a440b2f82f Mon Sep 17 00:00:00 2001 From: Tom Lee Date: Fri, 24 May 2013 20:18:20 -0700 Subject: [PATCH 2/4] Add _RUST_STAGE0 #ifdefs --- src/rt/rust_builtin.cpp | 4 ++++ src/rt/rust_task.cpp | 8 ++++++++ src/rt/rust_type.h | 8 ++++++++ 3 files changed, 20 insertions(+) diff --git a/src/rt/rust_builtin.cpp b/src/rt/rust_builtin.cpp index 99fd46737e02f..cf7c07770570c 100644 --- a/src/rt/rust_builtin.cpp +++ b/src/rt/rust_builtin.cpp @@ -754,7 +754,11 @@ class raw_thread: public rust_thread { virtual void run() { record_sp_limit(0); +#ifdef _RUST_STAGE0 + fn.f(NULL, fn.env, NULL); +#else fn.f(fn.env, NULL); +#endif } }; diff --git a/src/rt/rust_task.cpp b/src/rt/rust_task.cpp index 28d36a4bf88bd..b5ecb1661755a 100644 --- a/src/rt/rust_task.cpp +++ b/src/rt/rust_task.cpp @@ -162,7 +162,11 @@ void task_start_wrapper(spawn_args *a) bool threw_exception = false; try { +#ifdef _RUST_STAGE0 + a->f(NULL, a->envptr, a->argptr); +#else a->f(a->envptr, a->argptr); +#endif } catch (rust_task *ex) { assert(ex == task && "Expected this task to be thrown for unwinding"); threw_exception = true; @@ -183,7 +187,11 @@ void task_start_wrapper(spawn_args *a) if(env) { // free the environment (which should be a unique closure). const type_desc *td = env->td; +#ifdef _RUST_STAGE0 + td->drop_glue(NULL, NULL, NULL, box_body(env)); +#else td->drop_glue(NULL, NULL, box_body(env)); +#endif task->kernel->region()->free(env); } diff --git a/src/rt/rust_type.h b/src/rt/rust_type.h index 6d36d2c960a2d..b50c08379de7f 100644 --- a/src/rt/rust_type.h +++ b/src/rt/rust_type.h @@ -21,11 +21,19 @@ struct rust_opaque_box; // - the main function: has a NULL environment, but uses the void* arg // - unique closures of type fn~(): have a non-NULL environment, but // no arguments (and hence the final void*) is harmless +#ifdef _RUST_STAGE0 +typedef void (*CDECL spawn_fn)(void *, rust_opaque_box*, void *); +#else typedef void (*CDECL spawn_fn)(rust_opaque_box*, void *); +#endif struct type_desc; +#ifdef _RUST_STAGE0 +typedef void CDECL (glue_fn)(void *, void *, const type_desc **, void *); +#else typedef void CDECL (glue_fn)(void *, const type_desc **, void *); +#endif // Corresponds to the boxed data in the @ region. The body follows the // header; you can obtain a ptr via box_body() below. From a85993ff69d5ba9a2cf07b0d1889b3ddf2e099e5 Mon Sep 17 00:00:00 2001 From: Tom Lee Date: Sat, 25 May 2013 11:09:33 -0700 Subject: [PATCH 3/4] Added _RUST_STAGEN guard to rust_call_tydesc_glue --- src/rt/rust_builtin.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/rt/rust_builtin.cpp b/src/rt/rust_builtin.cpp index cf7c07770570c..f173fa836a5a4 100644 --- a/src/rt/rust_builtin.cpp +++ b/src/rt/rust_builtin.cpp @@ -731,10 +731,17 @@ rust_task_deref(rust_task *task) { // Must call on rust stack. extern "C" CDECL void rust_call_tydesc_glue(void *root, size_t *tydesc, size_t glue_index) { +#ifdef _RUST_STAGE0 + void (*glue_fn)(void *, void *, void *, void *) = + (void (*)(void *, void *, void *, void *))tydesc[glue_index]; + if (glue_fn) + glue_fn(0, 0, 0, root); +#else void (*glue_fn)(void *, void *, void *) = (void (*)(void *, void *, void *))tydesc[glue_index]; if (glue_fn) glue_fn(0, 0, root); +#endif } // Don't run on the Rust stack! From b7f71e1ee661ea0d5d9731fcf4779a452bbee486 Mon Sep 17 00:00:00 2001 From: Tom Lee Date: Mon, 27 May 2013 18:33:57 -0700 Subject: [PATCH 4/4] Implementing suggestions from @nikomatsakis --- src/librustc/middle/trans/base.rs | 87 +++++++++++++++------------- src/librustc/middle/trans/cabi.rs | 3 +- src/librustc/middle/trans/common.rs | 45 +++++++------- src/librustc/middle/trans/foreign.rs | 51 +++++++--------- src/librustc/middle/trans/glue.rs | 5 +- src/librustc/middle/trans/reflect.rs | 12 ++-- 6 files changed, 102 insertions(+), 101 deletions(-) diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index ed3ac5fadb4e2..5bbfaac0792ae 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -1593,7 +1593,7 @@ pub fn new_fn_ctxt_w_id(ccx: @CrateContext, impl_id: Option, param_substs: Option<@param_substs>, sp: Option) - -> (fn_ctxt, bool) { + -> fn_ctxt { for param_substs.each |p| { p.validate(); } debug!("new_fn_ctxt_w_id(path=%s, id=%?, impl_id=%?, \ @@ -1611,12 +1611,11 @@ pub fn new_fn_ctxt_w_id(ccx: @CrateContext, ty::subst_tps(ccx.tcx, substs.tys, substs.self_ty, output_type) } }; - let imm = ty::type_is_immediate(substd_output_type); - + let is_immediate = ty::type_is_immediate(substd_output_type); let fcx = @mut fn_ctxt_ { llfn: llfndecl, llenv: unsafe { - llvm::LLVMGetParam(llfndecl, arg_env(imm) as c_uint) + llvm::LLVMGetUndef(T_ptr(T_i8())) }, llretptr: None, llstaticallocas: llbbs.sa, @@ -1625,7 +1624,7 @@ pub fn new_fn_ctxt_w_id(ccx: @CrateContext, llself: None, personality: None, loop_ret: None, - has_immediate_return_value: imm, + has_immediate_return_value: is_immediate, llargs: @mut HashMap::new(), lllocals: @mut HashMap::new(), llupvars: @mut HashMap::new(), @@ -1636,9 +1635,11 @@ pub fn new_fn_ctxt_w_id(ccx: @CrateContext, path: path, ccx: @ccx }; - + fcx.llenv = unsafe { + llvm::LLVMGetParam(llfndecl, fcx.env_arg_pos() as c_uint) + }; fcx.llretptr = Some(make_return_pointer(fcx, substd_output_type)); - (fcx, imm) + fcx } pub fn new_fn_ctxt(ccx: @CrateContext, @@ -1646,7 +1647,7 @@ pub fn new_fn_ctxt(ccx: @CrateContext, llfndecl: ValueRef, output_type: ty::t, sp: Option) - -> (fn_ctxt, bool) { + -> fn_ctxt { new_fn_ctxt_w_id(ccx, path, llfndecl, -1, output_type, None, None, sp) } @@ -1666,8 +1667,7 @@ pub fn new_fn_ctxt(ccx: @CrateContext, // field of the fn_ctxt with pub fn create_llargs_for_fn_args(cx: fn_ctxt, self_arg: self_arg, - args: &[ast::arg], - ret_imm: bool) + args: &[ast::arg]) -> ~[ValueRef] { let _icx = cx.insn_ctxt("create_llargs_for_fn_args"); @@ -1693,7 +1693,7 @@ pub fn create_llargs_for_fn_args(cx: fn_ctxt, // llvm::LLVMGetParam for each argument. vec::from_fn(args.len(), |i| { unsafe { - let arg_n = arg_pos(ret_imm, i); + let arg_n = cx.arg_pos(i); let arg = &args[i]; let llarg = llvm::LLVMGetParam(cx.llfn, arg_n as c_uint); @@ -1832,15 +1832,15 @@ pub fn trans_closure(ccx: @CrateContext, param_substs.repr(ccx.tcx)); // Set up arguments to the function. - let (fcx, imm) = new_fn_ctxt_w_id(ccx, - path, - llfndecl, - id, - output_type, - impl_id, - param_substs, - Some(body.span)); - let raw_llargs = create_llargs_for_fn_args(fcx, self_arg, decl.inputs, imm); + let fcx = new_fn_ctxt_w_id(ccx, + path, + llfndecl, + id, + output_type, + impl_id, + param_substs, + Some(body.span)); + let raw_llargs = create_llargs_for_fn_args(fcx, self_arg, decl.inputs); // Set the fixed stack segment flag if necessary. if attr::attrs_contains_name(attributes, "fixed_stack_segment") { @@ -1965,16 +1965,16 @@ pub fn trans_enum_variant(ccx: @CrateContext, ty_param_substs, None, ty::node_id_to_type(ccx.tcx, enum_id)); - let (fcx, imm) = new_fn_ctxt_w_id(ccx, - ~[], - llfndecl, - variant.node.id, - enum_ty, - None, - param_substs, - None); - - let raw_llargs = create_llargs_for_fn_args(fcx, no_self, fn_args, imm); + let fcx = new_fn_ctxt_w_id(ccx, + ~[], + llfndecl, + variant.node.id, + enum_ty, + None, + param_substs, + None); + + let raw_llargs = create_llargs_for_fn_args(fcx, no_self, fn_args); let bcx = top_scope_block(fcx, None), lltop = bcx.llbb; let arg_tys = ty::ty_fn_args(node_id_type(bcx, variant.node.id)); let bcx = copy_args_to_allocas(fcx, bcx, fn_args, raw_llargs, arg_tys); @@ -2044,16 +2044,16 @@ pub fn trans_tuple_struct(ccx: @CrateContext, ty_to_str(ccx.tcx, ctor_ty))) }; - let (fcx, imm) = new_fn_ctxt_w_id(ccx, - ~[], - llfndecl, - ctor_id, - tup_ty, - None, - param_substs, - None); + let fcx = new_fn_ctxt_w_id(ccx, + ~[], + llfndecl, + ctor_id, + tup_ty, + None, + param_substs, + None); - let raw_llargs = create_llargs_for_fn_args(fcx, no_self, fn_args, imm); + let raw_llargs = create_llargs_for_fn_args(fcx, no_self, fn_args); let bcx = top_scope_block(fcx, None); let lltop = bcx.llbb; @@ -2301,14 +2301,19 @@ pub fn create_entry_wrapper(ccx: @CrateContext, let llfdecl = decl_fn(ccx.llmod, "_rust_main", lib::llvm::CCallConv, llfty); - let (fcx, _) = new_fn_ctxt(ccx, ~[], llfdecl, nt, None); + let fcx = new_fn_ctxt(ccx, ~[], llfdecl, nt, None); + + // the args vector built in create_entry_fn will need + // be updated if this assertion starts to fail. + assert!(fcx.has_immediate_return_value); let bcx = top_scope_block(fcx, None); let lltop = bcx.llbb; // Call main. let llenvarg = unsafe { - llvm::LLVMGetParam(llfdecl, arg_env(true) as c_uint) + let env_arg = fcx.env_arg_pos(); + llvm::LLVMGetParam(llfdecl, env_arg as c_uint) }; let args = ~[llenvarg]; let llresult = Call(bcx, main_llfn, args); diff --git a/src/librustc/middle/trans/cabi.rs b/src/librustc/middle/trans/cabi.rs index ecf9963b68a74..c6f4d23041973 100644 --- a/src/librustc/middle/trans/cabi.rs +++ b/src/librustc/middle/trans/cabi.rs @@ -132,8 +132,7 @@ pub impl FnType { bcx: block, ret_ty: TypeRef, llwrapfn: ValueRef, - llargbundle: ValueRef, - ret_imm: bool) { + llargbundle: ValueRef) { let mut atys = /*bad*/copy self.arg_tys; let mut attrs = /*bad*/copy self.attrs; let mut j = 0u; diff --git a/src/librustc/middle/trans/common.rs b/src/librustc/middle/trans/common.rs index 00b6797668398..ad5dadaf8701d 100644 --- a/src/librustc/middle/trans/common.rs +++ b/src/librustc/middle/trans/common.rs @@ -351,6 +351,30 @@ pub struct fn_ctxt_ { ccx: @@CrateContext } +pub impl fn_ctxt_ { + pub fn arg_pos(&self, arg: uint) -> uint { + if self.has_immediate_return_value { + arg + 1u + } else { + arg + 2u + } + } + + pub fn out_arg_pos(&self) -> uint { + assert!(self.has_immediate_return_value); + 0u + } + + pub fn env_arg_pos(&self) -> uint { + if !self.has_immediate_return_value { + 1u + } else { + 0u + } + } + +} + pub type fn_ctxt = @mut fn_ctxt_; pub fn warn_not_to_commit(ccx: @CrateContext, msg: &str) { @@ -660,27 +684,6 @@ pub fn mk_block(llbb: BasicBlockRef, parent: Option, kind: block_kind, @mut block_(llbb, parent, kind, is_lpad, node_info, fcx) } -pub fn arg_pos(ret_imm: bool, arg: uint) -> uint { - if ret_imm { - arg + 1u - } else { - arg + 2u - } -} - -pub fn arg_out(ret_imm: bool) -> uint { - assert!(ret_imm); - 0u -} - -pub fn arg_env(ret_imm: bool) -> uint { - if !ret_imm { - 1u - } else { - 0u - } -} - pub struct Result { bcx: block, val: ValueRef diff --git a/src/librustc/middle/trans/foreign.rs b/src/librustc/middle/trans/foreign.rs index 08e17a4d2ec26..63356a135d059 100644 --- a/src/librustc/middle/trans/foreign.rs +++ b/src/librustc/middle/trans/foreign.rs @@ -150,14 +150,10 @@ fn build_shim_fn_(ccx: @CrateContext, ccx.llmod, shim_name, tys.shim_fn_ty); // Declare the body of the shim function: - let (fcx, imm) = new_fn_ctxt(ccx, ~[], llshimfn, tys.fn_sig.output, None); + let fcx = new_fn_ctxt(ccx, ~[], llshimfn, tys.fn_sig.output, None); let bcx = top_scope_block(fcx, None); let lltop = bcx.llbb; - // - // FIXME [#6575] this seems to be making the assumption that the first - // implicit argument is always available? - // let llargbundle = get_param(llshimfn, 0u); let llargvals = arg_builder(bcx, tys, llargbundle); @@ -179,8 +175,7 @@ fn build_shim_fn_(ccx: @CrateContext, type wrap_arg_builder<'self> = &'self fn(bcx: block, tys: &ShimTypes, llwrapfn: ValueRef, - llargbundle: ValueRef, - ret_imm: bool); + llargbundle: ValueRef); type wrap_ret_builder<'self> = &'self fn(bcx: block, tys: &ShimTypes, @@ -195,7 +190,7 @@ fn build_wrap_fn_(ccx: @CrateContext, arg_builder: wrap_arg_builder, ret_builder: wrap_ret_builder) { let _icx = ccx.insn_ctxt("foreign::build_wrap_fn_"); - let (fcx, imm) = new_fn_ctxt(ccx, ~[], llwrapfn, tys.fn_sig.output, None); + let fcx = new_fn_ctxt(ccx, ~[], llwrapfn, tys.fn_sig.output, None); // Patch up the return type if it's not immediate and we're returning via // the C ABI. @@ -210,7 +205,7 @@ fn build_wrap_fn_(ccx: @CrateContext, // Allocate the struct and write the arguments into it. let llargbundle = alloca(bcx, tys.bundle_ty); - arg_builder(bcx, tys, llwrapfn, llargbundle, imm); + arg_builder(bcx, tys, llwrapfn, llargbundle); // Create call itself. let llshimfnptr = PointerCast(bcx, llshimfn, T_ptr(T_i8())); @@ -438,14 +433,14 @@ pub fn trans_foreign_mod(ccx: @CrateContext, cc: lib::llvm::CallConv) { debug!("build_direct_fn(%s)", *link_name(ccx, item)); - let (fcx, imm) = new_fn_ctxt(ccx, ~[], decl, tys.fn_sig.output, None); + let fcx = new_fn_ctxt(ccx, ~[], decl, tys.fn_sig.output, None); let bcx = top_scope_block(fcx, None), lltop = bcx.llbb; let llbasefn = base_fn(ccx, *link_name(ccx, item), tys, cc); let ty = ty::lookup_item_type(ccx.tcx, ast_util::local_def(item.id)).ty; let ret_ty = ty::ty_fn_ret(ty); let args = vec::from_fn(ty::ty_fn_args(ty).len(), |i| { - get_param(decl, arg_pos(imm, i)) + get_param(decl, fcx.arg_pos(i)) }); let retval = Call(bcx, llbasefn, args); if !ty::type_is_nil(ret_ty) && !ty::type_is_bot(ret_ty) { @@ -464,7 +459,7 @@ pub fn trans_foreign_mod(ccx: @CrateContext, cc: lib::llvm::CallConv) { debug!("build_fast_ffi_fn(%s)", *link_name(ccx, item)); - let (fcx, imm) = new_fn_ctxt(ccx, ~[], decl, tys.fn_sig.output, None); + let fcx = new_fn_ctxt(ccx, ~[], decl, tys.fn_sig.output, None); let bcx = top_scope_block(fcx, None), lltop = bcx.llbb; let llbasefn = base_fn(ccx, *link_name(ccx, item), tys, cc); set_no_inline(fcx.llfn); @@ -473,7 +468,7 @@ pub fn trans_foreign_mod(ccx: @CrateContext, ast_util::local_def(item.id)).ty; let ret_ty = ty::ty_fn_ret(ty); let args = vec::from_fn(ty::ty_fn_args(ty).len(), |i| { - get_param(decl, arg_pos(imm, i)) + get_param(decl, fcx.arg_pos(i)) }); let retval = Call(bcx, llbasefn, args); if !ty::type_is_nil(ret_ty) && !ty::type_is_bot(ret_ty) { @@ -514,13 +509,13 @@ pub fn trans_foreign_mod(ccx: @CrateContext, fn build_args(bcx: block, tys: &ShimTypes, llwrapfn: ValueRef, - llargbundle: ValueRef, - ret_imm: bool) { + llargbundle: ValueRef) { let _icx = bcx.insn_ctxt("foreign::wrap::build_args"); let ccx = bcx.ccx(); let n = tys.llsig.llarg_tys.len(); for uint::range(0, n) |i| { - let mut llargval = get_param(llwrapfn, arg_pos(ret_imm, i)); + let arg_i = bcx.fcx.arg_pos(i); + let mut llargval = get_param(llwrapfn, arg_i); // In some cases, Rust will pass a pointer which the // native C type doesn't have. In that case, just @@ -558,14 +553,14 @@ pub fn trans_intrinsic(ccx: @CrateContext, let output_type = ty::ty_fn_ret(ty::node_id_to_type(ccx.tcx, item.id)); - let (fcx, imm) = new_fn_ctxt_w_id(ccx, - path, - decl, - item.id, - output_type, - None, - Some(substs), - Some(item.span)); + let fcx = new_fn_ctxt_w_id(ccx, + path, + decl, + item.id, + output_type, + None, + Some(substs), + Some(item.span)); // Set the fixed stack segment flag if necessary. if attr::attrs_contains_name(attributes, "fixed_stack_segment") { @@ -574,7 +569,7 @@ pub fn trans_intrinsic(ccx: @CrateContext, let mut bcx = top_scope_block(fcx, None); let lltop = bcx.llbb; - let first_real_arg = arg_pos(imm, 0u); + let first_real_arg = fcx.arg_pos(0u); match *ccx.sess.str_of(item.ident) { ~"atomic_cxchg" => { let old = AtomicCmpXchg(bcx, @@ -1356,14 +1351,12 @@ pub fn trans_foreign_fn(ccx: @CrateContext, fn build_args(bcx: block, tys: &ShimTypes, llwrapfn: ValueRef, - llargbundle: ValueRef, - ret_imm: bool) { + llargbundle: ValueRef) { let _icx = bcx.insn_ctxt("foreign::foreign::wrap::build_args"); tys.fn_ty.build_wrap_args(bcx, tys.llsig.llret_ty, llwrapfn, - llargbundle, - ret_imm); + llargbundle); } fn build_ret(bcx: block, tys: &ShimTypes, llargbundle: ValueRef) { diff --git a/src/librustc/middle/trans/glue.rs b/src/librustc/middle/trans/glue.rs index 29709cd553d5b..405e5e36de799 100644 --- a/src/librustc/middle/trans/glue.rs +++ b/src/librustc/middle/trans/glue.rs @@ -727,7 +727,7 @@ pub fn make_generic_glue_inner(ccx: @CrateContext, helper: glue_helper) -> ValueRef { let _icx = ccx.insn_ctxt("make_generic_glue_inner"); - let (fcx, imm) = new_fn_ctxt(ccx, ~[], llfn, ty::mk_nil(), None); + let fcx = new_fn_ctxt(ccx, ~[], llfn, ty::mk_nil(), None); lib::llvm::SetLinkage(llfn, lib::llvm::InternalLinkage); ccx.stats.n_glues_created += 1u; // All glue functions take values passed *by alias*; this is a @@ -740,7 +740,8 @@ pub fn make_generic_glue_inner(ccx: @CrateContext, let bcx = top_scope_block(fcx, None); let lltop = bcx.llbb; - let llrawptr0 = unsafe { llvm::LLVMGetParam(llfn, arg_pos(true, 1u) as c_uint) }; + let rawptr0_arg = fcx.arg_pos(1u); + let llrawptr0 = unsafe { llvm::LLVMGetParam(llfn, rawptr0_arg as c_uint) }; helper(bcx, llrawptr0, t); finish_fn(fcx, lltop); return llfn; diff --git a/src/librustc/middle/trans/reflect.rs b/src/librustc/middle/trans/reflect.rs index 681b11423ddc3..839c9a96b78e8 100644 --- a/src/librustc/middle/trans/reflect.rs +++ b/src/librustc/middle/trans/reflect.rs @@ -286,19 +286,19 @@ pub impl Reflector { let llfty = type_of_fn(ccx, [opaqueptrty], ty::mk_int()); let llfdecl = decl_internal_cdecl_fn(ccx.llmod, sym, llfty); + let fcx = new_fn_ctxt(ccx, + ~[], + llfdecl, + ty::mk_uint(), + None); let arg = unsafe { // // we know the return type of llfdecl is an int here, so // no need for a special check to see if the return type // is immediate. // - llvm::LLVMGetParam(llfdecl, arg_pos(true, 0u) as c_uint) + llvm::LLVMGetParam(llfdecl, fcx.arg_pos(0u) as c_uint) }; - let (fcx, _) = new_fn_ctxt(ccx, - ~[], - llfdecl, - ty::mk_uint(), - None); let bcx = top_scope_block(fcx, None); let arg = BitCast(bcx, arg, llptrty); let ret = adt::trans_get_discr(bcx, repr, arg);