remove deprecation notice for TT #449
[parrot.git] / src / frame_builder.c
blobad0b02ed03dd3d3b2b16dacd931101805e4ab3cf
1 /*
2 Copyright (C) 2008-2009, Parrot Foundation.
3 $Id$
5 =head1 NAME
7 src/frame_builder.c
9 =head1 DESCRIPTION
11 Functions for the ManagedStruct PMC and others.
13 =head1 FUNCTIONS
15 =cut
19 /* HEADERIZER HFILE: none */
20 /* HEADERIZER STOP */
22 #include "parrot/parrot.h"
23 #include "pmc/pmc_fixedintegerarray.h"
24 #include "pmc/pmc_unmanagedstruct.h"
25 #include "pmc/pmc_managedstruct.h"
26 #include "frame_builder.h"
30 =over 4
32 =item C<void Parrot_jit_free_buffer(PARROT_INTERP, void *ptr, void *priv)>
34 This is a callback to implement the proper freeing semantics. It is called by
35 the ManagedStruct PMC as it is garbage collected.
37 =cut
41 void
42 Parrot_jit_free_buffer(SHIM_INTERP, void *ptr, void *priv)
44 const struct jit_buffer_private_data * const jit = (struct jit_buffer_private_data*)priv;
45 mem_free_executable(ptr, jit->size);
46 free(priv);
51 =item C<PMC *Parrot_jit_clone_buffer(PARROT_INTERP, PMC *pmc, void *priv)>
53 This is a callback to implement the proper cloning semantics for jit buffers.
54 It is called by the ManagedStruct PMC's clone() function.
56 =back
58 =cut
62 PMC *
63 Parrot_jit_clone_buffer(PARROT_INTERP, PMC *pmc, void *priv)
65 PMC * const rv = Parrot_pmc_new(interp, pmc->vtable->base_type);
67 VTABLE_init(interp, rv);
68 /* copy the attributes */
70 void (*tmpfreefunc)(PARROT_INTERP, void*, void*);
71 GETATTR_ManagedStruct_custom_free_func(interp, pmc, tmpfreefunc);
72 SETATTR_ManagedStruct_custom_free_func(interp, rv , tmpfreefunc);
75 PMC* (*tmpclonefunc)(PARROT_INTERP, PMC*, void*);
76 GETATTR_ManagedStruct_custom_clone_func(interp, pmc, tmpclonefunc);
77 SETATTR_ManagedStruct_custom_clone_func(interp, rv , tmpclonefunc);
81 void *freepriv, *clonepriv;
82 GETATTR_ManagedStruct_custom_free_priv(interp , pmc, freepriv);
83 GETATTR_ManagedStruct_custom_clone_priv(interp, pmc, clonepriv);
84 if (freepriv) {
85 void *tmp = mem_gc_allocate_zeroed_typed(interp, struct jit_buffer_private_data);
86 memcpy(tmp, freepriv, sizeof (struct jit_buffer_private_data));
87 SETATTR_ManagedStruct_custom_free_priv(interp, rv , tmp);
88 if (clonepriv == freepriv) {
89 /* clonepriv is a copy of freepriv, make it a copy in the clone too. */
90 SETATTR_ManagedStruct_custom_clone_priv(interp, rv , tmp);
91 clonepriv = NULL; /* disable the clonepriv copying below */
94 if (clonepriv) {
95 void *tmp = mem_gc_allocate_zeroed_typed(interp, struct jit_buffer_private_data);
96 memcpy(tmp, clonepriv, sizeof (struct jit_buffer_private_data));
97 SETATTR_ManagedStruct_custom_clone_priv(interp, rv , tmp);
101 /* copy the execmem buffer */
102 if (PARROT_MANAGEDSTRUCT(pmc)->ptr) {
103 struct jit_buffer_private_data *jit = (struct jit_buffer_private_data*)priv;
104 void *ptr = PARROT_MANAGEDSTRUCT(pmc)->ptr;
105 void *newptr = mem_alloc_executable(jit->size);
106 if (!newptr)
107 Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_JIT_ERROR,
108 "Cannot allocate executable memory");
109 memcpy(newptr, ptr, jit->size);
110 PARROT_MANAGEDSTRUCT(rv)->ptr = newptr;
113 return rv;
118 emit_is8bit(long disp)
120 return disp >= -128 && disp <= 127;
123 char *
124 emit_disp8_32(char *pc, int disp)
126 if (emit_is8bit(disp)) {
127 *(pc++) = (char)disp;
128 return pc;
130 else {
131 *(long *)pc = disp;
132 return pc + 4;
136 void
137 emit_sib(PARROT_INTERP, char *pc, int scale, int i, int base)
139 int scale_byte;
141 switch (scale) {
142 case 1:
143 scale_byte = emit_Scale_1;
144 break;
145 case 2:
146 scale_byte = emit_Scale_2;
147 break;
148 case 4:
149 scale_byte = emit_Scale_4;
150 break;
151 case 8:
152 scale_byte = emit_Scale_8;
153 break;
154 default:
155 Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_JIT_ERROR,
156 "Invalid scale factor %d\n", scale);
157 return;
160 *pc = (char)(scale_byte | (i == emit_None ? emit_Index_None : emit_reg_Index(i)) |
161 emit_reg_Base(base));
164 char *
165 emit_r_X(PARROT_INTERP, char *pc, int reg_opcode, int base, int i, int scale, long disp)
167 if (i && !scale)
168 Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_JIT_ERROR,
169 "emit_r_X passed invalid scale+index combo\n");
171 if (base == emit_EBP) {
172 /* modrm disp */
173 if (i == emit_None) {
174 *(pc++) = (char)((emit_is8bit(disp) ? emit_Mod_b01 : emit_Mod_b10)
175 | reg_opcode | emit_reg_rm(emit_EBP));
176 return emit_disp8_32(pc, disp);
178 /* modrm sib disp */
179 else {
180 *(pc++) = (char)((emit_is8bit(disp) ? emit_Mod_b01 : emit_Mod_b10)
181 | reg_opcode | emit_b100);
182 emit_sib(interp, pc++, scale, i, base);
183 return emit_disp8_32(pc, disp);
187 /* modrm sib disp */
188 if (base == emit_ESP) {
189 *(pc++) = (char)((emit_is8bit(disp) ? emit_Mod_b01 : emit_Mod_b10)
190 | reg_opcode | emit_rm_b100);
191 emit_sib(interp, pc++, scale, i, emit_ESP);
192 return emit_disp8_32(pc, disp);
195 /* modrm disp32 */
196 if (!base && !(i && scale)) {
197 *(pc++) = (char)(emit_Mod_b00 | reg_opcode | emit_rm_b101);
198 *(long *)pc = disp;
199 return pc + 4;
202 /* Ok, everything should be more regular here */
203 *(pc++) = (char)((disp == 0 ? emit_Mod_b00 :
204 (emit_is8bit(disp) ?
205 emit_Mod_b01 : emit_Mod_b10)) |
206 reg_opcode |
207 (!base || (scale && i) ? emit_rm_b100 : emit_reg_rm(base)));
209 if (!base || (scale && i)) {
210 emit_sib(interp, pc++, scale, i, base);
212 if (disp)
213 pc = emit_disp8_32(pc, disp);
215 return pc;
218 char *
219 emit_shift_i_r(PARROT_INTERP, char *pc, int opcode, int imm, int reg)
221 if (opcode == emit_b000 && imm < 0) {
222 opcode = emit_b001; /* -rol => 32 + ror */
223 imm = -imm;
226 if (imm == 0) {
227 /* noop */
229 else if (imm == 1) {
230 *(pc++) = (char) 0xd1;
231 *(pc++) = (char) emit_alu_X_r(opcode, reg);
233 else if (imm > 1 && imm < 33) {
234 *(pc++) = (char) 0xc1;
235 *(pc++) = (char) emit_alu_X_r(opcode, reg);
236 *(pc++) = (char)imm;
238 else {
239 Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_JIT_ERROR,
240 "emit_shift_i_r passed invalid shift\n");
243 return pc;
246 char *
247 emit_popl_r(char *pc, int reg)
249 *(pc++) = (char)(0x58 | (reg - 1));
250 return pc;
253 unsigned char *lastpc;
255 size_t
256 calc_signature_needs(const char *sig, int *strings)
258 size_t stack_size = 0;
259 while (*sig) {
260 switch (*sig) {
261 case 't':
262 ++(*strings);
263 stack_size +=4;
264 break;
265 case 'd':
266 stack_size +=8;
267 break;
268 default:
269 stack_size +=4;
270 break;
272 ++sig;
274 return stack_size;
279 * The function generated here is called as func(interp, nci_info)
280 * interp ... 8(%ebp)
281 * nci_info ... 12(%ebp)
283 * The generate function for a specific signature looks quite similar to
284 * an optimized compile of src/nci.c:pcf_x_yy(). In case of any troubles
285 * just compare the disassembly.
287 * If a non-NULL sizeptr is passed, the integer it points to will be written
288 * with the size of the allocated execmem buffer.
291 void *
292 Parrot_jit_build_call_func(PARROT_INTERP, PMC *pmc_nci, STRING *signature, int *sizeptr)
294 char *pc;
295 char *execmem;
296 int i = 0;
297 int arg_count = 0;
298 int string_buffer_count = 0;
299 const int ST_SIZE_OF = 124;
300 const int JIT_ALLOC_SIZE = 1024;
302 char * const signature_str = Parrot_str_to_cstring(interp, signature);
303 /* skip over the result */
304 char *sig = signature_str + 1;
305 size_t stack_space_needed = calc_signature_needs(sig,
306 &string_buffer_count);
308 int base_offset = 0;
309 int strings_offset = base_offset - (sizeof (char *) * string_buffer_count);
310 int st_offset = strings_offset - ST_SIZE_OF;
311 int args_offset = st_offset - stack_space_needed;
312 int temp_calls_offset = args_offset - 16;
313 int total_stack_needed = -temp_calls_offset;
315 UNUSED(pmc_nci);
318 * ESP
319 * 0-15, 16 bytes for utility calls
320 * stack_space_needed for actual NCI call
321 * st
322 * STRINGS -> char * holding space
323 * EBP
326 /* this ought to be enough - the caller of this function
327 * should free the function pointer returned here
329 pc = execmem = (char *)mem_alloc_executable(JIT_ALLOC_SIZE);
330 if (! pc)
331 Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_JIT_ERROR,
332 "Cannot allocate executable memory");
335 /* this generated jit function will be called as (INTERP (EBP 8), func_ptr
336 * (ESP 12), args signature (ESP 16)) */
338 /* make stack frame, preserve %ebx */
339 jit_emit_stack_frame_enter(pc);
341 emitm_subl_i_r(pc, total_stack_needed, emit_ESP);
343 /* Parrot_init_arg_nci(interp, &st, "S"); */
344 /* args signature "S" */
345 emitm_movl_m_r(interp, pc, emit_EAX, emit_EBP, 0, 1, 16);
346 emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 8);
348 /*&st*/
349 emitm_lea_m_r(interp, pc, emit_EAX, emit_EBP, 0, 1, st_offset);
350 emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 4);
352 /*interpreter*/
353 emitm_movl_m_r(interp, pc, emit_EAX, emit_EBP, 0, 1, 8);
354 emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 0);
356 /* XXX FIXME (TT #1325) This whole function require major rework */
357 /* if (sig && *sig) */
358 /* emitm_call_cfunc(pc, Parrot_init_arg_nci); */
360 while (*sig) {
361 emitm_movl_i_m(pc, arg_count, emit_EBP, 0, 1, temp_calls_offset + 8);
363 switch (*sig) {
364 case '0': /* null ptr or such - doesn't consume a reg */
365 jit_emit_bxor_rr_i(interp, pc, emit_EAX, emit_EAX);
366 emitm_movl_m_r(interp, pc, emit_EAX, emit_EBP, 0, 1, args_offset);
367 break;
368 case 'f':
369 /* FIXME (TT #1325) emitm_call_cfunc(pc, get_nci_N); */
370 emitm_fstps(interp, pc, emit_EBP, 0, 1, args_offset);
371 break;
372 case 'N':
373 case 'd':
374 /* FIXME (TT #1325) emitm_call_cfunc(pc, get_nci_N); */
375 emitm_fstpl(interp, pc, emit_EBP, 0, 1, args_offset);
376 args_offset += 4;
377 break;
378 case 'I': /* INTVAL */
379 case 'l': /* long */
380 case 'i': /* int */
381 /* FIXME (TT #1325) emitm_call_cfunc(pc, get_nci_I); */
382 emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, args_offset);
383 break;
384 case 't': /* string, pass a cstring */
385 /* FIXME (TT #1325) emitm_call_cfunc(pc, get_nci_S); */
386 emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 4);
387 emitm_call_cfunc(pc, string_to_cstring_nullable);
389 emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, args_offset);
390 /* save off temporary allocation address */
391 emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, strings_offset);
392 strings_offset += 4;
394 /* reset ESP(4) */
395 emitm_lea_m_r(interp, pc, emit_EAX, emit_EBP, 0, 1, st_offset);
396 emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 4);
397 break;
398 case 's': /* short: movswl intreg_o(base), %eax */
399 /* FIXME (TT #1325) emitm_call_cfunc(pc, get_nci_I); */
400 emitm_movswl_r_r(pc, emit_EAX, emit_EAX);
401 emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, args_offset);
402 break;
403 case 'c': /* char: movsbl intreg_o(base), %eax */
404 /* emitm_call_cfunc(pc, get_nci_I); */
405 emitm_movsbl_r_r(pc, emit_EAX, emit_EAX);
406 emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, args_offset);
407 break;
408 case 'J': /* interpreter */
409 emitm_movl_m_r(interp, pc, emit_EAX, emit_EBP, 0, 1, 8);
410 emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, args_offset);
411 --arg_count;
412 break;
413 case 'p': /* push pmc->data */
414 /* FIXME (TT #1325) emitm_call_cfunc(pc, get_nci_p); */
415 emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, args_offset);
416 break;
417 case 'O': /* push PMC * object in P2 */
418 case 'P': /* push PMC * */
419 case '@':
420 /* FIXME (TT #1325) emitm_call_cfunc(pc, get_nci_P); */
421 emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, args_offset);
422 break;
423 case 'v':
424 break;
425 case 'b': /* buffer (void*) pass Buffer_bufstart(SReg) */
426 /* FIXME (TT #1325) emitm_call_cfunc(pc, get_nci_S); */
427 emitm_movl_m_r(interp, pc, emit_EAX, emit_EAX, 0, 1,
428 (size_t) &Buffer_bufstart((STRING *) NULL));
429 emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, args_offset);
430 break;
431 case 'B': /* buffer (void**) pass &Buffer_bufstart(SReg) */
432 /* FIXME (TT #1325) emitm_call_cfunc(pc, get_nci_S); */
433 emitm_lea_m_r(interp, pc, emit_EAX, emit_EAX, 0, 1,
434 (size_t) &Buffer_bufstart((STRING *) NULL));
435 emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, args_offset);
436 break;
437 case 'S':
438 /* FIXME (TT #1325) emitm_call_cfunc(pc, get_nci_S); */
439 emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, args_offset);
440 break;
443 /* I have no idea how to handle these */
444 case '2':
445 case '3':
446 case '4':
447 case 'V':
448 mem_free_executable(execmem, JIT_ALLOC_SIZE);
449 Parrot_str_free_cstring(signature_str);
450 return NULL;
451 break;
452 default:
453 Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_JIT_ERROR,
454 "Unknown arg Signature %c\n", *sig);
456 * oops unknown signature:
457 * cleanup and try nci.c
459 mem_free_executable(execmem, JIT_ALLOC_SIZE);
460 Parrot_str_free_cstring(signature_str);
461 return NULL;
463 args_offset +=4;
464 ++arg_count;
465 ++sig;
468 /* prepare to call VTABLE_get_pointer, set up args */
469 /* interpreter - movl 8(%ebp), %eax */
470 emitm_movl_m_r(interp, pc, emit_EAX, emit_EBP, 0, 1, 8);
471 emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 0);
473 /* pmc - movl 12(%ebp), %eax */
474 emitm_movl_m_r(interp, pc, emit_EAX, emit_EBP, 0, 1, 12);
475 emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 4);
477 /* get the get_pointer() pointer from the pmc's vtable */
478 emitm_movl_m_r(interp, pc, emit_EAX, emit_EAX, 0, 1, offsetof(PMC, vtable));
479 emitm_movl_m_r(interp, pc, emit_EAX, emit_EAX, 0, 1, offsetof(VTABLE, get_pointer));
481 /* call get_pointer(), result goes into eax */
482 emitm_callr(pc, emit_EAX);
483 emitm_addl_i_r(pc, 16, emit_ESP);
485 /* call the resulting function pointer */
486 emitm_callr(pc, emit_EAX);
487 emitm_subl_i_r(pc, 16, emit_ESP);
489 /* SAVE OFF EAX */
490 emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 8);
492 /*&st*/
493 emitm_lea_m_r(interp, pc, emit_EAX, emit_EBP, 0, 1, st_offset);
494 emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 4);
496 /*interpreter*/
497 emitm_movl_m_r(interp, pc, emit_EAX, emit_EBP, 0, 1, 8);
498 emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 0);
500 /* RESTORE BACK EAX */
501 emitm_movl_m_r(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 8);
503 /* now place return value in registers */
504 /* first in signature is the return value */
505 sig = signature_str; /* the result */
506 switch (*sig) {
507 /* I have no idea how to handle these */
508 case '2':
509 case '3':
510 case '4':
511 /* get integer from pointer - untested */
512 emitm_movl_m_r(interp, pc, emit_EAX, emit_EAX, 0, 1, 0);
513 if (*sig == 2) /* short */
514 emitm_movswl_r_r(pc, emit_EAX, emit_EAX);
515 /* XXX FIXME (TT #1325) emitm_call_cfunc(pc, set_nci_I);*/
516 break;
517 case 'f':
518 case 'd':
519 jit_emit_fstore_mb_n(interp, pc, emit_EBP, temp_calls_offset + 8);
520 /* XXX FIXME (TT #1325) emitm_call_cfunc(pc, set_nci_N); */
521 /* pop num from st(0) and mov to reg */
522 break;
523 case 's':
524 /* movswl %ax, %eax */
525 emitm_movswl_r_r(pc, emit_EAX, emit_EAX);
526 emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 8);
527 /* XXX FIXME (TT #1325) emitm_call_cfunc(pc, set_nci_I); */
528 break;
529 case 'c':
530 /* movsbl %al, %eax */
531 emitm_movsbl_r_r(pc, emit_EAX, emit_EAX);
532 emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 8);
533 /* XXX FIXME (TT #1325) emitm_call_cfunc(pc, set_nci_I); */
534 break;
535 case 'I': /* INTVAL */
536 case 'l':
537 case 'i':
538 emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 8);
539 /* XXX FIXME (TT #1325) emitm_call_cfunc(pc, set_nci_I); */
540 break;
541 case 'v': /* void - do nothing */
542 break;
543 case 'P':
544 emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 8);
545 /* XXX FIXME (TT #1325) emitm_call_cfunc(pc, set_nci_P); */
546 break;
547 case 'p': /* make a new unmanaged struct */
548 /* save return value on stack */
550 /* save pointer p */
551 emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 12);
553 /* make new pmc */
554 emitm_movl_i_m(pc, enum_class_UnManagedStruct, emit_EBP, 0, 1, temp_calls_offset + 4);
555 emitm_call_cfunc(pc, Parrot_pmc_new);
557 /* restore pointer p to EDX */
558 emitm_movl_m_r(interp, pc, emit_EDX, emit_EBP, 0, 1, temp_calls_offset + 12);
560 /* copy UnManagedStruct to stack for set_nci_P call */
561 emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 8);
563 /* eax = PMC, get return value into edx */
564 /* mov data(%eax), %eax
565 mov %edx, ptr(%eax) */
566 emitm_movl_m_r(interp, pc, emit_EAX, emit_EAX, 0, 1, offsetof(struct PMC, data));
567 emitm_movl_r_m(interp, pc, emit_EDX, emit_EAX, 0, 1,
568 offsetof(struct Parrot_UnManagedStruct_attributes, ptr));
570 /* reset EBP(4) */
571 emitm_lea_m_r(interp, pc, emit_EAX, emit_EBP, 0, 1, st_offset);
572 emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 4);
574 /* XXX FIXME (TT #1325) emitm_call_cfunc(pc, set_nci_P); */
575 break;
576 case 'S':
577 emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 8);
578 /* XXX FIXME (TT #1325) emitm_call_cfunc(pc, set_nci_S); */
579 break;
580 case 't': /* string */
581 /* EAX is char* */
582 emitm_movl_i_m(pc, 0, emit_EBP, 0, 1, temp_calls_offset + 8); /* len */
584 /* overwrites address of st in EBP(4) */
585 emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 4);
587 emitm_call_cfunc(pc, Parrot_str_new);
589 emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 8);
591 /* reset EBP(4) */
592 emitm_lea_m_r(interp, pc, emit_EAX, emit_EBP, 0, 1, st_offset);
593 emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 4);
595 /* XXX FIXME (TT #1325) emitm_call_cfunc(pc, set_nci_S); */
596 break;
597 default:
598 Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_JIT_ERROR,
599 "Unknown return Signature %c\n", *sig);
601 * oops unknown signature:
602 * cleanup and try nci.c
604 Parrot_str_free_cstring(signature_str);
605 mem_free_executable(execmem, JIT_ALLOC_SIZE);
606 return NULL;
609 /* free temporary strings */
610 strings_offset = st_offset + ST_SIZE_OF;
611 for (i=0; i<string_buffer_count; ++i) {
612 emitm_movl_m_r(interp, pc, emit_EAX, emit_EBP, 0, 1, strings_offset);
613 emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 0);
614 emitm_call_cfunc(pc, Parrot_str_free_cstring);
615 strings_offset += 4;
618 jit_emit_stack_frame_leave(pc);
619 emitm_ret(pc);
620 PARROT_ASSERT(pc - execmem <= JIT_ALLOC_SIZE);
622 if (sizeptr)
623 *sizeptr = JIT_ALLOC_SIZE;
624 Parrot_str_free_cstring(signature_str);
625 return (void *)D2FPTR(execmem);
629 * Local variables:
630 * c-file-style: "parrot"
631 * End:
632 * vim: expandtab shiftwidth=4: