64
64
* We store information about the bound variables for each arm as part of the
65
65
* per-arm `ArmData` struct. There is a mapping from identifiers to
66
66
* `BindingInfo` structs. These structs contain the mode/id/type of the
67
- * binding, but they also contain up to two LLVM values, called `llmatch` and
68
- * `llbinding` respectively (the `llbinding`, as will be described shortly, is
69
- * optional and only present for by-value bindings---therefore it is bundled
70
- * up as part of the `TransBindingMode` type). Both point at allocas.
67
+ * binding, but they also contain an LLVM value which points at an alloca
68
+ * called `llmatch`.
71
69
*
72
70
* The `llmatch` binding always stores a pointer into the value being matched
73
71
* which points at the data for the binding. If the value being matched has
83
81
* up against an identifier, we store the current pointer into the
84
82
* corresponding alloca.
85
83
*
86
- * In addition, for each by-value binding (copy or move), we will create a
87
- * second alloca (`llbinding`) that will hold the final value. In this
88
- * example, that means that `d` would have this second alloca of type `D` (and
89
- * hence `llbinding` has type `D*`).
90
- *
91
84
* Once a pattern is completely matched, and assuming that there is no guard
92
85
* pattern, we will branch to a block that leads to the body itself. For any
93
86
* by-value bindings, this block will first load the ptr from `llmatch` (the
94
- * one of type `D*`) and copy/move the value into `llbinding` (the one of type
95
- * `D`). The second alloca then becomes the value of the local variable. For
96
- * by ref bindings, the value of the local variable is simply the first
97
- * alloca.
87
+ * one of type `D*`) and then load a second time to get the actual value (the
88
+ * one of type `D`). For by ref bindings, the value of the local variable is
89
+ * simply the first alloca.
98
90
*
99
91
* So, for the example above, we would generate a setup kind of like this:
100
92
*
101
93
* +-------+
102
94
* | Entry |
103
95
* +-------+
104
96
* |
105
- * +-------------------------------------------+
106
- * | llmatch_c = (addr of first half of tuple) |
107
- * | llmatch_d = (addr of first half of tuple) |
108
- * +-------------------------------------------+
97
+ * +-------------------------------------------- +
98
+ * | llmatch_c = (addr of first half of tuple) |
99
+ * | llmatch_d = (addr of second half of tuple) |
100
+ * +-------------------------------------------- +
109
101
* |
110
102
* +--------------------------------------+
111
- * | *llbinding_d = **llmatch_dlbinding_d |
103
+ * | *llbinding_d = **llmatch_d |
112
104
* +--------------------------------------+
113
105
*
114
106
* If there is a guard, the situation is slightly different, because we must
127
119
* +-------------------------------------------+
128
120
* |
129
121
* +-------------------------------------------------+
130
- * | *llbinding_d = **llmatch_dlbinding_d |
122
+ * | *llbinding_d = **llmatch_d |
131
123
* | check condition |
132
- * | if false { free *llbinding_d, goto next case } |
124
+ * | if false { goto next case } |
133
125
* | if true { goto body } |
134
126
* +-------------------------------------------------+
135
127
*
136
128
* The handling for the cleanups is a bit... sensitive. Basically, the body
137
129
* is the one that invokes `add_clean()` for each binding. During the guard
138
130
* evaluation, we add temporary cleanups and revoke them after the guard is
139
- * evaluated (it could fail, after all). Presuming the guard fails, we drop
140
- * the various values we copied explicitly. Note that guards and moves are
131
+ * evaluated (it could fail, after all). Note that guards and moves are
141
132
* just plain incompatible.
142
133
*
143
134
* Some relevant helper functions that manage bindings:
144
135
* - `create_bindings_map()`
145
- * - `store_non_ref_bindings()`
146
136
* - `insert_lllocals()`
147
137
*
148
138
*
@@ -215,7 +205,6 @@ use middle::trans::datum;
215
205
use middle:: trans:: datum:: * ;
216
206
use middle:: trans:: expr:: Dest ;
217
207
use middle:: trans:: expr;
218
- use middle:: trans:: glue;
219
208
use middle:: trans:: tvec;
220
209
use middle:: trans:: type_of;
221
210
use middle:: trans:: debuginfo;
@@ -362,8 +351,8 @@ fn variant_opt(bcx: &Block, pat_id: ast::NodeId) -> Opt {
362
351
}
363
352
364
353
#[ deriving( Clone ) ]
365
- enum TransBindingMode {
366
- TrByValue ( /*llbinding:*/ ValueRef ) ,
354
+ pub enum TransBindingMode {
355
+ TrByValue ,
367
356
TrByRef ,
368
357
}
369
358
@@ -376,12 +365,12 @@ enum TransBindingMode {
376
365
* - `id` is the node id of the binding
377
366
* - `ty` is the Rust type of the binding */
378
367
#[ deriving( Clone ) ]
379
- struct BindingInfo {
380
- llmatch : ValueRef ,
381
- trmode : TransBindingMode ,
382
- id : ast:: NodeId ,
383
- span : Span ,
384
- ty : ty:: t ,
368
+ pub struct BindingInfo {
369
+ pub llmatch : ValueRef ,
370
+ pub trmode : TransBindingMode ,
371
+ pub id : ast:: NodeId ,
372
+ pub span : Span ,
373
+ pub ty : ty:: t ,
385
374
}
386
375
387
376
type BindingsMap = HashMap < Ident , BindingInfo > ;
@@ -1260,41 +1249,6 @@ fn compare_values<'a>(
1260
1249
}
1261
1250
}
1262
1251
1263
- fn store_non_ref_bindings < ' a > (
1264
- bcx : & ' a Block < ' a > ,
1265
- bindings_map : & BindingsMap ,
1266
- opt_cleanup_scope : Option < cleanup:: ScopeId > )
1267
- -> & ' a Block < ' a >
1268
- {
1269
- /*!
1270
- * For each copy/move binding, copy the value from the value being
1271
- * matched into its final home. This code executes once one of
1272
- * the patterns for a given arm has completely matched. It adds
1273
- * cleanups to the `opt_cleanup_scope`, if one is provided.
1274
- */
1275
-
1276
- let fcx = bcx. fcx ;
1277
- let mut bcx = bcx;
1278
- for ( _, & binding_info) in bindings_map. iter ( ) {
1279
- match binding_info. trmode {
1280
- TrByValue ( lldest) => {
1281
- let llval = Load ( bcx, binding_info. llmatch ) ; // get a T*
1282
- let datum = Datum :: new ( llval, binding_info. ty , Lvalue ) ;
1283
- bcx = datum. store_to ( bcx, lldest) ;
1284
-
1285
- match opt_cleanup_scope {
1286
- None => { }
1287
- Some ( s) => {
1288
- fcx. schedule_drop_mem ( s, lldest, binding_info. ty ) ;
1289
- }
1290
- }
1291
- }
1292
- TrByRef => { }
1293
- }
1294
- }
1295
- return bcx;
1296
- }
1297
-
1298
1252
fn insert_lllocals < ' a > ( bcx : & ' a Block < ' a > ,
1299
1253
bindings_map : & BindingsMap ,
1300
1254
cleanup_scope : cleanup:: ScopeId )
@@ -1308,9 +1262,8 @@ fn insert_lllocals<'a>(bcx: &'a Block<'a>,
1308
1262
1309
1263
for ( & ident, & binding_info) in bindings_map. iter ( ) {
1310
1264
let llval = match binding_info. trmode {
1311
- // By value bindings: use the stack slot that we
1312
- // copied/moved the value into
1313
- TrByValue ( lldest) => lldest,
1265
+ // By value bindings: load from the ptr into the matched value
1266
+ TrByValue => Load ( bcx, binding_info. llmatch ) ,
1314
1267
1315
1268
// By ref binding: use the ptr into the matched value
1316
1269
TrByRef => binding_info. llmatch
@@ -1327,9 +1280,7 @@ fn insert_lllocals<'a>(bcx: &'a Block<'a>,
1327
1280
if bcx. sess ( ) . opts . debuginfo == FullDebugInfo {
1328
1281
debuginfo:: create_match_binding_metadata ( bcx,
1329
1282
ident,
1330
- binding_info. id ,
1331
- binding_info. span ,
1332
- datum) ;
1283
+ binding_info) ;
1333
1284
}
1334
1285
}
1335
1286
bcx
@@ -1355,11 +1306,8 @@ fn compile_guard<'a, 'b>(
1355
1306
// scope for any non-ref bindings we create.
1356
1307
let temp_scope = bcx. fcx . push_custom_cleanup_scope ( ) ;
1357
1308
1358
- let mut bcx = bcx;
1359
- bcx = store_non_ref_bindings ( bcx, & data. bindings_map ,
1360
- Some ( cleanup:: CustomScope ( temp_scope) ) ) ;
1361
- bcx = insert_lllocals ( bcx, & data. bindings_map ,
1362
- cleanup:: CustomScope ( temp_scope) ) ;
1309
+ let mut bcx = insert_lllocals ( bcx, & data. bindings_map ,
1310
+ cleanup:: CustomScope ( temp_scope) ) ;
1363
1311
1364
1312
let val = unpack_datum ! ( bcx, expr:: trans( bcx, guard_expr) ) ;
1365
1313
let val = val. to_llbool ( bcx) ;
@@ -1370,9 +1318,10 @@ fn compile_guard<'a, 'b>(
1370
1318
bcx. fcx . pop_custom_cleanup_scope ( temp_scope) ;
1371
1319
1372
1320
return with_cond ( bcx, Not ( bcx, val) , |bcx| {
1373
- // Guard does not match: free the values we copied,
1374
- // and remove all bindings from the lllocals table
1375
- let bcx = drop_bindings ( bcx, data) ;
1321
+ // Guard does not match: remove all bindings from the lllocals table
1322
+ for ( _, & binding_info) in data. bindings_map . iter ( ) {
1323
+ bcx. fcx . lllocals . borrow_mut ( ) . remove ( & binding_info. id ) ;
1324
+ }
1376
1325
match chk {
1377
1326
// If the default arm is the only one left, move on to the next
1378
1327
// condition explicitly rather than (possibly) falling back to
@@ -1386,21 +1335,6 @@ fn compile_guard<'a, 'b>(
1386
1335
} ;
1387
1336
bcx
1388
1337
} ) ;
1389
-
1390
- fn drop_bindings < ' a > ( bcx : & ' a Block < ' a > , data : & ArmData )
1391
- -> & ' a Block < ' a > {
1392
- let mut bcx = bcx;
1393
- for ( _, & binding_info) in data. bindings_map . iter ( ) {
1394
- match binding_info. trmode {
1395
- TrByValue ( llval) => {
1396
- bcx = glue:: drop_ty ( bcx, llval, binding_info. ty ) ;
1397
- }
1398
- TrByRef => { }
1399
- }
1400
- bcx. fcx . lllocals . borrow_mut ( ) . remove ( & binding_info. id ) ;
1401
- }
1402
- return bcx;
1403
- }
1404
1338
}
1405
1339
1406
1340
fn compile_submatch < ' a , ' b > (
@@ -1836,10 +1770,10 @@ fn create_bindings_map(bcx: &Block, pat: Gc<ast::Pat>) -> BindingsMap {
1836
1770
// in this case, the final type of the variable will be T,
1837
1771
// but during matching we need to store a *T as explained
1838
1772
// above
1839
- llmatch = alloca ( bcx, llvariable_ty . ptr_to ( ) , "__llmatch" ) ;
1840
- trmode = TrByValue ( alloca ( bcx ,
1841
- llvariable_ty ,
1842
- bcx . ident ( ident ) . as_slice ( ) ) ) ;
1773
+ llmatch = alloca ( bcx,
1774
+ llvariable_ty . ptr_to ( ) ,
1775
+ bcx . ident ( ident ) . as_slice ( ) ) ;
1776
+ trmode = TrByValue ;
1843
1777
}
1844
1778
ast:: BindByRef ( _) => {
1845
1779
llmatch = alloca ( bcx,
@@ -1925,14 +1859,6 @@ fn trans_match_inner<'a>(scope_cx: &'a Block<'a>,
1925
1859
for arm_data in arm_datas. iter ( ) {
1926
1860
let mut bcx = arm_data. bodycx ;
1927
1861
1928
- // If this arm has a guard, then the various by-value bindings have
1929
- // already been copied into their homes. If not, we do it here. This
1930
- // is just to reduce code space. See extensive comment at the start
1931
- // of the file for more details.
1932
- if arm_data. arm . guard . is_none ( ) {
1933
- bcx = store_non_ref_bindings ( bcx, & arm_data. bindings_map , None ) ;
1934
- }
1935
-
1936
1862
// insert bindings into the lllocals map and add cleanups
1937
1863
let cleanup_scope = fcx. push_custom_cleanup_scope ( ) ;
1938
1864
bcx = insert_lllocals ( bcx, & arm_data. bindings_map ,
0 commit comments