Skip to content

Commit

Permalink
add behavior test for tail calls
Browse files Browse the repository at this point in the history
closes #9703
  • Loading branch information
andrewrk committed Jul 27, 2023
1 parent 00d6a4d commit 7b0c25c
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 0 deletions.
1 change: 1 addition & 0 deletions test/behavior.zig
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ test {
_ = @import("behavior/byval_arg_var.zig");
_ = @import("behavior/c_char_signedness.zig");
_ = @import("behavior/call.zig");
_ = @import("behavior/call_tail.zig");
_ = @import("behavior/cast.zig");
_ = @import("behavior/cast_int.zig");
_ = @import("behavior/comptime_memory.zig");
Expand Down
51 changes: 51 additions & 0 deletions test/behavior/call_tail.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
const std = @import("std");
const expect = std.testing.expect;

var base: usize = undefined;
var result_off: [7]usize = undefined;
var result_len: [7]usize = undefined;
var result_index: usize = 0;

noinline fn insertionSort(data: []u64) void {
result_off[result_index] = @intFromPtr(data.ptr) - base;
result_len[result_index] = data.len;
result_index += 1;
if (data.len > 1) {
var least_i: usize = 0;
var i: usize = 1;
while (i < data.len) : (i += 1) {
if (data[i] < data[least_i])
least_i = i;
}
std.mem.swap(u64, &data[0], &data[least_i]);

// there used to be a bug where
// `data[1..]` is created on the stack
// and pointed to by the first argument register
// then stack is invalidated by the tailcall and
// overwritten by callee
// https://github.com/ziglang/zig/issues/9703
return @call(.always_tail, insertionSort, .{data[1..]});
}
}

test "arguments pointed to on stack into tailcall" {
var data = [_]u64{ 1, 6, 2, 7, 1, 9, 3 };
base = @intFromPtr(&data);
insertionSort(data[0..]);
try expect(result_len[0] == 7);
try expect(result_len[1] == 6);
try expect(result_len[2] == 5);
try expect(result_len[3] == 4);
try expect(result_len[4] == 3);
try expect(result_len[5] == 2);
try expect(result_len[6] == 1);

try expect(result_off[0] == 0);
try expect(result_off[1] == 8);
try expect(result_off[2] == 16);
try expect(result_off[3] == 24);
try expect(result_off[4] == 32);
try expect(result_off[5] == 40);
try expect(result_off[6] == 48);
}

0 comments on commit 7b0c25c

Please sign in to comment.