Commit ffac0b02e7

Andrew Kelley <andrew@ziglang.org>
2019-08-27 16:14:11
implement and test struct field explicit alignment
1 parent a2e8ef7
Changed files (3)
src
test
stage1
behavior
src/analyze.cpp
@@ -1896,9 +1896,9 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) {
                     break;
                 }
             }
-            size_t next_abi_align = (next_src_field_index == field_count) ?
-                abi_align : struct_type->data.structure.fields[next_src_field_index].type_entry->abi_align;
-            next_offset = next_field_offset(next_offset, abi_align, field_type->abi_size, next_abi_align);
+            size_t next_align = (next_src_field_index == field_count) ?
+                abi_align : struct_type->data.structure.fields[next_src_field_index].align;
+            next_offset = next_field_offset(next_offset, abi_align, field_type->abi_size, next_align);
             size_in_bits = next_offset * 8;
         }
     }
src/ir.cpp
@@ -17127,6 +17127,7 @@ static IrInstruction *ir_analyze_container_member_access_inner(IrAnalyze *ira,
 static IrInstruction *ir_analyze_struct_field_ptr(IrAnalyze *ira, IrInstruction *source_instr,
         TypeStructField *field, IrInstruction *struct_ptr, ZigType *struct_type, bool initializing)
 {
+    Error err;
     switch (type_has_one_possible_value(ira->codegen, field->type_entry)) {
         case OnePossibleValueInvalid:
             return ira->codegen->invalid_instruction;
@@ -17137,9 +17138,9 @@ static IrInstruction *ir_analyze_struct_field_ptr(IrAnalyze *ira, IrInstruction
         case OnePossibleValueNo:
             break;
     }
+    if ((err = type_resolve(ira->codegen, struct_type, ResolveStatusAlignmentKnown)))
+        return ira->codegen->invalid_instruction;
     assert(struct_ptr->value.type->id == ZigTypeIdPointer);
-    bool is_packed = (struct_type->data.structure.layout == ContainerLayoutPacked);
-    uint32_t align_bytes = is_packed ? 1 : get_abi_alignment(ira->codegen, field->type_entry);
     uint32_t ptr_bit_offset = struct_ptr->value.type->data.pointer.bit_offset_in_host;
     uint32_t ptr_host_int_bytes = struct_ptr->value.type->data.pointer.host_int_bytes;
     uint32_t host_int_bytes_for_result_type = (ptr_host_int_bytes == 0) ?
@@ -17147,7 +17148,7 @@ static IrInstruction *ir_analyze_struct_field_ptr(IrAnalyze *ira, IrInstruction
     bool is_const = struct_ptr->value.type->data.pointer.is_const;
     bool is_volatile = struct_ptr->value.type->data.pointer.is_volatile;
     ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, field->type_entry,
-            is_const, is_volatile, PtrLenSingle, align_bytes,
+            is_const, is_volatile, PtrLenSingle, field->align,
             (uint32_t)(ptr_bit_offset + field->bit_offset_in_host),
             (uint32_t)host_int_bytes_for_result_type, false);
     if (instr_is_comptime(struct_ptr)) {
test/stage1/behavior/align.zig
@@ -290,3 +290,18 @@ test "read 128-bit field from default aligned struct in global memory" {
     expect((@ptrToInt(&default_aligned_global.badguy) % 16) == 0);
     expect(12 == default_aligned_global.badguy);
 }
+
+test "struct field explicit alignment" {
+    const S = struct {
+        const Node = struct {
+            next: *Node,
+            massive_byte: u8 align(64),
+        };
+    };
+
+    var node: S.Node = undefined;
+    node.massive_byte = 100;
+    expect(node.massive_byte == 100);
+    comptime expect(@typeOf(&node.massive_byte) == *align(64) u8);
+    expect(@ptrToInt(&node.massive_byte) % 64 == 0);
+}