diff --git a/test/c_abi/build.zig b/test/c_abi/build.zig new file mode 100644 index 0000000000000000000000000000000000000000..b9151f6dda121d65f63bd6c7ff0d48ba3b82c42f --- /dev/null +++ b/test/c_abi/build.zig @@ -0,0 +1,22 @@ +const Builder = @import("std").build.Builder; + +pub fn build(b: *Builder) void { + const rel_opts = b.standardReleaseOptions(); + const target = b.standardTargetOptions(.{}); + + const c_obj = b.addObject("cfuncs", null); + c_obj.addCSourceFile("cfuncs.c", &[_][]const u8{"-std=c99"}); + c_obj.setBuildMode(rel_opts); + c_obj.linkSystemLibrary("c"); + c_obj.target = target; + + const main = b.addTest("main.zig"); + main.setBuildMode(rel_opts); + main.addObject(c_obj); + main.target = target; + + const test_step = b.step("test", "Test the program"); + test_step.dependOn(&main.step); + + b.default_step.dependOn(test_step); +} diff --git a/test/c_abi/build_wasm.zig b/test/c_abi/build_wasm.zig new file mode 100644 index 0000000000000000000000000000000000000000..b2886508559a80bee7ad791f919193213da0f7ec --- /dev/null +++ b/test/c_abi/build_wasm.zig @@ -0,0 +1,24 @@ +const std = @import("std"); +const Builder = std.build.Builder; + +pub fn build(b: *Builder) void { + const rel_opts = b.standardReleaseOptions(); + const target: std.zig.CrossTarget = .{ .cpu_arch = .wasm32, .os_tag = .wasi }; + b.use_stage1 = false; + + const c_obj = b.addObject("cfuncs", null); + c_obj.addCSourceFile("cfuncs.c", &[_][]const u8{"-std=c99"}); + c_obj.setBuildMode(rel_opts); + c_obj.linkSystemLibrary("c"); + c_obj.setTarget(target); + + const main = b.addTest("main.zig"); + main.setBuildMode(rel_opts); + main.addObject(c_obj); + main.setTarget(target); + + const test_step = b.step("test", "Test the program"); + test_step.dependOn(&main.step); + + b.default_step.dependOn(test_step); +} diff --git a/test/c_abi/cfuncs.c b/test/c_abi/cfuncs.c new file mode 100644 index 0000000000000000000000000000000000000000..f5c90adba039a54869a4fa00f73f05279e237a14 --- /dev/null +++ b/test/c_abi/cfuncs.c @@ -0,0 +1,479 @@ +#include +#include +#include +#include + +void zig_panic(); + +static void assert_or_panic(bool ok) { + if (!ok) { + zig_panic(); + } +} + +struct i128 { + __int128 value; +}; + +struct u128 { + unsigned __int128 value; +}; + +void zig_u8(uint8_t); +void zig_u16(uint16_t); +void zig_u32(uint32_t); +void zig_u64(uint64_t); +void zig_struct_u128(struct u128); +void zig_i8(int8_t); +void zig_i16(int16_t); +void zig_i32(int32_t); +void zig_i64(int64_t); +void zig_struct_i128(struct i128); +void zig_five_integers(int32_t, int32_t, int32_t, int32_t, int32_t); + +void zig_f32(float); +void zig_f64(double); +void zig_five_floats(float, float, float, float, float); + +bool zig_ret_bool(); +uint8_t zig_ret_u8(); +uint16_t zig_ret_u16(); +uint32_t zig_ret_u32(); +uint64_t zig_ret_u64(); +int8_t zig_ret_i8(); +int16_t zig_ret_i16(); +int32_t zig_ret_i32(); +int64_t zig_ret_i64(); + +void zig_ptr(void *); + +void zig_bool(bool); + +struct BigStruct { + uint64_t a; + uint64_t b; + uint64_t c; + uint64_t d; + uint8_t e; +}; + +void zig_big_struct(struct BigStruct); + +union BigUnion { + struct BigStruct a; +}; + +void zig_big_union(union BigUnion); + +struct SmallStructInts { + uint8_t a; + uint8_t b; + uint8_t c; + uint8_t d; +}; + +void zig_small_struct_ints(struct SmallStructInts); +struct SmallStructInts zig_ret_small_struct_ints(); + +struct MedStructMixed { + uint32_t a; + float b; + float c; + uint32_t d; +}; + +void zig_med_struct_mixed(struct MedStructMixed); +struct MedStructMixed zig_ret_med_struct_mixed(); + +struct SmallPackedStruct { + uint8_t a: 2; + uint8_t b: 2; + uint8_t c: 2; + uint8_t d: 2; + uint8_t e: 1; +}; + +struct BigPackedStruct { + uint64_t a: 64; + uint64_t b: 64; + uint64_t c: 64; + uint64_t d: 64; + uint8_t e: 8; +}; + +//void zig_small_packed_struct(struct SmallPackedStruct); // #1481 +void zig_big_packed_struct(struct BigPackedStruct); + +struct SplitStructInts { + uint64_t a; + uint8_t b; + uint32_t c; +}; +void zig_split_struct_ints(struct SplitStructInts); + +struct SplitStructMixed { + uint64_t a; + uint8_t b; + float c; +}; +void zig_split_struct_mixed(struct SplitStructMixed); +struct SplitStructMixed zig_ret_split_struct_mixed(); + +struct BigStruct zig_big_struct_both(struct BigStruct); + +typedef struct Vector3 { + float x; + float y; + float z; +} Vector3; + +typedef struct Vector5 { + float x; + float y; + float z; + float w; + float q; +} Vector5; + +void run_c_tests(void) { + zig_u8(0xff); + zig_u16(0xfffe); + zig_u32(0xfffffffd); + zig_u64(0xfffffffffffffffc); + { + struct u128 s = {0xfffffffffffffffc}; + zig_struct_u128(s); + } + + zig_i8(-1); + zig_i16(-2); + zig_i32(-3); + zig_i64(-4); + { + struct i128 s = {-6}; + zig_struct_i128(s); + } + zig_five_integers(12, 34, 56, 78, 90); + + zig_f32(12.34f); + zig_f64(56.78); + zig_five_floats(1.0f, 2.0f, 3.0f, 4.0f, 5.0f); + + zig_ptr((void*)0xdeadbeefL); + + zig_bool(true); + + { + struct BigStruct s = {1, 2, 3, 4, 5}; + zig_big_struct(s); + } + + { + struct SmallStructInts s = {1, 2, 3, 4}; + zig_small_struct_ints(s); + } + + { + struct BigPackedStruct s = {1, 2, 3, 4, 5}; + zig_big_packed_struct(s); + } + + { + struct SmallPackedStruct s = {0, 1, 2, 3, 1}; + //zig_small_packed_struct(s); + } + + { + struct SplitStructInts s = {1234, 100, 1337}; + zig_split_struct_ints(s); + } + + { + struct MedStructMixed s = {1234, 100.0f, 1337.0f}; + zig_med_struct_mixed(s); + } + + { + struct SplitStructMixed s = {1234, 100, 1337.0f}; + zig_split_struct_mixed(s); + } + + { + struct BigStruct s = {30, 31, 32, 33, 34}; + struct BigStruct res = zig_big_struct_both(s); + assert_or_panic(res.a == 20); + assert_or_panic(res.b == 21); + assert_or_panic(res.c == 22); + assert_or_panic(res.d == 23); + assert_or_panic(res.e == 24); + } + + { + assert_or_panic(zig_ret_bool() == 1); + + assert_or_panic(zig_ret_u8() == 0xff); + assert_or_panic(zig_ret_u16() == 0xffff); + assert_or_panic(zig_ret_u32() == 0xffffffff); + assert_or_panic(zig_ret_u64() == 0xffffffffffffffff); + + assert_or_panic(zig_ret_i8() == -1); + assert_or_panic(zig_ret_i16() == -1); + assert_or_panic(zig_ret_i32() == -1); + assert_or_panic(zig_ret_i64() == -1); + } +} + +void c_u8(uint8_t x) { + assert_or_panic(x == 0xff); +} + +void c_u16(uint16_t x) { + assert_or_panic(x == 0xfffe); +} + +void c_u32(uint32_t x) { + assert_or_panic(x == 0xfffffffd); +} + +void c_u64(uint64_t x) { + assert_or_panic(x == 0xfffffffffffffffcULL); +} + +void c_struct_u128(struct u128 x) { + assert_or_panic(x.value == 0xfffffffffffffffcULL); +} + +void c_i8(int8_t x) { + assert_or_panic(x == -1); +} + +void c_i16(int16_t x) { + assert_or_panic(x == -2); +} + +void c_i32(int32_t x) { + assert_or_panic(x == -3); +} + +void c_i64(int64_t x) { + assert_or_panic(x == -4); +} + +void c_struct_i128(struct i128 x) { + assert_or_panic(x.value == -6); +} + +void c_f32(float x) { + assert_or_panic(x == 12.34f); +} + +void c_f64(double x) { + assert_or_panic(x == 56.78); +} + +void c_ptr(void *x) { + assert_or_panic(x == (void*)0xdeadbeefL); +} + +void c_bool(bool x) { + assert_or_panic(x); +} + +void c_five_integers(int32_t a, int32_t b, int32_t c, int32_t d, int32_t e) { + assert_or_panic(a == 12); + assert_or_panic(b == 34); + assert_or_panic(c == 56); + assert_or_panic(d == 78); + assert_or_panic(e == 90); +} + +void c_five_floats(float a, float b, float c, float d, float e) { + assert_or_panic(a == 1.0); + assert_or_panic(b == 2.0); + assert_or_panic(c == 3.0); + assert_or_panic(d == 4.0); + assert_or_panic(e == 5.0); +} + +void c_big_struct(struct BigStruct x) { + assert_or_panic(x.a == 1); + assert_or_panic(x.b == 2); + assert_or_panic(x.c == 3); + assert_or_panic(x.d == 4); + assert_or_panic(x.e == 5); +} + +void c_big_union(union BigUnion x) { + assert_or_panic(x.a.a == 1); + assert_or_panic(x.a.b == 2); + assert_or_panic(x.a.c == 3); + assert_or_panic(x.a.d == 4); +} + +void c_small_struct_ints(struct SmallStructInts x) { + assert_or_panic(x.a == 1); + assert_or_panic(x.b == 2); + assert_or_panic(x.c == 3); + assert_or_panic(x.d == 4); + + struct SmallStructInts y = zig_ret_small_struct_ints(); + + assert_or_panic(y.a == 1); + assert_or_panic(y.b == 2); + assert_or_panic(y.c == 3); + assert_or_panic(y.d == 4); +} + +struct SmallStructInts c_ret_small_struct_ints() { + struct SmallStructInts s = { + .a = 1, + .b = 2, + .c = 3, + .d = 4, + }; + return s; +} + +void c_med_struct_mixed(struct MedStructMixed x) { + assert_or_panic(x.a == 1234); + assert_or_panic(x.b == 100.0f); + assert_or_panic(x.c == 1337.0f); + + struct MedStructMixed y = zig_ret_med_struct_mixed(); + + assert_or_panic(y.a == 1234); + assert_or_panic(y.b == 100.0f); + assert_or_panic(y.c == 1337.0f); +} + +struct MedStructMixed c_ret_med_struct_mixed() { + struct MedStructMixed s = { + .a = 1234, + .b = 100.0, + .c = 1337.0, + }; + return s; +} + +void c_split_struct_ints(struct SplitStructInts x) { + assert_or_panic(x.a == 1234); + assert_or_panic(x.b == 100); + assert_or_panic(x.c == 1337); +} + +void c_split_struct_mixed(struct SplitStructMixed x) { + assert_or_panic(x.a == 1234); + assert_or_panic(x.b == 100); + assert_or_panic(x.c == 1337.0f); + struct SplitStructMixed y = zig_ret_split_struct_mixed(); + + assert_or_panic(y.a == 1234); + assert_or_panic(y.b == 100); + assert_or_panic(y.c == 1337.0f); +} + +struct SmallPackedStruct c_ret_small_packed_struct() { + struct SmallPackedStruct s = { + .a = 0, + .b = 1, + .c = 2, + .d = 3, + .e = 1, + }; + return s; +} + +void c_small_packed_struct(struct SmallPackedStruct x) { + assert_or_panic(x.a == 0); + assert_or_panic(x.a == 1); + assert_or_panic(x.a == 2); + assert_or_panic(x.a == 3); + assert_or_panic(x.e == 1); +} + +struct BigPackedStruct c_ret_big_packed_struct() { + struct BigPackedStruct s = { + .a = 1, + .b = 2, + .c = 3, + .d = 4, + .e = 5, + }; + return s; +} + +void c_big_packed_struct(struct BigPackedStruct x) { + assert_or_panic(x.a == 1); + assert_or_panic(x.b == 2); + assert_or_panic(x.c == 3); + assert_or_panic(x.d == 4); + assert_or_panic(x.e == 5); +} + +struct SplitStructMixed c_ret_split_struct_mixed() { + struct SplitStructMixed s = { + .a = 1234, + .b = 100, + .c = 1337.0f, + }; + return s; +} + +struct BigStruct c_big_struct_both(struct BigStruct x) { + assert_or_panic(x.a == 1); + assert_or_panic(x.b == 2); + assert_or_panic(x.c == 3); + assert_or_panic(x.d == 4); + assert_or_panic(x.e == 5); + struct BigStruct y = {10, 11, 12, 13, 14}; + return y; +} + +void c_small_struct_floats(Vector3 vec) { + assert_or_panic(vec.x == 3.0); + assert_or_panic(vec.y == 6.0); + assert_or_panic(vec.z == 12.0); +} + +void c_small_struct_floats_extra(Vector3 vec, const char *str) { + assert_or_panic(vec.x == 3.0); + assert_or_panic(vec.y == 6.0); + assert_or_panic(vec.z == 12.0); + assert_or_panic(!strcmp(str, "hello")); +} + +void c_big_struct_floats(Vector5 vec) { + assert_or_panic(vec.x == 76.0); + assert_or_panic(vec.y == -1.0); + assert_or_panic(vec.z == -12.0); + assert_or_panic(vec.w == 69); + assert_or_panic(vec.q == 55); +} + +bool c_ret_bool() { + return 1; +} +uint8_t c_ret_u8() { + return 0xff; +} +uint16_t c_ret_u16() { + return 0xffff; +} +uint32_t c_ret_u32() { + return 0xffffffff; +} +uint64_t c_ret_u64() { + return 0xffffffffffffffff; +} +int8_t c_ret_i8() { + return -1; +} +int16_t c_ret_i16() { + return -1; +} +int32_t c_ret_i32() { + return -1; +} +int64_t c_ret_i64() { + return -1; +} diff --git a/test/c_abi/main.zig b/test/c_abi/main.zig new file mode 100644 index 0000000000000000000000000000000000000000..71a53bedea335c977f47a8b462b73f70dff35960 --- /dev/null +++ b/test/c_abi/main.zig @@ -0,0 +1,503 @@ +const std = @import("std"); +const print = std.debug.print; +const expect = std.testing.expect; + +extern fn run_c_tests() void; + +export fn zig_panic() noreturn { + @panic("zig_panic called from C"); +} + +test "C importing Zig ABI Tests" { + run_c_tests(); +} + +extern fn c_u8(u8) void; +extern fn c_u16(u16) void; +extern fn c_u32(u32) void; +extern fn c_u64(u64) void; +extern fn c_struct_u128(U128) void; +extern fn c_i8(i8) void; +extern fn c_i16(i16) void; +extern fn c_i32(i32) void; +extern fn c_i64(i64) void; +extern fn c_struct_i128(I128) void; + +// On windows x64, the first 4 are passed via registers, others on the stack. +extern fn c_five_integers(i32, i32, i32, i32, i32) void; + +export fn zig_five_integers(a: i32, b: i32, c: i32, d: i32, e: i32) void { + expect(a == 12) catch @panic("test failure: zig_five_integers 12"); + expect(b == 34) catch @panic("test failure: zig_five_integers 34"); + expect(c == 56) catch @panic("test failure: zig_five_integers 56"); + expect(d == 78) catch @panic("test failure: zig_five_integers 78"); + expect(e == 90) catch @panic("test failure: zig_five_integers 90"); +} + +test "C ABI integers" { + c_u8(0xff); + c_u16(0xfffe); + c_u32(0xfffffffd); + c_u64(0xfffffffffffffffc); + c_struct_u128(.{ .value = 0xfffffffffffffffc }); + + c_i8(-1); + c_i16(-2); + c_i32(-3); + c_i64(-4); + c_struct_i128(.{ .value = -6 }); + c_five_integers(12, 34, 56, 78, 90); +} + +export fn zig_u8(x: u8) void { + expect(x == 0xff) catch @panic("test failure: zig_u8"); +} +export fn zig_u16(x: u16) void { + expect(x == 0xfffe) catch @panic("test failure: zig_u16"); +} +export fn zig_u32(x: u32) void { + expect(x == 0xfffffffd) catch @panic("test failure: zig_u32"); +} +export fn zig_u64(x: u64) void { + expect(x == 0xfffffffffffffffc) catch @panic("test failure: zig_u64"); +} +export fn zig_i8(x: i8) void { + expect(x == -1) catch @panic("test failure: zig_i8"); +} +export fn zig_i16(x: i16) void { + expect(x == -2) catch @panic("test failure: zig_i16"); +} +export fn zig_i32(x: i32) void { + expect(x == -3) catch @panic("test failure: zig_i32"); +} +export fn zig_i64(x: i64) void { + expect(x == -4) catch @panic("test failure: zig_i64"); +} + +const I128 = extern struct { + value: i128, +}; +const U128 = extern struct { + value: u128, +}; +export fn zig_struct_i128(a: I128) void { + expect(a.value == -6) catch @panic("test failure: zig_struct_i128"); +} +export fn zig_struct_u128(a: U128) void { + expect(a.value == 0xfffffffffffffffc) catch @panic("test failure: zig_struct_u128"); +} + +extern fn c_f32(f32) void; +extern fn c_f64(f64) void; + +// On windows x64, the first 4 are passed via registers, others on the stack. +extern fn c_five_floats(f32, f32, f32, f32, f32) void; + +export fn zig_five_floats(a: f32, b: f32, c: f32, d: f32, e: f32) void { + expect(a == 1.0) catch @panic("test failure: zig_five_floats 1.0"); + expect(b == 2.0) catch @panic("test failure: zig_five_floats 2.0"); + expect(c == 3.0) catch @panic("test failure: zig_five_floats 3.0"); + expect(d == 4.0) catch @panic("test failure: zig_five_floats 4.0"); + expect(e == 5.0) catch @panic("test failure: zig_five_floats 5.0"); +} + +test "C ABI floats" { + c_f32(12.34); + c_f64(56.78); + c_five_floats(1.0, 2.0, 3.0, 4.0, 5.0); +} + +export fn zig_f32(x: f32) void { + expect(x == 12.34) catch @panic("test failure: zig_f32"); +} +export fn zig_f64(x: f64) void { + expect(x == 56.78) catch @panic("test failure: zig_f64"); +} + +extern fn c_ptr(*anyopaque) void; + +test "C ABI pointer" { + c_ptr(@intToPtr(*anyopaque, 0xdeadbeef)); +} + +export fn zig_ptr(x: *anyopaque) void { + expect(@ptrToInt(x) == 0xdeadbeef) catch @panic("test failure: zig_ptr"); +} + +extern fn c_bool(bool) void; + +test "C ABI bool" { + c_bool(true); +} + +export fn zig_bool(x: bool) void { + expect(x) catch @panic("test failure: zig_bool"); +} + +const BigStruct = extern struct { + a: u64, + b: u64, + c: u64, + d: u64, + e: u8, +}; +extern fn c_big_struct(BigStruct) void; + +test "C ABI big struct" { + var s = BigStruct{ + .a = 1, + .b = 2, + .c = 3, + .d = 4, + .e = 5, + }; + c_big_struct(s); +} + +export fn zig_big_struct(x: BigStruct) void { + expect(x.a == 1) catch @panic("test failure: zig_big_struct 1"); + expect(x.b == 2) catch @panic("test failure: zig_big_struct 2"); + expect(x.c == 3) catch @panic("test failure: zig_big_struct 3"); + expect(x.d == 4) catch @panic("test failure: zig_big_struct 4"); + expect(x.e == 5) catch @panic("test failure: zig_big_struct 5"); +} + +const BigUnion = extern union { + a: BigStruct, +}; +extern fn c_big_union(BigUnion) void; + +test "C ABI big union" { + var x = BigUnion{ + .a = BigStruct{ + .a = 1, + .b = 2, + .c = 3, + .d = 4, + .e = 5, + }, + }; + c_big_union(x); +} + +export fn zig_big_union(x: BigUnion) void { + expect(x.a.a == 1) catch @panic("test failure: zig_big_union a"); + expect(x.a.b == 2) catch @panic("test failure: zig_big_union b"); + expect(x.a.c == 3) catch @panic("test failure: zig_big_union c"); + expect(x.a.d == 4) catch @panic("test failure: zig_big_union d"); + expect(x.a.e == 5) catch @panic("test failure: zig_big_union e"); +} + +const MedStructMixed = extern struct { + a: u32, + b: f32, + c: f32, + d: u32 = 0, +}; +extern fn c_med_struct_mixed(MedStructMixed) void; +extern fn c_ret_med_struct_mixed() MedStructMixed; + +test "C ABI medium struct of ints and floats" { + var s = MedStructMixed{ + .a = 1234, + .b = 100.0, + .c = 1337.0, + }; + c_med_struct_mixed(s); + var s2 = c_ret_med_struct_mixed(); + expect(s2.a == 1234) catch @panic("test failure"); + expect(s2.b == 100.0) catch @panic("test failure"); + expect(s2.c == 1337.0) catch @panic("test failure"); +} + +export fn zig_med_struct_mixed(x: MedStructMixed) void { + expect(x.a == 1234) catch @panic("test failure"); + expect(x.b == 100.0) catch @panic("test failure"); + expect(x.c == 1337.0) catch @panic("test failure"); +} + +const SmallStructInts = extern struct { + a: u8, + b: u8, + c: u8, + d: u8, +}; +extern fn c_small_struct_ints(SmallStructInts) void; +extern fn c_ret_small_struct_ints() SmallStructInts; + +test "C ABI small struct of ints" { + var s = SmallStructInts{ + .a = 1, + .b = 2, + .c = 3, + .d = 4, + }; + c_small_struct_ints(s); + var s2 = c_ret_small_struct_ints(); + expect(s2.a == 1) catch @panic("test failure"); + expect(s2.b == 2) catch @panic("test failure"); + expect(s2.c == 3) catch @panic("test failure"); + expect(s2.d == 4) catch @panic("test failure"); +} + +export fn zig_small_struct_ints(x: SmallStructInts) void { + expect(x.a == 1) catch @panic("test failure"); + expect(x.b == 2) catch @panic("test failure"); + expect(x.c == 3) catch @panic("test failure"); + expect(x.d == 4) catch @panic("test failure"); +} + +const SmallPackedStruct = packed struct { + a: u2, + b: u2, + c: u2, + d: u2, + e: bool, +}; +const c_small_packed_struct: fn (SmallPackedStruct) callconv(.C) void = @compileError("TODO: #1481"); +extern fn c_ret_small_packed_struct() SmallPackedStruct; + +// waiting on #1481 +//export fn zig_small_packed_struct(x: SmallPackedStruct) void { +// expect(x.a == 0) catch @panic("test failure"); +// expect(x.b == 1) catch @panic("test failure"); +// expect(x.c == 2) catch @panic("test failure"); +// expect(x.d == 3) catch @panic("test failure"); +// expect(x.e) catch @panic("test failure"); +//} + +test "C ABI small packed struct" { + var s = SmallPackedStruct{ .a = 0, .b = 1, .c = 2, .d = 3, .e = true }; + _ = s; //c_small_packed_struct(s); // waiting on #1481 + var s2 = c_ret_small_packed_struct(); + try expect(s2.a == 0); + try expect(s2.b == 1); + try expect(s2.c == 2); + try expect(s2.d == 3); + try expect(s2.e); +} + +const BigPackedStruct = packed struct { + a: u64, + b: u64, + c: u64, + d: u64, + e: u8, +}; +extern fn c_big_packed_struct(BigPackedStruct) void; +extern fn c_ret_big_packed_struct() BigPackedStruct; + +export fn zig_big_packed_struct(x: BigPackedStruct) void { + expect(x.a == 1) catch @panic("test failure"); + expect(x.b == 2) catch @panic("test failure"); + expect(x.c == 3) catch @panic("test failure"); + expect(x.d == 4) catch @panic("test failure"); + expect(x.e == 5) catch @panic("test failure"); +} + +test "C ABI big packed struct" { + var s = BigPackedStruct{ .a = 1, .b = 2, .c = 3, .d = 4, .e = 5 }; + c_big_packed_struct(s); + var s2 = c_ret_big_packed_struct(); + try expect(s2.a == 1); + try expect(s2.b == 2); + try expect(s2.c == 3); + try expect(s2.d == 4); + try expect(s2.e == 5); +} + +const SplitStructInt = extern struct { + a: u64, + b: u8, + c: u32, +}; +extern fn c_split_struct_ints(SplitStructInt) void; + +test "C ABI split struct of ints" { + var s = SplitStructInt{ + .a = 1234, + .b = 100, + .c = 1337, + }; + c_split_struct_ints(s); +} + +export fn zig_split_struct_ints(x: SplitStructInt) void { + expect(x.a == 1234) catch @panic("test failure"); + expect(x.b == 100) catch @panic("test failure"); + expect(x.c == 1337) catch @panic("test failure"); +} + +const SplitStructMixed = extern struct { + a: u64, + b: u8, + c: f32, +}; +extern fn c_split_struct_mixed(SplitStructMixed) void; +extern fn c_ret_split_struct_mixed() SplitStructMixed; + +test "C ABI split struct of ints and floats" { + var s = SplitStructMixed{ + .a = 1234, + .b = 100, + .c = 1337.0, + }; + c_split_struct_mixed(s); + var s2 = c_ret_split_struct_mixed(); + expect(s2.a == 1234) catch @panic("test failure"); + expect(s2.b == 100) catch @panic("test failure"); + expect(s2.c == 1337.0) catch @panic("test failure"); +} + +export fn zig_split_struct_mixed(x: SplitStructMixed) void { + expect(x.a == 1234) catch @panic("test failure"); + expect(x.b == 100) catch @panic("test failure"); + expect(x.c == 1337.0) catch @panic("test failure"); +} + +extern fn c_big_struct_both(BigStruct) BigStruct; + +test "C ABI sret and byval together" { + var s = BigStruct{ + .a = 1, + .b = 2, + .c = 3, + .d = 4, + .e = 5, + }; + var y = c_big_struct_both(s); + try expect(y.a == 10); + try expect(y.b == 11); + try expect(y.c == 12); + try expect(y.d == 13); + try expect(y.e == 14); +} + +export fn zig_big_struct_both(x: BigStruct) BigStruct { + expect(x.a == 30) catch @panic("test failure"); + expect(x.b == 31) catch @panic("test failure"); + expect(x.c == 32) catch @panic("test failure"); + expect(x.d == 33) catch @panic("test failure"); + expect(x.e == 34) catch @panic("test failure"); + var s = BigStruct{ + .a = 20, + .b = 21, + .c = 22, + .d = 23, + .e = 24, + }; + return s; +} + +const Vector3 = extern struct { + x: f32, + y: f32, + z: f32, +}; +extern fn c_small_struct_floats(Vector3) void; +extern fn c_small_struct_floats_extra(Vector3, ?[*]const u8) void; + +const Vector5 = extern struct { + x: f32, + y: f32, + z: f32, + w: f32, + q: f32, +}; +extern fn c_big_struct_floats(Vector5) void; + +test "C ABI structs of floats as parameter" { + var v3 = Vector3{ + .x = 3.0, + .y = 6.0, + .z = 12.0, + }; + c_small_struct_floats(v3); + c_small_struct_floats_extra(v3, "hello"); + + var v5 = Vector5{ + .x = 76.0, + .y = -1.0, + .z = -12.0, + .w = 69.0, + .q = 55, + }; + c_big_struct_floats(v5); +} + +export fn zig_ret_bool() bool { + return true; +} +export fn zig_ret_u8() u8 { + return 0xff; +} +export fn zig_ret_u16() u16 { + return 0xffff; +} +export fn zig_ret_u32() u32 { + return 0xffffffff; +} +export fn zig_ret_u64() u64 { + return 0xffffffffffffffff; +} +export fn zig_ret_i8() i8 { + return -1; +} +export fn zig_ret_i16() i16 { + return -1; +} +export fn zig_ret_i32() i32 { + return -1; +} +export fn zig_ret_i64() i64 { + return -1; +} + +export fn zig_ret_small_struct_ints() SmallStructInts { + return .{ + .a = 1, + .b = 2, + .c = 3, + .d = 4, + }; +} + +export fn zig_ret_med_struct_mixed() MedStructMixed { + return .{ + .a = 1234, + .b = 100.0, + .c = 1337.0, + }; +} + +export fn zig_ret_split_struct_mixed() SplitStructMixed { + return .{ + .a = 1234, + .b = 100, + .c = 1337.0, + }; +} + +extern fn c_ret_bool() bool; +extern fn c_ret_u8() u8; +extern fn c_ret_u16() u16; +extern fn c_ret_u32() u32; +extern fn c_ret_u64() u64; +extern fn c_ret_i8() i8; +extern fn c_ret_i16() i16; +extern fn c_ret_i32() i32; +extern fn c_ret_i64() i64; + +test "C ABI integer return types" { + try expect(c_ret_bool() == true); + + try expect(c_ret_u8() == 0xff); + try expect(c_ret_u16() == 0xffff); + try expect(c_ret_u32() == 0xffffffff); + try expect(c_ret_u64() == 0xffffffffffffffff); + + try expect(c_ret_i8() == -1); + try expect(c_ret_i16() == -1); + try expect(c_ret_i32() == -1); + try expect(c_ret_i64() == -1); +} diff --git a/test/stage1/c_abi/build.zig b/test/stage1/c_abi/build.zig deleted file mode 100644 index b9151f6dda121d65f63bd6c7ff0d48ba3b82c42f..0000000000000000000000000000000000000000 --- a/test/stage1/c_abi/build.zig +++ /dev/null @@ -1,22 +0,0 @@ -const Builder = @import("std").build.Builder; - -pub fn build(b: *Builder) void { - const rel_opts = b.standardReleaseOptions(); - const target = b.standardTargetOptions(.{}); - - const c_obj = b.addObject("cfuncs", null); - c_obj.addCSourceFile("cfuncs.c", &[_][]const u8{"-std=c99"}); - c_obj.setBuildMode(rel_opts); - c_obj.linkSystemLibrary("c"); - c_obj.target = target; - - const main = b.addTest("main.zig"); - main.setBuildMode(rel_opts); - main.addObject(c_obj); - main.target = target; - - const test_step = b.step("test", "Test the program"); - test_step.dependOn(&main.step); - - b.default_step.dependOn(test_step); -} diff --git a/test/stage1/c_abi/build_wasm.zig b/test/stage1/c_abi/build_wasm.zig deleted file mode 100644 index b2886508559a80bee7ad791f919193213da0f7ec..0000000000000000000000000000000000000000 --- a/test/stage1/c_abi/build_wasm.zig +++ /dev/null @@ -1,24 +0,0 @@ -const std = @import("std"); -const Builder = std.build.Builder; - -pub fn build(b: *Builder) void { - const rel_opts = b.standardReleaseOptions(); - const target: std.zig.CrossTarget = .{ .cpu_arch = .wasm32, .os_tag = .wasi }; - b.use_stage1 = false; - - const c_obj = b.addObject("cfuncs", null); - c_obj.addCSourceFile("cfuncs.c", &[_][]const u8{"-std=c99"}); - c_obj.setBuildMode(rel_opts); - c_obj.linkSystemLibrary("c"); - c_obj.setTarget(target); - - const main = b.addTest("main.zig"); - main.setBuildMode(rel_opts); - main.addObject(c_obj); - main.setTarget(target); - - const test_step = b.step("test", "Test the program"); - test_step.dependOn(&main.step); - - b.default_step.dependOn(test_step); -} diff --git a/test/stage1/c_abi/cfuncs.c b/test/stage1/c_abi/cfuncs.c deleted file mode 100644 index f5c90adba039a54869a4fa00f73f05279e237a14..0000000000000000000000000000000000000000 --- a/test/stage1/c_abi/cfuncs.c +++ /dev/null @@ -1,479 +0,0 @@ -#include -#include -#include -#include - -void zig_panic(); - -static void assert_or_panic(bool ok) { - if (!ok) { - zig_panic(); - } -} - -struct i128 { - __int128 value; -}; - -struct u128 { - unsigned __int128 value; -}; - -void zig_u8(uint8_t); -void zig_u16(uint16_t); -void zig_u32(uint32_t); -void zig_u64(uint64_t); -void zig_struct_u128(struct u128); -void zig_i8(int8_t); -void zig_i16(int16_t); -void zig_i32(int32_t); -void zig_i64(int64_t); -void zig_struct_i128(struct i128); -void zig_five_integers(int32_t, int32_t, int32_t, int32_t, int32_t); - -void zig_f32(float); -void zig_f64(double); -void zig_five_floats(float, float, float, float, float); - -bool zig_ret_bool(); -uint8_t zig_ret_u8(); -uint16_t zig_ret_u16(); -uint32_t zig_ret_u32(); -uint64_t zig_ret_u64(); -int8_t zig_ret_i8(); -int16_t zig_ret_i16(); -int32_t zig_ret_i32(); -int64_t zig_ret_i64(); - -void zig_ptr(void *); - -void zig_bool(bool); - -struct BigStruct { - uint64_t a; - uint64_t b; - uint64_t c; - uint64_t d; - uint8_t e; -}; - -void zig_big_struct(struct BigStruct); - -union BigUnion { - struct BigStruct a; -}; - -void zig_big_union(union BigUnion); - -struct SmallStructInts { - uint8_t a; - uint8_t b; - uint8_t c; - uint8_t d; -}; - -void zig_small_struct_ints(struct SmallStructInts); -struct SmallStructInts zig_ret_small_struct_ints(); - -struct MedStructMixed { - uint32_t a; - float b; - float c; - uint32_t d; -}; - -void zig_med_struct_mixed(struct MedStructMixed); -struct MedStructMixed zig_ret_med_struct_mixed(); - -struct SmallPackedStruct { - uint8_t a: 2; - uint8_t b: 2; - uint8_t c: 2; - uint8_t d: 2; - uint8_t e: 1; -}; - -struct BigPackedStruct { - uint64_t a: 64; - uint64_t b: 64; - uint64_t c: 64; - uint64_t d: 64; - uint8_t e: 8; -}; - -//void zig_small_packed_struct(struct SmallPackedStruct); // #1481 -void zig_big_packed_struct(struct BigPackedStruct); - -struct SplitStructInts { - uint64_t a; - uint8_t b; - uint32_t c; -}; -void zig_split_struct_ints(struct SplitStructInts); - -struct SplitStructMixed { - uint64_t a; - uint8_t b; - float c; -}; -void zig_split_struct_mixed(struct SplitStructMixed); -struct SplitStructMixed zig_ret_split_struct_mixed(); - -struct BigStruct zig_big_struct_both(struct BigStruct); - -typedef struct Vector3 { - float x; - float y; - float z; -} Vector3; - -typedef struct Vector5 { - float x; - float y; - float z; - float w; - float q; -} Vector5; - -void run_c_tests(void) { - zig_u8(0xff); - zig_u16(0xfffe); - zig_u32(0xfffffffd); - zig_u64(0xfffffffffffffffc); - { - struct u128 s = {0xfffffffffffffffc}; - zig_struct_u128(s); - } - - zig_i8(-1); - zig_i16(-2); - zig_i32(-3); - zig_i64(-4); - { - struct i128 s = {-6}; - zig_struct_i128(s); - } - zig_five_integers(12, 34, 56, 78, 90); - - zig_f32(12.34f); - zig_f64(56.78); - zig_five_floats(1.0f, 2.0f, 3.0f, 4.0f, 5.0f); - - zig_ptr((void*)0xdeadbeefL); - - zig_bool(true); - - { - struct BigStruct s = {1, 2, 3, 4, 5}; - zig_big_struct(s); - } - - { - struct SmallStructInts s = {1, 2, 3, 4}; - zig_small_struct_ints(s); - } - - { - struct BigPackedStruct s = {1, 2, 3, 4, 5}; - zig_big_packed_struct(s); - } - - { - struct SmallPackedStruct s = {0, 1, 2, 3, 1}; - //zig_small_packed_struct(s); - } - - { - struct SplitStructInts s = {1234, 100, 1337}; - zig_split_struct_ints(s); - } - - { - struct MedStructMixed s = {1234, 100.0f, 1337.0f}; - zig_med_struct_mixed(s); - } - - { - struct SplitStructMixed s = {1234, 100, 1337.0f}; - zig_split_struct_mixed(s); - } - - { - struct BigStruct s = {30, 31, 32, 33, 34}; - struct BigStruct res = zig_big_struct_both(s); - assert_or_panic(res.a == 20); - assert_or_panic(res.b == 21); - assert_or_panic(res.c == 22); - assert_or_panic(res.d == 23); - assert_or_panic(res.e == 24); - } - - { - assert_or_panic(zig_ret_bool() == 1); - - assert_or_panic(zig_ret_u8() == 0xff); - assert_or_panic(zig_ret_u16() == 0xffff); - assert_or_panic(zig_ret_u32() == 0xffffffff); - assert_or_panic(zig_ret_u64() == 0xffffffffffffffff); - - assert_or_panic(zig_ret_i8() == -1); - assert_or_panic(zig_ret_i16() == -1); - assert_or_panic(zig_ret_i32() == -1); - assert_or_panic(zig_ret_i64() == -1); - } -} - -void c_u8(uint8_t x) { - assert_or_panic(x == 0xff); -} - -void c_u16(uint16_t x) { - assert_or_panic(x == 0xfffe); -} - -void c_u32(uint32_t x) { - assert_or_panic(x == 0xfffffffd); -} - -void c_u64(uint64_t x) { - assert_or_panic(x == 0xfffffffffffffffcULL); -} - -void c_struct_u128(struct u128 x) { - assert_or_panic(x.value == 0xfffffffffffffffcULL); -} - -void c_i8(int8_t x) { - assert_or_panic(x == -1); -} - -void c_i16(int16_t x) { - assert_or_panic(x == -2); -} - -void c_i32(int32_t x) { - assert_or_panic(x == -3); -} - -void c_i64(int64_t x) { - assert_or_panic(x == -4); -} - -void c_struct_i128(struct i128 x) { - assert_or_panic(x.value == -6); -} - -void c_f32(float x) { - assert_or_panic(x == 12.34f); -} - -void c_f64(double x) { - assert_or_panic(x == 56.78); -} - -void c_ptr(void *x) { - assert_or_panic(x == (void*)0xdeadbeefL); -} - -void c_bool(bool x) { - assert_or_panic(x); -} - -void c_five_integers(int32_t a, int32_t b, int32_t c, int32_t d, int32_t e) { - assert_or_panic(a == 12); - assert_or_panic(b == 34); - assert_or_panic(c == 56); - assert_or_panic(d == 78); - assert_or_panic(e == 90); -} - -void c_five_floats(float a, float b, float c, float d, float e) { - assert_or_panic(a == 1.0); - assert_or_panic(b == 2.0); - assert_or_panic(c == 3.0); - assert_or_panic(d == 4.0); - assert_or_panic(e == 5.0); -} - -void c_big_struct(struct BigStruct x) { - assert_or_panic(x.a == 1); - assert_or_panic(x.b == 2); - assert_or_panic(x.c == 3); - assert_or_panic(x.d == 4); - assert_or_panic(x.e == 5); -} - -void c_big_union(union BigUnion x) { - assert_or_panic(x.a.a == 1); - assert_or_panic(x.a.b == 2); - assert_or_panic(x.a.c == 3); - assert_or_panic(x.a.d == 4); -} - -void c_small_struct_ints(struct SmallStructInts x) { - assert_or_panic(x.a == 1); - assert_or_panic(x.b == 2); - assert_or_panic(x.c == 3); - assert_or_panic(x.d == 4); - - struct SmallStructInts y = zig_ret_small_struct_ints(); - - assert_or_panic(y.a == 1); - assert_or_panic(y.b == 2); - assert_or_panic(y.c == 3); - assert_or_panic(y.d == 4); -} - -struct SmallStructInts c_ret_small_struct_ints() { - struct SmallStructInts s = { - .a = 1, - .b = 2, - .c = 3, - .d = 4, - }; - return s; -} - -void c_med_struct_mixed(struct MedStructMixed x) { - assert_or_panic(x.a == 1234); - assert_or_panic(x.b == 100.0f); - assert_or_panic(x.c == 1337.0f); - - struct MedStructMixed y = zig_ret_med_struct_mixed(); - - assert_or_panic(y.a == 1234); - assert_or_panic(y.b == 100.0f); - assert_or_panic(y.c == 1337.0f); -} - -struct MedStructMixed c_ret_med_struct_mixed() { - struct MedStructMixed s = { - .a = 1234, - .b = 100.0, - .c = 1337.0, - }; - return s; -} - -void c_split_struct_ints(struct SplitStructInts x) { - assert_or_panic(x.a == 1234); - assert_or_panic(x.b == 100); - assert_or_panic(x.c == 1337); -} - -void c_split_struct_mixed(struct SplitStructMixed x) { - assert_or_panic(x.a == 1234); - assert_or_panic(x.b == 100); - assert_or_panic(x.c == 1337.0f); - struct SplitStructMixed y = zig_ret_split_struct_mixed(); - - assert_or_panic(y.a == 1234); - assert_or_panic(y.b == 100); - assert_or_panic(y.c == 1337.0f); -} - -struct SmallPackedStruct c_ret_small_packed_struct() { - struct SmallPackedStruct s = { - .a = 0, - .b = 1, - .c = 2, - .d = 3, - .e = 1, - }; - return s; -} - -void c_small_packed_struct(struct SmallPackedStruct x) { - assert_or_panic(x.a == 0); - assert_or_panic(x.a == 1); - assert_or_panic(x.a == 2); - assert_or_panic(x.a == 3); - assert_or_panic(x.e == 1); -} - -struct BigPackedStruct c_ret_big_packed_struct() { - struct BigPackedStruct s = { - .a = 1, - .b = 2, - .c = 3, - .d = 4, - .e = 5, - }; - return s; -} - -void c_big_packed_struct(struct BigPackedStruct x) { - assert_or_panic(x.a == 1); - assert_or_panic(x.b == 2); - assert_or_panic(x.c == 3); - assert_or_panic(x.d == 4); - assert_or_panic(x.e == 5); -} - -struct SplitStructMixed c_ret_split_struct_mixed() { - struct SplitStructMixed s = { - .a = 1234, - .b = 100, - .c = 1337.0f, - }; - return s; -} - -struct BigStruct c_big_struct_both(struct BigStruct x) { - assert_or_panic(x.a == 1); - assert_or_panic(x.b == 2); - assert_or_panic(x.c == 3); - assert_or_panic(x.d == 4); - assert_or_panic(x.e == 5); - struct BigStruct y = {10, 11, 12, 13, 14}; - return y; -} - -void c_small_struct_floats(Vector3 vec) { - assert_or_panic(vec.x == 3.0); - assert_or_panic(vec.y == 6.0); - assert_or_panic(vec.z == 12.0); -} - -void c_small_struct_floats_extra(Vector3 vec, const char *str) { - assert_or_panic(vec.x == 3.0); - assert_or_panic(vec.y == 6.0); - assert_or_panic(vec.z == 12.0); - assert_or_panic(!strcmp(str, "hello")); -} - -void c_big_struct_floats(Vector5 vec) { - assert_or_panic(vec.x == 76.0); - assert_or_panic(vec.y == -1.0); - assert_or_panic(vec.z == -12.0); - assert_or_panic(vec.w == 69); - assert_or_panic(vec.q == 55); -} - -bool c_ret_bool() { - return 1; -} -uint8_t c_ret_u8() { - return 0xff; -} -uint16_t c_ret_u16() { - return 0xffff; -} -uint32_t c_ret_u32() { - return 0xffffffff; -} -uint64_t c_ret_u64() { - return 0xffffffffffffffff; -} -int8_t c_ret_i8() { - return -1; -} -int16_t c_ret_i16() { - return -1; -} -int32_t c_ret_i32() { - return -1; -} -int64_t c_ret_i64() { - return -1; -} diff --git a/test/stage1/c_abi/main.zig b/test/stage1/c_abi/main.zig deleted file mode 100644 index 71a53bedea335c977f47a8b462b73f70dff35960..0000000000000000000000000000000000000000 --- a/test/stage1/c_abi/main.zig +++ /dev/null @@ -1,503 +0,0 @@ -const std = @import("std"); -const print = std.debug.print; -const expect = std.testing.expect; - -extern fn run_c_tests() void; - -export fn zig_panic() noreturn { - @panic("zig_panic called from C"); -} - -test "C importing Zig ABI Tests" { - run_c_tests(); -} - -extern fn c_u8(u8) void; -extern fn c_u16(u16) void; -extern fn c_u32(u32) void; -extern fn c_u64(u64) void; -extern fn c_struct_u128(U128) void; -extern fn c_i8(i8) void; -extern fn c_i16(i16) void; -extern fn c_i32(i32) void; -extern fn c_i64(i64) void; -extern fn c_struct_i128(I128) void; - -// On windows x64, the first 4 are passed via registers, others on the stack. -extern fn c_five_integers(i32, i32, i32, i32, i32) void; - -export fn zig_five_integers(a: i32, b: i32, c: i32, d: i32, e: i32) void { - expect(a == 12) catch @panic("test failure: zig_five_integers 12"); - expect(b == 34) catch @panic("test failure: zig_five_integers 34"); - expect(c == 56) catch @panic("test failure: zig_five_integers 56"); - expect(d == 78) catch @panic("test failure: zig_five_integers 78"); - expect(e == 90) catch @panic("test failure: zig_five_integers 90"); -} - -test "C ABI integers" { - c_u8(0xff); - c_u16(0xfffe); - c_u32(0xfffffffd); - c_u64(0xfffffffffffffffc); - c_struct_u128(.{ .value = 0xfffffffffffffffc }); - - c_i8(-1); - c_i16(-2); - c_i32(-3); - c_i64(-4); - c_struct_i128(.{ .value = -6 }); - c_five_integers(12, 34, 56, 78, 90); -} - -export fn zig_u8(x: u8) void { - expect(x == 0xff) catch @panic("test failure: zig_u8"); -} -export fn zig_u16(x: u16) void { - expect(x == 0xfffe) catch @panic("test failure: zig_u16"); -} -export fn zig_u32(x: u32) void { - expect(x == 0xfffffffd) catch @panic("test failure: zig_u32"); -} -export fn zig_u64(x: u64) void { - expect(x == 0xfffffffffffffffc) catch @panic("test failure: zig_u64"); -} -export fn zig_i8(x: i8) void { - expect(x == -1) catch @panic("test failure: zig_i8"); -} -export fn zig_i16(x: i16) void { - expect(x == -2) catch @panic("test failure: zig_i16"); -} -export fn zig_i32(x: i32) void { - expect(x == -3) catch @panic("test failure: zig_i32"); -} -export fn zig_i64(x: i64) void { - expect(x == -4) catch @panic("test failure: zig_i64"); -} - -const I128 = extern struct { - value: i128, -}; -const U128 = extern struct { - value: u128, -}; -export fn zig_struct_i128(a: I128) void { - expect(a.value == -6) catch @panic("test failure: zig_struct_i128"); -} -export fn zig_struct_u128(a: U128) void { - expect(a.value == 0xfffffffffffffffc) catch @panic("test failure: zig_struct_u128"); -} - -extern fn c_f32(f32) void; -extern fn c_f64(f64) void; - -// On windows x64, the first 4 are passed via registers, others on the stack. -extern fn c_five_floats(f32, f32, f32, f32, f32) void; - -export fn zig_five_floats(a: f32, b: f32, c: f32, d: f32, e: f32) void { - expect(a == 1.0) catch @panic("test failure: zig_five_floats 1.0"); - expect(b == 2.0) catch @panic("test failure: zig_five_floats 2.0"); - expect(c == 3.0) catch @panic("test failure: zig_five_floats 3.0"); - expect(d == 4.0) catch @panic("test failure: zig_five_floats 4.0"); - expect(e == 5.0) catch @panic("test failure: zig_five_floats 5.0"); -} - -test "C ABI floats" { - c_f32(12.34); - c_f64(56.78); - c_five_floats(1.0, 2.0, 3.0, 4.0, 5.0); -} - -export fn zig_f32(x: f32) void { - expect(x == 12.34) catch @panic("test failure: zig_f32"); -} -export fn zig_f64(x: f64) void { - expect(x == 56.78) catch @panic("test failure: zig_f64"); -} - -extern fn c_ptr(*anyopaque) void; - -test "C ABI pointer" { - c_ptr(@intToPtr(*anyopaque, 0xdeadbeef)); -} - -export fn zig_ptr(x: *anyopaque) void { - expect(@ptrToInt(x) == 0xdeadbeef) catch @panic("test failure: zig_ptr"); -} - -extern fn c_bool(bool) void; - -test "C ABI bool" { - c_bool(true); -} - -export fn zig_bool(x: bool) void { - expect(x) catch @panic("test failure: zig_bool"); -} - -const BigStruct = extern struct { - a: u64, - b: u64, - c: u64, - d: u64, - e: u8, -}; -extern fn c_big_struct(BigStruct) void; - -test "C ABI big struct" { - var s = BigStruct{ - .a = 1, - .b = 2, - .c = 3, - .d = 4, - .e = 5, - }; - c_big_struct(s); -} - -export fn zig_big_struct(x: BigStruct) void { - expect(x.a == 1) catch @panic("test failure: zig_big_struct 1"); - expect(x.b == 2) catch @panic("test failure: zig_big_struct 2"); - expect(x.c == 3) catch @panic("test failure: zig_big_struct 3"); - expect(x.d == 4) catch @panic("test failure: zig_big_struct 4"); - expect(x.e == 5) catch @panic("test failure: zig_big_struct 5"); -} - -const BigUnion = extern union { - a: BigStruct, -}; -extern fn c_big_union(BigUnion) void; - -test "C ABI big union" { - var x = BigUnion{ - .a = BigStruct{ - .a = 1, - .b = 2, - .c = 3, - .d = 4, - .e = 5, - }, - }; - c_big_union(x); -} - -export fn zig_big_union(x: BigUnion) void { - expect(x.a.a == 1) catch @panic("test failure: zig_big_union a"); - expect(x.a.b == 2) catch @panic("test failure: zig_big_union b"); - expect(x.a.c == 3) catch @panic("test failure: zig_big_union c"); - expect(x.a.d == 4) catch @panic("test failure: zig_big_union d"); - expect(x.a.e == 5) catch @panic("test failure: zig_big_union e"); -} - -const MedStructMixed = extern struct { - a: u32, - b: f32, - c: f32, - d: u32 = 0, -}; -extern fn c_med_struct_mixed(MedStructMixed) void; -extern fn c_ret_med_struct_mixed() MedStructMixed; - -test "C ABI medium struct of ints and floats" { - var s = MedStructMixed{ - .a = 1234, - .b = 100.0, - .c = 1337.0, - }; - c_med_struct_mixed(s); - var s2 = c_ret_med_struct_mixed(); - expect(s2.a == 1234) catch @panic("test failure"); - expect(s2.b == 100.0) catch @panic("test failure"); - expect(s2.c == 1337.0) catch @panic("test failure"); -} - -export fn zig_med_struct_mixed(x: MedStructMixed) void { - expect(x.a == 1234) catch @panic("test failure"); - expect(x.b == 100.0) catch @panic("test failure"); - expect(x.c == 1337.0) catch @panic("test failure"); -} - -const SmallStructInts = extern struct { - a: u8, - b: u8, - c: u8, - d: u8, -}; -extern fn c_small_struct_ints(SmallStructInts) void; -extern fn c_ret_small_struct_ints() SmallStructInts; - -test "C ABI small struct of ints" { - var s = SmallStructInts{ - .a = 1, - .b = 2, - .c = 3, - .d = 4, - }; - c_small_struct_ints(s); - var s2 = c_ret_small_struct_ints(); - expect(s2.a == 1) catch @panic("test failure"); - expect(s2.b == 2) catch @panic("test failure"); - expect(s2.c == 3) catch @panic("test failure"); - expect(s2.d == 4) catch @panic("test failure"); -} - -export fn zig_small_struct_ints(x: SmallStructInts) void { - expect(x.a == 1) catch @panic("test failure"); - expect(x.b == 2) catch @panic("test failure"); - expect(x.c == 3) catch @panic("test failure"); - expect(x.d == 4) catch @panic("test failure"); -} - -const SmallPackedStruct = packed struct { - a: u2, - b: u2, - c: u2, - d: u2, - e: bool, -}; -const c_small_packed_struct: fn (SmallPackedStruct) callconv(.C) void = @compileError("TODO: #1481"); -extern fn c_ret_small_packed_struct() SmallPackedStruct; - -// waiting on #1481 -//export fn zig_small_packed_struct(x: SmallPackedStruct) void { -// expect(x.a == 0) catch @panic("test failure"); -// expect(x.b == 1) catch @panic("test failure"); -// expect(x.c == 2) catch @panic("test failure"); -// expect(x.d == 3) catch @panic("test failure"); -// expect(x.e) catch @panic("test failure"); -//} - -test "C ABI small packed struct" { - var s = SmallPackedStruct{ .a = 0, .b = 1, .c = 2, .d = 3, .e = true }; - _ = s; //c_small_packed_struct(s); // waiting on #1481 - var s2 = c_ret_small_packed_struct(); - try expect(s2.a == 0); - try expect(s2.b == 1); - try expect(s2.c == 2); - try expect(s2.d == 3); - try expect(s2.e); -} - -const BigPackedStruct = packed struct { - a: u64, - b: u64, - c: u64, - d: u64, - e: u8, -}; -extern fn c_big_packed_struct(BigPackedStruct) void; -extern fn c_ret_big_packed_struct() BigPackedStruct; - -export fn zig_big_packed_struct(x: BigPackedStruct) void { - expect(x.a == 1) catch @panic("test failure"); - expect(x.b == 2) catch @panic("test failure"); - expect(x.c == 3) catch @panic("test failure"); - expect(x.d == 4) catch @panic("test failure"); - expect(x.e == 5) catch @panic("test failure"); -} - -test "C ABI big packed struct" { - var s = BigPackedStruct{ .a = 1, .b = 2, .c = 3, .d = 4, .e = 5 }; - c_big_packed_struct(s); - var s2 = c_ret_big_packed_struct(); - try expect(s2.a == 1); - try expect(s2.b == 2); - try expect(s2.c == 3); - try expect(s2.d == 4); - try expect(s2.e == 5); -} - -const SplitStructInt = extern struct { - a: u64, - b: u8, - c: u32, -}; -extern fn c_split_struct_ints(SplitStructInt) void; - -test "C ABI split struct of ints" { - var s = SplitStructInt{ - .a = 1234, - .b = 100, - .c = 1337, - }; - c_split_struct_ints(s); -} - -export fn zig_split_struct_ints(x: SplitStructInt) void { - expect(x.a == 1234) catch @panic("test failure"); - expect(x.b == 100) catch @panic("test failure"); - expect(x.c == 1337) catch @panic("test failure"); -} - -const SplitStructMixed = extern struct { - a: u64, - b: u8, - c: f32, -}; -extern fn c_split_struct_mixed(SplitStructMixed) void; -extern fn c_ret_split_struct_mixed() SplitStructMixed; - -test "C ABI split struct of ints and floats" { - var s = SplitStructMixed{ - .a = 1234, - .b = 100, - .c = 1337.0, - }; - c_split_struct_mixed(s); - var s2 = c_ret_split_struct_mixed(); - expect(s2.a == 1234) catch @panic("test failure"); - expect(s2.b == 100) catch @panic("test failure"); - expect(s2.c == 1337.0) catch @panic("test failure"); -} - -export fn zig_split_struct_mixed(x: SplitStructMixed) void { - expect(x.a == 1234) catch @panic("test failure"); - expect(x.b == 100) catch @panic("test failure"); - expect(x.c == 1337.0) catch @panic("test failure"); -} - -extern fn c_big_struct_both(BigStruct) BigStruct; - -test "C ABI sret and byval together" { - var s = BigStruct{ - .a = 1, - .b = 2, - .c = 3, - .d = 4, - .e = 5, - }; - var y = c_big_struct_both(s); - try expect(y.a == 10); - try expect(y.b == 11); - try expect(y.c == 12); - try expect(y.d == 13); - try expect(y.e == 14); -} - -export fn zig_big_struct_both(x: BigStruct) BigStruct { - expect(x.a == 30) catch @panic("test failure"); - expect(x.b == 31) catch @panic("test failure"); - expect(x.c == 32) catch @panic("test failure"); - expect(x.d == 33) catch @panic("test failure"); - expect(x.e == 34) catch @panic("test failure"); - var s = BigStruct{ - .a = 20, - .b = 21, - .c = 22, - .d = 23, - .e = 24, - }; - return s; -} - -const Vector3 = extern struct { - x: f32, - y: f32, - z: f32, -}; -extern fn c_small_struct_floats(Vector3) void; -extern fn c_small_struct_floats_extra(Vector3, ?[*]const u8) void; - -const Vector5 = extern struct { - x: f32, - y: f32, - z: f32, - w: f32, - q: f32, -}; -extern fn c_big_struct_floats(Vector5) void; - -test "C ABI structs of floats as parameter" { - var v3 = Vector3{ - .x = 3.0, - .y = 6.0, - .z = 12.0, - }; - c_small_struct_floats(v3); - c_small_struct_floats_extra(v3, "hello"); - - var v5 = Vector5{ - .x = 76.0, - .y = -1.0, - .z = -12.0, - .w = 69.0, - .q = 55, - }; - c_big_struct_floats(v5); -} - -export fn zig_ret_bool() bool { - return true; -} -export fn zig_ret_u8() u8 { - return 0xff; -} -export fn zig_ret_u16() u16 { - return 0xffff; -} -export fn zig_ret_u32() u32 { - return 0xffffffff; -} -export fn zig_ret_u64() u64 { - return 0xffffffffffffffff; -} -export fn zig_ret_i8() i8 { - return -1; -} -export fn zig_ret_i16() i16 { - return -1; -} -export fn zig_ret_i32() i32 { - return -1; -} -export fn zig_ret_i64() i64 { - return -1; -} - -export fn zig_ret_small_struct_ints() SmallStructInts { - return .{ - .a = 1, - .b = 2, - .c = 3, - .d = 4, - }; -} - -export fn zig_ret_med_struct_mixed() MedStructMixed { - return .{ - .a = 1234, - .b = 100.0, - .c = 1337.0, - }; -} - -export fn zig_ret_split_struct_mixed() SplitStructMixed { - return .{ - .a = 1234, - .b = 100, - .c = 1337.0, - }; -} - -extern fn c_ret_bool() bool; -extern fn c_ret_u8() u8; -extern fn c_ret_u16() u16; -extern fn c_ret_u32() u32; -extern fn c_ret_u64() u64; -extern fn c_ret_i8() i8; -extern fn c_ret_i16() i16; -extern fn c_ret_i32() i32; -extern fn c_ret_i64() i64; - -test "C ABI integer return types" { - try expect(c_ret_bool() == true); - - try expect(c_ret_u8() == 0xff); - try expect(c_ret_u16() == 0xffff); - try expect(c_ret_u32() == 0xffffffff); - try expect(c_ret_u64() == 0xffffffffffffffff); - - try expect(c_ret_i8() == -1); - try expect(c_ret_i16() == -1); - try expect(c_ret_i32() == -1); - try expect(c_ret_i64() == -1); -} diff --git a/test/standalone.zig b/test/standalone.zig index 2b24fe686d9242af79e047272447e59f2a174382..c0b5b804e2bec95bf21a07828a973cb5f4f7a844 100644 --- a/test/standalone.zig +++ b/test/standalone.zig @@ -41,11 +41,11 @@ pub fn addCases(cases: *tests.StandaloneContext) void { // C ABI compatibility issue: https://github.com/ziglang/zig/issues/1481 if (builtin.cpu.arch == .x86_64) { if (builtin.zig_backend == .stage1) { // https://github.com/ziglang/zig/issues/12222 - cases.addBuildFile("test/stage1/c_abi/build.zig", .{}); + cases.addBuildFile("test/c_abi/build.zig", .{}); } } // C ABI tests only pass for the Wasm target when using stage2 - cases.addBuildFile("test/stage1/c_abi/build_wasm.zig", .{ + cases.addBuildFile("test/c_abi/build_wasm.zig", .{ .requires_stage2 = true, .use_emulation = true, });