| author | |
| committer | |
| log | 1c8cd268bedaa5bcfad7ab6a73fc85ded09e547f |
| tree | 0da757bca2ed448e2a0cc0d9da1eeace420cc31c |
| parent | eea4cd2924edcade85b77879384738d5593bbff5 |
Make the code used to calculate the variable slot index into the frame
match what's done during the structure layout calculation.
Prevents a few nasty LLVM errors when such types are passed around.2 files changed, 35 insertions(+), 6 deletions(-)
src/stage1/codegen.cpp+16-6| ... | ... | @@ -242,14 +242,24 @@ struct CalcLLVMFieldIndex { |
| 242 | 242 | static void calc_llvm_field_index_add(CodeGen *g, CalcLLVMFieldIndex *calc, ZigType *ty) { |
| 243 | 243 | if (!type_has_bits(g, ty)) return; |
| 244 | 244 | uint32_t ty_align = get_abi_alignment(g, ty); |
| 245 | ||
| 245 | 246 | if (calc->offset % ty_align != 0) { |
| 246 | 247 | uint32_t llvm_align = LLVMABIAlignmentOfType(g->target_data_ref, get_llvm_type(g, ty)); |
| 247 | if (llvm_align >= ty_align) { | |
| 248 | ty_align = llvm_align; // llvm's padding is sufficient | |
| 249 | } else if (calc->offset) { | |
| 250 | calc->field_index += 1; // zig will insert an extra padding field here | |
| 251 | } | |
| 252 | calc->offset += ty_align - (calc->offset % ty_align); // padding bytes | |
| 248 | ||
| 249 | // Alignment according to Zig. | |
| 250 | uint32_t adj_offset = calc->offset + (ty_align - (calc->offset % ty_align)); | |
| 251 | // Alignment according to LLVM. | |
| 252 | uint32_t adj_llvm_offset = (calc->offset % llvm_align) ? | |
| 253 | calc->offset + (llvm_align - (calc->offset % llvm_align)) : | |
| 254 | calc->offset; | |
| 255 | // Cannot under-align structure fields. | |
| 256 | assert(adj_offset >= adj_llvm_offset); | |
| 257 | ||
| 258 | // Zig will insert an extra padding field here. | |
| 259 | if (adj_offset != adj_llvm_offset) | |
| 260 | calc->field_index += 1; | |
| 261 | ||
| 262 | calc->offset = adj_offset; | |
| 253 | 263 | } |
| 254 | 264 | calc->offset += ty->abi_size; |
| 255 | 265 | calc->field_index += 1; |
test/stage1/behavior/async_fn.zig+19| ... | ... | @@ -1589,3 +1589,22 @@ test "@asyncCall with pass-by-value arguments" { |
| 1589 | 1589 | F2, |
| 1590 | 1590 | }); |
| 1591 | 1591 | } |
| 1592 | ||
| 1593 | test "@asyncCall with arguments having non-standard alignment" { | |
| 1594 | const F0: u64 = 0xbeefbeef; | |
| 1595 | const F1: u64 = 0xf00df00df00df00d; | |
| 1596 | ||
| 1597 | const S = struct { | |
| 1598 | pub fn f(_fill0: u32, s: struct { x: u64 align(16) }, _fill1: u64) callconv(.Async) void { | |
| 1599 | // The compiler inserts extra alignment for s, check that the | |
| 1600 | // generated code picks the right slot for fill1. | |
| 1601 | expectEqual(F0, _fill0); | |
| 1602 | expectEqual(F1, _fill1); | |
| 1603 | } | |
| 1604 | }; | |
| 1605 | ||
| 1606 | var buffer: [1024]u8 align(@alignOf(@Frame(S.f))) = undefined; | |
| 1607 | // The function pointer must not be comptime-known. | |
| 1608 | var t = S.f; | |
| 1609 | var frame_ptr = @asyncCall(&buffer, {}, t, .{ F0, undefined, F1 }); | |
| 1610 | } |