@@ -85,6 +85,18 @@ pub enum Repr {
85
85
* all start with a field for the discriminant.
86
86
*/
87
87
General ( IntType , Vec < Struct > ) ,
88
+ /**
89
+ * Two cases distinguished by a nullable pointer: the case with discriminant
90
+ * `nndiscr` must have single field which is known to be nonnull due to its type.
91
+ * The other case is known to be zero sized. Hence we represent the enum
92
+ * as simply a nullable pointer: if not null it indicates the `nndiscr` variant,
93
+ * otherwise it indicates the other case.
94
+ */
95
+ RawNullablePointer {
96
+ pub nndiscr : Disr ,
97
+ pub nnty : ty:: t ,
98
+ pub nullfields : Vec < ty:: t >
99
+ } ,
88
100
/**
89
101
* Two cases distinguished by a nullable pointer: the case with discriminant
90
102
* `nndiscr` is represented by the struct `nonnull`, where the `ptrfield`th
@@ -96,7 +108,7 @@ pub enum Repr {
96
108
* is represented such that `None` is a null pointer and `Some` is the
97
109
* identity function.
98
110
*/
99
- NullablePointer {
111
+ StructWrappedNullablePointer {
100
112
pub nonnull : Struct ,
101
113
pub nndiscr : Disr ,
102
114
pub ptrfield : uint ,
@@ -200,17 +212,23 @@ fn represent_type_uncached(cx: &CrateContext, t: ty::t) -> Repr {
200
212
if cases. get ( 1 - discr) . is_zerolen ( cx) {
201
213
match cases. get ( discr) . find_ptr ( ) {
202
214
Some ( ptrfield) => {
203
- return NullablePointer {
204
- nndiscr : discr as u64 ,
205
- nonnull : mk_struct ( cx,
206
- cases. get ( discr)
207
- . tys
208
- . as_slice ( ) ,
209
- false ) ,
210
- ptrfield : ptrfield,
211
- nullfields : cases. get ( 1 - discr) . tys
212
- . clone ( )
213
- }
215
+ let st = mk_struct ( cx, cases. get ( discr) . tys . as_slice ( ) ,
216
+ false ) ;
217
+
218
+ return if st. fields . len ( ) == 1 {
219
+ RawNullablePointer {
220
+ nndiscr : discr as Disr ,
221
+ nnty : * st. fields . get ( 0 ) ,
222
+ nullfields : cases. get ( 1 - discr) . tys . clone ( )
223
+ }
224
+ } else {
225
+ StructWrappedNullablePointer {
226
+ nndiscr : discr as Disr ,
227
+ nonnull : st,
228
+ ptrfield : ptrfield,
229
+ nullfields : cases. get ( 1 - discr) . tys . clone ( )
230
+ }
231
+ } ;
214
232
}
215
233
None => { }
216
234
}
@@ -413,8 +431,8 @@ pub fn incomplete_type_of(cx: &CrateContext, r: &Repr, name: &str) -> Type {
413
431
}
414
432
pub fn finish_type_of ( cx : & CrateContext , r : & Repr , llty : & mut Type ) {
415
433
match * r {
416
- CEnum ( ..) | General ( ..) => { }
417
- Univariant ( ref st, _) | NullablePointer { nonnull : ref st, .. } =>
434
+ CEnum ( ..) | General ( ..) | RawNullablePointer { .. } => { }
435
+ Univariant ( ref st, _) | StructWrappedNullablePointer { nonnull : ref st, .. } =>
418
436
llty. set_struct_body ( struct_llfields ( cx, st, false ) . as_slice ( ) ,
419
437
st. packed )
420
438
}
@@ -423,7 +441,8 @@ pub fn finish_type_of(cx: &CrateContext, r: &Repr, llty: &mut Type) {
423
441
fn generic_type_of ( cx : & CrateContext , r : & Repr , name : Option < & str > , sizing : bool ) -> Type {
424
442
match * r {
425
443
CEnum ( ity, _, _) => ll_inttype ( cx, ity) ,
426
- Univariant ( ref st, _) | NullablePointer { nonnull : ref st, .. } => {
444
+ RawNullablePointer { nnty, .. } => type_of:: sizing_type_of ( cx, nnty) ,
445
+ Univariant ( ref st, _) | StructWrappedNullablePointer { nonnull : ref st, .. } => {
427
446
match name {
428
447
None => {
429
448
Type :: struct_ ( cx, struct_llfields ( cx, st, sizing) . as_slice ( ) ,
@@ -495,12 +514,10 @@ fn struct_llfields(cx: &CrateContext, st: &Struct, sizing: bool) -> Vec<Type> {
495
514
pub fn trans_switch ( bcx : & Block , r : & Repr , scrutinee : ValueRef )
496
515
-> ( _match:: branch_kind , Option < ValueRef > ) {
497
516
match * r {
498
- CEnum ( ..) | General ( ..) => {
517
+ CEnum ( ..) | General ( ..) |
518
+ RawNullablePointer { .. } | StructWrappedNullablePointer { .. } => {
499
519
( _match:: switch, Some ( trans_get_discr ( bcx, r, scrutinee, None ) ) )
500
520
}
501
- NullablePointer { nonnull : ref nonnull, nndiscr, ptrfield, .. } => {
502
- ( _match:: switch, Some ( nullable_bitdiscr ( bcx, nonnull, nndiscr, ptrfield, scrutinee) ) )
503
- }
504
521
Univariant ( ..) => {
505
522
( _match:: single, None )
506
523
}
@@ -528,8 +545,14 @@ pub fn trans_get_discr(bcx: &Block, r: &Repr, scrutinee: ValueRef, cast_to: Opti
528
545
val = C_u8 ( bcx. ccx ( ) , 0 ) ;
529
546
signed = false ;
530
547
}
531
- NullablePointer { nonnull : ref nonnull, nndiscr, ptrfield, .. } => {
532
- val = nullable_bitdiscr ( bcx, nonnull, nndiscr, ptrfield, scrutinee) ;
548
+ RawNullablePointer { nndiscr, nnty, .. } => {
549
+ let cmp = if nndiscr == 0 { IntEQ } else { IntNE } ;
550
+ let llptrty = type_of:: sizing_type_of ( bcx. ccx ( ) , nnty) ;
551
+ val = ICmp ( bcx, cmp, Load ( bcx, scrutinee) , C_null ( llptrty) ) ;
552
+ signed = false ;
553
+ }
554
+ StructWrappedNullablePointer { nonnull : ref nonnull, nndiscr, ptrfield, .. } => {
555
+ val = struct_wrapped_nullable_bitdiscr ( bcx, nonnull, nndiscr, ptrfield, scrutinee) ;
533
556
signed = false ;
534
557
}
535
558
}
@@ -539,10 +562,10 @@ pub fn trans_get_discr(bcx: &Block, r: &Repr, scrutinee: ValueRef, cast_to: Opti
539
562
}
540
563
}
541
564
542
- fn nullable_bitdiscr ( bcx : & Block , nonnull : & Struct , nndiscr : Disr , ptrfield : uint ,
543
- scrutinee : ValueRef ) -> ValueRef {
544
- let cmp = if nndiscr == 0 { IntEQ } else { IntNE } ;
565
+ fn struct_wrapped_nullable_bitdiscr ( bcx : & Block , nonnull : & Struct , nndiscr : Disr , ptrfield : uint ,
566
+ scrutinee : ValueRef ) -> ValueRef {
545
567
let llptr = Load ( bcx, GEPi ( bcx, scrutinee, [ 0 , ptrfield] ) ) ;
568
+ let cmp = if nndiscr == 0 { IntEQ } else { IntNE } ;
546
569
let llptrty = type_of:: type_of ( bcx. ccx ( ) , * nonnull. fields . get ( ptrfield) ) ;
547
570
ICmp ( bcx, cmp, llptr, C_null ( llptrty) )
548
571
}
@@ -590,7 +613,8 @@ pub fn trans_case<'a>(bcx: &'a Block<'a>, r: &Repr, discr: Disr)
590
613
Univariant ( ..) => {
591
614
bcx. ccx ( ) . sess ( ) . bug ( "no cases for univariants or structs" )
592
615
}
593
- NullablePointer { .. } => {
616
+ RawNullablePointer { .. } |
617
+ StructWrappedNullablePointer { .. } => {
594
618
assert ! ( discr == 0 || discr == 1 ) ;
595
619
_match:: single_result ( Result :: new ( bcx, C_i1 ( bcx. ccx ( ) , discr != 0 ) ) )
596
620
}
@@ -621,7 +645,13 @@ pub fn trans_start_init(bcx: &Block, r: &Repr, val: ValueRef, discr: Disr) {
621
645
Univariant ( ..) => {
622
646
assert_eq ! ( discr, 0 ) ;
623
647
}
624
- NullablePointer { nonnull : ref nonnull, nndiscr, ptrfield, .. } => {
648
+ RawNullablePointer { nndiscr, nnty, ..} => {
649
+ if discr != nndiscr {
650
+ let llptrty = type_of:: sizing_type_of ( bcx. ccx ( ) , nnty) ;
651
+ Store ( bcx, C_null ( llptrty) , val)
652
+ }
653
+ }
654
+ StructWrappedNullablePointer { nonnull : ref nonnull, nndiscr, ptrfield, .. } => {
625
655
if discr != nndiscr {
626
656
let llptrptr = GEPi ( bcx, val, [ 0 , ptrfield] ) ;
627
657
let llptrty = type_of:: type_of ( bcx. ccx ( ) ,
@@ -651,8 +681,11 @@ pub fn num_args(r: &Repr, discr: Disr) -> uint {
651
681
st. fields . len ( ) - ( if dtor { 1 } else { 0 } )
652
682
}
653
683
General ( _, ref cases) => cases. get ( discr as uint ) . fields . len ( ) - 1 ,
654
- NullablePointer { nonnull : ref nonnull, nndiscr,
655
- nullfields : ref nullfields, .. } => {
684
+ RawNullablePointer { nndiscr, ref nullfields, .. } => {
685
+ if discr == nndiscr { 1 } else { nullfields. len ( ) }
686
+ }
687
+ StructWrappedNullablePointer { nonnull : ref nonnull, nndiscr,
688
+ nullfields : ref nullfields, .. } => {
656
689
if discr == nndiscr { nonnull. fields . len ( ) } else { nullfields. len ( ) }
657
690
}
658
691
}
@@ -675,19 +708,25 @@ pub fn trans_field_ptr(bcx: &Block, r: &Repr, val: ValueRef, discr: Disr,
675
708
General ( _, ref cases) => {
676
709
struct_field_ptr ( bcx, cases. get ( discr as uint ) , val, ix + 1 , true )
677
710
}
678
- NullablePointer { nonnull : ref nonnull, nullfields : ref nullfields,
679
- nndiscr, .. } => {
680
- if discr == nndiscr {
681
- struct_field_ptr ( bcx, nonnull, val, ix, false )
682
- } else {
683
- // The unit-like case might have a nonzero number of unit-like fields.
684
- // (e.g., Result or Either with () as one side.)
685
- let ty = type_of:: type_of ( bcx. ccx ( ) , * nullfields. get ( ix) ) ;
686
- assert_eq ! ( machine:: llsize_of_alloc( bcx. ccx( ) , ty) , 0 ) ;
687
- // The contents of memory at this pointer can't matter, but use
688
- // the value that's "reasonable" in case of pointer comparison.
689
- PointerCast ( bcx, val, ty. ptr_to ( ) )
690
- }
711
+ RawNullablePointer { nndiscr, ref nullfields, .. } |
712
+ StructWrappedNullablePointer { nndiscr, ref nullfields, .. } if discr != nndiscr => {
713
+ // The unit-like case might have a nonzero number of unit-like fields.
714
+ // (e.d., Result of Either with (), as one side.)
715
+ let ty = type_of:: type_of ( bcx. ccx ( ) , * nullfields. get ( ix) ) ;
716
+ assert_eq ! ( machine:: llsize_of_alloc( bcx. ccx( ) , ty) , 0 ) ;
717
+ // The contents of memory at this pointer can't matter, but use
718
+ // the value that's "reasonable" in case of pointer comparision.
719
+ PointerCast ( bcx, val, ty. ptr_to ( ) )
720
+ }
721
+ RawNullablePointer { nndiscr, nnty, .. } => {
722
+ assert_eq ! ( ix, 0 ) ;
723
+ assert_eq ! ( discr, nndiscr) ;
724
+ let ty = type_of:: type_of ( bcx. ccx ( ) , nnty) ;
725
+ PointerCast ( bcx, val, ty. ptr_to ( ) )
726
+ }
727
+ StructWrappedNullablePointer { ref nonnull, nndiscr, .. } => {
728
+ assert_eq ! ( discr, nndiscr) ;
729
+ struct_field_ptr ( bcx, nonnull, val, ix, false )
691
730
}
692
731
}
693
732
}
@@ -759,7 +798,15 @@ pub fn trans_const(ccx: &CrateContext, r: &Repr, discr: Disr,
759
798
let contents = build_const_struct ( ccx, st, vals) ;
760
799
C_struct ( ccx, contents. as_slice ( ) , st. packed )
761
800
}
762
- NullablePointer { nonnull : ref nonnull, nndiscr, .. } => {
801
+ RawNullablePointer { nndiscr, nnty, .. } => {
802
+ if discr == nndiscr {
803
+ assert_eq ! ( vals. len( ) , 1 ) ;
804
+ vals[ 0 ]
805
+ } else {
806
+ C_null ( type_of:: sizing_type_of ( ccx, nnty) )
807
+ }
808
+ }
809
+ StructWrappedNullablePointer { nonnull : ref nonnull, nndiscr, .. } => {
763
810
if discr == nndiscr {
764
811
C_struct ( ccx, build_const_struct ( ccx,
765
812
nonnull,
@@ -867,7 +914,15 @@ pub fn const_get_discrim(ccx: &CrateContext, r: &Repr, val: ValueRef)
867
914
}
868
915
}
869
916
Univariant ( ..) => 0 ,
870
- NullablePointer { nndiscr, ptrfield, .. } => {
917
+ RawNullablePointer { nndiscr, .. } => {
918
+ if is_null ( val) {
919
+ /* subtraction as uint is ok because nndiscr is either 0 or 1 */
920
+ ( 1 - nndiscr) as Disr
921
+ } else {
922
+ nndiscr
923
+ }
924
+ }
925
+ StructWrappedNullablePointer { nndiscr, ptrfield, .. } => {
871
926
if is_null ( const_struct_field ( ccx, val, ptrfield) ) {
872
927
/* subtraction as uint is ok because nndiscr is either 0 or 1 */
873
928
( 1 - nndiscr) as Disr
@@ -891,7 +946,11 @@ pub fn const_get_field(ccx: &CrateContext, r: &Repr, val: ValueRef,
891
946
CEnum ( ..) => ccx. sess ( ) . bug ( "element access in C-like enum const" ) ,
892
947
Univariant ( ..) => const_struct_field ( ccx, val, ix) ,
893
948
General ( ..) => const_struct_field ( ccx, val, ix + 1 ) ,
894
- NullablePointer { .. } => const_struct_field ( ccx, val, ix)
949
+ RawNullablePointer { .. } => {
950
+ assert_eq ! ( ix, 0 ) ;
951
+ val
952
+ }
953
+ StructWrappedNullablePointer { .. } => const_struct_field ( ccx, val, ix)
895
954
}
896
955
}
897
956
0 commit comments