C ABI: Add tests for complex float/double support

These tests will be failing on many platforms until #8465 is resolved.

Luckily, the particular function signature used for __divXc3 and __mulXc3
seems to be OK on x86-64.
This commit is contained in:
Cody Tapscott 2022-10-09 23:24:29 -07:00
parent 879fb0c57c
commit a06185f362
2 changed files with 176 additions and 0 deletions

View File

@ -2,6 +2,7 @@
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <complex.h>
void zig_panic();
@ -50,6 +51,13 @@ void zig_ptr(void *);
void zig_bool(bool);
// Note: These two functions match the signature of __mulsc3 and __muldc3 in compiler-rt (and libgcc)
float complex zig_cmultf_comp(float a_r, float a_i, float b_r, float b_i);
double complex zig_cmultd_comp(double a_r, double a_i, double b_r, double b_i);
float complex zig_cmultf(float complex a, float complex b);
double complex zig_cmultd(double complex a, double complex b);
struct BigStruct {
uint64_t a;
uint64_t b;
@ -167,6 +175,43 @@ void run_c_tests(void) {
zig_bool(true);
// TODO: Resolve https://github.com/ziglang/zig/issues/8465
//{
// float complex a = 1.25f + I * 2.6f;
// float complex b = 11.3f - I * 1.5f;
// float complex z = zig_cmultf(a, b);
// assert_or_panic(creal(z) == 1.5f);
// assert_or_panic(cimag(z) == 13.5f);
//}
{
double complex a = 1.25 + I * 2.6;
double complex b = 11.3 - I * 1.5;
double complex z = zig_cmultd(a, b);
assert_or_panic(creal(z) == 1.5);
assert_or_panic(cimag(z) == 13.5);
}
{
float a_r = 1.25f;
float a_i = 2.6f;
float b_r = 11.3f;
float b_i = -1.5f;
float complex z = zig_cmultf_comp(a_r, a_i, b_r, b_i);
assert_or_panic(creal(z) == 1.5f);
assert_or_panic(cimag(z) == 13.5f);
}
{
double a_r = 1.25;
double a_i = 2.6;
double b_r = 11.3;
double b_i = -1.5;
double complex z = zig_cmultd_comp(a_r, a_i, b_r, b_i);
assert_or_panic(creal(z) == 1.5);
assert_or_panic(cimag(z) == 13.5);
}
{
struct BigStruct s = {1, 2, 3, 4, 5};
zig_big_struct(s);
@ -321,6 +366,42 @@ void c_five_floats(float a, float b, float c, float d, float e) {
assert_or_panic(e == 5.0);
}
float complex c_cmultf_comp(float a_r, float a_i, float b_r, float b_i) {
assert_or_panic(a_r == 1.25f);
assert_or_panic(a_i == 2.6f);
assert_or_panic(b_r == 11.3f);
assert_or_panic(b_i == -1.5f);
return 1.5f + I * 13.5f;
}
double complex c_cmultd_comp(double a_r, double a_i, double b_r, double b_i) {
assert_or_panic(a_r == 1.25);
assert_or_panic(a_i == 2.6);
assert_or_panic(b_r == 11.3);
assert_or_panic(b_i == -1.5);
return 1.5 + I * 13.5;
}
float complex c_cmultf(float complex a, float complex b) {
assert_or_panic(creal(a) == 1.25f);
assert_or_panic(cimag(a) == 2.6f);
assert_or_panic(creal(b) == 11.3f);
assert_or_panic(cimag(b) == -1.5f);
return 1.5f + I * 13.5f;
}
double complex c_cmultd(double complex a, double complex b) {
assert_or_panic(creal(a) == 1.25);
assert_or_panic(cimag(a) == 2.6);
assert_or_panic(creal(b) == 11.3);
assert_or_panic(cimag(b) == -1.5);
return 1.5 + I * 13.5;
}
void c_big_struct(struct BigStruct x) {
assert_or_panic(x.a == 1);
assert_or_panic(x.b == 2);

View File

@ -145,6 +145,101 @@ export fn zig_bool(x: bool) void {
expect(x) catch @panic("test failure: zig_bool");
}
// TODO: Replace these with the correct types once we resolve
// https://github.com/ziglang/zig/issues/8465
//
// For now, we have no way of referring to the _Complex C types from Zig,
// so our ABI is unavoidably broken on some platforms (such as i386)
const ComplexFloat = extern struct {
real: f32,
imag: f32,
};
const ComplexDouble = extern struct {
real: f64,
imag: f64,
};
// Note: These two functions match the signature of __mulsc3 and __muldc3 in compiler-rt (and libgcc)
extern fn c_cmultf_comp(a_r: f32, a_i: f32, b_r: f32, b_i: f32) ComplexFloat;
extern fn c_cmultd_comp(a_r: f64, a_i: f64, b_r: f64, b_i: f64) ComplexDouble;
extern fn c_cmultf(a: ComplexFloat, b: ComplexFloat) ComplexFloat;
extern fn c_cmultd(a: ComplexDouble, b: ComplexDouble) ComplexDouble;
test "C ABI complex float" {
if (true) return error.SkipZigTest; // See https://github.com/ziglang/zig/issues/8465
const a = ComplexFloat{ .real = 1.25, .imag = 2.6 };
const b = ComplexFloat{ .real = 11.3, .imag = -1.5 };
const z = c_cmultf(a, b);
expect(z.real == 1.5) catch @panic("test failure: zig_complex_float 1");
expect(z.imag == 13.5) catch @panic("test failure: zig_complex_float 2");
}
test "C ABI complex float by component" {
const a = ComplexFloat{ .real = 1.25, .imag = 2.6 };
const b = ComplexFloat{ .real = 11.3, .imag = -1.5 };
const z2 = c_cmultf_comp(a.real, a.imag, b.real, b.imag);
expect(z2.real == 1.5) catch @panic("test failure: zig_complex_float 3");
expect(z2.imag == 13.5) catch @panic("test failure: zig_complex_float 4");
}
test "C ABI complex double" {
const a = ComplexDouble{ .real = 1.25, .imag = 2.6 };
const b = ComplexDouble{ .real = 11.3, .imag = -1.5 };
const z = c_cmultd(a, b);
expect(z.real == 1.5) catch @panic("test failure: zig_complex_double 1");
expect(z.imag == 13.5) catch @panic("test failure: zig_complex_double 2");
}
test "C ABI complex double by component" {
const a = ComplexDouble{ .real = 1.25, .imag = 2.6 };
const b = ComplexDouble{ .real = 11.3, .imag = -1.5 };
const z = c_cmultd_comp(a.real, a.imag, b.real, b.imag);
expect(z.real == 1.5) catch @panic("test failure: zig_complex_double 3");
expect(z.imag == 13.5) catch @panic("test failure: zig_complex_double 4");
}
export fn zig_cmultf(a: ComplexFloat, b: ComplexFloat) ComplexFloat {
expect(a.real == 1.25) catch @panic("test failure: zig_cmultf 1");
expect(a.imag == 2.6) catch @panic("test failure: zig_cmultf 2");
expect(b.real == 11.3) catch @panic("test failure: zig_cmultf 3");
expect(b.imag == -1.5) catch @panic("test failure: zig_cmultf 4");
return .{ .real = 1.5, .imag = 13.5 };
}
export fn zig_cmultd(a: ComplexDouble, b: ComplexDouble) ComplexDouble {
expect(a.real == 1.25) catch @panic("test failure: zig_cmultd 1");
expect(a.imag == 2.6) catch @panic("test failure: zig_cmultd 2");
expect(b.real == 11.3) catch @panic("test failure: zig_cmultd 3");
expect(b.imag == -1.5) catch @panic("test failure: zig_cmultd 4");
return .{ .real = 1.5, .imag = 13.5 };
}
export fn zig_cmultf_comp(a_r: f32, a_i: f32, b_r: f32, b_i: f32) ComplexFloat {
expect(a_r == 1.25) catch @panic("test failure: zig_cmultf_comp 1");
expect(a_i == 2.6) catch @panic("test failure: zig_cmultf_comp 2");
expect(b_r == 11.3) catch @panic("test failure: zig_cmultf_comp 3");
expect(b_i == -1.5) catch @panic("test failure: zig_cmultf_comp 4");
return .{ .real = 1.5, .imag = 13.5 };
}
export fn zig_cmultd_comp(a_r: f64, a_i: f64, b_r: f64, b_i: f64) ComplexDouble {
expect(a_r == 1.25) catch @panic("test failure: zig_cmultd_comp 1");
expect(a_i == 2.6) catch @panic("test failure: zig_cmultd_comp 2");
expect(b_r == 11.3) catch @panic("test failure: zig_cmultd_comp 3");
expect(b_i == -1.5) catch @panic("test failure: zig_cmultd_comp 4");
return .{ .real = 1.5, .imag = 13.5 };
}
const BigStruct = extern struct {
a: u64,
b: u64,