auto merge of #6731 : thomaslee/rust/issue-6575, r=pcwalton
Fix for #6575. In the trans phase, rustc emits code for a function parameter that goes completely unused in the event the return type of the function in question happens to be an immediate. This patch modifies rustc & parts of rustrt to ensure that the vestigial parameter is no longer present in compiled code.
This commit is contained in:
commit
e3d0c1eb0e
10 changed files with 100 additions and 51 deletions
|
@ -1612,10 +1612,11 @@ pub fn new_fn_ctxt_w_id(ccx: @CrateContext,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let is_immediate = ty::type_is_immediate(substd_output_type);
|
let is_immediate = ty::type_is_immediate(substd_output_type);
|
||||||
|
|
||||||
let fcx = @mut fn_ctxt_ {
|
let fcx = @mut fn_ctxt_ {
|
||||||
llfn: llfndecl,
|
llfn: llfndecl,
|
||||||
llenv: unsafe { llvm::LLVMGetParam(llfndecl, 1u as c_uint) },
|
llenv: unsafe {
|
||||||
|
llvm::LLVMGetUndef(T_ptr(T_i8()))
|
||||||
|
},
|
||||||
llretptr: None,
|
llretptr: None,
|
||||||
llstaticallocas: llbbs.sa,
|
llstaticallocas: llbbs.sa,
|
||||||
llloadenv: None,
|
llloadenv: None,
|
||||||
|
@ -1634,7 +1635,9 @@ pub fn new_fn_ctxt_w_id(ccx: @CrateContext,
|
||||||
path: path,
|
path: path,
|
||||||
ccx: @ccx
|
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.llretptr = Some(make_return_pointer(fcx, substd_output_type));
|
||||||
fcx
|
fcx
|
||||||
}
|
}
|
||||||
|
@ -1690,7 +1693,7 @@ pub fn create_llargs_for_fn_args(cx: fn_ctxt,
|
||||||
// llvm::LLVMGetParam for each argument.
|
// llvm::LLVMGetParam for each argument.
|
||||||
vec::from_fn(args.len(), |i| {
|
vec::from_fn(args.len(), |i| {
|
||||||
unsafe {
|
unsafe {
|
||||||
let arg_n = first_real_arg + i;
|
let arg_n = cx.arg_pos(i);
|
||||||
let arg = &args[i];
|
let arg = &args[i];
|
||||||
let llarg = llvm::LLVMGetParam(cx.llfn, arg_n as c_uint);
|
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 {
|
fn create_main(ccx: @CrateContext, main_llfn: ValueRef) -> ValueRef {
|
||||||
let nt = ty::mk_nil();
|
let nt = ty::mk_nil();
|
||||||
|
|
||||||
let llfty = type_of_fn(ccx, [], nt);
|
let llfty = type_of_fn(ccx, [], nt);
|
||||||
let llfdecl = decl_fn(ccx.llmod, "_rust_main",
|
let llfdecl = decl_fn(ccx.llmod, "_rust_main",
|
||||||
lib::llvm::CCallConv, llfty);
|
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 bcx = top_scope_block(fcx, None);
|
||||||
let lltop = bcx.llbb;
|
let lltop = bcx.llbb;
|
||||||
|
|
||||||
// Call main.
|
// Call main.
|
||||||
let lloutputarg = C_null(T_ptr(T_i8()));
|
let llenvarg = unsafe {
|
||||||
let llenvarg = unsafe { llvm::LLVMGetParam(llfdecl, 1 as c_uint) };
|
let env_arg = fcx.env_arg_pos();
|
||||||
let args = ~[lloutputarg, llenvarg];
|
llvm::LLVMGetParam(llfdecl, env_arg as c_uint)
|
||||||
|
};
|
||||||
|
let args = ~[llenvarg];
|
||||||
let llresult = Call(bcx, main_llfn, args);
|
let llresult = Call(bcx, main_llfn, args);
|
||||||
Store(bcx, llresult, fcx.llretptr.get());
|
Store(bcx, llresult, fcx.llretptr.get());
|
||||||
|
|
||||||
|
@ -2345,8 +2355,6 @@ pub fn create_entry_wrapper(ccx: @CrateContext,
|
||||||
trans_external_path(ccx, start_def_id, start_fn_type);
|
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 crate_map = ccx.crate_map;
|
||||||
let opaque_crate_map = llvm::LLVMBuildPointerCast(bld,
|
let opaque_crate_map = llvm::LLVMBuildPointerCast(bld,
|
||||||
crate_map,
|
crate_map,
|
||||||
|
@ -2368,7 +2376,6 @@ pub fn create_entry_wrapper(ccx: @CrateContext,
|
||||||
bld, rust_main, T_ptr(T_i8()), noname());
|
bld, rust_main, T_ptr(T_i8()), noname());
|
||||||
|
|
||||||
~[
|
~[
|
||||||
retptr,
|
|
||||||
C_null(T_opaque_box_ptr(ccx)),
|
C_null(T_opaque_box_ptr(ccx)),
|
||||||
opaque_rust_main,
|
opaque_rust_main,
|
||||||
llvm::LLVMGetParam(llfn, 0),
|
llvm::LLVMGetParam(llfn, 0),
|
||||||
|
@ -2381,7 +2388,6 @@ pub fn create_entry_wrapper(ccx: @CrateContext,
|
||||||
debug!("using user-defined start fn");
|
debug!("using user-defined start fn");
|
||||||
let args = {
|
let args = {
|
||||||
~[
|
~[
|
||||||
retptr,
|
|
||||||
C_null(T_opaque_box_ptr(ccx)),
|
C_null(T_opaque_box_ptr(ccx)),
|
||||||
llvm::LLVMGetParam(llfn, 0 as c_uint),
|
llvm::LLVMGetParam(llfn, 0 as c_uint),
|
||||||
llvm::LLVMGetParam(llfn, 1 as c_uint),
|
llvm::LLVMGetParam(llfn, 1 as c_uint),
|
||||||
|
|
|
@ -510,11 +510,7 @@ pub fn trans_call_inner(in_cx: block,
|
||||||
|
|
||||||
let mut llargs = ~[];
|
let mut llargs = ~[];
|
||||||
|
|
||||||
if ty::type_is_immediate(ret_ty) {
|
if !ty::type_is_immediate(ret_ty) {
|
||||||
unsafe {
|
|
||||||
llargs.push(llvm::LLVMGetUndef(T_ptr(T_i8())));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
llargs.push(llretslot);
|
llargs.push(llretslot);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -351,6 +351,30 @@ pub struct fn_ctxt_ {
|
||||||
ccx: @@CrateContext
|
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 type fn_ctxt = @mut fn_ctxt_;
|
||||||
|
|
||||||
pub fn warn_not_to_commit(ccx: @CrateContext, msg: &str) {
|
pub fn warn_not_to_commit(ccx: @CrateContext, msg: &str) {
|
||||||
|
@ -660,9 +684,6 @@ pub fn mk_block(llbb: BasicBlockRef, parent: Option<block>, kind: block_kind,
|
||||||
@mut block_(llbb, parent, kind, is_lpad, node_info, fcx)
|
@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 {
|
pub struct Result {
|
||||||
bcx: block,
|
bcx: block,
|
||||||
val: ValueRef
|
val: ValueRef
|
||||||
|
@ -962,8 +983,7 @@ pub fn T_tydesc(targ_cfg: @session::config) -> TypeRef {
|
||||||
let tydescpp = T_ptr(T_ptr(tydesc));
|
let tydescpp = T_ptr(T_ptr(tydesc));
|
||||||
let pvoid = T_ptr(T_i8());
|
let pvoid = T_ptr(T_i8());
|
||||||
let glue_fn_ty =
|
let glue_fn_ty =
|
||||||
T_ptr(T_fn([T_ptr(T_nil()), T_ptr(T_nil()), tydescpp,
|
T_ptr(T_fn([T_ptr(T_nil()), tydescpp, pvoid], T_void()));
|
||||||
pvoid], T_void()));
|
|
||||||
|
|
||||||
let int_type = T_int(targ_cfg);
|
let int_type = T_int(targ_cfg);
|
||||||
let elems =
|
let elems =
|
||||||
|
|
|
@ -153,6 +153,7 @@ fn build_shim_fn_(ccx: @CrateContext,
|
||||||
let fcx = 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 bcx = top_scope_block(fcx, None);
|
||||||
let lltop = bcx.llbb;
|
let lltop = bcx.llbb;
|
||||||
|
|
||||||
let llargbundle = get_param(llshimfn, 0u);
|
let llargbundle = get_param(llshimfn, 0u);
|
||||||
let llargvals = arg_builder(bcx, tys, llargbundle);
|
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 llbasefn = base_fn(ccx, *link_name(ccx, item), tys, cc);
|
||||||
let ty = ty::lookup_item_type(ccx.tcx,
|
let ty = ty::lookup_item_type(ccx.tcx,
|
||||||
ast_util::local_def(item.id)).ty;
|
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| {
|
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 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) {
|
if !ty::type_is_nil(ret_ty) && !ty::type_is_bot(ret_ty) {
|
||||||
Store(bcx, retval, fcx.llretptr.get());
|
Store(bcx, retval, fcx.llretptr.get());
|
||||||
}
|
}
|
||||||
|
@ -465,11 +466,11 @@ pub fn trans_foreign_mod(ccx: @CrateContext,
|
||||||
set_fixed_stack_segment(fcx.llfn);
|
set_fixed_stack_segment(fcx.llfn);
|
||||||
let ty = ty::lookup_item_type(ccx.tcx,
|
let ty = ty::lookup_item_type(ccx.tcx,
|
||||||
ast_util::local_def(item.id)).ty;
|
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| {
|
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 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) {
|
if !ty::type_is_nil(ret_ty) && !ty::type_is_bot(ret_ty) {
|
||||||
Store(bcx, retval, fcx.llretptr.get());
|
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 _icx = bcx.insn_ctxt("foreign::wrap::build_args");
|
||||||
let ccx = bcx.ccx();
|
let ccx = bcx.ccx();
|
||||||
let n = tys.llsig.llarg_tys.len();
|
let n = tys.llsig.llarg_tys.len();
|
||||||
let implicit_args = first_real_arg; // return + env
|
|
||||||
for uint::range(0, n) |i| {
|
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
|
// In some cases, Rust will pass a pointer which the
|
||||||
// native C type doesn't have. In that case, just
|
// 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 mut bcx = top_scope_block(fcx, None);
|
||||||
let lltop = bcx.llbb;
|
let lltop = bcx.llbb;
|
||||||
|
let first_real_arg = fcx.arg_pos(0u);
|
||||||
match *ccx.sess.str_of(item.ident) {
|
match *ccx.sess.str_of(item.ident) {
|
||||||
~"atomic_cxchg" => {
|
~"atomic_cxchg" => {
|
||||||
let old = AtomicCmpXchg(bcx,
|
let old = AtomicCmpXchg(bcx,
|
||||||
|
@ -1269,8 +1271,6 @@ pub fn trans_foreign_fn(ccx: @CrateContext,
|
||||||
if !ty::type_is_immediate(tys.fn_sig.output) {
|
if !ty::type_is_immediate(tys.fn_sig.output) {
|
||||||
let llretptr = load_inbounds(bcx, llargbundle, [0u, n]);
|
let llretptr = load_inbounds(bcx, llargbundle, [0u, n]);
|
||||||
llargvals.push(llretptr);
|
llargvals.push(llretptr);
|
||||||
} else {
|
|
||||||
llargvals.push(C_null(T_ptr(T_i8())));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let llenvptr = C_null(T_opaque_box_ptr(bcx.ccx()));
|
let llenvptr = C_null(T_opaque_box_ptr(bcx.ccx()));
|
||||||
|
|
|
@ -19,6 +19,7 @@ use back::link::*;
|
||||||
use driver::session;
|
use driver::session;
|
||||||
use lib;
|
use lib;
|
||||||
use lib::llvm::{llvm, ValueRef, TypeRef, True};
|
use lib::llvm::{llvm, ValueRef, TypeRef, True};
|
||||||
|
use lib::llvm::type_to_str;
|
||||||
use middle::trans::adt;
|
use middle::trans::adt;
|
||||||
use middle::trans::base::*;
|
use middle::trans::base::*;
|
||||||
use middle::trans::callee;
|
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())),
|
Call(bcx, llfn, [C_null(T_ptr(T_nil())),
|
||||||
C_null(T_ptr(T_ptr(bcx.ccx().tydesc_type))), llrawptr]);
|
C_null(T_ptr(T_ptr(bcx.ccx().tydesc_type))),
|
||||||
|
llrawptr]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// See [Note-arg-mode]
|
// 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
|
// Class dtors have no explicit args, so the params should
|
||||||
// just consist of the output pointer and the environment
|
// just consist of the environment (self)
|
||||||
// (self)
|
assert_eq!(params.len(), 1);
|
||||||
assert_eq!(params.len(), 2);
|
|
||||||
|
|
||||||
// Take a reference to the class (because it's using the Drop trait),
|
// Take a reference to the class (because it's using the Drop trait),
|
||||||
// do so now.
|
// do so now.
|
||||||
let llval = alloca(bcx, val_ty(v0));
|
let llval = alloca(bcx, val_ty(v0));
|
||||||
Store(bcx, v0, llval);
|
Store(bcx, v0, llval);
|
||||||
|
|
||||||
let self_arg = PointerCast(bcx, llval, params[1]);
|
let self_arg = PointerCast(bcx, llval, params[0]);
|
||||||
let args = ~[C_null(T_ptr(T_i8())), self_arg];
|
let args = ~[self_arg];
|
||||||
|
|
||||||
Call(bcx, dtor_addr, args);
|
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 bcx = top_scope_block(fcx, None);
|
||||||
let lltop = bcx.llbb;
|
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);
|
helper(bcx, llrawptr0, t);
|
||||||
finish_fn(fcx, lltop);
|
finish_fn(fcx, lltop);
|
||||||
return llfn;
|
return llfn;
|
||||||
|
|
|
@ -286,14 +286,19 @@ pub impl Reflector {
|
||||||
|
|
||||||
let llfty = type_of_fn(ccx, [opaqueptrty], ty::mk_int());
|
let llfty = type_of_fn(ccx, [opaqueptrty], ty::mk_int());
|
||||||
let llfdecl = decl_internal_cdecl_fn(ccx.llmod, sym, llfty);
|
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,
|
let fcx = new_fn_ctxt(ccx,
|
||||||
~[],
|
~[],
|
||||||
llfdecl,
|
llfdecl,
|
||||||
ty::mk_uint(),
|
ty::mk_uint(),
|
||||||
None);
|
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 bcx = top_scope_block(fcx, None);
|
||||||
let arg = BitCast(bcx, arg, llptrty);
|
let arg = BitCast(bcx, arg, llptrty);
|
||||||
let ret = adt::trans_get_discr(bcx, repr, arg);
|
let ret = adt::trans_get_discr(bcx, repr, arg);
|
||||||
|
|
|
@ -46,9 +46,6 @@ pub fn type_of_fn(cx: @CrateContext, inputs: &[ty::t], output: ty::t)
|
||||||
let lloutputtype = type_of(cx, output);
|
let lloutputtype = type_of(cx, output);
|
||||||
if !output_is_immediate {
|
if !output_is_immediate {
|
||||||
atys.push(T_ptr(lloutputtype));
|
atys.push(T_ptr(lloutputtype));
|
||||||
} else {
|
|
||||||
// FIXME #6575: Eliminate this.
|
|
||||||
atys.push(T_ptr(T_i8()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Arg 1: Environment
|
// 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 {
|
pub fn type_of_dtor(ccx: @CrateContext, self_ty: ty::t) -> TypeRef {
|
||||||
T_fn([T_ptr(T_i8()), // output pointer
|
T_fn([T_ptr(type_of(ccx, self_ty))] /* self */, T_nil())
|
||||||
T_ptr(type_of(ccx, self_ty))], // self arg
|
|
||||||
T_nil())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn type_of_rooted(ccx: @CrateContext, t: ty::t) -> TypeRef {
|
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 {
|
pub fn type_of_glue_fn(ccx: @CrateContext, t: ty::t) -> TypeRef {
|
||||||
let tydescpp = T_ptr(T_ptr(ccx.tydesc_type));
|
let tydescpp = T_ptr(T_ptr(ccx.tydesc_type));
|
||||||
let llty = T_ptr(type_of(ccx, t));
|
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());
|
||||||
}
|
}
|
||||||
|
|
|
@ -731,10 +731,17 @@ rust_task_deref(rust_task *task) {
|
||||||
// Must call on rust stack.
|
// Must call on rust stack.
|
||||||
extern "C" CDECL void
|
extern "C" CDECL void
|
||||||
rust_call_tydesc_glue(void *root, size_t *tydesc, size_t glue_index) {
|
rust_call_tydesc_glue(void *root, size_t *tydesc, size_t glue_index) {
|
||||||
|
#ifdef _RUST_STAGE0
|
||||||
void (*glue_fn)(void *, void *, void *, void *) =
|
void (*glue_fn)(void *, void *, void *, void *) =
|
||||||
(void (*)(void *, void *, void *, void *))tydesc[glue_index];
|
(void (*)(void *, void *, void *, void *))tydesc[glue_index];
|
||||||
if (glue_fn)
|
if (glue_fn)
|
||||||
glue_fn(0, 0, 0, root);
|
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!
|
// Don't run on the Rust stack!
|
||||||
|
@ -754,7 +761,11 @@ public:
|
||||||
|
|
||||||
virtual void run() {
|
virtual void run() {
|
||||||
record_sp_limit(0);
|
record_sp_limit(0);
|
||||||
|
#ifdef _RUST_STAGE0
|
||||||
fn.f(NULL, fn.env, NULL);
|
fn.f(NULL, fn.env, NULL);
|
||||||
|
#else
|
||||||
|
fn.f(fn.env, NULL);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -162,9 +162,11 @@ void task_start_wrapper(spawn_args *a)
|
||||||
|
|
||||||
bool threw_exception = false;
|
bool threw_exception = false;
|
||||||
try {
|
try {
|
||||||
// The first argument is the return pointer; as the task fn
|
#ifdef _RUST_STAGE0
|
||||||
// must have void return type, we can safely pass 0.
|
a->f(NULL, a->envptr, a->argptr);
|
||||||
a->f(0, a->envptr, a->argptr);
|
#else
|
||||||
|
a->f(a->envptr, a->argptr);
|
||||||
|
#endif
|
||||||
} catch (rust_task *ex) {
|
} catch (rust_task *ex) {
|
||||||
assert(ex == task && "Expected this task to be thrown for unwinding");
|
assert(ex == task && "Expected this task to be thrown for unwinding");
|
||||||
threw_exception = true;
|
threw_exception = true;
|
||||||
|
@ -185,7 +187,11 @@ void task_start_wrapper(spawn_args *a)
|
||||||
if(env) {
|
if(env) {
|
||||||
// free the environment (which should be a unique closure).
|
// free the environment (which should be a unique closure).
|
||||||
const type_desc *td = env->td;
|
const type_desc *td = env->td;
|
||||||
|
#ifdef _RUST_STAGE0
|
||||||
td->drop_glue(NULL, NULL, NULL, box_body(env));
|
td->drop_glue(NULL, NULL, NULL, box_body(env));
|
||||||
|
#else
|
||||||
|
td->drop_glue(NULL, NULL, box_body(env));
|
||||||
|
#endif
|
||||||
task->kernel->region()->free(env);
|
task->kernel->region()->free(env);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,11 +21,19 @@ struct rust_opaque_box;
|
||||||
// - the main function: has a NULL environment, but uses the void* arg
|
// - the main function: has a NULL environment, but uses the void* arg
|
||||||
// - unique closures of type fn~(): have a non-NULL environment, but
|
// - unique closures of type fn~(): have a non-NULL environment, but
|
||||||
// no arguments (and hence the final void*) is harmless
|
// 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;
|
struct type_desc;
|
||||||
|
|
||||||
|
#ifdef _RUST_STAGE0
|
||||||
typedef void CDECL (glue_fn)(void *, void *, const type_desc **, void *);
|
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
|
// Corresponds to the boxed data in the @ region. The body follows the
|
||||||
// header; you can obtain a ptr via box_body() below.
|
// header; you can obtain a ptr via box_body() below.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue