@@ -85,20 +85,30 @@ 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
91
103
* field is known to be nonnull due to its type; if that field is null, then
92
104
* it represents the other case, which is inhabited by at most one value
93
105
* (and all other fields are undefined/unused).
94
- * If the case with the nullable pointer has a single field then we don't
95
- * wrap it in a struct and instead just deal with it directly as a pointer.
96
106
*
97
107
* For example, `std::option::Option` instantiated at a safe pointer type
98
108
* is represented such that `None` is a null pointer and `Some` is the
99
109
* identity function.
100
110
*/
101
- NullablePointer {
111
+ StructWrappedNullablePointer {
102
112
pub nonnull : Struct ,
103
113
pub nndiscr : Disr ,
104
114
pub ptrfield : uint ,
@@ -202,17 +212,23 @@ fn represent_type_uncached(cx: &CrateContext, t: ty::t) -> Repr {
202
212
if cases. get ( 1 - discr) . is_zerolen ( cx) {
203
213
match cases. get ( discr) . find_ptr ( ) {
204
214
Some ( ptrfield) => {
205
- return NullablePointer {
206
- nndiscr : discr as u64 ,
207
- nonnull : mk_struct ( cx,
208
- cases. get ( discr)
209
- . tys
210
- . as_slice ( ) ,
211
- false ) ,
212
- ptrfield : ptrfield,
213
- nullfields : cases. get ( 1 - discr) . tys
214
- . clone ( )
215
- }
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
+ } ;
216
232
}
217
233
None => { }
218
234
}
@@ -415,11 +431,8 @@ pub fn incomplete_type_of(cx: &CrateContext, r: &Repr, name: &str) -> Type {
415
431
}
416
432
pub fn finish_type_of ( cx : & CrateContext , r : & Repr , llty : & mut Type ) {
417
433
match * r {
418
- CEnum ( ..) | General ( ..) => {
419
- }
420
- NullablePointer { nonnull : ref st, .. } if st. fields . len ( ) == 1 => {
421
- }
422
- Univariant ( ref st, _) | NullablePointer { nonnull : ref st, .. } =>
434
+ CEnum ( ..) | General ( ..) | RawNullablePointer { .. } => { }
435
+ Univariant ( ref st, _) | StructWrappedNullablePointer { nonnull : ref st, .. } =>
423
436
llty. set_struct_body ( struct_llfields ( cx, st, false ) . as_slice ( ) ,
424
437
st. packed )
425
438
}
@@ -428,14 +441,8 @@ pub fn finish_type_of(cx: &CrateContext, r: &Repr, llty: &mut Type) {
428
441
fn generic_type_of ( cx : & CrateContext , r : & Repr , name : Option < & str > , sizing : bool ) -> Type {
429
442
match * r {
430
443
CEnum ( ity, _, _) => ll_inttype ( cx, ity) ,
431
- NullablePointer { nonnull : ref st, .. } if st. fields . len ( ) == 1 => {
432
- if sizing {
433
- type_of:: sizing_type_of ( cx, * st. fields . get ( 0 ) )
434
- } else {
435
- type_of:: type_of ( cx, * st. fields . get ( 0 ) )
436
- }
437
- }
438
- 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, .. } => {
439
446
match name {
440
447
None => {
441
448
Type :: struct_ ( cx, struct_llfields ( cx, st, sizing) . as_slice ( ) ,
@@ -507,12 +514,10 @@ fn struct_llfields(cx: &CrateContext, st: &Struct, sizing: bool) -> Vec<Type> {
507
514
pub fn trans_switch ( bcx : & Block , r : & Repr , scrutinee : ValueRef )
508
515
-> ( _match:: branch_kind , Option < ValueRef > ) {
509
516
match * r {
510
- CEnum ( ..) | General ( ..) => {
517
+ CEnum ( ..) | General ( ..) |
518
+ RawNullablePointer { .. } | StructWrappedNullablePointer { .. } => {
511
519
( _match:: switch, Some ( trans_get_discr ( bcx, r, scrutinee, None ) ) )
512
520
}
513
- NullablePointer { nonnull : ref nonnull, nndiscr, ptrfield, .. } => {
514
- ( _match:: switch, Some ( nullable_bitdiscr ( bcx, nonnull, nndiscr, ptrfield, scrutinee) ) )
515
- }
516
521
Univariant ( ..) => {
517
522
( _match:: single, None )
518
523
}
@@ -540,8 +545,14 @@ pub fn trans_get_discr(bcx: &Block, r: &Repr, scrutinee: ValueRef, cast_to: Opti
540
545
val = C_u8 ( bcx. ccx ( ) , 0 ) ;
541
546
signed = false ;
542
547
}
543
- NullablePointer { nonnull : ref nonnull, nndiscr, ptrfield, .. } => {
544
- 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) ;
545
556
signed = false ;
546
557
}
547
558
}
@@ -551,13 +562,9 @@ pub fn trans_get_discr(bcx: &Block, r: &Repr, scrutinee: ValueRef, cast_to: Opti
551
562
}
552
563
}
553
564
554
- fn nullable_bitdiscr ( bcx : & Block , nonnull : & Struct , nndiscr : Disr , ptrfield : uint ,
555
- scrutinee : ValueRef ) -> ValueRef {
556
- let llptr = if nonnull. fields . len ( ) == 1 {
557
- Load ( bcx, scrutinee)
558
- } else {
559
- Load ( bcx, GEPi ( bcx, scrutinee, [ 0 , ptrfield] ) )
560
- } ;
565
+ fn struct_wrapped_nullable_bitdiscr ( bcx : & Block , nonnull : & Struct , nndiscr : Disr , ptrfield : uint ,
566
+ scrutinee : ValueRef ) -> ValueRef {
567
+ let llptr = Load ( bcx, GEPi ( bcx, scrutinee, [ 0 , ptrfield] ) ) ;
561
568
let cmp = if nndiscr == 0 { IntEQ } else { IntNE } ;
562
569
let llptrty = type_of:: type_of ( bcx. ccx ( ) , * nonnull. fields . get ( ptrfield) ) ;
563
570
ICmp ( bcx, cmp, llptr, C_null ( llptrty) )
@@ -606,7 +613,8 @@ pub fn trans_case<'a>(bcx: &'a Block<'a>, r: &Repr, discr: Disr)
606
613
Univariant ( ..) => {
607
614
bcx. ccx ( ) . sess ( ) . bug ( "no cases for univariants or structs" )
608
615
}
609
- NullablePointer { .. } => {
616
+ RawNullablePointer { .. } |
617
+ StructWrappedNullablePointer { .. } => {
610
618
assert ! ( discr == 0 || discr == 1 ) ;
611
619
_match:: single_result ( Result :: new ( bcx, C_i1 ( bcx. ccx ( ) , discr != 0 ) ) )
612
620
}
@@ -637,13 +645,15 @@ pub fn trans_start_init(bcx: &Block, r: &Repr, val: ValueRef, discr: Disr) {
637
645
Univariant ( ..) => {
638
646
assert_eq ! ( discr, 0 ) ;
639
647
}
640
- NullablePointer { nonnull : ref nonnull , nndiscr, ptrfield , .. } => {
648
+ RawNullablePointer { nndiscr, nnty , ..} => {
641
649
if discr != nndiscr {
642
- let llptrptr = if nonnull. fields . len ( ) == 1 {
643
- val
644
- } else {
645
- GEPi ( bcx, val, [ 0 , ptrfield] )
646
- } ;
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, .. } => {
655
+ if discr != nndiscr {
656
+ let llptrptr = GEPi ( bcx, val, [ 0 , ptrfield] ) ;
647
657
let llptrty = type_of:: type_of ( bcx. ccx ( ) ,
648
658
* nonnull. fields . get ( ptrfield) ) ;
649
659
Store ( bcx, C_null ( llptrty) , llptrptr)
@@ -671,8 +681,11 @@ pub fn num_args(r: &Repr, discr: Disr) -> uint {
671
681
st. fields . len ( ) - ( if dtor { 1 } else { 0 } )
672
682
}
673
683
General ( _, ref cases) => cases. get ( discr as uint ) . fields . len ( ) - 1 ,
674
- NullablePointer { nonnull : ref nonnull, nndiscr,
675
- 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, .. } => {
676
689
if discr == nndiscr { nonnull. fields . len ( ) } else { nullfields. len ( ) }
677
690
}
678
691
}
@@ -695,24 +708,25 @@ pub fn trans_field_ptr(bcx: &Block, r: &Repr, val: ValueRef, discr: Disr,
695
708
General ( _, ref cases) => {
696
709
struct_field_ptr ( bcx, cases. get ( discr as uint ) , val, ix + 1 , true )
697
710
}
698
- NullablePointer { nonnull : ref nonnull, nullfields : ref nullfields,
699
- nndiscr, .. } => {
700
- if discr == nndiscr {
701
- if nonnull. fields . len ( ) == 1 {
702
- assert_eq ! ( ix, 0 ) ;
703
- val
704
- } else {
705
- struct_field_ptr ( bcx, nonnull, val, ix, false )
706
- }
707
- } else {
708
- // The unit-like case might have a nonzero number of unit-like fields.
709
- // (e.g., Result or Either with () as one side.)
710
- let ty = type_of:: type_of ( bcx. ccx ( ) , * nullfields. get ( ix) ) ;
711
- assert_eq ! ( machine:: llsize_of_alloc( bcx. ccx( ) , ty) , 0 ) ;
712
- // The contents of memory at this pointer can't matter, but use
713
- // the value that's "reasonable" in case of pointer comparison.
714
- PointerCast ( bcx, val, ty. ptr_to ( ) )
715
- }
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 )
716
730
}
717
731
}
718
732
}
@@ -784,15 +798,15 @@ pub fn trans_const(ccx: &CrateContext, r: &Repr, discr: Disr,
784
798
let contents = build_const_struct ( ccx, st, vals) ;
785
799
C_struct ( ccx, contents. as_slice ( ) , st. packed )
786
800
}
787
- NullablePointer { nonnull : ref st , nndiscr , .. } if st . fields . len ( ) == 1 => {
801
+ RawNullablePointer { nndiscr , nnty , .. } => {
788
802
if discr == nndiscr {
789
803
assert_eq ! ( vals. len( ) , 1 ) ;
790
804
vals[ 0 ]
791
805
} else {
792
- C_null ( type_of:: sizing_type_of ( ccx, * st . fields . get ( 0 ) ) )
806
+ C_null ( type_of:: sizing_type_of ( ccx, nnty ) )
793
807
}
794
808
}
795
- NullablePointer { nonnull : ref nonnull, nndiscr, .. } => {
809
+ StructWrappedNullablePointer { nonnull : ref nonnull, nndiscr, .. } => {
796
810
if discr == nndiscr {
797
811
C_struct ( ccx, build_const_struct ( ccx,
798
812
nonnull,
@@ -900,15 +914,15 @@ pub fn const_get_discrim(ccx: &CrateContext, r: &Repr, val: ValueRef)
900
914
}
901
915
}
902
916
Univariant ( ..) => 0 ,
903
- NullablePointer { nonnull : ref st , nndiscr, .. } if st . fields . len ( ) == 1 => {
917
+ RawNullablePointer { nndiscr, .. } => {
904
918
if is_null ( val) {
905
919
/* subtraction as uint is ok because nndiscr is either 0 or 1 */
906
920
( 1 - nndiscr) as Disr
907
921
} else {
908
922
nndiscr
909
923
}
910
924
}
911
- NullablePointer { nndiscr, ptrfield, .. } => {
925
+ StructWrappedNullablePointer { nndiscr, ptrfield, .. } => {
912
926
if is_null ( const_struct_field ( ccx, val, ptrfield) ) {
913
927
/* subtraction as uint is ok because nndiscr is either 0 or 1 */
914
928
( 1 - nndiscr) as Disr
@@ -932,11 +946,11 @@ pub fn const_get_field(ccx: &CrateContext, r: &Repr, val: ValueRef,
932
946
CEnum ( ..) => ccx. sess ( ) . bug ( "element access in C-like enum const" ) ,
933
947
Univariant ( ..) => const_struct_field ( ccx, val, ix) ,
934
948
General ( ..) => const_struct_field ( ccx, val, ix + 1 ) ,
935
- NullablePointer { nonnull : ref st , .. } if st . fields . len ( ) == 1 => {
949
+ RawNullablePointer { .. } => {
936
950
assert_eq ! ( ix, 0 ) ;
937
951
val
938
952
}
939
- NullablePointer { .. } => const_struct_field ( ccx, val, ix)
953
+ StructWrappedNullablePointer { .. } => const_struct_field ( ccx, val, ix)
940
954
}
941
955
}
942
956
0 commit comments