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