+ struct psi_ffi_context *context = pecalloc(1, sizeof(*context), 1);
+
+ context->params[0] = &ffi_type_pointer;
+ context->params[1] = &ffi_type_pointer;
+ rc = ffi_prep_cif(&context->signature, FFI_DEFAULT_ABI, 2, &ffi_type_void,
+ context->params);
+
+ if (FFI_OK != rc) {
+ pefree(context, 1);
+ return false;
+ }
+
+ C->context = context;
+ return true;
+}
+
+static void psi_ffi_dtor(struct psi_context *C)
+{
+ if (C->context) {
+ pefree(C->context, 1);
+ C->context = NULL;
+ }
+}
+
+static bool psi_ffi_composite_init(struct psi_context *C,
+ struct psi_decl_arg *darg)
+{
+ struct psi_ffi_struct_info *info;
+
+ if (darg->engine.type) {
+ return true;
+ }
+
+ info = pecalloc(1, sizeof(*info), 1);
+ info->eles = psi_plist_init((psi_plist_dtor) psi_ffi_type_free);
+
+ psi_context_composite_type_elements(C, darg, &info->eles);
+
+ /* add terminating NULL; libffi structs do not have an element count */
+ {
+ void *null_ptr = NULL;
+ info->eles = psi_plist_add(info->eles, &null_ptr);
+ }
+
+ info->strct.type = FFI_TYPE_STRUCT;
+ info->strct.alignment = 0;
+ info->strct.size = 0;
+ info->strct.elements = (ffi_type **) psi_plist_eles(info->eles);
+
+ darg->engine.info = info;
+ darg->engine.type = &info->strct;
+
+ return true;
+}
+
+static void psi_ffi_composite_dtor(struct psi_context *C,
+ struct psi_decl_arg *darg)
+{
+ struct psi_ffi_struct_info *info = darg->engine.info;
+
+ if (info) {
+ darg->engine.info = NULL;
+ darg->engine.type = NULL;
+
+ struct psi_plist *args = NULL;
+ struct psi_decl_type *dtype = psi_decl_type_get_real(darg->type);
+
+ if (dtype->type == PSI_T_STRUCT) {
+ args = dtype->real.strct->args;
+ } else if (dtype->type == PSI_T_UNION) {
+ args = dtype->real.unn->args;
+ }
+
+ size_t i = 0;
+ struct psi_decl_arg *tmp;
+
+ while (psi_plist_get(args, i++, &tmp)) {
+ psi_ffi_composite_dtor(C, tmp);
+ }