[svn:parrot] r49730 - in branches/gsoc_nci: config/gen/libffi src/nci src/pmc

plobsing at svn.parrot.org plobsing at svn.parrot.org
Sat Oct 30 06:11:25 UTC 2010


Author: plobsing
Date: Sat Oct 30 06:11:23 2010
New Revision: 49730
URL: https://trac.parrot.org/parrot/changeset/49730

Log:
switch ffi nci.pmc over to standard signature parser

Modified:
   branches/gsoc_nci/config/gen/libffi/nci-ffi.pmc.in
   branches/gsoc_nci/config/gen/libffi/nci.pmc.in
   branches/gsoc_nci/src/nci/signatures.c
   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	Sat Oct 30 00:02:26 2010	(r49729)
+++ branches/gsoc_nci/config/gen/libffi/nci-ffi.pmc.in	Sat Oct 30 06:11:23 2010	(r49730)
@@ -25,12 +25,14 @@
 /* HEADERIZER BEGIN: static */
 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END.  Your changes will be lost. */
 
-PARROT_IGNORABLE_RESULT
-static ffi_cif* build_libffi_func(PARROT_INTERP,
-    ARGMOD(Parrot_NCI_attributes *nci_info))
+static void build_libffi_func(PARROT_INTERP,
+    ARGMOD(Parrot_NCI_attributes *nci))
         __attribute__nonnull__(1)
         __attribute__nonnull__(2)
-        FUNC_MODIFIES(*nci_info);
+        FUNC_MODIFIES(*nci);
+
+static ffi_type * nci_to_ffi_type(PARROT_INTERP, nci_sig_elem_t nci_t)
+        __attribute__nonnull__(1);
 
 static INTVAL parse_prefix(INTVAL c);
 static INTVAL parse_sig(PARROT_INTERP,
@@ -41,16 +43,30 @@
 
 #define ASSERT_ARGS_build_libffi_func __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
        PARROT_ASSERT_ARG(interp) \
-    , PARROT_ASSERT_ARG(nci_info))
+    , PARROT_ASSERT_ARG(nci))
+#define ASSERT_ARGS_nci_to_ffi_type __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
+       PARROT_ASSERT_ARG(interp))
 #define ASSERT_ARGS_parse_prefix __attribute__unused__ int _ASSERT_ARGS_CHECK = (0)
 #define ASSERT_ARGS_parse_sig __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
        PARROT_ASSERT_ARG(interp))
 /* 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);
+#if (INTVAL_SIZE == 4)
+#  define ffi_type_parrot_intval ffi_type_sint32
+#elif (INTVAL_SIZE == 8)
+#  define ffi_type_parrot_intval ffi_type_sint64
+#else
+#  error "unhandled INTVAL_SIZE value"
+#endif
+
+#if (NUMVAL_SIZE == 4)
+#  define ffi_type_parrot_numval ffi_type_float
+#elif (NUMVAL_SIZE == 8)
+#  define ffi_type_parrot_numval ffi_type_double
+#else
+#  error "unhandled NUMVAL_SIZE value"
+#endif
 
 static
 size_t
@@ -76,10 +92,6 @@
                 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);
 
@@ -220,6 +232,83 @@
 
 /*
 
+=item C<static ffi_cif *sig_to_cif(PARROT_INTERP, Parrot_NCI_attributes *nci)>
+
+=cut
+
+*/
+
+static void
+sig_to_cif(PARROT_INTERP, ARGMOD(Parrot_NCI_attributes *nci)) {
+    int        i;
+    PMC       *sig   = nci->signature;
+    INTVAL     argc  = VTABLE_elements(interp, sig) - 1;
+    ffi_type  *ret_t = nci_to_ffi_type(interp, VTABLE_get_integer_keyed_int(interp, sig, 0));
+    ffi_type **arg_t = mem_gc_allocate_n_zeroed_typed(interp, argc, ffi_type *);
+    ffi_cif   *cif   = mem_gc_allocate_zeroed_typed(interp, ffi_cif);
+
+    for (i = 0; i < argc; i++) {
+        arg_t[i] = nci_to_ffi_type(interp, VTABLE_get_integer_keyed_int(interp, sig, i + 1));
+    }
+
+    if (ffi_prep_cif(cif, FFI_DEFAULT_ABI, argc, ret_t, arg_t) == FFI_OK) {
+        nci->cif = cif;
+        nci->arg_types = arg_t;
+        return;
+    }
+
+    mem_gc_free(interp, arg_t);
+    mem_gc_free(interp, cif);
+
+    Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_JIT_ERROR, "invalid ffi signature");
+}
+
+
+/*
+
+=item C<static ffi_type * nci_to_ffi_type(PARROT_INTERP, nci_sig_elem_t nci_t)>
+
+=cut
+
+*/
+
+static ffi_type *
+nci_to_ffi_type(PARROT_INTERP, nci_sig_elem_t nci_t) {
+    switch (nci_t) {
+      case enum_nci_sig_void:   return &ffi_type_void;
+      case enum_nci_sig_null:   return &ffi_type_pointer;
+      case enum_nci_sig_interp: return &ffi_type_pointer;
+
+      case enum_nci_sig_float:  return &ffi_type_float;
+      case enum_nci_sig_double: return &ffi_type_double;
+      case enum_nci_sig_numval: return &ffi_type_parrot_numval;
+
+      case enum_nci_sig_char:   return &ffi_type_schar;
+      case enum_nci_sig_short:  return &ffi_type_sshort;
+      case enum_nci_sig_int:    return &ffi_type_sint;
+      case enum_nci_sig_long:   return &ffi_type_slong;
+      case enum_nci_sig_intval: return &ffi_type_parrot_intval;
+
+      case enum_nci_sig_string:
+      case enum_nci_sig_cstring: 
+      case enum_nci_sig_cstringref:
+      case enum_nci_sig_bufref:
+                                return &ffi_type_pointer;
+
+      case enum_nci_sig_ptr:
+      case enum_nci_sig_pmc:
+      case enum_nci_sig_pmcinv:
+      case enum_nci_sig_pmcslurp:
+      case enum_nci_sig_ptrref:
+      case enum_nci_sig_shortref:
+      case enum_nci_sig_intref:
+      case enum_nci_sig_longref:
+                                return &ffi_type_pointer;
+    }
+}
+
+/*
+
 =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)>
 
@@ -661,24 +750,28 @@
     return length;
 }
 
-PARROT_IGNORABLE_RESULT
-static ffi_cif*
-build_libffi_func(PARROT_INTERP, ARGMOD(Parrot_NCI_attributes *nci_info))
+static void
+build_libffi_func(PARROT_INTERP, ARGMOD(Parrot_NCI_attributes *nci))
 {
     ASSERT_ARGS(build_libffi_func)
 
-    STRING * const key      = nci_info->signature;
-    const size_t key_length = Parrot_str_byte_length(interp, key);
+    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);
 
-    INTVAL r = parse_sig(interp, nci_info->signature, key_length, nci_info);
+    /* Arity is length of the signature minus one (the return type). */
+    nci->arity       = VTABLE_elements(interp, nci->signature) - 1;
 
-    return (ffi_cif*)nci_info->cif;
+    sig_to_cif(interp, nci);
 }
 
 pmclass NCI auto_attrs provides invokable {
     /* NCI thunk handling attributes */
     /* NCI thunk handling attributes */
-    ATTR STRING    *signature;              /* The signature. */
+    ATTR PMC       *signature;
+    ATTR STRING    *sig_str;              /* The signature. */
     ATTR void      *func;                   /* Function pointer to call. */
     ATTR void      *orig_func;
     ATTR PMC       *fb_info;                /* Frame-builder info */
@@ -770,7 +863,7 @@
             Parrot_str_free_cstring(key_c);
         }
 
-        nci_info->signature = key;
+        nci_info->sig_str = key;
     }
 
 /*
@@ -787,7 +880,7 @@
             Parrot_NCI_attributes * const nci_info = PARROT_NCI(SELF);
 
             Parrot_gc_mark_PMC_alive(interp, nci_info->fb_info);
-            Parrot_gc_mark_STRING_alive(interp, nci_info->signature);
+            Parrot_gc_mark_STRING_alive(interp, nci_info->sig_str);
             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);
@@ -842,7 +935,7 @@
         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;
@@ -907,7 +1000,8 @@
 
         if (!cif) {
             /* build the thunk only when necessary */
-            cif = build_libffi_func(interp, nci_info);
+            build_libffi_func(interp, nci_info);
+            cif = nci_info->cif;
 
             if (!cif && !func)
                 Parrot_ex_throw_from_c_args(INTERP, NULL,
@@ -971,7 +1065,10 @@
                     "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);
+            {
+                ffi_arg ret;
+                ffi_call(&pcc_cif, FFI_FN(Parrot_pcc_fill_params_from_c_args), &ret, pcc_ptr);
+            }
             
             Parrot_str_free_cstring(tmp_sig);
 
@@ -985,12 +1082,12 @@
             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':
+                switch (VTABLE_get_integer_keyed_int(interp, nci_info->signature, i + 1)) {
+                  case enum_nci_sig_interp:
                     values[i] = &interp;
                     j_offset++;
                     break;
-                  case 't':
+                  case enum_nci_sig_cstring:
                     if (STRING_IS_NULL(*(STRING**)pcc_val[i - j_offset])) {
                         translation_pointers[i] = (char*) NULL;
                     }
@@ -999,7 +1096,7 @@
                     }
                     values[i] = &translation_pointers[i];
                     break;
-                  case 'B':
+                  case enum_nci_sig_bufref:
                     if (STRING_IS_NULL(*(STRING**)pcc_val[i - j_offset])) {
                         translation_pointers[i] = (char*) NULL;
                     }
@@ -1009,56 +1106,51 @@
                     middle_man[i] = &translation_pointers[i];
                     values[i] = &middle_man[i];
                     break;
-                  case 'b':
+                  case enum_nci_sig_cstringref:
                     values[i] = &Buffer_bufstart(*(STRING**)pcc_val[i - j_offset]);
                     break;
-                  case 'c':
+                  case enum_nci_sig_char:
                     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':
+                  case enum_nci_sig_shortref:
                     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':
+                  case enum_nci_sig_short:
                     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':
+                  case enum_nci_sig_intref:
                     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':
+                  case enum_nci_sig_int:
                     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':
+                  case enum_nci_sig_longref:
                     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':
+                  case enum_nci_sig_long:
                     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':
+                  case enum_nci_sig_ptrref:
                     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*);
@@ -1066,26 +1158,25 @@
                                 (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':
+                  case enum_nci_sig_pmc:
                     translation_pointers[i] = *(PMC**)pcc_val[i - j_offset];
                     values[i] = &translation_pointers[i];
                     break;
-                  case 'p':
+                  case enum_nci_sig_ptr:
                     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':
+                  case enum_nci_sig_float:
                     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':
+                  case enum_nci_sig_double:
                     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;
                 }
@@ -1122,8 +1213,8 @@
             char *s;
             PMC *ret_object;
             s = Parrot_str_to_cstring(interp, nci_info->pcc_return_signature);
-            switch (*(char*)nci_info->return_translation) {
-              case 'p':
+            switch (VTABLE_get_integer_keyed_int(interp, nci_info->signature, 0)) {
+              case enum_nci_sig_ptr:
                 {
                     PMC *final_destination = PMCNULL;
 
@@ -1136,7 +1227,7 @@
                                                                     s, final_destination);
                 }
                 break;
-              case 't':
+              case enum_nci_sig_cstring:
                 {
                     STRING *final_destination = Parrot_str_new(interp, *(char**)return_data, 0);
                     ret_object = Parrot_pcc_build_call_from_c_args(interp,
@@ -1144,7 +1235,7 @@
                                                                    s, final_destination);
                 }
                 break;
-              case 'f':
+              case enum_nci_sig_float:
                 {
                     FLOATVAL final_destination = *(float*)return_data;
 
@@ -1180,18 +1271,18 @@
          * 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':
+            switch (VTABLE_get_integer_keyed_int(interp, nci_info->signature, i + 1)) {
+              case enum_nci_sig_bufref:
                 if (translation_pointers[i]) {
                     Parrot_str_free_cstring((char*)translation_pointers[i]);
                 }
                 break;
-              case (INTVAL)'t':
+              case enum_nci_sig_cstring:
                 if (translation_pointers[i]) {
                     Parrot_str_free_cstring((char*)translation_pointers[i]);
                 }
                 break;
-              case (INTVAL)'2':
+              case enum_nci_sig_shortref:
                 VTABLE_set_integer_native(interp, 
                             ((pmc_holder_t*)translation_pointers[i])->p, 
                             (INTVAL)*(short*)((pmc_holder_t*)translation_pointers[i])->ival);
@@ -1199,7 +1290,7 @@
                     mem_sys_free(translation_pointers[i]);
                 }
                 break;
-              case (INTVAL)'3':
+              case enum_nci_sig_intref:
                 VTABLE_set_integer_native(interp, 
                             ((pmc_holder_t*)translation_pointers[i])->p,
                             (INTVAL)*(int*)((pmc_holder_t*)translation_pointers[i])->ival);
@@ -1207,7 +1298,7 @@
                     mem_sys_free(translation_pointers[i]);
                 }
                 break;
-              case (INTVAL)'4':
+              case enum_nci_sig_longref:
                 VTABLE_set_integer_native(interp,
                             ((pmc_holder_t*)translation_pointers[i])->p,
                             (INTVAL)*(long*)((pmc_holder_t*)translation_pointers[i])->ival);
@@ -1215,7 +1306,7 @@
                     mem_sys_free(translation_pointers[i]);
                 }
                 break;
-              case (INTVAL)'V':
+              case enum_nci_sig_ptrref:
                 VTABLE_set_pointer(interp, 
                             ((pmc_holder_t*)translation_pointers[i])->p, 
                             (PMC*)*((pmc_holder_t*)translation_pointers[i])->pval);
@@ -1223,12 +1314,11 @@
                     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':
+              case enum_nci_sig_double:
+              case enum_nci_sig_char:
+              case enum_nci_sig_short:
+              case enum_nci_sig_int:
+              case enum_nci_sig_long:
                 if (translation_pointers[i]) {
                     mem_sys_free(translation_pointers[i]);
                 }
@@ -1311,7 +1401,7 @@
 
         if (nci_info) {
             if (!nci_info->cif) {
-                nci_info->cif = build_libffi_func(interp, nci_info);
+                build_libffi_func(interp, nci_info);
             }
             if (nci_info->cif) {
                 arity = nci_info->arity;

Modified: branches/gsoc_nci/config/gen/libffi/nci.pmc.in
==============================================================================
--- branches/gsoc_nci/config/gen/libffi/nci.pmc.in	Sat Oct 30 00:02:26 2010	(r49729)
+++ branches/gsoc_nci/config/gen/libffi/nci.pmc.in	Sat Oct 30 06:11:23 2010	(r49730)
@@ -54,6 +54,7 @@
     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);

Modified: branches/gsoc_nci/src/nci/signatures.c
==============================================================================
--- branches/gsoc_nci/src/nci/signatures.c	Sat Oct 30 00:02:26 2010	(r49729)
+++ branches/gsoc_nci/src/nci/signatures.c	Sat Oct 30 06:11:23 2010	(r49730)
@@ -56,7 +56,7 @@
 
         switch ((char)c) {
           case '0':    /* null ptr or such - doesn't consume a reg */
-            e = enum_nci_sig_void;
+            e = enum_nci_sig_null;
             break;
 
           case 'f':
@@ -142,6 +142,9 @@
         VTABLE_push_integer(interp, sig_pmc, e);
     }
 
+    if (VTABLE_elements(interp, sig_pmc) < 1)
+        VTABLE_push_integer(interp, sig_pmc, enum_nci_sig_void);
+
     return sig_pmc;
 }
 
@@ -229,10 +232,10 @@
     }
 
     PARROT_ASSERT(j < buf_len);
-    sig_buf[j++] = '\0';
+    sig_buf[j + 1] = '\0';
 
     *ret_sig    = Parrot_str_new(interp, sig_buf, 1);
-    *params_sig = j ?
+    *params_sig = j - 1 ?
                 Parrot_str_new(interp, &sig_buf[1], j - 1) :
                 CONST_STRING(interp, "");
 

Modified: branches/gsoc_nci/src/pmc/nci.pmc
==============================================================================
--- branches/gsoc_nci/src/pmc/nci.pmc	Sat Oct 30 00:02:26 2010	(r49729)
+++ branches/gsoc_nci/src/pmc/nci.pmc	Sat Oct 30 06:11:23 2010	(r49730)
@@ -25,12 +25,14 @@
 /* HEADERIZER BEGIN: static */
 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END.  Your changes will be lost. */
 
-PARROT_IGNORABLE_RESULT
-static ffi_cif* build_libffi_func(PARROT_INTERP,
-    ARGMOD(Parrot_NCI_attributes *nci_info))
+static void build_libffi_func(PARROT_INTERP,
+    ARGMOD(Parrot_NCI_attributes *nci))
         __attribute__nonnull__(1)
         __attribute__nonnull__(2)
-        FUNC_MODIFIES(*nci_info);
+        FUNC_MODIFIES(*nci);
+
+static ffi_type * nci_to_ffi_type(PARROT_INTERP, nci_sig_elem_t nci_t)
+        __attribute__nonnull__(1);
 
 static INTVAL parse_prefix(INTVAL c);
 static INTVAL parse_sig(PARROT_INTERP,
@@ -41,16 +43,30 @@
 
 #define ASSERT_ARGS_build_libffi_func __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
        PARROT_ASSERT_ARG(interp) \
-    , PARROT_ASSERT_ARG(nci_info))
+    , PARROT_ASSERT_ARG(nci))
+#define ASSERT_ARGS_nci_to_ffi_type __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
+       PARROT_ASSERT_ARG(interp))
 #define ASSERT_ARGS_parse_prefix __attribute__unused__ int _ASSERT_ARGS_CHECK = (0)
 #define ASSERT_ARGS_parse_sig __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
        PARROT_ASSERT_ARG(interp))
 /* 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);
+#if (INTVAL_SIZE == 4)
+#  define ffi_type_parrot_intval ffi_type_sint32
+#elif (INTVAL_SIZE == 8)
+#  define ffi_type_parrot_intval ffi_type_sint64
+#else
+#  error "unhandled INTVAL_SIZE value"
+#endif
+
+#if (NUMVAL_SIZE == 4)
+#  define ffi_type_parrot_numval ffi_type_float
+#elif (NUMVAL_SIZE == 8)
+#  define ffi_type_parrot_numval ffi_type_double
+#else
+#  error "unhandled NUMVAL_SIZE value"
+#endif
 
 static
 size_t
@@ -76,10 +92,6 @@
                 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);
 
@@ -220,6 +232,83 @@
 
 /*
 
+=item C<static ffi_cif *sig_to_cif(PARROT_INTERP, Parrot_NCI_attributes *nci)>
+
+=cut
+
+*/
+
+static void
+sig_to_cif(PARROT_INTERP, ARGMOD(Parrot_NCI_attributes *nci)) {
+    int        i;
+    PMC       *sig   = nci->signature;
+    INTVAL     argc  = VTABLE_elements(interp, sig) - 1;
+    ffi_type  *ret_t = nci_to_ffi_type(interp, VTABLE_get_integer_keyed_int(interp, sig, 0));
+    ffi_type **arg_t = mem_gc_allocate_n_zeroed_typed(interp, argc, ffi_type *);
+    ffi_cif   *cif   = mem_gc_allocate_zeroed_typed(interp, ffi_cif);
+
+    for (i = 0; i < argc; i++) {
+        arg_t[i] = nci_to_ffi_type(interp, VTABLE_get_integer_keyed_int(interp, sig, i + 1));
+    }
+
+    if (ffi_prep_cif(cif, FFI_DEFAULT_ABI, argc, ret_t, arg_t) == FFI_OK) {
+        nci->cif = cif;
+        nci->arg_types = arg_t;
+        return;
+    }
+
+    mem_gc_free(interp, arg_t);
+    mem_gc_free(interp, cif);
+
+    Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_JIT_ERROR, "invalid ffi signature");
+}
+
+
+/*
+
+=item C<static ffi_type * nci_to_ffi_type(PARROT_INTERP, nci_sig_elem_t nci_t)>
+
+=cut
+
+*/
+
+static ffi_type *
+nci_to_ffi_type(PARROT_INTERP, nci_sig_elem_t nci_t) {
+    switch (nci_t) {
+      case enum_nci_sig_void:   return &ffi_type_void;
+      case enum_nci_sig_null:   return &ffi_type_pointer;
+      case enum_nci_sig_interp: return &ffi_type_pointer;
+
+      case enum_nci_sig_float:  return &ffi_type_float;
+      case enum_nci_sig_double: return &ffi_type_double;
+      case enum_nci_sig_numval: return &ffi_type_parrot_numval;
+
+      case enum_nci_sig_char:   return &ffi_type_schar;
+      case enum_nci_sig_short:  return &ffi_type_sshort;
+      case enum_nci_sig_int:    return &ffi_type_sint;
+      case enum_nci_sig_long:   return &ffi_type_slong;
+      case enum_nci_sig_intval: return &ffi_type_parrot_intval;
+
+      case enum_nci_sig_string:
+      case enum_nci_sig_cstring: 
+      case enum_nci_sig_cstringref:
+      case enum_nci_sig_bufref:
+                                return &ffi_type_pointer;
+
+      case enum_nci_sig_ptr:
+      case enum_nci_sig_pmc:
+      case enum_nci_sig_pmcinv:
+      case enum_nci_sig_pmcslurp:
+      case enum_nci_sig_ptrref:
+      case enum_nci_sig_shortref:
+      case enum_nci_sig_intref:
+      case enum_nci_sig_longref:
+                                return &ffi_type_pointer;
+    }
+}
+
+/*
+
 =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)>
 
@@ -661,24 +750,28 @@
     return length;
 }
 
-PARROT_IGNORABLE_RESULT
-static ffi_cif*
-build_libffi_func(PARROT_INTERP, ARGMOD(Parrot_NCI_attributes *nci_info))
+static void
+build_libffi_func(PARROT_INTERP, ARGMOD(Parrot_NCI_attributes *nci))
 {
     ASSERT_ARGS(build_libffi_func)
 
-    STRING * const key      = nci_info->signature;
-    const size_t key_length = Parrot_str_byte_length(interp, key);
+    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);
 
-    INTVAL r = parse_sig(interp, nci_info->signature, key_length, nci_info);
+    /* Arity is length of the signature minus one (the return type). */
+    nci->arity       = VTABLE_elements(interp, nci->signature) - 1;
 
-    return (ffi_cif*)nci_info->cif;
+    sig_to_cif(interp, nci);
 }
 
 pmclass NCI auto_attrs provides invokable {
     /* NCI thunk handling attributes */
     /* NCI thunk handling attributes */
-    ATTR STRING    *signature;              /* The signature. */
+    ATTR PMC       *signature;
+    ATTR STRING    *sig_str;              /* The signature. */
     ATTR void      *func;                   /* Function pointer to call. */
     ATTR void      *orig_func;
     ATTR PMC       *fb_info;                /* Frame-builder info */
@@ -770,7 +863,7 @@
             Parrot_str_free_cstring(key_c);
         }
 
-        nci_info->signature = key;
+        nci_info->sig_str = key;
     }
 
 /*
@@ -787,7 +880,7 @@
             Parrot_NCI_attributes * const nci_info = PARROT_NCI(SELF);
 
             Parrot_gc_mark_PMC_alive(interp, nci_info->fb_info);
-            Parrot_gc_mark_STRING_alive(interp, nci_info->signature);
+            Parrot_gc_mark_STRING_alive(interp, nci_info->sig_str);
             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);
@@ -842,7 +935,7 @@
         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;
@@ -907,7 +1000,8 @@
 
         if (!cif) {
             /* build the thunk only when necessary */
-            cif = build_libffi_func(interp, nci_info);
+            build_libffi_func(interp, nci_info);
+            cif = nci_info->cif;
 
             if (!cif && !func)
                 Parrot_ex_throw_from_c_args(INTERP, NULL,
@@ -971,7 +1065,10 @@
                     "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);
+            {
+                ffi_arg ret;
+                ffi_call(&pcc_cif, FFI_FN(Parrot_pcc_fill_params_from_c_args), &ret, pcc_ptr);
+            }
             
             Parrot_str_free_cstring(tmp_sig);
 
@@ -985,12 +1082,12 @@
             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':
+                switch (VTABLE_get_integer_keyed_int(interp, nci_info->signature, i + 1)) {
+                  case enum_nci_sig_interp:
                     values[i] = &interp;
                     j_offset++;
                     break;
-                  case 't':
+                  case enum_nci_sig_cstring:
                     if (STRING_IS_NULL(*(STRING**)pcc_val[i - j_offset])) {
                         translation_pointers[i] = (char*) NULL;
                     }
@@ -999,7 +1096,7 @@
                     }
                     values[i] = &translation_pointers[i];
                     break;
-                  case 'B':
+                  case enum_nci_sig_bufref:
                     if (STRING_IS_NULL(*(STRING**)pcc_val[i - j_offset])) {
                         translation_pointers[i] = (char*) NULL;
                     }
@@ -1009,56 +1106,51 @@
                     middle_man[i] = &translation_pointers[i];
                     values[i] = &middle_man[i];
                     break;
-                  case 'b':
+                  case enum_nci_sig_cstringref:
                     values[i] = &Buffer_bufstart(*(STRING**)pcc_val[i - j_offset]);
                     break;
-                  case 'c':
+                  case enum_nci_sig_char:
                     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':
+                  case enum_nci_sig_shortref:
                     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':
+                  case enum_nci_sig_short:
                     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':
+                  case enum_nci_sig_intref:
                     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':
+                  case enum_nci_sig_int:
                     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':
+                  case enum_nci_sig_longref:
                     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':
+                  case enum_nci_sig_long:
                     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':
+                  case enum_nci_sig_ptrref:
                     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*);
@@ -1066,26 +1158,25 @@
                                 (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':
+                  case enum_nci_sig_pmc:
                     translation_pointers[i] = *(PMC**)pcc_val[i - j_offset];
                     values[i] = &translation_pointers[i];
                     break;
-                  case 'p':
+                  case enum_nci_sig_ptr:
                     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':
+                  case enum_nci_sig_float:
                     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':
+                  case enum_nci_sig_double:
                     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;
                 }
@@ -1122,8 +1213,8 @@
             char *s;
             PMC *ret_object;
             s = Parrot_str_to_cstring(interp, nci_info->pcc_return_signature);
-            switch (*(char*)nci_info->return_translation) {
-              case 'p':
+            switch (VTABLE_get_integer_keyed_int(interp, nci_info->signature, 0)) {
+              case enum_nci_sig_ptr:
                 {
                     PMC *final_destination = PMCNULL;
 
@@ -1136,7 +1227,7 @@
                                                                     s, final_destination);
                 }
                 break;
-              case 't':
+              case enum_nci_sig_cstring:
                 {
                     STRING *final_destination = Parrot_str_new(interp, *(char**)return_data, 0);
                     ret_object = Parrot_pcc_build_call_from_c_args(interp,
@@ -1144,7 +1235,7 @@
                                                                    s, final_destination);
                 }
                 break;
-              case 'f':
+              case enum_nci_sig_float:
                 {
                     FLOATVAL final_destination = *(float*)return_data;
 
@@ -1180,18 +1271,18 @@
          * 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':
+            switch (VTABLE_get_integer_keyed_int(interp, nci_info->signature, i + 1)) {
+              case enum_nci_sig_bufref:
                 if (translation_pointers[i]) {
                     Parrot_str_free_cstring((char*)translation_pointers[i]);
                 }
                 break;
-              case (INTVAL)'t':
+              case enum_nci_sig_cstring:
                 if (translation_pointers[i]) {
                     Parrot_str_free_cstring((char*)translation_pointers[i]);
                 }
                 break;
-              case (INTVAL)'2':
+              case enum_nci_sig_shortref:
                 VTABLE_set_integer_native(interp, 
                             ((pmc_holder_t*)translation_pointers[i])->p, 
                             (INTVAL)*(short*)((pmc_holder_t*)translation_pointers[i])->ival);
@@ -1199,7 +1290,7 @@
                     mem_sys_free(translation_pointers[i]);
                 }
                 break;
-              case (INTVAL)'3':
+              case enum_nci_sig_intref:
                 VTABLE_set_integer_native(interp, 
                             ((pmc_holder_t*)translation_pointers[i])->p,
                             (INTVAL)*(int*)((pmc_holder_t*)translation_pointers[i])->ival);
@@ -1207,7 +1298,7 @@
                     mem_sys_free(translation_pointers[i]);
                 }
                 break;
-              case (INTVAL)'4':
+              case enum_nci_sig_longref:
                 VTABLE_set_integer_native(interp,
                             ((pmc_holder_t*)translation_pointers[i])->p,
                             (INTVAL)*(long*)((pmc_holder_t*)translation_pointers[i])->ival);
@@ -1215,7 +1306,7 @@
                     mem_sys_free(translation_pointers[i]);
                 }
                 break;
-              case (INTVAL)'V':
+              case enum_nci_sig_ptrref:
                 VTABLE_set_pointer(interp, 
                             ((pmc_holder_t*)translation_pointers[i])->p, 
                             (PMC*)*((pmc_holder_t*)translation_pointers[i])->pval);
@@ -1223,12 +1314,11 @@
                     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':
+              case enum_nci_sig_double:
+              case enum_nci_sig_char:
+              case enum_nci_sig_short:
+              case enum_nci_sig_int:
+              case enum_nci_sig_long:
                 if (translation_pointers[i]) {
                     mem_sys_free(translation_pointers[i]);
                 }
@@ -1311,7 +1401,7 @@
 
         if (nci_info) {
             if (!nci_info->cif) {
-                nci_info->cif = build_libffi_func(interp, nci_info);
+                build_libffi_func(interp, nci_info);
             }
             if (nci_info->cif) {
                 arity = nci_info->arity;


More information about the parrot-commits mailing list