about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2013-05-28 17:37:57 -0700
committerbors <bors@rust-lang.org>2013-05-28 17:37:57 -0700
commite3d0c1eb0e86e04c2a6d5abe526516351cfaef3f (patch)
treeb0971e4ba3c1a990cdb9f9ee02b3d414b2fd7729
parent5676056ae6dd3a10d2c7323375ace3ca2fe1c308 (diff)
parentb7f71e1ee661ea0d5d9731fcf4779a452bbee486 (diff)
downloadrust-e3d0c1eb0e86e04c2a6d5abe526516351cfaef3f.tar.gz
rust-e3d0c1eb0e86e04c2a6d5abe526516351cfaef3f.zip
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.
-rw-r--r--src/librustc/middle/trans/base.rs28
-rw-r--r--src/librustc/middle/trans/callee.rs6
-rw-r--r--src/librustc/middle/trans/common.rs30
-rw-r--r--src/librustc/middle/trans/foreign.rs16
-rw-r--r--src/librustc/middle/trans/glue.rs18
-rw-r--r--src/librustc/middle/trans/reflect.rs11
-rw-r--r--src/librustc/middle/trans/type_of.rs9
-rw-r--r--src/rt/rust_builtin.cpp11
-rw-r--r--src/rt/rust_task.cpp12
-rw-r--r--src/rt/rust_type.h10
10 files changed, 100 insertions, 51 deletions
diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs
index 0518f699329..f0250d5a063 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());
 
@@ -2345,8 +2355,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,
@@ -2368,7 +2376,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),
@@ -2381,7 +2388,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 3d4649bba46..b710f33d6ab 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 be074cfc57a..ad5dadaf870 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<block>, 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 b0560c40277..63356a135d0 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 2f48eda7edd..405e5e36de7 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 b8d38cf7701..839c9a96b78 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 bddcb9a1d73..e3c424f8e7e 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 b0a46d2ac29..5e7357c9b7b 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 @@ public:
 
     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 266c0652c6e..b5ecb166175 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 ece0d48c3ae..b50c08379de 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.