]> git.lizzy.rs Git - rust.git/commitdiff
Fix handling of C arguments
authorSimonas Kazlauskas <git@kazlauskas.me>
Wed, 25 May 2016 23:45:13 +0000 (02:45 +0300)
committerSimonas Kazlauskas <git@kazlauskas.me>
Wed, 25 May 2016 23:45:13 +0000 (02:45 +0300)
Fixes #33868

src/librustc_trans/base.rs
src/librustc_trans/mir/mod.rs

index 03e12c1c8a7b04f312c8cb0f9123b80754ed02e6..5a9b4e109a5ba9837faf07f518bc800a475b6fcb 100644 (file)
@@ -1663,21 +1663,30 @@ fn bind_args(&'blk self,
                                     arg_ty,
                                     datum::Lvalue::new("FunctionContext::bind_args"))
                 } else {
-                    unpack_datum!(bcx, datum::lvalue_scratch_datum(bcx, arg_ty, "",
-                                                                   uninit_reason,
-                                                                   arg_scope_id, |bcx, dst| {
-                        debug!("FunctionContext::bind_args: {:?}: {:?}", hir_arg, arg_ty);
+                    let lltmp = if common::type_is_fat_ptr(bcx.tcx(), arg_ty) {
+                        let lltemp = alloc_ty(bcx, arg_ty, "");
                         let b = &bcx.build();
-                        if common::type_is_fat_ptr(bcx.tcx(), arg_ty) {
-                            let meta = &self.fn_ty.args[idx];
-                            idx += 1;
-                            arg.store_fn_arg(b, &mut llarg_idx, expr::get_dataptr(bcx, dst));
-                            meta.store_fn_arg(b, &mut llarg_idx, expr::get_meta(bcx, dst));
-                        } else {
-                            arg.store_fn_arg(b, &mut llarg_idx, dst);
-                        }
-                        bcx
-                    }))
+                        // we pass fat pointers as two words, but we want to
+                        // represent them internally as a pointer to two words,
+                        // so make an alloca to store them in.
+                        let meta = &self.fn_ty.args[idx];
+                        idx += 1;
+                        arg.store_fn_arg(b, &mut llarg_idx, expr::get_dataptr(bcx, lltemp));
+                        meta.store_fn_arg(b, &mut llarg_idx, expr::get_meta(bcx, lltemp));
+                        lltemp
+                    } else  {
+                        // otherwise, arg is passed by value, so store it into a temporary.
+                        let llarg_ty = arg.cast.unwrap_or(arg.memory_ty(bcx.ccx()));
+                        let lltemp = alloca(bcx, llarg_ty, "");
+                        let b = &bcx.build();
+                        arg.store_fn_arg(b, &mut llarg_idx, lltemp);
+                        // And coerce the temporary into the type we expect.
+                        b.pointercast(lltemp, arg.memory_ty(bcx.ccx()).ptr_to())
+                    };
+
+                    // FIXME: hacky lol?
+                    datum::Datum::new(lltmp, arg_ty,
+                                      datum::Lvalue::new("datum::lvalue_scratch_datum"))
                 }
             } else {
                 // FIXME(pcwalton): Reduce the amount of code bloat this is responsible for.
index b98e04e51c007d41e2a4f37c8b52de176438e1f9..ffc14b4468b5b68506147780bd753bb372238b24 100644 (file)
@@ -327,10 +327,10 @@ fn arg_value_refs<'bcx, 'tcx>(bcx: &BlockAndBuilder<'bcx, 'tcx>,
             llarg_idx += 1;
             llarg
         } else {
-            let lltemp = bcx.with_block(|bcx| {
-                base::alloc_ty(bcx, arg_ty, &format!("arg{}", arg_index))
-            });
             if common::type_is_fat_ptr(tcx, arg_ty) {
+                let lltemp = bcx.with_block(|bcx| {
+                    base::alloc_ty(bcx, arg_ty, &format!("arg{}", arg_index))
+                });
                 // we pass fat pointers as two words, but we want to
                 // represent them internally as a pointer to two words,
                 // so make an alloca to store them in.
@@ -338,12 +338,17 @@ fn arg_value_refs<'bcx, 'tcx>(bcx: &BlockAndBuilder<'bcx, 'tcx>,
                 idx += 1;
                 arg.store_fn_arg(bcx, &mut llarg_idx, get_dataptr(bcx, lltemp));
                 meta.store_fn_arg(bcx, &mut llarg_idx, get_meta(bcx, lltemp));
+                lltemp
             } else  {
-                // otherwise, arg is passed by value, so make a
-                // temporary and store it there
+                // otherwise, arg is passed by value, so store it into a temporary.
+                let llarg_ty = arg.cast.unwrap_or(arg.memory_ty(bcx.ccx()));
+                let lltemp = bcx.with_block(|bcx| {
+                    base::alloca(bcx, llarg_ty, &format!("arg{}", arg_index))
+                });
                 arg.store_fn_arg(bcx, &mut llarg_idx, lltemp);
+                // And coerce the temporary into the type we expect.
+                bcx.pointercast(lltemp, arg.memory_ty(bcx.ccx()).ptr_to())
             }
-            lltemp
         };
         bcx.with_block(|bcx| arg_scope.map(|scope| {
             // Is this a regular argument?