@@ -81,8 +81,14 @@ pub enum Repr {
81
81
Unit ( int ) ,
82
82
/// C-like enums; basically an int.
83
83
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 ) ,
86
92
/**
87
93
* General-case enums: discriminant as int, followed by fields.
88
94
* The fields start immediately after the discriminant, meaning
@@ -92,18 +98,6 @@ pub enum Repr {
92
98
General ( ~[ Struct ] )
93
99
}
94
100
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
-
107
101
/// For structs, and struct-like parts of anything fancier.
108
102
struct Struct {
109
103
size : u64 ,
@@ -129,14 +123,17 @@ pub fn represent_type(cx: @CrateContext, t: ty::t) -> @Repr {
129
123
}
130
124
let repr = @match ty:: get ( t) . sty {
131
125
ty:: ty_tup( ref elems) => {
132
- Univariant ( mk_struct ( cx, * elems) , NonStruct )
126
+ Univariant ( mk_struct ( cx, * elems) , false )
133
127
}
134
128
ty:: ty_struct( def_id, ref substs) => {
135
129
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| {
138
131
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)
140
137
}
141
138
ty:: ty_enum( def_id, ref substs) => {
142
139
struct Case { discr : int , tys : ~[ ty:: t ] } ;
@@ -156,7 +153,7 @@ pub fn represent_type(cx: @CrateContext, t: ty::t) -> @Repr {
156
153
} else if cases. len ( ) == 1 {
157
154
// Equivalent to a struct/tuple/newtype.
158
155
fail_unless ! ( cases[ 0 ] . discr == 0 ) ;
159
- Univariant ( mk_struct ( cx, cases[ 0 ] . tys ) , NonStruct )
156
+ Univariant ( mk_struct ( cx, cases[ 0 ] . tys ) , false )
160
157
} else if cases. all ( |c| c. tys . len ( ) == 0 ) {
161
158
// All bodies empty -> intlike
162
159
let discrs = cases. map ( |c| c. discr ) ;
@@ -206,16 +203,11 @@ fn generic_fields_of(cx: @CrateContext, r: &Repr, sizing: bool)
206
203
match * r {
207
204
Unit ( * ) => ~[ ] ,
208
205
CEnum ( * ) => ~[ T_enum_discrim ( cx) ] ,
209
- Univariant ( ref st, dt ) => {
210
- let f = if sizing {
206
+ Univariant ( ref st, _dtor ) => {
207
+ if sizing {
211
208
st. fields . map ( |& ty| type_of:: sizing_type_of ( cx, ty) )
212
209
} else {
213
210
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 ( ) ]
219
211
}
220
212
}
221
213
General ( ref sts) => {
@@ -308,9 +300,10 @@ pub fn trans_start_init(bcx: block, r: &Repr, val: ValueRef, discr: int) {
308
300
fail_unless ! ( min <= discr && discr <= max) ;
309
301
Store ( bcx, C_int ( bcx. ccx ( ) , discr) , GEPi ( bcx, val, [ 0 , 0 ] ) )
310
302
}
311
- Univariant ( _ , StructWithDtor ) => {
303
+ Univariant ( ref st , true ) => {
312
304
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 ] ) )
314
307
}
315
308
Univariant ( * ) => {
316
309
fail_unless ! ( discr == 0 ) ;
@@ -328,7 +321,10 @@ pub fn trans_start_init(bcx: block, r: &Repr, val: ValueRef, discr: int) {
328
321
pub fn num_args ( r : & Repr , discr : int ) -> uint {
329
322
match * r {
330
323
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
+ }
332
328
General ( ref cases) => cases[ discr as uint ] . fields . len ( )
333
329
}
334
330
}
@@ -343,12 +339,8 @@ pub fn trans_field_ptr(bcx: block, r: &Repr, val: ValueRef, discr: int,
343
339
Unit ( * ) | CEnum ( * ) => {
344
340
bcx. ccx ( ) . sess . bug ( ~"element access in C -like enum")
345
341
}
346
- Univariant ( ref st, dt ) => {
342
+ Univariant ( ref st, _dtor ) => {
347
343
fail_unless ! ( discr == 0 ) ;
348
- let val = match dt {
349
- NonStruct => val,
350
- StructWithDtor | StructWithoutDtor => GEPi ( bcx, val, [ 0 , 0 ] )
351
- } ;
352
344
struct_field_ptr ( bcx, st, val, ix, false )
353
345
}
354
346
General ( ref cases) => {
@@ -376,7 +368,7 @@ fn struct_field_ptr(bcx: block, st: &Struct, val: ValueRef, ix: uint,
376
368
/// Access the struct drop flag, if present.
377
369
pub fn trans_drop_flag_ptr ( bcx : block , r : & Repr , val : ValueRef ) -> ValueRef {
378
370
match * r {
379
- Univariant ( _ , StructWithDtor ) => GEPi ( bcx, val, [ 0 , 1 ] ) ,
371
+ Univariant ( ref st , true ) => GEPi ( bcx, val, [ 0 , st . fields . len ( ) - 1 ] ) ,
380
372
_ => bcx. ccx ( ) . sess . bug ( ~"tried to get drop flag of non-droppable \
381
373
type ")
382
374
}
@@ -415,15 +407,9 @@ pub fn trans_const(ccx: @CrateContext, r: &Repr, discr: int,
415
407
fail_unless ! ( min <= discr && discr <= max) ;
416
408
C_int ( ccx, discr)
417
409
}
418
- Univariant ( ref st, dt ) => {
410
+ Univariant ( ref st, _dro ) => {
419
411
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) )
427
413
}
428
414
General ( ref cases) => {
429
415
let case = & cases[ discr as uint ] ;
@@ -508,9 +494,7 @@ pub fn const_get_field(ccx: @CrateContext, r: &Repr, val: ValueRef,
508
494
match * r {
509
495
Unit ( * ) | CEnum ( * ) => ccx. sess . bug ( ~"element access in C -like enum \
510
496
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) ,
514
498
General ( * ) => const_struct_field ( ccx, const_get_elt ( ccx, val,
515
499
[ 1 , 0 ] ) , ix)
516
500
}
@@ -542,8 +526,7 @@ fn const_struct_field(ccx: @CrateContext, val: ValueRef, ix: uint)
542
526
/// Is it safe to bitcast a value to the one field of its one variant?
543
527
pub fn is_newtypeish( r: & Repr ) -> bool {
544
528
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 ,
547
530
_ => false
548
531
}
549
532
}
0 commit comments