7b0a49a5cadd6748edd886ba5345570c9d292ddf
14 static void psi_jit_handler(jit_type_t _sig
, void *result
, void **_args
, void *_data
);
15 static inline jit_type_t
psi_jit_decl_arg_type(decl_arg
*darg
);
17 static inline jit_abi_t
psi_jit_abi(const char *convention
) {
20 static inline jit_type_t
psi_jit_token_type(token_t t
) {
28 return jit_type_sbyte
;
30 return jit_type_ubyte
;
32 return jit_type_short
;
34 return jit_type_ushort
;
42 return jit_type_ulong
;
44 return jit_type_sys_bool
;
46 return jit_type_sys_int
;
48 return jit_type_sys_long
;
50 return jit_type_sys_float
;
52 return jit_type_sys_double
;
53 #ifdef HAVE_LONG_DOUBLE
54 case PSI_T_LONG_DOUBLE
:
55 return jit_type_sys_long_double
;
58 return jit_type_void_ptr
;
61 static inline jit_type_t
psi_jit_impl_type(token_t impl_type
) {
64 return jit_type_sbyte
;
68 return jit_type_void_ptr
;
71 return jit_type_sys_double
;
72 EMPTY_SWITCH_DEFAULT_CASE();
76 static void psi_jit_struct_type_dtor(void *type
) {
77 jit_type_t strct
= type
;
82 static size_t psi_jit_struct_type_pad(jit_type_t
**els
, size_t padding
) {
85 for (i
= 0; i
< padding
; ++i
) {
86 *els
++ = jit_type_copy(jit_type_sys_char
);
92 static unsigned psi_jit_struct_type_elements(decl_struct
*strct
, jit_type_t
**fields
) {
93 size_t i
, j
, argc
= strct
->args
->count
, nels
= 0, offset
= 0, maxalign
;
94 *fields
= calloc(argc
+ 1, sizeof(*fields
));
96 for (i
= 0; i
< strct
->args
->count
; ++i
) {
97 decl_arg
*darg
= strct
->args
->args
[i
];
98 jit_type_t type
= jit_type_copy(psi_jit_decl_arg_type(darg
));
99 size_t padding
, alignment
;
101 ZEND_ASSERT(jit_type_get_size(type
) == darg
->layout
->len
);
103 if ((alignment
= jit_type_get_alignment(type
)) > maxalign
) {
104 maxalign
= alignment
;
107 if ((padding
= psi_offset_padding(darg
->layout
->pos
- offset
, alignment
))) {
108 if (nels
+ padding
> argc
) {
110 *fields
= realloc(*fields
, (argc
+ 1) * sizeof(*fields
));
112 psi_jit_struct_type_pad(&(*fields
)[nels
], padding
);
116 ZEND_ASSERT(offset
== darg
->layout
->pos
);
118 offset
= (offset
+ darg
->layout
->len
+ alignment
- 1) & ~(alignment
- 1);
119 (*fields
)[nels
++] = type
;
122 /* apply struct alignment padding */
123 offset
= (offset
+ maxalign
- 1) & ~(maxalign
- 1);
125 ZEND_ASSERT(offset
<= strct
->size
);
126 if (offset
< strct
->size
) {
127 nels
+= psi_jit_struct_type_pad(&(*fields
)[nels
], strct
->size
- offset
);
132 static inline jit_type_t
psi_jit_decl_type(decl_type
*type
) {
133 decl_type
*real
= real_decl_type(type
);
135 if (real
->type
== PSI_T_STRUCT
) {
136 if (!real
->strct
->engine
.type
) {
138 jit_type_t strct
, *fields
= NULL
;
140 count
= psi_jit_struct_type_elements(real
->strct
, &fields
);
141 strct
= jit_type_create_struct(fields
, count
, 0);
143 real
->strct
->engine
.type
= strct
;
144 real
->strct
->engine
.dtor
= psi_jit_struct_type_dtor
;
147 return real
->strct
->engine
.type
;
149 return psi_jit_token_type(real
->type
);
151 static inline jit_type_t
psi_jit_decl_arg_type(decl_arg
*darg
) {
152 if (darg
->var
->pointer_level
) {
153 return jit_type_void_ptr
;
155 return psi_jit_decl_type(darg
->type
);
159 typedef struct PSI_LibjitContext
{
161 jit_type_t signature
;
163 struct PSI_LibjitData
**list
;
168 typedef struct PSI_LibjitCall
{
170 jit_type_t signature
;
171 void *params
[1]; /* [type1, type2, NULL, arg1, arg2] ... */
174 typedef struct PSI_LibjitData
{
175 PSI_LibjitContext
*context
;
177 zend_internal_arg_info
*arginfo
;
180 static inline PSI_LibjitCall
*PSI_LibjitCallAlloc(PSI_Context
*C
, decl
*decl
) {
181 size_t i
, c
= decl
->args
? decl
->args
->count
: 0;
182 PSI_LibjitCall
*call
= calloc(1, sizeof(*call
) + 2 * c
* sizeof(void *));
184 for (i
= 0; i
< c
; ++i
) {
185 call
->params
[i
] = psi_jit_decl_arg_type(decl
->args
->args
[i
]);
187 call
->params
[c
] = NULL
;
189 decl
->call
.info
= call
;
190 decl
->call
.rval
= &decl
->func
->ptr
;
192 decl
->call
.args
= (void **) &call
->params
[c
+1];
194 call
->signature
= jit_type_create_signature(
195 psi_jit_abi(decl
->abi
->convention
),
196 psi_jit_decl_arg_type(decl
->func
),
197 (jit_type_t
*) call
->params
, c
, 1);
201 static inline void PSI_LibjitCallInitClosure(PSI_Context
*C
, PSI_LibjitCall
*call
, impl
*impl
) {
202 PSI_LibjitContext
*context
= C
->context
;
203 call
->closure
= jit_closure_create(context
->jit
, context
->signature
,
204 &psi_jit_handler
, impl
);
207 static inline void PSI_LibjitCallFree(PSI_LibjitCall
*call
) {
208 jit_type_free(call
->signature
);
212 static inline PSI_LibjitContext
*PSI_LibjitContextInit(PSI_LibjitContext
*L
) {
213 jit_type_t params
[] = {
219 L
= malloc(sizeof(*L
));
221 memset(L
, 0, sizeof(*L
));
223 L
->jit
= jit_context_create();
224 L
->signature
= jit_type_create_signature(jit_abi_cdecl
, jit_type_void
,
230 static inline void PSI_LibjitContextDtor(PSI_LibjitContext
*L
) {
231 jit_type_free(L
->signature
);
232 jit_context_destroy(L
->jit
);
235 static inline void PSI_LibjitContextFree(PSI_LibjitContext
**L
) {
237 PSI_LibjitContextDtor(*L
);
243 static void psi_jit_handler(jit_type_t _sig
, void *result
, void **_args
, void *_data
)
245 psi_call(*(zend_execute_data
**)_args
[0], *(zval
**)_args
[1], _data
);
248 static void psi_jit_init(PSI_Context
*C
)
250 C
->context
= PSI_LibjitContextInit(NULL
);
253 static void psi_jit_dtor(PSI_Context
*C
)
258 for (i
= 0; i
< C
->decls
->count
; ++i
) {
259 decl
*decl
= C
->decls
->list
[i
];
261 PSI_LibjitCallFree(decl
->call
.info
);
264 PSI_LibjitContextFree((void *) &C
->context
);
267 static zend_function_entry
*psi_jit_compile(PSI_Context
*C
)
270 zend_function_entry
*zfe
;
271 PSI_LibjitContext
*ctx
= C
->context
;
277 zfe
= calloc(C
->impls
->count
+ 1, sizeof(*zfe
));
278 jit_context_build_start(ctx
->jit
);
280 for (i
= 0; i
< C
->impls
->count
; ++i
) {
281 zend_function_entry
*zf
= &zfe
[j
];
282 PSI_LibjitCall
*call
;
283 impl
*impl
= C
->impls
->list
[i
];
289 call
= PSI_LibjitCallAlloc(C
, impl
->decl
);
290 PSI_LibjitCallInitClosure(C
, call
, impl
);
292 zf
->fname
= impl
->func
->name
+ (impl
->func
->name
[0] == '\\');
293 zf
->num_args
= impl
->func
->args
->count
;
294 zf
->handler
= call
->closure
;
295 zf
->arg_info
= psi_internal_arginfo(impl
);
299 for (i
= 0; i
< C
->decls
->count
; ++i
) {
300 decl
*decl
= C
->decls
->list
[i
];
306 PSI_LibjitCallAlloc(C
, decl
);
309 jit_context_build_end(ctx
->jit
);
314 static void psi_jit_call(PSI_Context
*C
, decl_callinfo
*decl_call
, impl_vararg
*va
) {
315 PSI_LibjitCall
*call
= decl_call
->info
;
318 jit_type_t signature
;
319 size_t i
, nfixedargs
= decl_call
->argc
, ntotalargs
= nfixedargs
+ va
->args
->count
;
320 void **params
= calloc(2 * ntotalargs
+ 2, sizeof(void *));
322 for (i
= 0; i
< nfixedargs
; ++i
) {
323 params
[i
] = call
->params
[i
];
324 params
[i
+ ntotalargs
+ 1] = call
->params
[i
+ nfixedargs
+ 1];
326 for (i
= 0; i
< va
->args
->count
; ++i
) {
327 params
[nfixedargs
+ i
] = psi_jit_impl_type(va
->types
[i
]);
328 params
[nfixedargs
+ i
+ ntotalargs
+ 1] = &va
->values
[i
];
331 signature
= jit_type_create_signature(
332 jit_type_get_abi(call
->signature
),
333 jit_type_get_return(call
->signature
),
334 (jit_type_t
*) params
, ntotalargs
, 1);
335 ZEND_ASSERT(signature
);
337 jit_apply(signature
, decl_call
->sym
, ¶ms
[ntotalargs
+ 1],
338 nfixedargs
, *decl_call
->rval
);
339 jit_type_free(signature
);
342 jit_apply(call
->signature
, decl_call
->sym
, decl_call
->args
,
343 decl_call
->argc
, *decl_call
->rval
);
347 static PSI_ContextOps ops
= {
354 PSI_ContextOps
*PSI_Libjit(void)
359 #endif /* HAVE_LIBJIT */