From ffac0b02e75c9c620df11201ee70965856ba9ebf Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 27 Aug 2019 10:14:11 -0400 Subject: [PATCH] implement and test struct field explicit alignment --- src/analyze.cpp | 6 +++--- src/ir.cpp | 7 ++++--- test/stage1/behavior/align.zig | 15 +++++++++++++++ 3 files changed, 22 insertions(+), 6 deletions(-) diff --git a/src/analyze.cpp b/src/analyze.cpp index f1df64b17..247788b94 100644 --- a/src/analyze.cpp +++ b/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; } } diff --git a/src/ir.cpp b/src/ir.cpp index d98521de8..be0fd1ba6 100644 --- a/src/ir.cpp +++ b/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)) { diff --git a/test/stage1/behavior/align.zig b/test/stage1/behavior/align.zig index f607ac59d..677ae85b6 100644 --- a/test/stage1/behavior/align.zig +++ b/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); +}