@@ -40,10 +40,11 @@ use middle::cfg;
40
40
use middle:: infer;
41
41
use middle:: lang_items:: { LangItem , ExchangeMallocFnLangItem , StartFnLangItem } ;
42
42
use middle:: weak_lang_items;
43
+ use middle:: pat_util:: simple_identifier;
43
44
use middle:: subst:: Substs ;
44
45
use middle:: ty:: { self , Ty , HasTypeFlags } ;
45
46
use rustc:: ast_map;
46
- use session:: config:: { self , NoDebugInfo } ;
47
+ use session:: config:: { self , NoDebugInfo , FullDebugInfo } ;
47
48
use session:: Session ;
48
49
use trans:: _match;
49
50
use trans:: adt;
@@ -1035,6 +1036,13 @@ pub fn alloca_no_lifetime(cx: Block, ty: Type, name: &str) -> ValueRef {
1035
1036
Alloca ( cx, ty, name)
1036
1037
}
1037
1038
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
+
1038
1046
// Creates the alloca slot which holds the pointer to the slot for the final return value
1039
1047
pub fn make_return_slot_pointer < ' a , ' tcx > ( fcx : & FunctionContext < ' a , ' tcx > ,
1040
1048
output_type : Ty < ' tcx > ) -> ValueRef {
@@ -1297,78 +1305,70 @@ pub fn arg_kind<'a, 'tcx>(cx: &FunctionContext<'a, 'tcx>, t: Ty<'tcx>)
1297
1305
}
1298
1306
}
1299
1307
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 > {
1309
1316
let _icx = push_ctxt ( "create_datums_for_fn_args" ) ;
1310
1317
let fcx = bcx. fcx ;
1318
+ let arg_scope_id = cleanup:: CustomScope ( arg_scope) ;
1311
1319
1312
1320
// Return an array wrapping the ValueRefs that we get from `get_param` for
1313
1321
// 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 ;
1343
1331
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 ) ;
1350
1347
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
+ } ) )
1353
1355
} else {
1354
- let val = get_param ( bcx . fcx . llfn , idx) ;
1356
+ let llarg = get_param ( fcx. llfn , idx) ;
1355
1357
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) => {
1367
1367
unpack_datum ! ( bcx,
1368
1368
datum:: lvalue_scratch_datum( bcx,
1369
1369
arg_ty,
1370
1370
"tupled_args" ,
1371
- tuple_args_scope_id ,
1371
+ arg_scope_id ,
1372
1372
( ) ,
1373
1373
|( ) ,
1374
1374
mut bcx,
@@ -1392,46 +1392,27 @@ fn create_datums_for_fn_args_under_call_abi<'blk, 'tcx>(
1392
1392
} ;
1393
1393
}
1394
1394
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
+ }
1405
1401
}
1406
1402
} ;
1407
1403
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
+ } ;
1435
1416
debuginfo:: create_argument_metadata ( bcx, & args[ i] ) ;
1436
1417
}
1437
1418
@@ -1578,34 +1559,20 @@ pub fn trans_closure<'a, 'b, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
1578
1559
decl. inputs . iter ( )
1579
1560
. map ( |arg| node_id_type ( bcx, arg. id ) )
1580
1561
. 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
- } ;
1591
1562
for monomorphized_arg_type in & monomorphized_arg_types {
1592
1563
debug ! ( "trans_closure: monomorphized_arg_type: {:?}" ,
1593
1564
monomorphized_arg_type) ;
1594
1565
}
1595
1566
debug ! ( "trans_closure: function lltype: {}" ,
1596
1567
bcx. fcx. ccx. tn( ) . val_to_string( bcx. fcx. llfn) ) ;
1597
1568
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
1606
1572
} ;
1607
1573
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) ;
1609
1576
1610
1577
bcx = closure_env. load ( bcx, cleanup:: CustomScope ( arg_scope) ) ;
1611
1578
@@ -1806,18 +1773,30 @@ fn trans_enum_variant_or_tuple_like_struct<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx
1806
1773
1807
1774
let arg_tys = ccx. tcx ( ) . erase_late_bound_regions ( & ctor_ty. fn_args ( ) ) ;
1808
1775
1809
- let arg_datums = create_datums_for_fn_args ( bcx, & arg_tys[ ..] ) ;
1810
-
1811
1776
if !type_is_zero_size ( fcx. ccx , result_ty. unwrap ( ) ) {
1812
1777
let dest = fcx. get_ret_slot ( bcx, result_ty, "eret_slot" ) ;
1813
1778
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 ( ) {
1815
1781
let lldestptr = adt:: trans_field_ptr ( bcx,
1816
1782
& * repr,
1817
1783
dest,
1818
1784
disr,
1819
1785
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
+ }
1821
1800
}
1822
1801
adt:: trans_set_discr ( bcx, & * repr, dest, disr) ;
1823
1802
}
0 commit comments