Even more comments for ADT-related interfaces
This commit is contained in:
parent
6840b48074
commit
e13111fc5a
@ -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] {
|
||||||
|
@ -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>,
|
||||||
|
Loading…
Reference in New Issue
Block a user