@@ -79,17 +79,24 @@ fn variant_opt(tcx: ty::ctxt, pat_id: ast::node_id) -> opt {
79
79
core:: unreachable ( ) ;
80
80
}
81
81
82
+ struct binding {
83
+ val : ValueRef ;
84
+ mode: ast:: binding_mode;
85
+ ty: ty:: t;
86
+ }
87
+
82
88
type bind_map = ~[ {
83
89
ident: ast:: ident,
84
- val : ValueRef ,
85
- mode : ast:: binding_mode
90
+ binding: binding
86
91
} ] ;
87
92
88
- fn assoc ( key : ast:: ident , list : bind_map ) -> option < ValueRef > {
93
+ fn assoc ( key : ast:: ident , list : bind_map ) -> option < binding > {
89
94
for vec:: each( list) |elt| {
90
- if str:: eq ( * elt. ident , * key) { ret some ( elt. val ) ; }
95
+ if str:: eq ( * elt. ident , * key) {
96
+ return some ( elt. binding ) ;
97
+ }
91
98
}
92
- ret none;
99
+ return none;
93
100
}
94
101
95
102
type match_branch =
@@ -110,7 +117,9 @@ fn has_nested_bindings(m: match_, col: uint) -> bool {
110
117
ret false;
111
118
}
112
119
113
- fn expand_nested_bindings( m: match_, col: uint, val: ValueRef ) -> match_ {
120
+ fn expand_nested_bindings( bcx: block, m: match_, col: uint, val: ValueRef )
121
+ -> match_ {
122
+
114
123
let mut result = ~[ ] ;
115
124
for vec:: each( m) |br| {
116
125
alt br. pats[ col] . node {
@@ -123,8 +132,12 @@ fn expand_nested_bindings(m: match_, col: uint, val: ValueRef) -> match_ {
123
132
@{ pats: pats,
124
133
bound: vec:: append(
125
134
br. bound, ~[ { ident: path_to_ident( name) ,
126
- val: val,
127
- mode: mode} ] )
135
+ binding: binding {
136
+ val : val,
137
+ mode : mode,
138
+ ty : node_id_type( bcx,
139
+ br. pats[ col] . id)
140
+ } } ] )
128
141
with * br} ) ;
129
142
}
130
143
_ { vec:: push( result, br) ; }
@@ -135,7 +148,7 @@ fn expand_nested_bindings(m: match_, col: uint, val: ValueRef) -> match_ {
135
148
136
149
type enter_pat = fn ( @ast:: pat) -> option<~[ @ast:: pat] >;
137
150
138
- fn enter_match ( dm : DefMap , m : match_ , col : uint , val : ValueRef ,
151
+ fn enter_match ( bcx : block , dm : DefMap , m : match_ , col : uint , val : ValueRef ,
139
152
e : enter_pat ) -> match_ {
140
153
let mut result = ~[ ] ;
141
154
for vec:: each( m) |br| {
@@ -149,8 +162,11 @@ fn enter_match(dm: DefMap, m: match_, col: uint, val: ValueRef,
149
162
ast:: pat_ident ( mode, name, none) if !pat_is_variant ( dm, self ) {
150
163
vec:: append ( br. bound ,
151
164
~[ { ident: path_to_ident ( name) ,
152
- val: val,
153
- mode: mode} ] )
165
+ binding: binding {
166
+ val : val,
167
+ mode : mode,
168
+ ty : node_id_type ( bcx, br. pats [ col] . id )
169
+ } } ] )
154
170
}
155
171
_ { br. bound }
156
172
} ;
@@ -162,8 +178,10 @@ fn enter_match(dm: DefMap, m: match_, col: uint, val: ValueRef,
162
178
ret result;
163
179
}
164
180
165
- fn enter_default ( dm : DefMap , m : match_ , col : uint , val : ValueRef ) -> match_ {
166
- do enter_match ( dm, m, col, val) |p| {
181
+ fn enter_default ( bcx : block , dm : DefMap , m : match_ , col : uint , val : ValueRef )
182
+ -> match_ {
183
+
184
+ do enter_match ( bcx, dm, m, col, val) |p| {
167
185
alt p. node {
168
186
ast:: pat_wild | ast:: pat_rec ( _, _) | ast:: pat_tup ( _) { some ( ~[ ] ) }
169
187
ast:: pat_ident ( _, _, none) if !pat_is_variant ( dm, p) {
@@ -174,10 +192,11 @@ fn enter_default(dm: DefMap, m: match_, col: uint, val: ValueRef) -> match_ {
174
192
}
175
193
}
176
194
177
- fn enter_opt ( tcx : ty :: ctxt , m : match_ , opt : opt , col : uint ,
195
+ fn enter_opt ( bcx : block , m : match_ , opt : opt , col : uint ,
178
196
variant_size : uint , val : ValueRef ) -> match_ {
197
+ let tcx = bcx. tcx ( ) ;
179
198
let dummy = @{ id: 0 , node: ast:: pat_wild, span: dummy_sp ( ) } ;
180
- do enter_match ( tcx. def_map , m, col, val) |p| {
199
+ do enter_match ( bcx , tcx. def_map , m, col, val) |p| {
181
200
alt p. node {
182
201
ast:: pat_enum ( _, subpats) {
183
202
if opt_eq ( tcx, variant_opt ( tcx, p. id ) , opt) {
@@ -200,10 +219,10 @@ fn enter_opt(tcx: ty::ctxt, m: match_, opt: opt, col: uint,
200
219
}
201
220
}
202
221
203
- fn enter_rec ( dm : DefMap , m : match_ , col : uint , fields : ~ [ ast :: ident ] ,
204
- val : ValueRef ) -> match_ {
222
+ fn enter_rec ( bcx : block , dm : DefMap , m : match_ , col : uint ,
223
+ fields : ~ [ ast :: ident ] , val : ValueRef ) -> match_ {
205
224
let dummy = @{ id: 0 , node: ast:: pat_wild, span: dummy_sp ( ) } ;
206
- do enter_match ( dm, m, col, val) |p| {
225
+ do enter_match ( bcx , dm, m, col, val) |p| {
207
226
alt p. node {
208
227
ast:: pat_rec ( fpats, _) {
209
228
let mut pats = ~[ ] ;
@@ -221,30 +240,32 @@ fn enter_rec(dm: DefMap, m: match_, col: uint, fields: ~[ast::ident],
221
240
}
222
241
}
223
242
224
- fn enter_tup ( dm : DefMap , m : match_ , col : uint , val : ValueRef ,
243
+ fn enter_tup ( bcx : block , dm : DefMap , m : match_ , col : uint , val : ValueRef ,
225
244
n_elts : uint ) -> match_ {
226
245
let dummy = @{ id: 0 , node: ast:: pat_wild, span: dummy_sp ( ) } ;
227
- do enter_match ( dm, m, col, val) |p| {
246
+ do enter_match ( bcx , dm, m, col, val) |p| {
228
247
alt p. node {
229
248
ast:: pat_tup ( elts) { some ( elts) }
230
249
_ { some( vec:: from_elem ( n_elts, dummy) ) }
231
250
}
232
251
}
233
252
}
234
253
235
- fn enter_box ( dm : DefMap , m : match_ , col : uint , val : ValueRef ) -> match_ {
254
+ fn enter_box ( bcx : block , dm : DefMap , m : match_ , col : uint , val : ValueRef )
255
+ -> match_ {
236
256
let dummy = @{ id: 0 , node: ast:: pat_wild, span: dummy_sp ( ) } ;
237
- do enter_match ( dm, m, col, val) |p| {
257
+ do enter_match ( bcx , dm, m, col, val) |p| {
238
258
alt p. node {
239
259
ast:: pat_box ( sub) { some ( ~[ sub] ) }
240
260
_ { some( ~[ dummy] ) }
241
261
}
242
262
}
243
263
}
244
264
245
- fn enter_uniq ( dm : DefMap , m : match_ , col : uint , val : ValueRef ) -> match_ {
265
+ fn enter_uniq ( bcx : block , dm : DefMap , m : match_ , col : uint , val : ValueRef )
266
+ -> match_ {
246
267
let dummy = @{ id: 0 , node: ast:: pat_wild, span: dummy_sp ( ) } ;
247
- do enter_match ( dm, m, col, val) |p| {
268
+ do enter_match ( bcx , dm, m, col, val) |p| {
248
269
alt p. node {
249
270
ast:: pat_uniq ( sub) { some ( ~[ sub] ) }
250
271
_ { some( ~[ dummy] ) }
@@ -407,9 +428,24 @@ fn compile_submatch(bcx: block, m: match_, vals: ~[ValueRef],
407
428
some ( e) {
408
429
// Temporarily set bindings. They'll be rewritten to PHI nodes
409
430
// for the actual arm block.
431
+ //
432
+ // Also, in the case of by-value, do the copy now.
433
+
410
434
for data. id_map. each |key, val| {
411
- let loc = local_mem ( option:: get ( assoc ( key, m[ 0 ] . bound ) ) ) ;
412
- bcx. fcx . lllocals . insert ( val, loc) ;
435
+ let binding = assoc ( key, m[ 0 ] . bound ) . get ( ) ;
436
+ let ( llval, mode) = ( binding. val , binding. mode ) ;
437
+ let ty = binding. ty ;
438
+
439
+ if mode == ast:: bind_by_value {
440
+ let llty = type_of:: type_of ( bcx. fcx . ccx , ty) ;
441
+ let alloc = alloca ( bcx, llty) ;
442
+ bcx = copy_val ( bcx, INIT , alloc,
443
+ load_if_immediate ( bcx, llval, ty) , ty) ;
444
+ bcx. fcx . lllocals . insert ( val, local_mem ( alloc) ) ;
445
+ add_clean ( bcx, alloc, ty) ;
446
+ } else {
447
+ bcx. fcx . lllocals . insert ( val, local_mem ( llval) ) ;
448
+ }
413
449
} ;
414
450
let { bcx: guard_cx , val} = {
415
451
do with_scope_result ( bcx, e. info ( ) , ~"guard") |bcx| {
@@ -434,7 +470,7 @@ fn compile_submatch(bcx: block, m: match_, vals: ~[ValueRef],
434
470
let col = pick_col ( m) ;
435
471
let val = vals[ col] ;
436
472
let m = if has_nested_bindings ( m, col) {
437
- expand_nested_bindings ( m, col, val)
473
+ expand_nested_bindings ( bcx , m, col, val)
438
474
} else { m } ;
439
475
440
476
let vals_left = vec:: append ( vec:: slice ( vals, 0 u, col) ,
@@ -458,7 +494,7 @@ fn compile_submatch(bcx: block, m: match_, vals: ~[ValueRef],
458
494
let ix = option:: get ( ty:: field_idx ( field_name, fields) ) ;
459
495
vec:: push ( rec_vals, GEPi ( bcx, val, ~[ 0 u, ix] ) ) ;
460
496
}
461
- compile_submatch ( bcx, enter_rec ( dm, m, col, rec_fields, val) ,
497
+ compile_submatch ( bcx, enter_rec ( bcx , dm, m, col, rec_fields, val) ,
462
498
vec:: append ( rec_vals, vals_left) , chk, exits) ;
463
499
ret;
464
500
}
@@ -474,7 +510,7 @@ fn compile_submatch(bcx: block, m: match_, vals: ~[ValueRef],
474
510
vec:: push ( tup_vals, GEPi ( bcx, val, ~[ 0 u, i] ) ) ;
475
511
i += 1 u;
476
512
}
477
- compile_submatch ( bcx, enter_tup ( dm, m, col, val, n_tup_elts) ,
513
+ compile_submatch ( bcx, enter_tup ( bcx , dm, m, col, val, n_tup_elts) ,
478
514
vec:: append ( tup_vals, vals_left) , chk, exits) ;
479
515
ret;
480
516
}
@@ -485,7 +521,7 @@ fn compile_submatch(bcx: block, m: match_, vals: ~[ValueRef],
485
521
let box_no_addrspace = non_gc_box_cast ( bcx, llbox) ;
486
522
let unboxed =
487
523
GEPi ( bcx, box_no_addrspace, ~[ 0 u, abi:: box_field_body] ) ;
488
- compile_submatch ( bcx, enter_box ( dm, m, col, val) ,
524
+ compile_submatch ( bcx, enter_box ( bcx , dm, m, col, val) ,
489
525
vec:: append ( ~[ unboxed] , vals_left) , chk, exits) ;
490
526
ret;
491
527
}
@@ -495,7 +531,7 @@ fn compile_submatch(bcx: block, m: match_, vals: ~[ValueRef],
495
531
let box_no_addrspace = non_gc_box_cast ( bcx, llbox) ;
496
532
let unboxed =
497
533
GEPi ( bcx, box_no_addrspace, ~[ 0 u, abi:: box_field_body] ) ;
498
- compile_submatch ( bcx, enter_uniq ( dm, m, col, val) ,
534
+ compile_submatch ( bcx, enter_uniq ( bcx , dm, m, col, val) ,
499
535
vec:: append ( ~[ unboxed] , vals_left) , chk, exits) ;
500
536
ret;
501
537
}
@@ -544,7 +580,7 @@ fn compile_submatch(bcx: block, m: match_, vals: ~[ValueRef],
544
580
Switch ( bcx, test_val, else_cx. llbb , opts. len ( ) )
545
581
} else { C_int ( ccx, 0 ) } ; // Placeholder for when not using a switch
546
582
547
- let defaults = enter_default ( dm, m, col, val) ;
583
+ let defaults = enter_default ( bcx , dm, m, col, val) ;
548
584
let exhaustive = option:: is_none ( chk) && defaults. len ( ) == 0 u;
549
585
let len = opts. len ( ) ;
550
586
let mut i = 0 u;
@@ -599,7 +635,7 @@ fn compile_submatch(bcx: block, m: match_, vals: ~[ValueRef],
599
635
}
600
636
lit ( _) | range ( _, _) { }
601
637
}
602
- compile_submatch ( opt_cx, enter_opt ( tcx , m, opt, col, size, val) ,
638
+ compile_submatch ( opt_cx, enter_opt ( bcx , m, opt, col, size, val) ,
603
639
vec:: append ( unpacked, vals_left) , chk, exits) ;
604
640
}
605
641
@@ -624,9 +660,9 @@ fn make_phi_bindings(bcx: block, map: ~[exit_node],
624
660
for vec:: each( map) |ex| {
625
661
if ex. to as uint == our_block {
626
662
alt assoc ( name, ex. bound ) {
627
- some ( val ) {
663
+ some ( binding ) {
628
664
vec:: push ( llbbs, ex. from ) ;
629
- vec:: push ( vals, val) ;
665
+ vec:: push ( vals, binding . val ) ;
630
666
}
631
667
none { }
632
668
}
@@ -643,6 +679,54 @@ fn make_phi_bindings(bcx: block, map: ~[exit_node],
643
679
ret success;
644
680
}
645
681
682
+ // Copies by-value bindings into their homes.
683
+ fn copy_by_value_bindings ( bcx : block ,
684
+ exit_node_map : & [ exit_node ] ,
685
+ pat_ids : pat_util:: pat_id_map )
686
+ -> block {
687
+ let mut bcx = bcx;
688
+ let our_block = bcx. llbb as uint ;
689
+ for pat_ids. each |name, node_id| {
690
+ let bindings = dvec:: dvec ( ) ;
691
+ for exit_node_map. each |exit_node| {
692
+ if exit_node. to as uint == our_block {
693
+ match assoc ( name, exit_node. bound ) {
694
+ none => { }
695
+ some( binding) => bindings. push ( binding)
696
+ }
697
+ }
698
+ }
699
+
700
+ if bindings. len ( ) == 0 {
701
+ again;
702
+ }
703
+
704
+ let binding = bindings[ 0 ] ;
705
+ match binding. mode {
706
+ ast:: bind_by_ref => { }
707
+ ast:: bind_by_value => {
708
+ let llvalue;
709
+ match bcx. fcx . lllocals . get ( node_id) {
710
+ local_mem( llval) =>
711
+ llvalue = llval,
712
+ local_imm( _) =>
713
+ bcx. sess ( ) . bug ( ~"local_imm unexpected here")
714
+ }
715
+
716
+ let lltype = type_of:: type_of ( bcx. fcx . ccx , binding. ty ) ;
717
+ let allocation = alloca ( bcx, lltype) ;
718
+ let ty = binding. ty ;
719
+ bcx = copy_val ( bcx, INIT , allocation,
720
+ load_if_immediate ( bcx, llvalue, ty) , ty) ;
721
+ bcx. fcx . lllocals . insert ( node_id, local_mem ( allocation) ) ;
722
+ add_clean ( bcx, allocation, ty) ;
723
+ }
724
+ }
725
+ }
726
+
727
+ return bcx;
728
+ }
729
+
646
730
fn trans_alt ( bcx : block ,
647
731
alt_expr : @ast:: expr ,
648
732
expr : @ast:: expr ,
@@ -713,6 +797,7 @@ fn trans_alt_inner(scope_cx: block, expr: @ast::expr, arms: ~[ast::arm],
713
797
let body_cx = bodies[ i] ;
714
798
let id_map = pat_util:: pat_id_map ( tcx. def_map , a. pats [ 0 ] ) ;
715
799
if make_phi_bindings ( body_cx, exit_map, id_map) {
800
+ let body_cx = copy_by_value_bindings ( body_cx, exit_map, id_map) ;
716
801
let arm_dest = dup_for_join ( dest) ;
717
802
vec:: push ( arm_dests, arm_dest) ;
718
803
let mut arm_cx = trans_block ( body_cx, a. body , arm_dest) ;
0 commit comments