Skip to content

Commit 28243a5

Browse files
committed
librustc: Separate NullablePointer into RawNullablePointer and StructWrappedNullablePointer.
1 parent d104dab commit 28243a5

File tree

2 files changed

+92
-75
lines changed

2 files changed

+92
-75
lines changed

src/librustc/middle/trans/adt.rs

+88-74
Original file line numberDiff line numberDiff line change
@@ -85,20 +85,30 @@ pub enum Repr {
8585
* all start with a field for the discriminant.
8686
*/
8787
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+
},
88100
/**
89101
* Two cases distinguished by a nullable pointer: the case with discriminant
90102
* `nndiscr` is represented by the struct `nonnull`, where the `ptrfield`th
91103
* field is known to be nonnull due to its type; if that field is null, then
92104
* it represents the other case, which is inhabited by at most one value
93105
* (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.
96106
*
97107
* For example, `std::option::Option` instantiated at a safe pointer type
98108
* is represented such that `None` is a null pointer and `Some` is the
99109
* identity function.
100110
*/
101-
NullablePointer {
111+
StructWrappedNullablePointer {
102112
pub nonnull: Struct,
103113
pub nndiscr: Disr,
104114
pub ptrfield: uint,
@@ -202,17 +212,23 @@ fn represent_type_uncached(cx: &CrateContext, t: ty::t) -> Repr {
202212
if cases.get(1 - discr).is_zerolen(cx) {
203213
match cases.get(discr).find_ptr() {
204214
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+
};
216232
}
217233
None => { }
218234
}
@@ -415,11 +431,8 @@ pub fn incomplete_type_of(cx: &CrateContext, r: &Repr, name: &str) -> Type {
415431
}
416432
pub fn finish_type_of(cx: &CrateContext, r: &Repr, llty: &mut Type) {
417433
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, .. } =>
423436
llty.set_struct_body(struct_llfields(cx, st, false).as_slice(),
424437
st.packed)
425438
}
@@ -428,14 +441,8 @@ pub fn finish_type_of(cx: &CrateContext, r: &Repr, llty: &mut Type) {
428441
fn generic_type_of(cx: &CrateContext, r: &Repr, name: Option<&str>, sizing: bool) -> Type {
429442
match *r {
430443
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, .. } => {
439446
match name {
440447
None => {
441448
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> {
507514
pub fn trans_switch(bcx: &Block, r: &Repr, scrutinee: ValueRef)
508515
-> (_match::branch_kind, Option<ValueRef>) {
509516
match *r {
510-
CEnum(..) | General(..) => {
517+
CEnum(..) | General(..) |
518+
RawNullablePointer { .. } | StructWrappedNullablePointer { .. } => {
511519
(_match::switch, Some(trans_get_discr(bcx, r, scrutinee, None)))
512520
}
513-
NullablePointer { nonnull: ref nonnull, nndiscr, ptrfield, .. } => {
514-
(_match::switch, Some(nullable_bitdiscr(bcx, nonnull, nndiscr, ptrfield, scrutinee)))
515-
}
516521
Univariant(..) => {
517522
(_match::single, None)
518523
}
@@ -540,8 +545,14 @@ pub fn trans_get_discr(bcx: &Block, r: &Repr, scrutinee: ValueRef, cast_to: Opti
540545
val = C_u8(bcx.ccx(), 0);
541546
signed = false;
542547
}
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);
545556
signed = false;
546557
}
547558
}
@@ -551,13 +562,9 @@ pub fn trans_get_discr(bcx: &Block, r: &Repr, scrutinee: ValueRef, cast_to: Opti
551562
}
552563
}
553564

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]));
561568
let cmp = if nndiscr == 0 { IntEQ } else { IntNE };
562569
let llptrty = type_of::type_of(bcx.ccx(), *nonnull.fields.get(ptrfield));
563570
ICmp(bcx, cmp, llptr, C_null(llptrty))
@@ -606,7 +613,8 @@ pub fn trans_case<'a>(bcx: &'a Block<'a>, r: &Repr, discr: Disr)
606613
Univariant(..) => {
607614
bcx.ccx().sess().bug("no cases for univariants or structs")
608615
}
609-
NullablePointer { .. } => {
616+
RawNullablePointer { .. } |
617+
StructWrappedNullablePointer { .. } => {
610618
assert!(discr == 0 || discr == 1);
611619
_match::single_result(Result::new(bcx, C_i1(bcx.ccx(), discr != 0)))
612620
}
@@ -637,13 +645,15 @@ pub fn trans_start_init(bcx: &Block, r: &Repr, val: ValueRef, discr: Disr) {
637645
Univariant(..) => {
638646
assert_eq!(discr, 0);
639647
}
640-
NullablePointer { nonnull: ref nonnull, nndiscr, ptrfield, .. } => {
648+
RawNullablePointer { nndiscr, nnty, ..} => {
641649
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]);
647657
let llptrty = type_of::type_of(bcx.ccx(),
648658
*nonnull.fields.get(ptrfield));
649659
Store(bcx, C_null(llptrty), llptrptr)
@@ -671,8 +681,11 @@ pub fn num_args(r: &Repr, discr: Disr) -> uint {
671681
st.fields.len() - (if dtor { 1 } else { 0 })
672682
}
673683
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, .. } => {
676689
if discr == nndiscr { nonnull.fields.len() } else { nullfields.len() }
677690
}
678691
}
@@ -695,24 +708,25 @@ pub fn trans_field_ptr(bcx: &Block, r: &Repr, val: ValueRef, discr: Disr,
695708
General(_, ref cases) => {
696709
struct_field_ptr(bcx, cases.get(discr as uint), val, ix + 1, true)
697710
}
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)
716730
}
717731
}
718732
}
@@ -784,15 +798,15 @@ pub fn trans_const(ccx: &CrateContext, r: &Repr, discr: Disr,
784798
let contents = build_const_struct(ccx, st, vals);
785799
C_struct(ccx, contents.as_slice(), st.packed)
786800
}
787-
NullablePointer { nonnull: ref st, nndiscr, .. } if st.fields.len() == 1 => {
801+
RawNullablePointer { nndiscr, nnty, .. } => {
788802
if discr == nndiscr {
789803
assert_eq!(vals.len(), 1);
790804
vals[0]
791805
} else {
792-
C_null(type_of::sizing_type_of(ccx, *st.fields.get(0)))
806+
C_null(type_of::sizing_type_of(ccx, nnty))
793807
}
794808
}
795-
NullablePointer { nonnull: ref nonnull, nndiscr, .. } => {
809+
StructWrappedNullablePointer { nonnull: ref nonnull, nndiscr, .. } => {
796810
if discr == nndiscr {
797811
C_struct(ccx, build_const_struct(ccx,
798812
nonnull,
@@ -900,15 +914,15 @@ pub fn const_get_discrim(ccx: &CrateContext, r: &Repr, val: ValueRef)
900914
}
901915
}
902916
Univariant(..) => 0,
903-
NullablePointer { nonnull: ref st, nndiscr, .. } if st.fields.len() == 1 => {
917+
RawNullablePointer { nndiscr, .. } => {
904918
if is_null(val) {
905919
/* subtraction as uint is ok because nndiscr is either 0 or 1 */
906920
(1 - nndiscr) as Disr
907921
} else {
908922
nndiscr
909923
}
910924
}
911-
NullablePointer { nndiscr, ptrfield, .. } => {
925+
StructWrappedNullablePointer { nndiscr, ptrfield, .. } => {
912926
if is_null(const_struct_field(ccx, val, ptrfield)) {
913927
/* subtraction as uint is ok because nndiscr is either 0 or 1 */
914928
(1 - nndiscr) as Disr
@@ -932,11 +946,11 @@ pub fn const_get_field(ccx: &CrateContext, r: &Repr, val: ValueRef,
932946
CEnum(..) => ccx.sess().bug("element access in C-like enum const"),
933947
Univariant(..) => const_struct_field(ccx, val, ix),
934948
General(..) => const_struct_field(ccx, val, ix + 1),
935-
NullablePointer { nonnull: ref st, .. } if st.fields.len() == 1 => {
949+
RawNullablePointer { .. } => {
936950
assert_eq!(ix, 0);
937951
val
938952
}
939-
NullablePointer{ .. } => const_struct_field(ccx, val, ix)
953+
StructWrappedNullablePointer{ .. } => const_struct_field(ccx, val, ix)
940954
}
941955
}
942956

src/librustc/middle/trans/debuginfo.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -1657,7 +1657,10 @@ fn prepare_enum_metadata(cx: &CrateContext,
16571657
}),
16581658
}
16591659
}
1660-
adt::NullablePointer { nonnull: ref struct_def, nndiscr, .. } => {
1660+
adt::RawNullablePointer { nnty, .. } => {
1661+
FinalMetadata(type_metadata(cx, nnty, span))
1662+
}
1663+
adt::StructWrappedNullablePointer { nonnull: ref struct_def, nndiscr, .. } => {
16611664
let (metadata_stub,
16621665
variant_llvm_type,
16631666
member_description_factory) =

0 commit comments

Comments
 (0)