Skip to content

Commit ce24ebb

Browse files
committed
auto merge of #5314 : jld/rust/adt-simplification, r=pcwalton
Struct and enum representations have some complicatedness that's no longer needed. Now that everything's in one place and has access to anything we'd want to know about the type, flatten some of that out. Slight changes to representations in some cases.
2 parents 2ebb674 + 9eaa608 commit ce24ebb

File tree

1 file changed

+40
-77
lines changed
  • src/librustc/middle/trans

1 file changed

+40
-77
lines changed

src/librustc/middle/trans/adt.rs

+40-77
Original file line numberDiff line numberDiff line change
@@ -71,18 +71,16 @@ use util::ppaux::ty_to_str;
7171

7272
/// Representations.
7373
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),
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.
10894
struct 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] {
204190
fn 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)
247227
pub 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
*/
302281
pub 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
*/
328305
pub 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.
377353
pub 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 {
407383
pub 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 }
489456
pub 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)
506472
pub 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?
543507
pub 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

Comments
 (0)