@@ -22,7 +22,7 @@ use middle::trans::datum::*;
22
22
use middle:: trans:: expr:: { Dest , Ignore , SaveIn } ;
23
23
use middle:: trans:: expr;
24
24
use middle:: trans:: glue;
25
- use middle:: trans:: machine:: { llsize_of, nonzero_llsize_of} ;
25
+ use middle:: trans:: machine:: { llsize_of, nonzero_llsize_of, llsize_of_alloc } ;
26
26
use middle:: trans:: type_of;
27
27
use middle:: ty;
28
28
use util:: common:: indenter;
@@ -144,16 +144,19 @@ pub struct VecTypes {
144
144
vec_ty : ty:: t ,
145
145
unit_ty : ty:: t ,
146
146
llunit_ty : Type ,
147
- llunit_size : ValueRef
147
+ llunit_size : ValueRef ,
148
+ llunit_alloc_size : uint
148
149
}
149
150
150
151
impl VecTypes {
151
152
pub fn to_str ( & self , ccx : & CrateContext ) -> ~str {
152
- format ! ( "VecTypes \\ {vec_ty={}, unit_ty={}, llunit_ty={}, llunit_size={}\\ }" ,
153
+ format ! ( "VecTypes \\ {vec_ty={}, unit_ty={}, llunit_ty={}, llunit_size={}, \
154
+ llunit_alloc_size={}\\ }",
153
155
ty_to_str( ccx. tcx, self . vec_ty) ,
154
156
ty_to_str( ccx. tcx, self . unit_ty) ,
155
157
ccx. tn. type_to_str( self . llunit_ty) ,
156
- ccx. tn. val_to_str( self . llunit_size) )
158
+ ccx. tn. val_to_str( self . llunit_size) ,
159
+ self . llunit_alloc_size)
157
160
}
158
161
}
159
162
@@ -416,48 +419,10 @@ pub fn write_content(bcx: @mut Block,
416
419
expr:: trans_to_datum( bcx, element)
417
420
} ) ;
418
421
419
- let next_bcx = sub_block ( bcx, "expr_repeat: while next" ) ;
420
- let loop_bcx = loop_scope_block ( bcx, next_bcx, None , "expr_repeat" , None ) ;
421
- let cond_bcx = scope_block ( loop_bcx, None , "expr_repeat: loop cond" ) ;
422
- let set_bcx = scope_block ( loop_bcx, None , "expr_repeat: body: set" ) ;
423
- let inc_bcx = scope_block ( loop_bcx, None , "expr_repeat: body: inc" ) ;
424
- Br ( bcx, loop_bcx. llbb ) ;
425
-
426
- let loop_counter = {
427
- // i = 0
428
- let i = alloca ( loop_bcx, bcx. ccx ( ) . int_type , "__i" ) ;
429
- Store ( loop_bcx, C_uint ( bcx. ccx ( ) , 0 ) , i) ;
430
-
431
- Br ( loop_bcx, cond_bcx. llbb ) ;
432
- i
433
- } ;
434
-
435
- { // i < count
436
- let lhs = Load ( cond_bcx, loop_counter) ;
437
- let rhs = C_uint ( bcx. ccx ( ) , count) ;
438
- let cond_val = ICmp ( cond_bcx, lib:: llvm:: IntULT , lhs, rhs) ;
439
-
440
- CondBr ( cond_bcx, cond_val, set_bcx. llbb , next_bcx. llbb ) ;
441
- }
442
-
443
- { // v[i] = elem
444
- let i = Load ( set_bcx, loop_counter) ;
445
- let lleltptr = InBoundsGEP ( set_bcx, lldest, [ i] ) ;
446
- let set_bcx = elem. copy_to ( set_bcx, INIT , lleltptr) ;
447
-
448
- Br ( set_bcx, inc_bcx. llbb ) ;
449
- }
450
-
451
- { // i += 1
452
- let i = Load ( inc_bcx, loop_counter) ;
453
- let plusone = Add ( inc_bcx, i, C_uint ( bcx. ccx ( ) , 1 ) ) ;
454
- Store ( inc_bcx, plusone, loop_counter) ;
455
-
456
- Br ( inc_bcx, cond_bcx. llbb ) ;
457
- }
458
-
459
- return next_bcx;
460
-
422
+ iter_vec_loop ( bcx, lldest, vt,
423
+ C_uint ( bcx. ccx ( ) , count) , |set_bcx, lleltptr, _| {
424
+ elem. copy_to ( set_bcx, INIT , lleltptr)
425
+ } )
461
426
}
462
427
}
463
428
}
@@ -478,11 +443,13 @@ pub fn vec_types(bcx: @mut Block, vec_ty: ty::t) -> VecTypes {
478
443
let unit_ty = ty:: sequence_element_type ( bcx. tcx ( ) , vec_ty) ;
479
444
let llunit_ty = type_of:: type_of ( ccx, unit_ty) ;
480
445
let llunit_size = nonzero_llsize_of ( ccx, llunit_ty) ;
446
+ let llunit_alloc_size = llsize_of_alloc ( ccx, llunit_ty) ;
481
447
482
448
VecTypes { vec_ty : vec_ty,
483
449
unit_ty : unit_ty,
484
450
llunit_ty : llunit_ty,
485
- llunit_size : llunit_size}
451
+ llunit_size : llunit_size,
452
+ llunit_alloc_size : llunit_alloc_size}
486
453
}
487
454
488
455
pub fn elements_required ( bcx : @mut Block , content_expr : & ast:: Expr ) -> uint {
@@ -574,35 +541,94 @@ pub fn get_base_and_len(bcx: @mut Block, llval: ValueRef, vec_ty: ty::t) -> (Val
574
541
575
542
pub type iter_vec_block < ' self > = & ' self fn ( @mut Block , ValueRef , ty:: t ) -> @mut Block ;
576
543
544
+ pub fn iter_vec_loop ( bcx : @mut Block ,
545
+ data_ptr : ValueRef ,
546
+ vt : & VecTypes ,
547
+ count : ValueRef ,
548
+ f : iter_vec_block
549
+ ) -> @mut Block {
550
+ let _icx = push_ctxt ( "tvec::iter_vec_loop" ) ;
551
+
552
+ let next_bcx = sub_block ( bcx, "iter_vec_loop: while next" ) ;
553
+ let loop_bcx = loop_scope_block ( bcx, next_bcx, None , "iter_vec_loop" , None ) ;
554
+ let cond_bcx = scope_block ( loop_bcx, None , "iter_vec_loop: loop cond" ) ;
555
+ let body_bcx = scope_block ( loop_bcx, None , "iter_vec_loop: body: main" ) ;
556
+ let inc_bcx = scope_block ( loop_bcx, None , "iter_vec_loop: loop inc" ) ;
557
+ Br ( bcx, loop_bcx. llbb ) ;
558
+
559
+ let loop_counter = {
560
+ // i = 0
561
+ let i = alloca ( loop_bcx, bcx. ccx ( ) . int_type , "__i" ) ;
562
+ Store ( loop_bcx, C_uint ( bcx. ccx ( ) , 0 ) , i) ;
563
+
564
+ Br ( loop_bcx, cond_bcx. llbb ) ;
565
+ i
566
+ } ;
567
+
568
+ { // i < count
569
+ let lhs = Load ( cond_bcx, loop_counter) ;
570
+ let rhs = count;
571
+ let cond_val = ICmp ( cond_bcx, lib:: llvm:: IntULT , lhs, rhs) ;
572
+
573
+ CondBr ( cond_bcx, cond_val, body_bcx. llbb , next_bcx. llbb ) ;
574
+ }
575
+
576
+ { // loop body
577
+ let i = Load ( body_bcx, loop_counter) ;
578
+ let lleltptr = if vt. llunit_alloc_size == 0 {
579
+ data_ptr
580
+ } else {
581
+ InBoundsGEP ( body_bcx, data_ptr, [ i] )
582
+ } ;
583
+ let body_bcx = f ( body_bcx, lleltptr, vt. unit_ty ) ;
584
+
585
+ Br ( body_bcx, inc_bcx. llbb ) ;
586
+ }
587
+
588
+ { // i += 1
589
+ let i = Load ( inc_bcx, loop_counter) ;
590
+ let plusone = Add ( inc_bcx, i, C_uint ( bcx. ccx ( ) , 1 ) ) ;
591
+ Store ( inc_bcx, plusone, loop_counter) ;
592
+
593
+ Br ( inc_bcx, cond_bcx. llbb ) ;
594
+ }
595
+
596
+ next_bcx
597
+ }
598
+
577
599
pub fn iter_vec_raw ( bcx : @mut Block , data_ptr : ValueRef , vec_ty : ty:: t ,
578
600
fill : ValueRef , f : iter_vec_block ) -> @mut Block {
579
601
let _icx = push_ctxt ( "tvec::iter_vec_raw" ) ;
580
602
581
- let unit_ty = ty:: sequence_element_type ( bcx. tcx ( ) , vec_ty) ;
582
-
583
- // Calculate the last pointer address we want to handle.
584
- // FIXME (#3729): Optimize this when the size of the unit type is
585
- // statically known to not use pointer casts, which tend to confuse
586
- // LLVM.
587
- let data_end_ptr = pointer_add_byte ( bcx, data_ptr, fill) ;
588
-
589
- // Now perform the iteration.
590
- let header_bcx = base:: sub_block ( bcx, "iter_vec_loop_header" ) ;
591
- Br ( bcx, header_bcx. llbb ) ;
592
- let data_ptr =
593
- Phi ( header_bcx, val_ty ( data_ptr) , [ data_ptr] , [ bcx. llbb ] ) ;
594
- let not_yet_at_end =
595
- ICmp ( header_bcx, lib:: llvm:: IntULT , data_ptr, data_end_ptr) ;
596
- let body_bcx = base:: sub_block ( header_bcx, "iter_vec_loop_body" ) ;
597
- let next_bcx = base:: sub_block ( header_bcx, "iter_vec_next" ) ;
598
- CondBr ( header_bcx, not_yet_at_end, body_bcx. llbb , next_bcx. llbb ) ;
599
- let body_bcx = f ( body_bcx, data_ptr, unit_ty) ;
600
- AddIncomingToPhi ( data_ptr, InBoundsGEP ( body_bcx, data_ptr,
601
- [ C_int ( bcx. ccx ( ) , 1 ) ] ) ,
602
- body_bcx. llbb ) ;
603
- Br ( body_bcx, header_bcx. llbb ) ;
604
- return next_bcx;
603
+ let vt = vec_types ( bcx, vec_ty) ;
604
+ if ( vt. llunit_alloc_size == 0 ) {
605
+ // Special-case vectors with elements of size 0 so they don't go out of bounds (#9890)
606
+ iter_vec_loop ( bcx, data_ptr, & vt, fill, f)
607
+ } else {
608
+ // Calculate the last pointer address we want to handle.
609
+ // FIXME (#3729): Optimize this when the size of the unit type is
610
+ // statically known to not use pointer casts, which tend to confuse
611
+ // LLVM.
612
+ let data_end_ptr = pointer_add_byte ( bcx, data_ptr, fill) ;
613
+
614
+ // Now perform the iteration.
615
+ let header_bcx = base:: sub_block ( bcx, "iter_vec_loop_header" ) ;
616
+ Br ( bcx, header_bcx. llbb ) ;
617
+ let data_ptr =
618
+ Phi ( header_bcx, val_ty ( data_ptr) , [ data_ptr] , [ bcx. llbb ] ) ;
619
+ let not_yet_at_end =
620
+ ICmp ( header_bcx, lib:: llvm:: IntULT , data_ptr, data_end_ptr) ;
621
+ let body_bcx = base:: sub_block ( header_bcx, "iter_vec_loop_body" ) ;
622
+ let next_bcx = base:: sub_block ( header_bcx, "iter_vec_next" ) ;
623
+ CondBr ( header_bcx, not_yet_at_end, body_bcx. llbb , next_bcx. llbb ) ;
624
+ let body_bcx = f ( body_bcx, data_ptr, vt. unit_ty ) ;
625
+ AddIncomingToPhi ( data_ptr, InBoundsGEP ( body_bcx, data_ptr,
626
+ [ C_int ( bcx. ccx ( ) , 1 ) ] ) ,
627
+ body_bcx. llbb ) ;
628
+ Br ( body_bcx, header_bcx. llbb ) ;
629
+ next_bcx
605
630
631
+ }
606
632
}
607
633
608
634
pub fn iter_vec_uniq ( bcx : @mut Block , vptr : ValueRef , vec_ty : ty:: t ,
0 commit comments