@@ -52,7 +52,8 @@ type glue_fns = rec(ValueRef activate_glue,
52
52
ValueRef exit_task_glue ,
53
53
vec[ ValueRef ] upcall_glues ,
54
54
ValueRef no_op_type_glue ,
55
- ValueRef memcpy_glue ) ;
55
+ ValueRef memcpy_glue ,
56
+ ValueRef bzero_glue ) ;
56
57
57
58
tag arity { nullary; n_ary; }
58
59
type tag_info = rec ( type_handle th,
@@ -632,19 +633,110 @@ fn find_scope_cx(@block_ctxt cx) -> @block_ctxt {
632
633
}
633
634
}
634
635
635
- fn size_of ( TypeRef t) -> ValueRef {
636
+ fn umax ( @block_ctxt cx , ValueRef a, ValueRef b) -> ValueRef {
637
+ auto cond = cx. build . ICmp ( lib. llvm . LLVMIntULT , a, b) ;
638
+ ret cx. build . Select ( cond, b, a) ;
639
+ }
640
+
641
+ fn align_to ( @block_ctxt cx , ValueRef off, ValueRef align) -> ValueRef {
642
+ auto mask = cx. build . Sub ( align, C_int ( 1 ) ) ;
643
+ auto bumped = cx. build . Add ( off, mask) ;
644
+ ret cx. build . And ( bumped, cx. build . Not ( mask) ) ;
645
+ }
646
+
647
+ fn llsize_of ( TypeRef t) -> ValueRef {
636
648
ret llvm. LLVMConstIntCast ( lib. llvm . llvm . LLVMSizeOf ( t) , T_int ( ) , False ) ;
637
649
}
638
650
639
- fn align_of ( TypeRef t) -> ValueRef {
651
+ fn llalign_of ( TypeRef t) -> ValueRef {
640
652
ret llvm. LLVMConstIntCast ( lib. llvm . llvm . LLVMAlignOf ( t) , T_int ( ) , False ) ;
641
653
}
642
654
655
+ fn size_of ( @block_ctxt cx , @ty. t t ) -> ValueRef {
656
+ if ( !ty. type_has_dynamic_size ( t) ) {
657
+ ret llsize_of ( type_of ( cx. fcx . ccx , t) ) ;
658
+ }
659
+ ret dynamic_size_of ( cx, t) ;
660
+ }
661
+
662
+ fn align_of ( @block_ctxt cx , @ty. t t ) -> ValueRef {
663
+ if ( !ty. type_has_dynamic_size ( t) ) {
664
+ ret llalign_of ( type_of ( cx. fcx . ccx , t) ) ;
665
+ }
666
+ ret dynamic_align_of ( cx, t) ;
667
+ }
668
+
669
+ fn dynamic_size_of ( @block_ctxt cx , @ty. t t ) -> ValueRef {
670
+ alt ( t. struct ) {
671
+ case ( ty. ty_param ( ?p) ) {
672
+ auto szptr = field_of_tydesc ( cx, t, abi. tydesc_field_size ) ;
673
+ ret cx. build . Load ( szptr) ;
674
+ }
675
+ case ( ty. ty_tup ( ?elts) ) {
676
+ //
677
+ // C padding rules:
678
+ //
679
+ //
680
+ // - Pad after each element so that next element is aligned.
681
+ // - Pad after final structure member so that whole structure
682
+ // is aligned to max alignment of interior.
683
+ //
684
+ auto off = C_int ( 0 ) ;
685
+ auto max_align = C_int ( 1 ) ;
686
+ for ( @ty. t e in elts) {
687
+ auto elt_align = align_of( cx, e) ;
688
+ auto elt_size = size_of( cx, e) ;
689
+ auto aligned_off = align_to( cx, off, elt_align) ;
690
+ off = cx. build. Add ( aligned_off, elt_size) ;
691
+ max_align = umax( cx, max_align, elt_align) ;
692
+ }
693
+ off = align_to( cx, off, max_align) ;
694
+ ret off;
695
+ }
696
+ case ( ty. ty_rec( ?flds) ) {
697
+ auto off = C_int ( 0 ) ;
698
+ auto max_align = C_int ( 1 ) ;
699
+ for ( ty. field f in flds) {
700
+ auto elt_align = align_of( cx, f. ty) ;
701
+ auto elt_size = size_of( cx, f. ty) ;
702
+ auto aligned_off = align_to( cx, off, elt_align) ;
703
+ off = cx. build. Add ( aligned_off, elt_size) ;
704
+ max_align = umax( cx, max_align, elt_align) ;
705
+ }
706
+ off = align_to( cx, off, max_align) ;
707
+ ret off;
708
+ }
709
+ }
710
+ }
711
+
712
+ fn dynamic_align_of( @block_ctxt cx, @ty. t t) -> ValueRef {
713
+ alt ( t. struct ) {
714
+ case ( ty. ty_param( ?p) ) {
715
+ auto aptr = field_of_tydesc( cx, t, abi. tydesc_field_align) ;
716
+ ret cx. build. Load ( aptr) ;
717
+ }
718
+ case ( ty. ty_tup( ?elts) ) {
719
+ auto a = C_int ( 1 ) ;
720
+ for ( @ty. t e in elts) {
721
+ a = umax( cx, a, align_of( cx, e) ) ;
722
+ }
723
+ ret a;
724
+ }
725
+ case ( ty. ty_rec( ?flds) ) {
726
+ auto a = C_int ( 1 ) ;
727
+ for ( ty. field f in flds) {
728
+ a = umax( cx, a, align_of( cx, f. ty) ) ;
729
+ }
730
+ ret a;
731
+ }
732
+ }
733
+ }
734
+
643
735
fn trans_malloc_inner( @block_ctxt cx, TypeRef llptr_ty) -> result {
644
736
auto llbody_ty = lib. llvm. llvm. LLVMGetElementType ( llptr_ty) ;
645
737
// FIXME: need a table to collect tydesc globals.
646
738
auto tydesc = C_int ( 0 ) ;
647
- auto sz = size_of ( llbody_ty) ;
739
+ auto sz = llsize_of ( llbody_ty) ;
648
740
auto sub = trans_upcall( cx, "upcall_malloc" , vec( sz, tydesc) ) ;
649
741
sub. val = sub. bcx. build. IntToPtr ( sub. val, llptr_ty) ;
650
742
ret sub;
@@ -699,8 +791,8 @@ fn make_tydesc(@crate_ctxt cx, @ty.t t) {
699
791
auto pvoid = T_ptr ( T_i8 ( ) ) ;
700
792
auto glue_fn_ty = T_ptr ( T_fn ( vec( T_taskptr ( ) , pvoid) , T_void ( ) ) ) ;
701
793
auto tydesc = C_struct ( vec( C_null ( pvoid) ,
702
- size_of ( llty) ,
703
- align_of ( llty) ,
794
+ llsize_of ( llty) ,
795
+ llalign_of ( llty) ,
704
796
take_glue, // take_glue_off
705
797
drop_glue, // drop_glue_off
706
798
C_null ( glue_fn_ty) , // free_glue_off
@@ -1146,7 +1238,7 @@ fn iter_sequence(@block_ctxt cx,
1146
1238
C_int ( abi. vec_elt_fill) ) ) ;
1147
1239
1148
1240
auto llunit_ty = type_of( cx. fcx. ccx, elt_ty) ;
1149
- auto unit_sz = size_of( llunit_ty ) ;
1241
+ auto unit_sz = size_of( cx , elt_ty ) ;
1150
1242
1151
1243
auto len = cx. build. Load ( lenptr) ;
1152
1244
if ( trailing_null) {
@@ -1249,6 +1341,15 @@ fn call_memcpy(@block_ctxt cx,
1249
1341
vec( dst_ptr, src_ptr, size) ) ) ;
1250
1342
}
1251
1343
1344
+ fn call_bzero( @block_ctxt cx,
1345
+ ValueRef dst,
1346
+ ValueRef n_bytes) -> result {
1347
+ auto dst_ptr = cx. build. PointerCast ( dst, T_ptr( T_i8 ( ) ) ) ;
1348
+ auto size = cx. build. IntCast ( n_bytes, T_int ( ) ) ;
1349
+ ret res( cx, cx. build. FastCall ( cx. fcx. ccx. glues. bzero_glue,
1350
+ vec( dst_ptr, size) ) ) ;
1351
+ }
1352
+
1252
1353
fn memcpy_ty( @block_ctxt cx,
1253
1354
ValueRef dst,
1254
1355
ValueRef src,
@@ -1901,7 +2002,7 @@ impure fn trans_index(@block_ctxt cx, &ast.span sp, @ast.expr base,
1901
2002
auto v = lv. val;
1902
2003
1903
2004
auto llunit_ty = node_type( cx. fcx. ccx, ann) ;
1904
- auto unit_sz = size_of( llunit_ty ) ;
2005
+ auto unit_sz = size_of( cx , node_ann_type ( cx . fcx . ccx , ann ) ) ;
1905
2006
auto scaled_ix = ix. bcx. build. Mul ( ix. val, unit_sz) ;
1906
2007
1907
2008
auto lim = ix. bcx. build. GEP ( v, vec( C_int( 0 ) , C_int ( abi. vec_elt_fill) ) ) ;
@@ -2374,7 +2475,7 @@ impure fn trans_vec(@block_ctxt cx, vec[@ast.expr] args,
2374
2475
}
2375
2476
2376
2477
auto llunit_ty = type_of( cx. fcx. ccx, unit_ty) ;
2377
- auto unit_sz = size_of( llunit_ty ) ;
2478
+ auto unit_sz = size_of( cx , unit_ty ) ;
2378
2479
auto data_sz = llvm. LLVMConstMul ( C_int ( _vec. len[ @ast. expr] ( args) as int) ,
2379
2480
unit_sz) ;
2380
2481
@@ -2681,9 +2782,15 @@ impure fn trans_stmt(@block_ctxt cx, &ast.stmt s) -> result {
2681
2782
sub = copy_ty( sub. bcx, true, llptr, sub. val, ty) ;
2682
2783
}
2683
2784
case ( _) {
2684
- auto llty = type_of( cx. fcx. ccx, ty) ;
2685
- auto null = lib. llvm. llvm. LLVMConstNull ( llty) ;
2686
- sub = res( cx, cx. build. Store ( null, llptr) ) ;
2785
+ if ( middle. ty. type_has_dynamic_size( ty) ) {
2786
+ auto llsz = size_of( cx, ty) ;
2787
+ sub = call_bzero( cx, llptr, llsz) ;
2788
+
2789
+ } else {
2790
+ auto llty = type_of( cx. fcx. ccx, ty) ;
2791
+ auto null = lib. llvm. llvm. LLVMConstNull ( llty) ;
2792
+ sub = res( cx, cx. build. Store ( null, llptr) ) ;
2793
+ }
2687
2794
}
2688
2795
}
2689
2796
}
@@ -2779,8 +2886,14 @@ impure fn trans_block(@block_ctxt cx, &ast.block b) -> result {
2779
2886
auto bcx = cx;
2780
2887
2781
2888
for each ( @ast. local local in block_locals( b) ) {
2782
- auto ty = node_type( cx. fcx. ccx, local. ann) ;
2783
- auto val = bcx. build. Alloca ( ty) ;
2889
+ auto t = node_ann_type( cx. fcx. ccx, local. ann) ;
2890
+ auto val = C_int ( 0 ) ;
2891
+ if ( ty. type_has_dynamic_size( t) ) {
2892
+ auto n = size_of( bcx, t) ;
2893
+ val = bcx. build. ArrayAlloca ( T_i8 ( ) , n) ;
2894
+ } else {
2895
+ val = bcx. build. Alloca ( type_of( cx. fcx. ccx, t) ) ;
2896
+ }
2784
2897
cx. fcx. lllocals. insert( local. id, val) ;
2785
2898
}
2786
2899
auto r = res( bcx, C_nil ( ) ) ;
@@ -3684,6 +3797,47 @@ fn make_memcpy_glue(ModuleRef llmod) -> ValueRef {
3684
3797
ret fun;
3685
3798
}
3686
3799
3800
+ fn make_bzero_glue ( ModuleRef llmod) -> ValueRef {
3801
+
3802
+ // We're not using the LLVM memset intrinsic. Same as with memcpy.
3803
+
3804
+ auto p8 = T_ptr ( T_i8 ( ) ) ;
3805
+
3806
+ auto ty = T_fn ( vec ( p8, T_int ( ) ) , T_void ( ) ) ;
3807
+ auto fun = decl_fastcall_fn ( llmod, abi. bzero_glue_name ( ) , ty) ;
3808
+
3809
+ auto initbb = llvm. LLVMAppendBasicBlock ( fun, _str. buf ( "init" ) ) ;
3810
+ auto hdrbb = llvm. LLVMAppendBasicBlock ( fun, _str. buf ( "hdr" ) ) ;
3811
+ auto loopbb = llvm. LLVMAppendBasicBlock ( fun, _str. buf ( "loop" ) ) ;
3812
+ auto endbb = llvm. LLVMAppendBasicBlock ( fun, _str. buf ( "end" ) ) ;
3813
+
3814
+ auto dst = llvm. LLVMGetParam ( fun, 0 u) ;
3815
+ auto count = llvm. LLVMGetParam ( fun, 1 u) ;
3816
+
3817
+ // Init block.
3818
+ auto ib = new_builder ( initbb) ;
3819
+ auto ip = ib. Alloca ( T_int ( ) ) ;
3820
+ ib. Store ( C_int ( 0 ) , ip) ;
3821
+ ib. Br ( hdrbb) ;
3822
+
3823
+ // Loop-header block
3824
+ auto hb = new_builder ( hdrbb) ;
3825
+ auto i = hb. Load ( ip) ;
3826
+ hb. CondBr ( hb. ICmp ( lib. llvm . LLVMIntEQ , count, i) , endbb, loopbb) ;
3827
+
3828
+ // Loop-body block
3829
+ auto lb = new_builder ( loopbb) ;
3830
+ i = lb. Load ( ip) ;
3831
+ lb. Store ( C_integral ( 0 , T_i8 ( ) ) , lb. GEP ( dst, vec ( i) ) ) ;
3832
+ lb. Store ( lb. Add ( i, C_int ( 1 ) ) , ip) ;
3833
+ lb. Br ( hdrbb) ;
3834
+
3835
+ // End block
3836
+ auto eb = new_builder ( endbb) ;
3837
+ eb. RetVoid ( ) ;
3838
+ ret fun;
3839
+ }
3840
+
3687
3841
fn make_glues ( ModuleRef llmod) -> @glue_fns {
3688
3842
ret @rec( activate_glue = decl_glue ( llmod, abi. activate_glue_name ( ) ) ,
3689
3843
yield_glue = decl_glue ( llmod, abi. yield_glue_name ( ) ) ,
@@ -3704,7 +3858,8 @@ fn make_glues(ModuleRef llmod) -> @glue_fns {
3704
3858
_vec. init_fn [ ValueRef ] ( bind decl_upcall ( llmod, _) ,
3705
3859
abi. n_upcall_glues as uint ) ,
3706
3860
no_op_type_glue = make_no_op_type_glue ( llmod) ,
3707
- memcpy_glue = make_memcpy_glue ( llmod) ) ;
3861
+ memcpy_glue = make_memcpy_glue ( llmod) ,
3862
+ bzero_glue = make_bzero_glue ( llmod) ) ;
3708
3863
}
3709
3864
3710
3865
fn trans_crate ( session . session sess, @ast. crate crate, str output ,
0 commit comments