Ticket #1105: pre_merge.patch
File pre_merge.patch, 29.6 KB (added by plobsing, 12 years ago) |
---|
-
DEPRECATED.pod
diff --git a/DEPRECATED.pod b/DEPRECATED.pod index 76a372a..92eedb5 100644
a b 74 74 75 75 L<https://trac.parrot.org/parrot/ticket/918> 76 76 77 =item Use of 'v' in NCI parameter lists [eligible in 2.1] 78 79 An empty parameter list suffices to indicate no parameters to an NCI call. 80 This has been marked as deprecated in PDD16 for 2 years. 81 82 F<pdds/draft/pdd16_native_call.pod> 83 77 84 =back 78 85 79 86 =head1 Opcodes -
config/gen/parrot_include.pm
diff --git a/config/gen/parrot_include.pm b/config/gen/parrot_include.pm index 58dcb5d..b89d14b 100644
a b 39 39 include/parrot/library.h 40 40 include/parrot/longopt.h 41 41 include/parrot/multidispatch.h 42 include/parrot/nci.h 42 43 include/parrot/packfile.h 43 44 include/parrot/stat.h 44 45 include/parrot/string.h 45 46 include/parrot/pmc.h 46 47 include/parrot/warnings.h 47 48 include/parrot/gc_api.h 48 src/pmc/timer.pmc49 49 src/utils.c 50 50 ) ]; 51 51 $data{generated_files} = [ qw( -
include/parrot/nci.h
diff --git a/include/parrot/nci.h b/include/parrot/nci.h index 1ff85c4..86ad460 100644
a b 15 15 16 16 #include "parrot/parrot.h" 17 17 18 /* NCI PMC interface constants */ 19 /* &gen_from_enum(nci.pasm) */ 20 typedef enum { 21 PARROT_NCI_ARITY, 22 PARROT_NCI_PCC_SIGNATURE_PARAMS, 23 PARROT_NCI_PCC_SIGNATURE_RET, 24 PARROT_NCI_LONG_SIGNATURE, 25 PARROT_NCI_MULTI_SIG, 26 } parrot_nci_enum_t; 27 /* &end_gen */ 28 18 29 void *build_call_func(PARROT_INTERP, SHIM(PMC *pmc_nci), NOTNULL(STRING *signature), NOTNULL(int *jitted)); 19 30 20 31 #endif /* PARROT_NCI_H_GUARD */ -
(a) /dev/null vs. (b) b/lib/Parrot/NativeCall.pm
diff --git a/lib/Parrot/NativeCall.pm b/lib/Parrot/NativeCall.pm new file mode 100644 index 0000000..d0145f8
a b 1 # Copyright (C) 2009, Parrot Foundation. 2 # $Id$ 3 4 package Parrot::NativeCall; 5 6 use strict; 7 use warnings; 8 9 use base 'Exporter'; 10 our @EXPORT_OK = qw{ signature_nci_to_pcc }; 11 12 =head1 NAME 13 14 Parrot::NativeCall - Tools for building native call routines 15 16 =head1 SYNOPSIS 17 18 use Parrot::NativeCall 'signature_nci_to_pcc'; 19 20 my $pcc_sig = signature_nci_to_pcc("v VVV"); 21 22 =head1 DESCRIPTION 23 24 C<Parrot::NativeCall> knows how to map NCI signatures to nci frame 25 functions. 26 27 =head1 GLOBAL VARIABLES 28 29 =over 30 31 =item C<%signature_table> 32 33 Maps NCI signature items to elements of a native call routine. 34 35 For use by F<tools/build/nativecall.pl>. New code should probably write 36 a wrapper in this module to encapsulate the access. 37 38 =cut 39 40 our %signature_table = ( 41 p => { 42 as_proto => "void *", 43 other_decl => "PMC * const final_destination = pmc_new(interp, enum_class_UnManagedStruct);", 44 sig_char => "P", 45 ret_assign => "VTABLE_set_pointer(interp, final_destination, return_data);\n Parrot_pcc_fill_returns_from_c_args(interp, call_object, \"P\", final_destination);", 46 }, 47 i => { as_proto => "int", sig_char => "I" }, 48 l => { as_proto => "long", sig_char => "I" }, 49 c => { as_proto => "char", sig_char => "I" }, 50 s => { as_proto => "short", sig_char => "I" }, 51 f => { as_proto => "float", sig_char => "N" }, 52 d => { as_proto => "double", sig_char => "N" }, 53 t => { as_proto => "char *", 54 other_decl => "STRING *final_destination;", 55 ret_assign => "final_destination = Parrot_str_new(interp, return_data, 0);\n Parrot_pcc_fill_returns_from_c_args(interp, call_object, \"S\", final_destination);", 56 sig_char => "S" }, 57 v => { as_proto => "void", 58 return_type => "void *", 59 sig_char => "v", 60 ret_assign => "", 61 func_call_assign => "" 62 }, 63 P => { as_proto => "PMC *", sig_char => "P" }, 64 O => { as_proto => "PMC *", returns => "", sig_char => "Pi" }, 65 J => { as_proto => "PARROT_INTERP", returns => "", sig_char => "" }, 66 S => { as_proto => "STRING *", sig_char => "S" }, 67 I => { as_proto => "INTVAL", sig_char => "I" }, 68 N => { as_proto => "FLOATVAL", sig_char => "N" }, 69 b => { as_proto => "void *", as_return => "", sig_char => "S" }, 70 B => { as_proto => "char **", as_return => "", sig_char => "S" }, 71 # These should be replaced by modifiers in the future 72 2 => { as_proto => "short *", sig_char => "P", return_type => "short", 73 ret_assign => 'Parrot_pcc_fill_returns_from_c_args(interp, call_object, "I", return_data);' }, 74 3 => { as_proto => "int *", sig_char => "P", return_type => "int", 75 ret_assign => 'Parrot_pcc_fill_returns_from_c_args(interp, call_object, "I", return_data);' }, 76 4 => { as_proto => "long *", sig_char => "P", return_type => "long", 77 ret_assign => 'Parrot_pcc_fill_returns_from_c_args(interp, call_object, "I", return_data);' }, 78 L => { as_proto => "long *", as_return => "" }, 79 T => { as_proto => "char **", as_return => "" }, 80 V => { as_proto => "void **", as_return => "", sig_char => "P" }, 81 '@' => { as_proto => "PMC *", as_return => "", cname => "xAT_", sig_char => 'Ps' }, 82 ); 83 84 for (values %signature_table) { 85 if (not exists $_->{as_return}) { $_->{as_return} = $_->{as_proto} } 86 if (not exists $_->{return_type}) { $_->{return_type} = $_->{as_proto} } 87 if (not exists $_->{return_type_decl}) { $_->{return_type_decl} = $_->{return_type} } 88 if (not exists $_->{ret_assign} and exists $_->{sig_char}) { 89 $_->{ret_assign} = 'Parrot_pcc_fill_returns_from_c_args(interp, call_object, "' 90 . $_->{sig_char} . '", return_data);'; 91 } 92 if (not exists $_->{func_call_assign}) { 93 $_->{func_call_assign} = "return_data = " 94 } 95 } 96 97 =back 98 99 =head1 FUNCTIONS 100 101 =over 102 103 =item C<signature_nci_to_pcc> 104 105 Converts an NCI signature to a PCC signature. 106 107 =cut 108 109 sub signature_nci_to_pcc { 110 my $nci_sig = shift; 111 my ($nci_ret, $nci_params) = $nci_sig =~ /^(.)\s*(\S*)/; 112 my $pcc_ret = $signature_table{$nci_ret}{sig_char}; 113 my $pcc_params = join '', map $signature_table{$_}{sig_char}, split //, $nci_params; 114 return "${pcc_params}->${pcc_ret}"; 115 } 116 117 1; 118 119 =back 120 121 =cut 122 123 # Local Variables: 124 # mode: cperl 125 # cperl-indent-level: 4 126 # fill-column: 100 127 # End: 128 # vim: expandtab shiftwidth=4: -
src/extend.c
diff --git a/src/extend.c b/src/extend.c index 7d13cc7..5d247bd 100644
a b 1747 1747 (char *) NULL, 0); 1748 1748 Parrot_PMC sub = pmc_new(interp, enum_class_NCI); 1749 1749 VTABLE_set_pointer_keyed_str(interp, sub, sig, F2DPTR(func)); 1750 PObj_get_FLAGS(sub) |= PObj_private1_FLAG;1751 1750 return sub; 1752 1751 } 1753 1752 -
src/ops/core.ops
diff --git a/src/ops/core.ops b/src/ops/core.ops index 0b78166..eae4b8d 100644
a b 1322 1322 else { 1323 1323 $1 = pmc_new(interp, enum_class_NCI); 1324 1324 VTABLE_set_pointer_keyed_str(interp, $1, $4, F2DPTR(p)); 1325 PObj_get_FLAGS($1) |= PObj_private1_FLAG;1326 1325 } 1327 1326 Parrot_str_free_cstring(name); 1328 1327 } -
src/pmc/nci.pmc
diff --git a/src/pmc/nci.pmc b/src/pmc/nci.pmc index ef5c5e4..9da11e8 100644
a b 18 18 19 19 */ 20 20 21 #include "parrot/nci.h" 22 21 23 typedef INTVAL (*nci_sub_t)(PARROT_INTERP, PMC *); 22 typedef INTVAL (*nci_jit_sub_t)(PARROT_INTERP, PMC *, char *); 23 24 void pcc_params(PARROT_INTERP, STRING *sig, Parrot_NCI_attributes * const nci_info, 25 size_t sig_length); 26 void pcc_params(PARROT_INTERP, STRING *sig, Parrot_NCI_attributes * const nci_info, 27 size_t sig_length) { 28 char param_buf[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; 29 char *param_sig = sig_length <= 7 30 ? param_buf 31 : mem_allocate_n_typed(sig_length, char); 32 size_t j = 0; 33 size_t i; 34 35 for (i = 1; i < sig_length; i++) { 36 INTVAL c = Parrot_str_indexed(interp, sig, i); 24 typedef nci_sub_t nci_jit_sub_t; 37 25 38 switch (c) { 39 case (INTVAL)'0': /* null ptr or such - doesn't consume a reg */ 40 break; 41 case (INTVAL)'f': 42 case (INTVAL)'N': 43 case (INTVAL)'d': 44 param_sig[j++] = 'N'; 45 break; 46 case (INTVAL)'I': /* INTVAL */ 47 case (INTVAL)'l': /* long */ 48 case (INTVAL)'i': /* int */ 49 case (INTVAL)'s': /* short */ 50 case (INTVAL)'c': /* char */ 51 param_sig[j++] = 'I'; 52 break; 53 case (INTVAL)'S': 54 case (INTVAL)'t': /* string, pass a cstring */ 55 param_sig[j++] = 'S'; 56 break; 57 case (INTVAL)'J': /* interpreter */ 58 break; 59 case (INTVAL)'p': /* push pmc->data */ 60 case (INTVAL)'O': /* push PMC * object in P2 */ 61 case (INTVAL)'P': /* push PMC * */ 62 case (INTVAL)'V': /* push PMC * */ 63 param_sig[j++] = 'P'; 64 case (INTVAL)'v': 65 break; 66 /* I have no idea how to handle these */ 67 case (INTVAL)'2': 68 case (INTVAL)'3': 69 case (INTVAL)'4': 70 param_sig[j++] = 'I'; 71 break; 72 case (INTVAL)'@': 73 param_sig[j++] = '@'; 74 break; 75 case (INTVAL)'b': /* buffer (void*) pass Buffer_bufstart(SReg) */ 76 case (INTVAL)'B': /* buffer (void**) pass &Buffer_bufstart(SReg) */ 77 param_sig[j++] = 'S'; 78 break; 79 default: 80 if (sig_length > 7) 81 mem_sys_free(param_sig); 82 Parrot_ex_throw_from_c_args(interp, NULL, 26 #define NCI_raw_FLAG PObj_private0_FLAG 27 28 STRING *pcc_sig_params(PARROT_INTERP, STRING *sig); 29 STRING *pcc_sig_params(PARROT_INTERP, STRING *sig) { 30 size_t sig_len = Parrot_str_byte_length(interp, sig); 31 char param_buf[sig_len*2]; 32 33 size_t i, j; 34 35 for (i = 1, j = 0; i < sig_len; i++) { 36 INTVAL c = Parrot_str_indexed(interp, sig, i); 37 if (c > 127) { 38 Parrot_ex_throw_from_c_args(interp, NULL, 83 39 EXCEPTION_JIT_ERROR, 84 "Unknown param Signature %c\n", (char)c); 85 break; 40 "Unknown param type at %d in signature '%S' (way too big)\n", i, sig); 41 } 42 else { 43 switch ((char)c) { 44 case 'v': 45 case '0': 46 case 'J': 47 break; 48 case 'N': 49 case 'd': 50 case 'f': 51 param_buf[j++] = 'N'; 52 break; 53 case 'I': 54 case 'l': 55 case 'i': 56 case 's': 57 case 'c': 58 param_buf[j++] = 'I'; 59 break; 60 case 'S': 61 case 't': 62 case 'b': 63 case 'B': 64 param_buf[j++] = 'S'; 65 break; 66 case 'P': 67 case 'p': 68 case 'V': 69 case '2': 70 case '3': 71 case '4': 72 param_buf[j++] = 'P'; 73 break; 74 case 'O': 75 param_buf[j++] = 'P'; 76 param_buf[j++] = 'i'; 77 break; 78 case '@': 79 param_buf[j++] = 'P'; 80 param_buf[j++] = 's'; 81 break; 82 default: 83 Parrot_ex_throw_from_c_args(interp, NULL, 84 EXCEPTION_JIT_ERROR, 85 "Unknown param type at %d in signature '%S'\n", i, sig); 86 } 86 87 } 87 88 } 88 89 89 PARROT_ASSERT(j <= sig_length); 90 return string_make(interp, param_buf, j, NULL, PObj_constant_FLAG); 91 } 90 92 91 /* use only the signature-significant part of the string buffer */ 92 if (j) { 93 nci_info->pcc_params_signature = string_make(interp, param_sig, j, 94 NULL, PObj_constant_FLAG); 93 STRING *pcc_sig_ret(PARROT_INTERP, STRING *sig); 94 STRING *pcc_sig_ret(PARROT_INTERP, STRING *sig) { 95 INTVAL c = Parrot_str_indexed(interp, sig, 0); 96 if (c > 127) { 97 Parrot_ex_throw_from_c_args(interp, NULL, 98 EXCEPTION_JIT_ERROR, 99 "Unknown return type at %d in signature '%S' (way too big)\n", 0, sig); 100 } 101 else { 102 switch ((char)c) { 103 case 'v': 104 return CONST_STRING(interp, "v"); 105 case 'N': 106 case 'f': 107 case 'd': 108 return CONST_STRING(interp, "N"); 109 case 'I': 110 case 'l': 111 case 'i': 112 case 's': 113 case 'c': 114 return CONST_STRING(interp, "I"); 115 case 'S': 116 case 't': 117 return CONST_STRING(interp, "S"); 118 case 'p': 119 case 'P': 120 return CONST_STRING(interp, "P"); 121 case '2': 122 case '3': 123 case '4': 124 return CONST_STRING(interp, "P"); 125 default: 126 Parrot_ex_throw_from_c_args(interp, NULL, 127 EXCEPTION_JIT_ERROR, 128 "Unknown return type at %d in signature '%S'\n", 0, sig); 129 } 95 130 } 96 else97 nci_info->pcc_params_signature = CONST_STRING(interp, "");98 99 if (sig_length > 7)100 mem_sys_free(param_sig);101 131 } 102 132 103 133 /* actually build the NCI thunk */ … … 106 136 static 107 137 nci_sub_t build_func(PARROT_INTERP, PMC *pmc, Parrot_NCI_attributes *nci_info) 108 138 { 109 STRING *key = nci_info->signature; 110 size_t key_length = Parrot_str_byte_length(interp, key); 139 STRING *key = nci_info->nci_signature; 111 140 int jitted = 0; 112 141 113 pcc_params(interp, key, nci_info, key_length);114 115 /* Arity is length of that string minus one (the return type). */116 nci_info->arity = key_length - 1;117 118 142 /* Build call function. */ 119 143 nci_info->func = (PMC *)(build_call_func(interp, pmc, key, &jitted)); 120 nci_info->jitted = jitted;121 144 122 145 return (nci_sub_t)nci_info->func; 123 146 } 124 147 125 148 126 149 pmclass NCI auto_attrs { 127 ATTR STRING *signature; /* The signature. */ 128 ATTR void *func; /* Function pointer to call. */ 129 ATTR void *orig_func; /* Function pointer 130 * used to create func */ 131 ATTR STRING *pcc_params_signature; /* The signature. */ 132 ATTR STRING *long_signature; /* The full signature. */ 133 ATTR PMC *multi_sig; /* type tuple array (?) */ 134 ATTR INTVAL arity; /* Cached arity of the NCI. */ 135 ATTR INTVAL jitted; /* Is this a jitted NCI stub. */ 150 /* Signature Attributes */ 151 ATTR STRING *nci_signature; /* The NCI signature */ 152 ATTR STRING *pcc_signature_ret; /* The PCC return signature */ 153 ATTR STRING *pcc_signature_param; /* The PCC param signature */ 154 155 /* Function Pointers */ 156 ATTR void *func; /* Function pointer to call */ 157 ATTR void *orig_func; /* Function pointer being wrapped */ 158 159 /* Sub PMC Attributes */ 160 ATTR INTVAL arity; /* Number of params taken */ 161 /* MMD Attributes */ 162 ATTR PMC *multi_sig; 163 ATTR STRING *long_signature; 136 164 137 165 /* 138 166 … … 147 175 METHOD get_multisig() { 148 176 PMC *sig; 149 177 GET_ATTR_multi_sig(INTERP, SELF, sig); 150 if ( PMC_IS_NULL(sig))178 if (sig == NULL) { 151 179 sig = PMCNULL; 180 } 152 181 RETURN(PMC *sig); 153 182 } 154 183 … … 178 207 179 208 VTABLE void init() { 180 209 /* Mark that we're not a raw NCI. */ 181 PObj_flag_CLEAR(private2, SELF); 210 PObj_get_FLAGS(SELF) &= ~NCI_raw_FLAG; 211 /* Mark that we have a custom gc marker */ 182 212 PObj_custom_mark_SET(SELF); 183 213 } 184 214 185 215 /* 186 216 187 =item C<void set_pointer_keyed_str(STRING *key, void *func)>217 =item C<void *get_pointer()> 188 218 189 Sets the specified function pointer and signature (C<*key>). 219 =item C<void set_pointer(void *ptr)> 220 221 Get/Set the pointer being wrapped. Setting through this interface sets 222 the raw flag. 190 223 191 224 =cut 192 225 … … 194 227 195 228 VTABLE void set_pointer(void *ptr) { 196 229 SET_ATTR_orig_func(INTERP, SELF, ptr); 197 PObj_ flag_SET(private2, SELF);230 PObj_get_FLAGS(SELF) |= NCI_raw_FLAG; 198 231 } 199 232 200 233 VTABLE void *get_pointer() { 201 234 return PARROT_NCI(SELF)->orig_func; 202 235 } 203 236 237 /* 238 239 =item C<void set_pointer_keyed_str(STRING *key, void *func)> 240 241 Roughly equivalent to C<set_string(key)> and C<set_pointer(func)>. 242 Setting through this interface clears the raw flag. 243 244 =cut 245 246 */ 247 204 248 VTABLE void set_pointer_keyed_str(STRING *key, void *func) { 205 Parrot_NCI_attributes * const nci_info = PARROT_NCI(SELF); 206 207 /* Store the original function and signature. */ 208 SET_ATTR_orig_func(INTERP, SELF, func); 209 210 /* ensure that the STRING signature is constant */ 211 if (!PObj_constant_TEST(key)) { 212 char * const key_c = Parrot_str_to_cstring(INTERP, key); 213 size_t key_length = Parrot_str_byte_length(interp, key); 214 key = string_make(interp, key_c, key_length, 215 NULL, PObj_constant_FLAG); 216 Parrot_str_free_cstring(key_c); 249 SELF.set_string_native(key); 250 SELF.set_pointer(func); 251 PObj_get_FLAGS(SELF) &= ~NCI_raw_FLAG; 252 } 253 254 /* 255 256 =item C<STRING *get_string()> 257 258 =item C<void set_string(STRING *str)> 259 260 Get/Set the NCI signature. 261 262 =cut 263 264 */ 265 266 VTABLE STRING *get_string() { 267 return PARROT_NCI(SELF)->nci_signature; 268 } 269 270 VTABLE void set_string_native(STRING *str) { 271 if (!PObj_constant_TEST(str)) { 272 str = Parrot_str_copy(INTERP, str); 217 273 } 274 SET_ATTR_nci_signature(INTERP, SELF, str); 218 275 219 nci_info->signature = key; 276 /* set up derivative attributes */ 277 SET_ATTR_pcc_signature_param(INTERP, SELF, pcc_sig_params(INTERP, str)); 278 SET_ATTR_pcc_signature_ret(INTERP, SELF, pcc_sig_ret(INTERP, str)); 279 /* Arity is length of the NCI signature minus one (the return type). */ 280 SET_ATTR_arity(INTERP, SELF, Parrot_str_byte_length(INTERP, str) - 1); 220 281 } 221 282 222 283 /* … … 232 293 if (PARROT_NCI(SELF)) { 233 294 Parrot_NCI_attributes * const nci_info = PARROT_NCI(SELF); 234 295 235 Parrot_gc_mark_STRING_alive(interp, nci_info->signature); 236 Parrot_gc_mark_STRING_alive(interp, nci_info->pcc_params_signature); 296 Parrot_gc_mark_STRING_alive(interp, nci_info->nci_signature); 297 Parrot_gc_mark_STRING_alive(interp, nci_info->pcc_signature_param); 298 Parrot_gc_mark_STRING_alive(interp, nci_info->pcc_signature_ret); 237 299 Parrot_gc_mark_STRING_alive(interp, nci_info->long_signature); 238 300 Parrot_gc_mark_PMC_alive(interp, nci_info->multi_sig); 239 301 } … … 262 324 * ManagedStruct or Buffer? 263 325 */ 264 326 nci_info_ret->func = nci_info_self->func; 265 nci_info_ret->orig_func = nci_info_self->orig_func; 266 nci_info_ret->signature = nci_info_self->signature; 267 nci_info_ret->pcc_params_signature = nci_info_self->pcc_params_signature; 327 nci_info_ret->orig_func = nci_info_self->orig_func; 328 nci_info_ret->nci_signature = nci_info_self->nci_signature; 329 nci_info_ret->pcc_signature_param = nci_info_self->pcc_signature_param; 330 nci_info_ret->pcc_signature_ret = nci_info_self->pcc_signature_ret; 331 nci_info_ret->long_signature = nci_info_self->long_signature; 332 nci_info_ret->multi_sig = nci_info_self->multi_sig; 268 333 nci_info_ret->arity = nci_info_self->arity; 269 nci_info_ret->jitted = nci_info_self->jitted;270 334 PObj_get_FLAGS(ret) |= (PObj_get_FLAGS(SELF) & 0x7); 271 335 272 336 return ret; … … 306 370 PMC *cont; 307 371 308 372 GET_ATTR_orig_func(INTERP, SELF, orig_func); 309 func = PObj_ flag_TEST(private2, SELF)373 func = PObj_get_FLAGS(SELF) & NCI_raw_FLAG 310 374 ? (nci_sub_t) D2FPTR(orig_func) 311 375 : (nci_sub_t) D2FPTR(nci_info->func); 312 376 … … 320 384 "attempt to call NULL function"); 321 385 } 322 386 323 if (nci_info->jitted) { 324 nci_jit_sub_t jit_func = (nci_jit_sub_t) D2FPTR(nci_info->func); 387 func(INTERP, SELF); 325 388 326 /* Parrot_eprintf(interp, "JITTED %S\n", nci_info->signature); */327 sig_str = Parrot_str_to_cstring(interp, nci_info->pcc_params_signature);328 jit_func(INTERP, SELF, sig_str);329 Parrot_str_free_cstring(sig_str);330 }331 else {332 if (PObj_flag_TEST(private2, SELF)) {333 /* Parrot_eprintf(interp, "RAW NCI CALL\n"); */334 }335 else {336 /* Parrot_eprintf(interp, "HACKED %S\n", nci_info->signature); */337 }338 func(INTERP, SELF);339 }340 389 cont = INTERP->current_cont; 341 390 342 391 /* … … 397 446 398 447 */ 399 448 METHOD arity() { 400 Parrot_NCI_attributes * const nci_info = PARROT_NCI(SELF); 401 INTVAL arity = 0; 402 403 if (nci_info) { 404 if (!nci_info->func) 405 build_func(INTERP, SELF, nci_info); 406 if (nci_info->func) { 407 arity = nci_info->arity; 408 RETURN(INTVAL arity); 409 } 449 INTVAL arity; 450 GET_ATTR_arity(INTERP, SELF, arity); 451 RETURN(INTVAL arity); 452 } 453 454 /* 455 456 =item C<INTVAL get_integer_keyed_int(INTVAL key)> 457 458 =item C<STRING *get_string_keyed_int(INTVAL key)> 459 460 =item C<PMC *get_pmc_keyed_int(INTVAL key)> 461 462 Accessors for all attributes of this class not otherwise accessible through VTABLES. 463 Integers are used for keys to make access easier for JIT. These are also available to 464 PIR from F<runtime/parrot/include/nci.pasm> 465 466 =over 467 468 =item INTVAL keys 469 470 C<PARROT_NCI_ARITY> 471 472 =item STRING keys 473 474 C<PARROT_NCI_PCC_SIGNATURE_PARAMS>, C<PARROT_NCI_PCC_SIGNATURE_RET>, 475 C<PARROT_LONG_SIGNATURE> 476 477 =item PMC keys 478 479 C<PARROT_NCI_MULTI_SIG> 480 481 =back 482 483 =cut 484 485 */ 486 487 VTABLE INTVAL get_integer_keyed_int(INTVAL key) { 488 switch (key) { 489 case PARROT_NCI_ARITY: 490 return PARROT_NCI(SELF)->arity; 491 default: 492 Parrot_ex_throw_from_c_args(INTERP, NULL, 493 EXCEPTION_INVALID_OPERATION, 494 "Bad index for NCI.get_integer_keyed_int()"); 495 } 496 } 497 498 VTABLE STRING *get_string_keyed_int(INTVAL key) { 499 switch (key) { 500 case PARROT_NCI_PCC_SIGNATURE_PARAMS: 501 return PARROT_NCI(SELF)->pcc_signature_param; 502 case PARROT_NCI_PCC_SIGNATURE_RET: 503 return PARROT_NCI(SELF)->pcc_signature_ret; 504 case PARROT_NCI_LONG_SIGNATURE: 505 return PARROT_NCI(SELF)->long_signature; 506 default: 507 Parrot_ex_throw_from_c_args(INTERP, NULL, 508 EXCEPTION_INVALID_OPERATION, 509 "Bad index for NCI.get_string_keyed_int()"); 410 510 } 511 } 411 512 412 Parrot_ex_throw_from_c_args(INTERP, NULL, 413 EXCEPTION_INVALID_OPERATION, 414 "You cannot get the arity of an undefined NCI."); 513 VTABLE PMC *get_pmc_keyed_int(INTVAL key) { 514 PMC *retval; 515 switch (key) { 516 case PARROT_NCI_MULTI_SIG: 517 GET_ATTR_multi_sig(INTERP, SELF, retval); 518 default: 519 Parrot_ex_throw_from_c_args(INTERP, NULL, 520 EXCEPTION_INVALID_OPERATION, 521 "Bad index for NCI.get_pmc_keyed_int()"); 522 } 523 if (retval == NULL) { 524 retval = PMCNULL; 525 } 526 return retval; 415 527 } 416 528 } 417 529 -
t/pmc/nci.t
diff --git a/t/pmc/nci.t b/t/pmc/nci.t index 735f152..fbfca27 100644
a b 5 5 use strict; 6 6 use warnings; 7 7 use lib qw( . lib ../lib ../../lib ); 8 use Parrot::BuildUtil; 9 use Parrot::NativeCall 'signature_nci_to_pcc'; 10 11 my @nci_sigs; 12 BEGIN { 13 @nci_sigs = 14 grep {$_} 15 map {chomp; s/^\s*//; s/\s*$//; s/#.*$//; $_} 16 split /\n/, Parrot::BuildUtil::slurp_file('src/call_list.txt'); 17 } 18 8 19 use Test::More; 9 use Parrot::Test tests => 70;20 use Parrot::Test tests => (70 + @nci_sigs); 10 21 use Parrot::Config qw(%PConfig); 11 22 12 23 =head1 NAME … … 32 43 33 44 $ENV{TEST_PROG_ARGS} ||= ''; 34 45 46 foreach my $nci_sig (@nci_sigs) { 47 my ($nci_ret, $nci_params) = $nci_sig =~ /\S+/g; 48 $nci_params ||= ''; 49 my $pcc_sig = signature_nci_to_pcc($nci_sig); 50 pir_output_is( << "CODE", "$pcc_sig\n", "NCI PMC signatures equivalent to nativecall.pl ('$nci_sig')" ); 51 .include "nci.pasm" 52 .sub test :main 53 .local pmc nci 54 nci = new ['NCI'] 55 nci = "${nci_ret}${nci_params}" 56 .local string s 57 s = nci[ .PARROT_NCI_PCC_SIGNATURE_PARAMS ] 58 print s 59 print "->" 60 s = nci[ .PARROT_NCI_PCC_SIGNATURE_RET ] 61 print s 62 print "\\n" 63 .end 64 CODE 65 } 66 35 67 SKIP: { 36 68 unless ( -e "runtime/parrot/dynext/libnci_test$PConfig{load_ext}" ) { 37 69 skip( "Please make libnci_test$PConfig{load_ext}", Test::Builder->expected_tests() ); -
tools/build/nativecall.pl
diff --git a/tools/build/nativecall.pl b/tools/build/nativecall.pl index 9edd1a0..06341a6 100644
a b 30 30 use strict; 31 31 use warnings; 32 32 33 use lib 'lib'; 34 use Parrot::NativeCall; 35 33 36 my $opt_warndups = 0; 34 37 35 38 # This file will eventually be compiled … … 37 40 38 41 print_head( \@ARGV ); 39 42 40 41 my %sig_table = ( 42 p => { 43 as_proto => "void *", 44 other_decl => "PMC * const final_destination = pmc_new(interp, enum_class_UnManagedStruct);", 45 sig_char => "P", 46 ret_assign => "VTABLE_set_pointer(interp, final_destination, return_data);\n Parrot_pcc_fill_returns_from_c_args(interp, call_object, \"P\", final_destination);", 47 }, 48 i => { as_proto => "int", sig_char => "I" }, 49 l => { as_proto => "long", sig_char => "I" }, 50 c => { as_proto => "char", sig_char => "I" }, 51 s => { as_proto => "short", sig_char => "I" }, 52 f => { as_proto => "float", sig_char => "N" }, 53 d => { as_proto => "double", sig_char => "N" }, 54 t => { as_proto => "char *", 55 other_decl => "STRING *final_destination;", 56 ret_assign => "final_destination = Parrot_str_new(interp, return_data, 0);\n Parrot_pcc_fill_returns_from_c_args(interp, call_object, \"S\", final_destination);", 57 sig_char => "S" }, 58 v => { as_proto => "void", 59 return_type => "void *", 60 sig_char => "v", 61 ret_assign => "", 62 func_call_assign => "" 63 }, 64 P => { as_proto => "PMC *", sig_char => "P" }, 65 O => { as_proto => "PMC *", returns => "", sig_char => "Pi" }, 66 J => { as_proto => "PARROT_INTERP", returns => "", sig_char => "" }, 67 S => { as_proto => "STRING *", sig_char => "S" }, 68 I => { as_proto => "INTVAL", sig_char => "I" }, 69 N => { as_proto => "FLOATVAL", sig_char => "N" }, 70 b => { as_proto => "void *", as_return => "", sig_char => "S" }, 71 B => { as_proto => "char **", as_return => "", sig_char => "S" }, 72 # These should be replaced by modifiers in the future 73 2 => { as_proto => "short *", sig_char => "P", return_type => "short", 74 ret_assign => 'Parrot_pcc_fill_returns_from_c_args(interp, call_object, "I", return_data);' }, 75 3 => { as_proto => "int *", sig_char => "P", return_type => "int", 76 ret_assign => 'Parrot_pcc_fill_returns_from_c_args(interp, call_object, "I", return_data);' }, 77 4 => { as_proto => "long *", sig_char => "P", return_type => "long", 78 ret_assign => 'Parrot_pcc_fill_returns_from_c_args(interp, call_object, "I", return_data);' }, 79 L => { as_proto => "long *", as_return => "" }, 80 T => { as_proto => "char **", as_return => "" }, 81 V => { as_proto => "void **", as_return => "", sig_char => "P" }, 82 '@' => { as_proto => "PMC *", as_return => "", cname => "xAT_", sig_char => 'Ps' }, 83 ); 84 85 for (values %sig_table) { 86 if (not exists $_->{as_return}) { $_->{as_return} = $_->{as_proto} } 87 if (not exists $_->{return_type}) { $_->{return_type} = $_->{as_proto} } 88 if (not exists $_->{return_type_decl}) { $_->{return_type_decl} = $_->{return_type} } 89 if (not exists $_->{ret_assign} and exists $_->{sig_char}) { 90 $_->{ret_assign} = 'Parrot_pcc_fill_returns_from_c_args(interp, call_object, "' 91 . $_->{sig_char} . '", return_data);'; 92 } 93 if (not exists $_->{func_call_assign}) { 94 $_->{func_call_assign} = "return_data = " 95 } 96 } 97 43 my %sig_table = %Parrot::NativeCall::signature_table; 98 44 99 45 my $temp_cnt = 0; 100 46 my (@put_pointer, @put_pointer_nci_too, @nci_defs);