Skip to content

Commit b4abed6

Browse files
committed
Auto merge of #26738 - dotdash:trans_args, r=luqmana
The current split between create_datums_for_fn_args, copy_args_to_allocas and store_arg involves a detour via rvalue datums which cause additional work in form of insertvalue/extractvalue pairs for fat pointer arguments, and an extra alloca and memcpy for tupled args in rust-call functions. By merging those three functions into just one that actually covers the whole process of creating the final argument datums, we can skip all that. Also, this allows to easily merge in the handling of rust-call functions, allowing to make create_datum_for_fn_args_under_call_abi obsolete. cc #26600 -- The insertvalue instructions kicked us off of fast-isel.
2 parents fb379ef + a04784f commit b4abed6

File tree

4 files changed

+113
-187
lines changed

4 files changed

+113
-187
lines changed

src/librustc_trans/trans/_match.rs

+2-50
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,7 @@ use trans::monomorphize;
215215
use trans::tvec;
216216
use trans::type_of;
217217
use middle::ty::{self, Ty};
218-
use session::config::{NoDebugInfo, FullDebugInfo};
218+
use session::config::NoDebugInfo;
219219
use util::common::indenter;
220220
use util::nodemap::FnvHashMap;
221221
use util::ppaux;
@@ -1600,54 +1600,6 @@ pub fn store_local<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
16001600
}
16011601
}
16021602

1603-
/// Generates code for argument patterns like `fn foo(<pat>: T)`.
1604-
/// Creates entries in the `lllocals` map for each of the bindings
1605-
/// in `pat`.
1606-
///
1607-
/// # Arguments
1608-
///
1609-
/// - `pat` is the argument pattern
1610-
/// - `llval` is a pointer to the argument value (in other words,
1611-
/// if the argument type is `T`, then `llval` is a `T*`). In some
1612-
/// cases, this code may zero out the memory `llval` points at.
1613-
pub fn store_arg<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
1614-
pat: &ast::Pat,
1615-
arg: Datum<'tcx, Rvalue>,
1616-
arg_scope: cleanup::ScopeId)
1617-
-> Block<'blk, 'tcx> {
1618-
let _icx = push_ctxt("match::store_arg");
1619-
1620-
match simple_identifier(&*pat) {
1621-
Some(ident) => {
1622-
// Generate nicer LLVM for the common case of fn a pattern
1623-
// like `x: T`
1624-
let arg_ty = node_id_type(bcx, pat.id);
1625-
if type_of::arg_is_indirect(bcx.ccx(), arg_ty)
1626-
&& bcx.sess().opts.debuginfo != FullDebugInfo {
1627-
// Don't copy an indirect argument to an alloca, the caller
1628-
// already put it in a temporary alloca and gave it up, unless
1629-
// we emit extra-debug-info, which requires local allocas :(.
1630-
let arg_val = arg.add_clean(bcx.fcx, arg_scope);
1631-
bcx.fcx.lllocals.borrow_mut()
1632-
.insert(pat.id, Datum::new(arg_val, arg_ty, Lvalue));
1633-
bcx
1634-
} else {
1635-
mk_binding_alloca(
1636-
bcx, pat.id, ident.name, arg_scope, arg,
1637-
|arg, bcx, llval, _| arg.store_to(bcx, llval))
1638-
}
1639-
}
1640-
1641-
None => {
1642-
// General path. Copy out the values that are used in the
1643-
// pattern.
1644-
let arg = unpack_datum!(
1645-
bcx, arg.to_lvalue_datum_in_scope(bcx, "__arg", arg_scope));
1646-
bind_irrefutable_pat(bcx, pat, arg.val, arg_scope)
1647-
}
1648-
}
1649-
}
1650-
16511603
fn mk_binding_alloca<'blk, 'tcx, A, F>(bcx: Block<'blk, 'tcx>,
16521604
p_id: ast::NodeId,
16531605
name: ast::Name,
@@ -1687,7 +1639,7 @@ fn mk_binding_alloca<'blk, 'tcx, A, F>(bcx: Block<'blk, 'tcx>,
16871639
/// - bcx: starting basic block context
16881640
/// - pat: the irrefutable pattern being matched.
16891641
/// - val: the value being matched -- must be an lvalue (by ref, with cleanup)
1690-
fn bind_irrefutable_pat<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
1642+
pub fn bind_irrefutable_pat<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
16911643
pat: &ast::Pat,
16921644
val: ValueRef,
16931645
cleanup_scope: cleanup::ScopeId)

src/librustc_trans/trans/base.rs

+99-120
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,11 @@ use middle::cfg;
4040
use middle::infer;
4141
use middle::lang_items::{LangItem, ExchangeMallocFnLangItem, StartFnLangItem};
4242
use middle::weak_lang_items;
43+
use middle::pat_util::simple_identifier;
4344
use middle::subst::Substs;
4445
use middle::ty::{self, Ty, HasTypeFlags};
4546
use rustc::ast_map;
46-
use session::config::{self, NoDebugInfo};
47+
use session::config::{self, NoDebugInfo, FullDebugInfo};
4748
use session::Session;
4849
use trans::_match;
4950
use trans::adt;
@@ -1035,6 +1036,13 @@ pub fn alloca_no_lifetime(cx: Block, ty: Type, name: &str) -> ValueRef {
10351036
Alloca(cx, ty, name)
10361037
}
10371038

1039+
pub fn set_value_name(val: ValueRef, name: &str) {
1040+
unsafe {
1041+
let name = CString::new(name).unwrap();
1042+
llvm::LLVMSetValueName(val, name.as_ptr());
1043+
}
1044+
}
1045+
10381046
// Creates the alloca slot which holds the pointer to the slot for the final return value
10391047
pub fn make_return_slot_pointer<'a, 'tcx>(fcx: &FunctionContext<'a, 'tcx>,
10401048
output_type: Ty<'tcx>) -> ValueRef {
@@ -1297,78 +1305,70 @@ pub fn arg_kind<'a, 'tcx>(cx: &FunctionContext<'a, 'tcx>, t: Ty<'tcx>)
12971305
}
12981306
}
12991307

1300-
// work around bizarre resolve errors
1301-
pub type RvalueDatum<'tcx> = datum::Datum<'tcx, datum::Rvalue>;
1302-
1303-
// create_datums_for_fn_args: creates rvalue datums for each of the
1304-
// incoming function arguments. These will later be stored into
1305-
// appropriate lvalue datums.
1306-
pub fn create_datums_for_fn_args<'a, 'tcx>(bcx: Block<'a, 'tcx>,
1307-
arg_tys: &[Ty<'tcx>])
1308-
-> Vec<RvalueDatum<'tcx>> {
1308+
// create_datums_for_fn_args: creates lvalue datums for each of the
1309+
// incoming function arguments.
1310+
pub fn create_datums_for_fn_args<'a, 'tcx>(mut bcx: Block<'a, 'tcx>,
1311+
args: &[ast::Arg],
1312+
arg_tys: &[Ty<'tcx>],
1313+
has_tupled_arg: bool,
1314+
arg_scope: cleanup::CustomScopeIndex)
1315+
-> Block<'a, 'tcx> {
13091316
let _icx = push_ctxt("create_datums_for_fn_args");
13101317
let fcx = bcx.fcx;
1318+
let arg_scope_id = cleanup::CustomScope(arg_scope);
13111319

13121320
// Return an array wrapping the ValueRefs that we get from `get_param` for
13131321
// each argument into datums.
1314-
let mut i = fcx.arg_offset() as c_uint;
1315-
arg_tys.iter().map(|&arg_ty| {
1316-
if common::type_is_fat_ptr(bcx.tcx(), arg_ty) {
1317-
let llty = type_of::type_of(bcx.ccx(), arg_ty);
1318-
let data = get_param(fcx.llfn, i);
1319-
let extra = get_param(fcx.llfn, i + 1);
1320-
let fat_ptr = expr::make_fat_ptr(bcx, llty, data, extra);
1321-
i += 2;
1322-
datum::Datum::new(fat_ptr, arg_ty, datum::Rvalue { mode: datum::ByValue })
1323-
} else {
1324-
let llarg = get_param(fcx.llfn, i);
1325-
i += 1;
1326-
datum::Datum::new(llarg, arg_ty, arg_kind(fcx, arg_ty))
1327-
}
1328-
}).collect()
1329-
}
1330-
1331-
/// Creates rvalue datums for each of the incoming function arguments and
1332-
/// tuples the arguments. These will later be stored into appropriate lvalue
1333-
/// datums.
1334-
///
1335-
/// FIXME(pcwalton): Reduce the amount of code bloat this is responsible for.
1336-
fn create_datums_for_fn_args_under_call_abi<'blk, 'tcx>(
1337-
mut bcx: Block<'blk, 'tcx>,
1338-
arg_scope: cleanup::CustomScopeIndex,
1339-
arg_tys: &[Ty<'tcx>])
1340-
-> Vec<RvalueDatum<'tcx>> {
1341-
let mut result = Vec::new();
1342-
let mut idx = bcx.fcx.arg_offset() as c_uint;
1322+
//
1323+
// For certain mode/type combinations, the raw llarg values are passed
1324+
// by value. However, within the fn body itself, we want to always
1325+
// have all locals and arguments be by-ref so that we can cancel the
1326+
// cleanup and for better interaction with LLVM's debug info. So, if
1327+
// the argument would be passed by value, we store it into an alloca.
1328+
// This alloca should be optimized away by LLVM's mem-to-reg pass in
1329+
// the event it's not truly needed.
1330+
let mut idx = fcx.arg_offset() as c_uint;
13431331
for (i, &arg_ty) in arg_tys.iter().enumerate() {
1344-
if i < arg_tys.len() - 1 {
1345-
// Regular argument.
1346-
result.push(if common::type_is_fat_ptr(bcx.tcx(), arg_ty) {
1347-
let llty = type_of::type_of(bcx.ccx(), arg_ty);
1348-
let data = get_param(bcx.fcx.llfn, idx);
1349-
let extra = get_param(bcx.fcx.llfn, idx + 1);
1332+
let arg_datum = if !has_tupled_arg || i < arg_tys.len() - 1 {
1333+
if type_of::arg_is_indirect(bcx.ccx(), arg_ty)
1334+
&& bcx.sess().opts.debuginfo != FullDebugInfo {
1335+
// Don't copy an indirect argument to an alloca, the caller
1336+
// already put it in a temporary alloca and gave it up, unless
1337+
// we emit extra-debug-info, which requires local allocas :(.
1338+
let llarg = get_param(fcx.llfn, idx);
1339+
idx += 1;
1340+
bcx.fcx.schedule_lifetime_end(arg_scope_id, llarg);
1341+
bcx.fcx.schedule_drop_mem(arg_scope_id, llarg, arg_ty);
1342+
1343+
datum::Datum::new(llarg, arg_ty, datum::Lvalue)
1344+
} else if common::type_is_fat_ptr(bcx.tcx(), arg_ty) {
1345+
let data = get_param(fcx.llfn, idx);
1346+
let extra = get_param(fcx.llfn, idx + 1);
13501347
idx += 2;
1351-
let fat_ptr = expr::make_fat_ptr(bcx, llty, data, extra);
1352-
datum::Datum::new(fat_ptr, arg_ty, datum::Rvalue { mode: datum::ByValue })
1348+
unpack_datum!(bcx, datum::lvalue_scratch_datum(bcx, arg_ty, "",
1349+
arg_scope_id, (data, extra),
1350+
|(data, extra), bcx, dst| {
1351+
Store(bcx, data, expr::get_dataptr(bcx, dst));
1352+
Store(bcx, extra, expr::get_len(bcx, dst));
1353+
bcx
1354+
}))
13531355
} else {
1354-
let val = get_param(bcx.fcx.llfn, idx);
1356+
let llarg = get_param(fcx.llfn, idx);
13551357
idx += 1;
1356-
datum::Datum::new(val, arg_ty, arg_kind(bcx.fcx, arg_ty))
1357-
});
1358-
1359-
continue
1360-
}
1361-
1362-
// This is the last argument. Tuple it.
1363-
match arg_ty.sty {
1364-
ty::TyTuple(ref tupled_arg_tys) => {
1365-
let tuple_args_scope_id = cleanup::CustomScope(arg_scope);
1366-
let tuple =
1358+
let tmp = datum::Datum::new(llarg, arg_ty, arg_kind(fcx, arg_ty));
1359+
unpack_datum!(bcx, datum::lvalue_scratch_datum(bcx, arg_ty, "",
1360+
arg_scope_id, tmp,
1361+
|tmp, bcx, dst| tmp.store_to(bcx, dst)))
1362+
}
1363+
} else {
1364+
// FIXME(pcwalton): Reduce the amount of code bloat this is responsible for.
1365+
match arg_ty.sty {
1366+
ty::TyTuple(ref tupled_arg_tys) => {
13671367
unpack_datum!(bcx,
13681368
datum::lvalue_scratch_datum(bcx,
13691369
arg_ty,
13701370
"tupled_args",
1371-
tuple_args_scope_id,
1371+
arg_scope_id,
13721372
(),
13731373
|(),
13741374
mut bcx,
@@ -1392,46 +1392,27 @@ fn create_datums_for_fn_args_under_call_abi<'blk, 'tcx>(
13921392
};
13931393
}
13941394
bcx
1395-
}));
1396-
let tuple = unpack_datum!(bcx,
1397-
tuple.to_expr_datum()
1398-
.to_rvalue_datum(bcx,
1399-
"argtuple"));
1400-
result.push(tuple);
1401-
}
1402-
_ => {
1403-
bcx.tcx().sess.bug("last argument of a function with \
1404-
`rust-call` ABI isn't a tuple?!")
1395+
}))
1396+
}
1397+
_ => {
1398+
bcx.tcx().sess.bug("last argument of a function with \
1399+
`rust-call` ABI isn't a tuple?!")
1400+
}
14051401
}
14061402
};
14071403

1408-
}
1409-
1410-
result
1411-
}
1412-
1413-
fn copy_args_to_allocas<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
1414-
arg_scope: cleanup::CustomScopeIndex,
1415-
args: &[ast::Arg],
1416-
arg_datums: Vec<RvalueDatum<'tcx>>)
1417-
-> Block<'blk, 'tcx> {
1418-
debug!("copy_args_to_allocas");
1419-
1420-
let _icx = push_ctxt("copy_args_to_allocas");
1421-
let mut bcx = bcx;
1422-
1423-
let arg_scope_id = cleanup::CustomScope(arg_scope);
1424-
1425-
for (i, arg_datum) in arg_datums.into_iter().enumerate() {
1426-
// For certain mode/type combinations, the raw llarg values are passed
1427-
// by value. However, within the fn body itself, we want to always
1428-
// have all locals and arguments be by-ref so that we can cancel the
1429-
// cleanup and for better interaction with LLVM's debug info. So, if
1430-
// the argument would be passed by value, we store it into an alloca.
1431-
// This alloca should be optimized away by LLVM's mem-to-reg pass in
1432-
// the event it's not truly needed.
1433-
1434-
bcx = _match::store_arg(bcx, &*args[i].pat, arg_datum, arg_scope_id);
1404+
let pat = &*args[i].pat;
1405+
bcx = if let Some(ident) = simple_identifier(&*pat) {
1406+
// Generate nicer LLVM for the common case of fn a pattern
1407+
// like `x: T`
1408+
set_value_name(arg_datum.val, &bcx.name(ident.name));
1409+
bcx.fcx.lllocals.borrow_mut().insert(pat.id, arg_datum);
1410+
bcx
1411+
} else {
1412+
// General path. Copy out the values that are used in the
1413+
// pattern.
1414+
_match::bind_irrefutable_pat(bcx, pat, arg_datum.val, arg_scope_id)
1415+
};
14351416
debuginfo::create_argument_metadata(bcx, &args[i]);
14361417
}
14371418

@@ -1578,34 +1559,20 @@ pub fn trans_closure<'a, 'b, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
15781559
decl.inputs.iter()
15791560
.map(|arg| node_id_type(bcx, arg.id))
15801561
.collect::<Vec<_>>();
1581-
let monomorphized_arg_types = match closure_env {
1582-
closure::ClosureEnv::NotClosure => {
1583-
monomorphized_arg_types
1584-
}
1585-
1586-
// Tuple up closure argument types for the "rust-call" ABI.
1587-
closure::ClosureEnv::Closure(_) => {
1588-
vec![ccx.tcx().mk_tup(monomorphized_arg_types)]
1589-
}
1590-
};
15911562
for monomorphized_arg_type in &monomorphized_arg_types {
15921563
debug!("trans_closure: monomorphized_arg_type: {:?}",
15931564
monomorphized_arg_type);
15941565
}
15951566
debug!("trans_closure: function lltype: {}",
15961567
bcx.fcx.ccx.tn().val_to_string(bcx.fcx.llfn));
15971568

1598-
let arg_datums = match closure_env {
1599-
closure::ClosureEnv::NotClosure if abi == RustCall => {
1600-
create_datums_for_fn_args_under_call_abi(bcx, arg_scope, &monomorphized_arg_types[..])
1601-
}
1602-
_ => {
1603-
let arg_tys = untuple_arguments_if_necessary(ccx, &monomorphized_arg_types, abi);
1604-
create_datums_for_fn_args(bcx, &arg_tys)
1605-
}
1569+
let has_tupled_arg = match closure_env {
1570+
closure::ClosureEnv::NotClosure => abi == RustCall,
1571+
_ => false
16061572
};
16071573

1608-
bcx = copy_args_to_allocas(bcx, arg_scope, &decl.inputs, arg_datums);
1574+
bcx = create_datums_for_fn_args(bcx, &decl.inputs, &monomorphized_arg_types,
1575+
has_tupled_arg, arg_scope);
16091576

16101577
bcx = closure_env.load(bcx, cleanup::CustomScope(arg_scope));
16111578

@@ -1806,18 +1773,30 @@ fn trans_enum_variant_or_tuple_like_struct<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx
18061773

18071774
let arg_tys = ccx.tcx().erase_late_bound_regions(&ctor_ty.fn_args());
18081775

1809-
let arg_datums = create_datums_for_fn_args(bcx, &arg_tys[..]);
1810-
18111776
if !type_is_zero_size(fcx.ccx, result_ty.unwrap()) {
18121777
let dest = fcx.get_ret_slot(bcx, result_ty, "eret_slot");
18131778
let repr = adt::represent_type(ccx, result_ty.unwrap());
1814-
for (i, arg_datum) in arg_datums.into_iter().enumerate() {
1779+
let mut llarg_idx = fcx.arg_offset() as c_uint;
1780+
for (i, arg_ty) in arg_tys.into_iter().enumerate() {
18151781
let lldestptr = adt::trans_field_ptr(bcx,
18161782
&*repr,
18171783
dest,
18181784
disr,
18191785
i);
1820-
arg_datum.store_to(bcx, lldestptr);
1786+
if common::type_is_fat_ptr(bcx.tcx(), arg_ty) {
1787+
Store(bcx, get_param(fcx.llfn, llarg_idx), expr::get_dataptr(bcx, lldestptr));
1788+
Store(bcx, get_param(fcx.llfn, llarg_idx + 1), expr::get_len(bcx, lldestptr));
1789+
llarg_idx += 2;
1790+
} else {
1791+
let arg = get_param(fcx.llfn, llarg_idx);
1792+
llarg_idx += 1;
1793+
1794+
if arg_is_indirect(ccx, arg_ty) {
1795+
memcpy_ty(bcx, lldestptr, arg, arg_ty);
1796+
} else {
1797+
store_ty(bcx, arg, lldestptr, arg_ty);
1798+
}
1799+
}
18211800
}
18221801
adt::trans_set_discr(bcx, &*repr, dest, disr);
18231802
}

src/librustc_trans/trans/expr.rs

-3
Original file line numberDiff line numberDiff line change
@@ -291,9 +291,6 @@ pub fn get_dataptr(bcx: Block, fat_ptr: ValueRef) -> ValueRef {
291291
GEPi(bcx, fat_ptr, &[0, abi::FAT_PTR_ADDR])
292292
}
293293

294-
pub fn make_fat_ptr(bcx: Block, ty: Type, data: ValueRef, extra: ValueRef) -> ValueRef {
295-
InsertValue(bcx, InsertValue(bcx, C_undef(ty), data, 0), extra, 1)
296-
}
297294
pub fn copy_fat_ptr(bcx: Block, src_ptr: ValueRef, dst_ptr: ValueRef) {
298295
Store(bcx, Load(bcx, get_dataptr(bcx, src_ptr)), get_dataptr(bcx, dst_ptr));
299296
Store(bcx, Load(bcx, get_len(bcx, src_ptr)), get_len(bcx, dst_ptr));

0 commit comments

Comments
 (0)