-#define PSI_CALC_FN(op) int psi_calc_##op(int t1, impl_val *v1, int t2, impl_val *v2, impl_val *res) \
-{ \
- if (t1 == t2) { \
- switch (t1) { \
- case PSI_T_FLOAT: PSI_CALC_OP(fval); break; \
- case PSI_T_DOUBLE: PSI_CALC_OP(dval); break; \
- case PSI_T_LONG_DOUBLE: PSI_CALC_OP_LD; break; \
- case PSI_T_INT8: PSI_CALC_OP(i8); break; \
- case PSI_T_UINT8: PSI_CALC_OP(u8); break; \
- case PSI_T_INT16: PSI_CALC_OP(i16); break; \
- case PSI_T_UINT16: PSI_CALC_OP(u16); break; \
- case PSI_T_INT32: PSI_CALC_OP(i32); break; \
- case PSI_T_UINT32: PSI_CALC_OP(u32); break; \
- case PSI_T_INT64: PSI_CALC_OP(i64); break; \
- case PSI_T_UINT64: PSI_CALC_OP(u64); break; \
- EMPTY_SWITCH_DEFAULT_CASE(); \
- } \
- return t1; \
- } else if (t1 == PSI_T_DOUBLE) { \
- switch (t2) { \
- case PSI_T_LONG_DOUBLE: PSI_CALC_OP2_LD2(dval); return t2; \
- case PSI_T_FLOAT: PSI_CALC_OP2(dval, dval, fval); break; \
- case PSI_T_INT8: PSI_CALC_OP2(dval, dval, i8); break; \
- case PSI_T_UINT8: PSI_CALC_OP2(dval, dval, u8); break; \
- case PSI_T_INT16: PSI_CALC_OP2(dval, dval, i16); break; \
- case PSI_T_UINT16: PSI_CALC_OP2(dval, dval, u16); break; \
- case PSI_T_INT32: PSI_CALC_OP2(dval, dval, i32); break; \
- case PSI_T_UINT32: PSI_CALC_OP2(dval, dval, u32); break; \
- case PSI_T_INT64: PSI_CALC_OP2(dval, dval, i64); break; \
- case PSI_T_UINT64: PSI_CALC_OP2(dval, dval, u64); break; \
- EMPTY_SWITCH_DEFAULT_CASE(); \
- } \
- return t1; \
- } else if (t2 == PSI_T_DOUBLE) { \
- switch (t1) { \
- case PSI_T_LONG_DOUBLE: PSI_CALC_OP2_LD1(dval); return t1; \
- case PSI_T_FLOAT: PSI_CALC_OP2(dval, fval, dval); break; \
- case PSI_T_INT8: PSI_CALC_OP2(dval, i8, dval); break; \
- case PSI_T_UINT8: PSI_CALC_OP2(dval, u8, dval); break; \
- case PSI_T_INT16: PSI_CALC_OP2(dval, i16, dval); break; \
- case PSI_T_UINT16: PSI_CALC_OP2(dval, u16, dval); break; \
- case PSI_T_INT32: PSI_CALC_OP2(dval, i32, dval); break; \
- case PSI_T_UINT32: PSI_CALC_OP2(dval, u32, dval); break; \
- case PSI_T_INT64: PSI_CALC_OP2(dval, i64, dval); break; \
- case PSI_T_UINT64: PSI_CALC_OP2(dval, u64, dval); break; \
- EMPTY_SWITCH_DEFAULT_CASE(); \
- } \
- return t2; \
- } else if (t1 == PSI_T_LONG_DOUBLE) { \
- PSI_CALC_NO_LD; \
- switch (t2) { \
- case PSI_T_DOUBLE: PSI_CALC_OP2_LD1(dval); break; \
- case PSI_T_FLOAT: PSI_CALC_OP2_LD1(fval); break; \
- case PSI_T_INT8: PSI_CALC_OP2_LD1(i8); break; \
- case PSI_T_UINT8: PSI_CALC_OP2_LD1(u8); break; \
- case PSI_T_INT16: PSI_CALC_OP2_LD1(i16); break; \
- case PSI_T_UINT16: PSI_CALC_OP2_LD1(u16); break; \
- case PSI_T_INT32: PSI_CALC_OP2_LD1(i32); break; \
- case PSI_T_UINT32: PSI_CALC_OP2_LD1(u32); break; \
- case PSI_T_INT64: PSI_CALC_OP2_LD1(i64); break; \
- case PSI_T_UINT64: PSI_CALC_OP2_LD1(u64); break; \
- EMPTY_SWITCH_DEFAULT_CASE(); \
- } \
- return t1; \
- } else if (t2 == PSI_T_LONG_DOUBLE) { \
- PSI_CALC_NO_LD; \
- switch (t1) { \
- case PSI_T_DOUBLE: PSI_CALC_OP2_LD2(dval); break; \
- case PSI_T_FLOAT: PSI_CALC_OP2_LD2(fval); break; \
- case PSI_T_INT8: PSI_CALC_OP2_LD2(i8); break; \
- case PSI_T_UINT8: PSI_CALC_OP2_LD2(u8); break; \
- case PSI_T_INT16: PSI_CALC_OP2_LD2(i16); break; \
- case PSI_T_UINT16: PSI_CALC_OP2_LD2(u16); break; \
- case PSI_T_INT32: PSI_CALC_OP2_LD2(i32); break; \
- case PSI_T_UINT32: PSI_CALC_OP2_LD2(u32); break; \
- case PSI_T_INT64: PSI_CALC_OP2_LD2(i64); break; \
- case PSI_T_UINT64: PSI_CALC_OP2_LD2(u64); break; \
- EMPTY_SWITCH_DEFAULT_CASE(); \
- } \
- return t2; \
- } else if (t1 == PSI_T_FLOAT) { \
- switch (t2) { \
- case PSI_T_LONG_DOUBLE: PSI_CALC_OP2_LD2(fval); return t2; \
- case PSI_T_DOUBLE: PSI_CALC_OP2(dval, fval, dval); return t2; \
- case PSI_T_INT8: PSI_CALC_OP2(fval, fval, i8); break; \
- case PSI_T_UINT8: PSI_CALC_OP2(fval, fval, u8); break; \
- case PSI_T_INT16: PSI_CALC_OP2(fval, fval, i16); break; \
- case PSI_T_UINT16: PSI_CALC_OP2(fval, fval, u16); break; \
- case PSI_T_INT32: PSI_CALC_OP2(fval, fval, i32); break; \
- case PSI_T_UINT32: PSI_CALC_OP2(fval, fval, u32); break; \
- case PSI_T_INT64: PSI_CALC_OP2(fval, fval, i64); break; \
- case PSI_T_UINT64: PSI_CALC_OP2(fval, fval, u64); break; \
- EMPTY_SWITCH_DEFAULT_CASE(); \
- } \
- return t1; \
- } else if (t2 == PSI_T_FLOAT) { \
- switch (t1) { \
- case PSI_T_LONG_DOUBLE: PSI_CALC_OP2_LD1(fval); return t1; \
- case PSI_T_DOUBLE: PSI_CALC_OP2(dval, dval, fval); return t1; \
- case PSI_T_INT8: PSI_CALC_OP2(fval, i8, fval); break; \
- case PSI_T_UINT8: PSI_CALC_OP2(fval, u8, fval); break; \
- case PSI_T_INT16: PSI_CALC_OP2(fval, i16, fval); break; \
- case PSI_T_UINT16: PSI_CALC_OP2(fval, u16, fval); break; \
- case PSI_T_INT32: PSI_CALC_OP2(fval, i32, fval); break; \
- case PSI_T_UINT32: PSI_CALC_OP2(fval, u32, fval); break; \
- case PSI_T_INT64: PSI_CALC_OP2(fval, i64, fval); break; \
- case PSI_T_UINT64: PSI_CALC_OP2(fval, u64, fval); break; \
- EMPTY_SWITCH_DEFAULT_CASE(); \
- } \
- return t2; \
- } else { \
- int64_t sval1 = v1->i64, sval2 = v2->i64; \
- uint64_t uval1 = v1->u64, uval2 = v2->u64; \
- switch (t1) { \
- case PSI_T_INT8: sval1 >>= 8; \
- case PSI_T_INT16: sval1 >>= 8; \
- case PSI_T_INT32: sval1 >>= 8; \
- case PSI_T_INT64: \
- switch (t2) { \
- case PSI_T_INT8: sval2 >>= 8; \
- case PSI_T_INT16: sval2 >>= 8; \
- case PSI_T_INT32: sval2 >>= 8; \
- case PSI_T_INT64: \
- res->i64 = PSI_CALC(sval1 , sval2); \
- return PSI_T_INT64; \
- case PSI_T_UINT8: uval2 >>= 8; \
- case PSI_T_UINT16: uval2 >>= 8; \
- case PSI_T_UINT32: uval2 >>= 8; \
- case PSI_T_UINT64: \
- res->i64 = PSI_CALC(sval1, uval2); \
- return PSI_T_INT64; \
- } \
- break; \
- case PSI_T_UINT8: uval1 >>= 8; \
- case PSI_T_UINT16: uval1 >>= 8; \
- case PSI_T_UINT32: uval1 >>= 8; \
- case PSI_T_UINT64: \
- switch (t2) { \
- case PSI_T_INT8: sval2 >>= 8; \
- case PSI_T_INT16: sval2 >>= 8; \
- case PSI_T_INT32: sval2 >>= 8; \
- case PSI_T_INT64: \
- res->i64 = PSI_CALC(uval1, sval2); \
- return PSI_T_INT64; \
- case PSI_T_UINT8: uval2 >>= 8; \
- case PSI_T_UINT16: uval2 >>= 8; \
- case PSI_T_UINT32: uval2 >>= 8; \
- case PSI_T_UINT64: \
- res->u64 = PSI_CALC(uval1, uval2); \
- return PSI_T_UINT64; \
- } \
- break; \
- } \
- } \
- ZEND_ASSERT(0); \
- return 0; \
-}
-
-#undef PSI_CALC
-#define PSI_CALC(var1, var2) (var1) + (var2)
-PSI_CALC_FN(add)
-#undef PSI_CALC
-#define PSI_CALC(var1, var2) (var1) * (var2)
-PSI_CALC_FN(mul)
-#undef PSI_CALC
-#define PSI_CALC(var1, var2) (var1) - (var2)
-PSI_CALC_FN(sub)
-#undef PSI_CALC
-#define PSI_CALC(var1, var2) (var1) / (var2)
-PSI_CALC_FN(div)
-
-static inline void psi_do_args(impl *impl) {
- size_t i;
-
- for (i = 0; i < impl->decl->args->count; ++i) {
- impl->decl->call.args[i] = impl->decl->args->args[i]->let->ptr;
- }
-
- if (!impl->decl->func->var->pointer_level) {
- decl_type *real = real_decl_type(impl->decl->func->type);
-
- switch (real->type) {
- case PSI_T_STRUCT:
- impl->decl->func->ptr = psi_array_to_struct(real->strct, NULL);
- break;
- }
- }
-}
-
-static inline impl_vararg *psi_do_varargs(impl *impl) {
- size_t i, j;
- impl_vararg *va = &impl->func->args->vararg;
- size_t vacount = va->args->count;
-
-
- if (!vacount) {
- return NULL;
- }
-
- va->types = ecalloc(vacount, sizeof(*va->types));
- va->values = ecalloc(vacount, sizeof(*va->values));
-
- for (i = 0, j = 0; i < vacount; ++i) {
- impl_arg *vaarg = va->args->args[i];
- void *to_free = NULL;
- token_t let_fn, vatype = va->name->type->type;
-
- if (vatype == PSI_T_MIXED) {
- switch (Z_TYPE_P(vaarg->_zv)) {
- case IS_TRUE:
- case IS_FALSE: vatype = PSI_T_BOOL; break;
- case IS_LONG: vatype = PSI_T_INT; break;
- case IS_DOUBLE: vatype = PSI_T_FLOAT; break;
- default: vatype = PSI_T_STRING; break;
- }
- }
-
-
- switch (vatype) {
- case PSI_T_BOOL: let_fn = PSI_T_BOOLVAL; break;
- case PSI_T_INT: let_fn = PSI_T_INTVAL; break;
- case PSI_T_FLOAT:
- case PSI_T_DOUBLE: let_fn = PSI_T_FLOATVAL;break;
- case PSI_T_STRING: let_fn = PSI_T_STRVAL; break;
- EMPTY_SWITCH_DEFAULT_CASE();
- }
-
- va->types[i] = vatype;
- /* FIXME: varargs with struct-by-value :) */
- if (!psi_let_val(let_fn, vaarg, &va->values[i], NULL, &to_free)) {
- return NULL;
- }
-
- if (to_free) {
- if (!va->free_list) {
- va->free_list = ecalloc(vacount - i + 1, sizeof(*va->free_list));
- }
- va->free_list[j++] = to_free;
- }
- }
-
- return va;
-}
-
-void psi_call(zend_execute_data *execute_data, zval *return_value, impl *impl)
-{
- size_t i;
- impl_vararg *va = NULL;
-
- memset(impl->decl->func->ptr, 0, sizeof(impl_val));
-
- if (SUCCESS != psi_parse_args(execute_data, impl)) {