+static bool psi_jit_cb_init(struct psi_context *C,
+ struct psi_let_exp *exp, struct psi_impl *impl)
+{
+ struct psi_jit_context *context = C->context;
+ struct psi_jit_callback_info *cb_info;
+ struct psi_jit_decl_info *decl_info;
+
+ assert(exp->kind == PSI_LET_CALLBACK);
+
+ if (!psi_jit_decl_init(C, exp->data.callback->decl)) {
+ return false;
+ }
+
+ cb_info = pecalloc(1, sizeof(*cb_info), 1);
+ cb_info->impl_info = impl->info;
+ cb_info->let_exp = exp;
+
+ decl_info = exp->data.callback->decl->info;
+ cb_info->closure = jit_closure_create(context->jit, decl_info->signature,
+ &psi_jit_callback, cb_info);
+
+ if (!cb_info->closure) {
+ free(cb_info);
+ return false;
+ }
+
+ assert(!exp->data.callback->decl->sym);
+ exp->data.callback->info = cb_info;
+ exp->data.callback->decl->sym = cb_info->closure;
+
+ return true;
+}
+
+static void psi_jit_cb_dtor(struct psi_context *C,
+ struct psi_let_exp *let_exp, struct psi_impl *impl)
+{
+ assert(let_exp->kind == PSI_LET_CALLBACK);
+
+ psi_jit_decl_dtor(C, let_exp->data.callback->decl);
+
+ if (let_exp->data.callback->info) {
+ struct psi_jit_callback_info *info = let_exp->data.callback->info;
+
+ /* The memory for the closure will be reclaimed
+ * when the context is destroyed.
+ */
+ pefree(info, 1);
+ let_exp->data.callback->info = NULL;
+ }
+}
+
+static void psi_jit_call(struct psi_call_frame *frame) {
+ struct psi_decl *decl = psi_call_frame_get_decl(frame);
+ struct psi_impl *impl = psi_call_frame_get_impl(frame);
+ struct psi_jit_decl_info *decl_info = decl->info;
+ struct psi_jit_impl_info *impl_info;
+ struct psi_call_frame *prev;
+
+ if (impl) {
+ impl_info = impl->info;
+ prev = impl_info->frame;
+ impl_info->frame = frame;
+ }
+ jit_apply(decl_info->signature, decl->sym,
+ psi_call_frame_get_arg_pointers(frame), psi_plist_count(decl->args),
+ psi_call_frame_get_rpointer(frame));
+ if (impl) {
+ impl_info->frame = prev;
+ }
+}
+
+static void psi_jit_call_va(struct psi_call_frame *frame) {
+ jit_type_t signature;
+ struct psi_call_frame *prev;
+ struct psi_decl *decl = psi_call_frame_get_decl(frame);
+ struct psi_impl *impl = psi_call_frame_get_impl(frame);
+ struct psi_jit_decl_info *decl_info = decl->info;
+ struct psi_jit_impl_info *impl_info;
+ size_t i, va_count, argc;
+ jit_type_t *param_types;
+
+ argc = psi_plist_count(decl->args);
+ va_count = psi_call_frame_num_var_args(frame);
+ param_types = ecalloc(argc + va_count + 1, sizeof(jit_type_t));
+ memcpy(param_types, decl_info->params, argc * sizeof(jit_type_t));
+ for (i = 0; i < va_count; ++i) {
+ struct psi_call_frame_argument *frame_arg;
+
+ frame_arg = psi_call_frame_get_var_argument(frame, i);
+ param_types[argc + i] = psi_jit_impl_type(frame_arg->va_type);
+ }
+
+ signature = jit_type_create_signature(jit_abi_vararg,
+ jit_type_get_return(decl_info->signature),
+ param_types, argc + va_count, 1);
+ assert(signature);
+
+ if (impl) {
+ impl_info = impl->info;
+ prev = impl_info->frame;
+ impl_info->frame = frame;
+ }
+ jit_apply(signature, decl->sym,
+ psi_call_frame_get_arg_pointers(frame), argc,
+ psi_call_frame_get_rpointer(frame));
+ if (impl) {
+ impl_info->frame = prev;
+ }
+
+ jit_type_free(signature);
+
+ efree(param_types);
+}
+
+static void *psi_jit_typeof_impl(struct psi_context *C, token_t impl_type)
+{
+ return psi_jit_impl_type(impl_type);
+}
+
+static void *psi_jit_typeof_decl(struct psi_context *C, token_t decl_type)
+{
+ return psi_jit_token_type(decl_type);
+}
+
+static void *psi_jit_copyof_type(struct psi_context *C, void *orig_type)
+{
+ return jit_type_copy(orig_type);
+}
+
+static void psi_jit_layoutof_type(struct psi_context *C, void *orig_type,
+ struct psi_layout *l)
+{
+ l->pos = jit_type_get_alignment(orig_type);
+ l->len = jit_type_get_size(orig_type);