authorgravatar for thatlemon@gmail.comLemonBoy <thatlemon@gmail.com> 2020-11-14 15:30:06+01:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-11-16 11:37:49-07:00
log6624f9cd5c2d747224990fb9ba3e2b830a68f3e4
tree83df668aaca89947fb00b52486873bdfd33b6a0f
parent7d0c461b77890847899548cc69a701bcb0a3a6a6

stage1: Fix generation of pass-by-value args in async fns

The mismatch between the argument slot type in the frame structure and the one used in the store operation made the generated code write garbage over the nearby fields. Fixes #7104

2 files changed, 33 insertions(+), 1 deletions(-)

src/stage1/codegen.cpp+3-1
......@@ -4411,8 +4411,10 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutableGen *executable, IrIn
44114411 arg_calc = arg_calc_start;
44124412 for (size_t arg_i = 0; arg_i < gen_param_values.length; arg_i += 1) {
44134413 CalcLLVMFieldIndex prev = arg_calc;
4414 // Use the declared argument type and not the value one to be
4415 // consistent with the assignment operation below.
44144416 calc_llvm_field_index_add(g, &arg_calc, gen_param_types.at(arg_i));
4415 field_types[arg_calc.field_index - 1] = LLVMTypeOf(gen_param_values.at(arg_i));
4417 field_types[arg_calc.field_index - 1] = get_llvm_type(g, gen_param_types.at(arg_i));
44164418 if (arg_calc.field_index - prev.field_index > 1) {
44174419 // Padding field
44184420 uint32_t pad_bytes = arg_calc.offset - prev.offset - gen_param_types.at(arg_i)->abi_size;
test/stage1/behavior/async_fn.zig+30
......@@ -1559,3 +1559,33 @@ test "avoid forcing frame alignment resolution implicit cast to *c_void" {
15591559 resume @ptrCast(anyframe->bool, @alignCast(@alignOf(@Frame(S.foo)), S.x));
15601560 expect(nosuspend await frame);
15611561}
1562
1563test "@asyncCall with pass-by-value arguments" {
1564 const F0: u64 = 0xbeefbeefbeefbeef;
1565 const F1: u64 = 0xf00df00df00df00d;
1566 const F2: u64 = 0xcafecafecafecafe;
1567
1568 const S = struct {
1569 pub const ST = struct { f0: usize, f1: usize };
1570 pub const AT = [5]u8;
1571
1572 pub fn f(_fill0: u64, s: ST, _fill1: u64, a: AT, _fill2: u64) callconv(.Async) void {
1573 // Check that the array and struct arguments passed by value don't
1574 // end up overflowing the adjacent fields in the frame structure.
1575 expectEqual(F0, _fill0);
1576 expectEqual(F1, _fill1);
1577 expectEqual(F2, _fill2);
1578 }
1579 };
1580
1581 var buffer: [1024]u8 align(@alignOf(@Frame(S.f))) = undefined;
1582 // The function pointer must not be comptime-known.
1583 var t = S.f;
1584 var frame_ptr = @asyncCall(&buffer, {}, t, .{
1585 F0,
1586 .{ .f0 = 1, .f1 = 2 },
1587 F1,
1588 [_]u8{ 1, 2, 3, 4, 5 },
1589 F2,
1590 });
1591}