+}
+
+static void psi_ffi_extvar_get(ffi_cif *sig, void *result, void **args, void *data) {
+ struct psi_decl_extvar *evar = data;
+
+ psi_decl_extvar_get(evar, result);
+}
+
+static void psi_ffi_extvar_set(ffi_cif *sig, void *result, void **args, void *data) {
+ struct psi_decl_extvar *evar = data;
+
+ psi_decl_extvar_set(evar, args[0]);
+}
+
+static bool psi_ffi_decl_init(struct psi_context *, struct psi_decl *);
+
+static bool psi_ffi_extvar_init(struct psi_context *C,
+ struct psi_decl_extvar *evar)
+{
+ struct psi_ffi_extvar_info *info = pecalloc(1, sizeof(*info), 1);
+ ffi_status rc;
+
+ evar->info = info;
+
+ psi_ffi_decl_init(C, evar->getter);
+ psi_ffi_decl_init(C, evar->setter);
+
+ rc = ffi_prep_cif(&info->get.signature, FFI_DEFAULT_ABI, 0,
+ psi_context_decl_arg_call_type(C, evar->getter->func), NULL);
+ if (FFI_OK != rc) {
+ return false;
+ }
+ rc = psi_ffi_prep_closure(&info->get.closure, &info->get.code,
+ &info->get.signature, psi_ffi_extvar_get, evar);
+ if (FFI_OK != rc) {
+ return false;
+ }
+
+ info->set.params[0] = psi_context_decl_arg_call_type(C, evar->arg);
+ rc = ffi_prep_cif(&info->set.signature, FFI_DEFAULT_ABI, 1,
+ &ffi_type_void, info->set.params);
+ if (FFI_OK != rc) {
+ return false;
+ }
+ rc = psi_ffi_prep_closure(&info->set.closure, &info->set.code,
+ &info->set.signature, psi_ffi_extvar_set, evar);
+ if (FFI_OK != rc) {
+ return false;
+ }
+
+ evar->getter->sym = info->get.code;
+ evar->setter->sym = info->set.code;
+
+ return true;
+}
+
+static void psi_ffi_extvar_dtor(struct psi_context *C,
+ struct psi_decl_extvar *evar) {
+ if (evar->info) {
+ pefree(evar->info, 1);
+ evar->info = NULL;
+ }
+}
+
+static bool psi_ffi_decl_init(struct psi_context *C, struct psi_decl *decl)
+{
+ if (!decl->info) {
+ int rc;
+ size_t i, c = psi_plist_count(decl->args);
+ struct psi_decl_arg *arg;
+ struct psi_ffi_decl_info *info = pecalloc(1,
+ sizeof(*info) + 2 * c * sizeof(void *), 1);
+
+ decl->info = info;
+
+ for (i = 0; psi_plist_get(decl->args, i, &arg); ++i) {
+ info->params[i] = psi_context_decl_arg_call_type(C, arg);
+ }
+ info->params[c] = NULL;
+
+ rc = ffi_prep_cif(&info->signature, psi_ffi_abi(decl->abi->convention),
+ c, psi_context_decl_arg_call_type(C, decl->func), info->params);
+
+ if (FFI_OK != rc) {
+ pefree(info, 1);
+ decl->info = NULL;
+ return false;
+ }