Skip to content

Commit e3d0c1e

Browse files
committed
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.
2 parents 5676056 + b7f71e1 commit e3d0c1e

File tree

10 files changed

+100
-51
lines changed

10 files changed

+100
-51
lines changed

src/librustc/middle/trans/base.rs

+17-11
Original file line numberDiff line numberDiff line change
@@ -1612,10 +1612,11 @@ pub fn new_fn_ctxt_w_id(ccx: @CrateContext,
16121612
}
16131613
};
16141614
let is_immediate = ty::type_is_immediate(substd_output_type);
1615-
16161615
let fcx = @mut fn_ctxt_ {
16171616
llfn: llfndecl,
1618-
llenv: unsafe { llvm::LLVMGetParam(llfndecl, 1u as c_uint) },
1617+
llenv: unsafe {
1618+
llvm::LLVMGetUndef(T_ptr(T_i8()))
1619+
},
16191620
llretptr: None,
16201621
llstaticallocas: llbbs.sa,
16211622
llloadenv: None,
@@ -1634,7 +1635,9 @@ pub fn new_fn_ctxt_w_id(ccx: @CrateContext,
16341635
path: path,
16351636
ccx: @ccx
16361637
};
1637-
1638+
fcx.llenv = unsafe {
1639+
llvm::LLVMGetParam(llfndecl, fcx.env_arg_pos() as c_uint)
1640+
};
16381641
fcx.llretptr = Some(make_return_pointer(fcx, substd_output_type));
16391642
fcx
16401643
}
@@ -1690,7 +1693,7 @@ pub fn create_llargs_for_fn_args(cx: fn_ctxt,
16901693
// llvm::LLVMGetParam for each argument.
16911694
vec::from_fn(args.len(), |i| {
16921695
unsafe {
1693-
let arg_n = first_real_arg + i;
1696+
let arg_n = cx.arg_pos(i);
16941697
let arg = &args[i];
16951698
let llarg = llvm::LLVMGetParam(cx.llfn, arg_n as c_uint);
16961699

@@ -2293,19 +2296,26 @@ pub fn create_entry_wrapper(ccx: @CrateContext,
22932296
22942297
fn create_main(ccx: @CrateContext, main_llfn: ValueRef) -> ValueRef {
22952298
let nt = ty::mk_nil();
2299+
22962300
let llfty = type_of_fn(ccx, [], nt);
22972301
let llfdecl = decl_fn(ccx.llmod, "_rust_main",
22982302
lib::llvm::CCallConv, llfty);
22992303
23002304
let fcx = new_fn_ctxt(ccx, ~[], llfdecl, nt, None);
23012305
2306+
// the args vector built in create_entry_fn will need
2307+
// be updated if this assertion starts to fail.
2308+
assert!(fcx.has_immediate_return_value);
2309+
23022310
let bcx = top_scope_block(fcx, None);
23032311
let lltop = bcx.llbb;
23042312
23052313
// Call main.
2306-
let lloutputarg = C_null(T_ptr(T_i8()));
2307-
let llenvarg = unsafe { llvm::LLVMGetParam(llfdecl, 1 as c_uint) };
2308-
let args = ~[lloutputarg, llenvarg];
2314+
let llenvarg = unsafe {
2315+
let env_arg = fcx.env_arg_pos();
2316+
llvm::LLVMGetParam(llfdecl, env_arg as c_uint)
2317+
};
2318+
let args = ~[llenvarg];
23092319
let llresult = Call(bcx, main_llfn, args);
23102320
Store(bcx, llresult, fcx.llretptr.get());
23112321
@@ -2345,8 +2355,6 @@ pub fn create_entry_wrapper(ccx: @CrateContext,
23452355
trans_external_path(ccx, start_def_id, start_fn_type);
23462356
}
23472357
2348-
let retptr = llvm::LLVMBuildAlloca(bld, T_i8(), noname());
2349-
23502358
let crate_map = ccx.crate_map;
23512359
let opaque_crate_map = llvm::LLVMBuildPointerCast(bld,
23522360
crate_map,
@@ -2368,7 +2376,6 @@ pub fn create_entry_wrapper(ccx: @CrateContext,
23682376
bld, rust_main, T_ptr(T_i8()), noname());
23692377
23702378
~[
2371-
retptr,
23722379
C_null(T_opaque_box_ptr(ccx)),
23732380
opaque_rust_main,
23742381
llvm::LLVMGetParam(llfn, 0),
@@ -2381,7 +2388,6 @@ pub fn create_entry_wrapper(ccx: @CrateContext,
23812388
debug!("using user-defined start fn");
23822389
let args = {
23832390
~[
2384-
retptr,
23852391
C_null(T_opaque_box_ptr(ccx)),
23862392
llvm::LLVMGetParam(llfn, 0 as c_uint),
23872393
llvm::LLVMGetParam(llfn, 1 as c_uint),

src/librustc/middle/trans/callee.rs

+1-5
Original file line numberDiff line numberDiff line change
@@ -510,11 +510,7 @@ pub fn trans_call_inner(in_cx: block,
510510

511511
let mut llargs = ~[];
512512

513-
if ty::type_is_immediate(ret_ty) {
514-
unsafe {
515-
llargs.push(llvm::LLVMGetUndef(T_ptr(T_i8())));
516-
}
517-
} else {
513+
if !ty::type_is_immediate(ret_ty) {
518514
llargs.push(llretslot);
519515
}
520516

src/librustc/middle/trans/common.rs

+25-5
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,30 @@ pub struct fn_ctxt_ {
351351
ccx: @@CrateContext
352352
}
353353

354+
pub impl fn_ctxt_ {
355+
pub fn arg_pos(&self, arg: uint) -> uint {
356+
if self.has_immediate_return_value {
357+
arg + 1u
358+
} else {
359+
arg + 2u
360+
}
361+
}
362+
363+
pub fn out_arg_pos(&self) -> uint {
364+
assert!(self.has_immediate_return_value);
365+
0u
366+
}
367+
368+
pub fn env_arg_pos(&self) -> uint {
369+
if !self.has_immediate_return_value {
370+
1u
371+
} else {
372+
0u
373+
}
374+
}
375+
376+
}
377+
354378
pub type fn_ctxt = @mut fn_ctxt_;
355379

356380
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,
660684
@mut block_(llbb, parent, kind, is_lpad, node_info, fcx)
661685
}
662686

663-
// First two args are retptr, env
664-
pub static first_real_arg: uint = 2u;
665-
666687
pub struct Result {
667688
bcx: block,
668689
val: ValueRef
@@ -962,8 +983,7 @@ pub fn T_tydesc(targ_cfg: @session::config) -> TypeRef {
962983
let tydescpp = T_ptr(T_ptr(tydesc));
963984
let pvoid = T_ptr(T_i8());
964985
let glue_fn_ty =
965-
T_ptr(T_fn([T_ptr(T_nil()), T_ptr(T_nil()), tydescpp,
966-
pvoid], T_void()));
986+
T_ptr(T_fn([T_ptr(T_nil()), tydescpp, pvoid], T_void()));
967987

968988
let int_type = T_int(targ_cfg);
969989
let elems =

src/librustc/middle/trans/foreign.rs

+8-8
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,7 @@ fn build_shim_fn_(ccx: @CrateContext,
153153
let fcx = new_fn_ctxt(ccx, ~[], llshimfn, tys.fn_sig.output, None);
154154
let bcx = top_scope_block(fcx, None);
155155
let lltop = bcx.llbb;
156+
156157
let llargbundle = get_param(llshimfn, 0u);
157158
let llargvals = arg_builder(bcx, tys, llargbundle);
158159

@@ -437,11 +438,11 @@ pub fn trans_foreign_mod(ccx: @CrateContext,
437438
let llbasefn = base_fn(ccx, *link_name(ccx, item), tys, cc);
438439
let ty = ty::lookup_item_type(ccx.tcx,
439440
ast_util::local_def(item.id)).ty;
441+
let ret_ty = ty::ty_fn_ret(ty);
440442
let args = vec::from_fn(ty::ty_fn_args(ty).len(), |i| {
441-
get_param(decl, i + first_real_arg)
443+
get_param(decl, fcx.arg_pos(i))
442444
});
443445
let retval = Call(bcx, llbasefn, args);
444-
let ret_ty = ty::ty_fn_ret(ty);
445446
if !ty::type_is_nil(ret_ty) && !ty::type_is_bot(ret_ty) {
446447
Store(bcx, retval, fcx.llretptr.get());
447448
}
@@ -465,11 +466,11 @@ pub fn trans_foreign_mod(ccx: @CrateContext,
465466
set_fixed_stack_segment(fcx.llfn);
466467
let ty = ty::lookup_item_type(ccx.tcx,
467468
ast_util::local_def(item.id)).ty;
469+
let ret_ty = ty::ty_fn_ret(ty);
468470
let args = vec::from_fn(ty::ty_fn_args(ty).len(), |i| {
469-
get_param(decl, i + first_real_arg)
471+
get_param(decl, fcx.arg_pos(i))
470472
});
471473
let retval = Call(bcx, llbasefn, args);
472-
let ret_ty = ty::ty_fn_ret(ty);
473474
if !ty::type_is_nil(ret_ty) && !ty::type_is_bot(ret_ty) {
474475
Store(bcx, retval, fcx.llretptr.get());
475476
}
@@ -512,9 +513,9 @@ pub fn trans_foreign_mod(ccx: @CrateContext,
512513
let _icx = bcx.insn_ctxt("foreign::wrap::build_args");
513514
let ccx = bcx.ccx();
514515
let n = tys.llsig.llarg_tys.len();
515-
let implicit_args = first_real_arg; // return + env
516516
for uint::range(0, n) |i| {
517-
let mut llargval = get_param(llwrapfn, i + implicit_args);
517+
let arg_i = bcx.fcx.arg_pos(i);
518+
let mut llargval = get_param(llwrapfn, arg_i);
518519

519520
// In some cases, Rust will pass a pointer which the
520521
// native C type doesn't have. In that case, just
@@ -568,6 +569,7 @@ pub fn trans_intrinsic(ccx: @CrateContext,
568569

569570
let mut bcx = top_scope_block(fcx, None);
570571
let lltop = bcx.llbb;
572+
let first_real_arg = fcx.arg_pos(0u);
571573
match *ccx.sess.str_of(item.ident) {
572574
~"atomic_cxchg" => {
573575
let old = AtomicCmpXchg(bcx,
@@ -1269,8 +1271,6 @@ pub fn trans_foreign_fn(ccx: @CrateContext,
12691271
if !ty::type_is_immediate(tys.fn_sig.output) {
12701272
let llretptr = load_inbounds(bcx, llargbundle, [0u, n]);
12711273
llargvals.push(llretptr);
1272-
} else {
1273-
llargvals.push(C_null(T_ptr(T_i8())));
12741274
}
12751275

12761276
let llenvptr = C_null(T_opaque_box_ptr(bcx.ccx()));

src/librustc/middle/trans/glue.rs

+10-8
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ use back::link::*;
1919
use driver::session;
2020
use lib;
2121
use lib::llvm::{llvm, ValueRef, TypeRef, True};
22+
use lib::llvm::type_to_str;
2223
use middle::trans::adt;
2324
use middle::trans::base::*;
2425
use middle::trans::callee;
@@ -381,8 +382,9 @@ pub fn call_tydesc_glue_full(bcx: block,
381382
}
382383
};
383384

384-
Call(bcx, llfn, [C_null(T_ptr(T_nil())), C_null(T_ptr(T_nil())),
385-
C_null(T_ptr(T_ptr(bcx.ccx().tydesc_type))), llrawptr]);
385+
Call(bcx, llfn, [C_null(T_ptr(T_nil())),
386+
C_null(T_ptr(T_ptr(bcx.ccx().tydesc_type))),
387+
llrawptr]);
386388
}
387389

388390
// See [Note-arg-mode]
@@ -483,17 +485,16 @@ pub fn trans_struct_drop(bcx: block,
483485
};
484486

485487
// Class dtors have no explicit args, so the params should
486-
// just consist of the output pointer and the environment
487-
// (self)
488-
assert_eq!(params.len(), 2);
488+
// just consist of the environment (self)
489+
assert_eq!(params.len(), 1);
489490

490491
// Take a reference to the class (because it's using the Drop trait),
491492
// do so now.
492493
let llval = alloca(bcx, val_ty(v0));
493494
Store(bcx, v0, llval);
494495

495-
let self_arg = PointerCast(bcx, llval, params[1]);
496-
let args = ~[C_null(T_ptr(T_i8())), self_arg];
496+
let self_arg = PointerCast(bcx, llval, params[0]);
497+
let args = ~[self_arg];
497498

498499
Call(bcx, dtor_addr, args);
499500

@@ -739,7 +740,8 @@ pub fn make_generic_glue_inner(ccx: @CrateContext,
739740

740741
let bcx = top_scope_block(fcx, None);
741742
let lltop = bcx.llbb;
742-
let llrawptr0 = unsafe { llvm::LLVMGetParam(llfn, 3u as c_uint) };
743+
let rawptr0_arg = fcx.arg_pos(1u);
744+
let llrawptr0 = unsafe { llvm::LLVMGetParam(llfn, rawptr0_arg as c_uint) };
743745
helper(bcx, llrawptr0, t);
744746
finish_fn(fcx, lltop);
745747
return llfn;

src/librustc/middle/trans/reflect.rs

+8-3
Original file line numberDiff line numberDiff line change
@@ -286,14 +286,19 @@ pub impl Reflector {
286286

287287
let llfty = type_of_fn(ccx, [opaqueptrty], ty::mk_int());
288288
let llfdecl = decl_internal_cdecl_fn(ccx.llmod, sym, llfty);
289-
let arg = unsafe {
290-
llvm::LLVMGetParam(llfdecl, first_real_arg as c_uint)
291-
};
292289
let fcx = new_fn_ctxt(ccx,
293290
~[],
294291
llfdecl,
295292
ty::mk_uint(),
296293
None);
294+
let arg = unsafe {
295+
//
296+
// we know the return type of llfdecl is an int here, so
297+
// no need for a special check to see if the return type
298+
// is immediate.
299+
//
300+
llvm::LLVMGetParam(llfdecl, fcx.arg_pos(0u) as c_uint)
301+
};
297302
let bcx = top_scope_block(fcx, None);
298303
let arg = BitCast(bcx, arg, llptrty);
299304
let ret = adt::trans_get_discr(bcx, repr, arg);

src/librustc/middle/trans/type_of.rs

+2-7
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,6 @@ pub fn type_of_fn(cx: @CrateContext, inputs: &[ty::t], output: ty::t)
4646
let lloutputtype = type_of(cx, output);
4747
if !output_is_immediate {
4848
atys.push(T_ptr(lloutputtype));
49-
} else {
50-
// FIXME #6575: Eliminate this.
51-
atys.push(T_ptr(T_i8()));
5249
}
5350

5451
// Arg 1: Environment
@@ -334,9 +331,7 @@ pub fn llvm_type_name(cx: @CrateContext,
334331
}
335332

336333
pub fn type_of_dtor(ccx: @CrateContext, self_ty: ty::t) -> TypeRef {
337-
T_fn([T_ptr(T_i8()), // output pointer
338-
T_ptr(type_of(ccx, self_ty))], // self arg
339-
T_nil())
334+
T_fn([T_ptr(type_of(ccx, self_ty))] /* self */, T_nil())
340335
}
341336

342337
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 {
349344
pub fn type_of_glue_fn(ccx: @CrateContext, t: ty::t) -> TypeRef {
350345
let tydescpp = T_ptr(T_ptr(ccx.tydesc_type));
351346
let llty = T_ptr(type_of(ccx, t));
352-
return T_fn([T_ptr(T_nil()), T_ptr(T_nil()), tydescpp, llty], T_nil());
347+
return T_fn([T_ptr(T_nil()), tydescpp, llty], T_nil());
353348
}

src/rt/rust_builtin.cpp

+11
Original file line numberDiff line numberDiff line change
@@ -731,10 +731,17 @@ rust_task_deref(rust_task *task) {
731731
// Must call on rust stack.
732732
extern "C" CDECL void
733733
rust_call_tydesc_glue(void *root, size_t *tydesc, size_t glue_index) {
734+
#ifdef _RUST_STAGE0
734735
void (*glue_fn)(void *, void *, void *, void *) =
735736
(void (*)(void *, void *, void *, void *))tydesc[glue_index];
736737
if (glue_fn)
737738
glue_fn(0, 0, 0, root);
739+
#else
740+
void (*glue_fn)(void *, void *, void *) =
741+
(void (*)(void *, void *, void *))tydesc[glue_index];
742+
if (glue_fn)
743+
glue_fn(0, 0, root);
744+
#endif
738745
}
739746

740747
// Don't run on the Rust stack!
@@ -754,7 +761,11 @@ class raw_thread: public rust_thread {
754761

755762
virtual void run() {
756763
record_sp_limit(0);
764+
#ifdef _RUST_STAGE0
757765
fn.f(NULL, fn.env, NULL);
766+
#else
767+
fn.f(fn.env, NULL);
768+
#endif
758769
}
759770
};
760771

src/rt/rust_task.cpp

+9-3
Original file line numberDiff line numberDiff line change
@@ -162,9 +162,11 @@ void task_start_wrapper(spawn_args *a)
162162

163163
bool threw_exception = false;
164164
try {
165-
// The first argument is the return pointer; as the task fn
166-
// must have void return type, we can safely pass 0.
167-
a->f(0, a->envptr, a->argptr);
165+
#ifdef _RUST_STAGE0
166+
a->f(NULL, a->envptr, a->argptr);
167+
#else
168+
a->f(a->envptr, a->argptr);
169+
#endif
168170
} catch (rust_task *ex) {
169171
assert(ex == task && "Expected this task to be thrown for unwinding");
170172
threw_exception = true;
@@ -185,7 +187,11 @@ void task_start_wrapper(spawn_args *a)
185187
if(env) {
186188
// free the environment (which should be a unique closure).
187189
const type_desc *td = env->td;
190+
#ifdef _RUST_STAGE0
188191
td->drop_glue(NULL, NULL, NULL, box_body(env));
192+
#else
193+
td->drop_glue(NULL, NULL, box_body(env));
194+
#endif
189195
task->kernel->region()->free(env);
190196
}
191197

src/rt/rust_type.h

+9-1
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,19 @@ struct rust_opaque_box;
2121
// - the main function: has a NULL environment, but uses the void* arg
2222
// - unique closures of type fn~(): have a non-NULL environment, but
2323
// no arguments (and hence the final void*) is harmless
24-
typedef void (*CDECL spawn_fn)(void*, rust_opaque_box*, void *);
24+
#ifdef _RUST_STAGE0
25+
typedef void (*CDECL spawn_fn)(void *, rust_opaque_box*, void *);
26+
#else
27+
typedef void (*CDECL spawn_fn)(rust_opaque_box*, void *);
28+
#endif
2529

2630
struct type_desc;
2731

32+
#ifdef _RUST_STAGE0
2833
typedef void CDECL (glue_fn)(void *, void *, const type_desc **, void *);
34+
#else
35+
typedef void CDECL (glue_fn)(void *, const type_desc **, void *);
36+
#endif
2937

3038
// Corresponds to the boxed data in the @ region. The body follows the
3139
// header; you can obtain a ptr via box_body() below.

0 commit comments

Comments
 (0)