@@ -414,32 +414,29 @@ fn llalign_of(cx: @crate_ctxt, t: TypeRef) -> ValueRef {
414
414
False ) ;
415
415
}
416
416
417
- fn size_of ( bcx : @block_ctxt , t : ty:: t ) -> result {
418
- let { bcx, sz, align: _ } = metrics ( bcx, t, none) ;
419
- rslt ( bcx, sz)
417
+ fn size_of ( cx : @block_ctxt , t : ty:: t ) -> result {
418
+ size_of_ ( cx, t, align_total)
420
419
}
421
420
422
- fn align_of ( bcx : @ block_ctxt , t : ty :: t ) -> result {
423
- let { bcx , sz : _ , align } = metrics ( bcx , t , none ) ;
424
- rslt ( bcx , align )
421
+ tag align_mode {
422
+ align_total ;
423
+ align_next ( ty :: t ) ;
425
424
}
426
425
427
- // Computes the size/alignment of the type `t`. `opt_v`, if provided, should
428
- // be a pointer to the instance of type `t` whose size/alignment are being
429
- // computed. For most types, `opt_v` is not needed, because all instances
430
- // have the same size/alignment. However, for opaque types like closures, the
431
- // instance is required.
432
- fn metrics ( bcx : @block_ctxt , t : ty:: t , opt_v : option < ValueRef > )
433
- -> metrics_result {
434
- let ccx = bcx_ccx ( bcx) ;
426
+ fn size_of_ ( cx : @block_ctxt , t : ty:: t , mode : align_mode ) -> result {
427
+ let ccx = bcx_ccx ( cx) ;
435
428
if check type_has_static_size ( ccx, t) {
436
- let sp = bcx. sp ;
437
- let sz = llsize_of ( bcx_ccx ( bcx) , type_of ( ccx, sp, t) ) ;
438
- let align = llalign_of ( bcx_ccx ( bcx) , type_of ( ccx, sp, t) ) ;
439
- ret { bcx : bcx, sz : sz, align : align} ;
440
- } else {
441
- ret dynamic_metrics ( bcx, t, opt_v) ;
442
- }
429
+ let sp = cx. sp ;
430
+ rslt ( cx, llsize_of ( bcx_ccx ( cx) , type_of ( ccx, sp, t) ) )
431
+ } else { dynamic_size_of ( cx, t, mode) }
432
+ }
433
+
434
+ fn align_of ( cx : @block_ctxt , t : ty:: t ) -> result {
435
+ let ccx = bcx_ccx ( cx) ;
436
+ if check type_has_static_size ( ccx, t) {
437
+ let sp = cx. sp ;
438
+ rslt ( cx, llalign_of ( bcx_ccx ( cx) , type_of ( ccx, sp, t) ) )
439
+ } else { dynamic_align_of ( cx, t) }
443
440
}
444
441
445
442
fn alloca ( cx : @block_ctxt , t : TypeRef ) -> ValueRef {
@@ -545,18 +542,9 @@ fn static_size_of_tag(cx: @crate_ctxt, sp: span, t: ty::t)
545
542
}
546
543
}
547
544
548
- type metrics_result = {
549
- bcx: @block_ctxt,
550
- sz: ValueRef ,
551
- align: ValueRef
552
- } ;
553
-
554
- fn dynamic_metrics ( bcx : @block_ctxt ,
555
- t : ty:: t ,
556
- opt_v : option < ValueRef > ) -> metrics_result {
557
- fn c_struct_metrics ( bcx : @block_ctxt ,
558
- elts : [ ty:: t ] ,
559
- opt_v : option < ValueRef > ) -> metrics_result {
545
+ fn dynamic_size_of ( cx : @block_ctxt , t : ty:: t , mode : align_mode ) -> result {
546
+ fn align_elements ( cx : @block_ctxt , elts : [ ty:: t ] ,
547
+ mode : align_mode ) -> result {
560
548
//
561
549
// C padding rules:
562
550
//
@@ -565,45 +553,50 @@ fn dynamic_metrics(bcx: @block_ctxt,
565
553
// - Pad after final structure member so that whole structure
566
554
// is aligned to max alignment of interior.
567
555
//
568
- let bcx = bcx;
569
- let off = C_int ( bcx_ccx ( bcx) , 0 ) ;
570
- let max_align = C_int ( bcx_ccx ( bcx) , 1 ) ;
556
+
557
+ let off = C_int ( bcx_ccx ( cx) , 0 ) ;
558
+ let max_align = C_int ( bcx_ccx ( cx) , 1 ) ;
559
+ let bcx = cx;
571
560
for e: ty:: t in elts {
572
- let opt_ev = option:: map ( opt_v) { |v| ptr_offs ( bcx, v, off) } ;
573
- let elt_metrics = metrics ( bcx, e, opt_ev) ;
574
- bcx = elt_metrics. bcx ;
575
- let aligned_off = align_to ( bcx, off, elt_metrics. align ) ;
576
- off = Add ( bcx, aligned_off, elt_metrics. sz ) ;
577
- max_align = umax ( bcx, max_align, elt_metrics. align ) ;
561
+ let elt_align = align_of ( bcx, e) ;
562
+ bcx = elt_align. bcx ;
563
+ let elt_size = size_of ( bcx, e) ;
564
+ bcx = elt_size. bcx ;
565
+ let aligned_off = align_to ( bcx, off, elt_align. val ) ;
566
+ off = Add ( bcx, aligned_off, elt_size. val ) ;
567
+ max_align = umax ( bcx, max_align, elt_align. val ) ;
578
568
}
579
- off = align_to ( bcx, off, max_align) ;
580
- ret { bcx : bcx, sz : off, align : max_align } ;
569
+ off = alt mode {
570
+ align_total. {
571
+ align_to( bcx, off, max_align)
572
+ }
573
+ align_next ( t) {
574
+ let { bcx, val: align } = align_of ( bcx, t) ;
575
+ align_to ( bcx, off, align)
576
+ }
577
+ } ;
578
+ ret rslt( bcx, off) ;
581
579
}
582
-
583
- alt ty:: struct ( bcx_tcx ( bcx) , t) {
580
+ alt ty:: struct ( bcx_tcx ( cx) , t) {
584
581
ty:: ty_param ( p, _) {
585
- let ti = none :: < @tydesc_info > ;
586
- let { bcx, val: tydesc } =
587
- get_tydesc ( bcx, t, false , tps_normal, ti) . result ;
588
- let sz = Load ( bcx, GEPi ( bcx, tydesc, [ 0 , abi:: tydesc_field_size] ) ) ;
589
- let al = Load ( bcx, GEPi ( bcx, tydesc, [ 0 , abi:: tydesc_field_align] ) ) ;
590
- ret { bcx : bcx, sz : sz, align : al } ;
582
+ let szptr = field_of_tydesc ( cx, t, false , abi:: tydesc_field_size) ;
583
+ ret rslt( szptr. bcx , Load ( szptr. bcx , szptr. val ) ) ;
591
584
}
592
585
ty:: ty_rec ( flds) {
593
586
let tys: [ ty:: t ] = [ ] ;
594
587
for f: ty:: field in flds { tys += [ f. mt . ty ] ; }
595
- ret c_struct_metrics ( bcx , tys, opt_v ) ;
588
+ ret align_elements ( cx , tys, mode ) ;
596
589
}
597
590
ty:: ty_tup ( elts) {
598
591
let tys = [ ] ;
599
592
for tp in elts { tys += [ tp] ; }
600
- ret c_struct_metrics ( bcx , tys, opt_v ) ;
593
+ ret align_elements ( cx , tys, mode ) ;
601
594
}
602
595
ty:: ty_tag ( tid, tps) {
603
- let bcx = bcx ;
596
+ let bcx = cx ;
604
597
let ccx = bcx_ccx ( bcx) ;
598
+ // Compute max(variant sizes).
605
599
606
- // Compute max(variant sizes) and max(variant alignments).
607
600
let max_size: ValueRef = alloca ( bcx, ccx. int_type ) ;
608
601
Store ( bcx, C_int ( ccx, 0 ) , max_size) ;
609
602
let variants = ty:: tag_variants ( bcx_tcx ( bcx) , tid) ;
@@ -613,19 +606,12 @@ fn dynamic_metrics(bcx: @block_ctxt,
613
606
let raw_tys: [ ty:: t ] = variant. args ;
614
607
let tys: [ ty:: t ] = [ ] ;
615
608
for raw_ty: ty:: t in raw_tys {
616
- let t = ty:: substitute_type_params ( bcx_tcx ( bcx ) , tps, raw_ty) ;
609
+ let t = ty:: substitute_type_params ( bcx_tcx ( cx ) , tps, raw_ty) ;
617
610
tys += [ t] ;
618
611
}
619
-
620
- // Note: we do not pass in opt_v here for the value but rather
621
- // none. The reason is that what we would want to pass in is a
622
- // ptr to the blob data of the tag, but this is impossible until
623
- // we know the size/alignment of the blob data. Therefore, it is
624
- // not legal to have a tag type that contains an interior opaque
625
- // type. Fortunately this will never happen.
626
- let rslt = c_struct_metrics ( bcx, tys, none) ;
612
+ let rslt = align_elements ( bcx, tys, mode) ;
627
613
bcx = rslt. bcx ;
628
- let this_size = rslt. sz ;
614
+ let this_size = rslt. val ;
629
615
let old_max_size = Load ( bcx, max_size) ;
630
616
Store ( bcx, umax ( bcx, this_size, old_max_size) , max_size) ;
631
617
}
@@ -634,8 +620,41 @@ fn dynamic_metrics(bcx: @block_ctxt,
634
620
if vec:: len ( * variants) != 1 u {
635
621
Add ( bcx, max_size_val, llsize_of ( ccx, ccx. int_type ) )
636
622
} else { max_size_val } ;
637
- let total_align = C_int ( bcx_ccx ( bcx) , 1 ) ; // FIXME: stub
638
- ret { bcx : bcx, sz : total_size, align : total_align} ;
623
+ ret rslt( bcx, total_size) ;
624
+ }
625
+ }
626
+ }
627
+
628
+ fn dynamic_align_of ( cx : @block_ctxt , t : ty:: t ) -> result {
629
+ // FIXME: Typestate constraint that shows this alt is
630
+ // exhaustive
631
+ alt ty:: struct ( bcx_tcx ( cx) , t) {
632
+ ty:: ty_param ( p, _) {
633
+ let aptr = field_of_tydesc ( cx, t, false , abi:: tydesc_field_align) ;
634
+ ret rslt( aptr. bcx , Load ( aptr. bcx , aptr. val ) ) ;
635
+ }
636
+ ty:: ty_rec ( flds) {
637
+ let a = C_int ( bcx_ccx ( cx) , 1 ) ;
638
+ let bcx = cx;
639
+ for f: ty:: field in flds {
640
+ let align = align_of ( bcx, f. mt . ty ) ;
641
+ bcx = align. bcx ;
642
+ a = umax ( bcx, a, align. val ) ;
643
+ }
644
+ ret rslt( bcx, a) ;
645
+ }
646
+ ty:: ty_tag ( _, _) {
647
+ ret rslt ( cx, C_int ( bcx_ccx ( cx) , 1 ) ) ; // FIXME: stub
648
+ }
649
+ ty:: ty_tup ( elts) {
650
+ let a = C_int ( bcx_ccx ( cx) , 1 ) ;
651
+ let bcx = cx;
652
+ for e in elts {
653
+ let align = align_of ( bcx, e) ;
654
+ bcx = align. bcx ;
655
+ a = umax ( bcx, a, align. val ) ;
656
+ }
657
+ ret rslt( bcx, a) ;
639
658
}
640
659
}
641
660
}
@@ -744,10 +763,9 @@ fn GEP_tup_like(bcx: @block_ctxt, t: ty::t, base: ValueRef, ixs: [int])
744
763
let args = [ ] ;
745
764
for typ: ty:: t in s. prefix { args += [ typ] ; }
746
765
let prefix_ty = ty:: mk_tup ( bcx_tcx ( bcx) , args) ;
747
- let { bcx, sz: prefix_sz , align: _} = metrics ( bcx, prefix_ty, some ( base) ) ;
748
- let { bcx, val: align } = align_of ( bcx, s. target ) ;
749
- let sz = align_to ( bcx, prefix_sz, align) ;
750
- ret rslt( bcx, bump_ptr ( bcx, s. target , base, sz) ) ;
766
+
767
+ let sz = size_of_ ( bcx, prefix_ty, align_next ( s. target ) ) ;
768
+ ret rslt( sz. bcx , bump_ptr ( sz. bcx , s. target , base, sz. val ) ) ;
751
769
}
752
770
753
771
@@ -1999,7 +2017,7 @@ fn memmove_ty(bcx: @block_ctxt, dst: ValueRef, src: ValueRef, t: ty::t) ->
1999
2017
ret bcx;
2000
2018
}
2001
2019
2002
- let { bcx, sz : llsz , align : _ } = metrics ( bcx, t, some ( src ) ) ;
2020
+ let { bcx, val : llsz } = size_of ( bcx, t) ;
2003
2021
ret call_memmove ( bcx, dst, src, llsz) . bcx ;
2004
2022
}
2005
2023
0 commit comments