@@ -71,18 +71,16 @@ use util::ppaux::ty_to_str;
7171
7272/// Representations.
7373pub enum Repr {
74- /**
75- * `Unit` exists only so that an enum with a single C-like variant
76- * can occupy no space, for ABI compatibility with rustc from
77- * before (and during) the creation of this module. It may not be
78- * worth keeping around; `CEnum` and `Univariant` cover it
79- * overwise.
80- */
81- Unit ( int ) ,
8274 /// C-like enums; basically an int.
8375 CEnum ( int , int ) , // discriminant range
84- /// Single-case variants, and structs/tuples/records.
85- Univariant ( Struct , Destructor ) ,
76+ /**
77+ * Single-case variants, and structs/tuples/records.
78+ *
79+ * Structs with destructors need a dynamic destroyedness flag to
80+ * avoid running the destructor too many times; this is included
81+ * in the `Struct` if present.
82+ */
83+ Univariant ( Struct , bool ) ,
8684 /**
8785 * General-case enums: discriminant as int, followed by fields.
8886 * The fields start immediately after the discriminant, meaning
@@ -92,18 +90,6 @@ pub enum Repr {
9290 General ( ~[ Struct ] )
9391}
9492
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-
10793/// For structs, and struct-like parts of anything fancier.
10894struct Struct {
10995 size : u64 ,
@@ -129,14 +115,17 @@ pub fn represent_type(cx: @CrateContext, t: ty::t) -> @Repr {
129115 }
130116 let repr = @match ty:: get ( t) . sty {
131117 ty:: ty_tup( ref elems) => {
132- Univariant ( mk_struct ( cx, * elems) , NonStruct )
118+ Univariant ( mk_struct ( cx, * elems) , false )
133119 }
134120 ty:: ty_struct( def_id, ref substs) => {
135121 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| {
122+ let ftys = do fields. map |field| {
138123 ty:: lookup_field_type ( cx. tcx , def_id, field. id , substs)
139- } ) ) , if dt { StructWithDtor } else { StructWithoutDtor } )
124+ } ;
125+ let dtor = ty:: ty_dtor ( cx. tcx , def_id) . is_present ( ) ;
126+ let ftys =
127+ if dtor { ftys + [ ty:: mk_bool ( cx. tcx ) ] } else { ftys } ;
128+ Univariant ( mk_struct ( cx, ftys) , dtor)
140129 }
141130 ty:: ty_enum( def_id, ref substs) => {
142131 struct Case { discr : int , tys : ~[ ty:: t ] } ;
@@ -149,18 +138,15 @@ pub fn represent_type(cx: @CrateContext, t: ty::t) -> @Repr {
149138 } ;
150139 if cases. len ( ) == 0 {
151140 // Uninhabitable; represent as unit
152- Unit ( 0 )
153- } else if cases. len ( ) == 1 && cases[ 0 ] . tys . len ( ) == 0 {
154- // `()`-like; see comment on definition of `Unit`.
155- Unit ( cases[ 0 ] . discr )
156- } else if cases. len ( ) == 1 {
157- // Equivalent to a struct/tuple/newtype.
158- fail_unless ! ( cases[ 0 ] . discr == 0 ) ;
159- Univariant ( mk_struct ( cx, cases[ 0 ] . tys ) , NonStruct )
141+ Univariant ( mk_struct ( cx, ~[ ] ) , false )
160142 } else if cases. all ( |c| c. tys . len ( ) == 0 ) {
161143 // All bodies empty -> intlike
162144 let discrs = cases. map ( |c| c. discr ) ;
163145 CEnum ( discrs. min ( ) , discrs. max ( ) )
146+ } else if cases. len ( ) == 1 {
147+ // Equivalent to a struct/tuple/newtype.
148+ fail_unless ! ( cases[ 0 ] . discr == 0 ) ;
149+ Univariant ( mk_struct ( cx, cases[ 0 ] . tys ) , false )
164150 } else {
165151 // The general case. Since there's at least one
166152 // non-empty body, explicit discriminants should have
@@ -204,18 +190,12 @@ pub fn sizing_fields_of(cx: @CrateContext, r: &Repr) -> ~[TypeRef] {
204190fn generic_fields_of ( cx : @CrateContext , r : & Repr , sizing : bool )
205191 -> ~[ TypeRef ] {
206192 match * r {
207- Unit ( * ) => ~[ ] ,
208193 CEnum ( * ) => ~[ T_enum_discrim ( cx) ] ,
209- Univariant ( ref st, dt ) => {
210- let f = if sizing {
194+ Univariant ( ref st, _dtor ) => {
195+ if sizing {
211196 st. fields . map ( |& ty| type_of:: sizing_type_of ( cx, ty) )
212197 } else {
213198 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 ( ) ]
219199 }
220200 }
221201 General ( ref sts) => {
@@ -237,7 +217,7 @@ pub fn trans_switch(bcx: block, r: &Repr, scrutinee: ValueRef)
237217 CEnum ( * ) | General ( * ) => {
238218 ( _match:: switch, Some ( trans_get_discr ( bcx, r, scrutinee) ) )
239219 }
240- Unit ( * ) | Univariant ( * ) => {
220+ Univariant ( * ) => {
241221 ( _match:: single, None )
242222 }
243223 }
@@ -247,7 +227,6 @@ pub fn trans_switch(bcx: block, r: &Repr, scrutinee: ValueRef)
247227pub fn trans_get_discr ( bcx : block , r : & Repr , scrutinee : ValueRef )
248228 -> ValueRef {
249229 match * r {
250- Unit ( the_disc) => C_int ( bcx. ccx ( ) , the_disc) ,
251230 CEnum ( min, max) => load_discr ( bcx, scrutinee, min, max) ,
252231 Univariant ( * ) => C_int ( bcx. ccx ( ) , 0 ) ,
253232 General ( ref cases) => load_discr ( bcx, scrutinee, 0 ,
@@ -285,7 +264,7 @@ pub fn trans_case(bcx: block, r: &Repr, discr: int) -> _match::opt_result {
285264 CEnum ( * ) => {
286265 _match:: single_result ( rslt ( bcx, C_int ( bcx. ccx ( ) , discr) ) )
287266 }
288- Unit ( * ) | Univariant ( * ) => {
267+ Univariant ( * ) => {
289268 bcx. ccx ( ) . sess . bug ( ~"no cases for univariants or structs")
290269 }
291270 General ( * ) => {
@@ -301,16 +280,14 @@ pub fn trans_case(bcx: block, r: &Repr, discr: int) -> _match::opt_result {
301280 */
302281pub fn trans_start_init ( bcx : block , r : & Repr , val : ValueRef , discr : int ) {
303282 match * r {
304- Unit ( the_discr) => {
305- fail_unless ! ( discr == the_discr) ;
306- }
307283 CEnum ( min, max) => {
308284 fail_unless ! ( min <= discr && discr <= max) ;
309285 Store ( bcx, C_int ( bcx. ccx ( ) , discr) , GEPi ( bcx, val, [ 0 , 0 ] ) )
310286 }
311- Univariant ( _ , StructWithDtor ) => {
287+ Univariant ( ref st , true ) => {
312288 fail_unless ! ( discr == 0 ) ;
313- Store ( bcx, C_u8 ( 1 ) , GEPi ( bcx, val, [ 0 , 1 ] ) )
289+ Store ( bcx, C_bool ( true ) ,
290+ GEPi ( bcx, val, [ 0 , st. fields . len ( ) - 1 ] ) )
314291 }
315292 Univariant ( * ) => {
316293 fail_unless ! ( discr == 0 ) ;
@@ -327,8 +304,11 @@ pub fn trans_start_init(bcx: block, r: &Repr, val: ValueRef, discr: int) {
327304 */
328305pub fn num_args ( r : & Repr , discr : int ) -> uint {
329306 match * r {
330- Unit ( * ) | CEnum ( * ) => 0 ,
331- Univariant ( ref st, _) => { fail_unless ! ( discr == 0 ) ; st. fields . len ( ) }
307+ CEnum ( * ) => 0 ,
308+ Univariant ( ref st, dtor) => {
309+ fail_unless ! ( discr == 0 ) ;
310+ st. fields . len ( ) - ( if dtor { 1 } else { 0 } )
311+ }
332312 General ( ref cases) => cases[ discr as uint ] . fields . len ( )
333313 }
334314}
@@ -340,15 +320,11 @@ pub fn trans_field_ptr(bcx: block, r: &Repr, val: ValueRef, discr: int,
340320 // decide to do some kind of cdr-coding-like non-unique repr
341321 // someday), it will need to return a possibly-new bcx as well.
342322 match * r {
343- Unit ( * ) | CEnum ( * ) => {
323+ CEnum ( * ) => {
344324 bcx. ccx ( ) . sess . bug ( ~"element access in C -like enum")
345325 }
346- Univariant ( ref st, dt ) => {
326+ Univariant ( ref st, _dtor ) => {
347327 fail_unless ! ( discr == 0 ) ;
348- let val = match dt {
349- NonStruct => val,
350- StructWithDtor | StructWithoutDtor => GEPi ( bcx, val, [ 0 , 0 ] )
351- } ;
352328 struct_field_ptr ( bcx, st, val, ix, false )
353329 }
354330 General ( ref cases) => {
@@ -376,7 +352,7 @@ fn struct_field_ptr(bcx: block, st: &Struct, val: ValueRef, ix: uint,
376352/// Access the struct drop flag, if present.
377353pub fn trans_drop_flag_ptr ( bcx : block , r : & Repr , val : ValueRef ) -> ValueRef {
378354 match * r {
379- Univariant ( _ , StructWithDtor ) => GEPi ( bcx, val, [ 0 , 1 ] ) ,
355+ Univariant ( ref st , true ) => GEPi ( bcx, val, [ 0 , st . fields . len ( ) - 1 ] ) ,
380356 _ => bcx. ccx ( ) . sess . bug ( ~"tried to get drop flag of non-droppable \
381357 type ")
382358 }
@@ -407,23 +383,14 @@ pub fn trans_drop_flag_ptr(bcx: block, r: &Repr, val: ValueRef) -> ValueRef {
407383pub fn trans_const ( ccx : @CrateContext , r : & Repr , discr : int ,
408384 vals : & [ ValueRef ] ) -> ValueRef {
409385 match * r {
410- Unit ( * ) => {
411- C_struct ( ~[ ] )
412- }
413386 CEnum ( min, max) => {
414387 fail_unless ! ( vals. len( ) == 0 ) ;
415388 fail_unless ! ( min <= discr && discr <= max) ;
416389 C_int ( ccx, discr)
417390 }
418- Univariant ( ref st, dt ) => {
391+ Univariant ( ref st, _dro ) => {
419392 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- }
393+ C_struct ( build_const_struct ( ccx, st, vals) )
427394 }
428395 General ( ref cases) => {
429396 let case = & cases[ discr as uint ] ;
@@ -489,7 +456,6 @@ fn roundup(x: u64, a: u64) -> u64 { ((x + (a - 1)) / a) * a }
489456pub fn const_get_discrim ( ccx : @CrateContext , r : & Repr , val : ValueRef )
490457 -> int {
491458 match * r {
492- Unit ( discr) => discr,
493459 CEnum ( * ) => const_to_int ( val) as int ,
494460 Univariant ( * ) => 0 ,
495461 General ( * ) => const_to_int ( const_get_elt ( ccx, val, [ 0 ] ) ) as int ,
@@ -506,11 +472,9 @@ pub fn const_get_discrim(ccx: @CrateContext, r: &Repr, val: ValueRef)
506472pub fn const_get_field( ccx : @CrateContext , r : & Repr , val : ValueRef ,
507473 _discr : int , ix : uint ) -> ValueRef {
508474 match * r {
509- Unit ( * ) | CEnum ( * ) => ccx. sess . bug ( ~"element access in C -like enum \
475+ CEnum ( * ) => ccx. sess . bug ( ~"element access in C -like enum \
510476 const ") ,
511- Univariant ( _, NonStruct ) => const_struct_field ( ccx, val, ix) ,
512- Univariant ( * ) => const_struct_field ( ccx, const_get_elt ( ccx, val,
513- [ 0 ] ) , ix) ,
477+ Univariant ( * ) => const_struct_field ( ccx, val, ix) ,
514478 General ( * ) => const_struct_field ( ccx, const_get_elt ( ccx, val,
515479 [ 1 , 0 ] ) , ix)
516480 }
@@ -542,8 +506,7 @@ fn const_struct_field(ccx: @CrateContext, val: ValueRef, ix: uint)
542506/// Is it safe to bitcast a value to the one field of its one variant?
543507pub fn is_newtypeish( r: & Repr ) -> bool {
544508 match * r {
545- Univariant ( ref st, StructWithoutDtor )
546- | Univariant ( ref st, NonStruct ) => st. fields . len ( ) == 1 ,
509+ Univariant ( ref st, false ) => st. fields . len ( ) == 1 ,
547510 _ => false
548511 }
549512}
0 commit comments