about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc/middle/trans/glue.rs22
-rw-r--r--src/librustc/middle/trans/type_.rs8
2 files changed, 22 insertions, 8 deletions
diff --git a/src/librustc/middle/trans/glue.rs b/src/librustc/middle/trans/glue.rs
index 418c89e603d..60efe72fd13 100644
--- a/src/librustc/middle/trans/glue.rs
+++ b/src/librustc/middle/trans/glue.rs
@@ -230,7 +230,7 @@ pub fn lazily_emit_tydesc_glue(ccx: @mut CrateContext,
                                field: uint,
                                ti: @mut tydesc_info) {
     let _icx = push_ctxt("lazily_emit_tydesc_glue");
-    let llfnty = Type::glue_fn();
+    let llfnty = Type::glue_fn(type_of::type_of(ccx, ti.ty).ptr_to());
 
     if lazily_emit_simplified_tydesc_glue(ccx, field, ti) {
         return;
@@ -323,7 +323,20 @@ pub fn call_tydesc_glue_full(bcx: block,
       }
     };
 
-    let llrawptr = PointerCast(bcx, v, Type::i8p());
+    // When static type info is available, avoid casting parameter unless the
+    // glue is using a simplified type, because the function already has the
+    // right type. Otherwise cast to generic pointer.
+    let llrawptr = if static_ti.is_none() || static_glue_fn.is_none() {
+        PointerCast(bcx, v, Type::i8p())
+    } else {
+        let ty = static_ti.get().ty;
+        let simpl = simplified_glue_type(ccx.tcx, field, ty);
+        if simpl != ty {
+            PointerCast(bcx, v, type_of(ccx, simpl).ptr_to())
+        } else {
+            v
+        }
+    };
 
     let llfn = {
         match static_glue_fn {
@@ -709,13 +722,14 @@ pub fn make_generic_glue_inner(ccx: @mut CrateContext,
     // requirement since in many contexts glue is invoked indirectly and
     // the caller has no idea if it's dealing with something that can be
     // passed by value.
+    //
+    // llfn is expected be declared to take a parameter of the appropriate
+    // type, so we don't need to explicitly cast the function parameter.
 
     let bcx = top_scope_block(fcx, None);
     let lltop = bcx.llbb;
     let rawptr0_arg = fcx.arg_pos(0u);
     let llrawptr0 = unsafe { llvm::LLVMGetParam(llfn, rawptr0_arg as c_uint) };
-    let llty = type_of(ccx, t);
-    let llrawptr0 = PointerCast(bcx, llrawptr0, llty.ptr_to());
     let bcx = helper(bcx, llrawptr0, t);
 
     finish_fn(fcx, lltop, bcx);
diff --git a/src/librustc/middle/trans/type_.rs b/src/librustc/middle/trans/type_.rs
index 7878e17f7fc..67df6f38b3a 100644
--- a/src/librustc/middle/trans/type_.rs
+++ b/src/librustc/middle/trans/type_.rs
@@ -187,20 +187,20 @@ impl Type {
             None => ()
         }
 
-        let ty = Type::glue_fn();
+        let ty = Type::glue_fn(Type::i8p());
         cx.tn.associate_type("glue_fn", &ty);
 
         return ty;
     }
 
-    pub fn glue_fn() -> Type {
-        Type::func([ Type::nil().ptr_to(), Type::i8p() ],
+    pub fn glue_fn(t: Type) -> Type {
+        Type::func([ Type::nil().ptr_to(), t ],
             &Type::void())
     }
 
     pub fn tydesc(arch: Architecture) -> Type {
         let mut tydesc = Type::named_struct("tydesc");
-        let glue_fn_ty = Type::glue_fn().ptr_to();
+        let glue_fn_ty = Type::glue_fn(Type::i8p()).ptr_to();
 
         let int_ty = Type::int(arch);