1
Fork 0

Fix handling of C arguments

Fixes #33868
This commit is contained in:
Simonas Kazlauskas 2016-05-26 02:45:13 +03:00
parent da66f2fd8c
commit 97bf80f427
2 changed files with 34 additions and 20 deletions

View file

@ -1663,21 +1663,30 @@ impl<'blk, 'tcx> FunctionContext<'blk, 'tcx> {
arg_ty, arg_ty,
datum::Lvalue::new("FunctionContext::bind_args")) datum::Lvalue::new("FunctionContext::bind_args"))
} else { } else {
unpack_datum!(bcx, datum::lvalue_scratch_datum(bcx, arg_ty, "", let lltmp = if common::type_is_fat_ptr(bcx.tcx(), arg_ty) {
uninit_reason, let lltemp = alloc_ty(bcx, arg_ty, "");
arg_scope_id, |bcx, dst| {
debug!("FunctionContext::bind_args: {:?}: {:?}", hir_arg, arg_ty);
let b = &bcx.build(); let b = &bcx.build();
if common::type_is_fat_ptr(bcx.tcx(), arg_ty) { // we pass fat pointers as two words, but we want to
let meta = &self.fn_ty.args[idx]; // represent them internally as a pointer to two words,
idx += 1; // so make an alloca to store them in.
arg.store_fn_arg(b, &mut llarg_idx, expr::get_dataptr(bcx, dst)); let meta = &self.fn_ty.args[idx];
meta.store_fn_arg(b, &mut llarg_idx, expr::get_meta(bcx, dst)); idx += 1;
} else { arg.store_fn_arg(b, &mut llarg_idx, expr::get_dataptr(bcx, lltemp));
arg.store_fn_arg(b, &mut llarg_idx, dst); meta.store_fn_arg(b, &mut llarg_idx, expr::get_meta(bcx, lltemp));
} lltemp
bcx } 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 { } else {
// FIXME(pcwalton): Reduce the amount of code bloat this is responsible for. // FIXME(pcwalton): Reduce the amount of code bloat this is responsible for.

View file

@ -327,10 +327,10 @@ fn arg_value_refs<'bcx, 'tcx>(bcx: &BlockAndBuilder<'bcx, 'tcx>,
llarg_idx += 1; llarg_idx += 1;
llarg llarg
} else { } 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) { 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 // we pass fat pointers as two words, but we want to
// represent them internally as a pointer to two words, // represent them internally as a pointer to two words,
// so make an alloca to store them in. // so make an alloca to store them in.
@ -338,12 +338,17 @@ fn arg_value_refs<'bcx, 'tcx>(bcx: &BlockAndBuilder<'bcx, 'tcx>,
idx += 1; idx += 1;
arg.store_fn_arg(bcx, &mut llarg_idx, get_dataptr(bcx, lltemp)); arg.store_fn_arg(bcx, &mut llarg_idx, get_dataptr(bcx, lltemp));
meta.store_fn_arg(bcx, &mut llarg_idx, get_meta(bcx, lltemp)); meta.store_fn_arg(bcx, &mut llarg_idx, get_meta(bcx, lltemp));
lltemp
} else { } else {
// otherwise, arg is passed by value, so make a // otherwise, arg is passed by value, so store it into a temporary.
// temporary and store it there 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); 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| { bcx.with_block(|bcx| arg_scope.map(|scope| {
// Is this a regular argument? // Is this a regular argument?