0c5fcb5e63d35a5b3675774c56b84ea617928b4b
[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 typedef struct PSI_ClosureData {
25 void *context;
26 impl *impl;
27 } PSI_ClosureData;
28
29 static inline PSI_ClosureData *PSI_ClosureDataAlloc(void *context, impl *impl) {
30 PSI_ClosureData *data = malloc(sizeof(*data));
31
32 data->context = context;
33 data->impl = impl;
34
35 return data;
36 }
37
38 static inline size_t impl_num_min_args(impl *impl) {
39 size_t i, n = impl->func->args->count;
40
41 for (i = 0; i < impl->func->args->count; ++i) {
42 if (impl->func->args->args[i]->def) {
43 --n;
44 }
45 }
46 return n;
47 }
48
49 void jit_closure_handler(jit_type_t signature, void *result, void **args, void *user_data)
50 {
51 zend_execute_data *execute_data = args[0];
52 zval *return_value = args[1];
53 PSI_ClosureData *data = user_data;
54 impl_arg *iarg;
55
56 if (!data->impl->func->args->count) {
57 if (SUCCESS != zend_parse_parameters_none()) {
58 return;
59 }
60 } else
61 ZEND_PARSE_PARAMETERS_START(impl_num_min_args(data->impl), data->impl->func->args->count)
62 nextarg:
63 iarg = data->impl->func->args->args[_i];
64 if (iarg->def) {
65 Z_PARAM_OPTIONAL;
66 }
67 if (PSI_T_BOOL == iarg->type->type) {
68 if (iarg->def) {
69 iarg->val.bval = iarg->def->type == PSI_T_TRUE ? 1 : 0;
70 }
71 Z_PARAM_BOOL(iarg->val.bval);
72 } else if (PSI_T_INT == iarg->type->type) {
73 if (iarg->def) {
74 iarg->val.lval = atol(iarg->def->text);
75 }
76 Z_PARAM_LONG(iarg->val.lval);
77 } else if (PSI_T_FLOAT == iarg->type->type) {
78 if (iarg->def) {
79 iarg->val.dval = strtod(iarg->def->text, NULL);
80 }
81 Z_PARAM_DOUBLE(iarg->val.dval);
82 } else if (PSI_T_STRING == iarg->type->type) {
83 if (iarg->def) {
84 /* FIXME */
85 iarg->val.str.len = strlen(iarg->def->text) - 2;
86 iarg->val.str.val = &iarg->def->text[1];
87 }
88 Z_PARAM_STRING(iarg->val.str.val, iarg->val.str.len);
89 } else {
90 error_code = ZPP_ERROR_FAILURE;
91 break;
92 }
93 goto nextarg;
94 ZEND_PARSE_PARAMETERS_END();
95 }
96
97 zend_function_entry *PSI_CompilerCompile(PSI_Compiler *C)
98 {
99 size_t i, j = 0;
100 jit_type_t signature, params[] = {
101 jit_type_void_ptr,
102 jit_type_void_ptr
103 };
104 zend_function_entry *zfe = calloc(C->impls->count + 1, sizeof(*zfe));
105
106 for (i = 0; i < C->impls->count; ++i) {
107 zend_function_entry *zf;
108 PSI_ClosureData *data;
109
110 if (!C->impls->list[i]->decl) {
111 continue;
112 }
113 signature = jit_type_create_signature(jit_abi_cdecl, jit_type_void, params, 2, 1);
114
115 zf = &zfe[++j];
116 data = PSI_ClosureDataAlloc(C->context, C->impls->list[i]);
117 zf->fname = C->impls->list[i]->func->name;
118 zf->handler = jit_closure_create(C->context, signature, jit_closure_handler, data);
119 }
120
121 return zfe;
122 }