Skip to content

Commit e6b5e00

Browse files
committed
Simplify struct representation.
Out goes the extra layer of struct wrapping; the destructedness flag is added to the end of the struct. This means that, if the struct previously had alignment padding at the end, the flag will live there instead of increasing the struct size.
1 parent 1d8596d commit e6b5e00

File tree

1 file changed

+31
-48
lines changed
  • src/librustc/middle/trans

1 file changed

+31
-48
lines changed

src/librustc/middle/trans/adt.rs

+31-48
Original file line numberDiff line numberDiff line change
@@ -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.
108102
struct 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) {
328321
pub 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.
377369
pub 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?
543527
pub 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

Comments
 (0)