From 5749dc49d839ba607392ed0934008773d33f47d7 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Wed, 14 Aug 2019 00:35:51 -0400 Subject: [PATCH] respect local variable alignment in async functions --- src/all_types.hpp | 1 + src/analyze.cpp | 18 +++++++++++++----- test/stage1/behavior/coroutines.zig | 11 +++++++++++ 3 files changed, 25 insertions(+), 5 deletions(-) diff --git a/src/all_types.hpp b/src/all_types.hpp index 6445c05bf..22e38b9f0 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -1087,6 +1087,7 @@ struct TypeStructField { ConstExprValue *init_val; // null and then memoized uint32_t bit_offset_in_host; // offset from the memory at gen_index uint32_t host_int_bytes; // size of host integer + uint32_t align; }; enum ResolveStatus { diff --git a/src/analyze.cpp b/src/analyze.cpp index 6f3b09806..146f66124 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -1524,10 +1524,11 @@ static ZigType *get_struct_type(CodeGen *g, const char *type_name, SrcField fiel field->name = buf_create_from_str(fields[i].name); field->type_entry = fields[i].ty; field->src_index = i; + field->align = fields[i].align; if (type_has_bits(field->type_entry)) { assert(type_is_resolved(field->type_entry, ResolveStatusSizeKnown)); - unsigned field_abi_align = max(fields[i].align, field->type_entry->abi_align); + unsigned field_abi_align = max(field->align, field->type_entry->abi_align); if (field_abi_align > abi_align) { abi_align = field_abi_align; } @@ -5325,7 +5326,7 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) { } instruction->field_index = fields.length; - fields.append({name, child_type, 0}); + fields.append({name, child_type, instruction->align}); } @@ -6900,9 +6901,16 @@ static void resolve_llvm_types_struct(CodeGen *g, ZigType *struct_type, ResolveS if (type_has_bits(struct_type->data.structure.fields[next_src_field_index].type_entry)) break; } - size_t next_abi_align = (next_src_field_index == field_count) ? - struct_type->abi_align : - struct_type->data.structure.fields[next_src_field_index].type_entry->abi_align; + size_t next_abi_align; + if (next_src_field_index == field_count) { + next_abi_align = struct_type->abi_align; + } else { + if (struct_type->data.structure.fields[next_src_field_index].align == 0) { + next_abi_align = struct_type->data.structure.fields[next_src_field_index].type_entry->abi_align; + } else { + next_abi_align = struct_type->data.structure.fields[next_src_field_index].align; + } + } size_t llvm_next_abi_align = (next_src_field_index == field_count) ? llvm_struct_abi_align : LLVMABIAlignmentOfType(g->target_data_ref, diff --git a/test/stage1/behavior/coroutines.zig b/test/stage1/behavior/coroutines.zig index 13b04d778..2d76b4724 100644 --- a/test/stage1/behavior/coroutines.zig +++ b/test/stage1/behavior/coroutines.zig @@ -766,3 +766,14 @@ fn testAsyncAwaitTypicalUsage(comptime simulate_fail_download: bool, comptime si } }; } + +test "alignment of local variables in async functions" { + const S = struct { + fn doTheTest() void { + var y: u8 = 123; + var x: u8 align(128) = 1; + expect(@ptrToInt(&x) % 128 == 0); + } + }; + S.doTheTest(); +}