[svn:parrot] r49702 - in branches/gsoc_nci: config/gen/libffi src/pmc
plobsing at svn.parrot.org
plobsing at svn.parrot.org
Wed Oct 27 22:27:14 UTC 2010
Author: plobsing
Date: Wed Oct 27 22:27:14 2010
New Revision: 49702
URL: https://trac.parrot.org/parrot/changeset/49702
Log:
remove private2 (raw) flag from nci-ffi.pmc
(removed in trunk after branch start)
Modified:
branches/gsoc_nci/config/gen/libffi/nci-ffi.pmc.in
branches/gsoc_nci/src/pmc/nci.pmc
Modified: branches/gsoc_nci/config/gen/libffi/nci-ffi.pmc.in
==============================================================================
--- branches/gsoc_nci/config/gen/libffi/nci-ffi.pmc.in Wed Oct 27 21:51:16 2010 (r49701)
+++ branches/gsoc_nci/config/gen/libffi/nci-ffi.pmc.in Wed Oct 27 22:27:14 2010 (r49702)
@@ -860,8 +860,6 @@
*/
VTABLE void init() {
- /* Mark that we're not a raw NCI. */
- PObj_flag_CLEAR(private2, SELF);
PObj_custom_mark_SET(SELF);
}
@@ -875,11 +873,6 @@
*/
- VTABLE void set_pointer(void *ptr) {
- SET_ATTR_orig_func(INTERP, SELF, ptr);
- PObj_flag_SET(private2, SELF);
- }
-
VTABLE void *get_pointer() {
return PARROT_NCI(SELF)->orig_func;
}
@@ -1014,390 +1007,367 @@
PMC *call_object = Parrot_pcc_get_signature(interp, ctx);
void (*func)(void*,void*,void*); /* a function pointer for our function to call */
- if (PObj_flag_TEST(private2, SELF)) {
- void *orig_func;
- PMC *fb_info;
- GET_ATTR_orig_func(INTERP, SELF, orig_func);
- GET_ATTR_fb_info(INTERP, SELF, fb_info);
-
- func = (void (*)(void*, void*, void*))orig_func;
-
- if (!func) {
- /* build the thunk only when necessary */
- func = (void (*)(void*, void*, void*))build_func(interp, nci_info);
-
- if (!func)
- Parrot_ex_throw_from_c_args(INTERP, NULL,
- EXCEPTION_INVALID_OPERATION,
- "attempt to call NULL function");
- }
-
- func = (void (*)(void*, void*, void*))(orig_func);
- func(INTERP, SELF, fb_info);
+ PMC *positional, *arg_iter;
+ STRING *void_return;
+ void **values;
+ void **pcc_ptr;
+ void **translation_pointers = NULL; /* Data translation pointers, used to hold values
+ that are passed by reference so we can update
+ the objects after the FFI call is over */
+ void **pcc_val = NULL; /* A holder for the values passed to pcc */
+ void **middle_man = NULL; /* An array to hold various pointers so they are not lost if
+ the function changes values by reference */
+ void *return_data; /* Holds return data from FFI call */
+ size_t count, i, j_offset;
+ char *tmp_sig;
+ ffi_cif *cif, pcc_cif;
+ ffi_type **pcc_args;
+
+ cif = (ffi_cif*)nci_info->cif;
+ func = (void (*)(void*, void*, void*))nci_info->func;
+
+ if (!cif) {
+ /* build the thunk only when necessary */
+ cif = build_libffi_func(interp, nci_info);
+
+ if (!cif && !func)
+ Parrot_ex_throw_from_c_args(INTERP, NULL,
+ EXCEPTION_INVALID_OPERATION,
+ "attempt to call NULL function");
}
- else {
- PMC *positional, *arg_iter;
- STRING *void_return;
- void **values;
- void **pcc_ptr;
- void **translation_pointers = NULL; /* Data translation pointers, used to hold values
- that are passed by reference so we can update
- the objects after the FFI call is over */
- void **pcc_val = NULL; /* A holder for the values passed to pcc */
- void **middle_man = NULL; /* An array to hold various pointers so they are not lost if
- the function changes values by reference */
- void *return_data; /* Holds return data from FFI call */
- size_t count, i, j_offset;
- char *tmp_sig;
- ffi_cif *cif, pcc_cif;
- ffi_type **pcc_args;
-
- cif = (ffi_cif*)nci_info->cif;
- func = (void (*)(void*, void*, void*))nci_info->func;
-
- if (!cif) {
- /* build the thunk only when necessary */
- cif = build_libffi_func(interp, nci_info);
-
- if (!cif && !func)
- Parrot_ex_throw_from_c_args(INTERP, NULL,
- EXCEPTION_INVALID_OPERATION,
- "attempt to call NULL function");
- }
-
- if (nci_info->arity > 0) {
- size_t pcc_argc, pcc_values_offset, pcc_values_size, values_size;
- /* Function has arguments */
- pcc_args = mem_internal_allocate_n_zeroed_typed(nci_info->arity + 4, ffi_type*);
- tmp_sig = Parrot_str_to_cstring(interp, nci_info->pcc_params_signature);
-
- pcc_args[0] = &ffi_type_pointer;
- pcc_args[1] = &ffi_type_pointer;
- pcc_args[2] = &ffi_type_pointer;
- pcc_values_size = 0;
- values_size = 0;
- pcc_argc = Parrot_str_length(interp, nci_info->pcc_params_signature);
-
- /* Add up the size of memory needed for the actual call */
- for (i = 0; i < (size_t)nci_info->arity; i++) {
- values_size += cif->arg_types[i]->size;
- }
-
- pcc_ptr = (void**)mem_internal_allocate_n_zeroed_typed(pcc_argc + 4, void*);
-
- /* Setup Parrot_pcc_fill_params_from_c_args required arguments */
- pcc_ptr[0] = &interp;
- pcc_ptr[1] = &call_object;
- pcc_ptr[2] = &tmp_sig;
-
- pcc_val = mem_internal_allocate_n_zeroed_typed(pcc_argc, void*);
- /* Allocate enough room for the values passed to the ffi function plus add some
- padding just to be sure we have enough space. */
- values = mem_internal_allocate_zeroed(values_size + 2 * sizeof(void*));
- /* Middle man is used to contain */
- middle_man = mem_internal_allocate_n_zeroed_typed(nci_info->arity, void*);
- /* Add up the size of the pcc arguments */
- for (i = 0; i < pcc_argc; i++) {
- pcc_args[i + 3] = &ffi_type_pointer;
- if (tmp_sig[i] == 'N') {
- pcc_val[i] = mem_internal_allocate_typed(FLOATVAL);
- pcc_ptr[i+3] = &pcc_val[i];
- }
- else if (tmp_sig[i] == 'I') {
- pcc_val[i] = mem_internal_allocate_typed(INTVAL);
- pcc_ptr[i+3] = &pcc_val[i];
- }
- else if (tmp_sig[i] == 'P' || tmp_sig[i] == 'S') {
- pcc_val[i] = mem_internal_allocate_typed(void*);
- pcc_ptr[i+3] = &pcc_val[i];
- }
- }
-
- if (ffi_prep_cif(&pcc_cif, FFI_DEFAULT_ABI, 3 + pcc_argc,
- &ffi_type_void, pcc_args) != FFI_OK) {
- Parrot_ex_throw_from_c_args(INTERP, NULL,
- EXCEPTION_INVALID_OPERATION,
- "Bad signature generated for Parrot_pcc_fill_params_from_c_args in NCI");
- }
-
- ffi_call(&pcc_cif, FFI_FN(Parrot_pcc_fill_params_from_c_args), NULL, pcc_ptr);
-
- Parrot_str_free_cstring(tmp_sig);
-
- /*
- * Apply Argument Transformations
- * this is mostly to transform STRING* into char*
- * and add the parrot interp argument if it needs it
- * but other transformations might apply later, like packing an
- * object into a ManagedStruct
- */
- j_offset = 0;
- translation_pointers = mem_internal_allocate_n_zeroed_typed(nci_info->arity, void*);
- for (i = 0; i < (size_t)nci_info->arity; i++) {
- switch ((INTVAL)((char*)nci_info->arg_translation)[i]) {
- case 'J':
- values[i] = &interp;
- j_offset++;
- break;
- case 't':
- if (STRING_IS_NULL(*(STRING**)pcc_val[i - j_offset])) {
- translation_pointers[i] = (char*) NULL;
- }
- else {
- translation_pointers[i] = Parrot_str_to_cstring(interp, *(STRING**)pcc_val[i - j_offset]);
- }
- values[i] = &translation_pointers[i];
- break;
- case 'B':
- if (STRING_IS_NULL(*(STRING**)pcc_val[i - j_offset])) {
- translation_pointers[i] = (char*) NULL;
- }
- else {
- translation_pointers[i] = Parrot_str_to_cstring(interp, *(STRING**)pcc_val[i - j_offset]);
- }
- middle_man[i] = &translation_pointers[i];
- values[i] = &middle_man[i];
- break;
- case 'b':
- values[i] = &Buffer_bufstart(*(STRING**)pcc_val[i - j_offset]);
- break;
- case 'c':
- translation_pointers[i] = mem_internal_allocate_zeroed_typed(char);
- *((char**)translation_pointers)[i] = (char)*(INTVAL*)pcc_val[i - j_offset];
- values[i] = translation_pointers[i];
- break;
- case '2':
- translation_pointers[i] = mem_internal_allocate_zeroed_typed(pmc_holder_t);
- ((pmc_holder_t*)translation_pointers[i])->p = *(PMC**)pcc_val[i - j_offset];
- ((pmc_holder_t*)translation_pointers[i])->ival = (INTVAL*)mem_internal_allocate_zeroed_typed(short);
- *((pmc_holder_t*)translation_pointers[i])->ival = (short)VTABLE_get_integer(interp, *(PMC**)pcc_ptr[i - j_offset]);
- values[i] = &((pmc_holder_t*)translation_pointers[i])->ival;
- break;
- case 's':
- translation_pointers[i] = mem_internal_allocate_zeroed_typed(short);
- *((short**)translation_pointers)[i] = (short)*(INTVAL*)pcc_val[i - j_offset];
- values[i] = translation_pointers[i];
- break;
- case '3':
- translation_pointers[i] = mem_internal_allocate_zeroed_typed(pmc_holder_t);
- ((pmc_holder_t*)translation_pointers[i])->p = *(PMC**)pcc_val[i - j_offset];
- ((pmc_holder_t*)translation_pointers[i])->ival = (INTVAL*)mem_internal_allocate_zeroed_typed(int);
- *((pmc_holder_t*)translation_pointers[i])->ival = (int)VTABLE_get_integer(interp, *(PMC**)pcc_val[i - j_offset]);
- values[i] = &((pmc_holder_t*)translation_pointers[i])->ival;
- break;
- case 'i':
- translation_pointers[i] = mem_internal_allocate_zeroed_typed(int);
- *((int**)translation_pointers)[i] = (int)*(INTVAL*)pcc_val[i - j_offset];
- values[i] = translation_pointers[i];
- break;
- case '4':
- translation_pointers[i] = mem_internal_allocate_zeroed_typed(pmc_holder_t);
- ((pmc_holder_t*)translation_pointers[i])->p = *(PMC**)pcc_val[i - j_offset];
- ((pmc_holder_t*)translation_pointers[i])->ival = (INTVAL*)mem_internal_allocate_zeroed_typed(long);
- *((pmc_holder_t*)translation_pointers[i])->ival = (long)VTABLE_get_integer(interp, *(PMC**)pcc_val[i - j_offset]);
- values[i] = &((pmc_holder_t*)translation_pointers[i])->ival;
- break;
- case 'l':
- translation_pointers[i] = mem_internal_allocate_zeroed_typed(long);
- *((long**)translation_pointers)[i] = (long)*(INTVAL*)pcc_val[i - j_offset];
- values[i] = translation_pointers[i];
- break;
- case 'q':
- translation_pointers[i] = mem_internal_allocate_zeroed_typed(long long);
- *((long long**)translation_pointers)[i] = (long long)*(INTVAL*)pcc_val[i - j_offset];
- values[i] = translation_pointers[i];
- break;
- case 'V':
- translation_pointers[i] = mem_internal_allocate_zeroed_typed(pmc_holder_t);
- ((pmc_holder_t*)translation_pointers[i])->p = *(PMC**)pcc_val[i - j_offset];
- ((pmc_holder_t*)translation_pointers[i])->pval = (void**)mem_internal_allocate_zeroed_typed(void*);
- *((pmc_holder_t*)translation_pointers[i])->pval = PMC_IS_NULL(*(PMC**)pcc_val[i - j_offset]) ?
- (void *)NULL : (void*)VTABLE_get_pointer(interp, *(PMC**)pcc_val[i - j_offset]);
- values[i] = &((pmc_holder_t*)translation_pointers[i])->pval;
- break;
- case 'P':
- translation_pointers[i] = *(PMC**)pcc_val[i - j_offset];
- values[i] = &translation_pointers[i];
- break;
- case 'p':
- translation_pointers[i] = PMC_IS_NULL(*(PMC**)pcc_val[i - j_offset]) ?
- (void *)NULL : VTABLE_get_pointer(interp, *(PMC**)pcc_val[i - j_offset]);
- values[i] = &translation_pointers[i];
- break;
- case 'f':
- translation_pointers[i] = mem_internal_allocate_zeroed_typed(float);
- *((float**)translation_pointers)[i] = (float)*(FLOATVAL*)pcc_val[i - j_offset];
- values[i] = translation_pointers[i];
- break;
- case 'd':
- translation_pointers[i] = mem_internal_allocate_zeroed_typed(double);
- *((double**)translation_pointers)[i] = *(FLOATVAL*)pcc_val[i - j_offset];
- values[i] = translation_pointers[i];
- break;
- case ' ':
- default:
- break;
- }
- }
+ if (nci_info->arity > 0) {
+ size_t pcc_argc, pcc_values_offset, pcc_values_size, values_size;
+ /* Function has arguments */
+ pcc_args = mem_internal_allocate_n_zeroed_typed(nci_info->arity + 4, ffi_type*);
+ tmp_sig = Parrot_str_to_cstring(interp, nci_info->pcc_params_signature);
+
+ pcc_args[0] = &ffi_type_pointer;
+ pcc_args[1] = &ffi_type_pointer;
+ pcc_args[2] = &ffi_type_pointer;
+ pcc_values_size = 0;
+ values_size = 0;
+ pcc_argc = Parrot_str_length(interp, nci_info->pcc_params_signature);
- if (pcc_args) {
- mem_sys_free(pcc_args);
- }
- if (pcc_ptr) {
- mem_sys_free(pcc_ptr);
- }
- if (pcc_val) {
- for (i = 0; i < pcc_argc; i++) {
- mem_sys_free(pcc_val[i]);
- }
- if (pcc_val)
- mem_sys_free(pcc_val);
- }
- }
- else {
- /* No arguments */
- values = NULL;
+ /* Add up the size of memory needed for the actual call */
+ for (i = 0; i < (size_t)nci_info->arity; i++) {
+ values_size += cif->arg_types[i]->size;
}
- /*
- * This will allow for any type of datat to be returned.
- * Including one day Structures
- */
- return_data = mem_internal_allocate_zeroed(cif->rtype->size);
+ pcc_ptr = (void**)mem_internal_allocate_n_zeroed_typed(pcc_argc + 4, void*);
- ffi_call(cif, FFI_FN(func), return_data, values);
-
- if (cif->rtype != &ffi_type_void) {
- char *s;
- PMC *ret_object;
- s = Parrot_str_to_cstring(interp, nci_info->pcc_return_signature);
- switch (*(char*)nci_info->return_translation) {
- case 'p':
- {
- PMC *final_destination = PMCNULL;
-
- if (*(void**)return_data != NULL) {
- final_destination = Parrot_pmc_new(interp, enum_class_UnManagedStruct);
- VTABLE_set_pointer(interp, final_destination, *(void**)return_data);
- }
- ret_object = Parrot_pcc_build_call_from_c_args(interp,
- call_object,
- s, final_destination);
- }
- break;
- case 't':
- {
- STRING *final_destination = Parrot_str_new(interp, *(char**)return_data, 0);
- ret_object = Parrot_pcc_build_call_from_c_args(interp,
- call_object,
- s, final_destination);
- }
- break;
- case 'f':
- {
- FLOATVAL final_destination = *(float*)return_data;
-
- ret_object = Parrot_pcc_build_call_from_c_args(interp,
- call_object,
- s, final_destination);
- }
- break;
- default:
- switch (s[0]) {
- case 'N':
- ret_object = Parrot_pcc_build_call_from_c_args(interp,
- call_object,
- s, *(FLOATVAL*)return_data);
- case 'I':
- ret_object = Parrot_pcc_build_call_from_c_args(interp,
- call_object,
- s, *(INTVAL*)return_data);
- case 'P':
- case 'S':
- default:
- ret_object = Parrot_pcc_build_call_from_c_args(interp,
- call_object,
- s, *(void**)return_data);
- }
- break;
- }
- Parrot_str_free_cstring(s);
- }
+ /* Setup Parrot_pcc_fill_params_from_c_args required arguments */
+ pcc_ptr[0] = &interp;
+ pcc_ptr[1] = &call_object;
+ pcc_ptr[2] = &tmp_sig;
+
+ pcc_val = mem_internal_allocate_n_zeroed_typed(pcc_argc, void*);
+ /* Allocate enough room for the values passed to the ffi function plus add some
+ padding just to be sure we have enough space. */
+ values = mem_internal_allocate_zeroed(values_size + 2 * sizeof(void*));
+ /* Middle man is used to contain */
+ middle_man = mem_internal_allocate_n_zeroed_typed(nci_info->arity, void*);
+
+ /* Add up the size of the pcc arguments */
+ for (i = 0; i < pcc_argc; i++) {
+ pcc_args[i + 3] = &ffi_type_pointer;
+ if (tmp_sig[i] == 'N') {
+ pcc_val[i] = mem_internal_allocate_typed(FLOATVAL);
+ pcc_ptr[i+3] = &pcc_val[i];
+ }
+ else if (tmp_sig[i] == 'I') {
+ pcc_val[i] = mem_internal_allocate_typed(INTVAL);
+ pcc_ptr[i+3] = &pcc_val[i];
+ }
+ else if (tmp_sig[i] == 'P' || tmp_sig[i] == 'S') {
+ pcc_val[i] = mem_internal_allocate_typed(void*);
+ pcc_ptr[i+3] = &pcc_val[i];
+ }
+ }
+
+ if (ffi_prep_cif(&pcc_cif, FFI_DEFAULT_ABI, 3 + pcc_argc,
+ &ffi_type_void, pcc_args) != FFI_OK) {
+ Parrot_ex_throw_from_c_args(INTERP, NULL,
+ EXCEPTION_INVALID_OPERATION,
+ "Bad signature generated for Parrot_pcc_fill_params_from_c_args in NCI");
+ }
+
+ ffi_call(&pcc_cif, FFI_FN(Parrot_pcc_fill_params_from_c_args), NULL, pcc_ptr);
+
+ Parrot_str_free_cstring(tmp_sig);
/*
- * Free memory used for cstrings,
- * and any other translations that use temporary memory
+ * Apply Argument Transformations
+ * this is mostly to transform STRING* into char*
+ * and add the parrot interp argument if it needs it
+ * but other transformations might apply later, like packing an
+ * object into a ManagedStruct
*/
+ j_offset = 0;
+ translation_pointers = mem_internal_allocate_n_zeroed_typed(nci_info->arity, void*);
for (i = 0; i < (size_t)nci_info->arity; i++) {
switch ((INTVAL)((char*)nci_info->arg_translation)[i]) {
- case (INTVAL)'B':
- if (translation_pointers[i]) {
- Parrot_str_free_cstring((char*)translation_pointers[i]);
- }
+ case 'J':
+ values[i] = &interp;
+ j_offset++;
break;
- case (INTVAL)'t':
- if (translation_pointers[i]) {
- Parrot_str_free_cstring((char*)translation_pointers[i]);
+ case 't':
+ if (STRING_IS_NULL(*(STRING**)pcc_val[i - j_offset])) {
+ translation_pointers[i] = (char*) NULL;
}
- break;
- case (INTVAL)'2':
- VTABLE_set_integer_native(interp,
- ((pmc_holder_t*)translation_pointers[i])->p,
- (INTVAL)*(short*)((pmc_holder_t*)translation_pointers[i])->ival);
- if (translation_pointers[i]) {
- mem_sys_free(translation_pointers[i]);
+ else {
+ translation_pointers[i] = Parrot_str_to_cstring(interp, *(STRING**)pcc_val[i - j_offset]);
}
+ values[i] = &translation_pointers[i];
break;
- case (INTVAL)'3':
- VTABLE_set_integer_native(interp,
- ((pmc_holder_t*)translation_pointers[i])->p,
- (INTVAL)*(int*)((pmc_holder_t*)translation_pointers[i])->ival);
- if (translation_pointers[i]) {
- mem_sys_free(translation_pointers[i]);
- }
+ case 'B':
+ if (STRING_IS_NULL(*(STRING**)pcc_val[i - j_offset])) {
+ translation_pointers[i] = (char*) NULL;
+ }
+ else {
+ translation_pointers[i] = Parrot_str_to_cstring(interp, *(STRING**)pcc_val[i - j_offset]);
+ }
+ middle_man[i] = &translation_pointers[i];
+ values[i] = &middle_man[i];
+ break;
+ case 'b':
+ values[i] = &Buffer_bufstart(*(STRING**)pcc_val[i - j_offset]);
+ break;
+ case 'c':
+ translation_pointers[i] = mem_internal_allocate_zeroed_typed(char);
+ *((char**)translation_pointers)[i] = (char)*(INTVAL*)pcc_val[i - j_offset];
+ values[i] = translation_pointers[i];
+ break;
+ case '2':
+ translation_pointers[i] = mem_internal_allocate_zeroed_typed(pmc_holder_t);
+ ((pmc_holder_t*)translation_pointers[i])->p = *(PMC**)pcc_val[i - j_offset];
+ ((pmc_holder_t*)translation_pointers[i])->ival = (INTVAL*)mem_internal_allocate_zeroed_typed(short);
+ *((pmc_holder_t*)translation_pointers[i])->ival = (short)VTABLE_get_integer(interp, *(PMC**)pcc_ptr[i - j_offset]);
+ values[i] = &((pmc_holder_t*)translation_pointers[i])->ival;
+ break;
+ case 's':
+ translation_pointers[i] = mem_internal_allocate_zeroed_typed(short);
+ *((short**)translation_pointers)[i] = (short)*(INTVAL*)pcc_val[i - j_offset];
+ values[i] = translation_pointers[i];
+ break;
+ case '3':
+ translation_pointers[i] = mem_internal_allocate_zeroed_typed(pmc_holder_t);
+ ((pmc_holder_t*)translation_pointers[i])->p = *(PMC**)pcc_val[i - j_offset];
+ ((pmc_holder_t*)translation_pointers[i])->ival = (INTVAL*)mem_internal_allocate_zeroed_typed(int);
+ *((pmc_holder_t*)translation_pointers[i])->ival = (int)VTABLE_get_integer(interp, *(PMC**)pcc_val[i - j_offset]);
+ values[i] = &((pmc_holder_t*)translation_pointers[i])->ival;
+ break;
+ case 'i':
+ translation_pointers[i] = mem_internal_allocate_zeroed_typed(int);
+ *((int**)translation_pointers)[i] = (int)*(INTVAL*)pcc_val[i - j_offset];
+ values[i] = translation_pointers[i];
+ break;
+ case '4':
+ translation_pointers[i] = mem_internal_allocate_zeroed_typed(pmc_holder_t);
+ ((pmc_holder_t*)translation_pointers[i])->p = *(PMC**)pcc_val[i - j_offset];
+ ((pmc_holder_t*)translation_pointers[i])->ival = (INTVAL*)mem_internal_allocate_zeroed_typed(long);
+ *((pmc_holder_t*)translation_pointers[i])->ival = (long)VTABLE_get_integer(interp, *(PMC**)pcc_val[i - j_offset]);
+ values[i] = &((pmc_holder_t*)translation_pointers[i])->ival;
+ break;
+ case 'l':
+ translation_pointers[i] = mem_internal_allocate_zeroed_typed(long);
+ *((long**)translation_pointers)[i] = (long)*(INTVAL*)pcc_val[i - j_offset];
+ values[i] = translation_pointers[i];
+ break;
+ case 'q':
+ translation_pointers[i] = mem_internal_allocate_zeroed_typed(long long);
+ *((long long**)translation_pointers)[i] = (long long)*(INTVAL*)pcc_val[i - j_offset];
+ values[i] = translation_pointers[i];
+ break;
+ case 'V':
+ translation_pointers[i] = mem_internal_allocate_zeroed_typed(pmc_holder_t);
+ ((pmc_holder_t*)translation_pointers[i])->p = *(PMC**)pcc_val[i - j_offset];
+ ((pmc_holder_t*)translation_pointers[i])->pval = (void**)mem_internal_allocate_zeroed_typed(void*);
+ *((pmc_holder_t*)translation_pointers[i])->pval = PMC_IS_NULL(*(PMC**)pcc_val[i - j_offset]) ?
+ (void *)NULL : (void*)VTABLE_get_pointer(interp, *(PMC**)pcc_val[i - j_offset]);
+ values[i] = &((pmc_holder_t*)translation_pointers[i])->pval;
+ break;
+ case 'P':
+ translation_pointers[i] = *(PMC**)pcc_val[i - j_offset];
+ values[i] = &translation_pointers[i];
break;
- case (INTVAL)'4':
- VTABLE_set_integer_native(interp,
- ((pmc_holder_t*)translation_pointers[i])->p,
- (INTVAL)*(long*)((pmc_holder_t*)translation_pointers[i])->ival);
- if (translation_pointers[i]) {
- mem_sys_free(translation_pointers[i]);
- }
- break;
- case (INTVAL)'V':
- VTABLE_set_pointer(interp,
- ((pmc_holder_t*)translation_pointers[i])->p,
- (PMC*)*((pmc_holder_t*)translation_pointers[i])->pval);
- if (translation_pointers[i]) {
- mem_sys_free(translation_pointers[i]);
- }
+ case 'p':
+ translation_pointers[i] = PMC_IS_NULL(*(PMC**)pcc_val[i - j_offset]) ?
+ (void *)NULL : VTABLE_get_pointer(interp, *(PMC**)pcc_val[i - j_offset]);
+ values[i] = &translation_pointers[i];
break;
- case (INTVAL)'d':
- case (INTVAL)'c':
- case (INTVAL)'s':
- case (INTVAL)'i':
- case (INTVAL)'l':
- case (INTVAL)'q':
- if (translation_pointers[i]) {
- mem_sys_free(translation_pointers[i]);
- }
+ case 'f':
+ translation_pointers[i] = mem_internal_allocate_zeroed_typed(float);
+ *((float**)translation_pointers)[i] = (float)*(FLOATVAL*)pcc_val[i - j_offset];
+ values[i] = translation_pointers[i];
+ break;
+ case 'd':
+ translation_pointers[i] = mem_internal_allocate_zeroed_typed(double);
+ *((double**)translation_pointers)[i] = *(FLOATVAL*)pcc_val[i - j_offset];
+ values[i] = translation_pointers[i];
break;
+ case ' ':
default:
break;
}
}
-
- if (nci_info->arity > 0 && middle_man) {
- mem_sys_free(middle_man);
+
+ if (pcc_args) {
+ mem_sys_free(pcc_args);
+ }
+ if (pcc_ptr) {
+ mem_sys_free(pcc_ptr);
}
- if (return_data) {
- mem_sys_free(return_data);
+ if (pcc_val) {
+ for (i = 0; i < pcc_argc; i++) {
+ mem_sys_free(pcc_val[i]);
+ }
+ if (pcc_val)
+ mem_sys_free(pcc_val);
+ }
+ }
+ else {
+ /* No arguments */
+ values = NULL;
+ }
+
+ /*
+ * This will allow for any type of datat to be returned.
+ * Including one day Structures
+ */
+ return_data = mem_internal_allocate_zeroed(cif->rtype->size);
+
+ ffi_call(cif, FFI_FN(func), return_data, values);
+
+ if (cif->rtype != &ffi_type_void) {
+ char *s;
+ PMC *ret_object;
+ s = Parrot_str_to_cstring(interp, nci_info->pcc_return_signature);
+ switch (*(char*)nci_info->return_translation) {
+ case 'p':
+ {
+ PMC *final_destination = PMCNULL;
+
+ if (*(void**)return_data != NULL) {
+ final_destination = Parrot_pmc_new(interp, enum_class_UnManagedStruct);
+ VTABLE_set_pointer(interp, final_destination, *(void**)return_data);
+ }
+ ret_object = Parrot_pcc_build_call_from_c_args(interp,
+ call_object,
+ s, final_destination);
+ }
+ break;
+ case 't':
+ {
+ STRING *final_destination = Parrot_str_new(interp, *(char**)return_data, 0);
+ ret_object = Parrot_pcc_build_call_from_c_args(interp,
+ call_object,
+ s, final_destination);
+ }
+ break;
+ case 'f':
+ {
+ FLOATVAL final_destination = *(float*)return_data;
+
+ ret_object = Parrot_pcc_build_call_from_c_args(interp,
+ call_object,
+ s, final_destination);
+ }
+ break;
+ default:
+ switch (s[0]) {
+ case 'N':
+ ret_object = Parrot_pcc_build_call_from_c_args(interp,
+ call_object,
+ s, *(FLOATVAL*)return_data);
+ case 'I':
+ ret_object = Parrot_pcc_build_call_from_c_args(interp,
+ call_object,
+ s, *(INTVAL*)return_data);
+ case 'P':
+ case 'S':
+ default:
+ ret_object = Parrot_pcc_build_call_from_c_args(interp,
+ call_object,
+ s, *(void**)return_data);
+ }
+ break;
}
- if (values) {
- mem_sys_free(values);
+ Parrot_str_free_cstring(s);
+ }
+
+ /*
+ * Free memory used for cstrings,
+ * and any other translations that use temporary memory
+ */
+ for (i = 0; i < (size_t)nci_info->arity; i++) {
+ switch ((INTVAL)((char*)nci_info->arg_translation)[i]) {
+ case (INTVAL)'B':
+ if (translation_pointers[i]) {
+ Parrot_str_free_cstring((char*)translation_pointers[i]);
+ }
+ break;
+ case (INTVAL)'t':
+ if (translation_pointers[i]) {
+ Parrot_str_free_cstring((char*)translation_pointers[i]);
+ }
+ break;
+ case (INTVAL)'2':
+ VTABLE_set_integer_native(interp,
+ ((pmc_holder_t*)translation_pointers[i])->p,
+ (INTVAL)*(short*)((pmc_holder_t*)translation_pointers[i])->ival);
+ if (translation_pointers[i]) {
+ mem_sys_free(translation_pointers[i]);
+ }
+ break;
+ case (INTVAL)'3':
+ VTABLE_set_integer_native(interp,
+ ((pmc_holder_t*)translation_pointers[i])->p,
+ (INTVAL)*(int*)((pmc_holder_t*)translation_pointers[i])->ival);
+ if (translation_pointers[i]) {
+ mem_sys_free(translation_pointers[i]);
+ }
+ break;
+ case (INTVAL)'4':
+ VTABLE_set_integer_native(interp,
+ ((pmc_holder_t*)translation_pointers[i])->p,
+ (INTVAL)*(long*)((pmc_holder_t*)translation_pointers[i])->ival);
+ if (translation_pointers[i]) {
+ mem_sys_free(translation_pointers[i]);
+ }
+ break;
+ case (INTVAL)'V':
+ VTABLE_set_pointer(interp,
+ ((pmc_holder_t*)translation_pointers[i])->p,
+ (PMC*)*((pmc_holder_t*)translation_pointers[i])->pval);
+ if (translation_pointers[i]) {
+ mem_sys_free(translation_pointers[i]);
+ }
+ break;
+ case (INTVAL)'d':
+ case (INTVAL)'c':
+ case (INTVAL)'s':
+ case (INTVAL)'i':
+ case (INTVAL)'l':
+ case (INTVAL)'q':
+ if (translation_pointers[i]) {
+ mem_sys_free(translation_pointers[i]);
+ }
+ break;
+ default:
+ break;
}
}
+
+ if (nci_info->arity > 0 && middle_man) {
+ mem_sys_free(middle_man);
+ }
+ if (return_data) {
+ mem_sys_free(return_data);
+ }
+ if (values) {
+ mem_sys_free(values);
+ }
cont = INTERP->current_cont;
@@ -1463,16 +1433,12 @@
INTVAL arity = 0;
if (nci_info) {
- if (PObj_flag_TEST(private2, SELF)) {
+ if (!nci_info->cif) {
+ nci_info->cif = build_libffi_func(interp, nci_info);
}
- else {
- if (!nci_info->cif) {
- nci_info->cif = build_libffi_func(interp, nci_info);
- }
- if (nci_info->cif) {
- arity = nci_info->arity;
- RETURN(INTVAL arity);
- }
+ if (nci_info->cif) {
+ arity = nci_info->arity;
+ RETURN(INTVAL arity);
}
}
Modified: branches/gsoc_nci/src/pmc/nci.pmc
==============================================================================
--- branches/gsoc_nci/src/pmc/nci.pmc Wed Oct 27 21:51:16 2010 (r49701)
+++ branches/gsoc_nci/src/pmc/nci.pmc Wed Oct 27 22:27:14 2010 (r49702)
@@ -18,6 +18,9 @@
*/
+/* Cheat with this include, for whatever reason the space is required */
+# include "ffi.h"
+
/* HEADERIZER HFILE: none */
/* HEADERIZER BEGIN: static */
/* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
@@ -25,72 +28,800 @@
PARROT_IGNORABLE_RESULT
static nci_thunk_t /*@alt void@*/
build_func(PARROT_INTERP,
- ARGMOD(Parrot_NCI_attributes *nci))
+ ARGMOD(Parrot_NCI_attributes *nci_info))
+ __attribute__nonnull__(1)
+ __attribute__nonnull__(2)
+ FUNC_MODIFIES(*nci_info);
+
+static void pcc_params(PARROT_INTERP,
+ ARGIN(STRING *sig),
+ ARGMOD(Parrot_NCI_attributes *nci_info),
+ size_t sig_length)
__attribute__nonnull__(1)
__attribute__nonnull__(2)
- FUNC_MODIFIES(*nci);
+ __attribute__nonnull__(3)
+ FUNC_MODIFIES(*nci_info);
#define ASSERT_ARGS_build_func __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
PARROT_ASSERT_ARG(interp) \
- , PARROT_ASSERT_ARG(nci))
+ , PARROT_ASSERT_ARG(nci_info))
+#define ASSERT_ARGS_pcc_params __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
+ PARROT_ASSERT_ARG(interp) \
+ , PARROT_ASSERT_ARG(sig) \
+ , PARROT_ASSERT_ARG(nci_info))
/* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
/* HEADERIZER END: static */
+static
+INTVAL
+parse_sig(PARROT_INTERP, STRING *sig, size_t sig_length, Parrot_NCI_attributes *nci_info);
+
+static
+size_t
+parse_return(PARROT_INTERP, STRING* sig, size_t sig_length,
+ Parrot_NCI_attributes * nci_info, ffi_type **return_type);
+
+static
+size_t
+parse_args(PARROT_INTERP, STRING* sig, size_t start, size_t sig_length,
+ Parrot_NCI_attributes *nci_info, ffi_type ***arg_types);
+
+static
+size_t
+parse_identifier(PARROT_INTERP,
+ STRING* sig, size_t start, size_t end,
+ ffi_type** sig_obj,
+ char* pmc_type, size_t *pmc_count,
+ char* translation, size_t *translation_length);
+
+static
+size_t
+parse_structure(PARROT_INTERP, STRING* sig, size_t start, size_t end,
+ ffi_type** sig_obj, char* pmc_type);
+
+static
+INTVAL
+parse_prefix(INTVAL c);
+
+static
+size_t
+structure_length(PARROT_INTERP, STRING* sig, size_t start, size_t end);
+
+static
+size_t
+count_args(PARROT_INTERP, STRING* sig, size_t start, size_t end);
+
+static
+size_t
+find_matching(PARROT_INTERP, STRING* sig, size_t start, size_t sig_length,
+ INTVAL start_character, INTVAL end_character);
+
+#define IS_DIGIT(x) (((x) == '0') || ((x) == '1') || ((x) == '2') || ((x) == '3') \
+ || ((x) == '4') || ((x) == '5') || ((x) == '6') || ((x) == '7') \
+ || ((x) == '8') || ((x) == '9'))
+
+#define IS_PREFIX(x) (((x) == '*') || ((x) == 'u'))
+
+#define IS_OLD_TYPE(x) (((x) == 'P') || ((x) == 'J') || ((x) == 'N') || ((x) == 'S') \
+ || ((x) == 'O') || ((x) == '@') || ((x) == 'B') || ((x) == 'p') \
+ || ((x) == '2') || ((x) == '3') || ((x) == '4') || ((x) == 'U') \
+ || ((x) == 'V') || ((x) == 'I'))
+
+#define IS_TYPE(x) (((x) == 'i') || ((x) == 'v') || ((x) == 'l') || ((x) == 't') \
+ || ((x) == 'c') || ((x) == 'b') || ((x) == 'f') || ((x) == 'd') \
+ || ((x) == 's') || IS_OLD_TYPE(x))
+
+#define IS_POSTFIX(x) ((x) == '{') /* || IS_DIGIT(x)) */
+#define IS_INFIX(x) ((x) == '|')
+#define IS_START_CIRCUMFIX(x) ((x) == '(')
+#define IS_END_CIRCUMFIX(x) ((x) == ')')
+#define IS_NOT_END_CIRCUMFIX(x) ((x) != ')')
+
+#define PREFIX_POINTER (1<<0)
+#define PREFIX_SIGNED ( 0)
+#define PREFIX_UNSIGNED (1<<1)
+#define PREFIX_NATIVE (1<<2)
+
+typedef struct pmc_holder_t {
+ PMC* p;
+ union {
+ INTVAL* ival;
+ void** pval;
+ };
+} pmc_holder_t;
+
+/*
+
+=item C<static INTVAL parse_sig(PARROT_INTERP, STRING *sig,
+ size_t sig_length, Parrot_NCI_attributes *nci_info)>
+
+Parse a full signature. All signatures should contain a return type and a list of
+arguments. "vv" Would be the shortest "void fn(void)" signature you can legally make.
+
+See C<parse_return> and C<parse_args> to see how the signature is broken down.
+
+=cut
+
+*/
+
+static INTVAL
+parse_sig(PARROT_INTERP, STRING *sig, size_t sig_length, Parrot_NCI_attributes *nci_info) {
+ ffi_cif cif;
+ ffi_type *return_type;
+ ffi_type **arg_types;
+
+ if (sig_length) {
+ size_t i = parse_return(interp, sig, sig_length, nci_info, &return_type);
+ if (i < sig_length)
+ parse_args(interp, sig, i, sig_length, nci_info, &arg_types);
+ else {
+ arg_types = mem_internal_allocate_n_zeroed_typed(1, ffi_type*);
+ arg_types[0] = &ffi_type_void;
+ nci_info->pcc_params_signature = string_make(interp, "", 1, NULL, 0);
+ nci_info->arg_translation = NULL;
+ nci_info->arity = 0;
+ }
+ }
+ else {
+ arg_types = mem_internal_allocate_n_zeroed_typed(1, ffi_type*);
+ arg_types[0] = &ffi_type_void;
+ return_type = &ffi_type_void;
+ nci_info->pcc_params_signature = string_make(interp, "", 1, NULL, 0);
+ nci_info->arg_translation = NULL;
+ nci_info->arity = 0;
+ }
+
+ if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI,
+ nci_info->arity, return_type, arg_types) == FFI_OK) {
+ nci_info->cif = (void*)mem_internal_allocate_typed(ffi_cif);
+ memcpy(nci_info->cif, &cif, sizeof (ffi_cif));
+ nci_info->arg_types = arg_types;
+
+ return 1;
+ }
+
+ if (arg_types) {
+ mem_sys_free(arg_types);
+ }
+
+ /* TODO: Throw Error here. */
+ printf("Bad signature\n");
+
+ return 0;
+}
+
/*
-=item C<static nci_thunk_t build_func(PARROT_INTERP, Parrot_NCI_attributes
-*nci)>
+=item C<static size_t parse_return(PARROT_INTERP, STRING *sig, size_t sig_length,
+ Parrot_NCI_attributes* nci_info, ffi_type **return_type)>
-Actually build the NCI thunk.
+Parses the return type. This assumes the first identifier is the return type.
+
+See C<parse_identifier> to see how a single identifer is parsed.
=cut
*/
+static size_t
+parse_return(PARROT_INTERP, STRING *sig, size_t sig_length,
+ Parrot_NCI_attributes* nci_info, ffi_type **return_type) {
+ char *t = mem_allocate_n_zeroed_typed(2, char);
+ size_t j = 0, k = 0;
+ /* Should be 1 character plus a NULL" */
+ char * result_sig = mem_allocate_n_zeroed_typed(2, char);
+ size_t result_length = parse_identifier(interp,
+ sig, 0, sig_length,
+ return_type,
+ result_sig, &j,
+ t, &k);
+
+ nci_info->pcc_return_signature = string_make(interp, result_sig, 2, NULL, 0);
+ nci_info->return_translation = (void*)t;
+ mem_sys_free(result_sig);
+ return result_length;
+}
+
+/*
+
+=item C<static size_t parse_args(PARROT_INTERP, STRING* sig, size_t start, size_t sig_length,
+ Parrot_NCI_attributes *nci_info, ffi_type ***arg_types)>
+
+Parses the signatures arguments. It takes an offset to know where to start looking.
+This should fill out a list of C<ffi_type*> args.
+
+See C<parse_identifier> to see how a single identifer is parsed.
+
+=cut
+
+*/
+
+static size_t
+parse_args(PARROT_INTERP, STRING* sig, size_t start, size_t sig_length,
+ Parrot_NCI_attributes *nci_info, ffi_type ***arg_types) {
+ size_t i = start;
+ size_t arg_count = 0;
+ size_t argc = count_args(interp, sig, start, sig_length);
+ char* parrot_types = mem_allocate_n_zeroed_typed(argc + 1, char);
+ size_t parrot_types_length = 0;
+ char* translation_types = mem_allocate_n_zeroed_typed(argc + 1, char);
+ size_t translation_length = 0;
+
+ *arg_types = mem_internal_allocate_n_zeroed_typed(argc + 1, ffi_type*);
+
+ while (i < sig_length) {
+ ffi_type *ident;
+ i = parse_identifier(interp,
+ sig, i, sig_length,
+ &ident,
+ parrot_types, &parrot_types_length,
+ translation_types, &translation_length);
+ (*arg_types)[arg_count] = ident;
+ arg_count++;
+ }
+
+ nci_info->pcc_params_signature = string_make(interp, parrot_types,
+ strlen(parrot_types), NULL, 0);
+ nci_info->arg_translation = translation_types;
+ nci_info->arity = arg_count;
+
+ mem_sys_free(parrot_types);
+
+ return i;
+}
+
+/*
+
+=item C<static size_t parse_identifier(PARROT_INTERP, STRING *sig, size_t start,
+ size_t sig_length, ffi_type **type_obj,
+ char **type, size_t *pmc_count,
+ char **translation, size_t *translation_count)>
+
+Parse an identifier and build its representation used for PCC and any translations
+that are needed.
+
+An example of a transation is "t", it will take a STRING* and convert it to a
+char* for the function call.
+
+=cut
+
+*/
+
+static size_t
+parse_identifier(PARROT_INTERP,
+ STRING *sig, size_t start, size_t sig_length,
+ ffi_type **type_obj,
+ char *type, size_t *pmc_count,
+ char *translation, size_t *translation_count) {
+ size_t i = start;
+ INTVAL done = 0;
+
+ while (!done && i < sig_length) {
+ INTVAL c = Parrot_str_indexed(interp, sig, i);
+ int prefix = 0;
+ while (IS_PREFIX(c)) {
+ prefix |= parse_prefix(c);
+ i++;
+
+ if (i < sig_length)
+ c = Parrot_str_indexed(interp, sig, i);
+ else
+ return i;
+ }
+
+ if (IS_START_CIRCUMFIX(c)) {
+ i = parse_structure(interp, sig, i + 1, sig_length, type_obj, type);
+ i++;
+
+ if (i < sig_length)
+ c = Parrot_str_indexed(interp, sig, i);
+ else
+ return i;
+ }
+ else if (IS_TYPE(c)) {
+ if (prefix & PREFIX_POINTER) {
+ *type_obj = &ffi_type_pointer;
+ continue;
+ }
+ translation[(*translation_count)++] = ' ';
+ switch (c) {
+ case (INTVAL)' ':
+ case (INTVAL)'0': /* null ptr or such - doesn't consume a reg */
+ break;
+ case (INTVAL)'c':
+ translation[(*translation_count) - 1] = 'c';
+ type[(*pmc_count)++] = 'I';
+ if (prefix & PREFIX_UNSIGNED) {
+ *type_obj = &ffi_type_uchar;
+ }
+ else {
+ *type_obj = &ffi_type_schar;
+ }
+ break;
+ case (INTVAL)'B':
+ translation[(*translation_count) - 1] = 'B';
+ type[(*pmc_count)++] = 'S';
+ *type_obj = &ffi_type_pointer;
+ break;
+ case (INTVAL)'b':
+ translation[(*translation_count) - 1] = 'b';
+ type[(*pmc_count)++] = 'S';
+ *type_obj = &ffi_type_pointer;
+ break;
+ case (INTVAL)'s':
+ translation[(*translation_count) - 1] = 's';
+ type[(*pmc_count)++] = 'I';
+ if (prefix & PREFIX_UNSIGNED) {
+ *type_obj = &ffi_type_ushort;
+ }
+ else {
+ *type_obj = &ffi_type_sshort;
+ }
+ break;
+ case (INTVAL)'I': /* INTVAL */
+ case (INTVAL)'i':
+ translation[(*translation_count) - 1] = 'i';
+ type[(*pmc_count)++] = 'I';
+ if (prefix & PREFIX_UNSIGNED) {
+ *type_obj = &ffi_type_uint;
+ }
+ else {
+ *type_obj = &ffi_type_sint;
+ }
+ break;
+ case (INTVAL)'l':
+ translation[(*translation_count) - 1] = 'l';
+ type[(*pmc_count)++] = 'I';
+ if (prefix & PREFIX_UNSIGNED) {
+ *type_obj = &ffi_type_ulong;
+ }
+ else {
+ *type_obj = &ffi_type_slong;
+ }
+ break;
+ case (INTVAL)'q':
+ translation[(*translation_count) - 1] = 'q';
+ type[(*pmc_count)++] = 'I';
+ if (prefix & PREFIX_UNSIGNED) {
+ *type_obj = &ffi_type_uint64;
+ }
+ else {
+ *type_obj = &ffi_type_sint64;
+ }
+ break;
+ case (INTVAL)'J': /* interpreter */
+ translation[(*translation_count) - 1] = 'J';
+ *type_obj = &ffi_type_pointer;
+ break;
+ case (INTVAL)'p': /* push pmc->data */
+ translation[(*translation_count) - 1] = 'p';
+ type[(*pmc_count)++] = 'P';
+ *type_obj = &ffi_type_pointer;
+ break;
+ case (INTVAL)'2':
+ translation[(*translation_count) - 1] = '2';
+ type[(*pmc_count)++] = 'P';
+ *type_obj = &ffi_type_pointer;
+ break;
+ case (INTVAL)'3':
+ translation[(*translation_count) - 1] = '3';
+ type[(*pmc_count)++] = 'P';
+ *type_obj = &ffi_type_pointer;
+ break;
+ case (INTVAL)'4':
+ translation[(*translation_count) - 1] = '4';
+ type[(*pmc_count)++] = 'P';
+ *type_obj = &ffi_type_pointer;
+ break;
+ case (INTVAL)'P': /* push PMC * */
+ translation[(*translation_count) - 1] = 'P';
+ type[(*pmc_count)++] = 'P';
+ *type_obj = &ffi_type_pointer;
+ break;
+ case (INTVAL)'V': /* push PMC * */
+ translation[(*translation_count) - 1] = 'V';
+ type[(*pmc_count)++] = 'P';
+ *type_obj = &ffi_type_pointer;
+ break;
+ case (INTVAL)'S':
+ type[(*pmc_count)++] = 'S';
+ *type_obj = &ffi_type_pointer;
+ case (INTVAL)'t':
+ translation[(*translation_count) - 1] = 't';
+ type[(*pmc_count)++] = 'S';
+ *type_obj = &ffi_type_pointer;
+ break;
+ case (INTVAL)'v':
+ type[(*pmc_count)++] = 'v';
+ *type_obj = &ffi_type_void;
+ break;
+#if (DOUBLE_SIZE == 4) /* FLOATVAL is a float */
+ case (INTVAL)'N':
+#endif
+ case (INTVAL)'f':
+ translation[(*translation_count) - 1] = 'f';
+ type[(*pmc_count)++] = 'N';
+ *type_obj = &ffi_type_float;
+ break;
+#if (DOUBLE_SIZE == 8) /* FLOATVAL is a double */
+ case (INTVAL)'N':
+#endif
+ case (INTVAL)'d':
+ translation[(*translation_count) - 1] = 'd';
+ type[(*pmc_count)++] = 'N';
+ *type_obj = &ffi_type_double;
+ break;
+#if (DOUBLE_SIZE > 8) /* FLOATVAL is a long double */
+ case (INTVAL)'N':
+#endif
+ case (INTVAL)'D':
+ translation[(*translation_count) - 1] = 'D';
+ type[(*pmc_count)++] = 'N';
+ *type_obj = &ffi_type_longdouble;
+ break;
+ case (INTVAL)'O': /* push PMC * invocant */
+ *type_obj = &ffi_type_pointer;
+ type[(*pmc_count)++] = 'P';
+ type[(*pmc_count)++] = 'i';
+ break;
+ case (INTVAL)'@': /* push PMC * slurpy */
+ *type_obj = &ffi_type_pointer;
+ type[(*pmc_count)++] = 'P';
+ type[(*pmc_count)++] = 's';
+ break;
+ default:
+ Parrot_ex_throw_from_c_args(interp, NULL,
+ EXCEPTION_JIT_ERROR,
+ "Unknown param Signature %c\n", (char)c);
+ break;
+ }
+ i++;
+
+ if (i < sig_length)
+ c = Parrot_str_indexed(interp, sig, i);
+ else
+ return i;
+ }
+ else {
+ Parrot_ex_throw_from_c_args(interp, NULL,
+ EXCEPTION_JIT_ERROR,
+ "Unknown param Signature %c\n", (char)c);
+ }
+
+ /*
+ * Parse postfix ops
+ * TODO: Parse postfix ops, currently I skip them.
+ */
+ while (IS_POSTFIX(c)) {
+ i++;
+ if (i < sig_length)
+ c = Parrot_str_indexed(interp, sig, i);
+ else
+ return i;
+ }
+
+ if ((i < sig_length) && (c == (INTVAL)'|')) {
+ /* Its a union, parse it special. */
+ }
+ else {
+ done = 1;
+ }
+ }
+
+ return i;
+}
+
+/*
+
+=item C<static INTVAL parse_prefix(INTVAL c)>
+
+Parse a prefix character.
+
+=cut
+
+*/
+
+static INTVAL
+parse_prefix(INTVAL c) {
+ switch (c) {
+ case '*':
+ return PREFIX_POINTER;
+ break;
+ case 'u':
+ return PREFIX_UNSIGNED;
+ break;
+ default:
+ return 0;
+ break;
+ }
+
+ return 0;
+}
+
+/*
+
+=item C<static size_t parse_structure(PARROT_INTERP, STRING* sig, size_t start,
+ size_t sig_length, ffi_type **type_obj, char* pmc_type)>
+
+Parses a stucture.
+TODO: This should auto inflate to an UnmanagedStruct or a ManagedStruct in the future.
+
+=cut
+
+*/
+
+static size_t
+parse_structure(PARROT_INTERP, STRING* sig, size_t start, size_t sig_length,
+ ffi_type **type_obj, char* pmc_type) {
+ size_t i = start;
+ size_t struct_len = structure_length(interp, sig, start, sig_length);
+ size_t element_counter = 0;
+ INTVAL c;
+
+ *type_obj = (ffi_type*)mem_internal_allocate_typed(ffi_type*);
+ (*type_obj)->elements = mem_internal_allocate_n_zeroed_typed(struct_len + 1, ffi_type*);
+
+ (*type_obj)->size = (*type_obj)->alignment = 0;
+ (*type_obj)->type = FFI_TYPE_STRUCT;
+
+ c = Parrot_str_indexed(interp, sig, i);
+ while (i < sig_length && IS_NOT_END_CIRCUMFIX(c)) {
+ i = parse_identifier(interp, sig, i, sig_length,
+ &(*type_obj)->elements[element_counter],
+ NULL, 0, NULL, 0);
+ element_counter++;
+ c = Parrot_str_indexed(interp, sig, i);
+ }
+
+ (*type_obj)->elements[struct_len] = NULL;
+
+ return i;
+}
+
+/*
+
+=item C<static size_t structure_length(PARROT_INTERP, STRING* sig,
+ size_t start, size_t sig_length)>
+
+Calculates the number of items in a stucture for size purposes.
+
+=cut
+
+*/
+
+static size_t
+structure_length(PARROT_INTERP, STRING* sig, size_t start, size_t sig_length) {
+ size_t len = 0;
+ size_t i = start;
+ INTVAL depth = 0;
+ INTVAL c = Parrot_str_indexed(interp, sig, i);
+ while (i < sig_length && depth != -1) {
+ if (IS_START_CIRCUMFIX(c)) depth++;
+ else if (IS_END_CIRCUMFIX(c)) depth--;
+ else if (depth == 0 && (IS_TYPE(c))) len++;
+ i++;
+ c = Parrot_str_indexed(interp, sig, i);
+ }
+
+ return len;
+}
+
+/*
+
+=item C<static size_t find_matching(PARROT_INTERP, STRING* sig, size_t start,
+ size_t sig_length, INTVAL start_character, INTVAL end_character)>
+
+Find matching symbols, used for finding the start and stop of a stucture, it is
+also recursive to handle structures inside of structures.
+
+=cut
+
+*/
+
+static size_t
+find_matching(PARROT_INTERP, STRING* sig, size_t start, size_t sig_length,
+ INTVAL start_character, INTVAL end_character) {
+ size_t i = start;
+ INTVAL c = Parrot_str_indexed(interp, sig, i);
+ while (i < sig_length && c != end_character) {
+ if (c == start_character)
+ i = find_matching(interp, sig, i, sig_length, start_character, end_character);
+ i++;
+ c = Parrot_str_indexed(interp, sig, i);
+ }
+
+ return i;
+}
+
+/*
+
+=item C<size_t count_args(PARROT_INTERP, STRING* sig, size_t start, size_t sig_length)>
+
+Counts the number of arguments from a given starting point. It only counts
+identiers, not prefix, infix or postfix modifiers. Structures are considered as
+1 item in most cases.
+
+=cut
+
+*/
+
+static size_t
+count_args(PARROT_INTERP, STRING* sig, size_t start, size_t sig_length) {
+ size_t length = 0;
+ size_t i = start;
+
+ while (i < sig_length) {
+ const INTVAL c = Parrot_str_indexed(interp, sig, i);
+ if (IS_START_CIRCUMFIX(c)) {
+ i = find_matching(interp, sig, i + 1, sig_length, '(', ')');
+ length++;
+ }
+ else if (IS_TYPE(c)) {
+ length++;
+ }
+ i++;
+ }
+
+ return length;
+}
+
+static void
+pcc_params(PARROT_INTERP, ARGIN(STRING *sig), ARGMOD(Parrot_NCI_attributes *nci_info),
+ size_t sig_length)
+{
+ ASSERT_ARGS(pcc_params)
+
+ /* NCI and PCC have a 1 to 1 mapping except an
+ extra char in PCC for invocant and slurpy */
+ size_t buf_length = sig_length + 2 + 1;
+
+ /* avoid malloc churn on common signatures */
+ char static_buf[16];
+ char * const sig_buf = sig_length <= sizeof static_buf ?
+ static_buf :
+ (char *)mem_sys_allocate(buf_length);
+
+ size_t j = 0;
+ size_t i;
+
+ for (i = 0; i < sig_length; ++i) {
+ const INTVAL c = Parrot_str_indexed(interp, sig, i);
+
+ PARROT_ASSERT(j < buf_length - 1);
+
+ switch (c) {
+ case (INTVAL)'0': /* null ptr or such - doesn't consume a reg */
+ break;
+ case (INTVAL)'f':
+ case (INTVAL)'N':
+ case (INTVAL)'d':
+ sig_buf[j++] = 'N';
+ break;
+ case (INTVAL)'I': /* INTVAL */
+ case (INTVAL)'l': /* long */
+ case (INTVAL)'i': /* int */
+ case (INTVAL)'s': /* short */
+ case (INTVAL)'c': /* char */
+ sig_buf[j++] = 'I';
+ break;
+ case (INTVAL)'S':
+ case (INTVAL)'t': /* string, pass a cstring */
+ sig_buf[j++] = 'S';
+ break;
+ case (INTVAL)'J': /* interpreter */
+ break;
+ case (INTVAL)'p': /* push pmc->data */
+ case (INTVAL)'P': /* push PMC * */
+ case (INTVAL)'V': /* push PMC * */
+ case (INTVAL)'2':
+ case (INTVAL)'3':
+ case (INTVAL)'4':
+ sig_buf[j++] = 'P';
+ break;
+ case (INTVAL)'v':
+ /* null return */
+ if (j == 0)
+ sig_buf[j++] = '\0';
+ break;
+ case (INTVAL)'O': /* push PMC * invocant */
+ sig_buf[j++] = 'P';
+ sig_buf[j++] = 'i';
+ break;
+ case (INTVAL)'@': /* push PMC * slurpy */
+ sig_buf[j++] = 'P';
+ sig_buf[j++] = 's';
+ break;
+ case (INTVAL)'b': /* buffer (void*) pass Buffer_bufstart(SReg) */
+ case (INTVAL)'B': /* buffer (void**) pass &Buffer_bufstart(SReg) */
+ sig_buf[j++] = 'S';
+ break;
+ default:
+ Parrot_ex_throw_from_c_args(interp, NULL,
+ EXCEPTION_JIT_ERROR,
+ "Unknown param Signature %c\n", (char)c);
+ break;
+ }
+ }
+
+ PARROT_ASSERT(j < buf_length);
+ sig_buf[j++] = '\0';
+
+
+ nci_info->pcc_return_signature =
+ Parrot_str_new(interp, sig_buf, 1);
+
+ nci_info->pcc_params_signature = j ?
+ Parrot_str_new(interp, sig_buf + 1, j - 1) :
+ CONST_STRING(interp, "");
+
+ if (sig_buf != static_buf)
+ mem_sys_free(sig_buf);
+}
+
+PARROT_IGNORABLE_RESULT
+static ffi_cif*
+build_libffi_func(PARROT_INTERP, ARGMOD(Parrot_NCI_attributes *nci_info))
+{
+ ASSERT_ARGS(build_func)
+
+ STRING * const key = nci_info->signature;
+ const size_t key_length = Parrot_str_byte_length(interp, key);
+
+ INTVAL r = parse_sig(interp, nci_info->signature, key_length, nci_info);
+
+ return (ffi_cif*)nci_info->cif;
+}
+
+/* actually build the NCI thunk */
+
PARROT_IGNORABLE_RESULT
static nci_thunk_t
-build_func(PARROT_INTERP, ARGMOD(Parrot_NCI_attributes *nci))
+build_func(PARROT_INTERP, ARGMOD(Parrot_NCI_attributes *nci_info))
{
ASSERT_ARGS(build_func)
- nci->signature = Parrot_nci_parse_signature(interp, nci->sig_str);
- Parrot_nci_sig_to_pcc(interp, nci->signature,
- &nci->pcc_params_signature,
- &nci->pcc_return_signature);
+ STRING * const key = nci_info->signature;
+ const size_t key_length = Parrot_str_byte_length(interp, key);
- /* Arity is length of the signature minus one (the return type). */
- nci->arity = VTABLE_elements(interp, nci->signature) - 1;
+ pcc_params(interp, key, nci_info, key_length);
+
+ /* Arity is length of that string minus one (the return type). */
+ nci_info->arity = key_length - 1;
/* Build call function. */
- nci->fb_info = build_call_func(interp, nci->sig_str);
- nci->func = F2DPTR(VTABLE_get_pointer(interp, nci->fb_info));
+ nci_info->fb_info = build_call_func(interp, key);
+ nci_info->func = F2DPTR(VTABLE_get_pointer(interp, nci_info->fb_info));
- return (nci_thunk_t)nci->func;
+ return (nci_thunk_t)nci_info->func;
}
pmclass NCI auto_attrs provides invokable {
/* NCI thunk handling attributes */
- ATTR PMC *signature; /* parsed signature */
- ATTR STRING *sig_str; /* signature string */
- ATTR void *func; /* function pointer to call */
- ATTR PMC *fb_info; /* frame-builder info */
- ATTR void *orig_func; /* pointer to wrapped function */
+ /* NCI thunk handling attributes */
+ ATTR STRING *signature; /* The signature. */
+ ATTR void *func; /* Function pointer to call. */
+ ATTR void *orig_func;
+ ATTR PMC *fb_info; /* Frame-builder info */
+ ATTR void *cif; /* Function interface */
+ ATTR void *arg_types; /* Used for building the libffi call interface */
/* Parrot Sub-ish attributes */
ATTR STRING *pcc_params_signature;
ATTR STRING *pcc_return_signature;
- ATTR INTVAL arity;
+ ATTR void *arg_translation;
+ ATTR void *return_translation;
+ ATTR INTVAL arity; /* Cached arity of the NCI. */
/* MMD fields */
- ATTR STRING *long_signature;
- ATTR PMC *multi_sig;
+ ATTR STRING *long_signature; /* The full signature. */
+ ATTR PMC *multi_sig; /* type tuple array (?) */
/*
=item C<METHOD get_multisig()>
-Return the MMD signature PMC, if any or C<PMCNULL>.
+Return the MMD signature PMC, if any or a Null PMC.
=cut
@@ -106,6 +837,20 @@
/*
+=item C<METHOD set_raw_nci_ptr(void *func)>
+
+Sets the specified function pointer and raw flag.
+
+=cut
+
+*/
+
+ METHOD make_raw_nci(PMC *func) {
+ VTABLE_set_pointer(interp, SELF, (void *)func);
+ }
+
+/*
+
=item C<void init()>
Initializes the NCI with a C<NULL> function pointer.
@@ -118,10 +863,6 @@
PObj_custom_mark_SET(SELF);
}
- VTABLE void *get_pointer() {
- return PARROT_NCI(SELF)->orig_func;
- }
-
/*
=item C<void set_pointer_keyed_str(STRING *key, void *func)>
@@ -132,22 +873,25 @@
*/
+ VTABLE void *get_pointer() {
+ return PARROT_NCI(SELF)->orig_func;
+ }
+
VTABLE void set_pointer_keyed_str(STRING *key, void *func) {
Parrot_NCI_attributes * const nci_info = PARROT_NCI(SELF);
/* Store the original function and signature. */
- SET_ATTR_orig_func(INTERP, SELF, func);
+ SET_ATTR_func(INTERP, SELF, func);
/* ensure that the STRING signature is constant */
if (!PObj_constant_TEST(key)) {
char * const key_c = Parrot_str_to_cstring(INTERP, key);
const size_t key_length = Parrot_str_byte_length(interp, key);
- key = Parrot_str_new_init(interp, key_c, key_length,
- Parrot_default_encoding_ptr, PObj_constant_FLAG);
+ key = string_make(interp, key_c, key_length, NULL, 0);
Parrot_str_free_cstring(key_c);
}
- nci_info->sig_str = key;
+ nci_info->signature = key;
}
/*
@@ -163,19 +907,38 @@
if (PARROT_NCI(SELF)) {
Parrot_NCI_attributes * const nci_info = PARROT_NCI(SELF);
- Parrot_gc_mark_PMC_alive(interp, nci_info->signature);
Parrot_gc_mark_PMC_alive(interp, nci_info->fb_info);
- Parrot_gc_mark_PMC_alive(interp, nci_info->multi_sig);
-
- Parrot_gc_mark_STRING_alive(interp, nci_info->sig_str);
- Parrot_gc_mark_STRING_alive(interp, nci_info->long_signature);
+ Parrot_gc_mark_STRING_alive(interp, nci_info->signature);
Parrot_gc_mark_STRING_alive(interp, nci_info->pcc_params_signature);
Parrot_gc_mark_STRING_alive(interp, nci_info->pcc_return_signature);
+ Parrot_gc_mark_STRING_alive(interp, nci_info->long_signature);
+ Parrot_gc_mark_PMC_alive(interp, nci_info->multi_sig);
}
}
/*
+=item C<void destroy()>
+
+Free all of the memory used internally to store various things, like libffi call signatures.
+
+=cut
+
+*/
+
+ VTABLE void destroy() {
+ if (PARROT_NCI(SELF)) {
+ Parrot_NCI_attributes * const nci_info = PARROT_NCI(SELF);
+ mem_sys_free(nci_info->cif);
+ mem_sys_free(nci_info->arg_translation);
+ mem_sys_free(nci_info->arg_types);
+ mem_sys_free(nci_info->return_translation);
+ }
+ }
+
+
+/*
+
=item C<PMC *clone()>
Creates and returns a clone of the NCI.
@@ -187,7 +950,7 @@
VTABLE PMC *clone() {
Parrot_NCI_attributes * const nci_info_self = PARROT_NCI(SELF);
Parrot_NCI_attributes *nci_info_ret;
- void *orig_func;
+ void *cif;
PMC * const ret = Parrot_pmc_new(INTERP, SELF->vtable->base_type);
nci_info_ret = PARROT_NCI(ret);
@@ -199,12 +962,12 @@
nci_info_ret->func = nci_info_self->func;
nci_info_ret->fb_info = nci_info_self->fb_info;
nci_info_ret->orig_func = nci_info_self->orig_func;
+ nci_info_ret->cif = nci_info_self->cif;
nci_info_ret->signature = nci_info_self->signature;
- nci_info_ret->sig_str = nci_info_self->sig_str;
nci_info_ret->pcc_params_signature = nci_info_self->pcc_params_signature;
nci_info_ret->pcc_return_signature = nci_info_self->pcc_params_signature;
nci_info_ret->arity = nci_info_self->arity;
- PObj_get_FLAGS(ret) = PObj_get_FLAGS(SELF);
+ PObj_get_FLAGS(ret) |= (PObj_get_FLAGS(SELF) & 0x7);
return ret;
}
@@ -236,29 +999,376 @@
*/
VTABLE opcode_t *invoke(void *next) {
- Parrot_NCI_attributes * const nci_info = PARROT_NCI(SELF);
- nci_thunk_t func;
- PMC *fb_info;
+ Parrot_NCI_attributes * const nci_info = PARROT_NCI(SELF);
char *sig_str;
- void *orig_func;
PMC *cont;
+ INTVAL return_size = sizeof (void*);
+ PMC *ctx = CURRENT_CONTEXT(interp);
+ PMC *call_object = Parrot_pcc_get_signature(interp, ctx);
+ void (*func)(void*,void*,void*); /* a function pointer for our function to call */
+
+ PMC *positional, *arg_iter;
+ STRING *void_return;
+ void **values;
+ void **pcc_ptr;
+ void **translation_pointers = NULL; /* Data translation pointers, used to hold values
+ that are passed by reference so we can update
+ the objects after the FFI call is over */
+ void **pcc_val = NULL; /* A holder for the values passed to pcc */
+ void **middle_man = NULL; /* An array to hold various pointers so they are not lost if
+ the function changes values by reference */
+ void *return_data; /* Holds return data from FFI call */
+ size_t count, i, j_offset;
+ char *tmp_sig;
+ ffi_cif *cif, pcc_cif;
+ ffi_type **pcc_args;
- GET_ATTR_orig_func(INTERP, SELF, orig_func);
- func = (nci_thunk_t)D2FPTR(nci_info->func);
-
- GET_ATTR_fb_info(INTERP, SELF, fb_info);
+ cif = (ffi_cif*)nci_info->cif;
+ func = (void (*)(void*, void*, void*))nci_info->func;
- if (!func) {
+ if (!cif) {
/* build the thunk only when necessary */
- func = build_func(interp, nci_info);
+ cif = build_libffi_func(interp, nci_info);
- if (!func)
+ if (!cif && !func)
Parrot_ex_throw_from_c_args(INTERP, NULL,
EXCEPTION_INVALID_OPERATION,
"attempt to call NULL function");
}
- func(INTERP, SELF, fb_info);
+ if (nci_info->arity > 0) {
+ size_t pcc_argc, pcc_values_offset, pcc_values_size, values_size;
+ /* Function has arguments */
+ pcc_args = mem_internal_allocate_n_zeroed_typed(nci_info->arity + 4, ffi_type*);
+ tmp_sig = Parrot_str_to_cstring(interp, nci_info->pcc_params_signature);
+
+ pcc_args[0] = &ffi_type_pointer;
+ pcc_args[1] = &ffi_type_pointer;
+ pcc_args[2] = &ffi_type_pointer;
+ pcc_values_size = 0;
+ values_size = 0;
+ pcc_argc = Parrot_str_length(interp, nci_info->pcc_params_signature);
+
+ /* Add up the size of memory needed for the actual call */
+ for (i = 0; i < (size_t)nci_info->arity; i++) {
+ values_size += cif->arg_types[i]->size;
+ }
+
+ pcc_ptr = (void**)mem_internal_allocate_n_zeroed_typed(pcc_argc + 4, void*);
+
+ /* Setup Parrot_pcc_fill_params_from_c_args required arguments */
+ pcc_ptr[0] = &interp;
+ pcc_ptr[1] = &call_object;
+ pcc_ptr[2] = &tmp_sig;
+
+ pcc_val = mem_internal_allocate_n_zeroed_typed(pcc_argc, void*);
+ /* Allocate enough room for the values passed to the ffi function plus add some
+ padding just to be sure we have enough space. */
+ values = mem_internal_allocate_zeroed(values_size + 2 * sizeof(void*));
+ /* Middle man is used to contain */
+ middle_man = mem_internal_allocate_n_zeroed_typed(nci_info->arity, void*);
+
+ /* Add up the size of the pcc arguments */
+ for (i = 0; i < pcc_argc; i++) {
+ pcc_args[i + 3] = &ffi_type_pointer;
+ if (tmp_sig[i] == 'N') {
+ pcc_val[i] = mem_internal_allocate_typed(FLOATVAL);
+ pcc_ptr[i+3] = &pcc_val[i];
+ }
+ else if (tmp_sig[i] == 'I') {
+ pcc_val[i] = mem_internal_allocate_typed(INTVAL);
+ pcc_ptr[i+3] = &pcc_val[i];
+ }
+ else if (tmp_sig[i] == 'P' || tmp_sig[i] == 'S') {
+ pcc_val[i] = mem_internal_allocate_typed(void*);
+ pcc_ptr[i+3] = &pcc_val[i];
+ }
+ }
+
+ if (ffi_prep_cif(&pcc_cif, FFI_DEFAULT_ABI, 3 + pcc_argc,
+ &ffi_type_void, pcc_args) != FFI_OK) {
+ Parrot_ex_throw_from_c_args(INTERP, NULL,
+ EXCEPTION_INVALID_OPERATION,
+ "Bad signature generated for Parrot_pcc_fill_params_from_c_args in NCI");
+ }
+
+ ffi_call(&pcc_cif, FFI_FN(Parrot_pcc_fill_params_from_c_args), NULL, pcc_ptr);
+
+ Parrot_str_free_cstring(tmp_sig);
+
+ /*
+ * Apply Argument Transformations
+ * this is mostly to transform STRING* into char*
+ * and add the parrot interp argument if it needs it
+ * but other transformations might apply later, like packing an
+ * object into a ManagedStruct
+ */
+ j_offset = 0;
+ translation_pointers = mem_internal_allocate_n_zeroed_typed(nci_info->arity, void*);
+ for (i = 0; i < (size_t)nci_info->arity; i++) {
+ switch ((INTVAL)((char*)nci_info->arg_translation)[i]) {
+ case 'J':
+ values[i] = &interp;
+ j_offset++;
+ break;
+ case 't':
+ if (STRING_IS_NULL(*(STRING**)pcc_val[i - j_offset])) {
+ translation_pointers[i] = (char*) NULL;
+ }
+ else {
+ translation_pointers[i] = Parrot_str_to_cstring(interp, *(STRING**)pcc_val[i - j_offset]);
+ }
+ values[i] = &translation_pointers[i];
+ break;
+ case 'B':
+ if (STRING_IS_NULL(*(STRING**)pcc_val[i - j_offset])) {
+ translation_pointers[i] = (char*) NULL;
+ }
+ else {
+ translation_pointers[i] = Parrot_str_to_cstring(interp, *(STRING**)pcc_val[i - j_offset]);
+ }
+ middle_man[i] = &translation_pointers[i];
+ values[i] = &middle_man[i];
+ break;
+ case 'b':
+ values[i] = &Buffer_bufstart(*(STRING**)pcc_val[i - j_offset]);
+ break;
+ case 'c':
+ translation_pointers[i] = mem_internal_allocate_zeroed_typed(char);
+ *((char**)translation_pointers)[i] = (char)*(INTVAL*)pcc_val[i - j_offset];
+ values[i] = translation_pointers[i];
+ break;
+ case '2':
+ translation_pointers[i] = mem_internal_allocate_zeroed_typed(pmc_holder_t);
+ ((pmc_holder_t*)translation_pointers[i])->p = *(PMC**)pcc_val[i - j_offset];
+ ((pmc_holder_t*)translation_pointers[i])->ival = (INTVAL*)mem_internal_allocate_zeroed_typed(short);
+ *((pmc_holder_t*)translation_pointers[i])->ival = (short)VTABLE_get_integer(interp, *(PMC**)pcc_ptr[i - j_offset]);
+ values[i] = &((pmc_holder_t*)translation_pointers[i])->ival;
+ break;
+ case 's':
+ translation_pointers[i] = mem_internal_allocate_zeroed_typed(short);
+ *((short**)translation_pointers)[i] = (short)*(INTVAL*)pcc_val[i - j_offset];
+ values[i] = translation_pointers[i];
+ break;
+ case '3':
+ translation_pointers[i] = mem_internal_allocate_zeroed_typed(pmc_holder_t);
+ ((pmc_holder_t*)translation_pointers[i])->p = *(PMC**)pcc_val[i - j_offset];
+ ((pmc_holder_t*)translation_pointers[i])->ival = (INTVAL*)mem_internal_allocate_zeroed_typed(int);
+ *((pmc_holder_t*)translation_pointers[i])->ival = (int)VTABLE_get_integer(interp, *(PMC**)pcc_val[i - j_offset]);
+ values[i] = &((pmc_holder_t*)translation_pointers[i])->ival;
+ break;
+ case 'i':
+ translation_pointers[i] = mem_internal_allocate_zeroed_typed(int);
+ *((int**)translation_pointers)[i] = (int)*(INTVAL*)pcc_val[i - j_offset];
+ values[i] = translation_pointers[i];
+ break;
+ case '4':
+ translation_pointers[i] = mem_internal_allocate_zeroed_typed(pmc_holder_t);
+ ((pmc_holder_t*)translation_pointers[i])->p = *(PMC**)pcc_val[i - j_offset];
+ ((pmc_holder_t*)translation_pointers[i])->ival = (INTVAL*)mem_internal_allocate_zeroed_typed(long);
+ *((pmc_holder_t*)translation_pointers[i])->ival = (long)VTABLE_get_integer(interp, *(PMC**)pcc_val[i - j_offset]);
+ values[i] = &((pmc_holder_t*)translation_pointers[i])->ival;
+ break;
+ case 'l':
+ translation_pointers[i] = mem_internal_allocate_zeroed_typed(long);
+ *((long**)translation_pointers)[i] = (long)*(INTVAL*)pcc_val[i - j_offset];
+ values[i] = translation_pointers[i];
+ break;
+ case 'q':
+ translation_pointers[i] = mem_internal_allocate_zeroed_typed(long long);
+ *((long long**)translation_pointers)[i] = (long long)*(INTVAL*)pcc_val[i - j_offset];
+ values[i] = translation_pointers[i];
+ break;
+ case 'V':
+ translation_pointers[i] = mem_internal_allocate_zeroed_typed(pmc_holder_t);
+ ((pmc_holder_t*)translation_pointers[i])->p = *(PMC**)pcc_val[i - j_offset];
+ ((pmc_holder_t*)translation_pointers[i])->pval = (void**)mem_internal_allocate_zeroed_typed(void*);
+ *((pmc_holder_t*)translation_pointers[i])->pval = PMC_IS_NULL(*(PMC**)pcc_val[i - j_offset]) ?
+ (void *)NULL : (void*)VTABLE_get_pointer(interp, *(PMC**)pcc_val[i - j_offset]);
+ values[i] = &((pmc_holder_t*)translation_pointers[i])->pval;
+ break;
+ case 'P':
+ translation_pointers[i] = *(PMC**)pcc_val[i - j_offset];
+ values[i] = &translation_pointers[i];
+ break;
+ case 'p':
+ translation_pointers[i] = PMC_IS_NULL(*(PMC**)pcc_val[i - j_offset]) ?
+ (void *)NULL : VTABLE_get_pointer(interp, *(PMC**)pcc_val[i - j_offset]);
+ values[i] = &translation_pointers[i];
+ break;
+ case 'f':
+ translation_pointers[i] = mem_internal_allocate_zeroed_typed(float);
+ *((float**)translation_pointers)[i] = (float)*(FLOATVAL*)pcc_val[i - j_offset];
+ values[i] = translation_pointers[i];
+ break;
+ case 'd':
+ translation_pointers[i] = mem_internal_allocate_zeroed_typed(double);
+ *((double**)translation_pointers)[i] = *(FLOATVAL*)pcc_val[i - j_offset];
+ values[i] = translation_pointers[i];
+ break;
+ case ' ':
+ default:
+ break;
+ }
+ }
+
+ if (pcc_args) {
+ mem_sys_free(pcc_args);
+ }
+ if (pcc_ptr) {
+ mem_sys_free(pcc_ptr);
+ }
+ if (pcc_val) {
+ for (i = 0; i < pcc_argc; i++) {
+ mem_sys_free(pcc_val[i]);
+ }
+ if (pcc_val)
+ mem_sys_free(pcc_val);
+ }
+ }
+ else {
+ /* No arguments */
+ values = NULL;
+ }
+
+ /*
+ * This will allow for any type of datat to be returned.
+ * Including one day Structures
+ */
+ return_data = mem_internal_allocate_zeroed(cif->rtype->size);
+
+ ffi_call(cif, FFI_FN(func), return_data, values);
+
+ if (cif->rtype != &ffi_type_void) {
+ char *s;
+ PMC *ret_object;
+ s = Parrot_str_to_cstring(interp, nci_info->pcc_return_signature);
+ switch (*(char*)nci_info->return_translation) {
+ case 'p':
+ {
+ PMC *final_destination = PMCNULL;
+
+ if (*(void**)return_data != NULL) {
+ final_destination = Parrot_pmc_new(interp, enum_class_UnManagedStruct);
+ VTABLE_set_pointer(interp, final_destination, *(void**)return_data);
+ }
+ ret_object = Parrot_pcc_build_call_from_c_args(interp,
+ call_object,
+ s, final_destination);
+ }
+ break;
+ case 't':
+ {
+ STRING *final_destination = Parrot_str_new(interp, *(char**)return_data, 0);
+ ret_object = Parrot_pcc_build_call_from_c_args(interp,
+ call_object,
+ s, final_destination);
+ }
+ break;
+ case 'f':
+ {
+ FLOATVAL final_destination = *(float*)return_data;
+
+ ret_object = Parrot_pcc_build_call_from_c_args(interp,
+ call_object,
+ s, final_destination);
+ }
+ break;
+ default:
+ switch (s[0]) {
+ case 'N':
+ ret_object = Parrot_pcc_build_call_from_c_args(interp,
+ call_object,
+ s, *(FLOATVAL*)return_data);
+ case 'I':
+ ret_object = Parrot_pcc_build_call_from_c_args(interp,
+ call_object,
+ s, *(INTVAL*)return_data);
+ case 'P':
+ case 'S':
+ default:
+ ret_object = Parrot_pcc_build_call_from_c_args(interp,
+ call_object,
+ s, *(void**)return_data);
+ }
+ break;
+ }
+ Parrot_str_free_cstring(s);
+ }
+
+ /*
+ * Free memory used for cstrings,
+ * and any other translations that use temporary memory
+ */
+ for (i = 0; i < (size_t)nci_info->arity; i++) {
+ switch ((INTVAL)((char*)nci_info->arg_translation)[i]) {
+ case (INTVAL)'B':
+ if (translation_pointers[i]) {
+ Parrot_str_free_cstring((char*)translation_pointers[i]);
+ }
+ break;
+ case (INTVAL)'t':
+ if (translation_pointers[i]) {
+ Parrot_str_free_cstring((char*)translation_pointers[i]);
+ }
+ break;
+ case (INTVAL)'2':
+ VTABLE_set_integer_native(interp,
+ ((pmc_holder_t*)translation_pointers[i])->p,
+ (INTVAL)*(short*)((pmc_holder_t*)translation_pointers[i])->ival);
+ if (translation_pointers[i]) {
+ mem_sys_free(translation_pointers[i]);
+ }
+ break;
+ case (INTVAL)'3':
+ VTABLE_set_integer_native(interp,
+ ((pmc_holder_t*)translation_pointers[i])->p,
+ (INTVAL)*(int*)((pmc_holder_t*)translation_pointers[i])->ival);
+ if (translation_pointers[i]) {
+ mem_sys_free(translation_pointers[i]);
+ }
+ break;
+ case (INTVAL)'4':
+ VTABLE_set_integer_native(interp,
+ ((pmc_holder_t*)translation_pointers[i])->p,
+ (INTVAL)*(long*)((pmc_holder_t*)translation_pointers[i])->ival);
+ if (translation_pointers[i]) {
+ mem_sys_free(translation_pointers[i]);
+ }
+ break;
+ case (INTVAL)'V':
+ VTABLE_set_pointer(interp,
+ ((pmc_holder_t*)translation_pointers[i])->p,
+ (PMC*)*((pmc_holder_t*)translation_pointers[i])->pval);
+ if (translation_pointers[i]) {
+ mem_sys_free(translation_pointers[i]);
+ }
+ break;
+ case (INTVAL)'d':
+ case (INTVAL)'c':
+ case (INTVAL)'s':
+ case (INTVAL)'i':
+ case (INTVAL)'l':
+ case (INTVAL)'q':
+ if (translation_pointers[i]) {
+ mem_sys_free(translation_pointers[i]);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (nci_info->arity > 0 && middle_man) {
+ mem_sys_free(middle_man);
+ }
+ if (return_data) {
+ mem_sys_free(return_data);
+ }
+ if (values) {
+ mem_sys_free(values);
+ }
+
cont = INTERP->current_cont;
/*
@@ -306,7 +1416,7 @@
VTABLE INTVAL get_bool() {
Parrot_NCI_attributes * const nci_info = PARROT_NCI(SELF);
- return (0 != (INTVAL)nci_info->orig_func);
+ return (0 != (INTVAL)nci_info->cif);
}
/*
@@ -323,9 +1433,10 @@
INTVAL arity = 0;
if (nci_info) {
- if (!nci_info->func)
- build_func(INTERP, nci_info);
- if (nci_info->func) {
+ if (!nci_info->cif) {
+ nci_info->cif = build_libffi_func(interp, nci_info);
+ }
+ if (nci_info->cif) {
arity = nci_info->arity;
RETURN(INTVAL arity);
}
@@ -345,6 +1456,12 @@
F<docs/pdds/pdd03_calling_conventions.pod>.
+=head1 HISTORY
+
+Initial revision by sean 2002/08/04.
+
+Updates by John Harrison, Summer 2010, GSoC.
+
=cut
*/
@@ -355,3 +1472,4 @@
* End:
* vim: expandtab shiftwidth=4:
*/
+
More information about the parrot-commits
mailing list