@@ -81,8 +81,14 @@ pub enum Repr {
8181 Unit ( int ) ,
8282 /// C-like enums; basically an int.
8383 CEnum ( int , int ) , // discriminant range
84- /// Single-case variants, and structs/tuples/records.
85- Univariant ( Struct , Destructor ) ,
84+ /**
85+ * Single-case variants, and structs/tuples/records.
86+ *
87+ * Structs with destructors need a dynamic destroyedness flag to
88+ * avoid running the destructor too many times; this is included
89+ * in the `Struct` if present.
90+ */
91+ Univariant ( Struct , bool ) ,
8692 /**
8793 * General-case enums: discriminant as int, followed by fields.
8894 * The fields start immediately after the discriminant, meaning
@@ -92,18 +98,6 @@ pub enum Repr {
9298 General ( ~[ Struct ] )
9399}
94100
95- /**
96- * Structs without destructors have historically had an extra layer of
97- * LLVM-struct to make accessing them work the same as structs with
98- * destructors. This could probably be flattened to a boolean now
99- * that this module exists.
100- */
101- enum Destructor {
102- StructWithDtor ,
103- StructWithoutDtor ,
104- NonStruct
105- }
106-
107101/// For structs, and struct-like parts of anything fancier.
108102struct Struct {
109103 size : u64 ,
@@ -129,14 +123,17 @@ pub fn represent_type(cx: @CrateContext, t: ty::t) -> @Repr {
129123 }
130124 let repr = @match ty:: get ( t) . sty {
131125 ty:: ty_tup( ref elems) => {
132- Univariant ( mk_struct ( cx, * elems) , NonStruct )
126+ Univariant ( mk_struct ( cx, * elems) , false )
133127 }
134128 ty:: ty_struct( def_id, ref substs) => {
135129 let fields = ty:: lookup_struct_fields ( cx. tcx , def_id) ;
136- let dt = ty:: ty_dtor ( cx. tcx , def_id) . is_present ( ) ;
137- Univariant ( mk_struct ( cx, fields. map ( |field| {
130+ let ftys = do fields. map |field| {
138131 ty:: lookup_field_type ( cx. tcx , def_id, field. id , substs)
139- } ) ) , if dt { StructWithDtor } else { StructWithoutDtor } )
132+ } ;
133+ let dtor = ty:: ty_dtor ( cx. tcx , def_id) . is_present ( ) ;
134+ let ftys =
135+ if dtor { ftys + [ ty:: mk_bool ( cx. tcx ) ] } else { ftys } ;
136+ Univariant ( mk_struct ( cx, ftys) , dtor)
140137 }
141138 ty:: ty_enum( def_id, ref substs) => {
142139 struct Case { discr : int , tys : ~[ ty:: t ] } ;
@@ -156,7 +153,7 @@ pub fn represent_type(cx: @CrateContext, t: ty::t) -> @Repr {
156153 } else if cases. len ( ) == 1 {
157154 // Equivalent to a struct/tuple/newtype.
158155 fail_unless ! ( cases[ 0 ] . discr == 0 ) ;
159- Univariant ( mk_struct ( cx, cases[ 0 ] . tys ) , NonStruct )
156+ Univariant ( mk_struct ( cx, cases[ 0 ] . tys ) , false )
160157 } else if cases. all ( |c| c. tys . len ( ) == 0 ) {
161158 // All bodies empty -> intlike
162159 let discrs = cases. map ( |c| c. discr ) ;
@@ -206,16 +203,11 @@ fn generic_fields_of(cx: @CrateContext, r: &Repr, sizing: bool)
206203 match * r {
207204 Unit ( * ) => ~[ ] ,
208205 CEnum ( * ) => ~[ T_enum_discrim ( cx) ] ,
209- Univariant ( ref st, dt ) => {
210- let f = if sizing {
206+ Univariant ( ref st, _dtor ) => {
207+ if sizing {
211208 st. fields . map ( |& ty| type_of:: sizing_type_of ( cx, ty) )
212209 } else {
213210 st. fields . map ( |& ty| type_of:: type_of ( cx, ty) )
214- } ;
215- match dt {
216- NonStruct => f,
217- StructWithoutDtor => ~[ T_struct ( f) ] ,
218- StructWithDtor => ~[ T_struct ( f) , T_i8 ( ) ]
219211 }
220212 }
221213 General ( ref sts) => {
@@ -308,9 +300,10 @@ pub fn trans_start_init(bcx: block, r: &Repr, val: ValueRef, discr: int) {
308300 fail_unless ! ( min <= discr && discr <= max) ;
309301 Store ( bcx, C_int ( bcx. ccx ( ) , discr) , GEPi ( bcx, val, [ 0 , 0 ] ) )
310302 }
311- Univariant ( _ , StructWithDtor ) => {
303+ Univariant ( ref st , true ) => {
312304 fail_unless ! ( discr == 0 ) ;
313- Store ( bcx, C_u8 ( 1 ) , GEPi ( bcx, val, [ 0 , 1 ] ) )
305+ Store ( bcx, C_bool ( true ) ,
306+ GEPi ( bcx, val, [ 0 , st. fields . len ( ) - 1 ] ) )
314307 }
315308 Univariant ( * ) => {
316309 fail_unless ! ( discr == 0 ) ;
@@ -328,7 +321,10 @@ pub fn trans_start_init(bcx: block, r: &Repr, val: ValueRef, discr: int) {
328321pub fn num_args ( r : & Repr , discr : int ) -> uint {
329322 match * r {
330323 Unit ( * ) | CEnum ( * ) => 0 ,
331- Univariant ( ref st, _) => { fail_unless ! ( discr == 0 ) ; st. fields . len ( ) }
324+ Univariant ( ref st, dtor) => {
325+ fail_unless ! ( discr == 0 ) ;
326+ st. fields . len ( ) - ( if dtor { 1 } else { 0 } )
327+ }
332328 General ( ref cases) => cases[ discr as uint ] . fields . len ( )
333329 }
334330}
@@ -343,12 +339,8 @@ pub fn trans_field_ptr(bcx: block, r: &Repr, val: ValueRef, discr: int,
343339 Unit ( * ) | CEnum ( * ) => {
344340 bcx. ccx ( ) . sess . bug ( ~"element access in C -like enum")
345341 }
346- Univariant ( ref st, dt ) => {
342+ Univariant ( ref st, _dtor ) => {
347343 fail_unless ! ( discr == 0 ) ;
348- let val = match dt {
349- NonStruct => val,
350- StructWithDtor | StructWithoutDtor => GEPi ( bcx, val, [ 0 , 0 ] )
351- } ;
352344 struct_field_ptr ( bcx, st, val, ix, false )
353345 }
354346 General ( ref cases) => {
@@ -376,7 +368,7 @@ fn struct_field_ptr(bcx: block, st: &Struct, val: ValueRef, ix: uint,
376368/// Access the struct drop flag, if present.
377369pub fn trans_drop_flag_ptr ( bcx : block , r : & Repr , val : ValueRef ) -> ValueRef {
378370 match * r {
379- Univariant ( _ , StructWithDtor ) => GEPi ( bcx, val, [ 0 , 1 ] ) ,
371+ Univariant ( ref st , true ) => GEPi ( bcx, val, [ 0 , st . fields . len ( ) - 1 ] ) ,
380372 _ => bcx. ccx ( ) . sess . bug ( ~"tried to get drop flag of non-droppable \
381373 type ")
382374 }
@@ -415,15 +407,9 @@ pub fn trans_const(ccx: @CrateContext, r: &Repr, discr: int,
415407 fail_unless ! ( min <= discr && discr <= max) ;
416408 C_int ( ccx, discr)
417409 }
418- Univariant ( ref st, dt ) => {
410+ Univariant ( ref st, _dro ) => {
419411 fail_unless ! ( discr == 0 ) ;
420- let s = C_struct ( build_const_struct ( ccx, st, vals) ) ;
421- match dt {
422- NonStruct => s,
423- // The actual destructor flag doesn't need to be present.
424- // But add an extra struct layer for compatibility.
425- StructWithDtor | StructWithoutDtor => C_struct ( ~[ s] )
426- }
412+ C_struct ( build_const_struct ( ccx, st, vals) )
427413 }
428414 General ( ref cases) => {
429415 let case = & cases[ discr as uint ] ;
@@ -508,9 +494,7 @@ pub fn const_get_field(ccx: @CrateContext, r: &Repr, val: ValueRef,
508494 match * r {
509495 Unit ( * ) | CEnum ( * ) => ccx. sess . bug ( ~"element access in C -like enum \
510496 const ") ,
511- Univariant ( _, NonStruct ) => const_struct_field ( ccx, val, ix) ,
512- Univariant ( * ) => const_struct_field ( ccx, const_get_elt ( ccx, val,
513- [ 0 ] ) , ix) ,
497+ Univariant ( * ) => const_struct_field ( ccx, val, ix) ,
514498 General ( * ) => const_struct_field ( ccx, const_get_elt ( ccx, val,
515499 [ 1 , 0 ] ) , ix)
516500 }
@@ -542,8 +526,7 @@ fn const_struct_field(ccx: @CrateContext, val: ValueRef, ix: uint)
542526/// Is it safe to bitcast a value to the one field of its one variant?
543527pub fn is_newtypeish( r: & Repr ) -> bool {
544528 match * r {
545- Univariant ( ref st, StructWithoutDtor )
546- | Univariant ( ref st, NonStruct ) => st. fields . len ( ) == 1 ,
529+ Univariant ( ref st, false ) => st. fields . len ( ) == 1 ,
547530 _ => false
548531 }
549532}
0 commit comments