AC_DEFUN(PSI_STRUCT, [
AC_CHECK_SIZEOF($1, [], PSI_INCLUDES_DEFAULT($4))
psi_struct_name=`echo $1 | cut -d" " -f2`
- psi_struct_size=$AS_TR_SH(ac_cv_sizeof_struct_$1)
+ psi_struct_size=$AS_TR_SH(ac_cv_sizeof_$1)
psi_struct_members=
m4_foreach(member, [$2], [
AC_CHECK_MEMBER($1.member, [
PSI_MACRO(S_ISREG, int, [(mode_t m)], [(m)], sys/stat.h)
PSI_MACRO(S_ISLNK, int, [(mode_t m)], [(m)], sys/stat.h)
PSI_MACRO(S_ISSOCK, int, [(mode_t m)], [(m)], sys/stat.h)
- PSI_MACRO(S_TYPEISMQ, int, [(mode_t m)], [(m)], sys/stat.h)
- PSI_MACRO(S_TYPEISSEM, int, [(mode_t m)], [(m)], sys/stat.h)
- PSI_MACRO(S_TYPEISSHM, int, [(mode_t m)], [(m)], sys/stat.h)
- PSI_MACRO(S_TYPEISTMO, int, [(mode_t m)], [(m)], sys/stat.h)
+ PSI_MACRO(S_TYPEISMQ, int, [(struct stat *s)], [(s)], sys/stat.h)
+ PSI_MACRO(S_TYPEISSEM, int, [(struct stat *s)], [(s)], sys/stat.h)
+ PSI_MACRO(S_TYPEISSHM, int, [(struct stat *s)], [(s)], sys/stat.h)
+ PSI_MACRO(S_TYPEISTMO, int, [(struct stat *s)], [(s)], sys/stat.h)
dnl sys/time.h
PSI_STRUCT(struct timeval, [
[tv_sec],
AC_DEFINE_UNQUOTED(PHP_PSI_CONSTS, $PSI_CONSTS, Predefined constants)
AC_DEFINE_UNQUOTED(PHP_PSI_STRUCTS, $PSI_STRUCTS, Predefined structs)
- AC_DEFINE_UNQUOTED(PHP_PSI_SHLIB_SUFFIX, $SHLIB_SUFFIX_NAME, DL suffix)
+ AC_DEFINE_UNQUOTED(PHP_PSI_SHLIB_SUFFIX, ["]$SHLIB_SUFFIX_NAME["], DL suffix)
PHP_PSI_SRCDIR=PHP_EXT_SRCDIR(psi)
PHP_PSI_BUILDDIR=PHP_EXT_BUILDDIR(psi)
}
return 1;
}
+static inline decl *locate_free_decl(decls *decls, free_call *f) {
+ size_t i;
+
+ for (i = 0; i < decls->count; ++i) {
+ if (!strcmp(decls->list[i]->func->var->name, f->func)) {
+ f->decl = decls->list[i];
+ return decls->list[i];
+ }
+ }
+ return NULL;
+}
static inline int validate_impl_free_stmts(PSI_Data *data, impl *impl) {
- size_t i, j, k;
+ size_t i, j, k, l;
/* we can have any count of free stmts; freeing any out vars */
for (i = 0; i < impl->stmts->fre.count; ++i) {
free_stmt *fre = impl->stmts->fre.list[i];
- for (j = 0; j < fre->vars->count; ++j) {
- decl_var *free_var = fre->vars->vars[j];
- int check = 0;
+ for (j = 0; j < fre->calls->count; ++j) {
+ free_call *free_call = fre->calls->list[j];
- if (!strcmp(free_var->name, impl->decl->func->var->name)) {
- continue;
+ /* first find the decl of the free func */
+ if (!locate_free_decl(data->decls, free_call)) {
+ data->error(PSI_WARNING, "Unknown function '%s' in `free` statement"
+ " of implementation '%s'", free_call->func, impl->func->name);
+ return 0;
+ }
+ if (!impl->decl->args) {
+ data->error(PSI_WARNING, "Declaration '%s' of implementation '%s'"
+ " does not have any arguments to free",
+ impl->decl->func->var->name, impl->func->name);
}
- if (impl->decl->args) for (k = 0; k < impl->decl->args->count; ++k) {
- decl_arg *free_arg = impl->decl->args->args[k];
- if (!strcmp(free_var->name, free_arg->var->name)) {
- check = 1;
- free_var->arg = free_arg;
- break;
+ /* now check for known vars */
+ for (l = 0; l < free_call->vars->count; ++l) {
+ int check = 0;
+ decl_var *free_var = free_call->vars->vars[l];
+
+ for (k = 0; k < impl->decl->args->count; ++k) {
+ decl_arg *free_arg = impl->decl->args->args[k];
+
+ if (!strcmp(free_var->name, free_arg->var->name)) {
+ check = 1;
+ free_var->arg = free_arg;
+ break;
+ }
}
- }
- if (!check) {
- data->error(PSI_WARNING, "Unknown variable '%s' of `free` statement"
- " of implementation '%s'",
- free_var->name, impl->func->name);
- return 0;
+ if (!check) {
+ data->error(PSI_WARNING, "Unknown variable '%s' of `free` statement"
+ " of implementation '%s'",
+ free_var->name, impl->func->name);
+ return 0;
+ }
}
}
}
return C->closures = C->ops->compile(C);
}
+
+void PSI_ContextCall(PSI_Context *C, impl_val *ret_val, decl *decl, impl_val **args)
+{
+ C->ops->call(C, ret_val, decl, args);
+}
+
void PSI_ContextDtor(PSI_Context *C)
{
size_t i;
void (*init)(PSI_Context *C);
void (*dtor)(PSI_Context *C);
zend_function_entry *(*compile)(PSI_Context *C);
+ void (*call)(PSI_Context *C, impl_val *ret_val, decl *decl, impl_val **args);
};
struct PSI_Context {
void PSI_ContextBuild(PSI_Context *C, const char *path);
int PSI_ContextValidate(PSI_Context *C, PSI_Parser *P);
zend_function_entry *PSI_ContextCompile(PSI_Context *C);
+void PSI_ContextCall(PSI_Context *C, impl_val *ret_val, decl *decl, impl_val **args);
void PSI_ContextDtor(PSI_Context *C);
void PSI_ContextFree(PSI_Context **C);
return zfe;
}
+static void psi_ffi_call(PSI_Context *C, impl_val *ret_val, decl *decl, impl_val **args) {
+ ffi_cif signature;
+ ffi_type **types;
+ void **argps;
+ size_t i;
+
+ /* FIXME: cache in decl */
+
+ types = calloc(decl->args->count + 1, sizeof(*types));
+ argps = calloc(decl->args->count + 1, sizeof(*argps));
+ for (i = 0; i < decl->args->count; ++i) {
+ decl_arg *darg = decl->args->args[i];
+
+ types[i] = psi_ffi_decl_arg_type(darg);
+ argps[i] = args[i];
+ }
+
+ ffi_prep_cif(&signature, psi_ffi_abi(decl->abi->convention), decl->args->count,
+ psi_ffi_decl_arg_type(decl->func), types);
+ ffi_call(&signature, FFI_FN(decl->dlptr), ret_val, argps);
+
+ free(types);
+ free(argps);
+}
+
static PSI_ContextOps ops = {
psi_ffi_init,
psi_ffi_dtor,
psi_ffi_compile,
+ psi_ffi_call,
};
PSI_ContextOps *PSI_Libffi(void)
return zfe;
}
+static void psi_jit_call(PSI_Context *C, impl_val *ret_val, decl *decl, impl_val **args) {
+ jit_type_t signature, *types;
+ void **argps;
+ size_t i;
+
+ /* FIXME: cache in decl */
+
+ types = calloc(decl->args->count + 1, sizeof(*types));
+ argps = calloc(decl->args->count + 1, sizeof(*argps));
+ for (i = 0; i < decl->args->count; ++i) {
+ decl_arg *darg = decl->args->args[i];
+
+ types[i] = psi_jit_decl_arg_type(darg);
+ argps[i] = args[i];
+ }
+
+ signature = jit_type_create_signature(
+ psi_jit_abi(decl->abi->convention),
+ psi_jit_decl_arg_type(decl->func),
+ types, decl->args->count, 1);
+ jit_apply(signature, decl->dlptr, argps, decl->args->count, ret_val);
+
+ jit_type_free(signature);
+ free(types);
+ free(argps);
+
+}
+
static PSI_ContextOps ops = {
psi_jit_init,
psi_jit_dtor,
psi_jit_compile,
+ psi_jit_call,
};
PSI_ContextOps *PSI_Libjit(void)
void psi_do_free(free_stmt *fre)
{
- size_t i;
+ size_t i, j;
+ impl_val dummy, *argps[0x20];
+
+ for (i = 0; i < fre->calls->count; ++i) {
+ free_call *f = fre->calls->list[i];
- for (i = 0; i < fre->vars->count; ++i) {
- decl_var *dvar = fre->vars->vars[i];
+ for (j = 0; j < f->vars->count; ++j) {
+ decl_var *dvar = f->vars->vars[j];
+ decl_arg *darg = dvar->arg;
- if (dvar->arg && dvar->arg->let->out.ptr) {
- free(dvar->arg->let->out.ptr);
- dvar->arg->let->out.ptr = NULL;
+ argps[j] = &darg->let->out;
}
+
+ PSI_ContextCall(&PSI_G(context), &dummy, f->decl, argps);
}
}
free(ret);
}
-typedef struct free_stmt {
+typedef struct free_call {
+ char *func;
decl_vars *vars;
+ decl *decl;
+} free_call;
+
+static inline free_call *init_free_call(const char *func, decl_vars *vars) {
+ free_call *f = calloc(1, sizeof(*f));
+ f->func = strdup(func);
+ f->vars = vars;
+ return f;
+}
+
+static inline void free_free_call(free_call *f) {
+ free(f->func);
+ free(f);
+}
+
+typedef struct free_calls {
+ free_call **list;
+ size_t count;
+} free_calls;
+
+static inline free_calls *init_free_calls(free_call *f) {
+ free_calls *fcs = calloc(1, sizeof(*fcs));
+ if (f) {
+ fcs->count = 1;
+ fcs->list = calloc(1, sizeof(*fcs->list));
+ fcs->list[0] = f;
+ }
+ return fcs;
+}
+
+static inline void free_free_calls(free_calls *fcs) {
+ size_t i;
+
+ for (i = 0; i < fcs->count; ++i) {
+ free_free_call(fcs->list[i]);
+ }
+ free(fcs->list);
+ free(fcs);
+}
+
+static inline free_calls *add_free_call(free_calls *fcs, free_call *f) {
+ fcs->list = realloc(fcs->list, ++fcs->count * sizeof(*fcs->list));
+ fcs->list[fcs->count-1] = f;
+ return fcs;
+}
+
+typedef struct free_stmt {
+ free_calls *calls;
} free_stmt;
-static inline free_stmt *init_free_stmt(decl_vars *vars) {
- free_stmt *free_ = calloc(1, sizeof(*free_));
- free_->vars = vars;
- return free_;
+static inline free_stmt *init_free_stmt(free_calls *calls) {
+ free_stmt *f = calloc(1, sizeof(*f));
+ f->calls = calls;
+ return f;
}
-static inline void free_free_stmt(free_stmt *free_) {
- free_decl_vars(free_->vars);
- free(free_);
+static inline void free_free_stmt(free_stmt *f) {
+ free_free_calls(f->calls);
+ free(f);
}
typedef struct impl_stmt {
/* TOKEN is defined inside syntax_error */
%syntax_error {
PSI_ParserSyntaxError(P, P->psi.file.fn, P->line, "Unexpected token '%s'", TOKEN->text);
+ TOKEN->type = PSI_T_NAME;
}
%nonassoc NAME.
%type free_stmt {free_stmt*}
%destructor free_stmt {free_free_stmt($$);}
-free_stmt(free) ::= FREE decl_vars(vars) EOS. {
- free = init_free_stmt(vars);
+free_stmt(free) ::= FREE free_calls(calls) EOS. {
+ free = init_free_stmt(calls);
+}
+
+%type free_calls {free_calls*}
+%destructor free_calls {free_free_calls($$);}
+free_calls(calls) ::= free_call(call). {
+ calls = init_free_calls(call);
+}
+free_calls(calls) ::= free_calls(calls_) COMMA free_call(call). {
+ calls = add_free_call(calls_, call);
+}
+
+%type free_call {free_call*}
+%destructor free_call {free_free_call($$);}
+free_call(call) ::= NAME(F) LPAREN decl_vars(vars) RPAREN. {
+ call = init_free_call(F->text, vars);
}
%type impl_type {impl_type*}
let flags = intval($flags);
set $result = to_string(*buffer);
return to_int(idna_to_ascii_8z);
- free *buffer;
+ free free(buffer);
}
default char *idna_strerror(int rc);
function idn\strerror(int $rc) : string {