#include "ffi/ffi.h"
#define IS_W(arg) ((arg).ctype == FFI_CTYPE_WORD)
#define IS_D(arg) ((arg).ctype == FFI_CTYPE_DOUBLE)
#define IS_F(arg) ((arg).ctype == FFI_CTYPE_FLOAT)
#define W(arg) ((ffi_word_t)(arg).v.i)
#define D(arg) ((arg).v.d)
#define F(arg) ((arg).v.f)
void ffi_set_word(struct ffi_arg *arg, ffi_word_t v) {
arg->ctype = FFI_CTYPE_WORD;
arg->v.i = v;
}
void ffi_set_bool(struct ffi_arg *arg, bool v) {
arg->ctype = FFI_CTYPE_BOOL;
arg->v.i = v;
}
void ffi_set_ptr(struct ffi_arg *arg, void *v) {
ffi_set_word(arg, (ffi_word_t) v);
}
void ffi_set_double(struct ffi_arg *arg, double v) {
arg->ctype = FFI_CTYPE_DOUBLE;
arg->v.d = v;
}
void ffi_set_float(struct ffi_arg *arg, float v) {
arg->ctype = FFI_CTYPE_FLOAT;
arg->v.f = v;
}
typedef ffi_word_t (*w4w_t)(ffi_word_t, ffi_word_t, ffi_word_t, ffi_word_t);
typedef ffi_word_t (*w5w_t)(ffi_word_t, ffi_word_t, ffi_word_t, ffi_word_t,
ffi_word_t);
typedef ffi_word_t (*w6w_t)(ffi_word_t, ffi_word_t, ffi_word_t, ffi_word_t,
ffi_word_t, ffi_word_t);
typedef ffi_word_t (*wdw_t)(double, ffi_word_t);
typedef ffi_word_t (*wwd_t)(ffi_word_t, double);
typedef ffi_word_t (*wdd_t)(double, double);
typedef ffi_word_t (*wwwd_t)(ffi_word_t, ffi_word_t, double);
typedef ffi_word_t (*wwdw_t)(ffi_word_t, double, ffi_word_t);
typedef ffi_word_t (*wwdd_t)(ffi_word_t, double, double);
typedef ffi_word_t (*wdww_t)(double, ffi_word_t, ffi_word_t);
typedef ffi_word_t (*wdwd_t)(double, ffi_word_t, double);
typedef ffi_word_t (*wddw_t)(double, double, ffi_word_t);
typedef ffi_word_t (*wddd_t)(double, double, double);
typedef ffi_word_t (*wfw_t)(float, ffi_word_t);
typedef ffi_word_t (*wwf_t)(ffi_word_t, float);
typedef ffi_word_t (*wff_t)(float, float);
typedef ffi_word_t (*wwwf_t)(ffi_word_t, ffi_word_t, float);
typedef ffi_word_t (*wwfw_t)(ffi_word_t, float, ffi_word_t);
typedef ffi_word_t (*wwff_t)(ffi_word_t, float, float);
typedef ffi_word_t (*wfww_t)(float, ffi_word_t, ffi_word_t);
typedef ffi_word_t (*wfwf_t)(float, ffi_word_t, float);
typedef ffi_word_t (*wffw_t)(float, float, ffi_word_t);
typedef ffi_word_t (*wfff_t)(float, float, float);
typedef bool (*b4w_t)(ffi_word_t, ffi_word_t, ffi_word_t, ffi_word_t);
typedef bool (*b5w_t)(ffi_word_t, ffi_word_t, ffi_word_t, ffi_word_t,
ffi_word_t);
typedef bool (*b6w_t)(ffi_word_t, ffi_word_t, ffi_word_t, ffi_word_t,
ffi_word_t, ffi_word_t);
typedef bool (*bdw_t)(double, ffi_word_t);
typedef bool (*bwd_t)(ffi_word_t, double);
typedef bool (*bdd_t)(double, double);
typedef bool (*bwwd_t)(ffi_word_t, ffi_word_t, double);
typedef bool (*bwdw_t)(ffi_word_t, double, ffi_word_t);
typedef bool (*bwdd_t)(ffi_word_t, double, double);
typedef bool (*bdww_t)(double, ffi_word_t, ffi_word_t);
typedef bool (*bdwd_t)(double, ffi_word_t, double);
typedef bool (*bddw_t)(double, double, ffi_word_t);
typedef bool (*bddd_t)(double, double, double);
typedef bool (*bfw_t)(float, ffi_word_t);
typedef bool (*bwf_t)(ffi_word_t, float);
typedef bool (*bff_t)(float, float);
typedef bool (*bwwf_t)(ffi_word_t, ffi_word_t, float);
typedef bool (*bwfw_t)(ffi_word_t, float, ffi_word_t);
typedef bool (*bwff_t)(ffi_word_t, float, float);
typedef bool (*bfww_t)(float, ffi_word_t, ffi_word_t);
typedef bool (*bfwf_t)(float, ffi_word_t, float);
typedef bool (*bffw_t)(float, float, ffi_word_t);
typedef bool (*bfff_t)(float, float, float);
typedef double (*d4w_t)(ffi_word_t, ffi_word_t, ffi_word_t, ffi_word_t);
typedef double (*d5w_t)(ffi_word_t, ffi_word_t, ffi_word_t, ffi_word_t,
ffi_word_t);
typedef double (*d6w_t)(ffi_word_t, ffi_word_t, ffi_word_t, ffi_word_t,
ffi_word_t, ffi_word_t);
typedef double (*ddw_t)(double, ffi_word_t);
typedef double (*dwd_t)(ffi_word_t, double);
typedef double (*ddd_t)(double, double);
typedef double (*dwwd_t)(ffi_word_t, ffi_word_t, double);
typedef double (*dwdw_t)(ffi_word_t, double, ffi_word_t);
typedef double (*dwdd_t)(ffi_word_t, double, double);
typedef double (*ddww_t)(double, ffi_word_t, ffi_word_t);
typedef double (*ddwd_t)(double, ffi_word_t, double);
typedef double (*dddw_t)(double, double, ffi_word_t);
typedef double (*dddd_t)(double, double, double);
typedef float (*f4w_t)(ffi_word_t, ffi_word_t, ffi_word_t, ffi_word_t);
typedef float (*f5w_t)(ffi_word_t, ffi_word_t, ffi_word_t, ffi_word_t,
ffi_word_t);
typedef float (*f6w_t)(ffi_word_t, ffi_word_t, ffi_word_t, ffi_word_t,
ffi_word_t, ffi_word_t);
typedef float (*ffw_t)(float, ffi_word_t);
typedef float (*fwf_t)(ffi_word_t, float);
typedef float (*fff_t)(float, float);
typedef float (*fwwf_t)(ffi_word_t, ffi_word_t, float);
typedef float (*fwfw_t)(ffi_word_t, float, ffi_word_t);
typedef float (*fwff_t)(ffi_word_t, float, float);
typedef float (*ffww_t)(float, ffi_word_t, ffi_word_t);
typedef float (*ffwf_t)(float, ffi_word_t, float);
typedef float (*fffw_t)(float, float, ffi_word_t);
typedef float (*ffff_t)(float, float, float);
int ffi_call(ffi_fn_t *func, int nargs, struct ffi_arg *res,
struct ffi_arg *args) {
int i, doubles = 0, floats = 0;
if (nargs > 6) return -1;
for (i = 0; i < nargs; i++) {
doubles += (IS_D(args[i]));
floats += (IS_F(args[i]));
}
if (doubles > 0 && floats > 0) {
return -1;
}
switch (res->ctype) {
case FFI_CTYPE_WORD: {
ffi_word_t r;
if (doubles == 0) {
if (floats == 0) {
if (nargs <= 4) {
w4w_t f = (w4w_t) func;
r = f(W(args[0]), W(args[1]), W(args[2]), W(args[3]));
} else if (nargs == 5) {
w5w_t f = (w5w_t) func;
r = f(W(args[0]), W(args[1]), W(args[2]), W(args[3]), W(args[4]));
} else if (nargs == 6) {
w6w_t f = (w6w_t) func;
r = f(W(args[0]), W(args[1]), W(args[2]), W(args[3]), W(args[4]),
W(args[5]));
} else {
abort();
}
} else {
switch (nargs) {
case 0:
case 1:
case 2:
if (IS_F(args[0]) && IS_F(args[1])) {
wff_t f = (wff_t) func;
r = f(F(args[0]), F(args[1]));
} else if (IS_F(args[0])) {
wfw_t f = (wfw_t) func;
r = f(F(args[0]), W(args[1]));
} else {
wwf_t f = (wwf_t) func;
r = f(W(args[0]), F(args[1]));
}
break;
case 3:
if (IS_W(args[0]) && IS_W(args[1]) && IS_F(args[2])) {
wwwf_t f = (wwwf_t) func;
r = f(W(args[0]), W(args[1]), F(args[2]));
} else if (IS_W(args[0]) && IS_F(args[1]) && IS_W(args[2])) {
wwfw_t f = (wwfw_t) func;
r = f(W(args[0]), F(args[1]), W(args[2]));
} else if (IS_W(args[0]) && IS_F(args[1]) && IS_F(args[2])) {
wwff_t f = (wwff_t) func;
r = f(W(args[0]), F(args[1]), F(args[2]));
} else if (IS_F(args[0]) && IS_W(args[1]) && IS_W(args[2])) {
wfww_t f = (wfww_t) func;
r = f(F(args[0]), W(args[1]), W(args[2]));
} else if (IS_F(args[0]) && IS_W(args[1]) && IS_F(args[2])) {
wfwf_t f = (wfwf_t) func;
r = f(F(args[0]), W(args[1]), F(args[2]));
} else if (IS_F(args[0]) && IS_F(args[1]) && IS_W(args[2])) {
wffw_t f = (wffw_t) func;
r = f(F(args[0]), F(args[1]), W(args[2]));
} else if (IS_F(args[0]) && IS_F(args[1]) && IS_F(args[2])) {
wfff_t f = (wfff_t) func;
r = f(F(args[0]), F(args[1]), F(args[2]));
} else {
abort();
}
break;
default:
return -1;
}
}
} else {
switch (nargs) {
case 0:
case 1:
case 2:
if (IS_D(args[0]) && IS_D(args[1])) {
wdd_t f = (wdd_t) func;
r = f(D(args[0]), D(args[1]));
} else if (IS_D(args[0])) {
wdw_t f = (wdw_t) func;
r = f(D(args[0]), W(args[1]));
} else {
wwd_t f = (wwd_t) func;
r = f(W(args[0]), D(args[1]));
}
break;
case 3:
if (IS_W(args[0]) && IS_W(args[1]) && IS_D(args[2])) {
wwwd_t f = (wwwd_t) func;
r = f(W(args[0]), W(args[1]), D(args[2]));
} else if (IS_W(args[0]) && IS_D(args[1]) && IS_W(args[2])) {
wwdw_t f = (wwdw_t) func;
r = f(W(args[0]), D(args[1]), W(args[2]));
} else if (IS_W(args[0]) && IS_D(args[1]) && IS_D(args[2])) {
wwdd_t f = (wwdd_t) func;
r = f(W(args[0]), D(args[1]), D(args[2]));
} else if (IS_D(args[0]) && IS_W(args[1]) && IS_W(args[2])) {
wdww_t f = (wdww_t) func;
r = f(D(args[0]), W(args[1]), W(args[2]));
} else if (IS_D(args[0]) && IS_W(args[1]) && IS_D(args[2])) {
wdwd_t f = (wdwd_t) func;
r = f(D(args[0]), W(args[1]), D(args[2]));
} else if (IS_D(args[0]) && IS_D(args[1]) && IS_W(args[2])) {
wddw_t f = (wddw_t) func;
r = f(D(args[0]), D(args[1]), W(args[2]));
} else if (IS_D(args[0]) && IS_D(args[1]) && IS_D(args[2])) {
wddd_t f = (wddd_t) func;
r = f(D(args[0]), D(args[1]), D(args[2]));
} else {
abort();
}
break;
default:
return -1;
}
}
res->v.i = (uint64_t) r;
} break;
case FFI_CTYPE_BOOL: {
ffi_word_t r;
if (doubles == 0) {
if (floats == 0) {
if (nargs <= 4) {
b4w_t f = (b4w_t) func;
r = f(W(args[0]), W(args[1]), W(args[2]), W(args[3]));
} else if (nargs == 5) {
b5w_t f = (b5w_t) func;
r = f(W(args[0]), W(args[1]), W(args[2]), W(args[3]), W(args[4]));
} else if (nargs == 6) {
b6w_t f = (b6w_t) func;
r = f(W(args[0]), W(args[1]), W(args[2]), W(args[3]), W(args[4]),
W(args[5]));
} else {
abort();
}
} else {
switch (nargs) {
case 0:
case 1:
case 2:
if (IS_F(args[0]) && IS_F(args[1])) {
bff_t f = (bff_t) func;
r = f(F(args[0]), F(args[1]));
} else if (IS_F(args[0])) {
bfw_t f = (bfw_t) func;
r = f(F(args[0]), W(args[1]));
} else {
bwf_t f = (bwf_t) func;
r = f(W(args[0]), F(args[1]));
}
break;
case 3:
if (IS_W(args[0]) && IS_W(args[1]) && IS_F(args[2])) {
bwwf_t f = (bwwf_t) func;
r = f(W(args[0]), W(args[1]), F(args[2]));
} else if (IS_W(args[0]) && IS_F(args[1]) && IS_W(args[2])) {
bwfw_t f = (bwfw_t) func;
r = f(W(args[0]), F(args[1]), W(args[2]));
} else if (IS_W(args[0]) && IS_F(args[1]) && IS_F(args[2])) {
bwff_t f = (bwff_t) func;
r = f(W(args[0]), F(args[1]), F(args[2]));
} else if (IS_F(args[0]) && IS_W(args[1]) && IS_W(args[2])) {
bfww_t f = (bfww_t) func;
r = f(F(args[0]), W(args[1]), W(args[2]));
} else if (IS_F(args[0]) && IS_W(args[1]) && IS_F(args[2])) {
bfwf_t f = (bfwf_t) func;
r = f(F(args[0]), W(args[1]), F(args[2]));
} else if (IS_F(args[0]) && IS_F(args[1]) && IS_W(args[2])) {
bffw_t f = (bffw_t) func;
r = f(F(args[0]), F(args[1]), W(args[2]));
} else if (IS_F(args[0]) && IS_F(args[1]) && IS_F(args[2])) {
bfff_t f = (bfff_t) func;
r = f(F(args[0]), F(args[1]), F(args[2]));
} else {
abort();
}
break;
default:
return -1;
}
}
} else {
switch (nargs) {
case 0:
case 1:
case 2:
if (IS_D(args[0]) && IS_D(args[1])) {
bdd_t f = (bdd_t) func;
r = f(D(args[0]), D(args[1]));
} else if (IS_D(args[0])) {
bdw_t f = (bdw_t) func;
r = f(D(args[0]), W(args[1]));
} else {
bwd_t f = (bwd_t) func;
r = f(W(args[0]), D(args[1]));
}
break;
case 3:
if (IS_W(args[0]) && IS_W(args[1]) && IS_D(args[2])) {
bwwd_t f = (bwwd_t) func;
r = f(W(args[0]), W(args[1]), D(args[2]));
} else if (IS_W(args[0]) && IS_D(args[1]) && IS_W(args[2])) {
bwdw_t f = (bwdw_t) func;
r = f(W(args[0]), D(args[1]), W(args[2]));
} else if (IS_W(args[0]) && IS_D(args[1]) && IS_D(args[2])) {
bwdd_t f = (bwdd_t) func;
r = f(W(args[0]), D(args[1]), D(args[2]));
} else if (IS_D(args[0]) && IS_W(args[1]) && IS_W(args[2])) {
bdww_t f = (bdww_t) func;
r = f(D(args[0]), W(args[1]), W(args[2]));
} else if (IS_D(args[0]) && IS_W(args[1]) && IS_D(args[2])) {
bdwd_t f = (bdwd_t) func;
r = f(D(args[0]), W(args[1]), D(args[2]));
} else if (IS_D(args[0]) && IS_D(args[1]) && IS_W(args[2])) {
bddw_t f = (bddw_t) func;
r = f(D(args[0]), D(args[1]), W(args[2]));
} else if (IS_D(args[0]) && IS_D(args[1]) && IS_D(args[2])) {
bddd_t f = (bddd_t) func;
r = f(D(args[0]), D(args[1]), D(args[2]));
} else {
abort();
}
break;
default:
return -1;
}
}
res->v.i = (uint64_t) r;
} break;
case FFI_CTYPE_DOUBLE: {
double r;
if (doubles == 0) {
if (nargs <= 4) {
d4w_t f = (d4w_t) func;
r = f(W(args[0]), W(args[1]), W(args[2]), W(args[3]));
} else if (nargs == 5) {
d5w_t f = (d5w_t) func;
r = f(W(args[0]), W(args[1]), W(args[2]), W(args[3]), W(args[4]));
} else if (nargs == 6) {
d6w_t f = (d6w_t) func;
r = f(W(args[0]), W(args[1]), W(args[2]), W(args[3]), W(args[4]),
W(args[5]));
} else {
abort();
}
} else {
switch (nargs) {
case 0:
case 1:
case 2:
if (IS_D(args[0]) && IS_D(args[1])) {
ddd_t f = (ddd_t) func;
r = f(D(args[0]), D(args[1]));
} else if (IS_D(args[0])) {
ddw_t f = (ddw_t) func;
r = f(D(args[0]), W(args[1]));
} else {
dwd_t f = (dwd_t) func;
r = f(W(args[0]), D(args[1]));
}
break;
case 3:
if (IS_W(args[0]) && IS_W(args[1]) && IS_D(args[2])) {
dwwd_t f = (dwwd_t) func;
r = f(W(args[0]), W(args[1]), D(args[2]));
} else if (IS_W(args[0]) && IS_D(args[1]) && IS_W(args[2])) {
dwdw_t f = (dwdw_t) func;
r = f(W(args[0]), D(args[1]), W(args[2]));
} else if (IS_W(args[0]) && IS_D(args[1]) && IS_D(args[2])) {
dwdd_t f = (dwdd_t) func;
r = f(W(args[0]), D(args[1]), D(args[2]));
} else if (IS_D(args[0]) && IS_W(args[1]) && IS_W(args[2])) {
ddww_t f = (ddww_t) func;
r = f(D(args[0]), W(args[1]), W(args[2]));
} else if (IS_D(args[0]) && IS_W(args[1]) && IS_D(args[2])) {
ddwd_t f = (ddwd_t) func;
r = f(D(args[0]), W(args[1]), D(args[2]));
} else if (IS_D(args[0]) && IS_D(args[1]) && IS_W(args[2])) {
dddw_t f = (dddw_t) func;
r = f(D(args[0]), D(args[1]), W(args[2]));
} else if (IS_D(args[0]) && IS_D(args[1]) && IS_D(args[2])) {
dddd_t f = (dddd_t) func;
r = f(D(args[0]), D(args[1]), D(args[2]));
} else {
abort();
}
break;
default:
return -1;
}
}
res->v.d = r;
} break;
case FFI_CTYPE_FLOAT: {
double r;
if (floats == 0) {
if (nargs <= 4) {
f4w_t f = (f4w_t) func;
r = f(W(args[0]), W(args[1]), W(args[2]), W(args[3]));
} else if (nargs == 5) {
f5w_t f = (f5w_t) func;
r = f(W(args[0]), W(args[1]), W(args[2]), W(args[3]), W(args[4]));
} else if (nargs == 6) {
f6w_t f = (f6w_t) func;
r = f(W(args[0]), W(args[1]), W(args[2]), W(args[3]), W(args[4]),
W(args[5]));
} else {
abort();
}
} else {
switch (nargs) {
case 0:
case 1:
case 2:
if (IS_F(args[0]) && IS_F(args[1])) {
fff_t f = (fff_t) func;
r = f(F(args[0]), F(args[1]));
} else if (IS_F(args[0])) {
ffw_t f = (ffw_t) func;
r = f(F(args[0]), W(args[1]));
} else {
fwf_t f = (fwf_t) func;
r = f(W(args[0]), F(args[1]));
}
break;
case 3:
if (IS_W(args[0]) && IS_W(args[1]) && IS_F(args[2])) {
fwwf_t f = (fwwf_t) func;
r = f(W(args[0]), W(args[1]), F(args[2]));
} else if (IS_W(args[0]) && IS_F(args[1]) && IS_W(args[2])) {
fwfw_t f = (fwfw_t) func;
r = f(W(args[0]), F(args[1]), W(args[2]));
} else if (IS_W(args[0]) && IS_F(args[1]) && IS_F(args[2])) {
fwff_t f = (fwff_t) func;
r = f(W(args[0]), F(args[1]), F(args[2]));
} else if (IS_F(args[0]) && IS_W(args[1]) && IS_W(args[2])) {
ffww_t f = (ffww_t) func;
r = f(F(args[0]), W(args[1]), W(args[2]));
} else if (IS_F(args[0]) && IS_W(args[1]) && IS_F(args[2])) {
ffwf_t f = (ffwf_t) func;
r = f(F(args[0]), W(args[1]), F(args[2]));
} else if (IS_F(args[0]) && IS_F(args[1]) && IS_W(args[2])) {
fffw_t f = (fffw_t) func;
r = f(F(args[0]), F(args[1]), W(args[2]));
} else if (IS_F(args[0]) && IS_F(args[1]) && IS_F(args[2])) {
ffff_t f = (ffff_t) func;
r = f(F(args[0]), F(args[1]), F(args[2]));
} else {
abort();
}
break;
default:
return -1;
}
}
res->v.f = r;
} break;
}
return 0;
}