140
140
* the various values we copied explicitly. Note that guards and moves are
141
141
* just plain incompatible.
142
142
*
143
+ * Some relevant helper functions that manage bindings:
144
+ * - `create_bindings_map()`
145
+ * - `store_non_ref_bindings()`
146
+ * - `insert_lllocals()`
147
+ *
143
148
*/
144
149
145
150
use core:: prelude:: * ;
@@ -314,7 +319,6 @@ pub fn variant_opt(bcx: block, pat_id: ast::node_id)
314
319
pub enum TransBindingMode {
315
320
TrByValue ( /*ismove:*/ bool , /*llbinding:*/ ValueRef ) ,
316
321
TrByRef ,
317
- TrByImplicitRef
318
322
}
319
323
320
324
/**
@@ -670,8 +674,8 @@ pub fn enter_tup<'r>(bcx: block,
670
674
let dummy = @ast:: pat { id : 0 , node : ast:: pat_wild, span : dummy_sp ( ) } ;
671
675
do enter_match ( bcx, dm, m, col, val) |p| {
672
676
match p. node {
673
- ast:: pat_tup( /*bad*/ copy elts) => {
674
- Some ( elts)
677
+ ast:: pat_tup( ref elts) => {
678
+ Some ( copy * elts)
675
679
}
676
680
_ => {
677
681
assert_is_binding_or_wild ( bcx, p) ;
@@ -698,7 +702,7 @@ pub fn enter_tuple_struct<'r>(bcx: block,
698
702
let dummy = @ast:: pat { id : 0 , node : ast:: pat_wild, span : dummy_sp ( ) } ;
699
703
do enter_match ( bcx, dm, m, col, val) |p| {
700
704
match p. node {
701
- ast:: pat_enum( _, Some ( /*bad*/ copy elts) ) => Some ( elts) ,
705
+ ast:: pat_enum( _, Some ( ref elts) ) => Some ( copy * elts) ,
702
706
_ => {
703
707
assert_is_binding_or_wild ( bcx, p) ;
704
708
Some ( vec:: from_elem ( n_elts, dummy) )
@@ -881,7 +885,7 @@ fn match_datum(bcx: block, val: ValueRef, pat_id: ast::node_id) -> Datum {
881
885
//! we should just pass around a Datum and be done with it.
882
886
883
887
let ty = node_id_type ( bcx, pat_id) ;
884
- Datum { val : val, ty : ty, mode : datum:: ByRef , source : RevokeClean }
888
+ Datum { val : val, ty : ty, mode : datum:: ByRef ( RevokeClean ) }
885
889
}
886
890
887
891
@@ -988,7 +992,7 @@ pub fn root_pats_as_necessary(mut bcx: block,
988
992
let pat_id = br. pats [ col] . id ;
989
993
if pat_id != 0 {
990
994
let datum = Datum { val : val, ty : node_id_type ( bcx, pat_id) ,
991
- mode : ByRef , source : ZeroMem } ;
995
+ mode : ByRef ( ZeroMem ) } ;
992
996
bcx = datum. root_and_write_guard ( bcx, br. pats [ col] . span , pat_id, 0 ) ;
993
997
}
994
998
}
@@ -1125,10 +1129,10 @@ pub fn compare_values(cx: block,
1125
1129
}
1126
1130
}
1127
1131
1128
- pub fn store_non_ref_bindings ( bcx : block ,
1129
- data : & ArmData ,
1130
- opt_temp_cleanups : Option < & mut ~[ ValueRef ] > )
1131
- -> block
1132
+ fn store_non_ref_bindings ( bcx : block ,
1133
+ bindings_map : & BindingsMap ,
1134
+ mut opt_temp_cleanups : Option < & mut ~[ ValueRef ] > )
1135
+ -> block
1132
1136
{
1133
1137
/*!
1134
1138
*
@@ -1140,13 +1144,12 @@ pub fn store_non_ref_bindings(bcx: block,
1140
1144
*/
1141
1145
1142
1146
let mut bcx = bcx;
1143
- let mut opt_temp_cleanups = opt_temp_cleanups;
1144
- for data. bindings_map. each_value |& binding_info| {
1147
+ for bindings_map. each_value |& binding_info| {
1145
1148
match binding_info. trmode {
1146
1149
TrByValue ( is_move, lldest) => {
1147
1150
let llval = Load ( bcx, binding_info. llmatch ) ; // get a T*
1148
1151
let datum = Datum { val : llval, ty : binding_info. ty ,
1149
- mode : ByRef , source : ZeroMem } ;
1152
+ mode : ByRef ( ZeroMem ) } ;
1150
1153
bcx = {
1151
1154
if is_move {
1152
1155
datum. move_to ( bcx, INIT , lldest)
@@ -1161,22 +1164,28 @@ pub fn store_non_ref_bindings(bcx: block,
1161
1164
temp_cleanups
1162
1165
}
1163
1166
}
1164
- TrByRef | TrByImplicitRef => { }
1167
+ TrByRef => { }
1165
1168
}
1166
1169
}
1167
1170
return bcx;
1168
1171
}
1169
1172
1170
- pub fn insert_lllocals ( bcx : block ,
1171
- data : & ArmData ,
1172
- add_cleans : bool ) -> block {
1173
+ fn insert_lllocals ( bcx : block ,
1174
+ bindings_map : & BindingsMap ,
1175
+ binding_mode : IrrefutablePatternBindingMode ,
1176
+ add_cleans : bool ) -> block {
1173
1177
/*!
1174
- *
1175
1178
* For each binding in `data.bindings_map`, adds an appropriate entry into
1176
1179
* the `fcx.lllocals` map. If add_cleans is true, then adds cleanups for
1177
- * the bindings. */
1180
+ * the bindings.
1181
+ */
1178
1182
1179
- for data. bindings_map. each_value |& binding_info| {
1183
+ let llmap = match binding_mode {
1184
+ BindLocal => bcx. fcx . lllocals ,
1185
+ BindArgument => bcx. fcx . llargs
1186
+ } ;
1187
+
1188
+ for bindings_map. each_value |& binding_info| {
1180
1189
let llval = match binding_info. trmode {
1181
1190
// By value bindings: use the stack slot that we
1182
1191
// copied/moved the value into
@@ -1192,17 +1201,12 @@ pub fn insert_lllocals(bcx: block,
1192
1201
TrByRef => {
1193
1202
binding_info. llmatch
1194
1203
}
1195
-
1196
- // Ugly: for implicit ref, we actually want a T*, but
1197
- // we have a T**, so we had to load. This will go away
1198
- // once implicit refs go away.
1199
- TrByImplicitRef => {
1200
- Load ( bcx, binding_info. llmatch )
1201
- }
1202
1204
} ;
1203
1205
1204
- bcx. fcx . lllocals . insert ( binding_info. id ,
1205
- local_mem ( llval) ) ;
1206
+ debug ! ( "binding %? to %s" ,
1207
+ binding_info. id,
1208
+ val_str( bcx. ccx( ) . tn, llval) ) ;
1209
+ llmap. insert ( binding_info. id , llval) ;
1206
1210
}
1207
1211
return bcx;
1208
1212
}
@@ -1223,8 +1227,8 @@ pub fn compile_guard(bcx: block,
1223
1227
1224
1228
let mut bcx = bcx;
1225
1229
let mut temp_cleanups = ~[ ] ;
1226
- bcx = store_non_ref_bindings ( bcx, data, Some ( & mut temp_cleanups) ) ;
1227
- bcx = insert_lllocals ( bcx, data, false ) ;
1230
+ bcx = store_non_ref_bindings ( bcx, & data. bindings_map , Some ( & mut temp_cleanups) ) ;
1231
+ bcx = insert_lllocals ( bcx, & data. bindings_map , BindLocal , false ) ;
1228
1232
1229
1233
let val = unpack_result ! ( bcx, {
1230
1234
do with_scope_result( bcx, guard_expr. info( ) ,
@@ -1254,7 +1258,7 @@ pub fn compile_guard(bcx: block,
1254
1258
TrByValue ( _, llval) => {
1255
1259
bcx = glue:: drop_ty ( bcx, llval, binding_info. ty ) ;
1256
1260
}
1257
- TrByRef | TrByImplicitRef => { }
1261
+ TrByRef => { }
1258
1262
}
1259
1263
bcx. fcx . lllocals . remove ( & binding_info. id ) ;
1260
1264
}
@@ -1621,6 +1625,42 @@ pub fn trans_match(bcx: block,
1621
1625
}
1622
1626
}
1623
1627
1628
+ fn create_bindings_map( bcx : block , pat : @ast:: pat ) -> BindingsMap {
1629
+ // Create the bindings map, which is a mapping from each binding name
1630
+ // to an alloca() that will be the value for that local variable.
1631
+ // Note that we use the names because each binding will have many ids
1632
+ // from the various alternatives.
1633
+ let ccx = bcx. ccx ( ) ;
1634
+ let tcx = bcx. tcx ( ) ;
1635
+ let mut bindings_map = HashMap :: new ( ) ;
1636
+ do pat_bindings ( tcx. def_map , pat) |bm, p_id, _s, path| {
1637
+ let ident = path_to_ident ( path) ;
1638
+ let variable_ty = node_id_type ( bcx, p_id) ;
1639
+ let llvariable_ty = type_of:: type_of ( ccx, variable_ty) ;
1640
+
1641
+ let llmatch, trmode;
1642
+ match bm {
1643
+ ast:: bind_by_copy | ast:: bind_infer => {
1644
+ // in this case, the final type of the variable will be T,
1645
+ // but during matching we need to store a *T as explained
1646
+ // above
1647
+ let is_move = ccx. maps . moves_map . contains ( & p_id) ;
1648
+ llmatch = alloca ( bcx, T_ptr ( llvariable_ty) ) ;
1649
+ trmode = TrByValue ( is_move, alloca ( bcx, llvariable_ty) ) ;
1650
+ }
1651
+ ast:: bind_by_ref( _) => {
1652
+ llmatch = alloca ( bcx, llvariable_ty) ;
1653
+ trmode = TrByRef ;
1654
+ }
1655
+ } ;
1656
+ bindings_map. insert ( ident, BindingInfo {
1657
+ llmatch : llmatch, trmode : trmode,
1658
+ id : p_id, ty : variable_ty
1659
+ } ) ;
1660
+ }
1661
+ return bindings_map;
1662
+ }
1663
+
1624
1664
pub fn trans_match_inner ( scope_cx : block ,
1625
1665
discr_expr : @ast:: expr ,
1626
1666
arms : & [ ast:: arm ] ,
@@ -1637,41 +1677,9 @@ pub fn trans_match_inner(scope_cx: block,
1637
1677
}
1638
1678
1639
1679
let mut arm_datas = ~[ ] , matches = ~[ ] ;
1640
- for arms . each |arm| {
1680
+ for vec :: each( arms ) |arm| {
1641
1681
let body = scope_block ( bcx, arm. body . info ( ) , "case_body" ) ;
1642
-
1643
- // Create the bindings map, which is a mapping from each binding name
1644
- // to an alloca() that will be the value for that local variable.
1645
- // Note that we use the names because each binding will have many ids
1646
- // from the various alternatives.
1647
- let mut bindings_map = HashMap :: new ( ) ;
1648
- do pat_bindings ( tcx. def_map , arm. pats [ 0 ] ) |bm, p_id, _s, path| {
1649
- let ident = path_to_ident ( path) ;
1650
- let variable_ty = node_id_type ( bcx, p_id) ;
1651
- let llvariable_ty = type_of:: type_of ( bcx. ccx ( ) , variable_ty) ;
1652
-
1653
- let llmatch, trmode;
1654
- match bm {
1655
- ast:: bind_by_copy | ast:: bind_infer => {
1656
- // in this case, the final type of the variable will be T,
1657
- // but during matching we need to store a *T as explained
1658
- // above
1659
- let is_move =
1660
- scope_cx. ccx ( ) . maps . moves_map . contains ( & p_id) ;
1661
- llmatch = alloca ( bcx, T_ptr ( llvariable_ty) ) ;
1662
- trmode = TrByValue ( is_move, alloca ( bcx, llvariable_ty) ) ;
1663
- }
1664
- ast:: bind_by_ref( _) => {
1665
- llmatch = alloca ( bcx, llvariable_ty) ;
1666
- trmode = TrByRef ;
1667
- }
1668
- } ;
1669
- bindings_map. insert ( ident, BindingInfo {
1670
- llmatch : llmatch, trmode : trmode,
1671
- id : p_id, ty : variable_ty
1672
- } ) ;
1673
- }
1674
-
1682
+ let bindings_map = create_bindings_map ( bcx, arm. pats [ 0 ] ) ;
1675
1683
let arm_data = @ArmData { bodycx : body,
1676
1684
arm : arm,
1677
1685
bindings_map : bindings_map} ;
@@ -1693,7 +1701,7 @@ pub fn trans_match_inner(scope_cx: block,
1693
1701
None
1694
1702
}
1695
1703
} ;
1696
- let lldiscr = discr_datum. to_ref_llval ( bcx) ;
1704
+ let lldiscr = discr_datum. to_zeroable_ref_llval ( bcx) ;
1697
1705
compile_submatch ( bcx, matches, [ lldiscr] , chk) ;
1698
1706
1699
1707
let mut arm_cxs = ~[ ] ;
@@ -1705,11 +1713,11 @@ pub fn trans_match_inner(scope_cx: block,
1705
1713
// is just to reduce code space. See extensive comment at the start
1706
1714
// of the file for more details.
1707
1715
if arm_data. arm . guard . is_none ( ) {
1708
- bcx = store_non_ref_bindings ( bcx, * arm_data, None ) ;
1716
+ bcx = store_non_ref_bindings ( bcx, & arm_data. bindings_map , None ) ;
1709
1717
}
1710
1718
1711
1719
// insert bindings into the lllocals map and add cleanups
1712
- bcx = insert_lllocals ( bcx, * arm_data, true ) ;
1720
+ bcx = insert_lllocals ( bcx, & arm_data. bindings_map , BindLocal , true ) ;
1713
1721
1714
1722
bcx = controlflow:: trans_block ( bcx, & arm_data. arm . body , dest) ;
1715
1723
bcx = trans_block_cleanups ( bcx, block_cleanups ( arm_data. bodycx ) ) ;
@@ -1757,27 +1765,25 @@ pub fn bind_irrefutable_pat(bcx: block,
1757
1765
if make_copy {
1758
1766
let binding_ty = node_id_type ( bcx, pat. id ) ;
1759
1767
let datum = Datum { val : val, ty : binding_ty,
1760
- mode : ByRef , source : RevokeClean } ;
1768
+ mode : ByRef ( RevokeClean ) } ;
1761
1769
let scratch = scratch_datum ( bcx, binding_ty, false ) ;
1762
1770
datum. copy_to_datum ( bcx, INIT , scratch) ;
1763
1771
match binding_mode {
1764
1772
BindLocal => {
1765
- bcx. fcx . lllocals . insert ( pat. id ,
1766
- local_mem ( scratch. val ) ) ;
1773
+ bcx. fcx . lllocals . insert ( pat. id , scratch. val ) ;
1767
1774
}
1768
1775
BindArgument => {
1769
- bcx. fcx . llargs . insert ( pat. id ,
1770
- local_mem ( scratch. val ) ) ;
1776
+ bcx. fcx . llargs . insert ( pat. id , scratch. val ) ;
1771
1777
}
1772
1778
}
1773
1779
add_clean ( bcx, scratch. val , binding_ty) ;
1774
1780
} else {
1775
1781
match binding_mode {
1776
1782
BindLocal => {
1777
- bcx. fcx . lllocals . insert ( pat. id , local_mem ( val) ) ;
1783
+ bcx. fcx . lllocals . insert ( pat. id , val) ;
1778
1784
}
1779
1785
BindArgument => {
1780
- bcx. fcx . llargs . insert ( pat. id , local_mem ( val) ) ;
1786
+ bcx. fcx . llargs . insert ( pat. id , val) ;
1781
1787
}
1782
1788
}
1783
1789
}
0 commit comments