zig/test/behavior/var_args.zig
Andrew Kelley 6f303c01f3 LLVM: add extra padding to structs and tuples sometimes
* Sema: resolve type fully when emitting an alloc AIR instruction to
   avoid tripping assertion for checking struct field alignment.
 * LLVM backend: keep a reference to the LLVM target data alive during
   lowering so that we can ask LLVM what it thinks the ABI alignment
   and size of LLVM types are. We need this in order to lower tuples and
   structs so that we can put in extra padding bytes when Zig disagrees
   with LLVM about the size or alignment of something.
 * LLVM backend: make the LLVM struct type packed that contains the most
   aligned union field and the padding. This prevents the struct from
   being too big according to LLVM. In the future, we may want to
   consider instead emitting unions in a "flat" manner; putting the tag,
   most aligned union field, and padding all in the same struct field
   space.
 * LLVM backend: make structs with 2 or fewer fields return isByRef=false.
   This results in more efficient codegen. This required lowering of
   bitcast to sometimes store the struct into an alloca, ptrcast, and
   then load because LLVM does not allow bitcasting structs.
 * enable more passing behavior tests.
2022-03-01 18:24:00 -07:00

115 lines
3.5 KiB
Zig

const builtin = @import("builtin");
const expect = @import("std").testing.expect;
fn add(args: anytype) i32 {
var sum = @as(i32, 0);
{
comptime var i: usize = 0;
inline while (i < args.len) : (i += 1) {
sum += args[i];
}
}
return sum;
}
test "add arbitrary args" {
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
try expect(add(.{ @as(i32, 1), @as(i32, 2), @as(i32, 3), @as(i32, 4) }) == 10);
try expect(add(.{@as(i32, 1234)}) == 1234);
try expect(add(.{}) == 0);
}
fn readFirstVarArg(args: anytype) void {
_ = args[0];
}
test "send void arg to var args" {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
readFirstVarArg(.{{}});
}
test "pass args directly" {
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
try expect(addSomeStuff(.{ @as(i32, 1), @as(i32, 2), @as(i32, 3), @as(i32, 4) }) == 10);
try expect(addSomeStuff(.{@as(i32, 1234)}) == 1234);
try expect(addSomeStuff(.{}) == 0);
}
fn addSomeStuff(args: anytype) i32 {
return add(args);
}
test "runtime parameter before var args" {
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
try expect((try extraFn(10, .{})) == 0);
try expect((try extraFn(10, .{false})) == 1);
try expect((try extraFn(10, .{ false, true })) == 2);
comptime {
try expect((try extraFn(10, .{})) == 0);
try expect((try extraFn(10, .{false})) == 1);
try expect((try extraFn(10, .{ false, true })) == 2);
}
}
fn extraFn(extra: u32, args: anytype) !usize {
_ = extra;
if (args.len >= 1) {
try expect(args[0] == false);
}
if (args.len >= 2) {
try expect(args[1] == true);
}
return args.len;
}
const foos = [_]fn (anytype) bool{
foo1,
foo2,
};
fn foo1(args: anytype) bool {
_ = args;
return true;
}
fn foo2(args: anytype) bool {
_ = args;
return false;
}
test "array of var args functions" {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
try expect(foos[0](.{}));
try expect(!foos[1](.{}));
}
test "pass zero length array to var args param" {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
doNothingWithFirstArg(.{""});
}
fn doNothingWithFirstArg(args: anytype) void {
_ = args[0];
}