Even more comments for ADT-related interfaces

This commit is contained in:
Jed Davis 2013-03-02 14:03:41 -08:00
parent 6840b48074
commit e13111fc5a
2 changed files with 46 additions and 6 deletions

View File

@ -394,9 +394,20 @@ pub fn trans_drop_flag_ptr(bcx: block, r: &Repr, val: ValueRef) -> ValueRef {
* alignment!) from the representation's `type_of`, so it needs a * alignment!) from the representation's `type_of`, so it needs a
* pointer cast before use. * pointer cast before use.
* *
* Currently it has the same size as the type, but this may be changed * The LLVM type system does not directly support unions, and only
* in the future to avoid allocating unnecessary space after values of * pointers can be bitcast, so a constant (and, by extension, the
* shorter-than-maximum cases. * GlobalVariable initialized by it) will have a type that can vary
* depending on which case of an enum it is.
*
* To understand the alignment situation, consider `enum E { V64(u64),
* V32(u32, u32) }` on win32. The type should have 8-byte alignment
* to accommodate the u64 (currently it doesn't; this is a known bug),
* but `V32(x, y)` would have LLVM type `{i32, i32, i32}`, which is
* 4-byte aligned.
*
* Currently the returned value has the same size as the type, but
* this may be changed in the future to avoid allocating unnecessary
* space after values of shorter-than-maximum cases.
*/ */
pub fn trans_const(ccx: @CrateContext, r: &Repr, discr: int, pub fn trans_const(ccx: @CrateContext, r: &Repr, discr: int,
vals: &[ValueRef]) -> ValueRef { vals: &[ValueRef]) -> ValueRef {
@ -424,6 +435,9 @@ pub fn trans_const(ccx: @CrateContext, r: &Repr, discr: int,
let max_sz = cases.map(|s| s.size).max(); let max_sz = cases.map(|s| s.size).max();
let body = build_const_struct(ccx, case, vals); let body = build_const_struct(ccx, case, vals);
// The unary packed struct has alignment 1 regardless of
// its contents, so it will always be located at the
// expected offset at runtime.
C_struct([C_int(ccx, discr), C_struct([C_int(ccx, discr),
C_packed_struct([C_struct(body)]), C_packed_struct([C_struct(body)]),
padding(max_sz - case.size)]) padding(max_sz - case.size)])
@ -434,6 +448,12 @@ pub fn trans_const(ccx: @CrateContext, r: &Repr, discr: int,
/** /**
* Building structs is a little complicated, because we might need to * Building structs is a little complicated, because we might need to
* insert padding if a field's value is less aligned than its type. * insert padding if a field's value is less aligned than its type.
*
* Continuing the example from `trans_const`, a value of type `(u32,
* E)` should have the `E` at offset 8, but if that field's
* initializer is 4-byte aligned then simply translating the tuple as
* a two-element struct will locate it at offset 4, and accesses to it
* will read the wrong memory.
*/ */
fn build_const_struct(ccx: @CrateContext, st: &Struct, vals: &[ValueRef]) fn build_const_struct(ccx: @CrateContext, st: &Struct, vals: &[ValueRef])
-> ~[ValueRef] { -> ~[ValueRef] {

View File

@ -1158,9 +1158,9 @@ fn trans_rec_or_struct(bcx: block,
let mut need_base = vec::from_elem(field_tys.len(), true); let mut need_base = vec::from_elem(field_tys.len(), true);
let numbered_fields = do fields.map |field| { let numbered_fields = do fields.map |field| {
match do vec::position(field_tys) |field_ty| { let opt_pos = vec::position(field_tys, |field_ty|
field_ty.ident == field.node.ident field_ty.ident == field.node.ident);
} { match opt_pos {
Some(i) => { Some(i) => {
need_base[i] = false; need_base[i] = false;
(i, field.node.expr) (i, field.node.expr)
@ -1196,11 +1196,31 @@ fn trans_rec_or_struct(bcx: block,
} }
} }
/**
* Information that `trans_adt` needs in order to fill in the fields
* of a struct copied from a base struct (e.g., from an expression
* like `Foo { a: b, ..base }`.
*
* Note that `fields` may be empty; the base expression must always be
* evaluated for side-effects.
*/
struct StructBaseInfo { struct StructBaseInfo {
/// The base expression; will be evaluated after all explicit fields.
expr: @ast::expr, expr: @ast::expr,
/// The indices of fields to copy paired with their types.
fields: ~[(uint, ty::t)] fields: ~[(uint, ty::t)]
} }
/**
* Constructs an ADT instance:
*
* - `fields` should be a list of field indices paired with the
* expression to store into that field. The initializers will be
* evaluated in the order specified by `fields`.
*
* - `optbase` contains information on the base struct (if any) from
* which remaining fields are copied; see comments on `StructBaseInfo`.
*/
fn trans_adt(bcx: block, repr: &adt::Repr, discr: int, fn trans_adt(bcx: block, repr: &adt::Repr, discr: int,
fields: &[(uint, @ast::expr)], fields: &[(uint, @ast::expr)],
optbase: Option<StructBaseInfo>, optbase: Option<StructBaseInfo>,