@@ -71,18 +71,16 @@ use util::ppaux::ty_to_str;
71
71
72
72
/// Representations.
73
73
pub 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 ) ,
82
74
/// C-like enums; basically an int.
83
75
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 ) ,
86
84
/**
87
85
* General-case enums: discriminant as int, followed by fields.
88
86
* The fields start immediately after the discriminant, meaning
@@ -92,18 +90,6 @@ pub enum Repr {
92
90
General ( ~[ Struct ] )
93
91
}
94
92
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
93
/// For structs, and struct-like parts of anything fancier.
108
94
struct Struct {
109
95
size : u64 ,
@@ -129,14 +115,17 @@ pub fn represent_type(cx: @CrateContext, t: ty::t) -> @Repr {
129
115
}
130
116
let repr = @match ty:: get ( t) . sty {
131
117
ty:: ty_tup( ref elems) => {
132
- Univariant ( mk_struct ( cx, * elems) , NonStruct )
118
+ Univariant ( mk_struct ( cx, * elems) , false )
133
119
}
134
120
ty:: ty_struct( def_id, ref substs) => {
135
121
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| {
138
123
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)
140
129
}
141
130
ty:: ty_enum( def_id, ref substs) => {
142
131
struct Case { discr : int , tys : ~[ ty:: t ] } ;
@@ -149,18 +138,15 @@ pub fn represent_type(cx: @CrateContext, t: ty::t) -> @Repr {
149
138
} ;
150
139
if cases. len ( ) == 0 {
151
140
// 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 )
160
142
} else if cases. all ( |c| c. tys . len ( ) == 0 ) {
161
143
// All bodies empty -> intlike
162
144
let discrs = cases. map ( |c| c. discr ) ;
163
145
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 )
164
150
} else {
165
151
// The general case. Since there's at least one
166
152
// non-empty body, explicit discriminants should have
@@ -204,18 +190,12 @@ pub fn sizing_fields_of(cx: @CrateContext, r: &Repr) -> ~[TypeRef] {
204
190
fn generic_fields_of ( cx : @CrateContext , r : & Repr , sizing : bool )
205
191
-> ~[ TypeRef ] {
206
192
match * r {
207
- Unit ( * ) => ~[ ] ,
208
193
CEnum ( * ) => ~[ T_enum_discrim ( cx) ] ,
209
- Univariant ( ref st, dt ) => {
210
- let f = if sizing {
194
+ Univariant ( ref st, _dtor ) => {
195
+ if sizing {
211
196
st. fields . map ( |& ty| type_of:: sizing_type_of ( cx, ty) )
212
197
} else {
213
198
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
199
}
220
200
}
221
201
General ( ref sts) => {
@@ -237,7 +217,7 @@ pub fn trans_switch(bcx: block, r: &Repr, scrutinee: ValueRef)
237
217
CEnum ( * ) | General ( * ) => {
238
218
( _match:: switch, Some ( trans_get_discr ( bcx, r, scrutinee) ) )
239
219
}
240
- Unit ( * ) | Univariant ( * ) => {
220
+ Univariant ( * ) => {
241
221
( _match:: single, None )
242
222
}
243
223
}
@@ -247,7 +227,6 @@ pub fn trans_switch(bcx: block, r: &Repr, scrutinee: ValueRef)
247
227
pub fn trans_get_discr ( bcx : block , r : & Repr , scrutinee : ValueRef )
248
228
-> ValueRef {
249
229
match * r {
250
- Unit ( the_disc) => C_int ( bcx. ccx ( ) , the_disc) ,
251
230
CEnum ( min, max) => load_discr ( bcx, scrutinee, min, max) ,
252
231
Univariant ( * ) => C_int ( bcx. ccx ( ) , 0 ) ,
253
232
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 {
285
264
CEnum ( * ) => {
286
265
_match:: single_result ( rslt ( bcx, C_int ( bcx. ccx ( ) , discr) ) )
287
266
}
288
- Unit ( * ) | Univariant ( * ) => {
267
+ Univariant ( * ) => {
289
268
bcx. ccx ( ) . sess . bug ( ~"no cases for univariants or structs")
290
269
}
291
270
General ( * ) => {
@@ -301,16 +280,14 @@ pub fn trans_case(bcx: block, r: &Repr, discr: int) -> _match::opt_result {
301
280
*/
302
281
pub fn trans_start_init ( bcx : block , r : & Repr , val : ValueRef , discr : int ) {
303
282
match * r {
304
- Unit ( the_discr) => {
305
- fail_unless ! ( discr == the_discr) ;
306
- }
307
283
CEnum ( min, max) => {
308
284
fail_unless ! ( min <= discr && discr <= max) ;
309
285
Store ( bcx, C_int ( bcx. ccx ( ) , discr) , GEPi ( bcx, val, [ 0 , 0 ] ) )
310
286
}
311
- Univariant ( _ , StructWithDtor ) => {
287
+ Univariant ( ref st , true ) => {
312
288
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 ] ) )
314
291
}
315
292
Univariant ( * ) => {
316
293
fail_unless ! ( discr == 0 ) ;
@@ -327,8 +304,11 @@ pub fn trans_start_init(bcx: block, r: &Repr, val: ValueRef, discr: int) {
327
304
*/
328
305
pub fn num_args ( r : & Repr , discr : int ) -> uint {
329
306
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
+ }
332
312
General ( ref cases) => cases[ discr as uint ] . fields . len ( )
333
313
}
334
314
}
@@ -340,15 +320,11 @@ pub fn trans_field_ptr(bcx: block, r: &Repr, val: ValueRef, discr: int,
340
320
// decide to do some kind of cdr-coding-like non-unique repr
341
321
// someday), it will need to return a possibly-new bcx as well.
342
322
match * r {
343
- Unit ( * ) | CEnum ( * ) => {
323
+ CEnum ( * ) => {
344
324
bcx. ccx ( ) . sess . bug ( ~"element access in C -like enum")
345
325
}
346
- Univariant ( ref st, dt ) => {
326
+ Univariant ( ref st, _dtor ) => {
347
327
fail_unless ! ( discr == 0 ) ;
348
- let val = match dt {
349
- NonStruct => val,
350
- StructWithDtor | StructWithoutDtor => GEPi ( bcx, val, [ 0 , 0 ] )
351
- } ;
352
328
struct_field_ptr ( bcx, st, val, ix, false )
353
329
}
354
330
General ( ref cases) => {
@@ -376,7 +352,7 @@ fn struct_field_ptr(bcx: block, st: &Struct, val: ValueRef, ix: uint,
376
352
/// Access the struct drop flag, if present.
377
353
pub fn trans_drop_flag_ptr ( bcx : block , r : & Repr , val : ValueRef ) -> ValueRef {
378
354
match * r {
379
- Univariant ( _ , StructWithDtor ) => GEPi ( bcx, val, [ 0 , 1 ] ) ,
355
+ Univariant ( ref st , true ) => GEPi ( bcx, val, [ 0 , st . fields . len ( ) - 1 ] ) ,
380
356
_ => bcx. ccx ( ) . sess . bug ( ~"tried to get drop flag of non-droppable \
381
357
type ")
382
358
}
@@ -407,23 +383,14 @@ pub fn trans_drop_flag_ptr(bcx: block, r: &Repr, val: ValueRef) -> ValueRef {
407
383
pub fn trans_const ( ccx : @CrateContext , r : & Repr , discr : int ,
408
384
vals : & [ ValueRef ] ) -> ValueRef {
409
385
match * r {
410
- Unit ( * ) => {
411
- C_struct ( ~[ ] )
412
- }
413
386
CEnum ( min, max) => {
414
387
fail_unless ! ( vals. len( ) == 0 ) ;
415
388
fail_unless ! ( min <= discr && discr <= max) ;
416
389
C_int ( ccx, discr)
417
390
}
418
- Univariant ( ref st, dt ) => {
391
+ Univariant ( ref st, _dro ) => {
419
392
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) )
427
394
}
428
395
General ( ref cases) => {
429
396
let case = & cases[ discr as uint ] ;
@@ -489,7 +456,6 @@ fn roundup(x: u64, a: u64) -> u64 { ((x + (a - 1)) / a) * a }
489
456
pub fn const_get_discrim ( ccx : @CrateContext , r : & Repr , val : ValueRef )
490
457
-> int {
491
458
match * r {
492
- Unit ( discr) => discr,
493
459
CEnum ( * ) => const_to_int ( val) as int ,
494
460
Univariant ( * ) => 0 ,
495
461
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)
506
472
pub fn const_get_field( ccx : @CrateContext , r : & Repr , val : ValueRef ,
507
473
_discr : int , ix : uint ) -> ValueRef {
508
474
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 \
510
476
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) ,
514
478
General ( * ) => const_struct_field ( ccx, const_get_elt ( ccx, val,
515
479
[ 1 , 0 ] ) , ix)
516
480
}
@@ -542,8 +506,7 @@ fn const_struct_field(ccx: @CrateContext, val: ValueRef, ix: uint)
542
506
/// Is it safe to bitcast a value to the one field of its one variant?
543
507
pub fn is_newtypeish( r: & Repr ) -> bool {
544
508
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 ,
547
510
_ => false
548
511
}
549
512
}
0 commit comments