diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index 90449e8a17aef..5bbfaac0792ae 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -1612,10 +1612,11 @@ pub fn new_fn_ctxt_w_id(ccx: @CrateContext, } }; let is_immediate = 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::LLVMGetUndef(T_ptr(T_i8())) + }, llretptr: None, llstaticallocas: llbbs.sa, llloadenv: None, @@ -1634,7 +1635,9 @@ 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 } @@ -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 = cx.arg_pos(i); let arg = &args[i]; let llarg = llvm::LLVMGetParam(cx.llfn, arg_n as c_uint); @@ -2293,19 +2296,26 @@ 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); + // 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 lloutputarg = C_null(T_ptr(T_i8())); - let llenvarg = unsafe { llvm::LLVMGetParam(llfdecl, 1 as c_uint) }; - let args = ~[lloutputarg, llenvarg]; + let llenvarg = unsafe { + 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); Store(bcx, llresult, fcx.llretptr.get()); @@ -2347,8 +2357,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 +2379,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 +2391,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/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..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,9 +684,6 @@ 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 struct Result { bcx: block, val: ValueRef @@ -962,8 +983,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..63356a135d059 100644 --- a/src/librustc/middle/trans/foreign.rs +++ b/src/librustc/middle/trans/foreign.rs @@ -153,6 +153,7 @@ fn build_shim_fn_(ccx: @CrateContext, let fcx = new_fn_ctxt(ccx, ~[], llshimfn, tys.fn_sig.output, None); let bcx = top_scope_block(fcx, None); let lltop = bcx.llbb; + let llargbundle = get_param(llshimfn, 0u); let llargvals = arg_builder(bcx, tys, llargbundle); @@ -437,11 +438,11 @@ pub fn trans_foreign_mod(ccx: @CrateContext, 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, fcx.arg_pos(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()); } @@ -465,11 +466,11 @@ pub fn trans_foreign_mod(ccx: @CrateContext, 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, fcx.arg_pos(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()); } @@ -512,9 +513,9 @@ pub fn trans_foreign_mod(ccx: @CrateContext, 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 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 @@ -568,6 +569,7 @@ pub fn trans_intrinsic(ccx: @CrateContext, let mut bcx = top_scope_block(fcx, None); let lltop = bcx.llbb; + let first_real_arg = fcx.arg_pos(0u); match *ccx.sess.str_of(item.ident) { ~"atomic_cxchg" => { let old = AtomicCmpXchg(bcx, @@ -1269,8 +1271,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())); diff --git a/src/librustc/middle/trans/glue.rs b/src/librustc/middle/trans/glue.rs index 2f48eda7edd26..405e5e36de799 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); @@ -739,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, 3u 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 b8d38cf7701bc..839c9a96b78e8 100644 --- a/src/librustc/middle/trans/reflect.rs +++ b/src/librustc/middle/trans/reflect.rs @@ -286,14 +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 arg = unsafe { - llvm::LLVMGetParam(llfdecl, first_real_arg as c_uint) - }; 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, fcx.arg_pos(0u) as c_uint) + }; 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..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! @@ -754,7 +761,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 266c0652c6e59..b5ecb1661755a 100644 --- a/src/rt/rust_task.cpp +++ b/src/rt/rust_task.cpp @@ -162,9 +162,11 @@ 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); +#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; @@ -185,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 ece0d48c3ae44..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 -typedef void (*CDECL spawn_fn)(void*, rust_opaque_box*, void *); +#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.