authorgravatar for thatlemon@gmail.comLemonBoy <thatlemon@gmail.com> 2020-11-16 17:55:02+01:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-11-17 16:55:44-07:00
log1c8cd268bedaa5bcfad7ab6a73fc85ded09e547f
tree0da757bca2ed448e2a0cc0d9da1eeace420cc31c
parenteea4cd2924edcade85b77879384738d5593bbff5

stage1: Fix asyncCall with non-abi-aligned arguments

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 {
242242static void calc_llvm_field_index_add(CodeGen *g, CalcLLVMFieldIndex *calc, ZigType *ty) {
243243 if (!type_has_bits(g, ty)) return;
244244 uint32_t ty_align = get_abi_alignment(g, ty);
245
245246 if (calc->offset % ty_align != 0) {
246247 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;
253263 }
254264 calc->offset += ty->abi_size;
255265 calc->field_index += 1;
test/stage1/behavior/async_fn.zig+19
......@@ -1589,3 +1589,22 @@ test "@asyncCall with pass-by-value arguments" {
15891589 F2,
15901590 });
15911591}
1592
1593test "@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}