@@ -479,38 +479,202 @@ fn decr_refcnt_and_if_zero(@block_ctxt cx,
479
479
ret res( next_cx, phi) ;
480
480
}
481
481
482
- fn type_is_scalar ( @ast. ty t ) -> bool {
483
- alt ( t. node ) {
484
- case ( ast. ty_nil ) { ret true ; }
485
- case ( ast. ty_bool ) { ret true ; }
486
- case ( ast. ty_int ) { ret true ; }
487
- case ( ast. ty_uint ) { ret true ; }
488
- case ( ast. ty_machine ( _) ) { ret true ; }
489
- case ( ast. ty_char ) { ret true ; }
482
+ type val_and_ty_fn =
483
+ fn ( @block_ctxt cx , ValueRef v, @typeck. ty t ) -> result ;
484
+
485
+ // Iterates through the elements of a tup, rec or tag.
486
+ fn iter_structural_ty ( @block_ctxt cx ,
487
+ ValueRef v,
488
+ @typeck. ty t ,
489
+ val_and_ty_fn f)
490
+ -> result {
491
+ let result r = res ( cx, C_nil ( ) ) ;
492
+ alt ( t. struct ) {
493
+ case ( typeck. ty_tup ( ?args) ) {
494
+ let int i = 0 ;
495
+ for ( tup( bool, @typeck. ty) arg in args) {
496
+ auto elt = r. bcx. build. GEP ( v, vec( C_int ( 0 ) , C_int ( i) ) ) ;
497
+ r = f( r. bcx, elt, arg. _1) ;
498
+ i += 1 ;
499
+ }
500
+ }
501
+ // FIXME: handle records and tags when we support them.
490
502
}
491
- ret false ;
503
+ ret r ;
492
504
}
493
505
494
- fn trans_copy_ty ( @block_ctxt cx ,
495
- bool is_init ,
496
- ValueRef dst,
497
- ValueRef src,
498
- @ast. ty t ) -> result {
499
- if ( type_is_scalar ( t) ) {
500
- ret res ( cx, cx. build . Store ( src, dst) ) ;
506
+ // Iterates through the elements of a vec or str.
507
+ fn iter_sequence ( @block_ctxt cx ,
508
+ ValueRef v,
509
+ @typeck . ty ty,
510
+ val_and_ty_fn f) -> result {
511
+
512
+ fn iter_sequence_body ( @block_ctxt cx ,
513
+ ValueRef v,
514
+ @typeck. ty elt_ty ,
515
+ val_and_ty_fn f,
516
+ bool trailing_null ) -> result {
517
+
518
+ auto p0 = cx. build . GEP ( v, vec ( C_int ( 0 ) ,
519
+ C_int ( abi. vec_elt_data ) ) ) ;
520
+ auto lenptr = cx. build . GEP ( v, vec ( C_int ( 0 ) ,
521
+ C_int ( abi. vec_elt_fill ) ) ) ;
522
+ auto len = cx. build . Load ( lenptr) ;
523
+ if ( trailing_null) {
524
+ len = cx. build . Sub ( len, C_int ( 1 ) ) ;
525
+ }
526
+
527
+ auto r = res ( cx, C_nil ( ) ) ;
528
+
529
+ auto cond_cx = new_sub_block_ctxt ( cx, "sequence-iter cond" ) ;
530
+ auto body_cx = new_sub_block_ctxt ( cx, "sequence-iter body" ) ;
531
+ auto next_cx = new_sub_block_ctxt ( cx, "next" ) ;
532
+
533
+ auto ix = cond_cx. build . Phi ( T_int ( ) , vec ( C_int ( 0 ) ) , vec ( cx. llbb ) ) ;
534
+ auto end_test = cond_cx. build . ICmp ( lib. llvm . LLVMIntEQ , ix, len) ;
535
+ cond_cx. build . CondBr ( end_test, body_cx. llbb , next_cx. llbb ) ;
536
+
537
+ auto elt = body_cx. build . GEP ( p0, vec ( ix) ) ;
538
+ auto body_res = f ( body_cx, elt, elt_ty) ;
539
+ auto next_ix = body_res. bcx . build . Add ( ix, C_int ( 1 ) ) ;
540
+ cond_cx. build . AddIncomingToPhi ( ix, vec ( next_ix) ,
541
+ vec ( body_res. bcx . llbb ) ) ;
542
+
543
+ body_res. bcx . build . Br ( cond_cx. llbb ) ;
544
+ ret res( next_cx, C_nil ( ) ) ;
545
+ }
546
+
547
+ alt ( ty. struct ) {
548
+ case ( typeck. ty_vec ( ?et) ) {
549
+ ret iter_sequence_body ( cx, v, et, f, false ) ;
550
+ }
551
+ case ( typeck. ty_str ) {
552
+ auto et = typeck. plain_ty ( typeck. ty_machine ( common. ty_u8 ) ) ;
553
+ ret iter_sequence_body ( cx, v, et, f, false ) ;
554
+ }
501
555
}
556
+ cx. fcx . ccx . sess . bug ( "bad type in trans.iter_sequence" ) ;
557
+ fail;
558
+ }
559
+
560
+ fn incr_all_refcnts ( @block_ctxt cx ,
561
+ ValueRef v,
562
+ @typeck. ty t ) -> result {
502
563
503
- alt ( t. node ) {
504
- case ( ast. ty_str ) {
505
- let result r = res ( cx, C_nil ( ) ) ;
506
- if ( is_init) {
507
- r = trans_drop_str ( cx, dst) ;
564
+ if ( typeck. type_is_boxed ( t) ) {
565
+ ret incr_refcnt ( cx, v) ;
566
+
567
+ } else if ( typeck. type_is_binding ( t) ) {
568
+ cx. fcx . ccx . sess . unimpl ( "binding type in trans.incr_all_refcnts" ) ;
569
+
570
+ } else if ( typeck. type_is_structural ( t) ) {
571
+ ret iter_structural_ty ( cx, v, t,
572
+ bind incr_all_refcnts ( _, _, _) ) ;
573
+ }
574
+ }
575
+
576
+ fn drop_ty ( @block_ctxt cx ,
577
+ ValueRef v,
578
+ @typeck. ty t ) -> result {
579
+
580
+ alt ( t. struct ) {
581
+ case ( typeck. ty_str ) {
582
+ ret decr_refcnt_and_if_zero ( cx, v,
583
+ bind trans_non_gc_free ( _, v) ,
584
+ "free string" ,
585
+ T_int ( ) , C_int ( 0 ) ) ;
586
+ }
587
+
588
+ case ( typeck. ty_vec ( _) ) {
589
+ fn hit_zero ( @block_ctxt cx , ValueRef v,
590
+ @typeck. ty t ) -> result {
591
+ auto res = iter_sequence ( cx, v, t, bind drop_ty ( _, _, _) ) ;
592
+ // FIXME: switch gc/non-gc on stratum of the type.
593
+ ret trans_non_gc_free ( res. bcx , v) ;
594
+ }
595
+ ret decr_refcnt_and_if_zero ( cx, v,
596
+ bind hit_zero ( _, v, t) ,
597
+ "free vector" ,
598
+ T_int ( ) , C_int ( 0 ) ) ;
599
+ }
600
+
601
+ case ( typeck. ty_box ( _) ) {
602
+ fn hit_zero ( @block_ctxt cx , ValueRef v,
603
+ @typeck. ty elt_ty ) -> result {
604
+ auto res = drop_ty ( cx,
605
+ cx. build . GEP ( v, vec ( C_int ( 0 ) ) ) ,
606
+ elt_ty) ;
607
+ // FIXME: switch gc/non-gc on stratum of the type.
608
+ ret trans_non_gc_free ( res. bcx , v) ;
609
+ }
610
+ ret incr_refcnt ( cx, v) ;
611
+ }
612
+
613
+ case ( _) {
614
+ if ( typeck. type_is_structural ( t) ) {
615
+ ret iter_structural_ty ( cx, v, t,
616
+ bind drop_ty ( _, _, _) ) ;
617
+
618
+ } else if ( typeck. type_is_binding ( t) ) {
619
+ cx. fcx . ccx . sess . unimpl ( "binding type in trans.drop_ty" ) ;
620
+
621
+ } else if ( typeck. type_is_scalar ( t) ||
622
+ typeck. type_is_nil ( t) ) {
623
+ ret res ( cx, C_nil ( ) ) ;
508
624
}
509
- r = incr_refcnt ( r. bcx , src) ;
510
- ret res( r. bcx , r. bcx . build . Store ( src, dst) ) ;
511
625
}
512
626
}
513
- cx. fcx . ccx . sess . unimpl ( "ty variant in trans_copy_ty" ) ;
627
+ cx. fcx . ccx . sess . bug ( "bad type in trans.drop_ty" ) ;
628
+ fail;
629
+ }
630
+
631
+ fn build_memcpy ( @block_ctxt cx ,
632
+ ValueRef dst,
633
+ ValueRef src,
634
+ TypeRef llty) -> result {
635
+ auto memcpy = cx. fcx . ccx . fn_names . get ( "llvm.memcpy" ) ;
636
+ auto src_ptr = cx. build . PointerCast ( src, T_ptr ( T_i8 ( ) ) ) ;
637
+ auto dst_ptr = cx. build . PointerCast ( dst, T_ptr ( T_i8 ( ) ) ) ;
638
+ auto size = lib. llvm . llvm . LLVMSizeOf ( llty) ;
639
+ auto align = lib. llvm . llvm . LLVMAlignOf ( llty) ;
640
+ auto volatile = C_integral ( 0 , T_i1 ( ) ) ;
641
+ ret res ( cx, cx. build . Call ( memcpy,
642
+ vec ( dst_ptr, src_ptr,
643
+ size, align, volatile) ) ) ;
644
+ }
645
+
646
+ fn copy_ty ( @block_ctxt cx ,
647
+ bool is_init ,
648
+ ValueRef dst,
649
+ ValueRef src,
650
+ @typeck. ty t ) -> result {
651
+ if ( typeck. type_is_scalar ( t) ) {
652
+ ret res ( cx, cx. build . Store ( src, dst) ) ;
653
+
654
+ } else if ( typeck. type_is_nil ( t) ) {
655
+ ret res ( cx, C_nil ( ) ) ;
656
+
657
+ } else if ( typeck. type_is_binding ( t) ) {
658
+ cx. fcx . ccx . sess . unimpl ( "binding type in trans.copy_ty" ) ;
659
+
660
+ } else if ( typeck. type_is_boxed ( t) ) {
661
+ auto r = incr_refcnt ( cx, src) ;
662
+ if ( ! is_init) {
663
+ r = drop_ty ( r. bcx , dst, t) ;
664
+ }
665
+ ret res( r. bcx , r. bcx . build . Store ( src, dst) ) ;
666
+
667
+ } else if ( typeck. type_is_structural ( t) ) {
668
+ auto r = incr_all_refcnts ( cx, src, t) ;
669
+ if ( ! is_init) {
670
+ r = drop_ty ( r. bcx , dst, t) ;
671
+ }
672
+ auto llty = type_of ( cx. fcx . ccx , t) ;
673
+ r = build_memcpy ( r. bcx , dst, src, llty) ;
674
+ }
675
+
676
+ cx. fcx . ccx . sess . bug ( "unexpected type in trans.copy_ty: " +
677
+ typeck. ty_to_str ( t) ) ;
514
678
fail;
515
679
}
516
680
@@ -1023,13 +1187,12 @@ impure fn trans_expr(@block_ctxt cx, &ast.expr e) -> result {
1023
1187
}
1024
1188
}
1025
1189
1026
- case ( ast. expr_assign ( ?dst, ?src, _ ) ) {
1190
+ case ( ast. expr_assign ( ?dst, ?src, ?ann ) ) {
1027
1191
auto lhs_res = trans_lval ( cx, * dst) ;
1028
1192
check ( lhs_res. _1 ) ;
1029
1193
auto rhs_res = trans_expr ( lhs_res. _0 . bcx , * src) ;
1030
- // FIXME: call trans_copy_ty once we have a ty here.
1031
- ret res ( rhs_res. bcx ,
1032
- rhs_res. bcx . build . Store ( rhs_res. val , lhs_res. _0 . val ) ) ;
1194
+ auto t = node_ann_type ( cx. fcx . ccx , ann) ;
1195
+ ret copy_ty ( rhs_res. bcx , true , lhs_res. _0 . val , rhs_res. val , t) ;
1033
1196
}
1034
1197
1035
1198
case ( ast. expr_call ( ?f, ?args, _) ) {
@@ -1451,7 +1614,12 @@ fn trans_main_fn(@crate_ctxt cx, ValueRef llcrate) {
1451
1614
1452
1615
fn declare_intrinsics ( ModuleRef llmod) {
1453
1616
let vec[ TypeRef ] T_trap_args = vec ( ) ;
1617
+ // FIXME: switch this to 64-bit memcpy when targeting a 64-bit system.
1618
+ let vec[ TypeRef ] T_memcpy_args = vec ( T_ptr ( T_i8 ( ) ) ,
1619
+ T_ptr ( T_i8 ( ) ) ,
1620
+ T_i32 ( ) , T_i32 ( ) , T_i1 ( ) ) ;
1454
1621
decl_cdecl_fn ( llmod, "llvm.trap" , T_fn ( T_trap_args , T_void ( ) ) ) ;
1622
+ decl_cdecl_fn ( llmod, "llvm.memcpy" , T_fn ( T_memcpy_args , T_void ( ) ) ) ;
1455
1623
}
1456
1624
1457
1625
fn trans_crate ( session . session sess, @ast. crate crate, str output ) {
0 commit comments