Skip to content

Commit 306a99e

Browse files
committedJun 20, 2015
Auto merge of #26411 - dotdash:fat_in_registers, r=aatch
This has a number of advantages compared to creating a copy in memory and passing a pointer. The obvious one is that we don't have to put the data into memory but can keep it in registers. Since we're currently passing a pointer anyway (instead of using e.g. a known offset on the stack, which is what the `byval` attribute would achieve), we only use a single additional register for each fat pointer, but save at least two pointers worth of stack in exchange (sometimes more because more than one copy gets eliminated). On archs that pass arguments on the stack, we save a pointer worth of stack even without considering the omitted copies. Additionally, LLVM can optimize the code a lot better, to a large degree due to the fact that lots of copies are gone or can be optimized away. Additionally, we can now emit attributes like nonnull on the data and/or vtable pointers contained in the fat pointer, potentially allowing for even more optimizations. This results in LLVM passes being about 3-7% faster (depending on the crate), and the resulting code is also a few percent smaller, for example: |text|data|filename| |----|----|--------| |5671479|3941461|before/librustc-d8ace771.so| |5447663|3905745|after/librustc-d8ace771.so| | | | | |1944425|2394024|before/libstd-d8ace771.so| |1896769|2387610|after/libstd-d8ace771.so| I had to remove a call in the backtrace-debuginfo test, because LLVM can now merge the tails of some blocks when optimizations are turned on, which can't correctly preserve line info. Fixes #22924 Cc #22891 (at least for fat pointers the code is good now)
·
1.88.01.2.0
2 parents 40d19bf + f777562 commit 306a99e

File tree

17 files changed

+322
-256
lines changed

17 files changed

+322
-256
lines changed
 

‎src/librustc_llvm/lib.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2252,6 +2252,18 @@ pub fn get_param(llfn: ValueRef, index: c_uint) -> ValueRef {
22522252
}
22532253
}
22542254

2255+
pub fn get_params(llfn: ValueRef) -> Vec<ValueRef> {
2256+
unsafe {
2257+
let num_params = LLVMCountParams(llfn);
2258+
let mut params = Vec::with_capacity(num_params as usize);
2259+
for idx in 0..num_params {
2260+
params.push(LLVMGetParam(llfn, idx));
2261+
}
2262+
2263+
params
2264+
}
2265+
}
2266+
22552267
#[allow(missing_copy_implementations)]
22562268
pub enum RustString_opaque {}
22572269
pub type RustStringRef = *mut RustString_opaque;

‎src/librustc_trans/trans/_match.rs

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -828,19 +828,11 @@ fn compare_values<'blk, 'tcx>(cx: Block<'blk, 'tcx>,
828828
None,
829829
&format!("comparison of `{}`", rhs_t),
830830
StrEqFnLangItem);
831-
let t = ty::mk_str_slice(cx.tcx(), cx.tcx().mk_region(ty::ReStatic), ast::MutImmutable);
832-
// The comparison function gets the slices by value, so we have to make copies here. Even
833-
// if the function doesn't write through the pointer, things like lifetime intrinsics
834-
// require that we do this properly
835-
let lhs_arg = alloc_ty(cx, t, "lhs");
836-
let rhs_arg = alloc_ty(cx, t, "rhs");
837-
memcpy_ty(cx, lhs_arg, lhs, t);
838-
memcpy_ty(cx, rhs_arg, rhs, t);
839-
let res = callee::trans_lang_call(cx, did, &[lhs_arg, rhs_arg], None, debug_loc);
840-
call_lifetime_end(res.bcx, lhs_arg);
841-
call_lifetime_end(res.bcx, rhs_arg);
842-
843-
res
831+
let lhs_data = Load(cx, expr::get_dataptr(cx, lhs));
832+
let lhs_len = Load(cx, expr::get_len(cx, lhs));
833+
let rhs_data = Load(cx, expr::get_dataptr(cx, rhs));
834+
let rhs_len = Load(cx, expr::get_len(cx, rhs));
835+
callee::trans_lang_call(cx, did, &[lhs_data, lhs_len, rhs_data, rhs_len], None, debug_loc)
844836
}
845837

846838
let _icx = push_ctxt("compare_values");

‎src/librustc_trans/trans/asm.rs

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -45,32 +45,31 @@ pub fn trans_inline_asm<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, ia: &ast::InlineAsm)
4545
output_types.push(type_of::type_of(bcx.ccx(), out_datum.ty));
4646
let val = out_datum.val;
4747
if is_rw {
48-
ext_inputs.push(unpack_result!(bcx, {
49-
callee::trans_arg_datum(bcx,
50-
expr_ty(bcx, &**out),
51-
out_datum,
52-
cleanup::CustomScope(temp_scope),
53-
callee::DontAutorefArg)
54-
}));
48+
bcx = callee::trans_arg_datum(bcx,
49+
expr_ty(bcx, &**out),
50+
out_datum,
51+
cleanup::CustomScope(temp_scope),
52+
callee::DontAutorefArg,
53+
&mut ext_inputs);
5554
ext_constraints.push(i.to_string());
5655
}
5756
val
5857

5958
}).collect::<Vec<_>>();
6059

6160
// Now the input operands
62-
let mut inputs = ia.inputs.iter().map(|&(ref c, ref input)| {
61+
let mut inputs = Vec::new();
62+
for &(ref c, ref input) in &ia.inputs {
6363
constraints.push((*c).clone());
6464

6565
let in_datum = unpack_datum!(bcx, expr::trans(bcx, &**input));
66-
unpack_result!(bcx, {
67-
callee::trans_arg_datum(bcx,
66+
bcx = callee::trans_arg_datum(bcx,
6867
expr_ty(bcx, &**input),
6968
in_datum,
7069
cleanup::CustomScope(temp_scope),
71-
callee::DontAutorefArg)
72-
})
73-
}).collect::<Vec<_>>();
70+
callee::DontAutorefArg,
71+
&mut inputs);
72+
}
7473
inputs.push_all(&ext_inputs[..]);
7574

7675
// no failure occurred preparing operands, no need to cleanup

‎src/librustc_trans/trans/attributes.rs

Lines changed: 47 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ pub fn from_fn_type<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fn_type: ty::Ty<'tcx
188188
};
189189

190190
// Index 0 is the return value of the llvm func, so we start at 1
191-
let mut first_arg_offset = 1;
191+
let mut idx = 1;
192192
if let ty::FnConverging(ret_ty) = ret_ty {
193193
// A function pointer is called without the declaration
194194
// available, so we have to apply any attributes with ABI
@@ -206,7 +206,7 @@ pub fn from_fn_type<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fn_type: ty::Ty<'tcx
206206
.arg(1, llvm::DereferenceableAttribute(llret_sz));
207207

208208
// Add one more since there's an outptr
209-
first_arg_offset += 1;
209+
idx += 1;
210210
} else {
211211
// The `noalias` attribute on the return value is useful to a
212212
// function ptr caller.
@@ -236,10 +236,9 @@ pub fn from_fn_type<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fn_type: ty::Ty<'tcx
236236
}
237237
}
238238

239-
for (idx, &t) in input_tys.iter().enumerate().map(|(i, v)| (i + first_arg_offset, v)) {
239+
for &t in input_tys.iter() {
240240
match t.sty {
241-
// this needs to be first to prevent fat pointers from falling through
242-
_ if !common::type_is_immediate(ccx, t) => {
241+
_ if type_of::arg_is_indirect(ccx, t) => {
243242
let llarg_sz = machine::llsize_of_real(ccx, type_of::type_of(ccx, t));
244243

245244
// For non-immediate arguments the callee gets its own copy of
@@ -256,49 +255,63 @@ pub fn from_fn_type<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fn_type: ty::Ty<'tcx
256255

257256
// `Box` pointer parameters never alias because ownership is transferred
258257
ty::TyBox(inner) => {
259-
let llsz = machine::llsize_of_real(ccx, type_of::type_of(ccx, inner));
260-
261-
attrs.arg(idx, llvm::Attribute::NoAlias)
262-
.arg(idx, llvm::DereferenceableAttribute(llsz));
258+
attrs.arg(idx, llvm::Attribute::NoAlias);
259+
260+
if common::type_is_sized(ccx.tcx(), inner) {
261+
let llsz = machine::llsize_of_real(ccx, type_of::type_of(ccx, inner));
262+
attrs.arg(idx, llvm::DereferenceableAttribute(llsz));
263+
} else {
264+
attrs.arg(idx, llvm::NonNullAttribute);
265+
if ty::type_is_trait(inner) {
266+
attrs.arg(idx + 1, llvm::NonNullAttribute);
267+
}
268+
}
263269
}
264270

265-
// `&mut` pointer parameters never alias other parameters, or mutable global data
266-
//
267-
// `&T` where `T` contains no `UnsafeCell<U>` is immutable, and can be marked as both
268-
// `readonly` and `noalias`, as LLVM's definition of `noalias` is based solely on
269-
// memory dependencies rather than pointer equality
270-
ty::TyRef(b, mt) if mt.mutbl == ast::MutMutable ||
271-
!ty::type_contents(ccx.tcx(), mt.ty).interior_unsafe() => {
271+
ty::TyRef(b, mt) => {
272+
// `&mut` pointer parameters never alias other parameters, or mutable global data
273+
//
274+
// `&T` where `T` contains no `UnsafeCell<U>` is immutable, and can be marked as
275+
// both `readonly` and `noalias`, as LLVM's definition of `noalias` is based solely
276+
// on memory dependencies rather than pointer equality
277+
let interior_unsafe = ty::type_contents(ccx.tcx(), mt.ty).interior_unsafe();
272278

273-
let llsz = machine::llsize_of_real(ccx, type_of::type_of(ccx, mt.ty));
274-
attrs.arg(idx, llvm::Attribute::NoAlias)
275-
.arg(idx, llvm::DereferenceableAttribute(llsz));
279+
if mt.mutbl == ast::MutMutable || !interior_unsafe {
280+
attrs.arg(idx, llvm::Attribute::NoAlias);
281+
}
276282

277-
if mt.mutbl == ast::MutImmutable {
283+
if mt.mutbl == ast::MutImmutable && !interior_unsafe {
278284
attrs.arg(idx, llvm::Attribute::ReadOnly);
279285
}
280286

287+
// & pointer parameters are also never null and for sized types we also know
288+
// exactly how many bytes we can dereference
289+
if common::type_is_sized(ccx.tcx(), mt.ty) {
290+
let llsz = machine::llsize_of_real(ccx, type_of::type_of(ccx, mt.ty));
291+
attrs.arg(idx, llvm::DereferenceableAttribute(llsz));
292+
} else {
293+
attrs.arg(idx, llvm::NonNullAttribute);
294+
if ty::type_is_trait(mt.ty) {
295+
attrs.arg(idx + 1, llvm::NonNullAttribute);
296+
}
297+
}
298+
299+
// When a reference in an argument has no named lifetime, it's
300+
// impossible for that reference to escape this function
301+
// (returned or stored beyond the call by a closure).
281302
if let ReLateBound(_, BrAnon(_)) = *b {
282303
attrs.arg(idx, llvm::Attribute::NoCapture);
283304
}
284305
}
285306

286-
// When a reference in an argument has no named lifetime, it's impossible for that
287-
// reference to escape this function (returned or stored beyond the call by a closure).
288-
ty::TyRef(&ReLateBound(_, BrAnon(_)), mt) => {
289-
let llsz = machine::llsize_of_real(ccx, type_of::type_of(ccx, mt.ty));
290-
attrs.arg(idx, llvm::Attribute::NoCapture)
291-
.arg(idx, llvm::DereferenceableAttribute(llsz));
292-
}
293-
294-
// & pointer parameters are also never null and we know exactly how
295-
// many bytes we can dereference
296-
ty::TyRef(_, mt) => {
297-
let llsz = machine::llsize_of_real(ccx, type_of::type_of(ccx, mt.ty));
298-
attrs.arg(idx, llvm::DereferenceableAttribute(llsz));
299-
}
300307
_ => ()
301308
}
309+
310+
if common::type_is_fat_ptr(ccx.tcx(), t) {
311+
idx += 2;
312+
} else {
313+
idx += 1;
314+
}
302315
}
303316

304317
attrs

‎src/librustc_trans/trans/base.rs

Lines changed: 46 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1297,16 +1297,28 @@ pub type RvalueDatum<'tcx> = datum::Datum<'tcx, datum::Rvalue>;
12971297
// create_datums_for_fn_args: creates rvalue datums for each of the
12981298
// incoming function arguments. These will later be stored into
12991299
// appropriate lvalue datums.
1300-
pub fn create_datums_for_fn_args<'a, 'tcx>(fcx: &FunctionContext<'a, 'tcx>,
1300+
pub fn create_datums_for_fn_args<'a, 'tcx>(bcx: Block<'a, 'tcx>,
13011301
arg_tys: &[Ty<'tcx>])
13021302
-> Vec<RvalueDatum<'tcx>> {
13031303
let _icx = push_ctxt("create_datums_for_fn_args");
1304+
let fcx = bcx.fcx;
13041305

13051306
// Return an array wrapping the ValueRefs that we get from `get_param` for
13061307
// each argument into datums.
1307-
arg_tys.iter().enumerate().map(|(i, &arg_ty)| {
1308-
let llarg = get_param(fcx.llfn, fcx.arg_pos(i) as c_uint);
1309-
datum::Datum::new(llarg, arg_ty, arg_kind(fcx, arg_ty))
1308+
let mut i = fcx.arg_offset() as c_uint;
1309+
arg_tys.iter().map(|&arg_ty| {
1310+
if common::type_is_fat_ptr(bcx.tcx(), arg_ty) {
1311+
let llty = type_of::type_of(bcx.ccx(), arg_ty);
1312+
let data = get_param(fcx.llfn, i);
1313+
let extra = get_param(fcx.llfn, i + 1);
1314+
let fat_ptr = expr::make_fat_ptr(bcx, llty, data, extra);
1315+
i += 2;
1316+
datum::Datum::new(fat_ptr, arg_ty, datum::Rvalue { mode: datum::ByValue })
1317+
} else {
1318+
let llarg = get_param(fcx.llfn, i);
1319+
i += 1;
1320+
datum::Datum::new(llarg, arg_ty, arg_kind(fcx, arg_ty))
1321+
}
13101322
}).collect()
13111323
}
13121324

@@ -1321,12 +1333,23 @@ fn create_datums_for_fn_args_under_call_abi<'blk, 'tcx>(
13211333
arg_tys: &[Ty<'tcx>])
13221334
-> Vec<RvalueDatum<'tcx>> {
13231335
let mut result = Vec::new();
1336+
let mut idx = bcx.fcx.arg_offset() as c_uint;
13241337
for (i, &arg_ty) in arg_tys.iter().enumerate() {
13251338
if i < arg_tys.len() - 1 {
13261339
// Regular argument.
1327-
let llarg = get_param(bcx.fcx.llfn, bcx.fcx.arg_pos(i) as c_uint);
1328-
result.push(datum::Datum::new(llarg, arg_ty, arg_kind(bcx.fcx,
1329-
arg_ty)));
1340+
result.push(if common::type_is_fat_ptr(bcx.tcx(), arg_ty) {
1341+
let llty = type_of::type_of(bcx.ccx(), arg_ty);
1342+
let data = get_param(bcx.fcx.llfn, idx);
1343+
let extra = get_param(bcx.fcx.llfn, idx + 1);
1344+
idx += 2;
1345+
let fat_ptr = expr::make_fat_ptr(bcx, llty, data, extra);
1346+
datum::Datum::new(fat_ptr, arg_ty, datum::Rvalue { mode: datum::ByValue })
1347+
} else {
1348+
let val = get_param(bcx.fcx.llfn, idx);
1349+
idx += 1;
1350+
datum::Datum::new(val, arg_ty, arg_kind(bcx.fcx, arg_ty))
1351+
});
1352+
13301353
continue
13311354
}
13321355

@@ -1346,15 +1369,21 @@ fn create_datums_for_fn_args_under_call_abi<'blk, 'tcx>(
13461369
llval| {
13471370
for (j, &tupled_arg_ty) in
13481371
tupled_arg_tys.iter().enumerate() {
1349-
let llarg =
1350-
get_param(bcx.fcx.llfn,
1351-
bcx.fcx.arg_pos(i + j) as c_uint);
13521372
let lldest = GEPi(bcx, llval, &[0, j]);
1353-
let datum = datum::Datum::new(
1354-
llarg,
1355-
tupled_arg_ty,
1356-
arg_kind(bcx.fcx, tupled_arg_ty));
1357-
bcx = datum.store_to(bcx, lldest);
1373+
if common::type_is_fat_ptr(bcx.tcx(), tupled_arg_ty) {
1374+
let data = get_param(bcx.fcx.llfn, idx);
1375+
let extra = get_param(bcx.fcx.llfn, idx + 1);
1376+
Store(bcx, data, expr::get_dataptr(bcx, lldest));
1377+
Store(bcx, extra, expr::get_len(bcx, lldest));
1378+
idx += 2;
1379+
} else {
1380+
let datum = datum::Datum::new(
1381+
get_param(bcx.fcx.llfn, idx),
1382+
tupled_arg_ty,
1383+
arg_kind(bcx.fcx, tupled_arg_ty));
1384+
idx += 1;
1385+
bcx = datum.store_to(bcx, lldest);
1386+
};
13581387
}
13591388
bcx
13601389
}));
@@ -1566,7 +1595,7 @@ pub fn trans_closure<'a, 'b, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
15661595
}
15671596
_ => {
15681597
let arg_tys = untuple_arguments_if_necessary(ccx, &monomorphized_arg_types, abi);
1569-
create_datums_for_fn_args(&fcx, &arg_tys)
1598+
create_datums_for_fn_args(bcx, &arg_tys)
15701599
}
15711600
};
15721601

@@ -1773,7 +1802,7 @@ fn trans_enum_variant_or_tuple_like_struct<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx
17731802
ty::erase_late_bound_regions(
17741803
ccx.tcx(), &ty::ty_fn_args(ctor_ty));
17751804

1776-
let arg_datums = create_datums_for_fn_args(&fcx, &arg_tys[..]);
1805+
let arg_datums = create_datums_for_fn_args(bcx, &arg_tys[..]);
17771806

17781807
if !type_is_zero_size(fcx.ccx, result_ty.unwrap()) {
17791808
let dest = fcx.get_ret_slot(bcx, result_ty, "eret_slot");

‎src/librustc_trans/trans/callee.rs

Lines changed: 62 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,7 @@ pub use self::CallArgs::*;
2121
use arena::TypedArena;
2222
use back::link;
2323
use session;
24-
use llvm::ValueRef;
25-
use llvm::get_param;
26-
use llvm;
24+
use llvm::{self, ValueRef, get_params};
2725
use metadata::csearch;
2826
use middle::def;
2927
use middle::subst;
@@ -343,19 +341,16 @@ pub fn trans_fn_pointer_shim<'a, 'tcx>(
343341
&block_arena);
344342
let mut bcx = init_function(&fcx, false, sig.output);
345343

344+
let llargs = get_params(fcx.llfn);
345+
346+
let self_idx = fcx.arg_offset();
346347
// the first argument (`self`) will be ptr to the the fn pointer
347348
let llfnpointer = if is_by_ref {
348-
Load(bcx, get_param(fcx.llfn, fcx.arg_pos(0) as u32))
349+
Load(bcx, llargs[self_idx])
349350
} else {
350-
get_param(fcx.llfn, fcx.arg_pos(0) as u32)
351+
llargs[self_idx]
351352
};
352353

353-
// the remaining arguments will be the untupled values
354-
let llargs: Vec<_> =
355-
sig.inputs.iter()
356-
.enumerate()
357-
.map(|(i, _)| get_param(fcx.llfn, fcx.arg_pos(i+1) as u32))
358-
.collect();
359354
assert!(!fcx.needs_ret_allocas);
360355

361356
let dest = fcx.llretslotptr.get().map(|_|
@@ -366,7 +361,7 @@ pub fn trans_fn_pointer_shim<'a, 'tcx>(
366361
DebugLoc::None,
367362
bare_fn_ty,
368363
|bcx, _| Callee { bcx: bcx, data: Fn(llfnpointer) },
369-
ArgVals(&llargs[..]),
364+
ArgVals(&llargs[(self_idx + 1)..]),
370365
dest).bcx;
371366

372367
finish_fn(&fcx, bcx, sig.output, DebugLoc::None);
@@ -927,13 +922,12 @@ fn trans_args_under_call_abi<'blk, 'tcx>(
927922
// Translate the `self` argument first.
928923
if !ignore_self {
929924
let arg_datum = unpack_datum!(bcx, expr::trans(bcx, &*arg_exprs[0]));
930-
llargs.push(unpack_result!(bcx, {
931-
trans_arg_datum(bcx,
932-
args[0],
933-
arg_datum,
934-
arg_cleanup_scope,
935-
DontAutorefArg)
936-
}))
925+
bcx = trans_arg_datum(bcx,
926+
args[0],
927+
arg_datum,
928+
arg_cleanup_scope,
929+
DontAutorefArg,
930+
llargs);
937931
}
938932

939933
// Now untuple the rest of the arguments.
@@ -951,21 +945,20 @@ fn trans_args_under_call_abi<'blk, 'tcx>(
951945
tuple_expr.id));
952946
let repr = adt::represent_type(bcx.ccx(), tuple_type);
953947
let repr_ptr = &*repr;
954-
llargs.extend(field_types.iter().enumerate().map(|(i, field_type)| {
948+
for (i, field_type) in field_types.iter().enumerate() {
955949
let arg_datum = tuple_lvalue_datum.get_element(
956950
bcx,
957951
field_type,
958952
|srcval| {
959953
adt::trans_field_ptr(bcx, repr_ptr, srcval, 0, i)
960954
}).to_expr_datum();
961-
unpack_result!(bcx, trans_arg_datum(
962-
bcx,
963-
field_type,
964-
arg_datum,
965-
arg_cleanup_scope,
966-
DontAutorefArg)
967-
)
968-
}));
955+
bcx = trans_arg_datum(bcx,
956+
field_type,
957+
arg_datum,
958+
arg_cleanup_scope,
959+
DontAutorefArg,
960+
llargs);
961+
}
969962
}
970963
_ => {
971964
bcx.sess().span_bug(tuple_expr.span,
@@ -988,13 +981,12 @@ fn trans_overloaded_call_args<'blk, 'tcx>(
988981
let arg_tys = ty::erase_late_bound_regions(bcx.tcx(), &ty::ty_fn_args(fn_ty));
989982
if !ignore_self {
990983
let arg_datum = unpack_datum!(bcx, expr::trans(bcx, arg_exprs[0]));
991-
llargs.push(unpack_result!(bcx, {
992-
trans_arg_datum(bcx,
993-
arg_tys[0],
994-
arg_datum,
995-
arg_cleanup_scope,
996-
DontAutorefArg)
997-
}))
984+
bcx = trans_arg_datum(bcx,
985+
arg_tys[0],
986+
arg_datum,
987+
arg_cleanup_scope,
988+
DontAutorefArg,
989+
llargs);
998990
}
999991

1000992
// Now untuple the rest of the arguments.
@@ -1004,13 +996,12 @@ fn trans_overloaded_call_args<'blk, 'tcx>(
1004996
for (i, &field_type) in field_types.iter().enumerate() {
1005997
let arg_datum =
1006998
unpack_datum!(bcx, expr::trans(bcx, arg_exprs[i + 1]));
1007-
llargs.push(unpack_result!(bcx, {
1008-
trans_arg_datum(bcx,
1009-
field_type,
1010-
arg_datum,
1011-
arg_cleanup_scope,
1012-
DontAutorefArg)
1013-
}))
999+
bcx = trans_arg_datum(bcx,
1000+
field_type,
1001+
arg_datum,
1002+
arg_cleanup_scope,
1003+
DontAutorefArg,
1004+
llargs);
10141005
}
10151006
}
10161007
_ => {
@@ -1067,11 +1058,10 @@ pub fn trans_args<'a, 'blk, 'tcx>(cx: Block<'blk, 'tcx>,
10671058
};
10681059

10691060
let arg_datum = unpack_datum!(bcx, expr::trans(bcx, &**arg_expr));
1070-
llargs.push(unpack_result!(bcx, {
1071-
trans_arg_datum(bcx, arg_ty, arg_datum,
1072-
arg_cleanup_scope,
1073-
DontAutorefArg)
1074-
}));
1061+
bcx = trans_arg_datum(bcx, arg_ty, arg_datum,
1062+
arg_cleanup_scope,
1063+
DontAutorefArg,
1064+
llargs);
10751065
}
10761066
}
10771067
ArgOverloadedCall(arg_exprs) => {
@@ -1085,19 +1075,17 @@ pub fn trans_args<'a, 'blk, 'tcx>(cx: Block<'blk, 'tcx>,
10851075
ArgOverloadedOp(lhs, rhs, autoref) => {
10861076
assert!(!variadic);
10871077

1088-
llargs.push(unpack_result!(bcx, {
1089-
trans_arg_datum(bcx, arg_tys[0], lhs,
1090-
arg_cleanup_scope,
1091-
DontAutorefArg)
1092-
}));
1078+
bcx = trans_arg_datum(bcx, arg_tys[0], lhs,
1079+
arg_cleanup_scope,
1080+
DontAutorefArg,
1081+
llargs);
10931082

10941083
assert_eq!(arg_tys.len(), 1 + rhs.len());
10951084
for (rhs, rhs_id) in rhs {
1096-
llargs.push(unpack_result!(bcx, {
1097-
trans_arg_datum(bcx, arg_tys[1], rhs,
1098-
arg_cleanup_scope,
1099-
if autoref { DoAutorefArg(rhs_id) } else { DontAutorefArg })
1100-
}));
1085+
bcx = trans_arg_datum(bcx, arg_tys[1], rhs,
1086+
arg_cleanup_scope,
1087+
if autoref { DoAutorefArg(rhs_id) } else { DontAutorefArg },
1088+
llargs);
11011089
}
11021090
}
11031091
ArgVals(vs) => {
@@ -1118,8 +1106,9 @@ pub fn trans_arg_datum<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
11181106
formal_arg_ty: Ty<'tcx>,
11191107
arg_datum: Datum<'tcx, Expr>,
11201108
arg_cleanup_scope: cleanup::ScopeId,
1121-
autoref_arg: AutorefArg)
1122-
-> Result<'blk, 'tcx> {
1109+
autoref_arg: AutorefArg,
1110+
llargs: &mut Vec<ValueRef>)
1111+
-> Block<'blk, 'tcx> {
11231112
let _icx = push_ctxt("trans_arg_datum");
11241113
let mut bcx = bcx;
11251114
let ccx = bcx.ccx();
@@ -1141,6 +1130,10 @@ pub fn trans_arg_datum<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
11411130
bcx, arg_datum.to_lvalue_datum(bcx, "arg", arg_id));
11421131
val = arg_datum.val;
11431132
}
1133+
DontAutorefArg if common::type_is_fat_ptr(bcx.tcx(), arg_datum_ty) &&
1134+
!bcx.fcx.type_needs_drop(arg_datum_ty) => {
1135+
val = arg_datum.val
1136+
}
11441137
DontAutorefArg => {
11451138
// Make this an rvalue, since we are going to be
11461139
// passing ownership.
@@ -1159,7 +1152,7 @@ pub fn trans_arg_datum<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
11591152
}
11601153
}
11611154

1162-
if formal_arg_ty != arg_datum_ty {
1155+
if type_of::arg_is_indirect(ccx, formal_arg_ty) && formal_arg_ty != arg_datum_ty {
11631156
// this could happen due to e.g. subtyping
11641157
let llformal_arg_ty = type_of::type_of_explicit_arg(ccx, formal_arg_ty);
11651158
debug!("casting actual type ({}) to match formal ({})",
@@ -1170,5 +1163,13 @@ pub fn trans_arg_datum<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
11701163
}
11711164

11721165
debug!("--- trans_arg_datum passing {}", bcx.val_to_string(val));
1173-
Result::new(bcx, val)
1166+
1167+
if common::type_is_fat_ptr(bcx.tcx(), formal_arg_ty) {
1168+
llargs.push(Load(bcx, expr::get_dataptr(bcx, val)));
1169+
llargs.push(Load(bcx, expr::get_len(bcx, val)));
1170+
} else {
1171+
llargs.push(val);
1172+
}
1173+
1174+
bcx
11741175
}

‎src/librustc_trans/trans/closure.rs

Lines changed: 6 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
use arena::TypedArena;
1212
use back::link::{self, mangle_internal_name_by_path_and_seq};
13-
use llvm::{ValueRef, get_param};
13+
use llvm::{ValueRef, get_params};
1414
use middle::mem_categorization::Typer;
1515
use trans::adt;
1616
use trans::attributes;
@@ -405,11 +405,14 @@ fn trans_fn_once_adapter_shim<'a, 'tcx>(
405405
&block_arena);
406406
let mut bcx = init_function(&fcx, false, sig.output);
407407

408+
let llargs = get_params(fcx.llfn);
409+
408410
// the first argument (`self`) will be the (by value) closure env.
409411
let self_scope = fcx.push_custom_cleanup_scope();
410412
let self_scope_id = CustomScope(self_scope);
411413
let rvalue_mode = datum::appropriate_rvalue_mode(ccx, closure_ty);
412-
let llself = get_param(lloncefn, fcx.arg_pos(0) as u32);
414+
let self_idx = fcx.arg_offset();
415+
let llself = llargs[self_idx];
413416
let env_datum = Datum::new(llself, closure_ty, Rvalue::new(rvalue_mode));
414417
let env_datum = unpack_datum!(bcx,
415418
env_datum.to_lvalue_datum_in_scope(bcx, "self",
@@ -418,19 +421,6 @@ fn trans_fn_once_adapter_shim<'a, 'tcx>(
418421
debug!("trans_fn_once_adapter_shim: env_datum={}",
419422
bcx.val_to_string(env_datum.val));
420423

421-
// the remaining arguments will be packed up in a tuple.
422-
let input_tys = match sig.inputs[1].sty {
423-
ty::TyTuple(ref tys) => &**tys,
424-
_ => bcx.sess().bug(&format!("trans_fn_once_adapter_shim: not rust-call! \
425-
closure_def_id={:?}",
426-
closure_def_id))
427-
};
428-
let llargs: Vec<_> =
429-
input_tys.iter()
430-
.enumerate()
431-
.map(|(i, _)| get_param(lloncefn, fcx.arg_pos(i+1) as u32))
432-
.collect();
433-
434424
let dest =
435425
fcx.llretslotptr.get().map(
436426
|_| expr::SaveIn(fcx.get_ret_slot(bcx, sig.output, "ret_slot")));
@@ -442,7 +432,7 @@ fn trans_fn_once_adapter_shim<'a, 'tcx>(
442432
DebugLoc::None,
443433
llref_fn_ty,
444434
|bcx, _| Callee { bcx: bcx, data: callee_data },
445-
ArgVals(&llargs),
435+
ArgVals(&llargs[(self_idx + 1)..]),
446436
dest).bcx;
447437

448438
fcx.pop_custom_cleanup_scope(self_scope);

‎src/librustc_trans/trans/common.rs

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -421,13 +421,8 @@ pub struct FunctionContext<'a, 'tcx: 'a> {
421421
}
422422

423423
impl<'a, 'tcx> FunctionContext<'a, 'tcx> {
424-
pub fn arg_pos(&self, arg: usize) -> usize {
425-
let arg = self.env_arg_pos() + arg;
426-
if self.llenv.is_some() {
427-
arg + 1
428-
} else {
429-
arg
430-
}
424+
pub fn arg_offset(&self) -> usize {
425+
self.env_arg_pos() + if self.llenv.is_some() { 1 } else { 0 }
431426
}
432427

433428
pub fn env_arg_pos(&self) -> usize {

‎src/librustc_trans/trans/expr.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,9 @@ pub fn get_dataptr(bcx: Block, fat_ptr: ValueRef) -> ValueRef {
293293
GEPi(bcx, fat_ptr, &[0, abi::FAT_PTR_ADDR])
294294
}
295295

296+
pub fn make_fat_ptr(bcx: Block, ty: Type, data: ValueRef, extra: ValueRef) -> ValueRef {
297+
InsertValue(bcx, InsertValue(bcx, C_undef(ty), data, 0), extra, 1)
298+
}
296299
pub fn copy_fat_ptr(bcx: Block, src_ptr: ValueRef, dst_ptr: ValueRef) {
297300
Store(bcx, Load(bcx, get_dataptr(bcx, src_ptr)), get_dataptr(bcx, dst_ptr));
298301
Store(bcx, Load(bcx, get_len(bcx, src_ptr)), get_len(bcx, dst_ptr));

‎src/librustc_trans/trans/foreign.rs

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
// except according to those terms.
1010

1111

12-
use back::link;
12+
use back::{abi, link};
1313
use llvm::{ValueRef, CallConv, get_param};
1414
use llvm;
1515
use middle::weak_lang_items;
@@ -22,6 +22,7 @@ use trans::cabi;
2222
use trans::common::*;
2323
use trans::debuginfo::DebugLoc;
2424
use trans::declare;
25+
use trans::expr;
2526
use trans::machine;
2627
use trans::monomorphize;
2728
use trans::type_::Type;
@@ -272,10 +273,11 @@ pub fn trans_native_call<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
272273
}
273274
}
274275

275-
for (i, &llarg_rust) in llargs_rust.iter().enumerate() {
276-
let mut llarg_rust = llarg_rust;
276+
let mut offset = 0;
277+
for (i, arg_ty) in arg_tys.iter().enumerate() {
278+
let mut llarg_rust = llargs_rust[i + offset];
277279

278-
if arg_tys[i].is_ignore() {
280+
if arg_ty.is_ignore() {
279281
continue;
280282
}
281283

@@ -286,7 +288,7 @@ pub fn trans_native_call<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
286288
i,
287289
ccx.tn().val_to_string(llarg_rust),
288290
rust_indirect,
289-
ccx.tn().type_to_string(arg_tys[i].ty));
291+
ccx.tn().type_to_string(arg_ty.ty));
290292

291293
// Ensure that we always have the Rust value indirectly,
292294
// because it makes bitcasting easier.
@@ -295,15 +297,21 @@ pub fn trans_native_call<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
295297
base::alloca(bcx,
296298
type_of::type_of(ccx, passed_arg_tys[i]),
297299
"__arg");
298-
base::store_ty(bcx, llarg_rust, scratch, passed_arg_tys[i]);
300+
if type_is_fat_ptr(ccx.tcx(), passed_arg_tys[i]) {
301+
Store(bcx, llargs_rust[i + offset], expr::get_dataptr(bcx, scratch));
302+
Store(bcx, llargs_rust[i + offset + 1], expr::get_len(bcx, scratch));
303+
offset += 1;
304+
} else {
305+
base::store_ty(bcx, llarg_rust, scratch, passed_arg_tys[i]);
306+
}
299307
llarg_rust = scratch;
300308
}
301309

302310
debug!("llarg_rust={} (after indirection)",
303311
ccx.tn().val_to_string(llarg_rust));
304312

305313
// Check whether we need to do any casting
306-
match arg_tys[i].cast {
314+
match arg_ty.cast {
307315
Some(ty) => llarg_rust = BitCast(bcx, llarg_rust, ty.ptr_to()),
308316
None => ()
309317
}
@@ -312,7 +320,7 @@ pub fn trans_native_call<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
312320
ccx.tn().val_to_string(llarg_rust));
313321

314322
// Finally, load the value if needed for the foreign ABI
315-
let foreign_indirect = arg_tys[i].is_indirect();
323+
let foreign_indirect = arg_ty.is_indirect();
316324
let llarg_foreign = if foreign_indirect {
317325
llarg_rust
318326
} else {
@@ -328,7 +336,7 @@ pub fn trans_native_call<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
328336
i, ccx.tn().val_to_string(llarg_foreign));
329337

330338
// fill padding with undef value
331-
match arg_tys[i].pad {
339+
match arg_ty.pad {
332340
Some(ty) => llargs_foreign.push(C_undef(ty)),
333341
None => ()
334342
}
@@ -783,12 +791,12 @@ pub fn trans_rust_fn_with_foreign_abi<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
783791
// If the types in the ABI and the Rust types don't match,
784792
// bitcast the llforeign_arg pointer so it matches the types
785793
// Rust expects.
786-
if llforeign_arg_ty.cast.is_some() {
794+
if llforeign_arg_ty.cast.is_some() && !type_is_fat_ptr(ccx.tcx(), rust_ty){
787795
assert!(!foreign_indirect);
788796
llforeign_arg = builder.bitcast(llforeign_arg, llrust_ty.ptr_to());
789797
}
790798

791-
let llrust_arg = if rust_indirect {
799+
let llrust_arg = if rust_indirect || type_is_fat_ptr(ccx.tcx(), rust_ty) {
792800
llforeign_arg
793801
} else {
794802
if ty::type_is_bool(rust_ty) {
@@ -810,7 +818,15 @@ pub fn trans_rust_fn_with_foreign_abi<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
810818

811819
debug!("llrust_arg {}{}: {}", "#",
812820
i, ccx.tn().val_to_string(llrust_arg));
813-
llrust_args.push(llrust_arg);
821+
if type_is_fat_ptr(ccx.tcx(), rust_ty) {
822+
let next_llrust_ty = rust_param_tys.next().expect("Not enough parameter types!");
823+
llrust_args.push(builder.load(builder.bitcast(builder.gepi(
824+
llrust_arg, &[0, abi::FAT_PTR_ADDR]), llrust_ty.ptr_to())));
825+
llrust_args.push(builder.load(builder.bitcast(builder.gepi(
826+
llrust_arg, &[0, abi::FAT_PTR_EXTRA]), next_llrust_ty.ptr_to())));
827+
} else {
828+
llrust_args.push(llrust_arg);
829+
}
814830
}
815831

816832
// Perform the call itself

‎src/librustc_trans/trans/glue.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -259,7 +259,7 @@ fn get_drop_glue_core<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
259259
// llfn is expected be declared to take a parameter of the appropriate
260260
// type, so we don't need to explicitly cast the function parameter.
261261

262-
let llrawptr0 = get_param(llfn, fcx.arg_pos(0) as c_uint);
262+
let llrawptr0 = get_param(llfn, fcx.arg_offset() as c_uint);
263263
let bcx = make_drop_glue(bcx, llrawptr0, g);
264264
finish_fn(&fcx, bcx, ty::FnConverging(ty::mk_nil(ccx.tcx())), DebugLoc::None);
265265

‎src/librustc_trans/trans/intrinsic.rs

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -275,17 +275,13 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
275275
} else {
276276
(&exprs[0], &exprs[1])
277277
};
278-
let arg_tys = ty::erase_late_bound_regions(bcx.tcx(), &ty::ty_fn_args(callee_ty));
279278

280279
// evaluate destination address
281-
let lldest_addr = unpack_result!(bcx, {
282-
let dest_datum = unpack_datum!(bcx, expr::trans(bcx, dest_expr));
283-
callee::trans_arg_datum(bcx,
284-
arg_tys[0],
285-
dest_datum,
286-
cleanup::CustomScope(cleanup_scope),
287-
callee::DontAutorefArg)
288-
});
280+
let dest_datum = unpack_datum!(bcx, expr::trans(bcx, dest_expr));
281+
let dest_datum = unpack_datum!(
282+
bcx, dest_datum.to_rvalue_datum(bcx, "arg"));
283+
let dest_datum = unpack_datum!(
284+
bcx, dest_datum.to_appropriate_datum(bcx));
289285

290286
// `expr::trans_into(bcx, expr, dest)` is equiv to
291287
//
@@ -294,7 +290,7 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
294290
// which for `dest == expr::SaveIn(addr)`, is equivalent to:
295291
//
296292
// `trans(bcx, expr).store_to(bcx, addr)`.
297-
let lldest = expr::Dest::SaveIn(lldest_addr);
293+
let lldest = expr::Dest::SaveIn(dest_datum.val);
298294
bcx = expr::trans_into(bcx, source_expr, lldest);
299295

300296
let llresult = C_nil(ccx);
@@ -370,8 +366,7 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
370366
(_, "size_of_val") => {
371367
let tp_ty = *substs.types.get(FnSpace, 0);
372368
if !type_is_sized(tcx, tp_ty) {
373-
let info = Load(bcx, expr::get_len(bcx, llargs[0]));
374-
let (llsize, _) = glue::size_and_align_of_dst(bcx, tp_ty, info);
369+
let (llsize, _) = glue::size_and_align_of_dst(bcx, tp_ty, llargs[1]);
375370
llsize
376371
} else {
377372
let lltp_ty = type_of::type_of(ccx, tp_ty);
@@ -385,8 +380,7 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
385380
(_, "min_align_of_val") => {
386381
let tp_ty = *substs.types.get(FnSpace, 0);
387382
if !type_is_sized(tcx, tp_ty) {
388-
let info = Load(bcx, expr::get_len(bcx, llargs[0]));
389-
let (_, llalign) = glue::size_and_align_of_dst(bcx, tp_ty, info);
383+
let (_, llalign) = glue::size_and_align_of_dst(bcx, tp_ty, llargs[1]);
390384
llalign
391385
} else {
392386
C_uint(ccx, type_of::align_of(ccx, tp_ty))
@@ -399,7 +393,16 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
399393
}
400394
(_, "drop_in_place") => {
401395
let tp_ty = *substs.types.get(FnSpace, 0);
402-
glue::drop_ty(bcx, llargs[0], tp_ty, call_debug_location);
396+
let ptr = if type_is_sized(tcx, tp_ty) {
397+
llargs[0]
398+
} else {
399+
let scratch = rvalue_scratch_datum(bcx, tp_ty, "tmp");
400+
Store(bcx, llargs[0], expr::get_dataptr(bcx, scratch.val));
401+
Store(bcx, llargs[1], expr::get_len(bcx, scratch.val));
402+
fcx.schedule_lifetime_end(cleanup::CustomScope(cleanup_scope), scratch.val);
403+
scratch.val
404+
};
405+
glue::drop_ty(bcx, ptr, tp_ty, call_debug_location);
403406
C_nil(ccx)
404407
}
405408
(_, "type_name") => {
@@ -980,7 +983,7 @@ fn with_overflow_intrinsic<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
980983
let ret = C_undef(type_of::type_of(bcx.ccx(), t));
981984
let ret = InsertValue(bcx, ret, result, 0);
982985
let ret = InsertValue(bcx, ret, overflow, 1);
983-
if type_is_immediate(bcx.ccx(), t) {
986+
if !arg_is_indirect(bcx.ccx(), t) {
984987
let tmp = alloc_ty(bcx, t, "tmp");
985988
Store(bcx, ret, tmp);
986989
load_ty(bcx, tmp, t)

‎src/librustc_trans/trans/meth.rs

Lines changed: 21 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
use arena::TypedArena;
1212
use back::abi;
1313
use back::link;
14-
use llvm::{ValueRef, get_param};
14+
use llvm::{ValueRef, get_params};
1515
use metadata::csearch;
1616
use middle::subst::{Subst, Substs};
1717
use middle::subst::VecPerParamSpace;
@@ -468,27 +468,28 @@ fn trans_trait_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
468468
self_datum.val
469469
};
470470

471-
trans_trait_callee_from_llval(bcx, method_ty, vtable_index, llval)
471+
let llself = Load(bcx, GEPi(bcx, llval, &[0, abi::FAT_PTR_ADDR]));
472+
let llvtable = Load(bcx, GEPi(bcx, llval, &[0, abi::FAT_PTR_EXTRA]));
473+
trans_trait_callee_from_llval(bcx, method_ty, vtable_index, llself, llvtable)
472474
}
473475

474476
/// Same as `trans_trait_callee()` above, except that it is given a by-ref pointer to the object
475477
/// pair.
476478
pub fn trans_trait_callee_from_llval<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
477479
callee_ty: Ty<'tcx>,
478480
vtable_index: usize,
479-
llpair: ValueRef)
481+
llself: ValueRef,
482+
llvtable: ValueRef)
480483
-> Callee<'blk, 'tcx> {
481484
let _icx = push_ctxt("meth::trans_trait_callee");
482485
let ccx = bcx.ccx();
483486

484487
// Load the data pointer from the object.
485-
debug!("trans_trait_callee_from_llval(callee_ty={}, vtable_index={}, llpair={})",
488+
debug!("trans_trait_callee_from_llval(callee_ty={}, vtable_index={}, llself={}, llvtable={})",
486489
callee_ty,
487490
vtable_index,
488-
bcx.val_to_string(llpair));
489-
let llboxptr = GEPi(bcx, llpair, &[0, abi::FAT_PTR_ADDR]);
490-
let llbox = Load(bcx, llboxptr);
491-
let llself = PointerCast(bcx, llbox, Type::i8p(ccx));
491+
bcx.val_to_string(llself),
492+
bcx.val_to_string(llvtable));
492493

493494
// Replace the self type (&Self or Box<Self>) with an opaque pointer.
494495
let llcallee_ty = match callee_ty.sty {
@@ -505,19 +506,13 @@ pub fn trans_trait_callee_from_llval<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
505506
ccx.sess().bug("meth::trans_trait_callee given non-bare-rust-fn");
506507
}
507508
};
508-
let llvtable = Load(bcx,
509-
PointerCast(bcx,
510-
GEPi(bcx, llpair,
511-
&[0, abi::FAT_PTR_EXTRA]),
512-
Type::vtable(ccx).ptr_to().ptr_to()));
513-
let mptr = Load(bcx, GEPi(bcx, llvtable, &[0, vtable_index + VTABLE_OFFSET]));
514-
let mptr = PointerCast(bcx, mptr, llcallee_ty.ptr_to());
509+
let mptr = Load(bcx, GEPi(bcx, llvtable, &[vtable_index + VTABLE_OFFSET]));
515510

516511
return Callee {
517512
bcx: bcx,
518513
data: TraitItem(MethodData {
519-
llfn: mptr,
520-
llself: llself,
514+
llfn: PointerCast(bcx, mptr, llcallee_ty.ptr_to()),
515+
llself: PointerCast(bcx, llself, Type::i8p(ccx)),
521516
})
522517
};
523518
}
@@ -611,42 +606,14 @@ pub fn trans_object_shim<'a, 'tcx>(
611606
&block_arena);
612607
let mut bcx = init_function(&fcx, false, sig.output);
613608

614-
// the first argument (`self`) will be a trait object
615-
let llobject = get_param(fcx.llfn, fcx.arg_pos(0) as u32);
616-
617-
debug!("trans_object_shim: llobject={}",
618-
bcx.val_to_string(llobject));
619-
620-
// the remaining arguments will be, well, whatever they are
621-
let input_tys =
622-
match fty.abi {
623-
RustCall => {
624-
// unpack the tuple to extract the input type arguments:
625-
match sig.inputs[1].sty {
626-
ty::TyTuple(ref tys) => &**tys,
627-
_ => {
628-
bcx.sess().bug(
629-
&format!("rust-call expects a tuple not {:?}",
630-
sig.inputs[1]));
631-
}
632-
}
633-
}
634-
_ => {
635-
// skip the self parameter:
636-
&sig.inputs[1..]
637-
}
638-
};
609+
let llargs = get_params(fcx.llfn);
639610

640-
let llargs: Vec<_> =
641-
input_tys.iter()
642-
.enumerate()
643-
.map(|(i, _)| {
644-
let llarg = get_param(fcx.llfn, fcx.arg_pos(i+1) as u32);
645-
debug!("trans_object_shim: input #{} == {}",
646-
i, bcx.val_to_string(llarg));
647-
llarg
648-
})
649-
.collect();
611+
let self_idx = fcx.arg_offset();
612+
let llself = llargs[self_idx];
613+
let llvtable = llargs[self_idx + 1];
614+
615+
debug!("trans_object_shim: llself={}, llvtable={}",
616+
bcx.val_to_string(llself), bcx.val_to_string(llvtable));
650617

651618
assert!(!fcx.needs_ret_allocas);
652619

@@ -668,8 +635,8 @@ pub fn trans_object_shim<'a, 'tcx>(
668635
|bcx, _| trans_trait_callee_from_llval(bcx,
669636
method_bare_fn_ty,
670637
method_offset_in_vtable,
671-
llobject),
672-
ArgVals(&llargs),
638+
llself, llvtable),
639+
ArgVals(&llargs[(self_idx + 2)..]),
673640
dest).bcx;
674641

675642
finish_fn(&fcx, bcx, sig.output, DebugLoc::None);

‎src/librustc_trans/trans/type_.rs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -171,10 +171,6 @@ impl Type {
171171
Type::struct_(ccx, &[], false)
172172
}
173173

174-
pub fn vtable(ccx: &CrateContext) -> Type {
175-
Type::array(&Type::i8p(ccx).ptr_to(), 1)
176-
}
177-
178174
pub fn glue_fn(ccx: &CrateContext, t: Type) -> Type {
179175
Type::func(&[t], &Type::void(ccx))
180176
}

‎src/librustc_trans/trans/type_of.rs

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,12 @@ fn ensure_array_fits_in_address_space<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
3636

3737
pub fn arg_is_indirect<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
3838
arg_ty: Ty<'tcx>) -> bool {
39-
!type_is_immediate(ccx, arg_ty)
39+
!type_is_immediate(ccx, arg_ty) && !type_is_fat_ptr(ccx.tcx(), arg_ty)
4040
}
4141

4242
pub fn return_uses_outptr<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
4343
ty: Ty<'tcx>) -> bool {
44-
!type_is_immediate(ccx, ty)
44+
arg_is_indirect(ccx, ty)
4545
}
4646

4747
pub fn type_of_explicit_arg<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
@@ -136,8 +136,15 @@ pub fn type_of_rust_fn<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
136136
}
137137

138138
// ... then explicit args.
139-
let input_tys = inputs.iter().map(|&arg_ty| type_of_explicit_arg(cx, arg_ty));
140-
atys.extend(input_tys);
139+
for input in &inputs {
140+
let arg_ty = type_of_explicit_arg(cx, input);
141+
142+
if type_is_fat_ptr(cx.tcx(), input) {
143+
atys.extend(arg_ty.field_types());
144+
} else {
145+
atys.push(arg_ty);
146+
}
147+
}
141148

142149
Type::func(&atys[..], &lloutputtype)
143150
}

‎src/test/codegen/function-arguments.rs

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,53 @@ pub fn struct_return() -> S {
8787
}
8888
}
8989

90+
// Hack to get the correct size for the length part in slices
91+
// CHECK: @helper([[USIZE:i[0-9]+]])
92+
#[no_mangle]
93+
fn helper(_: usize) {
94+
}
95+
96+
// CHECK: @slice(i8* noalias nonnull readonly, [[USIZE]])
97+
// FIXME #25759 This should also have `nocapture`
98+
#[no_mangle]
99+
fn slice(_: &[u8]) {
100+
}
101+
102+
// CHECK: @mutable_slice(i8* noalias nonnull, [[USIZE]])
103+
// FIXME #25759 This should also have `nocapture`
104+
#[no_mangle]
105+
fn mutable_slice(_: &mut [u8]) {
106+
}
107+
108+
// CHECK: @unsafe_slice(%UnsafeInner* nonnull, [[USIZE]])
109+
// unsafe interior means this isn't actually readonly and there may be aliases ...
110+
#[no_mangle]
111+
pub fn unsafe_slice(_: &[UnsafeInner]) {
112+
}
113+
114+
// CHECK: @str(i8* noalias nonnull readonly, [[USIZE]])
115+
// FIXME #25759 This should also have `nocapture`
116+
#[no_mangle]
117+
fn str(_: &[u8]) {
118+
}
119+
120+
// CHECK: @trait_borrow(i8* nonnull, void (i8*)** nonnull)
121+
// FIXME #25759 This should also have `nocapture`
122+
#[no_mangle]
123+
fn trait_borrow(_: &Drop) {
124+
}
125+
126+
// CHECK: @trait_box(i8* noalias nonnull, void (i8*)** nonnull)
127+
#[no_mangle]
128+
fn trait_box(_: Box<Drop>) {
129+
}
130+
131+
// CHECK: { i16*, [[USIZE]] } @return_slice(i16* noalias nonnull readonly, [[USIZE]])
132+
#[no_mangle]
133+
fn return_slice(x: &[u16]) -> &[u16] {
134+
x
135+
}
136+
90137
// CHECK: noalias i8* @allocator()
91138
#[no_mangle]
92139
#[allocator]

‎src/test/run-pass/backtrace-debuginfo.rs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -97,10 +97,6 @@ fn inner_inlined(counter: &mut i32, main_pos: Pos, outer_pos: Pos) {
9797
let inner_pos = pos!(); aux::callback_inlined(|aux_pos| {
9898
check!(counter; main_pos, outer_pos, inner_pos, aux_pos);
9999
});
100-
101-
// this tests a distinction between two independent calls to the inlined function.
102-
// (un)fortunately, LLVM somehow merges two consecutive such calls into one node.
103-
inner_further_inlined(counter, main_pos, outer_pos, pos!());
104100
}
105101

106102
#[inline(never)]

0 commit comments

Comments
 (0)
Please sign in to comment.