273c47890818a95cf16770f5d4fd124dbc391bcf
14 static void psi_jit_handler(jit_type_t _sig
, void *result
, void **_args
, void *_data
);
16 static inline jit_abi_t
psi_jit_abi(const char *convention
) {
19 static inline jit_type_t
psi_jit_token_type(token_t t
) {
24 return jit_type_sbyte
;
26 return jit_type_ubyte
;
28 return jit_type_short
;
30 return jit_type_ushort
;
38 return jit_type_ulong
;
40 return jit_type_sys_bool
;
42 return jit_type_sys_float
;
44 return jit_type_sys_double
;
46 return jit_type_void_ptr
;
47 EMPTY_SWITCH_DEFAULT_CASE();
50 static inline jit_type_t
psi_jit_impl_type(token_t impl_type
) {
53 return jit_type_sbyte
;
57 return jit_type_void_ptr
;
60 return jit_type_sys_double
;
61 EMPTY_SWITCH_DEFAULT_CASE();
64 static inline jit_type_t
psi_jit_decl_type(decl_type
*type
) {
65 return psi_jit_token_type(real_decl_type(type
)->type
);
67 static inline jit_type_t
psi_jit_decl_arg_type(decl_arg
*darg
) {
68 if (darg
->var
->pointer_level
) {
69 return jit_type_void_ptr
;
71 return psi_jit_decl_type(darg
->type
);
75 typedef struct PSI_LibjitContext
{
79 struct PSI_LibjitData
**list
;
84 typedef struct PSI_LibjitCall
{
87 void *params
[1]; /* [type1, type2, NULL, arg1, arg2] ... */
90 typedef struct PSI_LibjitData
{
91 PSI_LibjitContext
*context
;
93 zend_internal_arg_info
*arginfo
;
96 static inline PSI_LibjitCall
*PSI_LibjitCallAlloc(PSI_Context
*C
, decl
*decl
) {
97 size_t i
, c
= decl
->args
? decl
->args
->count
: 0;
98 PSI_LibjitCall
*call
= calloc(1, sizeof(*call
) + 2 * c
* sizeof(void *));
100 for (i
= 0; i
< c
; ++i
) {
101 call
->params
[i
] = psi_jit_decl_arg_type(decl
->args
->args
[i
]);
103 call
->params
[c
] = NULL
;
105 decl
->call
.info
= call
;
106 decl
->call
.rval
= decl
->func
->ptr
;
108 decl
->call
.args
= (void **) &call
->params
[c
+1];
110 call
->signature
= jit_type_create_signature(
111 psi_jit_abi(decl
->abi
->convention
),
112 psi_jit_decl_arg_type(decl
->func
),
113 (jit_type_t
*) call
->params
, c
, 1);
117 static inline void PSI_LibjitCallInitClosure(PSI_Context
*C
, PSI_LibjitCall
*call
, impl
*impl
) {
118 PSI_LibjitContext
*context
= C
->context
;
119 call
->closure
= jit_closure_create(context
->jit
, context
->signature
,
120 &psi_jit_handler
, impl
);
123 static inline void PSI_LibjitCallFree(PSI_LibjitCall
*call
) {
124 jit_type_free(call
->signature
);
128 static inline PSI_LibjitContext
*PSI_LibjitContextInit(PSI_LibjitContext
*L
) {
129 jit_type_t params
[] = {
135 L
= malloc(sizeof(*L
));
137 memset(L
, 0, sizeof(*L
));
139 L
->jit
= jit_context_create();
140 L
->signature
= jit_type_create_signature(jit_abi_cdecl
, jit_type_void
,
146 static inline void PSI_LibjitContextDtor(PSI_LibjitContext
*L
) {
147 jit_type_free(L
->signature
);
148 jit_context_destroy(L
->jit
);
151 static inline void PSI_LibjitContextFree(PSI_LibjitContext
**L
) {
153 PSI_LibjitContextDtor(*L
);
159 static void psi_jit_handler(jit_type_t _sig
, void *result
, void **_args
, void *_data
)
161 psi_call(*(zend_execute_data
**)_args
[0], *(zval
**)_args
[1], _data
);
164 static void psi_jit_init(PSI_Context
*C
)
166 C
->context
= PSI_LibjitContextInit(NULL
);
169 static void psi_jit_dtor(PSI_Context
*C
)
174 for (i
= 0; i
< C
->decls
->count
; ++i
) {
175 decl
*decl
= C
->decls
->list
[i
];
177 PSI_LibjitCallFree(decl
->call
.info
);
180 PSI_LibjitContextFree((void *) &C
->context
);
183 static zend_function_entry
*psi_jit_compile(PSI_Context
*C
)
186 zend_function_entry
*zfe
;
187 PSI_LibjitContext
*ctx
= C
->context
;
193 zfe
= calloc(C
->impls
->count
+ 1, sizeof(*zfe
));
194 jit_context_build_start(ctx
->jit
);
196 for (i
= 0; i
< C
->impls
->count
; ++i
) {
197 zend_function_entry
*zf
= &zfe
[j
];
198 PSI_LibjitCall
*call
;
199 impl
*impl
= C
->impls
->list
[i
];
205 call
= PSI_LibjitCallAlloc(C
, impl
->decl
);
206 PSI_LibjitCallInitClosure(C
, call
, impl
);
208 zf
->fname
= impl
->func
->name
+ (impl
->func
->name
[0] == '\\');
209 zf
->num_args
= impl
->func
->args
->count
;
210 zf
->handler
= call
->closure
;
211 zf
->arg_info
= psi_internal_arginfo(impl
);
215 for (i
= 0; i
< C
->decls
->count
; ++i
) {
216 decl
*decl
= C
->decls
->list
[i
];
222 PSI_LibjitCallAlloc(C
, decl
);
225 jit_context_build_end(ctx
->jit
);
230 static void psi_jit_call(PSI_Context
*C
, decl_callinfo
*decl_call
, impl_vararg
*va
) {
231 PSI_LibjitCall
*call
= decl_call
->info
;
234 jit_type_t signature
;
235 size_t i
, nfixedargs
= decl_call
->argc
, ntotalargs
= nfixedargs
+ va
->args
->count
;
236 void **params
= calloc(2 * ntotalargs
+ 2, sizeof(void *));
238 for (i
= 0; i
< nfixedargs
; ++i
) {
239 params
[i
] = call
->params
[i
];
240 params
[i
+ ntotalargs
+ 1] = call
->params
[i
+ nfixedargs
+ 1];
242 for (i
= 0; i
< va
->args
->count
; ++i
) {
243 params
[nfixedargs
+ i
] = psi_jit_impl_type(va
->types
[i
]);
244 params
[nfixedargs
+ i
+ ntotalargs
+ 1] = &va
->values
[i
];
247 signature
= jit_type_create_signature(
248 jit_type_get_abi(call
->signature
),
249 jit_type_get_return(call
->signature
),
250 (jit_type_t
*) params
, ntotalargs
, 1);
251 ZEND_ASSERT(signature
);
253 jit_apply(signature
, decl_call
->sym
, ¶ms
[ntotalargs
+ 1],
254 nfixedargs
, decl_call
->rval
);
255 jit_type_free(signature
);
258 jit_apply(call
->signature
, decl_call
->sym
, decl_call
->args
,
259 decl_call
->argc
, decl_call
->rval
);
263 static PSI_ContextOps ops
= {
270 PSI_ContextOps
*PSI_Libjit(void)
275 #endif /* HAVE_LIBJIT */