flush
[m6w6/ext-psi] / src / compiler.c
1 #include <stdlib.h>
2
3 #include <jit/jit.h>
4
5 #include <php.h>
6 #include <Zend/zend_API.h>
7
8 #include "compiler.h"
9
10 PSI_Compiler *PSI_CompilerInit(PSI_Compiler *C, PSI_Validator *V, void *context)
11 {
12 if (!C) {
13 C = malloc(sizeof(*C));
14 }
15 memset(C, 0, sizeof(*C));
16
17 PSI_DataExchange((PSI_Data *) C, (PSI_Data *) V);
18
19 C->context = context;
20
21 return C;
22 }
23
24 void PSI_CompilerDtor(PSI_Compiler *C)
25 {
26 PSI_DataDtor((PSI_Data *) C);
27 }
28
29 void PSI_Compiler_Free(PSI_Compiler **C)
30 {
31 if (*C) {
32 PSI_CompilerDtor(*C);
33 free(*C);
34 *C = NULL;
35 }
36 }
37
38 typedef struct PSI_ClosureData {
39 void *context;
40 impl *impl;
41 } PSI_ClosureData;
42
43 static inline PSI_ClosureData *PSI_ClosureDataAlloc(void *context, impl *impl) {
44 PSI_ClosureData *data = malloc(sizeof(*data));
45
46 data->context = context;
47 data->impl = impl;
48
49 return data;
50 }
51
52 static inline size_t impl_num_min_args(impl *impl) {
53 size_t i, n = impl->func->args->count;
54
55 for (i = 0; i < impl->func->args->count; ++i) {
56 if (impl->func->args->args[i]->def) {
57 --n;
58 }
59 }
60 return n;
61 }
62
63 static void psi_jit_closure_handler(jit_type_t signature, void *result, void **args, void *user_data)
64 {
65 zend_execute_data *execute_data = *(zend_execute_data **)args[0];
66 zval *return_value = *(zval **)args[1];
67 PSI_ClosureData *data = user_data;
68 impl_arg *iarg;
69
70 if (!data->impl->func->args->count) {
71 if (SUCCESS != zend_parse_parameters_none()) {
72 return;
73 }
74 } else
75 ZEND_PARSE_PARAMETERS_START(impl_num_min_args(data->impl), data->impl->func->args->count)
76 nextarg:
77 iarg = data->impl->func->args->args[_i];
78 if (iarg->def) {
79 Z_PARAM_OPTIONAL;
80 }
81 if (PSI_T_BOOL == iarg->type->type) {
82 if (iarg->def) {
83 iarg->val.bval = iarg->def->type == PSI_T_TRUE ? 1 : 0;
84 }
85 Z_PARAM_BOOL(iarg->val.bval);
86 } else if (PSI_T_INT == iarg->type->type) {
87 if (iarg->def) {
88 iarg->val.lval = atol(iarg->def->text);
89 }
90 Z_PARAM_LONG(iarg->val.lval);
91 } else if (PSI_T_FLOAT == iarg->type->type) {
92 if (iarg->def) {
93 iarg->val.dval = strtod(iarg->def->text, NULL);
94 }
95 Z_PARAM_DOUBLE(iarg->val.dval);
96 } else if (PSI_T_STRING == iarg->type->type) {
97 if (iarg->def) {
98 /* FIXME */
99 iarg->val.str.len = strlen(iarg->def->text) - 2;
100 iarg->val.str.val = &iarg->def->text[1];
101 }
102 Z_PARAM_STRING(iarg->val.str.val, iarg->val.str.len);
103 } else {
104 error_code = ZPP_ERROR_FAILURE;
105 break;
106 }
107 goto nextarg;
108 ZEND_PARSE_PARAMETERS_END();
109 }
110
111 zend_function_entry *PSI_CompilerCompile(PSI_Compiler *C)
112 {
113 size_t i, j = 0;
114 jit_type_t signature, params[] = {
115 jit_type_void_ptr,
116 jit_type_void_ptr
117 };
118 zend_function_entry *zfe = calloc(C->impls->count + 1, sizeof(*zfe));
119
120 for (i = 0; i < C->impls->count; ++i) {
121 zend_function_entry *zf;
122 volatile PSI_ClosureData *data;
123
124 if (!C->impls->list[i]->decl) {
125 continue;
126 }
127 signature = jit_type_create_signature(jit_abi_vararg, jit_type_void, params, 2, 1);
128
129 zf = &zfe[j++];
130 data = PSI_ClosureDataAlloc(C->context, C->impls->list[i]);
131 zf->fname = C->impls->list[i]->func->name;
132 zf->handler = jit_closure_create(C->context, signature, &psi_jit_closure_handler, data);
133 fprintf(stderr, "Compiled closure for %s\n", zf->fname);
134 printf("Closuredata: %p of closure %p\n", data, zf->handler);
135 }
136
137 return zfe;
138 }