Ticket #1105: merge_complete_tweaked.patch
File merge_complete_tweaked.patch, 161.0 KB (added by plobsing, 12 years ago) |
---|
-
DEPRECATED.pod
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 -
src/ops/core.ops
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
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 *);24 typedef nci_sub_t nci_jit_sub_t; 23 25 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; 26 #define NCI_raw_FLAG PObj_private0_FLAG 34 27 35 for (i = 1; i < sig_length; i++) { 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 36 INTVAL c = Parrot_str_indexed(interp, sig, i); 37 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, 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); 86 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 } 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); 95 100 } 96 else 97 nci_info->pcc_params_signature = CONST_STRING(interp, ""); 98 99 if (sig_length > 7) 100 mem_sys_free(param_sig); 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 } 130 } 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 */ 136 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; 164 137 165 /* 138 166 139 167 =item C<METHOD get_multisig()> … … 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)> 190 220 221 Get/Set the pointer being wrapped. Setting through this interface sets 222 the raw flag. 223 191 224 =cut 192 225 193 226 */ 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); 249 SELF.set_string_native(key); 250 SELF.set_pointer(func); 251 PObj_get_FLAGS(SELF) &= ~NCI_raw_FLAG; 252 } 206 253 207 /* Store the original function and signature. */ 208 SET_ATTR_orig_func(INTERP, SELF, func); 254 /* 209 255 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); 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; 449 INTVAL arity; 450 GET_ATTR_arity(INTERP, SELF, arity); 451 RETURN(INTVAL arity); 452 } 402 453 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 } 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()"); 410 495 } 496 } 411 497 412 Parrot_ex_throw_from_c_args(INTERP, NULL, 413 EXCEPTION_INVALID_OPERATION, 414 "You cannot get the arity of an undefined NCI."); 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()"); 510 } 415 511 } 512 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; 527 } 416 528 } 417 529 418 530 /* -
src/frame_builder.c
1 /*2 Copyright (C) 2008-2009, Parrot Foundation.3 $Id$4 */5 6 /* HEADERIZER HFILE: none */7 /* HEADERIZER STOP */8 9 #include "parrot/parrot.h"10 #include "pmc/pmc_fixedintegerarray.h"11 #include "pmc/pmc_unmanagedstruct.h"12 #include "pmc/pmc_managedstruct.h"13 #include "frame_builder.h"14 15 /*16 17 =over 418 19 =item C<void Parrot_jit_free_buffer(PARROT_INTERP, void *ptr, void *priv)>20 21 This is a callback to implement the proper freeing semantics. It is called by22 the ManagedStruct PMC as it is garbage collected.23 24 =cut25 26 */27 28 void29 Parrot_jit_free_buffer(PARROT_INTERP, void *ptr, void *priv)30 {31 const struct jit_buffer_private_data * const jit = (struct jit_buffer_private_data*)priv;32 mem_free_executable(ptr, jit->size);33 free(priv);34 }35 36 /*37 38 =item C<PMC *Parrot_jit_clone_buffer(PARROT_INTERP, PMC *pmc, void *priv)>39 40 This is a callback to implement the proper cloning semantics for jit buffers.41 It is called by the ManagedStruct PMC's clone() function.42 43 =back44 45 =cut46 47 */48 49 PMC *50 Parrot_jit_clone_buffer(PARROT_INTERP, PMC *pmc, void *priv)51 {52 PMC * const rv = pmc_new(interp, pmc->vtable->base_type);53 54 VTABLE_init(interp, rv);55 /* copy the attributes */56 {57 void (*tmpfreefunc)(PARROT_INTERP, void*, void*);58 GETATTR_ManagedStruct_custom_free_func(interp, pmc, tmpfreefunc);59 SETATTR_ManagedStruct_custom_free_func(interp, rv , tmpfreefunc);60 }61 {62 PMC* (*tmpclonefunc)(PARROT_INTERP, PMC*, void*);63 GETATTR_ManagedStruct_custom_clone_func(interp, pmc, tmpclonefunc);64 SETATTR_ManagedStruct_custom_clone_func(interp, rv , tmpclonefunc);65 }66 67 {68 void *freepriv, *clonepriv;69 GETATTR_ManagedStruct_custom_free_priv(interp , pmc, freepriv);70 GETATTR_ManagedStruct_custom_clone_priv(interp, pmc, clonepriv);71 if (freepriv) {72 void *tmp = mem_sys_allocate(sizeof (struct jit_buffer_private_data));73 memcpy(tmp, freepriv, sizeof (struct jit_buffer_private_data));74 SETATTR_ManagedStruct_custom_free_priv(interp, rv , tmp);75 if (clonepriv == freepriv) {76 /* clonepriv is a copy of freepriv, make it a copy in the clone too. */77 SETATTR_ManagedStruct_custom_clone_priv(interp, rv , tmp);78 clonepriv = NULL; /* disable the clonepriv copying below */79 }80 }81 if (clonepriv) {82 void *tmp = mem_sys_allocate(sizeof (struct jit_buffer_private_data));83 memcpy(tmp, clonepriv, sizeof (struct jit_buffer_private_data));84 SETATTR_ManagedStruct_custom_clone_priv(interp, rv , tmp);85 }86 }87 88 /* copy the execmem buffer */89 if (PARROT_MANAGEDSTRUCT(pmc)->ptr) {90 struct jit_buffer_private_data *jit = (struct jit_buffer_private_data*)priv;91 void *ptr = PARROT_MANAGEDSTRUCT(pmc)->ptr;92 void *newptr = mem_alloc_executable(jit->size);93 if (!newptr)94 Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_JIT_ERROR,95 "Cannot allocate executable memory");96 memcpy(newptr, ptr, jit->size);97 PARROT_MANAGEDSTRUCT(rv)->ptr = newptr;98 }99 100 return rv;101 }102 103 104 int105 emit_is8bit(long disp)106 {107 return disp >= -128 && disp <= 127;108 }109 110 char *111 emit_disp8_32(char *pc, int disp)112 {113 if (emit_is8bit(disp)) {114 *(pc++) = (char)disp;115 return pc;116 }117 else {118 *(long *)pc = disp;119 return pc + 4;120 }121 }122 123 void124 emit_sib(PARROT_INTERP, char *pc, int scale, int i, int base)125 {126 int scale_byte;127 128 switch (scale) {129 case 1:130 scale_byte = emit_Scale_1;131 break;132 case 2:133 scale_byte = emit_Scale_2;134 break;135 case 4:136 scale_byte = emit_Scale_4;137 break;138 case 8:139 scale_byte = emit_Scale_8;140 break;141 default:142 Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_JIT_ERROR,143 "Invalid scale factor %d\n", scale);144 return;145 }146 147 *pc = (char)(scale_byte | (i == emit_None ? emit_Index_None : emit_reg_Index(i)) |148 emit_reg_Base(base));149 }150 151 char *152 emit_r_X(PARROT_INTERP, char *pc, int reg_opcode, int base, int i, int scale, long disp)153 {154 if (i && !scale)155 Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_JIT_ERROR,156 "emit_r_X passed invalid scale+index combo\n");157 158 if (base == emit_EBP) {159 /* modrm disp */160 if (i == emit_None) {161 *(pc++) = (char)((emit_is8bit(disp) ? emit_Mod_b01 : emit_Mod_b10)162 | reg_opcode | emit_reg_rm(emit_EBP));163 return emit_disp8_32(pc, disp);164 }165 /* modrm sib disp */166 else {167 *(pc++) = (char)((emit_is8bit(disp) ? emit_Mod_b01 : emit_Mod_b10)168 | reg_opcode | emit_b100);169 emit_sib(interp, pc++, scale, i, base);170 return emit_disp8_32(pc, disp);171 }172 }173 174 /* modrm sib disp */175 if (base == emit_ESP) {176 *(pc++) = (char)((emit_is8bit(disp) ? emit_Mod_b01 : emit_Mod_b10)177 | reg_opcode | emit_rm_b100);178 emit_sib(interp, pc++, scale, i, emit_ESP);179 return emit_disp8_32(pc, disp);180 }181 182 /* modrm disp32 */183 if (!base && !(i && scale)) {184 *(pc++) = (char)(emit_Mod_b00 | reg_opcode | emit_rm_b101);185 *(long *)pc = disp;186 return pc + 4;187 }188 189 /* Ok, everything should be more regular here */190 *(pc++) = (char)((disp == 0 ? emit_Mod_b00 :191 (emit_is8bit(disp) ?192 emit_Mod_b01 : emit_Mod_b10)) |193 reg_opcode |194 (!base || (scale && i) ? emit_rm_b100 : emit_reg_rm(base)));195 196 if (!base || (scale && i)) {197 emit_sib(interp, pc++, scale, i, base);198 }199 if (disp)200 pc = emit_disp8_32(pc, disp);201 202 return pc;203 }204 205 char *206 emit_shift_i_r(PARROT_INTERP, char *pc, int opcode, int imm, int reg)207 {208 if (opcode == emit_b000 && imm < 0) {209 opcode = emit_b001; /* -rol => 32 + ror */210 imm = -imm;211 }212 213 if (imm == 0) {214 /* noop */215 }216 else if (imm == 1) {217 *(pc++) = (char) 0xd1;218 *(pc++) = (char) emit_alu_X_r(opcode, reg);219 }220 else if (imm > 1 && imm < 33) {221 *(pc++) = (char) 0xc1;222 *(pc++) = (char) emit_alu_X_r(opcode, reg);223 *(pc++) = (char)imm;224 }225 else {226 Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_JIT_ERROR,227 "emit_shift_i_r passed invalid shift\n");228 }229 230 return pc;231 }232 233 char *234 emit_popl_r(char *pc, int reg)235 {236 *(pc++) = (char)(0x58 | (reg - 1));237 return pc;238 }239 240 unsigned char *lastpc;241 242 size_t243 calc_signature_needs(const char *sig, int *strings)244 {245 size_t stack_size = 0;246 while (*sig) {247 switch (*sig) {248 case 't':249 (*strings)++;250 stack_size +=4;251 break;252 case 'd':253 stack_size +=8;254 break;255 default:256 stack_size +=4;257 break;258 }259 sig++;260 }261 return stack_size;262 263 }264 265 /*266 * The function generated here is called as func(interp, nci_info)267 * interp ... 8(%ebp)268 * nci_info ... 12(%ebp)269 *270 * The generate function for a specific signature looks quite similar to271 * an optimized compile of src/nci.c:pcf_x_yy(). In case of any troubles272 * just compare the disassembly.273 *274 * If a non-NULL sizeptr is passed, the integer it points to will be written275 * with the size of the allocated execmem buffer.276 */277 278 void *279 Parrot_jit_build_call_func(PARROT_INTERP, PMC *pmc_nci, STRING *signature, int *sizeptr)280 {281 char *pc;282 char *execmem;283 int i = 0;284 int arg_count = 0;285 int string_buffer_count = 0;286 const int ST_SIZE_OF = 124;287 const int JIT_ALLOC_SIZE = 1024;288 289 char *signature_str = Parrot_str_to_cstring(interp, signature);290 /* skip over the result */291 char *sig = signature_str + 1;292 size_t stack_space_needed = calc_signature_needs(sig,293 &string_buffer_count);294 295 int base_offset = 0;296 int strings_offset = base_offset - (sizeof (char *) * string_buffer_count);297 int st_offset = strings_offset - ST_SIZE_OF;298 int args_offset = st_offset - stack_space_needed;299 int temp_calls_offset = args_offset - 16;300 int total_stack_needed = -temp_calls_offset;301 302 /*303 * ESP304 * 0-15, 16 bytes for utility calls305 * stack_space_needed for actual NCI call306 * st307 * STRINGS -> char * holding space308 * EBP309 */310 311 /* this ought to be enough - the caller of this function312 * should free the function pointer returned here313 */314 pc = execmem = (char *)mem_alloc_executable(JIT_ALLOC_SIZE);315 if (! pc)316 Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_JIT_ERROR,317 "Cannot allocate executable memory");318 319 320 /* this generated jit function will be called as (INTERP (EBP 8), func_ptr321 * (ESP 12), args signature (ESP 16)) */322 323 /* make stack frame, preserve %ebx */324 jit_emit_stack_frame_enter(pc);325 326 emitm_subl_i_r(pc, total_stack_needed, emit_ESP);327 328 /* Parrot_init_arg_nci(interp, &st, "S"); */329 /* args signature "S" */330 emitm_movl_m_r(interp, pc, emit_EAX, emit_EBP, 0, 1, 16);331 emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 8);332 333 /*&st*/334 emitm_lea_m_r(interp, pc, emit_EAX, emit_EBP, 0, 1, st_offset);335 emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 4);336 337 /*interpreter*/338 emitm_movl_m_r(interp, pc, emit_EAX, emit_EBP, 0, 1, 8);339 emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 0);340 341 /* XXX FIXME This whole function require major rework */342 /* XXX FIXME if (sig && *sig) */343 /* XXX FIXME emitm_call_cfunc(pc, Parrot_init_arg_nci); */344 345 while (*sig) {346 emitm_movl_i_m(pc, arg_count, emit_EBP, 0, 1, temp_calls_offset + 8);347 348 switch (*sig) {349 case '0': /* null ptr or such - doesn't consume a reg */350 jit_emit_bxor_rr_i(interp, pc, emit_EAX, emit_EAX);351 emitm_movl_m_r(interp, pc, emit_EAX, emit_EBP, 0, 1, args_offset);352 break;353 case 'f':354 /* FIXME emitm_call_cfunc(pc, get_nci_N); */355 emitm_fstps(interp, pc, emit_EBP, 0, 1, args_offset);356 break;357 case 'N':358 case 'd':359 /* FIXME emitm_call_cfunc(pc, get_nci_N); */360 emitm_fstpl(interp, pc, emit_EBP, 0, 1, args_offset);361 args_offset += 4;362 break;363 case 'I': /* INTVAL */364 case 'l': /* long */365 case 'i': /* int */366 /* FIXME emitm_call_cfunc(pc, get_nci_I); */367 emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, args_offset);368 break;369 case 't': /* string, pass a cstring */370 /* FIXME emitm_call_cfunc(pc, get_nci_S); */371 emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 4);372 emitm_call_cfunc(pc, string_to_cstring_nullable);373 374 emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, args_offset);375 /* save off temporary allocation address */376 emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, strings_offset);377 strings_offset += 4;378 379 /* reset ESP(4) */380 emitm_lea_m_r(interp, pc, emit_EAX, emit_EBP, 0, 1, st_offset);381 emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 4);382 break;383 case 's': /* short: movswl intreg_o(base), %eax */384 /* FIXME emitm_call_cfunc(pc, get_nci_I); */385 emitm_movswl_r_r(pc, emit_EAX, emit_EAX);386 emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, args_offset);387 break;388 case 'c': /* char: movsbl intreg_o(base), %eax */389 /* emitm_call_cfunc(pc, get_nci_I); */390 emitm_movsbl_r_r(pc, emit_EAX, emit_EAX);391 emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, args_offset);392 break;393 case 'J': /* interpreter */394 emitm_movl_m_r(interp, pc, emit_EAX, emit_EBP, 0, 1, 8);395 emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, args_offset);396 arg_count--;397 break;398 case 'p': /* push pmc->data */399 /* FIXME emitm_call_cfunc(pc, get_nci_p); */400 emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, args_offset);401 break;402 case 'O': /* push PMC * object in P2 */403 case 'P': /* push PMC * */404 case '@':405 /* FIXME emitm_call_cfunc(pc, get_nci_P); */406 emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, args_offset);407 break;408 case 'v':409 break;410 case 'b': /* buffer (void*) pass Buffer_bufstart(SReg) */411 /* FIXME emitm_call_cfunc(pc, get_nci_S); */412 emitm_movl_m_r(interp, pc, emit_EAX, emit_EAX, 0, 1,413 (size_t) &Buffer_bufstart((STRING *) NULL));414 emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, args_offset);415 break;416 case 'B': /* buffer (void**) pass &Buffer_bufstart(SReg) */417 /* FIXME emitm_call_cfunc(pc, get_nci_S); */418 emitm_lea_m_r(interp, pc, emit_EAX, emit_EAX, 0, 1,419 (size_t) &Buffer_bufstart((STRING *) NULL));420 emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, args_offset);421 break;422 case 'S':423 /* FIXME emitm_call_cfunc(pc, get_nci_S); */424 emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, args_offset);425 break;426 427 428 /* I have no idea how to handle these */429 case '2':430 case '3':431 case '4':432 case 'V':433 mem_free_executable(execmem, JIT_ALLOC_SIZE);434 Parrot_str_free_cstring(signature_str);435 return NULL;436 break;437 default:438 Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_JIT_ERROR,439 "Unknown arg Signature %c\n", *sig);440 /*441 * oops unknown signature:442 * cleanup and try nci.c443 */444 mem_free_executable(execmem, JIT_ALLOC_SIZE);445 Parrot_str_free_cstring(signature_str);446 return NULL;447 }448 args_offset +=4;449 arg_count++;450 sig++;451 }452 453 /* prepare to call VTABLE_get_pointer, set up args */454 /* interpreter - movl 8(%ebp), %eax */455 emitm_movl_m_r(interp, pc, emit_EAX, emit_EBP, 0, 1, 8);456 emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 0);457 458 /* pmc - movl 12(%ebp), %eax */459 emitm_movl_m_r(interp, pc, emit_EAX, emit_EBP, 0, 1, 12);460 emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 4);461 462 /* get the get_pointer() pointer from the pmc's vtable */463 emitm_movl_m_r(interp, pc, emit_EAX, emit_EAX, 0, 1, offsetof(PMC, vtable));464 emitm_movl_m_r(interp, pc, emit_EAX, emit_EAX, 0, 1, offsetof(VTABLE, get_pointer));465 466 /* call get_pointer(), result goes into eax */467 emitm_callr(pc, emit_EAX);468 emitm_addl_i_r(pc, 16, emit_ESP);469 470 /* call the resulting function pointer */471 emitm_callr(pc, emit_EAX);472 emitm_subl_i_r(pc, 16, emit_ESP);473 474 /* SAVE OFF EAX */475 emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 8);476 477 /*&st*/478 emitm_lea_m_r(interp, pc, emit_EAX, emit_EBP, 0, 1, st_offset);479 emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 4);480 481 /*interpreter*/482 emitm_movl_m_r(interp, pc, emit_EAX, emit_EBP, 0, 1, 8);483 emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 0);484 485 /* RESTORE BACK EAX */486 emitm_movl_m_r(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 8);487 488 /* now place return value in registers */489 /* first in signature is the return value */490 sig = signature_str; /* the result */491 switch (*sig) {492 /* I have no idea how to handle these */493 case '2':494 case '3':495 case '4':496 /* get integer from pointer - untested */497 emitm_movl_m_r(interp, pc, emit_EAX, emit_EAX, 0, 1, 0);498 if (*sig == 2) /* short */499 emitm_movswl_r_r(pc, emit_EAX, emit_EAX);500 /* XXX FIXME emitm_call_cfunc(pc, set_nci_I);*/501 break;502 case 'f':503 case 'd':504 jit_emit_fstore_mb_n(interp, pc, emit_EBP, temp_calls_offset + 8);505 /* XXX FIXME emitm_call_cfunc(pc, set_nci_N); */506 /* pop num from st(0) and mov to reg */507 break;508 case 's':509 /* movswl %ax, %eax */510 emitm_movswl_r_r(pc, emit_EAX, emit_EAX);511 emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 8);512 /* XXX FIXME emitm_call_cfunc(pc, set_nci_I); */513 break;514 case 'c':515 /* movsbl %al, %eax */516 emitm_movsbl_r_r(pc, emit_EAX, emit_EAX);517 emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 8);518 /* XXX FIXME emitm_call_cfunc(pc, set_nci_I); */519 break;520 case 'I': /* INTVAL */521 case 'l':522 case 'i':523 emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 8);524 /* XXX FIXME emitm_call_cfunc(pc, set_nci_I); */525 break;526 case 'v': /* void - do nothing */527 break;528 case 'P':529 emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 8);530 /* XXX FIXME emitm_call_cfunc(pc, set_nci_P); */531 break;532 case 'p': /* make a new unmanaged struct */533 /* save return value on stack */534 535 /* save pointer p */536 emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 12);537 538 /* make new pmc */539 emitm_movl_i_m(pc, enum_class_UnManagedStruct, emit_EBP, 0, 1, temp_calls_offset + 4);540 emitm_call_cfunc(pc, pmc_new);541 542 /* restore pointer p to EDX */543 emitm_movl_m_r(interp, pc, emit_EDX, emit_EBP, 0, 1, temp_calls_offset + 12);544 545 /* copy UnManagedStruct to stack for set_nci_P call */546 emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 8);547 548 /* eax = PMC, get return value into edx */549 /* mov data(%eax), %eax550 mov %edx, ptr(%eax) */551 emitm_movl_m_r(interp, pc, emit_EAX, emit_EAX, 0, 1, offsetof(struct PMC, data));552 emitm_movl_r_m(interp, pc, emit_EDX, emit_EAX, 0, 1,553 offsetof(struct Parrot_UnManagedStruct_attributes, ptr));554 555 /* reset EBP(4) */556 emitm_lea_m_r(interp, pc, emit_EAX, emit_EBP, 0, 1, st_offset);557 emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 4);558 559 /* XXX FIXME emitm_call_cfunc(pc, set_nci_P); */560 break;561 case 'S':562 emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 8);563 /* XXX FIXME emitm_call_cfunc(pc, set_nci_S); */564 break;565 case 't': /* string */566 /* EAX is char* */567 emitm_movl_i_m(pc, 0, emit_EBP, 0, 1, temp_calls_offset + 8); /* len */568 569 /* overwrites address of st in EBP(4) */570 emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 4);571 572 emitm_call_cfunc(pc, Parrot_str_new);573 574 emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 8);575 576 /* reset EBP(4) */577 emitm_lea_m_r(interp, pc, emit_EAX, emit_EBP, 0, 1, st_offset);578 emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 4);579 580 /* XXX FIXME emitm_call_cfunc(pc, set_nci_S); */581 break;582 default:583 Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_JIT_ERROR,584 "Unknown return Signature %c\n", *sig);585 /*586 * oops unknown signature:587 * cleanup and try nci.c588 */589 Parrot_str_free_cstring(signature_str);590 mem_free_executable(execmem, JIT_ALLOC_SIZE);591 return NULL;592 }593 594 /* free temporary strings */595 strings_offset = st_offset + ST_SIZE_OF;596 for (i=0; i<string_buffer_count; i++) {597 emitm_movl_m_r(interp, pc, emit_EAX, emit_EBP, 0, 1, strings_offset);598 emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 0);599 emitm_call_cfunc(pc, Parrot_str_free_cstring);600 strings_offset += 4;601 }602 603 jit_emit_stack_frame_leave(pc);604 emitm_ret(pc);605 PARROT_ASSERT(pc - execmem <= JIT_ALLOC_SIZE);606 607 if (sizeptr)608 *sizeptr = JIT_ALLOC_SIZE;609 Parrot_str_free_cstring(signature_str);610 return (void *)D2FPTR(execmem);611 }612 613 /*614 * Local variables:615 * c-file-style: "parrot"616 * End:617 * vim: expandtab shiftwidth=4:618 */ -
src/frame_builder.h
1 1 /* 2 2 * Copyright (C) 2002-2009, Parrot Foundation. 3 */ 4 5 /* 3 * 6 4 * frame_builder.h 7 5 * 8 * i3869 *10 6 * $Id$ 11 7 */ 12 8 13 #ifndef PARROT_ I386_JIT_EMIT_H_GUARD14 #define PARROT_ I386_JIT_EMIT_H_GUARD9 #ifndef PARROT_FRAME_BUILDER_H_GUARD 10 #define PARROT_FRAME_BUILDER_H_GUARD 15 11 16 12 #if defined(__cplusplus) 17 13 # define EXTERN extern "C" … … 21 17 22 18 #include <assert.h> 23 19 #include "parrot/parrot.h" 24 #include "parrot/hash.h"25 #include "parrot/oplib/ops.h"26 20 27 21 /* 28 22 * NCI interface 29 23 */ 24 30 25 void * 31 Parrot_jit_build_call_func(Interp *, PMC *, STRING *, int*);26 Parrot_jit_build_call_func(Interp *, PMC *, STRING *, void **); 32 27 33 28 /* custom pmc callback functions */ 34 29 void … … 37 32 PMC* 38 33 Parrot_jit_clone_buffer(PARROT_INTERP, PMC *pmc, void *priv); 39 34 40 struct jit_buffer_private_data {41 int size;42 };43 44 /* Scale factor values */45 #define emit_Scale(scale) ((scale) << 6)46 #define emit_Scale_1 emit_Scale(0)47 #define emit_Scale_2 emit_Scale(1)48 #define emit_Scale_4 emit_Scale(2)49 #define emit_Scale_8 emit_Scale(3)50 51 /* ESIB byte */52 #define emit_reg_Index(x) (((x)-1) << 3)53 #define emit_reg_Base(x) ((x)-1)54 #define emit_Index_None ((emit_b100) << 3)55 56 35 /* 57 36 * helper funcs - get argument n 58 37 */ 59 38 60 /* 61 * if we have a delegated method like typeof_i_p, that returns an INTVAL 62 * and that is all in a sequence of JITted opcodes, and when these INTVAL 63 * is MAPped, we got a problem. So the EXT_CALL flag is disabled - mapped 64 * registers are saved/restored around vtable calls. 65 */ 66 #define JIT_VTABLE_OPS 1 39 #endif /* PARROT_FRAME_BUILDER_H_GUARD */ 67 40 68 /* EXEC_SHARED generates code to be used with libparrot.so69 * It grabs the real address of cgp_core from the gcc generated code70 * x/1i cgp_code71 * jmp *0xXXXX72 * x/1wx 0xXXXX73 * real address of cpg_core74 * s. exec_emit_end75 * XXX This should be a command line option.76 */77 #undef EXEC_SHARED78 79 extern UINTVAL ld(UINTVAL);80 81 #define NEG_MINUS_ZERO82 /* #define NEG_ZERO_SUB */83 84 /* Register codes */85 #define emit_None 086 87 /* These are + 1 the real values */88 #define emit_EAX 189 #define emit_ECX 290 #define emit_EDX 391 #define emit_EBX 492 #define emit_ESP 593 #define emit_EBP 694 #define emit_ESI 795 #define emit_EDI 896 97 /* Scratch register. */98 99 #define ISR1 emit_EAX100 #define FSR1 0101 102 #define emit_b00 0103 #define emit_b01 1104 #define emit_b10 2105 #define emit_b11 3106 107 #define emit_b000 0108 #define emit_b001 1109 #define emit_b010 2110 #define emit_b011 3111 #define emit_b100 4112 #define emit_b101 5113 #define emit_b110 6114 #define emit_b111 7115 116 /* Mod R/M byte */117 #define emit_reg(x) ((x) << 3)118 #define emit_Mod(Mod) ((Mod) << 6)119 #define emit_reg_rm(x) ((x)-1)120 121 /* Mod values for Mod R/M Byte */122 #define emit_Mod_b00 emit_Mod(emit_b00)123 #define emit_Mod_b01 emit_Mod(emit_b01)124 #define emit_Mod_b10 emit_Mod(emit_b10)125 126 /* special R/M values */127 #define emit_rm_b101 emit_b101128 #define emit_rm_b100 emit_b100129 130 #define emit_r_m(interp, pc, reg1, b, i, s, d) \131 emit_r_X((interp), (pc), emit_reg((reg1)-1), (b), (i), (s), (d))132 133 #define emit_alu_X_r(X, reg) ((emit_b11 << 6) | ((X) << 3) | ((reg) - 1))134 135 #define emit_alu_r_r(reg1, reg2) emit_alu_X_r(((reg1) - 1), (reg2))136 137 int emit_is8bit(long disp);138 139 char * emit_disp8_32(char *pc, int disp);140 141 void emit_sib(PARROT_INTERP, char *pc, int scale, int i, int base);142 143 char * emit_r_X(PARROT_INTERP, char *pc, int reg_opcode, int base, int i,144 int scale, long disp);145 146 char * emit_shift_i_r(PARROT_INTERP, char *pc, int opcode, int imm, int reg);147 148 char * emit_shift_i_m(PARROT_INTERP, char *pc, int opcode, int imm,149 int base, int i, int scale, long disp);150 151 char * emit_shift_r_r(PARROT_INTERP, char *pc, int opcode, int reg1, int reg2);152 153 char * emit_shift_r_m(PARROT_INTERP, char *pc, int opcode, int reg,154 int base, int i, int scale, long disp);155 156 /* CDQ - need this to do multiply */157 #define emitm_cdq(pc) *((pc)++) = (char) 0x99158 159 /* RET */160 #define emitm_ret(pc) *((pc)++) = (char) 0xc3161 162 /* NOP */163 #define emit_nop(pc) *((pc)++) = (char) 0x90164 165 /* PUSHes */166 167 #define emitm_pushl_r(pc, reg) \168 *((pc)++) = (char) 0x50 | ((reg) - 1)169 170 #define emitm_pushl_i(pc, imm) { \171 *((pc)++) = (char) 0x68; \172 *(long *)(pc) = (long)(imm); \173 (pc) += 4; }174 175 #define emitm_pushl_m(pc, mem) { \176 *((pc)++) = (char) 0xff; \177 *((pc)++) = (char) 0x35; \178 *(long *)(pc) = (long)(mem); \179 (pc) += 4; }180 181 char * emit_pushl_m(PARROT_INTERP, char *pc, int base, int i, int scale,182 long disp);183 184 /* POPs */185 186 char * emit_popl_r(char *pc, int reg);187 188 # define emitm_popl_r(pc, reg) \189 (pc) = emit_popl_r((pc), (reg))190 191 char * emit_popl_m(PARROT_INTERP, char *pc, int base, int i, int scale,192 long disp);193 194 /* MOVes */195 196 char * emit_movb_r_r(char *pc, int reg1, int reg2);197 198 # define jit_emit_mov_rr_i(pc, reg2, reg1) if ((reg1) != (reg2)) { \199 *((pc)++) = (char) 0x89; \200 *((pc)++) = (char) emit_alu_r_r((reg1), (reg2)); }201 202 # define jit_emit_mov_ri_i(interp, pc, reg, imm) { \203 *((pc)++) = (char)(0xb8 | ((reg) - 1)); \204 *(long *)(pc) = (long)(imm); (pc) += 4; }205 206 # define emitm_movX_Y_Z(interp, op, pc, reg1, b, i, s, d) { \207 *((pc)++) = (char) (op); \208 (pc) = emit_r_m((interp), (pc), (reg1), (b), (i), (s), (long)(d)); }209 210 # define emitm_movb_r_m(interp, pc, reg1, b, i, s, d) \211 emitm_movX_Y_Z((interp), 0x88, (pc), (reg1), (b), (i), (s), (d))212 213 # define emitm_movl_r_m(interp, pc, reg1, b, i, s, d) \214 emitm_movX_Y_Z((interp), 0x89, (pc), (reg1), (b), (i), (s), (d))215 216 /* move byte/word with sign extension */217 # define emitm_movsbl_r_m(interp, pc, reg1, b, i, s, d) { \218 *((pc)++) = (char) 0x0f; \219 emitm_movX_Y_Z((interp), 0xBE, (pc), (reg1), (b), (i), (s), (d)); \220 }221 222 # define emitm_movswl_r_m(interp, pc, reg1, b, i, s, d) { \223 *((pc)++) = (char) 0x0f; \224 emitm_movX_Y_Z((interp), 0xBF, (pc), (reg1), (b), (i), (s), (d)); \225 }226 227 # define emitm_movsbl_r_r(pc, reg1, reg2) { \228 *((pc)++) = (char) 0x0f; \229 *((pc)++) = (char) 0xbe; \230 *((pc)++) = (char) emit_alu_r_r((reg1), (reg2)); \231 }232 233 # define emitm_movswl_r_r(pc, reg1, reg2) { \234 *((pc)++) = (char) 0x0f; \235 *((pc)++) = (char) 0xbf; \236 *((pc)++) = (char) emit_alu_r_r((reg1), (reg2)); \237 }238 239 # define emitm_movb_m_r(interp, pc, reg1, b, i, s, d) \240 emitm_movX_Y_Z((interp), 0x8a, (pc), (reg1), (b), (i), (s), (d))241 242 # define emitm_movl_m_r(interp, pc, reg1, b, i, s, d) \243 emitm_movX_Y_Z((interp), 0x8b, (pc), (reg1), (b), (i), (s), (d))244 245 # define emitm_lea_m_r(interp, pc, reg1, b, i, s, d) \246 emitm_movX_Y_Z((interp), 0x8d, (pc), (reg1), (b), (i), (s), (d))247 248 char * emit_movb_i_m(PARROT_INTERP, char *pc, char imm, int base, int i,249 int scale, long disp);250 251 # define emitm_movl_i_m(pc, imm, b, i, s, d) { \252 *((pc)++) = (char) 0xc7; \253 (pc) = emit_r_X((interp), (pc), emit_reg(emit_b000), (b), (i), (s), (long)(d)); \254 *(long *)(pc) = (long)(imm); (pc) += 4; }255 256 /* Various ALU formats */257 258 # define emitm_alul_r_r(pc, op, reg1, reg2) { \259 *((pc)++) = (char) (op); *((pc)++) = (char) emit_alu_r_r((reg1), (reg2)); }260 261 # define emitm_alub_i_r(pc, op1, op2, imm, reg) { \262 *((pc)++) = (char) (op1); *((pc)++) = (char) emit_alu_X_r((op2), (reg)); *((pc)++) = (char)(imm); }263 264 # define emitm_alul_i_r(pc, op1, op2, imm, reg) { \265 *((pc)++) = (char) (op1); \266 *((pc)++) = (char) emit_alu_X_r((op2), (reg)); \267 *(long *)((pc)) = (long)(imm); (pc) += 4; }268 269 # define emitm_alul_i_m(pc, op1, op2, imm, b, i, s, d) { \270 *((pc)++) = (char) (op1); \271 (pc) = emit_r_X((interp), (pc), emit_reg(op2), (b), (i), (s), (d)); \272 *(long *)(pc) = (long)(imm); (pc) += 4; }273 274 # define emitm_alul_r_m(pc, op, reg, b, i, s, d) { \275 *((pc)++) = (char) (op); \276 (pc) = emit_r_X((interp), (pc), emit_reg((reg)-1), (b), (i), (s), (long)(d)); }277 278 /* ADDs */279 280 # define emitm_addb_r_r(pc, reg1, reg2) \281 emitm_alul_r_r((pc), 0x00, (reg1), (reg2))282 283 # define emitm_addb_i_r(pc, imm, reg) \284 emitm_alub_i_r((pc), 0x83, emit_b000, (imm), (reg))285 286 # define jit_emit_add_rr_i(interp, pc, reg1, reg2) \287 emitm_alul_r_r((pc), 0x01, (reg2), (reg1))288 289 # define jit_emit_add_ri_i(interp, pc, reg, imm) \290 emitm_alul_i_r((pc), 0x81, emit_b000, (imm), (reg))291 292 # define emitm_addl_i_r(pc, imm, reg) \293 emitm_alul_i_r((pc), 0x81, emit_b000, (imm), (reg))294 295 # define emitm_addl_i_m(pc, imm, b, i, s, d) \296 emitm_alul_i_m((pc), 0x81, emit_b000, (imm), (b), (i), (s), (d))297 298 # define emitm_addl_r_m(pc, reg, b, i, s, d) \299 emitm_alul_r_m((pc), 0x01, (reg), (b), (i), (s), (d))300 301 # define emitm_addl_m_r(pc, reg, b, i, s, d) \302 emitm_alul_r_m((pc), 0x03, (reg), (b), (i), (s), (d))303 304 /* SUBs */305 306 # define jit_emit_sub_rr_i(interp, pc, reg1, reg2) \307 emitm_alul_r_r((pc), 0x29, (reg2), (reg1))308 309 # define emitm_subl_i_r(pc, imm, reg) \310 emitm_alul_i_r((pc), 0x81, emit_b101, (imm), (reg))311 312 # define jit_emit_sub_ri_i(interp, pc, r, i) emitm_subl_i_r((pc), (i), (r))313 314 # define emitm_subl_r_m(pc, reg, b, i, s, d) \315 emitm_alul_r_m((pc), 0x29, (reg), (b), (i), (s), (d))316 317 # define emitm_subl_m_r(pc, reg, b, i, s, d) \318 emitm_alul_r_m((pc), 0x2b, (reg), (b), (i), (s), (d))319 320 # define emitm_subl_i_m(pc, imm, b, i, s, d) \321 emitm_alul_i_m((pc), 0x81, emit_b101, (imm), (b), (i), (s), (d))322 323 /* These are used by both signed and unsigned EDIV, but only unsigned MUL */324 # define emitm_alu_imp_r(pc, op, reg) { \325 *((pc)++) = (char) 0xf7; \326 *((pc)++) = (char) emit_alu_X_r((op), (reg)); }327 328 # define emitm_alu_imp_m(pc, op, b, i, s, d) { \329 *((pc)++) = (char) 0xf7; \330 (pc) = emit_r_X((interp), (pc), emit_reg(op), (b), (i), (s), (d)); }331 332 /* Unsigned MUL and EDIV */333 /* EAX implicit destination in multiply and divide */334 335 # define emitm_umull_r(pc, reg2) emitm_alu_imp_r((pc), emit_b100, (reg2))336 337 # define emitm_udivl_r(pc, reg2) emitm_alu_imp_r((pc), emit_b110, (reg2))338 339 # define emitm_umull_m(pc, b, i, s, d) \340 emitm_alu_imp_m((pc), emit_b100, (b), (i), (s), (d))341 342 # define emitm_udivl_m(pc, b, i, s, d) \343 emitm_alu_imp_m((pc), emit_b110, (b), (i), (s), (d))344 345 /* Signed MUL and EDIV */346 347 # define emitm_sdivl_r(pc, reg2) emitm_alu_imp_r((pc), emit_b111, (reg2))348 349 # define emitm_sdivl_m(pc, b, i, s, d) \350 emitm_alu_imp_m((pc), emit_b111, (b), (i), (s), (d))351 352 # define jit_emit_cdq(pc) *(pc)++ = 0x99353 354 /* TEST for zero */355 # define jit_emit_test_r_i(pc, reg1) emitm_alul_r_r((pc), 0x85, (reg1), (reg1))356 357 # define emitm_smull_r(pc, reg2) emitm_alu_imp_r((pc), emit_b101, (reg2))358 359 # define jit_emit_mul_rr_i(interp, pc, reg1, reg2) { \360 *(pc)++ = 0xf; \361 emitm_alul_r_r((pc), 0xaf, (reg1), (reg2)); }362 363 # define emitm_smull_r_m(pc, reg1, b, i, s, d) { \364 *(pc)++ = 0xf; \365 emitm_alul_r_m((pc), 0xaf, (reg1), (b), (i), (s), (d)); }366 367 char * opt_mul(PARROT_INTERP, char *pc, int dest, INTVAL imm, int src);368 369 # define jit_emit_mul_rir_i(pc, dest, imm, src) \370 (pc) = opt_mul(interp, (pc), (dest), (imm), (src))371 372 373 # define jit_emit_mul_ri_i(pc, r, imm) jit_emit_mul_rir_i((pc), (r), (imm), (r))374 375 # define jit_emit_mul_RIM_ii(pc, reg, imm, ofs) \376 emitm_alul_r_m((pc), 0x69, (reg), emit_EBX, emit_None, 1, (ofs)); \377 *(long *)(pc) = (long)(imm); \378 (pc) += 4;379 380 /* NEG */381 382 # define jit_emit_neg_r_i(pc, reg) emitm_alu_imp_r((pc), emit_b011, (reg))383 384 # define emitm_negl_m(pc, b, i, s, d) \385 emitm_alu_imp_m((pc), emit_b011, (b), (i), (s), (d))386 387 /* AND */388 389 # define emit_andl_r_r(pc, reg1, reg2) emitm_alul_r_r((pc), 0x21, (reg1), (reg2))390 # define jit_emit_band_rr_i(interp, pc, r1, r2) emit_andl_r_r((pc), (r2), (r1))391 392 # define jit_emit_band_ri_i(interp, pc, reg, imm) \393 emitm_alul_i_r((pc), 0x81, emit_b100, (imm), (reg))394 395 # define emitm_andl_r_m(pc, reg, b, i, s, d) \396 emitm_alul_r_m((pc), 0x21, (reg), (b), (i), (s), (d))397 398 # define emitm_andl_m_r(pc, reg, b, i, s, d) \399 emitm_alul_r_m((pc), 0x23, (reg), (b), (i), (s), (d))400 401 # define emitm_andl_i_m(pc, imm, b, i, s, d) \402 emitm_alul_i_m((pc), 0x81, emit_b100, (imm), (b), (i), (s), (d))403 404 /* TEST op */405 # define jit_emit_test_rr_i(pc, r1, r2) emitm_alul_r_r((pc), 0x85, (r1), (r2))406 407 # define jit_emit_test_ri_i(pc, r, im) \408 emitm_alul_i_r((pc), 0xF7, emit_b000, (im), (r))409 410 # define jit_emit_test_RM_i(pc, r, offs) \411 emitm_alul_r_m((pc), 0x85, (r), emit_EBX, 0, 1, (offs))412 413 /* OR */414 415 # define jit_emit_bor_rr_i(interp, pc, reg1, reg2) emitm_alul_r_r((pc), 0x9, (reg2), (reg1))416 417 # define jit_emit_bor_ri_i(interp, pc, reg, imm) \418 emitm_alul_i_r((pc), 0x81, emit_b001, (imm), (reg))419 420 # define emitm_orl_r_m(pc, reg, b, i, s, d) \421 emitm_alul_r_m((pc), 0x09, (reg), (b), (i), (s), (d))422 423 # define emitm_orl_m_r(pc, reg, b, i, s, d) \424 emitm_alul_r_m((pc), 0x0b, (reg), (b), (i), (s), (d))425 426 # define emitm_orl_i_m(pc, imm, b, i, s, d) \427 emitm_alul_i_m((pc), 0x81, emit_b001, (imm), (b), (i), (s), (d))428 429 /* XOR */430 431 # define jit_emit_bxor_rr_i(interp, pc, reg1, reg2) \432 emitm_alul_r_r((pc), 0x31, (reg2), (reg1))433 434 # define jit_emit_bxor_ri_i(intepr, pc, reg, imm) \435 emitm_alul_i_r((pc), 0x81, emit_b110, (imm), (reg))436 437 # define emitm_xorl_r_m(pc, reg, b, i, s, d) \438 emitm_alul_r_m((pc), 0x31, (reg), (b), (i), (s), (d))439 440 # define emitm_xorl_m_r(pc, reg, b, i, s, d) \441 emitm_alul_r_m((pc), 0x33, (reg), (b), (i), (s), (d))442 443 # define emitm_xorl_i_m(pc, imm, b, i, s, d) \444 emitm_alul_i_m((pc), 0x81, emit_b110, (imm), (b), (i), (s), (d))445 446 /* NOT */447 448 # define jit_emit_not_r_i(pc, reg) emitm_alu_imp_r((pc), emit_b010, (reg))449 # define emitm_notl_m(pc, b, i, s, d) \450 emitm_alu_imp_m((pc), emit_b010, (b), (i), (s), (d))451 452 # define jit_emit_not_M_i(interp, pc, offs) emitm_notl_m((pc), emit_EBX, 0, 1, (offs))453 454 /* XCHG */455 # define jit_emit_xchg_rr_i(interp, pc, r1, r2) { \456 if ((r1) != (r2)) { \457 *((pc)++) = (char) 0x87; \458 *((pc)++) = (char) emit_alu_r_r((r1), (r2)); \459 } \460 }461 462 # define jit_emit_xchg_rm_i(pc, r, m) { \463 emitm_alul_r_m((pc), 0x87, (r), emit_None, emit_None, emit_None, (m)) \464 }465 # define jit_emit_xchg_RM_i(interp, pc, r, offs) { \466 emitm_alul_r_m((pc), 0x87, (r), emit_EBX, emit_None, 1, (offs)) \467 }468 # define jit_emit_xchg_MR_i(interp, pc, offs, r) jit_emit_xchg_RM_i((interp), (pc), (r), (offs))469 470 /* SHL */471 472 # define jit_emit_shl_ri_i(interp, pc, reg, imm) \473 { (pc) = emit_shift_i_r((interp), (pc), emit_b100, (imm), (reg)); }474 475 # define emitm_shll_i_m(pc, imm, b, i, s, d) \476 { (pc) = emit_shift_i_m((pc), emit_b100, (imm), (b), (i), (s), (d)); }477 478 # define emitm_shll_r_r(interp, pc, reg1, reg2) \479 { (pc) = emit_shift_r_r((interp), (pc), emit_b100, (reg1), (reg2)); }480 481 # define emitm_shll_r_m(pc, reg, b, i, s, d) \482 { (pc) = emit_shift_r_m((pc), emit_b100, (reg), (b), (i), (s), (d)); }483 484 /* SHR */485 486 # define jit_emit_lsr_ri_i(interp, pc, reg, imm) \487 { (pc) = emit_shift_i_r((interp), (pc), emit_b101, (imm), (reg)); }488 489 # define emitm_shrl_i_m(pc, imm, b, i, s, d) \490 { (pc) = emit_shift_i_m((pc), emit_b101, (imm), (b), (i), (s), (d)); }491 492 # define emitm_shrl_r_r(interp, pc, reg1, reg2) \493 { (pc) = emit_shift_r_r((interp), (pc), emit_b101, (reg1), (reg2)); }494 495 # define emitm_shrl_r_m(pc, reg, b, i, s, d) \496 { (pc) = emit_shift_r_m((pc), emit_b101, (reg), (b), (i), (s), (d)); }497 498 /* SAL */499 500 # define emitm_sall_i_r(interp, pc, imm, reg) \501 { (pc) = emit_shift_i_r((interp), (pc), emit_b100, (imm), (reg)); }502 503 # define emitm_sall_i_m(pc, imm, b, i, s, d) \504 { (pc) = emit_shift_i_m((pc), emit_b100, (imm), (b), (i), (s), (d)); }505 506 # define emitm_sall_r_r(interp, pc, reg1, reg2) \507 { (pc) = emit_shift_r_r((interp), (pc), emit_b100, (reg1), (reg2)); }508 509 # define emitm_sall_r_m(pc, reg, b, i, s, d) \510 { (pc) = emit_shift_r_m((pc), emit_b100, (reg), (b), (i), (s), (d)); }511 512 /* SAR */513 514 # define jit_emit_shr_ri_i(interp, pc, reg, imm) \515 { (pc) = emit_shift_i_r((interp), (pc), emit_b111, (imm), (reg)); }516 517 518 # define emitm_sarl_i_m(pc, imm, b, i, s, d) \519 { (pc) = emit_shift_i_m((pc), emit_b111, (imm), (b), (i), (s), (d)); }520 521 # define emitm_sarl_r_r(interp, pc, reg1, reg2) \522 { (pc) = emit_shift_r_r((interp), (pc), emit_b111, (reg1), (reg2)); }523 524 # define emitm_sarl_r_m(pc, reg, b, i, s, d) \525 { (pc) = emit_shift_r_m((pc), emit_b111, (reg), (b), (i), (s), (d)); }526 527 /* rotate */528 529 # define jit_emit_rol_ri_i(interp, pc, reg, imm) \530 { (pc) = emit_shift_i_r((interp), (pc), emit_b000, (imm), (reg)); }531 532 # define jit_emit_ror_ri_i(interp, pc, reg, imm) \533 { (pc) = emit_shift_i_r((interp), (pc), emit_b001, (imm), (reg)); }534 535 /* interface, shift r1 by r2 bits */536 537 # define jit_emit_shl_rr_i(interp, pc, r1, r2) \538 (pc) = opt_shift_rr((interp), jit_info, (r1), (r2), emit_b100)539 540 # define jit_emit_shl_RM_i(interp, pc, r1, offs) \541 (pc) = opt_shift_rm((interp), jit_info, (r1), (offs), emit_b100)542 543 /* shr seems to be the arithmetic shift */544 # define jit_emit_shr_rr_i(interp, pc, r1, r2) \545 (pc) = opt_shift_rr((interp), jit_info, (r1), (r2), emit_b111)546 547 # define jit_emit_shr_RM_i(interp, pc, r1, offs) \548 (pc) = opt_shift_rm((interp), jit_info, (r1), (offs), emit_b111)549 550 # define jit_emit_lsr_rr_i(interp, pc, r1, r2) \551 (pc) = opt_shift_rr((interp), jit_info, (r1), (r2), emit_b101)552 553 # define jit_emit_lsr_RM_i(interp, pc, r1, offs) \554 (pc) = opt_shift_rm((interp), jit_info, (r1), (offs), emit_b101)555 556 /* MOV (reg), reg */557 # define emit_movm_r_r(pc, src, dest) \558 *((pc)++) = (char) 0x8b; \559 *((pc)++) = (char) (src) | (dest) << 3560 561 /* MOV X(reg), reg */562 # define emit_movb_i_r_r(pc, imm, src, dest) \563 *((pc)++) = (char)(0x8b); \564 *((p)c++) = (char)(0x40 | ((src) - 1) | ((dest) - 1) << 3); \565 *((pc)++) = (imm)566 567 /* INC / DEC */568 # define jit_emit_inc_r_i(pc, reg) *((pc)++) = (char)(0x40 | ((reg) - 1))569 # define jit_emit_dec_r_i(pc, reg) *((pc)++) = (char)(0x48 | ((reg) - 1))570 571 /* Floating point ops */572 573 # define emitm_floatop 0xd8 /* 11011000 */574 # define jit_emit_dec_fsp(pc) { *((pc)++) = (char) 0xD9; *((pc)++) = (char) 0xF6; }575 # define jit_emit_inc_fsp(pc) { *((pc)++) = (char) 0xD9; *((pc)++) = (char) 0xF7; }576 577 # define emitm_fl_2(interp, pc, mf, opa, opb, b, i, s, d) { \578 *((pc)++) = (char)(emitm_floatop | ((mf) << 1) | (opa)); \579 (pc) = emit_r_X((interp), (pc), emit_reg(opb), (b), (i), (s), (long)(d)); }580 581 # define emitm_fl_3(pc, d_p_opa, opb_r, sti) { \582 *((pc)++) = (char)(emitm_floatop | (d_p_opa)); \583 *((pc)++) = (char)(0xc0 | ((opb_r) << 3) | (sti)); }584 585 # define emitm_fl_4(pc, op) { \586 *((pc)++) = (char)(emitm_floatop | emit_b001); \587 *((pc)++) = (char)(0xe0 | (op)); }588 589 /* Integer loads and stores */590 # define emitm_fildl(interp, pc, b, i, s, d) \591 emitm_fl_2((interp), (pc), emit_b01, 1, emit_b000, (b), (i), (s), (d))592 593 # define emitm_fistpl(interp, pc, b, i, s, d) \594 emitm_fl_2((interp), (pc), emit_b01, 1, emit_b011, (b), (i), (s), (d))595 596 # define emitm_fistl(interp, pc, b, i, s, d) \597 emitm_fl_2((interp), (pc), emit_b01, 1, emit_b010, (b), (i), (s), (d))598 599 /* long long integer load/store */600 # define emitm_fildll(interp, pc, b, i, s, d) \601 emitm_fl_2((interp), (pc), emit_b11, 1, emit_b101, (b), (i), (s), (d))602 603 # define emitm_fistpll(interp, pc, b, i, s, d) \604 emitm_fl_2((interp), (pc), emit_b11, 1, emit_b111, (b), (i), (s), (d))605 606 /* Double loads and stores */607 # define emitm_fldl(interp, pc, b, i, s, d) \608 emitm_fl_2((interp), (pc), emit_b10, 1, emit_b000, (b), (i), (s), (d))609 610 # define emitm_fstpl(interp, pc, b, i, s, d) \611 emitm_fl_2((interp), (pc), emit_b10, 1, emit_b011, (b), (i), (s), (d))612 613 # define emitm_fstl(interp, pc, b, i, s, d) \614 emitm_fl_2((interp), (pc), emit_b10, 1, emit_b010, (b), (i), (s), (d))615 616 /* long double load / store */617 # define emitm_fldt(interp, pc, b, i, s, d) \618 emitm_fl_2((interp), (pc), emit_b01, 1, emit_b101, (b), (i), (s), (d))619 620 # define emitm_fstpt(interp, pc, b, i, s, d) \621 emitm_fl_2((interp), (pc), emit_b01, 1, emit_b111, (b), (i), (s), (d))622 623 /* short float load / store */624 # define emitm_flds(interp, pc, b, i, s, d) \625 emitm_fl_2((interp), (pc), emit_b00, 1, emit_b000, (b), (i), (s), (d))626 627 # define emitm_fstps(interp, pc, b, i, s, d) \628 emitm_fl_2((interp), (pc), emit_b00, 1, emit_b010, (b), (i), (s), (d))629 630 #if NUMVAL_SIZE == 8631 632 # define jit_emit_fload_m_n(interp, pc, address) \633 emitm_fldl((interp), (pc), emit_None, emit_None, emit_None, (address))634 635 # define jit_emit_fload_mb_n(interp, pc, base, offs) \636 emitm_fldl((interp), (pc), (base), emit_None, 1, (offs))637 638 # define jit_emit_fstore_m_n(interp, pc, address) \639 emitm_fstpl((interp), (pc), emit_None, emit_None, emit_None, (address))640 641 # define jit_emit_fstore_mb_n(interp, pc, base, offs) \642 emitm_fstpl((interp), (pc), (base), emit_None, 1, (offs))643 644 # define jit_emit_fst_mb_n(interp, pc, base, offs) \645 emitm_fstl((interp), (pc), (base), emit_None, 1, (offs))646 647 #else /* NUMVAL_SIZE */648 649 # define jit_emit_fload_m_n(interp, pc, address) \650 emitm_fldt((pc), emit_None, emit_None, emit_None, (address))651 652 # define jit_emit_fload_mb_n(interp, pc, base, offs) \653 emitm_fldt((pc), (base), emit_None, 1, (offs))654 655 # define jit_emit_fstore_m_n(pc, address) \656 emitm_fstpt((pc), emit_None, emit_None, emit_None, (address))657 658 # define jit_emit_fstore_mb_n(interp, pc, base, offs) \659 emitm_fstpt((pc), (base), emit_None, 1, (offs))660 661 # define jit_emit_fst_mb_n(interp, pc, base, offs) \662 emitm_fstt((pc), (base), emit_None, 1, (offs))663 664 #endif /* NUMVAL_SIZE */665 666 #if INTVAL_SIZE == 4667 668 # define jit_emit_fload_m_i(interp, pc, address) \669 emitm_fildl((interp), (pc), emit_None, emit_None, emit_None, (address))670 # define jit_emit_fload_mb_i(interp, pc, offs) \671 emitm_fildl((interp), (pc), emit_EBX, emit_None, 1, (offs))672 # define jit_emit_fstore_m_i(pc, m) \673 emitm_fistpl((pc), emit_None, emit_None, emit_None, (m))674 675 #else /* INTVAL_SIZE */676 677 # define jit_emit_fload_m_i(interp, pc, address) \678 emitm_fildll((interp), (pc), emit_None, emit_None, emit_None, (address))679 # define jit_emit_fload_mb_i(interp, pc, offs) \680 emitm_fildll((interp), (pc), emit_EBX, emit_None, 1, (offs))681 # define jit_emit_fstore_m_i(pc, m) \682 emitm_fistpll((pc), emit_None, emit_None, emit_None, (m))683 684 #endif /* INTVAL_SIZE */685 686 /* 0xD8 ops */687 # define emitm_fadd(pc, sti) emitm_fl_3((pc), emit_b000, emit_b000, (sti))688 # define emitm_fmul(pc, sti) emitm_fl_3((pc), emit_b000, emit_b001, (sti))689 # define emitm_fsub(pc, sti) emitm_fl_3((pc), emit_b000, emit_b100, (sti))690 # define emitm_fdiv(pc, sti) emitm_fl_3((pc), emit_b000, emit_b110, (sti))691 692 /* 0xD9 ops */693 # define emitm_fldz(pc) { *((pc)++) = (char) 0xd9; *((pc)++) = (char) 0xee; }694 # define emitm_fld1(pc) { *((pc)++) = (char) 0xd9; *((pc)++) = (char) 0xe8; }695 # define emitm_fsqrt(pc) { *((pc)++) = (char) 0xd9; *((pc)++) = (char) 0xfa; }696 # define emitm_fsin(pc) { *((pc)++) = (char) 0xd9; *((pc)++) = (char) 0xfe; }697 # define emitm_fcos(pc) { *((pc)++) = (char) 0xd9; *((pc)++) = (char) 0xff; }698 # define emitm_fxam(pc) { *((pc)++) = (char) 0xd9; *((pc)++) = (char) 0xe5; }699 700 /* FXCH ST, ST(i) , optimize 2 consecutive fxch with same reg */701 # define emitm_fxch(pc, sti) { \702 emitm_fl_3((pc), emit_b001, emit_b001, (sti)); \703 }704 705 /* FLD ST, ST(i), optimized FSTP(N+1);FLD(N) => FST(N+1) */706 extern unsigned char *lastpc;707 # define emitm_fld(pc, sti) do { \708 if ((unsigned char *)(pc) == (lastpc + 2) && \709 (int)(*lastpc) == (int)0xDD && \710 (int)lastpc[1] == (int)(0xD8+(sti)+1)) \711 lastpc[1] = 0xD0+(sti)+1; \712 else \713 emitm_fl_3((pc), emit_b001, emit_b000, (sti)); \714 } while (0)715 716 /* 0xDA, 0xDB ops */717 /* FCMOV*, FCOMI PPRO */718 719 /* 0xDC like 0xD8 with reversed operands */720 # define emitm_faddr(pc, sti) emitm_fl_3((pc), emit_b100, emit_b000, (sti))721 # define emitm_fmulr(pc, sti) emitm_fl_3((pc), emit_b100, emit_b001, (sti))722 # define emitm_fsubr(pc, sti) emitm_fl_3((pc), emit_b100, emit_b100, (sti))723 724 /* 0xDD ops */725 /* FFree ST(i) */726 # define emitm_ffree(pc, sti) emitm_fl_3((pc), emit_b101, emit_b000, (sti))727 728 /* FST ST(i) = ST */729 # define emitm_fst(pc, sti) emitm_fl_3((pc), emit_b101, emit_b010, (sti))730 731 /* FSTP ST(i) = ST, POP */732 # define emitm_fstp(pc, sti) { \733 lastpc = (unsigned char*) (pc); \734 emitm_fl_3((pc), emit_b101, emit_b011, (sti)); \735 }736 737 /* FUCOM ST(i) <=> ST unordered compares */738 # define emitm_fucom(pc, sti) emitm_fl_3((pc), emit_b101, emit_b100, (sti))739 740 /* FUCOMP ST(i) <=> ST, POP */741 # define emitm_fucomp(pc, sti) emitm_fl_3((pc), emit_b101, emit_b101, (sti))742 743 /* 0xDE ops */744 /* FADDP Add ST(i) = ST + ST(i); POP */745 # define emitm_faddp(pc, sti) emitm_fl_3((pc), emit_b110, emit_b000, (sti))746 747 /* FMULP Mul ST(i) = ST * ST(i); POP */748 # define emitm_fmulp(pc, sti) emitm_fl_3((pc), emit_b110, emit_b001, (sti))749 750 /* FSUB ST = ST - ST(i) */751 752 /* FSUBRP SubR ST(i) = ST - ST(i); POP */753 # define emitm_fsubrp(pc, sti) emitm_fl_3((pc), emit_b110, emit_b100, (sti))754 755 /* FSUBP Sub ST(i) = ST(i) - ST; POP */756 # define emitm_fsubp(pc, sti) emitm_fl_3((pc), emit_b110, emit_b101, (sti))757 758 /* FDIVRP DivR ST(i) = ST(i) / ST(0); POP */759 # define emitm_fdivrp(pc, sti) emitm_fl_3((pc), emit_b110, emit_b110, (sti))760 761 /* FDIVP Div ST(i) = ST(0) / ST(i); POP ST(0) */762 # define emitm_fdivp(pc, sti) emitm_fl_3((pc), emit_b110, emit_b111, (sti))763 764 /* 0xDF OPS: FCOMIP, FUCOMIP PPRO */765 766 /* Negate - called change sign */767 # define emitm_fchs(pc) emitm_fl_4((pc), 0)768 769 /* ABS - ST(0) = ABS(ST(0)) */770 # define emitm_fabs(pc) emitm_fl_4((pc), 1)771 772 /* Comparisons */773 774 # define emitm_fcom(pc, sti) emitm_fl_3((pc), emit_b000, emit_b010, (sti))775 776 # define emitm_fcomp(pc, sti) emitm_fl_3((pc), emit_b000, emit_b011, (sti))777 778 #ifdef PARROT_HAS_JIT_FCOMIP779 # define emitm_fcomip(pc, sti) emitm_fl_3((pc), emit_b111, emit_b110, (sti))780 # define emitm_fcomi(pc, sti) emitm_fl_3((pc), emit_b011, emit_b110, (sti))781 #else782 # define emitm_fcomip(pc, sti) do { \783 emitm_fcomp((pc), (sti)); \784 emitm_fstw(pc); \785 emitm_sahf(pc); \786 } while (0)787 # define emitm_fcomi(pc, sti) do { \788 emitm_fcom((pc), (sti)); \789 emitm_fstw(pc); \790 emitm_sahf(pc); \791 } while (0)792 #endif793 794 # define emitm_fcompp(pc) { *((pc)++) = (char) 0xde; *((pc)++) = (char) 0xd9; }795 796 # define emitm_fcom_m(interp, pc, b, i, s, d) \797 emitm_fl_2((interp), (pc), emit_b10, 0, emit_b010, (b), (i), (s), (d))798 799 # define emitm_fcomp_m(interp, pc, b, i, s, d) \800 emitm_fl_2((interp), (pc), emit_b10, 0, emit_b011, (b), (i), (s), (d))801 802 /* ST -= real64 */803 # define emitm_fsub_m(interp, pc, b, i, s, d) \804 emitm_fl_2((interp), (pc), emit_b10, 0, emit_b100, (b), (i), (s), (d))805 806 /* ST -= int32_mem */807 # define emitm_fisub_m(interp, pc, b, i, s, d) \808 emitm_fl_2((interp), (pc), emit_b01, 0, emit_b100, (b), (i), (s), (d))809 810 # define emitm_fadd_m(interp, pc, b, i, s, d) \811 emitm_fl_2((interp), (pc), emit_b10, 0, emit_b000, (b), (i), (s), (d))812 813 /* ST += int32_mem */814 # define emitm_fiadd_m(interp, pc, b, i, s, d) \815 emitm_fl_2((interp), (pc), emit_b01, 0, emit_b000, (b), (i), (s), (d))816 817 /* ST *= real64 */818 # define emitm_fmul_m(interp, pc, b, i, s, d) \819 emitm_fl_2((interp), (pc), emit_b10, 0, emit_b001, (b), (i), (s), (d))820 821 /* ST *= int32_mem */822 # define emitm_fimul_m(interp, pc, b, i, s, d) \823 emitm_fl_2((interp), (pc), emit_b01, 0, emit_b001, (b), (i), (s), (d))824 825 /* ST /= real64 */826 # define emitm_fdiv_m(interp, pc, b, i, s, d) \827 emitm_fl_2((interp), (pc), emit_b10, 0, emit_b110, (b), (i), (s), (d))828 829 /* ST /= int32_mem */830 # define emitm_fidiv_m(interp, pc, b, i, s, d) \831 emitm_fl_2((interp), (pc), emit_b01, 0, emit_b110, (b), (i), (s), (d))832 833 /* Ops Needed to support loading EFLAGs for conditional branches */834 # define emitm_fstw(pc) emitm_fl_3((pc), emit_b111, emit_b100, emit_b000)835 836 # define emitm_sahf(pc) *((pc)++) = (char) 0x9e837 838 /* misc float */839 # define emitm_ftst(pc) { *(pc)++ = 0xd9; *(pc)++ = 0xE4; }840 # define emitm_fprem(pc) { *(pc)++ = 0xd9; *(pc)++ = 0xF8; }841 # define emitm_fprem1(pc) { *(pc)++ = 0xd9; *(pc)++ = 0xF5; }842 843 # define emitm_fldcw(interp, pc, mem) \844 emitm_fl_2((interp), (pc), emit_b00, 1, emit_b101, 0, 0, 0, (mem))845 846 #if defined(NEG_MINUS_ZERO)847 # define jit_emit_neg_r_n(pc, r) { \848 if (r) { \849 emitm_fld((pc), (r)); \850 } \851 emitm_fchs(pc); \852 if (r) { \853 emitm_fstp((pc), ((r)+1)); \854 } \855 }856 857 # define jit_emit_neg_M_n(interp, pc, mem) { \858 jit_emit_fload_mb_n((interp), (pc), emit_EBX, (mem)); \859 emitm_fchs(pc); \860 jit_emit_fstore_mb_n((interp), (pc), emit_EBX, (mem)); \861 }862 863 #elif defined(NEG_ZERO_SUB)864 865 # define jit_emit_neg_r_n(pc, r) { \866 emitm_fldz(pc); \867 emitm_fsubrp((pc), ((r)+1)); \868 }869 870 # define jit_emit_neg_M_n(interp, pc, mem) { \871 jit_emit_fload_mb_n((interp), (pc), emit_EBX, (mem)); \872 emitm_fldz(pc); \873 emitm_fsubrp((pc), 1); \874 jit_emit_fstore_mb_n((interp), (pc), emit_EBX, (mem)); \875 }876 #else877 878 # define jit_emit_neg_r_n(pc, r) { \879 if (r) { \880 emitm_fld((pc), (r)); \881 } \882 emitm_ftst(pc); \883 emitm_fstw(pc); \884 emitm_sahf(pc); \885 emitm_jxs((pc), emitm_jz, 2); \886 emitm_fchs(pc); \887 if (r) { \888 emitm_fstp((pc), ((r)+1)); \889 } \890 }891 892 # define jit_emit_neg_M_n(interp, pc, mem) { \893 jit_emit_fload_mb_n((interp), (pc), emit_EBX, (mem)); \894 emitm_ftst(pc); \895 emitm_fstw(pc); \896 emitm_sahf(pc); \897 emitm_jxs((pc), emitm_jz, 2); \898 emitm_fchs(pc); \899 jit_emit_fstore_mb_n((interp), (pc), emit_EBX, (mem)); \900 }901 #endif902 903 # define jit_emit_sin_r_n(pc, r) \904 if (r) { \905 emitm_fld((pc), (r)); \906 } \907 emitm_fsin(pc); \908 if (r) { \909 emitm_fstp((pc), ((r)+1)); \910 }911 912 # define jit_emit_cos_r_n(pc, r) \913 if (r) { \914 emitm_fld((pc), (r)); \915 } \916 emitm_fcos(pc); \917 if (r) { \918 emitm_fstp((pc), ((r)+1)); \919 }920 921 # define jit_emit_sqrt_r_n(pc, r) \922 if (r) { \923 emitm_fld((pc), (r)); \924 } \925 emitm_fsqrt(pc); \926 if (r) { \927 emitm_fstp((pc), ((r)+1)); \928 }929 930 # define jit_emit_abs_r_n(pc, r) { \931 if (r) { \932 emitm_fld((pc), (r)); \933 } \934 emitm_fabs(pc); \935 if (r) { \936 emitm_fstp((pc), ((r)+1)); \937 } \938 }939 940 # define jit_emit_abs_r_i(pc, r) { \941 jit_emit_test_r_i((pc), (r)); \942 emitm_jxs((pc), emitm_jns, 3); \943 jit_emit_not_r_i((pc), (r)); \944 jit_emit_inc_r_i((pc), (r)); \945 }946 947 # define jit_emit_abs_m_n(interp, pc, mem) { \948 jit_emit_fload_m_n((interp), (pc), (mem)); \949 emitm_fabs(pc); \950 jit_emit_fstore_m_n((pc), (mem)); \951 }952 953 /* Integer comparisons */954 # define jit_emit_cmp_rr(pc, reg1, reg2) \955 emitm_alul_r_r((pc), 0x39, (reg2), (reg1))956 # define jit_emit_cmp_rr_i(pc, r1, r2) jit_emit_cmp_rr((pc), (r1), (r2))957 958 # define emitm_cmpl_r_m(pc, reg, b, i, s, d) \959 emitm_alul_r_m((pc), 0x3b, (reg), (b), (i), (s), (d))960 961 # define emitm_cmpl_m_r(pc, reg, b, i, s, d) \962 emitm_alul_r_m((pc), 0x39, (reg), (b), (i), (s), (d))963 964 # define jit_emit_cmp_ri_i(interp, pc, reg, imm) \965 emitm_alul_i_r((pc), 0x81, emit_b111, (imm), (reg))966 967 /* Unconditional Jump/Call */968 969 # define emitm_call_cfunc(pc, func) emitm_calll((pc), (char *)(func) - (pc) - 4)970 971 # define emitm_calll(pc, disp) { \972 *((pc)++) = (char) 0xe8; \973 *(long *)(pc) = (disp); (pc) += 4; }974 975 # define emitm_callr(pc, reg) { \976 *((pc)++) = (char) 0xff; \977 *((pc)++) = (char) 0xd0 | ((reg) - 1); }978 979 # define emitm_callm(pc, b, i, s, d) { \980 *((pc)++) = (char) 0xff; \981 (pc) = emit_r_X((interp), (pc), emit_reg(emit_b010), (b), (i), (s), (d)); }982 983 # define emitm_jumps(pc, disp) { \984 *((pc)++) = (char) 0xeb; \985 *((pc)++) = (disp); }986 987 # define emitm_jumpl(pc, disp) { \988 *((pc)++) = (char) 0xe9; \989 *(long *)(pc) = (disp); (pc) += 4; }990 991 # define emitm_jumpr(pc, reg) { \992 *((pc)++) = (char) 0xff; \993 *((pc)++) = (char)(0xe0 | ((reg) - 1)); }994 995 # define emitm_jumpm(pc, b, i, s, d) { \996 *((pc)++) = (char) 0xff; \997 (pc) = emit_r_X((interp), (pc), emit_reg(emit_b100), (b), (i), (s), (d)); }998 999 /* Conditional jumps */1000 1001 /* Short jump - 8 bit disp */1002 # define emitm_jxs(pc, code, disp) { \1003 *((pc)++) = (char)(0x70 | (code)); \1004 *((pc)++) = (char)(disp); }1005 1006 /* Long jump - 32 bit disp */1007 # define emitm_jxl(pc, code, disp) { \1008 *((pc)++) = (char) 0x0f; \1009 *((pc)++) = (char)(0x80 | (code)); \1010 *(long *)(pc) = (disp); (pc) += 4; }1011 1012 # define emitm_jo 01013 # define emitm_jno 11014 # define emitm_jb 21015 # define emitm_jnb 31016 # define emitm_jz 41017 # define emitm_je emitm_jz1018 # define emitm_jnz 51019 # define emitm_jne emitm_jnz1020 # define emitm_jbe 61021 # define emitm_ja 71022 # define emitm_js 81023 # define emitm_jns 91024 # define emitm_jp 101025 # define emitm_jnp 111026 # define emitm_jl 121027 # define emitm_jnl 131028 # define emitm_jle 141029 # define emitm_jg 151030 1031 /* set byte conditional */1032 # define jit_emit_setcc_r(pc, cc, r) \1033 *(pc)++ = 0x0f; \1034 *(pc)++ = 0x90 + (cc); \1035 *(pc)++ = (char) emit_alu_X_r(0, (r))1036 1037 41 /* 1038 * core.jit interface1039 *1040 * The new offset based versions have uppercase RM or MR inside1041 * That's probably only during transition time1042 */1043 1044 # define jit_emit_mov_mi_i(pc, dest, immediate) \1045 emitm_movl_i_m((pc), (immediate), emit_None, emit_None, emit_None, (dest))1046 1047 # define jit_emit_mov_MI_i(interp, pc, offs, immediate) \1048 emitm_movl_i_m((pc), (immediate), emit_EBX, emit_None, 1, (offs))1049 1050 # define jit_emit_mov_rm_i(interp, pc, reg, address) \1051 emitm_movl_m_r((interp), (pc), (reg), emit_None, emit_None, emit_None, (address))1052 1053 # define jit_emit_mov_RM_i(interp, pc, reg, offs) \1054 emitm_movl_m_r((interp), (pc), (reg), emit_EBX, emit_None, 1, (offs))1055 1056 # define jit_emit_mov_mr_i(interp, pc, address, reg) \1057 emitm_movl_r_m((interp), (pc), (reg), emit_None, emit_None, emit_None, (address))1058 1059 # define jit_emit_mov_MR_i(interp, pc, offs, reg) \1060 emitm_movl_r_m((interp), (pc), (reg), emit_EBX, emit_None, 1, (offs))1061 1062 # define jit_emit_mul_RM_i(interp, pc, reg, offs) \1063 emitm_smull_r_m((pc), (reg), emit_EBX, emit_None, 1, (offs))1064 1065 # define jit_emit_sub_RM_i(interp, pc, reg, offs) \1066 emitm_subl_m_r((pc), (reg), emit_EBX, emit_None, 1, (offs))1067 1068 # define jit_emit_sub_MR_i(interp, pc, offs, reg) \1069 emitm_subl_r_m((pc), (reg), emit_EBX, emit_None, 1, (offs))1070 1071 # define jit_emit_sub_MI_i(pc, offs, imm) \1072 emitm_subl_i_m((pc), (imm), emit_EBX, emit_None, 1, (offs))1073 1074 # define jit_emit_add_RM_i(interp, pc, reg, offs) \1075 emitm_addl_m_r((pc), (reg), emit_EBX, emit_None, 1, (offs))1076 1077 # define jit_emit_add_MR_i(interp, pc, offs, reg) \1078 emitm_addl_r_m((pc), (reg), emit_EBX, emit_None, 1, (offs))1079 1080 # define jit_emit_add_MI_i(pc, offs, imm) \1081 emitm_addl_i_m((pc), (imm), emit_EBX, emit_None, 1, (offs))1082 1083 # define jit_emit_cmp_rm_i(pc, reg, address) \1084 emitm_cmpl_r_m((pc), (reg), emit_None, emit_None, emit_None, (address))1085 1086 # define jit_emit_cmp_RM_i(interp, pc, reg, offs) \1087 emitm_cmpl_r_m((pc), (reg), emit_EBX, emit_None, 1, (offs))1088 1089 # define jit_emit_cmp_MR_i(interp, pc, offs, reg) \1090 emitm_cmpl_m_r((pc), (reg), emit_EBX, emit_None, 1, (offs))1091 1092 /* high level routines, behave like real 2 register FP */1093 1094 /* mapped float registers numbers are ST(1)-ST(4).1095 * scratch register is ST(0)1096 */1097 1098 /* ST(i) <- numvar */1099 # define jit_emit_mov_RM_n(interp, pc, r, d) { \1100 jit_emit_fload_mb_n((interp), (pc), emit_EBX, (d)); \1101 emitm_fstp((pc), ((r)+1)); \1102 }1103 1104 /* ST(i) <= NUM_CONST */1105 # define jit_emit_mov_ri_n(interp, pc, r, i) { \1106 jit_emit_fload_m_n((interp), (pc), (i)); \1107 emitm_fstp((pc), ((r)+1)); \1108 }1109 1110 /* ST(i) <= &INT_CONST */1111 # define jit_emit_mov_ri_ni(interp, pc, r, i) { \1112 jit_emit_fload_m_i((interp), (pc), (i)); \1113 emitm_fstp((pc), ((r)+1)); \1114 }1115 1116 /* ST(i) <= INT_REG */1117 # define jit_emit_mov_RM_ni(interp, pc, r, i) { \1118 jit_emit_fload_mb_i((interp), (pc), (i)); \1119 emitm_fstp((pc), ((r)+1)); \1120 }1121 1122 /* NUM_REG(i) <= &INT_CONST1123 * the int const i is loaded from the code memory1124 */1125 # define jit_emit_mov_MI_ni(interp, pc, offs, i) { \1126 jit_emit_fload_m_i((interp), (pc), (i)); \1127 jit_emit_fstore_mb_n((interp), (pc), emit_EBX, (offs)); \1128 }1129 1130 /* INT_REG <= ST(i) */1131 # define jit_emit_mov_mr_in(pc, mem, r) { \1132 emitm_fld((pc), (r)); \1133 jit_emit_fstore_m_i((pc), (mem)); \1134 }1135 1136 /* numvar <- ST(i) */1137 # define jit_emit_mov_mr_n(pc, d, r) { \1138 emitm_fld((pc), (r)); \1139 jit_emit_fstore_m_n((pc), (d)); \1140 }1141 1142 # define jit_emit_mov_MR_n(interp, pc, d, r) { \1143 if (r) { \1144 emitm_fld((pc), (r)); \1145 jit_emit_fstore_mb_n((interp), (pc), emit_EBX, (d)); \1146 } \1147 else { \1148 jit_emit_fst_mb_n((interp), (pc), emit_EBX, (d)); \1149 } \1150 }1151 1152 /* ST(r1) <= ST(r2) */1153 # define jit_emit_mov_rr_n(pc, r1, r2) { \1154 if ((r1) != (r2)) { \1155 if (r2) { \1156 emitm_fld((pc), (r2)); \1157 emitm_fstp((pc), ((r1)+1)); \1158 } \1159 else { \1160 emitm_fst((pc), (r1)); \1161 } \1162 } \1163 }1164 1165 /* ST(r1) xchg ST(r2) */1166 # define jit_emit_xchg_rr_n(interp, pc, r1, r2) { \1167 if ((r1) != (r2)) { \1168 emitm_fld((pc), (r1)); \1169 emitm_fld((pc), ((r2)+1)); \1170 emitm_fstp((pc), ((r1)+2)); \1171 emitm_fstp((pc), ((r2)+1)); \1172 } \1173 }1174 1175 # define jit_emit_xchg_RM_n(interp, pc, r, offs) { \1176 emitm_fld((pc), (r)); \1177 jit_emit_fload_mb_n((interp), (pc), emit_EBX, (offs)); \1178 emitm_fstp((pc), ((r)+2)); \1179 jit_emit_fstore_mb_n((interp), (pc), emit_EBX, (offs)); \1180 }1181 1182 # define jit_emit_xchg_MR_n(interp, pc, offs, r) { \1183 emitm_fld((pc), (r)); \1184 jit_emit_fload_mb_n((interp), (pc), emit_EBX, (offs)); \1185 emitm_fstp((pc), ((r)+2)); \1186 jit_emit_fstore_mb_n((interp), (pc), emit_EBX, (offs)); \1187 }1188 1189 # define jit_emit_finit(pc) { *((pc)++) = (char) 0xdb; *((pc)++) = (char) 0xe3; }1190 1191 /* ST(i) op= MEM */1192 1193 # define jit_emit_xxx_rm_n(interp, op, pc, r, m) { \1194 jit_emit_fload_m_n((interp), (pc), (m)); \1195 emitm_f ## op ## p((pc), ((r)+1)); \1196 }1197 1198 # define jit_emit_xxx_RM_n(interp, op, pc, r, offs) { \1199 jit_emit_fload_mb_n((interp), (pc), emit_EBX, (offs)); \1200 emitm_f ## op ## p((pc), ((r)+1)); \1201 }1202 1203 /*1204 * float ops in two flavors: abs memory for constants, offsets for regs1205 */1206 1207 # define jit_emit_add_ri_n(interp, pc, r, m) jit_emit_xxx_rm_n((interp), add, (pc), (r), (m))1208 # define jit_emit_sub_ri_n(interp, pc, r, m) jit_emit_xxx_rm_n((interp), sub, (pc), (r), (m))1209 # define jit_emit_mul_ri_n(interp, pc, r, m) jit_emit_xxx_rm_n((interp), mul, (pc), (r), (m))1210 1211 # define jit_emit_add_RM_n(interp, pc, r, o) jit_emit_xxx_RM_n((interp), add, (pc), (r), (o))1212 # define jit_emit_sub_RM_n(interp, pc, r, o) jit_emit_xxx_RM_n((interp), sub, (pc), (r), (o))1213 # define jit_emit_mul_RM_n(interp, pc, r, o) jit_emit_xxx_RM_n((interp), mul, (pc), (r), (o))1214 1215 /* ST(r1) += ST(r2) */1216 /* r1 == 0: ST(0) <- ST(0) + ST(i)1217 * r2 == 0: ST(i) <- ST(0) + ST(i)1218 */1219 # define jit_emit_add_rr_n(interp, pc, r1, r2) do { \1220 if (!(r1)) { \1221 emitm_fadd((pc), (r2)); \1222 } \1223 else if (!(r2)) { \1224 emitm_faddr((pc), (r1)); \1225 } \1226 else { \1227 emitm_fld((pc), (r2)); \1228 emitm_faddp((pc), ((r1)+1)); \1229 } \1230 } \1231 while (0)1232 /*1233 * ST(r) += INT_REG1234 */1235 # define jit_emit_add_RM_ni(pc, r, offs) { \1236 emitm_fld((pc), (r)); \1237 emitm_fiadd_m((pc), emit_EBX, 0, 1, (offs)); \1238 emitm_fstp((pc), ((r)+1)); \1239 }1240 1241 /* ST(r1) -= ST(r2) */1242 /* r1 == 0: ST(0) <- ST(0) - ST(i)1243 * r2 == 0: ST(i) <- ST(i) - ST(0)1244 */1245 # define jit_emit_sub_rr_n(interp, pc, r1, r2) do { \1246 if (!(r1)) { \1247 emitm_fsub((pc), (r2)); \1248 } \1249 else if (!(r2)) { \1250 emitm_fsubr((pc), (r1)); \1251 } \1252 else { \1253 emitm_fld((pc), (r2)); \1254 emitm_fsubp((pc), ((r1)+1)); \1255 } \1256 } \1257 while (0)1258 1259 /*1260 * ST(r) -= INT_REG1261 */1262 # define jit_emit_sub_RM_ni(pc, r, offs) { \1263 emitm_fld((pc), (r)); \1264 emitm_fisub_m((pc), emit_EBX, 0, 1, (offs)); \1265 emitm_fstp((pc), ((r)+1)); \1266 }1267 1268 # define jit_emit_inc_r_n(pc, r) { \1269 emitm_fld1(pc); \1270 emitm_faddp((pc), ((r)+1)); \1271 }1272 1273 # define jit_emit_dec_r_n(pc, r) { \1274 emitm_fld1(pc); \1275 emitm_fsubp((pc), ((r)+1)); \1276 }1277 1278 /* ST(r1) *= ST(r2) */1279 /* r1 == 0: ST(0) <- ST(0) * ST(i)1280 * r2 == 0: ST(i) <- ST(0) * ST(i)1281 */1282 # define jit_emit_mul_rr_n(interp, pc, r1, r2) do { \1283 if (!(r1)) { \1284 emitm_fmul((pc), (r2)); \1285 } \1286 else if (!(r2)) { \1287 emitm_fmulr((pc), (r1)); \1288 } \1289 else { \1290 emitm_fld((pc), (r2)); \1291 emitm_fmulp((pc), ((r1)+1)); \1292 } \1293 } \1294 while (0)1295 1296 /*1297 * ST(r) *= INT_REG1298 */1299 # define jit_emit_mul_RM_ni(pc, r, offs) { \1300 emitm_fld((pc), (r)); \1301 emitm_fimul_m((pc), emit_EBX, 0, 1, (offs)); \1302 emitm_fstp((pc), ((r)+1)); \1303 }1304 1305 /*1306 * ST(r) /= INT_REG1307 */1308 # define jit_emit_div_RM_ni(pc, r, offs) { \1309 emitm_fld((pc), (r)); \1310 emitm_fidiv_m((pc), emit_EBX, 0, 1, (offs)); \1311 emitm_fstp((pc), ((r)+1)); \1312 }1313 1314 /* test r for zero */1315 # define jit_emit_test_r_n(pc, r) { \1316 if (r) { \1317 emitm_fxch((pc), (r)); \1318 } \1319 emitm_fxam(pc); \1320 emitm_fstw(pc); \1321 emitm_sahf(pc); \1322 if (r) { \1323 emitm_fxch((pc), (r)); \1324 } \1325 }1326 1327 enum { JIT_X86BRANCH, JIT_X86JUMP, JIT_X86CALL };1328 1329 # define jit_emit_stack_frame_enter(pc) do { \1330 emitm_pushl_r((pc), emit_EBP); \1331 jit_emit_mov_rr_i((pc), emit_EBP, emit_ESP); \1332 } while (0)1333 1334 # define jit_emit_stack_frame_leave(pc) do { \1335 jit_emit_mov_rr_i((pc), emit_ESP, emit_EBP); \1336 emitm_popl_r((pc), emit_EBP); \1337 } while (0)1338 1339 # define jit_emit_end(pc) { \1340 jit_emit_add_ri_i((interp), (pc), emit_ESP, 4); \1341 emitm_popl_r((pc), emit_EDI); \1342 emitm_popl_r((pc), emit_ESI); \1343 emitm_popl_r((pc), emit_EBX); \1344 emitm_popl_r((pc), emit_EBP); \1345 emitm_ret(pc); \1346 }1347 1348 size_t calc_signature_needs(const char *sig, int *strings);1349 1350 void * Parrot_jit_build_call_func(PARROT_INTERP, PMC *pmc_nci,1351 STRING *signature, int *sizeptr);1352 1353 /*1354 * register usage1355 * %edi, %esi ... mapped, preserved1356 * %edx, %ecx ... mapped, not preserved1357 * %ebx ... base pointer for register access, preserved1358 * %eax ... scratch, return value register1359 */1360 1361 #endif /* PARROT_I386_JIT_EMIT_H_GUARD */1362 1363 /*1364 42 * Local variables: 1365 43 * c-file-style: "parrot" 1366 44 * End: -
src/nci_test.c
110 110 PARROT_DYNEXT_EXPORT void nci_vfff(float, float, float); 111 111 PARROT_DYNEXT_EXPORT void nci_vV(const char **); 112 112 PARROT_DYNEXT_EXPORT void nci_vVVV(const char **, const char **, const char **); 113 PARROT_DYNEXT_EXPORT int nci_i20(int, int, int, int, int, int, int, int, int, int, int, int, 114 int, int, int, int, int, int, int); 113 115 114 116 /* Declarations for callback tests */ 115 117 … … 1191 1193 *ptr3 = "Go suck a lemon.\n"; 1192 1194 } 1193 1195 1196 /* 1197 1198 =item C<int 1199 nci_i20(int sel, int v1, int v2, int v3, int v4, int v5, int v6, int v7, int v8, int v9, int v10, 1200 int v11, int v12, int v13, int v14, int v15, int v16, int v17, int v18)> 1201 1202 Prints and returns the nth value in a list of integers. First argument is the selector; subsequents, 1203 the list. 1204 1205 This function is designed to be outside of the range of the static frame builder as an excercise for 1206 the dynamic frame builder. 1207 1208 =cut 1209 1210 */ 1211 PARROT_DYNEXT_EXPORT int 1212 nci_i20(int sel, int v1, int v2, int v3, int v4, int v5, int v6, int v7, int v8, int v9, int v10, 1213 int v11, int v12, int v13, int v14, int v15, int v16, int v17, int v18) { 1214 int *selected; 1215 switch ((sel < 0 ? -sel : sel) % 18) { 1216 case 0: selected = &v1; break; 1217 case 1: selected = &v2; break; 1218 case 2: selected = &v3; break; 1219 case 3: selected = &v4; break; 1220 case 4: selected = &v5; break; 1221 case 5: selected = &v6; break; 1222 case 6: selected = &v7; break; 1223 case 7: selected = &v8; break; 1224 case 8: selected = &v9; break; 1225 case 9: selected = &v10; break; 1226 case 10: selected = &v11; break; 1227 case 11: selected = &v12; break; 1228 case 12: selected = &v13; break; 1229 case 13: selected = &v14; break; 1230 case 14: selected = &v15; break; 1231 case 15: selected = &v16; break; 1232 case 16: selected = &v17; break; 1233 case 17: selected = &v18; break; 1234 default: printf("default case reached (should never happen)"); return -1; 1235 } 1236 printf("%d\n", *selected); 1237 return *selected; 1238 } 1239 1194 1240 #ifdef TEST 1195 1241 1196 1242 char l2 = 4; -
src/extend.c
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 -
tools/build/nativecall.pl
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 43 my %sig_table = %Parrot::NativeCall::signature_table; 40 44 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 future73 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 98 99 45 my $temp_cnt = 0; 100 46 my (@put_pointer, @put_pointer_nci_too, @nci_defs); 101 47 my %seen; … … 494 440 return F2DPTR(VTABLE_get_pointer(interp, b)); 495 441 } 496 442 else { 497 int jit_size;498 void * const result = Parrot_jit_build_call_func(interp, pmc_nci, signature, & jit_size);443 void *priv; 444 void * const result = Parrot_jit_build_call_func(interp, pmc_nci, signature, &priv); 499 445 if (result) { 500 struct jit_buffer_private_data *priv;501 446 *jitted = 1; 502 447 temp_pmc = pmc_new(interp, enum_class_ManagedStruct); 503 448 VTABLE_set_pointer(interp, temp_pmc, (void *)result); 504 449 #ifdef PARROT_HAS_EXEC_PROTECT 505 priv = (struct jit_buffer_private_data *)506 mem_sys_allocate(sizeof(struct jit_buffer_private_data));507 priv->size = jit_size;508 450 SETATTR_ManagedStruct_custom_free_func(interp, temp_pmc, Parrot_jit_free_buffer); 509 451 SETATTR_ManagedStruct_custom_free_priv(interp, temp_pmc, priv); 510 452 SETATTR_ManagedStruct_custom_clone_func(interp, temp_pmc, Parrot_jit_clone_buffer); -
MANIFEST
1 1 # ex: set ro: 2 2 # $Id$ 3 3 # 4 # generated by tools/dev/mk_manifest_and_skip.pl Thu Nov 5 20:59:582009 UT4 # generated by tools/dev/mk_manifest_and_skip.pl Fri Nov 6 04:08:02 2009 UT 5 5 # 6 6 # See below for documentation on the format of this file. 7 7 # … … 234 234 config/auto/env/test_unsetenv_c.in [] 235 235 config/auto/format.pm [] 236 236 config/auto/frames.pm [] 237 config/auto/frames/test_exec_cygwin_c.in []238 config/auto/frames/test_exec_linux_c.in []239 config/auto/frames/test_exec_openbsd_c.in []240 237 config/auto/gc.pm [] 241 238 config/auto/gc/test_c.in [] 242 239 config/auto/gcc.pm [] … … 258 255 config/auto/isreg.pm [] 259 256 config/auto/isreg/test_c.in [] 260 257 config/auto/jit.pm [] 258 config/auto/libjit.pm [] 259 config/auto/libjit/libjit_c.in [] 261 260 config/auto/memalign.pm [] 262 261 config/auto/memalign/test2_c.in [] 263 262 config/auto/memalign/test_c.in [] … … 310 309 config/gen/crypto.pm [] 311 310 config/gen/crypto/digest_pmc.in [] 312 311 config/gen/crypto/digest_t.in [] 312 config/gen/libjit.pm [] 313 config/gen/libjit/frame_builder_libjit_c.in [] 314 config/gen/libjit/frame_builder_libjit_h.in [] 313 315 config/gen/makefiles.pm [] 314 316 config/gen/makefiles/CFLAGS.in [] 315 317 config/gen/makefiles/data_json.in [] … … 1065 1067 lib/Parrot/IO/Path.pm [devel]lib 1066 1068 lib/Parrot/Install.pm [devel]lib 1067 1069 lib/Parrot/Manifest.pm [devel]lib 1070 lib/Parrot/NativeCall.pm [devel]lib 1068 1071 lib/Parrot/Op.pm [devel]lib 1069 1072 lib/Parrot/OpTrans.pm [devel]lib 1070 1073 lib/Parrot/OpTrans/C.pm [devel]lib … … 1269 1272 src/exceptions.c [] 1270 1273 src/exit.c [] 1271 1274 src/extend.c [] 1272 src/frame_builder.c []1273 1275 src/frame_builder.h [] 1274 1276 src/gc/alloc_memory.c [] 1275 1277 src/gc/alloc_resources.c [] … … 1940 1942 t/steps/auto/inline-01.t [test] 1941 1943 t/steps/auto/isreg-01.t [test] 1942 1944 t/steps/auto/jit-01.t [test] 1945 t/steps/auto/libjit-01.t [test] 1943 1946 t/steps/auto/memalign-01.t [test] 1944 1947 t/steps/auto/msvc-01.t [test] 1945 1948 t/steps/auto/neg_0-01.t [test] … … 1964 1967 t/steps/gen/config_pm-01.t [test] 1965 1968 t/steps/gen/core_pmcs-01.t [test] 1966 1969 t/steps/gen/crypto-01.t [test] 1970 t/steps/gen/libjit-01.t [test] 1967 1971 t/steps/gen/makefiles-01.t [test] 1968 1972 t/steps/gen/opengl-01.t [test] 1969 1973 t/steps/gen/parrot_include-01.t [test] -
lib/Parrot/Configure/Options/Conf.pm
105 105 --without-gmp Build parrot without GMP support 106 106 --without-opengl Build parrot without OpenGL support (GL/GLU/GLUT) 107 107 --without-pcre Build parrot without pcre support 108 --without-libjit Build parrot without LibJIT support 108 109 109 110 ICU Options: 110 111 -
lib/Parrot/Configure/Options/Conf/Shared.pm
75 75 without-gettext 76 76 without-gmp 77 77 without-icu 78 without-libjit 78 79 without-opengl 79 80 without-pcre 80 81 without-threads -
lib/Parrot/Configure/Step/List.pm
39 39 auto::format 40 40 auto::isreg 41 41 auto::arch 42 auto::libjit 42 43 auto::jit 43 44 auto::frames 44 45 auto::cpu … … 70 71 gen::parrot_include 71 72 gen::opengl 72 73 gen::call_list 74 gen::libjit 73 75 gen::makefiles 74 76 gen::platform 75 77 gen::config_pm 76 78 ); 77 79 80 =pod 81 82 =cut 83 78 84 sub get_steps_list { return @steps; } 79 85 80 86 1; -
lib/Parrot/Distribution.pm
433 433 include/parrot/config.h 434 434 include/parrot/has_header.h 435 435 src/gc/malloc.c 436 src/frame_builder_libjit.h 437 src/frame_builder_libjit.c 436 438 } unless @exemptions; 437 439 438 440 my $path = -f $file ? $file : $file->path; -
lib/Parrot/NativeCall.pm
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: -
include/parrot/nci.h
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 */ -
t/pmc/nci.t
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 => (71 + @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() ); … … 2753 2785 Go suck a lemon. 2754 2786 OUTPUT 2755 2787 2788 my $test_code = <<'CODE'; 2789 .sub test :main 2790 .local pmc libnci_test 2791 $S0 = 'libnci_test' 2792 libnci_test = loadlib $S0 2793 2794 .local pmc nci_i20 2795 nci_i20 = dlfunc libnci_test, "nci_i20", "iiiiiiiiiiiiiiiiiiii" 2796 2797 .local pmc args 2798 args = new ['FixedIntegerArray'] 2799 args = 18 2800 2801 $I0 = 2 2802 args[0] = 1 2803 args[1] = 1 2804 2805 LOOP1: 2806 $I1 = $I0 - 1 2807 $I1 = args[$I1] 2808 2809 $I2 = $I0 - 2 2810 $I2 = args[$I2] 2811 2812 $I3 = $I1 + $I2 2813 args[$I0] = $I3 2814 inc $I0 2815 if $I0 < 18 goto LOOP1 2816 2817 $I0 = args 2818 dec $I0 2819 2820 $I1 = args[0] 2821 $I2 = args[1] 2822 $I3 = args[2] 2823 $I4 = args[3] 2824 $I5 = args[4] 2825 $I6 = args[5] 2826 $I7 = args[6] 2827 $I8 = args[7] 2828 $I9 = args[8] 2829 $I10 = args[9] 2830 $I11 = args[10] 2831 $I12 = args[11] 2832 $I13 = args[12] 2833 $I14 = args[13] 2834 $I15 = args[14] 2835 $I16 = args[15] 2836 $I17 = args[16] 2837 $I18 = args[17] 2838 2839 LOOP2: 2840 nci_i20($I0, $I1, $I2, $I3, $I4, $I5, $I6, $I7, $I8, $I9, $I10, $I11, $I12, $I13, $I14, $I15, $I16, $I17, $I18) 2841 $I0 = $I0 / 2 2842 if $I0 > 0 goto LOOP2 2843 .end 2844 CODE 2845 if ($PConfig{cc_build_call_frames}) { 2846 pir_output_is($test_code, <<DYNAMIC_FRAMEBUILDER_OUTPUT, 'dynamic frame builder builds ridiculous call frames'); 2847 2584 2848 34 2849 5 2850 2 2851 1 2852 DYNAMIC_FRAMEBUILDER_OUTPUT 2853 } else { 2854 my $output_re = qr/^Parrot VM: PANIC: iiiiiiiiiiiiiiiiiiii is an unknown signature type./; 2855 pir_error_output_like($test_code, $output_re, "static frame builder can't build ridiculous signatures"); 2856 } 2857 2756 2858 # Local Variables: 2757 2859 # mode: cperl 2758 2860 # cperl-indent-level: 4 -
t/steps/auto/libjit-01.t
1 #! perl 2 # Copyright (C) 2009, Parrot Foundation. 3 # $Id$ 4 # auto/libjit-01.t 5 6 use strict; 7 use warnings; 8 9 use Test::More tests => 34; 10 use lib qw( lib t/configure/testlib ); 11 use Parrot::Configure; 12 use Parrot::Configure::Options 'process_options'; 13 use Parrot::Configure::Test qw( 14 test_step_thru_runstep 15 rerun_defaults_for_testing 16 test_step_constructor_and_description 17 ); 18 use IO::CaptureOutput qw( capture ); 19 20 use_ok('config::init::defaults'); 21 use_ok('config::auto::libjit'); 22 23 my ($args, $step_list_ref) = process_options( { 24 argv => [ q{--without-libjit} ], 25 mode => 'configure', 26 } ); 27 28 my $conf = Parrot::Configure->new; 29 30 my $serialized = $conf->pcfreeze(); 31 32 test_step_thru_runstep( $conf, 'init::defaults', $args ); 33 34 my $pkg = 'auto::libjit'; 35 my ( $step, $ret ); 36 37 $conf->add_steps($pkg); 38 $conf->options->set(%$args); 39 $step = test_step_constructor_and_description($conf); 40 $ret = $step->runstep($conf); 41 ok( $ret, "runstep() returned true value" ); 42 is( $step->result(), 'no', "Result is 'no', as expected" ); 43 is( $conf->data->get( 'HAS_LIBJIT' ), 0, 44 "Got expected result with --without-libjit option" ); 45 $conf->cc_clean(); 46 47 $conf->replenish($serialized); 48 49 ($args, $step_list_ref) = process_options( { 50 argv => [ ], 51 mode => q{configure}, 52 } ); 53 rerun_defaults_for_testing($conf, $args ); 54 $conf->add_steps($pkg); 55 $conf->options->set( %{$args} ); 56 $step = test_step_constructor_and_description($conf); 57 $ret = $step->runstep($conf); 58 ok( $ret, "runstep() returned true value" ); 59 like( $step->result(), qr/yes|no/, "Result is either 'yes' or 'no'" ); 60 ok( defined( $conf->data->get( 'HAS_LIBJIT' ) ), 61 "'HAS_LIBJIT' has defined value" ); 62 $conf->cc_clean(); 63 64 ########## _evaluate_cc_run ########## 65 66 my ($test, $has_libjit, $verbose); 67 68 $step->set_result( undef ); 69 70 $test = q{USES INTERPRETER: 33}; 71 $has_libjit = 0; 72 $verbose = 0; 73 $has_libjit = $step->_evaluate_cc_run($test, $has_libjit, $verbose); 74 ok( $has_libjit, "_evaluate_cc_run() returned true value, as expected" ); 75 is( $step->result(), 'yes', "result is yes, as expected" ); 76 77 $step->set_result( undef ); 78 79 $test = q{foobar}; 80 $has_libjit = 0; 81 $verbose = 0; 82 $has_libjit = $step->_evaluate_cc_run($test, $has_libjit, $verbose); 83 ok( ! $has_libjit, "_evaluate_cc_run() returned false value, as expected" ); 84 ok( ! defined($step->result()), "result is undefined, as expected" ); 85 86 $step->set_result( undef ); 87 88 $test = q{USES INTERPRETER: 33}; 89 $has_libjit = 0; 90 $verbose = 1; 91 { 92 my ($stdout, $stderr); 93 capture( 94 sub { $has_libjit = 95 $step->_evaluate_cc_run($test, $has_libjit, $verbose); }, 96 \$stdout, 97 \$stderr, 98 ); 99 ok( $has_libjit, "_evaluate_cc_run() returned true value, as expected" ); 100 is( $step->result(), 'yes', "result is yes, as expected" ); 101 like( $stdout, qr/\(yes\)/, "Got expected verbose output" ); 102 } 103 104 ########## _handle_has_libjit() ########## 105 106 my $extra_libs; 107 108 $conf->data->set( 'libjit_has_alloca' => undef ); 109 $conf->data->set( 'libs' => '' ); 110 111 $has_libjit = 1; 112 $extra_libs = 'mylibs'; 113 $conf->data->set( 'cpuarch' => 'i386' ); 114 115 auto::libjit::_handle_has_libjit($conf, $has_libjit, $extra_libs); 116 ok( $conf->data->get( 'libjit_has_alloca'), 117 "on i386 with libJIT, 'libjit_has_alloca' has true value" ); 118 is( $conf->data->get( 'libs' ), " $extra_libs", 119 "Got expected value for libs" ); 120 121 $conf->data->set( 'libjit_has_alloca' => undef ); 122 $conf->data->set( 'libs' => '' ); 123 124 $has_libjit = 1; 125 $extra_libs = 'mylibs'; 126 $conf->data->set( 'cpuarch' => 'ppc' ); 127 128 auto::libjit::_handle_has_libjit($conf, $has_libjit, $extra_libs); 129 ok( ! $conf->data->get( 'libjit_has_alloca'), 130 "on non-i386 with libJIT, 'libjit_has_alloca' has false value" ); 131 is( $conf->data->get( 'libs' ), " $extra_libs", 132 "Got expected value for libs" ); 133 134 $conf->data->set( 'libjit_has_alloca' => undef ); 135 $conf->data->set( 'libs' => '' ); 136 137 $has_libjit = 0; 138 $extra_libs = 'mylibs'; 139 140 auto::libjit::_handle_has_libjit($conf, $has_libjit, $extra_libs); 141 ok( ! $conf->data->get( 'libjit_has_alloca'), 142 "without libJIT, 'libjit_has_alloca' has false value" ); 143 is( $conf->data->get( 'libs' ), "", 144 "Got expected value for libs" ); 145 146 ################### DOCUMENTATION ################### 147 148 =head1 NAME 149 150 auto/libjit-01.t - test auto::libjit 151 152 =head1 SYNOPSIS 153 154 % prove t/steps/auto/libjit-01.t 155 156 =head1 DESCRIPTION 157 158 The files in this directory test functionality used by F<Configure.pl>. 159 160 The tests in this file test auto::libjit. 161 162 =head1 SEE ALSO 163 164 config::auto::libjit, F<Configure.pl>. 165 166 =cut 167 168 # Local Variables: 169 # mode: cperl 170 # cperl-indent-level: 4 171 # fill-column: 100 172 # End: 173 # vim: expandtab shiftwidth=4: -
t/steps/auto/frames-01.t
5 5 6 6 use strict; 7 7 use warnings; 8 use Test::More tests => 2 7;8 use Test::More tests => 28; 9 9 use lib qw( lib t/configure/testlib ); 10 10 use_ok('config::init::defaults'); 11 11 use_ok('config::auto::frames'); … … 33 33 $conf->options->set( %{$args} ); 34 34 my $step = test_step_constructor_and_description($conf); 35 35 36 # To avoid a warning about an unitialized value, we will set nvsize to 8, 37 # cpuarch to i386 and osname to linux. 36 # To avoid a warning about an uninitialized value, we will set osname to linux. 38 37 # This is normally done during earlier configuration steps. 39 $conf->data->set( nvsize => 8 );40 $conf->data->set( cpuarch => 'i386' );41 38 $conf->data->set( osname => 'linux' ); 42 39 40 $conf->data->set( HAS_LIBJIT => 1 ); 43 41 my $ret = $step->runstep($conf); 44 42 ok( $ret, "runstep() returned true value" ); 45 43 ok( defined ( $step->result() ), 46 44 "Got defined result" ); 47 TODO: { 48 local $TODO = 49 'build frames temporarily disabled at pcc_reapply merge: TT #1132'; 50 is( $step->result(), 'yes', "Result is 'yes', as expected" ); 51 } 45 is( $step->result(), 'yes', "Result is 'yes', as expected" ); 46 47 $conf->data->set( HAS_LIBJIT => undef ); 48 $ret = $step->runstep($conf); 49 ok( $ret, "runstep() returned true value" ); 50 ok( defined ( $step->result() ), 51 "Got defined result" ); 52 is( $step->result(), 'no', "Result is 'no', as expected" ); 53 52 54 $conf->cc_clean(); 53 55 $step->set_result( undef ); 54 56 … … 68 70 ok( ! $can_build_call_frames, 69 71 "_call_frames_buildable() returned false value, as expected" ); 70 72 73 $conf->data->set( HAS_LIBJIT => 1 ); 71 74 $conf->options->set( buildframes => undef ); 72 $conf->data->set( osname => 'linux' );73 $conf->data->set( cpuarch => 'i386' );74 $conf->data->set( nvsize => 8 );75 75 $can_build_call_frames = auto::frames::_call_frames_buildable($conf); 76 TODO: { 77 local $TODO = 78 'build frames temporarily disabled at pcc_reapply merge: TT #1132'; 79 ok( $can_build_call_frames, 80 "_call_frames_buildable() returned true value, as expected (i386/non darwin/8)" 81 ); 82 } 76 ok( $can_build_call_frames, 77 "_call_frames_buildable() returned true value, as expected" ); 83 78 84 $conf->data->set( osname => 'darwin' ); 85 $conf->data->set( cpuarch => 'i386' ); 86 $conf->data->set( nvsize => 8 ); 79 $conf->data->set( HAS_LIBJIT => undef ); 80 $conf->options->set( buildframes => 0 ); 87 81 $can_build_call_frames = auto::frames::_call_frames_buildable($conf); 88 82 ok( ! $can_build_call_frames, 89 "_call_frames_buildable() returned false value, as expected (i386/darwin/8)" );83 "_call_frames_buildable() returned false value, as expected" ); 90 84 91 $conf->data->set( osname => 'linux' );92 $conf->data->set( cpuarch => 'ppc' );93 $conf->data->set( nvsize => 8 );94 $can_build_call_frames = auto::frames::_call_frames_buildable($conf);95 ok( ! $can_build_call_frames,96 "_call_frames_buildable() returned false value, as expected (ppc/linux/8)" );97 98 $conf->data->set( osname => 'linux' );99 $conf->data->set( cpuarch => 'i386' );100 $conf->data->set( nvsize => 4 );101 $can_build_call_frames = auto::frames::_call_frames_buildable($conf);102 ok( ! $can_build_call_frames,103 "_call_frames_buildable() returned false value, as expected (i386/linux/4)" );104 105 85 ##### _handle_call_frames_buildable() ##### 106 86 107 $conf->data->set( nvsize => 8 );108 $conf->data->set( cpuarch => 'i386' );109 $conf->data->set( osname => 'linux' );110 111 87 my $rv; 112 88 113 89 $can_build_call_frames = 0; … … 123 99 $conf->data->set( 'has_exec_protect' => undef ); 124 100 125 101 $can_build_call_frames = 1; 126 my $realos = $conf->data->get( 'osname' );127 $conf->data->set( 'osname' => 'foobar' );128 102 $rv = $step->_handle_can_build_call_frames( $conf, $can_build_call_frames ); 129 103 ok( $rv, "_handle_can_build_call_frames() returned true value" ); 130 104 is( $conf->data->get( 'cc_build_call_frames'), '-DCAN_BUILD_CALL_FRAMES', 131 105 "cc_build_call_frames set to expected value" ); 132 is( $conf->data->get( 'has_exec_protect' ), 0,133 "has_exec_protect is 0, as expected" );106 is( $conf->data->get( 'has_exec_protect' ), 1, 107 "has_exec_protect is 1, as expected" ); 134 108 is( $step->result(), 'yes', "Result is 'yes', as expected" ); 135 109 136 110 $conf->data->set( 'cc_build_call_frames' => undef ); 137 111 $conf->data->set( 'has_exec_protect' => undef ); 138 $conf->data->set( 'osname' => $realos );139 112 140 113 pass("Completed all tests in $0"); 141 114 -
t/steps/gen/libjit-01.t
1 #! perl 2 # Copyright (C) 2009, Parrot Foundation. 3 # $Id$ 4 # gen/libjit-01.t 5 6 use strict; 7 use warnings; 8 9 use constant NUM_GENERATED_FILES => 2; 10 # use Test::More tests => 8 + 2*NUM_GENERATED_FILES; 11 use Test::More qw( no_plan ); 12 13 use File::Copy 'move'; 14 use File::Temp 'tempfile'; 15 16 use lib 'lib'; 17 use Parrot::Configure; 18 use Parrot::Configure::Options 'process_options'; 19 use Parrot::Configure::Test qw( 20 test_step_thru_runstep 21 rerun_defaults_for_testing 22 test_step_constructor_and_description 23 ); 24 25 use_ok('config::gen::libjit'); 26 27 my ($args, $step_list_ref) = process_options( 28 { 29 argv => [], 30 mode => 'configure', 31 } 32 ); 33 34 my $conf = Parrot::Configure->new; 35 36 my $serialized = $conf->pcfreeze(); 37 38 my $pkg = 'gen::libjit'; 39 $conf->add_steps($pkg); 40 $conf->options->set( %$args ); 41 my $step = test_step_constructor_and_description($conf); 42 43 is( scalar keys %{$step->{targets}}, NUM_GENERATED_FILES, 44 "Expected number of generated files"); 45 is_deeply([keys %{$step->{targets}}], [keys %{$step->{templates}}], 46 "Templates match targets"); 47 48 foreach (keys %{$step->{templates}}) { 49 ok(-f $step->{templates}{$_}, "Able to locate $_ template") 50 } 51 52 my %orig_files; 53 foreach (keys %{$step->{targets}}) { 54 if (-f (my $targ_name = $step->{targets}{$_})) { 55 $orig_files{$_} = tempfile(); 56 move($targ_name, $orig_files{$_}); 57 } 58 } 59 60 my %orig_conf = map { $_ => $conf->data->get($_) } qw[ iv nv ]; 61 $conf->data->set( iv => 'int', nv => 'float' ); 62 # Set a value for 'libjit_has_alloca' to avoid uninitialized value warning. 63 $conf->data->set( 'libjit_has_alloca' => 1 ); 64 my $ret = $step->runstep($conf); 65 ok( $ret, "runstep() returned true value" ); 66 foreach (keys %{$step->{targets}}) { 67 ok(-f $step->{targets}{$_}, "$_ target generated"); 68 } 69 70 # re-set for next test 71 $conf->data->set(%orig_conf); 72 $step->set_result( '' ); 73 foreach (keys %{$step->{targets}}) { 74 if (exists $orig_files{$_}) { 75 move( $orig_files{$_}, $step->{targets}{$_} ); 76 } else { 77 unlink $_; 78 } 79 } 80 81 $conf->replenish($serialized); 82 83 pass("Completed all tests in $0"); 84 85 ################### DOCUMENTATION ################### 86 87 =head1 NAME 88 89 gen/libjit-01.t - test gen::libjit 90 91 =head1 SYNOPSIS 92 93 % prove t/steps/gen/libjit-01.t 94 95 =head1 DESCRIPTION 96 97 The files in this directory test functionality used by F<Configure.pl>. 98 99 The tests in this file test gen::libjit. 100 101 =head1 SEE ALSO 102 103 config::gen::libjit, F<Configure.pl>. 104 105 =cut 106 107 # Local Variables: 108 # mode: cperl 109 # cperl-indent-level: 4 110 # fill-column: 100 111 # End: 112 # vim: expandtab shiftwidth=4: -
config/auto/libjit.pm
1 # Copyright (C) 2009, Parrot Foundation. 2 # $Id$ 3 4 =head1 NAME 5 6 config/auto/libjit - Check whether LibJIT is installed 7 8 =head1 DESCRIPTION 9 10 Determines whether libjit is present is installed and functional on the system. 11 It is OK when it doesn't exist. 12 13 The libjit library implements just-in-time compilation functionality. Unlike 14 other JITs, this one is designed to be independent of any particular virtual 15 machine bytecode format or language. 16 17 libjit can be obtained from L<http://freshmeat.net/projects/libjit/> or through 18 your distribution's package manager. Developer documentation is available from 19 L<http://www.gnu.org/software/dotgnu/libjit-doc/libjit.html> 20 21 =cut 22 23 package auto::libjit; 24 25 use strict; 26 use warnings; 27 28 use base 'Parrot::Configure::Step'; 29 30 use Parrot::Configure::Utils ':auto'; 31 32 sub _init { 33 my $self = shift; 34 my %data = ( 35 description => 'Is LibJIT installed', 36 result => '', 37 ); 38 return \%data; 39 } 40 41 sub runstep { 42 my ($self, $conf) = @_; 43 44 my ($verbose, $without) = $conf->options->get( qw{ 45 verbose 46 without-libjit 47 }); 48 49 my ($has_libjit, $extra_libs); 50 if ($without) { 51 $has_libjit = 0; 52 } 53 else { 54 $extra_libs = $self->_select_lib( { 55 conf => $conf, 56 osname => $conf->data->get_p5('OSNAME'), 57 cc => $conf->data->get('cc'), 58 win32_nongcc => 'libjit.lib', 59 default => '-ljit', 60 } ); 61 62 $conf->cc_gen('config/auto/libjit/libjit_c.in'); 63 eval { $conf->cc_build('', $extra_libs) }; 64 if ($@) { 65 print "cc_build() failed: $@\n" if $verbose; 66 $has_libjit = 0; 67 } 68 else { 69 my $test; 70 eval { $test = $conf->cc_run(); }; 71 if ($@) { 72 print "cc_run() failed: $@\n" if $verbose; 73 $has_libjit = 0; 74 } 75 else { 76 $has_libjit = 77 $self->_evaluate_cc_run($test, $has_libjit, $verbose); 78 } 79 } 80 $conf->cc_clean(); 81 } 82 83 $conf->data->set( HAS_LIBJIT => $has_libjit ); 84 _handle_has_libjit($conf, $has_libjit, $extra_libs); 85 $self->set_result( $has_libjit ? 'yes' : 'no' ); 86 87 return 1; 88 } 89 90 sub _evaluate_cc_run { 91 my ($self, $test, $has_libjit, $verbose) = @_; 92 if ($test =~ m/^USES INTERPRETER: \d+/ ) { 93 $has_libjit = 1; 94 print " (yes) " if $verbose; 95 $self->set_result("yes"); 96 } 97 return $has_libjit; 98 } 99 100 sub _handle_has_libjit { 101 my ($conf, $has_libjit, $extra_libs) = @_; 102 if ($has_libjit) { 103 $conf->data->set( 104 libjit_has_alloca => ($conf->data->get('cpuarch') eq 'i386' ? '1' : '0'), 105 ); 106 $conf->data->add( ' ', libs => $extra_libs ); 107 } 108 else { 109 $conf->data->set( libjit_has_alloca => 0 ); 110 } 111 } 112 113 1; 114 115 # Local Variables: 116 # mode: cperl 117 # cperl-indent-level: 4 118 # fill-column: 100 119 # End: 120 # vim: expandtab shiftwidth=4: -
config/auto/frames.pm
40 40 41 41 sub _call_frames_buildable { 42 42 my $conf = shift; 43 44 my $osname = $conf->data->get('osname');45 my $cpuarch = $conf->data->get('cpuarch');46 my $nvsize = $conf->data->get('nvsize');47 43 my $can_build_call_frames; 48 44 49 45 if (defined $conf->options->get('buildframes')) { 50 46 $can_build_call_frames = $conf->options->get('buildframes'); 51 47 } 52 48 else { 53 # TT #1132 54 # Temporary disable build frames automatically. 55 #$can_build_call_frames = ($nvsize == 8 && $cpuarch eq 'i386' 56 # && $osname ne 'darwin'); 57 $can_build_call_frames = 0; 49 $can_build_call_frames = $conf->data->get('HAS_LIBJIT'); 58 50 } 59 51 return $can_build_call_frames; 60 52 } … … 63 55 my ($self, $conf, $can_build_call_frames) = @_; 64 56 if ( $can_build_call_frames ) { 65 57 $conf->data->set( 66 cc_build_call_frames => '-DCAN_BUILD_CALL_FRAMES', 58 cc_build_call_frames => '-DCAN_BUILD_CALL_FRAMES', 59 has_exec_protect => 1, 67 60 ); 68 # test for executable malloced memory69 my $osname = $conf->data->get( 'osname' );70 if ( -e "config/auto/frames/test_exec_${osname}_c.in" ) {71 $conf->cc_gen("config/auto/frames/test_exec_${osname}_c.in");72 eval { $conf->cc_build(); };73 if ($@) {74 $conf->data->set( has_exec_protect => 0 );75 }76 else {77 my $exec_protect_test = (78 $conf->cc_run(0) !~ /ok/ && $conf->cc_run(1) =~ /ok/79 );80 if ($exec_protect_test) {81 $conf->data->set( has_exec_protect => 1 );82 }83 else {84 $conf->data->set( has_exec_protect => 0 );85 }86 }87 $conf->cc_clean();88 }89 else {90 $conf->data->set( has_exec_protect => 0 );91 }92 61 $self->set_result( 'yes' ); 93 62 } 94 63 else { 95 $conf->data->set( 64 $conf->data->set(cc_build_call_frames => ''); 96 65 $self->set_result( 'no' ); 97 66 } 98 67 return 1; -
config/auto/libjit/libjit_c.in
1 /* 2 * Copyright (C) 2009, Parrot Foundation. 3 * $Id$ 4 */ 5 6 #include <stdlib.h> 7 #include <stdio.h> 8 #include <jit/jit.h> 9 10 int 11 main(int argc, char *argv[]) { 12 jit_init(); 13 printf("USES INTERPRETER: %i\n", jit_uses_interpreter()); 14 return EXIT_SUCCESS; 15 } 16 17 /* 18 * Local variables: 19 * c-file-style: "parrot" 20 * End: 21 * vim: expandtab shiftwidth=4: 22 */ -
config/auto/frames/test_exec_openbsd_c.in
1 /*2 Copyright (C) 2004-2009, Parrot Foundation.3 $Id$4 5 test for exec privs6 */7 8 #include <stdio.h>9 #include <stdlib.h>10 #include <sys/mman.h>11 #include <limits.h>12 #include <errno.h>13 #include <malloc.h>14 #include <unistd.h>15 #ifndef PAGE_SIZE16 # define PAGE_SIZE sysconf(_SC_PAGESIZE)17 #endif18 19 /*20 * c equiv:21 int t() {22 return 1;23 }24 */25 26 char code[] = {27 0xB8, 0x01, 0, 0, 0, /* movl $1, %eax */28 0xC3 /* ret */29 };30 31 typedef int (*pf)(void);32 33 int34 main(int argc, char *argv[])35 {36 pf t;37 char *p;38 int rc;39 int prot = PROT_READ;40 41 if (argc != 2) {42 fprintf(stderr, "usage: test 0 | 1\n");43 exit(1);44 }45 if (atoi(argv[1]))46 prot |= PROT_EXEC;47 48 p = malloc(PAGE_SIZE);49 memcpy(p, code, sizeof (code));50 t = (pf) p;51 rc = mprotect(p, PAGE_SIZE, prot);52 if (rc) {53 fprintf(stderr, "p = %p PAGE_SIZE = %d (0x%x)\n", p,54 PAGE_SIZE, PAGE_SIZE);55 perror("failure");56 }57 58 if (t() == 1)59 puts("ok");60 else61 return 1;62 63 return 0;64 }65 66 /*67 * Local variables:68 * c-file-style: "parrot"69 * End:70 * vim: expandtab shiftwidth=4:71 */ -
config/auto/frames/test_exec_linux_c.in
1 /*2 Copyright (C) 2004-2009, Parrot Foundation.3 $Id$4 5 test for exec privs6 */7 8 #include <stdio.h>9 #include <stdlib.h>10 #include <sys/mman.h>11 #include <limits.h>12 #include <errno.h>13 #include <malloc.h>14 #include <unistd.h>15 #ifndef PAGE_SIZE16 # define PAGE_SIZE getpagesize()17 #endif18 19 /*20 * c equiv:21 int t() {22 return 1;23 }24 */25 26 char code[] = {27 0xB8, 0x01, 0, 0, 0, /* movl $1, %eax */28 0xC3 /* ret */29 };30 31 typedef int (*pf)(void);32 33 int34 main(int argc, char *argv[])35 {36 pf t;37 char *p;38 int rc;39 int prot = PROT_READ;40 41 if (argc != 2) {42 fprintf(stderr, "usage: test 0 | 1\n");43 exit(1);44 }45 if (atoi(argv[1]))46 prot |= PROT_EXEC;47 48 p = memalign(PAGE_SIZE, sizeof (code));49 memcpy(p, code, sizeof (code));50 t = (pf) p;51 rc = mprotect(p, PAGE_SIZE, prot);52 if (rc) {53 fprintf(stderr, "p = %p PAGE_SIZE = %d (0x%x)\n", p,54 PAGE_SIZE, PAGE_SIZE);55 perror("failure");56 }57 58 if (t() == 1)59 puts("ok");60 else61 return 1;62 63 return 0;64 }65 66 /*67 * Local variables:68 * c-file-style: "parrot"69 * End:70 * vim: expandtab shiftwidth=4:71 */ -
config/auto/frames/test_exec_cygwin_c.in
1 /*2 Copyright (C) 2008-2009, Parrot Foundation.3 $Id$4 5 test for exec privs6 */7 8 #include <stdio.h>9 #include <stdlib.h>10 #include <sys/mman.h>11 #include <limits.h>12 #include <errno.h>13 #include <malloc.h>14 #include <unistd.h>15 #include <string.h>16 #ifndef PAGE_SIZE17 # define PAGE_SIZE getpagesize()18 #endif19 #20 21 /*22 * c equiv:23 int t() {24 return 1;25 }26 */27 28 char code[] = {29 0xB8, 0x01, 0, 0, 0, /* movl $1, %eax */30 0xC3 /* ret */31 };32 33 typedef int (*pf)(void);34 35 int36 main(int argc, char *argv[])37 {38 pf t;39 char *p;40 int rc;41 int prot = PROT_READ;42 43 if (argc != 2) {44 fprintf(stderr, "usage: test 0 | 1\n");45 exit(1);46 }47 48 if (atoi(argv[1]))49 prot |= PROT_EXEC;50 51 p = memalign(PAGE_SIZE, PAGE_SIZE);52 memcpy(p, code, sizeof (code));53 54 t = (pf) p;55 rc = mprotect(p, PAGE_SIZE, prot);56 57 if (rc) {58 fprintf(stderr, "p = %p PAGE_SIZE = %d (0x%x)\n", p,59 PAGE_SIZE, PAGE_SIZE);60 perror("failure");61 }62 63 if (t() == 1)64 puts("ok");65 else66 return 1;67 68 return 0;69 }70 71 /*72 * Local variables:73 * c-file-style: "parrot"74 * End:75 * vim: expandtab shiftwidth=4:76 */ -
config/gen/parrot_include.pm
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( -
config/gen/libjit.pm
1 # Copyright (C) 2009, Parrot Foundation. 2 # $Id$ 3 4 =head1 NAME 5 6 config/gen/libjit.pm - LibJIT Code Generation 7 8 =head1 DESCRIPTION 9 10 Populate F<config/gen/frame_builder_libjit_h.in> and 11 F<configu/gen/frame_builder_libjit_c.in> with system appropriate 12 type information and automatically generated parrot function and 13 vtable jit wrappers. 14 15 =cut 16 17 package gen::libjit; 18 19 use strict; 20 use warnings; 21 22 use base 'Parrot::Configure::Step'; 23 24 use Parrot::Configure::Utils ':gen'; 25 26 27 sub _init { 28 my $self = shift; 29 my %data = ( 30 description => 'Generate LibJIT specific code', 31 result => '', 32 targets => { 33 frame_builder_h => 'src/frame_builder_libjit.h', 34 frame_builder_c => 'src/frame_builder_libjit.c', 35 }, 36 templates => { 37 frame_builder_h => 'config/gen/libjit/frame_builder_libjit_h.in', 38 frame_builder_c => 'config/gen/libjit/frame_builder_libjit_c.in', 39 }, 40 wrapped_vtables => { 41 get_integer => [ () => 'INTVAL' ], 42 set_integer_native => [ ('INTVAL') => 'void' ], 43 get_pointer => [ () => 'void_ptr' ], 44 set_pointer => [ ('void_ptr') => 'void' ], 45 get_string_keyed_int => [ ('INTVAL') => 'void_ptr' ], 46 }, 47 wrapped_funcs => { 48 Parrot_pcc_fill_params_from_c_args => 49 [ qw(void_ptr void_ptr void_ptr ...) => 'void' ], 50 Parrot_pcc_fill_returns_from_c_args => 51 [ qw(void_ptr void_ptr void_ptr ...) => 'void' ], 52 53 Parrot_str_new => 54 [ qw(void_ptr void_ptr UINTVAL) => 'void_ptr' ], 55 Parrot_str_to_cstring => 56 [ qw(void_ptr void_ptr) => 'void_ptr' ], 57 Parrot_str_free_cstring => 58 [ ('void_ptr') => 'void' ], 59 60 pmc_new_noinit => 61 [ qw(void_ptr INTVAL) => 'void_ptr' ], 62 63 mem_sys_allocate => [ ('long') => 'void_ptr' ], 64 mem_sys_free => [ ('void_ptr') => 'void' ], 65 }, 66 ); 67 return \%data; 68 } 69 70 sub runstep { 71 my ($self, $conf) = @_; 72 73 my ($libjit_iv, $libjit_uv) = @{ 74 my $iv = $conf->data->get('iv') || ''; 75 { 76 short => [ 'jit_type_sys_short' , 'jit_type_sys_ushort' ], 77 int => [ 'jit_type_sys_int' , 'jit_type_sys_uint' ], 78 long => [ 'jit_type_sys_long' , 'jit_type_sys_ulong' ], 79 'long long' => [ 'jit_type_sys_longlong', 'jit_type_sys_ulonglong' ], 80 }->{$iv} 81 or die "Couldn't determine libjity type for intval of type '$iv'"; 82 }; 83 84 my $libjit_nv = do { 85 my $nv = $conf->data->get('nv') || ''; 86 { 87 float => 'jit_type_sys_float', 88 double => 'jit_type_sys_double', 89 'long double' => 'jit_type_sys_long_double', 90 }->{$nv} 91 or die "Couldn't determine libjity type for floatval of type '$nv'"; 92 }; 93 94 $conf->data->set( libjit_iv => $libjit_iv, 95 libjit_uv => $libjit_uv, 96 libjit_nv => $libjit_nv, ); 97 98 my @vtable_wrappers = 99 map {gen_vtable_wrapper($self, $_)} keys %{$self->{wrapped_vtables}}; 100 my @function_wrappers = 101 map {gen_function_wrapper($self, $_)} keys %{$self->{wrapped_funcs}}; 102 103 $conf->data->set( 104 TEMP_vtable_wrap_decls => 105 (join "\n", map {$_->{decl}} @vtable_wrappers), 106 TEMP_vtable_wrap_defns => 107 (join "\n", map {$_->{defn}} @vtable_wrappers), 108 TEMP_func_wrap_decls => 109 (join "\n", map {$_->{decl}} @function_wrappers), 110 TEMP_func_wrap_defns => 111 (join "\n", map {$_->{defn}} @function_wrappers) 112 ); 113 114 foreach my $t (keys %{$self->{targets}}) { 115 $conf->genfile($self->{templates}{$t}, $self->{targets}{$t}); 116 $conf->append_configure_log($t); 117 } 118 119 return 1; 120 } 121 122 sub gen_vtable_wrapper { 123 my ($self, $entry_name) = @_; 124 125 my $entry_sig = $self->{wrapped_vtables}{$entry_name}; 126 $_ = jit_prefix_type($_) for @$entry_sig; 127 128 my $ret_t = pop @$entry_sig; 129 my $arg_t = join ", ", @$entry_sig; 130 131 my $n_args = scalar @$entry_sig; 132 my $arg_decls_t = join ", ", map {'jit_value_t'} 1..$n_args; 133 my $arg_decls_v = join ", ", map {"jit_value_t v$_"} 1..$n_args; 134 my $arg_v = join ", ", map {"v$_"} 1..$n_args; 135 136 my $_arg_decls_t = $n_args ? ", $arg_decls_t" : ""; 137 my $_arg_decls_v = $n_args ? ", $arg_decls_v" : ""; 138 my $_arg_t = $n_args ? ", $arg_t" : ""; 139 my $_arg_v = $n_args ? ", $arg_v" : ""; 140 141 return { decl => <<DECL, defn => <<DEFN }; 142 static jit_value_t 143 jit__vtable_$entry_name(jit_function_t, jit_value_t, jit_value_t $_arg_decls_t); 144 DECL 145 static jit_value_t 146 jit__vtable_$entry_name(jit_function_t f, jit_value_t interp, jit_value_t self $_arg_decls_v) { 147 jit_type_t sig; 148 jit_value_t vtable, method; 149 jit_type_t arg_t[] = { jit_type_void_ptr, jit_type_void_ptr $_arg_t }; 150 jit_value_t arg_v[] = { interp, self $_arg_v }; 151 152 sig = jit_type_create_signature(jit_abi_cdecl, $ret_t, arg_t, $n_args + 2, 1); 153 154 vtable = jit_insn_load_relative(f, self, offsetof(PMC, vtable), jit_type_void_ptr); 155 method = jit_insn_load_relative(f, vtable, offsetof(VTABLE, $entry_name), jit_type_void_ptr); 156 157 return jit_insn_call_indirect(f, method, sig, arg_v, $n_args + 2, 0); 158 } 159 DEFN 160 } 161 162 sub gen_function_wrapper { 163 my ($self, $func_name) = @_; 164 165 my $func_sig = $self->{wrapped_funcs}{$func_name}; 166 $_ = jit_prefix_type($_) for @$func_sig; 167 168 my $ret_t = pop @$func_sig; 169 170 my $vararg = 0; 171 if ($func_sig->[-1] eq '...') { 172 $vararg = 1; 173 pop @$func_sig; 174 } 175 176 my $arg_t = join ", ", @$func_sig; 177 178 my $n_args = scalar @$func_sig; 179 my $arg_decls_t = join ", ", map {'jit_value_t'} 1..$n_args; 180 my $arg_decls_v = join ", ", map {"jit_value_t v$_"} 1..$n_args; 181 my $arg_v = join ", ", map {"v$_"} 1..$n_args; 182 183 my ($decl, $defn); 184 if ($vararg) { 185 $decl = <<DECL; 186 static jit_value_t 187 jit__$func_name(jit_function_t, $arg_decls_t, jit_type_t *, jit_value_t *, int); 188 DECL 189 $defn = <<DEFN; 190 static jit_value_t 191 jit__$func_name(jit_function_t f, $arg_decls_v, jit_type_t *va_t, jit_value_t *va_v, int va_n) { 192 int i; 193 int n_args = $n_args + va_n; 194 jit_type_t sig; 195 jit_type_t arg_t[n_args]; 196 jit_value_t arg_v[n_args]; 197 jit_type_t carg_t[] = { $arg_t }; 198 jit_value_t carg_v[] = { $arg_v }; 199 200 for (i = 0; i < $n_args; i++) { 201 arg_t[i] = carg_t[i]; 202 arg_v[i] = carg_v[i]; 203 } 204 for (i = $n_args; i < n_args; i++) { 205 arg_t[i] = va_t[i - $n_args]; 206 arg_v[i] = va_v[i - $n_args]; 207 } 208 209 sig = jit_type_create_signature(jit_abi_cdecl, $ret_t, arg_t, n_args, 1); 210 211 return jit_insn_call_native(f, "$func_name", (void *)&$func_name, sig, arg_v, n_args, 0); 212 } 213 DEFN 214 } 215 else { 216 $decl = <<DECL; 217 static jit_value_t 218 jit__$func_name(jit_function_t, $arg_decls_t); 219 DECL 220 $defn = <<DEFN; 221 static jit_value_t 222 jit__$func_name(jit_function_t f, $arg_decls_v) { 223 int n_args = $n_args; 224 jit_type_t sig; 225 jit_type_t arg_t[] = { $arg_t }; 226 jit_value_t arg_v[] = { $arg_v }; 227 228 sig = jit_type_create_signature(jit_abi_cdecl, $ret_t, arg_t, n_args, 1); 229 230 return jit_insn_call_native(f, "$func_name", (void *)&$func_name, sig, arg_v, n_args, 0); 231 } 232 DEFN 233 } 234 235 return { decl => $decl, defn => $defn }; 236 } 237 238 sub jit_prefix_type { 239 my $type = shift; 240 if ($type =~ /^[_a-z]+$/) { 241 return "jit_type_$type"; 242 } 243 elsif ($type =~ /^[_A-Z]+$/) { 244 return "JIT_TYPE_$type"; 245 } 246 else { 247 return $type; 248 } 249 } 250 251 1; 252 253 # Local Variables: 254 # mode: cperl 255 # cperl-indent-level: 4 256 # fill-column: 100 257 # End: 258 # vim: expandtab shiftwidth=4: -
config/gen/makefiles/root.in
218 218 myconfig \ 219 219 $(GEN_PASM_INCLUDES) \ 220 220 $(SRC_DIR)/call_list.txt \ 221 $(SRC_DIR)/frame_builder_libjit.h \ 222 $(SRC_DIR)/frame_builder_libjit.c \ 221 223 MANIFEST.configure.generated \ 222 224 .configure_trace.sto \ 223 225 .parrot_current_rev … … 442 444 $(SRC_DIR)/longopt$(O) \ 443 445 $(SRC_DIR)/misc$(O) \ 444 446 $(SRC_DIR)/multidispatch$(O) \ 445 $(SRC_DIR)/frame_builder $(O) \447 $(SRC_DIR)/frame_builder_libjit$(O) \ 446 448 $(SRC_DIR)/nci$(O) \ 447 449 $(SRC_DIR)/oo$(O) \ 448 450 $(SRC_DIR)/packfile$(O) \ … … 625 627 $(SRC_DIR)/key.str \ 626 628 $(SRC_DIR)/library.str \ 627 629 $(SRC_DIR)/multidispatch.str \ 628 $(SRC_DIR)/frame_builder .str \630 $(SRC_DIR)/frame_builder_libjit.str \ 629 631 $(SRC_DIR)/nci.str \ 630 632 $(SRC_DIR)/packfile.str \ 631 633 $(SRC_DIR)/pmc.str \ … … 1224 1226 $(SRC_DIR)/exit$(O) : $(GENERAL_H_FILES) $(SRC_DIR)/exit.c 1225 1227 1226 1228 $(SRC_DIR)/nci$(O) : $(GENERAL_H_FILES) $(SRC_DIR)/nci.c $(SRC_DIR)/nci.str \ 1227 $(SRC_DIR)/frame_builder .h \1229 $(SRC_DIR)/frame_builder_libjit.h \ 1228 1230 $(SRC_DIR)/pmc/pmc_context.h \ 1229 1231 $(SRC_DIR)/pmc/pmc_unmanagedstruct.h \ 1230 1232 $(SRC_DIR)/pmc/pmc_managedstruct.h \ 1231 1233 $(SRC_DIR)/pmc/pmc_nci.h \ 1232 1234 $(SRC_DIR)/pmc/pmc_pointer.h 1233 1235 1234 $(SRC_DIR)/frame_builder $(O) : $(SRC_DIR)/frame_builder.h $(GENERAL_H_FILES) \1235 $(SRC_DIR)/frame_builder .c \1236 $(SRC_DIR)/frame_builder .str \1236 $(SRC_DIR)/frame_builder_libjit$(O) : $(SRC_DIR)/frame_builder_libjit.h $(GENERAL_H_FILES) \ 1237 $(SRC_DIR)/frame_builder_libjit.c \ 1238 $(SRC_DIR)/frame_builder_libjit.str \ 1237 1239 $(SRC_DIR)/pmc/pmc_fixedintegerarray.h \ 1238 1240 $(SRC_DIR)/pmc/pmc_unmanagedstruct.h \ 1239 1241 $(SRC_DIR)/pmc/pmc_managedstruct.h -
config/gen/libjit/frame_builder_libjit_c.in
1 /* 2 Copyright (C) 2008-2009, Parrot Foundation. 3 $Id$ 4 */ 5 6 /* HEADERIZER HFILE: none */ 7 /* HEADERIZER STOP */ 8 9 #include "parrot/parrot.h" 10 #include "pmc/pmc_context.h" 11 #include "pmc/pmc_integer.h" 12 #include "pmc/pmc_managedstruct.h" 13 #include "pmc/pmc_unmanagedstruct.h" 14 #include "frame_builder.h" 15 #include "frame_builder_libjit.h" 16 17 #ifdef PARROT_HAS_LIBJIT 18 19 /* 20 21 =over 4 22 23 =item C<void *Parrot_jit_build_call_func(PARROT_INTERP, PMC *nci, STRING *sig, void **priv)> 24 25 Public interface to NCI function interface builder. 26 27 =cut 28 29 */ 30 31 void * 32 Parrot_jit_build_call_func(PARROT_INTERP, PMC *pmc, STRING *sig, void **priv) { 33 void *thunk; 34 char *sig_cstr; 35 36 sig_cstr = Parrot_str_to_cstring(interp, sig); 37 *priv = mem_sys_allocate(sizeof (struct jit_buffer_private_data)); 38 39 thunk = Parrot_jit_create_thunk(interp, sig_cstr, *priv); 40 41 Parrot_str_free_cstring(sig_cstr); 42 43 return thunk; 44 } 45 46 /* 47 48 =item C<void Parrot_jit_free_buffer(PARROT_INTERP, void *ptr, void *priv)> 49 50 This is a callback to implement the proper freeing semantics. It is called by 51 the ManagedStruct PMC as it is garbage collected. 52 53 =cut 54 55 */ 56 57 void 58 Parrot_jit_free_buffer(PARROT_INTERP, void *ptr, void *priv) 59 { 60 struct jit_buffer_private_data *jit = (struct jit_buffer_private_data*)priv; 61 jit_context_destroy(jit->ctx); 62 mem_sys_free(jit->sig); 63 mem_sys_free(priv); 64 } 65 66 /* 67 68 =item C<PMC *Parrot_jit_clone_buffer(PARROT_INTERP, PMC *pmc, void *priv)> 69 70 This is a callback to implement the proper cloning semantics for jit buffers. 71 It is called by the ManagedStruct PMC's clone() function. 72 73 =back 74 75 =cut 76 77 */ 78 79 PMC * 80 Parrot_jit_clone_buffer(PARROT_INTERP, PMC *pmc, void *priv) 81 { 82 PMC * const rv = pmc_new(interp, pmc->vtable->base_type); 83 84 VTABLE_init(interp, rv); 85 /* copy the attributes */ 86 { 87 void (*tmpfreefunc)(PARROT_INTERP, void*, void*); 88 GETATTR_ManagedStruct_custom_free_func(interp, pmc, tmpfreefunc); 89 SETATTR_ManagedStruct_custom_free_func(interp, rv , tmpfreefunc); 90 } 91 { 92 PMC* (*tmpclonefunc)(PARROT_INTERP, PMC*, void*); 93 GETATTR_ManagedStruct_custom_clone_func(interp, pmc, tmpclonefunc); 94 SETATTR_ManagedStruct_custom_clone_func(interp, rv , tmpclonefunc); 95 } 96 97 /* compile a clone of the function */ 98 if (PARROT_MANAGEDSTRUCT(pmc)->ptr) { 99 void *rv_priv; 100 struct jit_buffer_private_data *jit = (struct jit_buffer_private_data*)priv; 101 STRING *sig = Parrot_str_new(interp, jit->sig, 0); 102 PARROT_MANAGEDSTRUCT(rv)->ptr = Parrot_jit_build_call_func(interp, rv, sig, &rv_priv); 103 } 104 105 return rv; 106 } 107 108 /* 109 * JIT functions 110 */ 111 112 static void * 113 Parrot_jit_create_thunk(PARROT_INTERP, char *sig, void *priv) { 114 struct jit_buffer_private_data *p; 115 jit_function_t f; 116 jit_value_t jit_interp, jit_nci_pmc, jit_pcc_sig; 117 jit_value_t jit_func, jit_pcc_sig_args, jit_pcc_sig_ret; 118 jit_value_t jit_call_object; 119 120 /* populate private data */ 121 p = (struct jit_buffer_private_data*)priv; 122 p->ctx = jit_context_create(); 123 p->sig = mem_sys_strdup(sig); 124 125 /* start compiling */ 126 jit_context_build_start(p->ctx); 127 128 /* start JIT function */ 129 { 130 jit_type_t arg_types[] = { 131 jit_type_void_ptr, /* interp */ 132 jit_type_void_ptr, /* nci_pmc */ 133 }; 134 jit_type_t f_sig = jit_type_create_signature(jit_abi_cdecl, jit_type_void, arg_types, 2, 1); 135 f = jit_function_create(p->ctx, f_sig); 136 } 137 138 /* get the incomming args */ 139 jit_interp = jit_value_get_param(f, 0); 140 jit_nci_pmc = jit_value_get_param(f, 1); 141 142 /* get information out of the NCI object */ 143 jit_func = jit__vtable_get_pointer(f, jit_interp, jit_nci_pmc); 144 { 145 jit_value_t temp = jit__vtable_get_string_keyed_int(f, jit_interp, jit_nci_pmc, 146 jit_value_create_nint_constant(f, JIT_TYPE_INTVAL, PARROT_NCI_PCC_SIGNATURE_PARAMS)); 147 jit_pcc_sig_args = jit__Parrot_str_to_cstring(f, jit_interp, temp); 148 } 149 { 150 jit_value_t temp = jit__vtable_get_string_keyed_int(f, jit_interp, jit_nci_pmc, 151 jit_value_create_nint_constant(f, JIT_TYPE_INTVAL, PARROT_NCI_PCC_SIGNATURE_RET)); 152 jit_pcc_sig_ret = jit__Parrot_str_to_cstring(f, jit_interp, temp); 153 } 154 155 /* get call_object */ 156 { 157 jit_value_t ctx = jit__CURRENT_CONTEXT(f, jit_interp); 158 jit_call_object = jit__Parrot_pcc_get_signature(f, jit_interp, ctx); 159 } 160 161 /* get the outgoing args */ 162 { 163 int nargs = strlen(sig) - 1; 164 165 jit_type_t jit_args_t[nargs]; 166 jit_value_t jit_args_v[nargs]; 167 jit_value_t jit_regs[nargs]; 168 169 Parrot_jit_parse_sig_args_pre(interp, sig, nargs, f, jit_interp, jit_call_object, jit_pcc_sig_args, 170 jit_args_t, jit_args_v, jit_regs); 171 172 /* get the return type */ 173 { 174 jit_type_t ret_t; 175 jit_value_t ret_v; 176 177 ret_t = Parrot_jit_parse_sig_ret_pre(interp, sig); 178 179 /* make the call */ 180 { 181 jit_type_t jit_sig 182 = jit_type_create_signature(jit_abi_cdecl, ret_t, jit_args_t, nargs, 1); 183 ret_v = jit_insn_call_indirect(f, jit_func, jit_sig, jit_args_v, nargs, 0); 184 } 185 186 /* get the incomming return */ 187 Parrot_jit_parse_sig_ret_post(interp, sig, f, jit_interp, jit_call_object, jit_pcc_sig_ret, ret_v); 188 } 189 190 /* clean up args */ 191 Parrot_jit_parse_sig_args_post(interp, sig, nargs, f, jit_interp, jit_args_v, jit_regs); 192 } 193 194 /* free PCC signature bits */ 195 jit__Parrot_str_free_cstring(f, jit_pcc_sig_args); 196 jit__Parrot_str_free_cstring(f, jit_pcc_sig_ret); 197 198 /* end JIT function */ 199 jit_insn_return(f, NULL); 200 201 /* compile to native callable func poitner */ 202 jit_function_compile(f); 203 jit_context_build_end(p->ctx); 204 205 return jit_function_to_closure(f); 206 } 207 208 static int 209 Parrot_jit_create_arg_regs(PARROT_INTERP, char *sig, int nargs, 210 jit_function_t f, jit_value_t *reg_v) { 211 int i, j; 212 for (i = 0, j = 0; i < nargs; i++) { 213 char c; 214 switch (c = sig[i]) { 215 case 'I': 216 case 'c': 217 case 's': 218 case 'i': 219 case 'l': 220 reg_v[j++] = jit_value_create(f, JIT_TYPE_INTVAL); 221 break; 222 223 case 'N': 224 case 'd': 225 case 'f': 226 reg_v[j++] = jit_value_create(f, JIT_TYPE_FLOATVAL); 227 break; 228 229 case 'S': 230 case 'B': 231 case 'b': 232 case 't': 233 reg_v[j++] = jit_value_create(f, jit_type_void_ptr); 234 break; 235 236 case 'p': 237 case 'P': 238 case 'O': 239 case '@': 240 case '2': 241 case '3': 242 case '4': 243 case 'V': 244 reg_v[j++] = jit_value_create(f, jit_type_void_ptr); 245 break; 246 247 default: 248 /* don't catch errors here; fail elsewhere */ 249 break; 250 } 251 } 252 253 return j; 254 } 255 256 static void 257 Parrot_jit_fill_args(PARROT_INTERP, char *sig, int nargs, int nregs, 258 jit_function_t f, jit_value_t jit_interp, jit_value_t call_object, jit_value_t jit_pcc_sig_args, 259 jit_value_t *reg_v, jit_type_t *arg_t, jit_value_t *arg_v) { 260 int i, j; 261 262 /* fill argument registers */ 263 { 264 jit_type_t jit_reg_addr_t[nregs]; 265 jit_value_t jit_reg_addr_v[nregs]; 266 for (i = 0; i < nregs; i++) { 267 jit_reg_addr_t[i] = jit_type_void_ptr; 268 jit_value_set_addressable(reg_v[i]); 269 jit_reg_addr_v[i] = jit_insn_address_of(f, reg_v[i]); 270 } 271 jit__Parrot_pcc_fill_params_from_c_args(f, jit_interp, call_object, jit_pcc_sig_args, 272 jit_reg_addr_t, jit_reg_addr_v, nregs); 273 } 274 275 for (i = 0, j = 0; i < nargs; i++) { 276 char c; 277 jit_type_t t1; 278 jit_label_t l1; 279 jit_value_t v1, v2, v3, v4; 280 switch (c = sig[i]) { 281 case 'I': 282 t1 = JIT_TYPE_INTVAL; 283 goto pop_reg; 284 case 'c': 285 t1 = jit_type_sys_char; 286 goto pop_reg; 287 case 's': 288 t1 = jit_type_sys_short; 289 goto pop_reg; 290 case 'i': 291 t1 = jit_type_sys_int; 292 goto pop_reg; 293 case 'l': 294 t1 = jit_type_sys_long; 295 goto pop_reg; 296 case 'N': 297 t1 = JIT_TYPE_FLOATVAL; 298 goto pop_reg; 299 case 'f': 300 t1 = jit_type_sys_float; 301 goto pop_reg; 302 case 'd': 303 t1 = jit_type_sys_double; 304 goto pop_reg; 305 case 'S': 306 case 'P': 307 case 'O': 308 case '@': 309 t1 = jit_type_void_ptr; 310 pop_reg: 311 arg_t[i] = t1; 312 arg_v[i] = jit_value_create(f, t1); 313 jit_insn_store(f, arg_v[i], reg_v[j]); 314 j++; 315 break; 316 317 case 't': 318 arg_t[i] = jit_type_void_ptr; 319 arg_v[i] = jit_value_create(f, jit_type_void_ptr); 320 jit_insn_store(f, arg_v[i], 321 jit_value_create_nint_constant(f, jit_type_void_ptr, (jit_nint)NULL)); 322 v1 = jit_insn_eq(f, reg_v[j], 323 jit_value_create_nint_constant(f, jit_type_void_ptr, (jit_nint)NULL)); 324 l1 = jit_label_undefined; 325 jit_insn_branch_if(f, v1, &l1); 326 jit_insn_store(f, arg_v[i], jit__Parrot_str_to_cstring(f, jit_interp, reg_v[j])); 327 jit_insn_label(f, &l1); 328 329 j++; 330 break; 331 332 case 'b': 333 arg_t[i] = jit_type_void_ptr; 334 arg_v[i] = jit__Buffer_bufstart(f, reg_v[j]); 335 j++; 336 break; 337 338 case 'B': 339 arg_t[i] = jit_type_void_ptr; 340 arg_v[i] = jit_value_create(f, jit_type_void_ptr); 341 jit_insn_store(f, arg_v[i], 342 jit_value_create_nint_constant(f, jit_type_void_ptr, (jit_nint)NULL)); 343 v1 = jit_insn_eq(f, reg_v[j], 344 jit_value_create_nint_constant(f, jit_type_void_ptr, (jit_nint)NULL)); 345 l1 = jit_label_undefined; 346 jit_insn_branch_if(f, v1, &l1); 347 v2 = jit__Parrot_str_to_cstring(f, jit_interp, reg_v[j]); 348 v3 = jit_value_create(f, jit_type_void_ptr); 349 jit_value_set_addressable(v3); 350 jit_insn_store(f, v3, v2); 351 jit_insn_store(f, arg_v[i], jit_insn_address_of(f, v3)); 352 jit_insn_label(f, &l1); 353 j++; 354 break; 355 356 case 'p': 357 arg_t[i] = jit_type_void_ptr; 358 arg_v[i] = jit_value_create(f, jit_type_void_ptr); 359 jit_insn_store(f, arg_v[i], 360 jit_value_create_nint_constant(f, jit_type_void_ptr, (jit_nint)NULL)); 361 v1 = jit__PMC_IS_NULL(f, reg_v[j]); 362 l1 = jit_label_undefined; 363 jit_insn_branch_if(f, v1, &l1); 364 v2 = jit__vtable_get_pointer(f, jit_interp, reg_v[j]); 365 jit_insn_store(f, arg_v[i], v2); 366 jit_insn_label(f, &l1); 367 j++; 368 break; 369 370 case '2': 371 t1 = jit_type_sys_short; 372 goto call_get_integer; 373 case '3': 374 t1 = jit_type_sys_int; 375 goto call_get_integer; 376 case '4': 377 t1 = jit_type_sys_long; 378 call_get_integer: 379 arg_t[i] = jit_type_void_ptr; 380 v1 = jit__vtable_get_integer(f, jit_interp, reg_v[j]); 381 v2 = jit_value_create(f, t1); 382 jit_value_set_addressable(v2); 383 jit_insn_store(f, v2, v1); 384 arg_v[i] = jit_insn_address_of(f, v2); 385 j++; 386 break; 387 388 case 'V': 389 arg_t[i] = jit_type_void_ptr; 390 v1 = jit__vtable_get_pointer(f, jit_interp, reg_v[j]); 391 v2 = jit_value_create(f, jit_type_void_ptr); 392 jit_value_set_addressable(v2); 393 jit_insn_store(f, v2, v1); 394 arg_v[i] = jit_insn_address_of(f, v2); 395 j++; 396 break; 397 398 case '0': 399 arg_t[i] = jit_type_void_ptr; 400 arg_v[i] = jit_value_create_nint_constant(f, jit_type_void_ptr, (jit_nint)NULL); 401 break; 402 403 case 'J': 404 arg_t[i] = jit_type_void_ptr; 405 arg_v[i] = jit_interp; 406 break; 407 408 default: 409 Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_JIT_ERROR, 410 "unkown arg type '%c'", c); 411 return; 412 } 413 } 414 } 415 416 static void 417 Parrot_jit_parse_sig_args_pre(PARROT_INTERP, char *sig, int nargs, 418 jit_function_t f, jit_value_t jit_interp, jit_value_t call_object, jit_value_t jit_pcc_sig_args, 419 jit_type_t *jit_args_t, 420 jit_value_t *jit_args_v, jit_value_t *jit_regs_v) { 421 int nregs; 422 423 sig += 1; /* ignore return character */ 424 425 nregs = Parrot_jit_create_arg_regs(interp, sig, nargs, f, jit_regs_v); 426 Parrot_jit_fill_args(interp, sig, nargs, nregs, f, jit_interp, call_object, jit_pcc_sig_args, 427 jit_regs_v, jit_args_t, jit_args_v); 428 } 429 430 static jit_type_t 431 Parrot_jit_parse_sig_ret_pre(PARROT_INTERP, char *sig) { 432 char c; 433 switch (c = sig[0]) { 434 case 'v': 435 return jit_type_void; 436 437 case 'I': 438 return JIT_TYPE_INTVAL; 439 case 'c': 440 return jit_type_sys_char; 441 case 's': 442 return jit_type_sys_short; 443 case 'i': 444 return jit_type_sys_int; 445 case 'l': 446 return jit_type_sys_long; 447 448 case 'N': 449 return JIT_TYPE_FLOATVAL; 450 case 'f': 451 return jit_type_sys_float; 452 case 'd': 453 return jit_type_sys_double; 454 455 case 'S': 456 case 't': 457 return jit_type_void_ptr; 458 459 case 'p': 460 case 'P': 461 return jit_type_void_ptr; 462 463 default: 464 /* FAIL */ 465 Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_JIT_ERROR, 466 "unknown return type '%c'", c); 467 return NULL; 468 } 469 } 470 471 static void 472 Parrot_jit_parse_sig_ret_post(PARROT_INTERP, char *sig, 473 jit_function_t f, jit_value_t jit_interp, jit_value_t call_object, 474 jit_value_t pcc_sig, jit_value_t retval) { 475 jit_type_t ret_t[1]; 476 jit_value_t ret_v[1]; 477 478 jit_type_t t1; 479 jit_value_t v1, v2, v3; 480 switch (sig[0]) { 481 case 'v': 482 break; 483 484 case 'I': 485 case 'c': 486 case 's': 487 case 'i': 488 case 'l': 489 ret_t[0] = JIT_TYPE_INTVAL; 490 goto fill_ret; 491 case 'N': 492 case 'f': 493 case 'd': 494 ret_t[0] = JIT_TYPE_FLOATVAL; 495 goto fill_ret; 496 case 'S': 497 case 'P': 498 ret_t[0] = jit_type_void_ptr; 499 goto fill_ret; 500 case 't': 501 ret_t[0] = jit_type_void_ptr; 502 retval = jit__Parrot_str_new(f, jit_interp, retval, 503 jit_value_create_nint_constant(f, jit_type_sys_int, 0)); 504 goto fill_ret; 505 case 'p': 506 ret_t[0] = jit_type_void_ptr; 507 v1 = jit__pmc_new_noinit(f, jit_interp, 508 jit_value_create_intval_constant(f, enum_class_UnManagedStruct)); 509 jit__vtable_set_pointer(f, jit_interp, v1, retval); 510 retval = v1; 511 goto fill_ret; 512 case '2': 513 t1 = jit_type_sys_short; 514 goto create_int_pmc; 515 case '3': 516 t1 = jit_type_sys_int; 517 goto create_int_pmc; 518 case '4': 519 t1 = jit_type_sys_long; 520 create_int_pmc: 521 ret_t[0] = jit_type_void_ptr; 522 v1 = jit_insn_load_relative(f, retval, 0, t1); 523 v2 = jit__pmc_new_noinit(f, jit_interp, 524 jit_value_create_intval_constant(f, enum_class_Integer)); 525 jit__vtable_set_integer_native(f, jit_interp, v2, v1); 526 retval = v2; 527 fill_ret: 528 ret_v[0] = jit_value_create(f, ret_t[0]); 529 jit_insn_store(f, ret_v[0], retval); 530 jit__Parrot_pcc_fill_returns_from_c_args(f, jit_interp, call_object, pcc_sig, ret_t, ret_v, 1); 531 break; 532 533 default: 534 /* ignore (failed elsewhere) */ 535 break; 536 } 537 } 538 539 static void 540 Parrot_jit_parse_sig_args_post(PARROT_INTERP, char *sig, int nargs, 541 jit_function_t f, jit_value_t jit_interp, 542 jit_value_t *args, jit_value_t *regs) { 543 int i, j; 544 545 sig += 1; 546 547 for (i = 0, j = 0; i < nargs; i++) { 548 jit_type_t t1; 549 jit_value_t v1; 550 switch (sig[i]) { 551 case 't': 552 jit__Parrot_str_free_cstring(f, args[i]); 553 j++; 554 break; 555 556 case 'B': 557 v1 = jit_insn_load_relative(f, args[i], 0, jit_type_void_ptr); 558 jit__Parrot_str_free_cstring(f, v1); 559 j++; 560 break; 561 562 case '2': 563 t1 = jit_type_sys_short; 564 goto set_integer; 565 case '3': 566 t1 = jit_type_sys_int; 567 goto set_integer; 568 case '4': 569 t1 = jit_type_sys_long; 570 set_integer: 571 v1 = jit_insn_load_relative(f, args[i], 0, t1); 572 jit__vtable_set_integer_native(f, jit_interp, regs[j], v1); 573 j++; 574 break; 575 576 case 'V': 577 v1 = jit_insn_load_relative(f, args[i], 0, jit_type_void_ptr); 578 jit__vtable_set_pointer(f, jit_interp, regs[j], v1); 579 j++; 580 break; 581 582 case 'I': 583 case 'c': 584 case 'i': 585 case 'l': 586 case 'N': 587 case 'f': 588 case 'd': 589 case 'S': 590 case 'b': 591 case 'p': 592 case 'P': 593 case 'O': 594 case '@': 595 j++; 596 break; 597 598 default: 599 /* ignore */ 600 break; 601 } 602 } 603 } 604 605 static jit_value_t 606 jit_value_create_intval_constant(jit_function_t f, INTVAL i) { 607 return jit_value_create_nint_constant(f, JIT_TYPE_INTVAL, i); 608 } 609 610 /* 611 * JIT wrappers 612 */ 613 614 /* custom wrappers */ 615 static jit_value_t 616 jit__Buffer_bufstart(jit_function_t f, jit_value_t buf) { 617 return jit_insn_load_relative(f, buf, offsetof(Buffer, _bufstart), jit_type_void_ptr); 618 } 619 620 static jit_value_t 621 jit__CURRENT_CONTEXT(jit_function_t f, jit_value_t interp) { 622 return jit_insn_load_relative(f, interp, offsetof(struct parrot_interp_t, ctx), jit_type_void_ptr); 623 } 624 625 static jit_value_t 626 jit__PMC_IS_NULL(jit_function_t f, jit_value_t pmc) { 627 return jit_insn_or(f, 628 jit_insn_eq(f, pmc, 629 jit_value_create_nint_constant(f, jit_type_void_ptr, (jit_nint)NULL)), 630 jit_insn_eq(f, pmc, 631 jit_value_create_nint_constant(f, jit_type_void_ptr, (jit_nint)PMCNULL))); 632 } 633 634 static jit_value_t 635 jit__Parrot_pcc_get_signature(jit_function_t f, jit_value_t interp, jit_value_t ctx) { 636 return jit_insn_load_relative(f, 637 jit_insn_load_relative(f, ctx, offsetof(struct PMC, data), jit_type_void_ptr), 638 offsetof(struct Parrot_Context_attributes, current_sig), 639 jit_type_void_ptr); 640 } 641 642 /* vtable wrappers */ 643 @TEMP_vtable_wrap_defns@ 644 645 /* function wrappers */ 646 @TEMP_func_wrap_defns@ 647 648 #endif /* PARROT_HAS_LIBJIT */ 649 650 /* 651 * Local variables: 652 * c-file-style: "parrot" 653 * End: 654 * vim: expandtab shiftwidth=4: 655 */ -
config/gen/libjit/frame_builder_libjit_h.in
1 /* frame_builder_libjit.h 2 * $Id$ 3 * Copyright (C) 2009, Parrot Foundation. 4 */ 5 6 #ifndef PARROT_FRAME_BUILDER_LIBJIT_H_GUARD 7 #define PARROT_FRAME_BUILDER_LIBJIT_H_GUARD 8 9 10 #if defined(__cplusplus) 11 # define EXTERN extern "C" 12 #else 13 # define EXTERN 14 #endif 15 16 #include <assert.h> 17 #include "parrot/parrot.h" 18 #include "frame_builder.h" 19 20 #ifdef PARROT_HAS_LIBJIT 21 22 # include <jit/jit.h> 23 24 /* 25 * JITted function state data 26 */ 27 struct jit_buffer_private_data { 28 jit_context_t ctx; 29 char *sig; 30 }; 31 32 /* 33 * JIT types 34 */ 35 36 # define JIT_TYPE_UINTVAL @libjit_uv@ 37 # define JIT_TYPE_INTVAL @libjit_iv@ 38 # define JIT_TYPE_FLOATVAL @libjit_nv@ 39 40 /* 41 * JIT functions 42 */ 43 44 static void * 45 Parrot_jit_create_thunk(Interp *, char *, void *); 46 47 static void 48 Parrot_jit_parse_sig_args_pre(Interp *, char *, int, jit_function_t, jit_value_t, jit_value_t, jit_value_t, 49 jit_type_t *, jit_value_t *, jit_value_t *); 50 51 static jit_type_t 52 Parrot_jit_parse_sig_ret_pre(Interp *, char *); 53 54 static void 55 Parrot_jit_parse_sig_ret_post(Interp *, char *, jit_function_t, jit_value_t, jit_value_t, jit_value_t, jit_value_t); 56 57 static void 58 Parrot_jit_parse_sig_args_post(Interp *, char *, int, jit_function_t, jit_value_t, jit_value_t *, jit_value_t *); 59 60 static int 61 Parrot_jit_create_arg_regs(Interp *, char *, int, jit_function_t, jit_value_t *); 62 63 static void 64 Parrot_jit_fill_args(Interp *, char *, int, int, jit_function_t, jit_value_t, jit_value_t, jit_value_t, 65 jit_value_t *, jit_type_t *, jit_value_t *); 66 67 static jit_value_t 68 jit_value_create_intval_constant(jit_function_t, INTVAL); 69 70 /* 71 * workaround for platforms that lack libjit alloca support 72 */ 73 # if @libjit_has_alloca@ 74 # define JIT_ALLOCA(f, n) jit_insn_alloca((f), (n)) 75 # define JIT_ALLOCA_FREE(f, p) 76 # else 77 # define JIT_ALLOCA(f, n) jit__mem_sys_allocate((f), (n)) 78 # define JIT_ALLOCA_FREE(f, p) jit__mem_sys_free((f), (p)) 79 # endif 80 81 /* 82 * JIT wrappers 83 */ 84 85 /* custom wrappers */ 86 static jit_value_t 87 jit__Buffer_bufstart(jit_function_t, jit_value_t); 88 89 static jit_value_t 90 jit__CURRENT_CONTEXT(jit_function_t, jit_value_t); 91 92 static jit_value_t 93 jit__PMC_IS_NULL(jit_function_t, jit_value_t); 94 95 static jit_value_t 96 jit__Parrot_pcc_get_signature(jit_function_t, jit_value_t, jit_value_t); 97 98 /* vtable wrappers */ 99 @TEMP_vtable_wrap_decls@ 100 101 /* function wrappers */ 102 @TEMP_func_wrap_decls@ 103 104 #endif /* PARROT_HAS_LIBJIT */ 105 #endif /* PARROT_FRAME_BUILDER_LIBJIT_H_GUARD */ 106 107 /* 108 * Local variables: 109 * c-file-style: "parrot" 110 * End: 111 * vim: expandtab shiftwidth=4: 112 */