I still think too much junk is in jit_emit.h
The patch attached shows how I would re-factor it.
Kevin
NotFound wrote:
On Fri, Aug 22, 2008 at 9:51 PM, Kevin Tew <[EMAIL PROTECTED]> wrote:
0015a810 t Parrot_store_arg
little t means its not exported.
set_nci_* functions should probably be moved elsewhere.
as well as the Parrot_jit_build_call_func
I found Parrot_jit_build_call_func in src/jit/i386/jit_emit.h, so I made
my changes in place.
Parrot_store_arg lacked the PARROT_API attribute. Fixed in r30457
diff --git a/config/auto/jit.pm b/config/auto/jit.pm
index 8897dc3..702bdbd 100644
--- a/config/auto/jit.pm
+++ b/config/auto/jit.pm
@@ -108,7 +108,7 @@ sub runstep {
jitcapable => 1,
cc_hasjit => " -DHAS_JIT -D\U$jitcpuarch",
TEMP_jit_o =>
-'$(SRC_DIR)/jit$(O) $(SRC_DIR)/jit_cpu$(O) $(SRC_DIR)/jit_debug$(O) $(SRC_DIR)/jit_debug_xcoff$(O)'
+'$(SRC_DIR)/jit$(O) $(SRC_DIR)/jit_cpu$(O) $(SRC_DIR)/jit_build_call$(O) $(SRC_DIR)/jit_debug$(O) $(SRC_DIR)/jit_debug_xcoff$(O)'
);
my $execcapable = $self->_first_probe_for_exec(
diff --git a/config/gen/makefiles/root.in b/config/gen/makefiles/root.in
index bc2bc15..aeed059 100644
--- a/config/gen/makefiles/root.in
+++ b/config/gen/makefiles/root.in
@@ -223,6 +223,7 @@ GEN_SOURCES = \
$(SRC_DIR)/nci.c \
$(SRC_DIR)/core_ops_switch.c \
$(SRC_DIR)/jit_cpu.c \
+ $(SRC_DIR)/jit_build_call.c \
$(SRC_DIR)/parrot_config.c \
$(SRC_DIR)/null_config.c \
$(SRC_DIR)/install_config.c \
@@ -1053,6 +1054,8 @@ $(SRC_DIR)/jit_debug_xcoff$(O) : $(GENERAL_H_FILES)
$(SRC_DIR)/jit_cpu$(O) : $(GENERAL_H_FILES) $(SRC_DIR)/jit_emit.h
+$(SRC_DIR)/jit_build_call$(O) : $(GENERAL_H_FILES) $(SRC_DIR)/jit_emit.h
+
$(SRC_DIR)/exec$(O) : $(GENERAL_H_FILES) @TEMP_exec_h@ $(SRC_DIR)/jit_emit.h
$(SRC_DIR)/exec_dep$(O) : $(GENERAL_H_FILES) @TEMP_exec_h@ $(SRC_DIR)/jit_emit.h
@@ -1243,6 +1246,8 @@ $(SRC_DIR)/jit_emit.h : $(SRC_DIR)/jit/@jitcpuarch@/jit_emit.h
$(CP) $(SRC_DIR)/jit/@jitcpuarch@/jit_emit.h $(SRC_DIR)/jit_emit.h
$(SRC_DIR)/exec_dep.h : $(SRC_DIR)/jit/@jitcpuarch@/exec_dep.h
$(CP) $(SRC_DIR)/jit/@jitcpuarch@/exec_dep.h $(SRC_DIR)/exec_dep.h
+$(SRC_DIR)/jit_build_call.c : $(SRC_DIR)/jit/@jitcpuarch@/jit_build_call.c
+ $(CP) $(SRC_DIR)/jit/@jitcpuarch@/jit_build_call.c $(SRC_DIR)/jit_build_call.c
$(SRC_DIR)/jit_cpu.c : lib/Parrot/OpLib/core.pm $(SRC_DIR)/jit_emit.h \
$(SRC_DIR)/jit/@jitcpuarch@/core.jit $(JIT_BUILD_TOOL)
$(PERL) $(JIT_BUILD_TOOL) @jitcpuarch@ $(SRC_DIR)/jit_cpu.c
@@ -1669,6 +1674,7 @@ archclean: dynoplibs-clean dynpmc-clean dynext-clean
$(SRC_DIR)/asmfun.s \
$(SRC_DIR)/jit_emit.h \
$(SRC_DIR)/jit_cpu.c \
+ $(SRC_DIR)/jit_build_call.c \
$(SRC_DIR)/exec_cpu.c \
$(SRC_DIR)/exec_start$(O) \
install_config.fpmc \
diff --git a/include/parrot/nci.h b/include/parrot/nci.h
index 1b85a73..10a133a 100644
--- a/include/parrot/nci.h
+++ b/include/parrot/nci.h
@@ -17,6 +17,27 @@
void *build_call_func(PARROT_INTERP, SHIM(PMC *pmc_nci), NOTNULL(STRING *signature), NOTNULL(int *jitted));
+/*
+ * helper funcs - get argument n
+ */
+INTVAL get_nci_I(PARROT_INTERP, ARGMOD(call_state *st), int n);
+FLOATVAL get_nci_N(PARROT_INTERP, ARGMOD(call_state *st), int n);
+
+PARROT_WARN_UNUSED_RESULT
+PARROT_CANNOT_RETURN_NULL
+STRING* get_nci_S(PARROT_INTERP, ARGMOD(call_state *st), int n);
+
+PARROT_WARN_UNUSED_RESULT
+PARROT_CANNOT_RETURN_NULL
+PMC* get_nci_P(PARROT_INTERP, ARGMOD(call_state *st), int n);
+
+/*
+ * set return value
+ */
+void set_nci_I(PARROT_INTERP, ARGOUT(call_state *st), INTVAL val);
+void set_nci_N(PARROT_INTERP, ARGOUT(call_state *st), FLOATVAL val);
+void set_nci_S(PARROT_INTERP, ARGOUT(call_state *st), STRING *val);
+void set_nci_P(PARROT_INTERP, ARGOUT(call_state *st), PMC* val);
#endif /* PARROT_NCI_H_GUARD */
/*
diff --git a/src/jit/i386/jit_build_call.c b/src/jit/i386/jit_build_call.c
new file mode 100644
index 0000000..94e2e57
--- /dev/null
+++ b/src/jit/i386/jit_build_call.c
@@ -0,0 +1,367 @@
+#include "parrot/parrot.h"
+#include "parrot/hash.h"
+#include "parrot/oplib/ops.h"
+#include "jit.h"
+#define JIT_EMIT 1
+#include "jit_emit.h"
+
+static size_t
+calc_signature_needs(const char *sig, int *strings)
+{
+ size_t stack_size = 0;
+ while (*sig) {
+ switch (*sig) {
+ case 't':
+ (*strings)++;
+ stack_size +=4;
+ break;
+ case 'd':
+ stack_size +=8;
+ break;
+ default:
+ stack_size +=4;
+ break;
+ }
+ sig++;
+ }
+ return stack_size;
+
+}
+/*
+ * The function generated here is called as func(interp, nci_info)
+ * interp ... 8(%ebp)
+ * nci_info ... 12(%ebp)
+ *
+ * The generate function for a specific signature looks quite similar to
+ * an optimized compile of src/nci.c:pcf_x_yy(). In case of any troubles
+ * just compare the disassembly.
+ */
+void *
+Parrot_jit_build_call_func(PARROT_INTERP, PMC *pmc_nci, STRING *signature)
+{
+ Parrot_jit_info_t jit_info;
+ int i = 0;
+ char *pc;
+ int arg_count = 0;
+ int strings = 0;
+ const int ST_SIZE_OF = 124;
+ const int JIT_ALLOC_SIZE = 1024;
+
+ char *sig = (char *)signature->strstart + 1; /* skip over the result */
+ size_t stack_space_needed = calc_signature_needs(sig, &strings);
+
+ int st_offset = 16 + stack_space_needed;
+ int args_offset = 16;
+ int strings_offset = st_offset + ST_SIZE_OF;
+ int total_stack_needed = strings_offset + 4 * strings;
+
+ /* this ought to be enough - the caller of this function
+ * should free the function pointer returned here
+ */
+ pc = jit_info.native_ptr = jit_info.arena.start = (char *)mem_alloc_executable(JIT_ALLOC_SIZE);
+
+
+ /* this generated jit function will be called as (INTERP (EBP 8), func_ptr (ESP 12), args signature (ESP 16)) */
+ /* make stack frame, preserve %ebx */
+ jit_emit_stack_frame_enter(pc);
+
+ emitm_subl_i_r(pc, total_stack_needed, emit_ESP);
+
+ /* Parrot_init_arg_nci(interp, &st, "S"); */
+ emitm_movl_m_r(interp, pc, emit_EAX, emit_EBP, 0, 1, 16);
+ emitm_movl_r_m(interp, pc, emit_EAX, emit_ESP, 0, 1, 8);
+
+ /*&st*/
+ emitm_lea_m_r(interp, pc, emit_EAX, emit_ESP, 0, 1, st_offset);
+ emitm_movl_r_m(interp, pc, emit_EAX, emit_ESP, 0, 1, 4);
+
+ /*interpreter*/
+ emitm_movl_m_r(interp, pc, emit_EAX, emit_EBP, 0, 1, 8);
+ emitm_movl_r_m(interp, pc, emit_EAX, emit_ESP, 0, 1, 0);
+
+ if (sig && *sig)
+ emitm_call_cfunc(pc, Parrot_init_arg_nci);
+
+ while (*sig) {
+ emitm_movl_i_m(pc, arg_count, emit_ESP, 0, 1, 8);
+
+ switch (*sig) {
+ case '0': /* null ptr or such - doesn't consume a reg */
+ jit_emit_bxor_rr_i(interp, pc, emit_EAX, emit_EAX);
+ emitm_movl_m_r(interp, pc, emit_EAX, emit_ESP, 0, 1, args_offset);
+ break;
+ case 'f':
+ emitm_call_cfunc(pc, get_nci_N);
+ emitm_fstps(interp, pc, emit_ESP, 0, 1, args_offset);
+ break;
+ case 'N':
+ case 'd':
+ emitm_call_cfunc(pc, get_nci_N);
+ emitm_fstpl(interp, pc, emit_ESP, 0, 1, args_offset);
+ args_offset += 4;
+ break;
+ case 'I': /* INTVAL */
+ case 'l': /* long */
+ case 'i': /* int */
+ emitm_call_cfunc(pc, get_nci_I);
+ emitm_movl_r_m(interp, pc, emit_EAX, emit_ESP, 0, 1, args_offset);
+ break;
+ case 't': /* string, pass a cstring */
+ emitm_call_cfunc(pc, get_nci_S);
+ emitm_movl_r_m(interp, pc, emit_EAX, emit_ESP, 0, 1, 4);
+ emitm_call_cfunc(pc, string_to_cstring);
+
+ emitm_movl_r_m(interp, pc, emit_EAX, emit_ESP, 0, 1, args_offset);
+ /* save off temporary allocation address */
+ emitm_movl_r_m(interp, pc, emit_EAX, emit_ESP, 0, 1, strings_offset);
+ strings_offset += 4;
+
+ /* reset ESP(4) */
+ emitm_lea_m_r(interp, pc, emit_EAX, emit_ESP, 0, 1, st_offset);
+ emitm_movl_r_m(interp, pc, emit_EAX, emit_ESP, 0, 1, 4);
+ break;
+ case 's': /* short: movswl intreg_o(base), %eax */
+ emitm_call_cfunc(pc, get_nci_I);
+ emitm_movswl_r_r(pc, emit_EAX, emit_EAX)
+ emitm_movl_r_m(interp, pc, emit_EAX, emit_ESP, 0, 1, args_offset);
+ break;
+ case 'c': /* char: movsbl intreg_o(base), %eax */
+ emitm_call_cfunc(pc, get_nci_I);
+ emitm_movsbl_r_r(pc, emit_EAX, emit_EAX);
+ emitm_movl_r_m(interp, pc, emit_EAX, emit_ESP, 0, 1, args_offset);
+ break;
+ case 'J': /* interpreter */
+ emitm_movl_m_r(interp, pc, emit_EAX, emit_EBP, 0, 1, 8);
+ emitm_movl_r_m(interp, pc, emit_EAX, emit_ESP, 0, 1, args_offset);
+ arg_count--;
+ break;
+ case 'p': /* push pmc->data */
+ emitm_call_cfunc(pc, get_nci_P);
+# if ! PMC_DATA_IN_EXT
+ /* mov pmc, %edx
+ * mov 8(%edx), %eax
+ * push %eax
+ */
+ emitm_movl_m_r(interp, pc, emit_EAX, emit_EAX, 0, 1, offsetof(struct PMC, data));
+# else
+ /* push pmc->pmc_ext->data
+ * mov pmc, %edx
+ * mov pmc_ext(%edx), %eax
+ * mov data(%eax), %eax
+ * push %eax
+ */
+ emitm_movl_m_r(interp, pc, emit_EAX, emit_EAX, 0, 1, offsetof(struct PMC, pmc_ext));
+ emitm_movl_m_r(interp, pc, emit_EAX, emit_EAX, 0, 1, offsetof(struct PMC_EXT, data));
+# endif
+ emitm_movl_r_m(interp, pc, emit_EAX, emit_ESP, 0, 1, args_offset);
+ break;
+ case 'O': /* push PMC * object in P2 */
+ case 'P': /* push PMC * */
+ case '@':
+ emitm_call_cfunc(pc, get_nci_P);
+# if PARROT_CATCH_NULL
+ /* PMCNULL is a global */
+ jit_emit_cmp_rm_i(pc, emit_EAX, &PMCNULL);
+ emitm_jxs(pc, emitm_jne, 2); /* skip the xor */
+ jit_emit_bxor_rr_i(interp, pc, emit_EAX, emit_EAX);
+# endif
+ emitm_movl_r_m(interp, pc, emit_EAX, emit_ESP, 0, 1, args_offset);
+ break;
+ case 'v':
+ break;
+ case 'V':
+ emitm_call_cfunc(pc, get_nci_P);
+ emitm_lea_m_r(interp, pc, emit_EAX, emit_EAX, 0, 1, offsetof(struct PMC, data));
+ /* emitm_lea_m_r(interp, pc, emit_EAX, emit_EAX, 0, 1, 0); */
+ emitm_movl_r_m(interp, pc, emit_EAX, emit_ESP, 0, 1, args_offset);
+ break;
+ case 'b': /* buffer (void*) pass PObj_bufstart(SReg) */
+ emitm_call_cfunc(pc, get_nci_S);
+ emitm_movl_m_r(interp, pc, emit_EAX, emit_EAX, 0, 1, (size_t) &PObj_bufstart((STRING *) 0));
+ emitm_movl_r_m(interp, pc, emit_EAX, emit_ESP, 0, 1, args_offset);
+ break;
+ case 'B': /* buffer (void**) pass &PObj_bufstart(SReg) */
+ emitm_call_cfunc(pc, get_nci_S);
+ emitm_lea_m_r(interp, pc, emit_EAX, emit_EAX, 0, 1, (size_t) &PObj_bufstart((STRING *) 0));
+ emitm_movl_r_m(interp, pc, emit_EAX, emit_ESP, 0, 1, args_offset);
+ break;
+ case 'S':
+ emitm_call_cfunc(pc, get_nci_S);
+ emitm_movl_r_m(interp, pc, emit_EAX, emit_ESP, 0, 1, args_offset);
+ break;
+
+
+ /* I have no idea how to handle these */
+ case '2':
+ case '3':
+ case '4':
+ mem_free_executable(jit_info.native_ptr);
+ return NULL;
+ break;
+ /* This might be right. Or not... */
+ /* we need the offset of PMC_int_val */
+ emitm_call_cfunc(pc, get_nci_P);
+ emitm_lea_m_r(interp, pc, emit_EAX, emit_EAX, 0, 1, (size_t) &PMC_int_val((PMC *) 0));
+ emitm_movl_r_m(interp, pc, emit_EAX, emit_ESP, 0, 1, args_offset);
+ break;
+ default:
+ Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_JIT_ERROR,
+ "Unknown arg Signature %c\n", *sig);
+ /*
+ * oops unknown signature:
+ * cleanup and try nci.c
+ */
+ mem_free_executable(jit_info.native_ptr);
+ return NULL;
+ }
+ args_offset +=4;
+ arg_count++;
+ sig++;
+ }
+
+ emitm_addl_i_r(pc, 16, emit_ESP);
+ /* get the pmc from stack - movl 12(%ebp), %eax */
+ emitm_movl_m_r(interp, pc, emit_EAX, emit_EBP, 0, 1, 12);
+ emitm_callm(pc, emit_EAX, emit_None, emit_None, 0);
+ emitm_subl_i_r(pc, 16, emit_ESP);
+
+ /* SAVE OFF EAX */
+ emitm_movl_r_m(interp, pc, emit_EAX, emit_ESP, 0, 1, 8);
+
+ /*&st*/
+ emitm_lea_m_r(interp, pc, emit_EAX, emit_ESP, 0, 1, st_offset);
+ emitm_movl_r_m(interp, pc, emit_EAX, emit_ESP, 0, 1, 4);
+
+ /*interpreter*/
+ emitm_movl_m_r(interp, pc, emit_EAX, emit_EBP, 0, 1, 8);
+ emitm_movl_r_m(interp, pc, emit_EAX, emit_ESP, 0, 1, 0);
+
+ /* RESTORE BACK EAX */
+ emitm_movl_m_r(interp, pc, emit_EAX, emit_ESP, 0, 1, 8);
+
+ /* now place return value in registers */
+ /* first in signature is the return value */
+ sig = (char *)signature->strstart; /* the result */
+ switch (*sig) {
+ /* I have no idea how to handle these */
+ case '2':
+ case '3':
+ case '4':
+ /* get integer from pointer - untested */
+ emitm_movl_m_r(interp, pc, emit_EAX, emit_EAX, 0, 1, 0);
+ if (*sig == 2) /* short */
+ emitm_movswl_r_r(pc, emit_EAX, emit_EAX);
+ emitm_call_cfunc(pc, set_nci_I);
+ break;
+ case 'f':
+ case 'd':
+ jit_emit_fstore_mb_n(interp, pc, emit_ESP, 8);
+ emitm_call_cfunc(pc, set_nci_N);
+ /* pop num from st(0) and mov to reg */
+ break;
+ case 's':
+ /* movswl %ax, %eax */
+ emitm_movswl_r_r(pc, emit_EAX, emit_EAX);
+ emitm_movl_r_m(interp, pc, emit_EAX, emit_ESP, 0, 1, 8);
+ emitm_call_cfunc(pc, set_nci_I);
+ break;
+ case 'c':
+ /* movsbl %al, %eax */
+ emitm_movsbl_r_r(pc, emit_EAX, emit_EAX);
+ emitm_movl_r_m(interp, pc, emit_EAX, emit_ESP, 0, 1, 8);
+ emitm_call_cfunc(pc, set_nci_I);
+ break;
+ case 'I': /* INTVAL */
+ case 'l':
+ case 'i':
+ emitm_movl_r_m(interp, pc, emit_EAX, emit_ESP, 0, 1, 8);
+ emitm_call_cfunc(pc, set_nci_I);
+ break;
+ case 'v': /* void - do nothing */
+ break;
+ case 'P':
+ emitm_movl_r_m(interp, pc, emit_EAX, emit_ESP, 0, 1, 8);
+ emitm_call_cfunc(pc, set_nci_P);
+ break;
+ case 'p': /* make a new unmanaged struct */
+ /* save return value on stack */
+
+ /* save pointer p */
+ emitm_movl_r_m(interp, pc, emit_EAX, emit_ESP, 0, 1, 12);
+
+ /* make new pmc */
+ emitm_movl_i_m(pc, enum_class_UnManagedStruct, emit_ESP, 0, 1, 4);
+ emitm_call_cfunc(pc, pmc_new);
+
+ /* restore pointer p to EDX */
+ emitm_movl_m_r(interp, pc, emit_EDX, emit_ESP, 0, 1, 12);
+
+ /* copy UnManagedStruct to stack for set_nci_P call */
+ emitm_movl_r_m(interp, pc, emit_EAX, emit_ESP, 0, 1, 8);
+
+ /* eax = PMC, get return value into edx */
+ /* stuff return value into pmc->data */
+
+# if ! PMC_DATA_IN_EXT
+ /* mov %edx, (data) %eax */
+ emitm_movl_r_m(interp, pc, emit_EDX, emit_EAX, 0, 1, offsetof(struct PMC, data));
+# else
+ /* mov pmc_ext(%eax), %eax
+ mov %edx, data(%eax) */
+ emitm_movl_m_r(interp, pc, emit_EAX, emit_EAX, 0, 1, offsetof(struct PMC, pmc_ext));
+ emitm_movl_r_m(interp, pc, emit_EDX, emit_EAX, 0, 1, offsetof(struct PMC_EXT, data));
+# endif
+
+ /* reset ESP(4) */
+ emitm_lea_m_r(interp, pc, emit_EAX, emit_ESP, 0, 1, st_offset);
+ emitm_movl_r_m(interp, pc, emit_EAX, emit_ESP, 0, 1, 4);
+
+ emitm_call_cfunc(pc, set_nci_P);
+ break;
+ case 'S':
+ emitm_movl_r_m(interp, pc, emit_EAX, emit_ESP, 0, 1, 8);
+ emitm_call_cfunc(pc, set_nci_S);
+ break;
+ case 't': /* string */
+ /* EAX is char* */
+ emitm_movl_i_m(pc, 0, emit_ESP, 0, 1, 8); /* len */
+
+ /* overrights addres of st in ESP(4) */
+ emitm_movl_r_m(interp, pc, emit_EAX, emit_ESP, 0, 1, 4);
+
+ emitm_call_cfunc(pc, string_from_cstring);
+
+ emitm_movl_r_m(interp, pc, emit_EAX, emit_ESP, 0, 1, 8);
+
+ /* reset ESP(4) */
+ emitm_lea_m_r(interp, pc, emit_EAX, emit_ESP, 0, 1, st_offset);
+ emitm_movl_r_m(interp, pc, emit_EAX, emit_ESP, 0, 1, 4);
+
+ emitm_call_cfunc(pc, set_nci_S);
+ break;
+ default:
+ Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_JIT_ERROR,
+ "Unknown return Signature %c\n", *sig);
+ /*
+ * oops unknown signature:
+ * cleanup and try nci.c
+ */
+ mem_free_executable(jit_info.native_ptr);
+ return NULL;
+ }
+
+ /* free temporary strings */
+ strings_offset = st_offset + ST_SIZE_OF;
+ for (i=0; i<strings; i++) {
+ emitm_movl_m_r(interp, pc, emit_EAX, emit_ESP, 0, 1, strings_offset);
+ emitm_movl_r_m(interp, pc, emit_EAX, emit_ESP, 0, 1, 0);
+ emitm_call_cfunc(pc, string_cstring_free);
+ }
+
+ jit_emit_stack_frame_leave(pc);
+ emitm_ret(pc);
+ PARROT_ASSERT(pc - jit_info.arena.start <= JIT_ALLOC_SIZE);
+ /* could shrink arena.start here to used size */
+ PObj_active_destroy_SET(pmc_nci);
+ return (void *)D2FPTR(jit_info.arena.start);
+}
diff --git a/src/jit/i386/jit_emit.h b/src/jit/i386/jit_emit.h
index e67061e..3471605 100644
--- a/src/jit/i386/jit_emit.h
+++ b/src/jit/i386/jit_emit.h
@@ -24,113 +24,6 @@
#include "parrot/hash.h"
#include "parrot/oplib/ops.h"
-/*
- * helper funcs - get argument n
- */
-static INTVAL
-get_nci_I(PARROT_INTERP, ARGMOD(call_state *st), int n)
-{
- if (n >= st->src.n)
- Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION,
- "too few arguments passed to NCI function");
-
- Parrot_fetch_arg_nci(interp, st);
-
- return UVal_int(st->val);
-}
-
-static FLOATVAL
-get_nci_N(PARROT_INTERP, ARGMOD(call_state *st), int n)
-{
- if (n >= st->src.n)
- Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION,
- "too few arguments passed to NCI function");
-
- Parrot_fetch_arg_nci(interp, st);
-
- return UVal_num(st->val);
-}
-
-PARROT_WARN_UNUSED_RESULT
-PARROT_CANNOT_RETURN_NULL
-static STRING*
-get_nci_S(PARROT_INTERP, ARGMOD(call_state *st), int n)
-{
- /* TODO or act like below? */
- if (n >= st->src.n)
- Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION,
- "too few arguments passed to NCI function");
-
- Parrot_fetch_arg_nci(interp, st);
-
- return UVal_str(st->val);
-}
-
-PARROT_WARN_UNUSED_RESULT
-PARROT_CANNOT_RETURN_NULL
-static PMC*
-get_nci_P(PARROT_INTERP, ARGMOD(call_state *st), int n)
-{
- /*
- * exessive args are passed as NULL
- * used by e.g. MMD infix like __add
- */
- if (n < st->src.n)
- Parrot_fetch_arg_nci(interp, st);
- else
- UVal_pmc(st->val) = PMCNULL;
-
- return UVal_pmc(st->val);
-}
-
-/*
- * set return value
- */
-static void
-set_nci_I(PARROT_INTERP, ARGOUT(call_state *st), INTVAL val)
-{
- Parrot_init_ret_nci(interp, st, "I");
- if (st->dest.i < st->dest.n) {
- UVal_int(st->val) = val;
- Parrot_convert_arg(interp, st);
- Parrot_store_arg(interp, st);
- }
-}
-
-static void
-set_nci_N(PARROT_INTERP, ARGOUT(call_state *st), FLOATVAL val)
-{
- Parrot_init_ret_nci(interp, st, "N");
- if (st->dest.i < st->dest.n) {
- UVal_num(st->val) = val;
- Parrot_convert_arg(interp, st);
- Parrot_store_arg(interp, st);
- }
-}
-
-static void
-set_nci_S(PARROT_INTERP, ARGOUT(call_state *st), STRING *val)
-{
- Parrot_init_ret_nci(interp, st, "S");
- if (st->dest.i < st->dest.n) {
- UVal_str(st->val) = val;
- Parrot_convert_arg(interp, st);
- Parrot_store_arg(interp, st);
- }
-}
-
-static void
-set_nci_P(PARROT_INTERP, ARGOUT(call_state *st), PMC* val)
-{
- Parrot_init_ret_nci(interp, st, "P");
- if (st->dest.i < st->dest.n) {
- UVal_pmc(st->val) = val;
- Parrot_convert_arg(interp, st);
- Parrot_store_arg(interp, st);
- }
-}
-
-
#if defined HAVE_COMPUTED_GOTO && defined __GNUC__ && PARROT_I386_JIT_CGP
# define JIT_CGP
#endif
@@ -3822,367 +3715,6 @@ count_regs(PARROT_INTERP, char *sig, char *sig_start)
return first_reg;
}
-static size_t
-calc_signature_needs(const char *sig, int *strings)
-{
- size_t stack_size = 0;
- while (*sig) {
- switch (*sig) {
- case 't':
- (*strings)++;
- stack_size +=4;
- break;
- case 'd':
- stack_size +=8;
- break;
- default:
- stack_size +=4;
- break;
- }
- sig++;
- }
- return stack_size;
-
-}
-/*
- * The function generated here is called as func(interp, nci_info)
- * interp ... 8(%ebp)
- * nci_info ... 12(%ebp)
- *
- * The generate function for a specific signature looks quite similar to
- * an optimized compile of src/nci.c:pcf_x_yy(). In case of any troubles
- * just compare the disassembly.
- */
-void *
-Parrot_jit_build_call_func(PARROT_INTERP, PMC *pmc_nci, STRING *signature)
-{
- Parrot_jit_info_t jit_info;
- int i = 0;
- char *pc;
- int arg_count = 0;
- int strings = 0;
- const int ST_SIZE_OF = 124;
- const int JIT_ALLOC_SIZE = 1024;
-
- char *sig = (char *)signature->strstart + 1; /* skip over the result */
- size_t stack_space_needed = calc_signature_needs(sig, &strings);
-
- int st_offset = 16 + stack_space_needed;
- int args_offset = 16;
- int strings_offset = st_offset + ST_SIZE_OF;
- int total_stack_needed = strings_offset + 4 * strings;
-
- /* this ought to be enough - the caller of this function
- * should free the function pointer returned here
- */
- pc = jit_info.native_ptr = jit_info.arena.start = (char *)mem_alloc_executable(JIT_ALLOC_SIZE);
-
-
- /* this generated jit function will be called as (INTERP (EBP 8), func_ptr (ESP 12), args signature (ESP 16)) */
- /* make stack frame, preserve %ebx */
- jit_emit_stack_frame_enter(pc);
-
- emitm_subl_i_r(pc, total_stack_needed, emit_ESP);
-
- /* Parrot_init_arg_nci(interp, &st, "S"); */
- emitm_movl_m_r(interp, pc, emit_EAX, emit_EBP, 0, 1, 16);
- emitm_movl_r_m(interp, pc, emit_EAX, emit_ESP, 0, 1, 8);
-
- /*&st*/
- emitm_lea_m_r(interp, pc, emit_EAX, emit_ESP, 0, 1, st_offset);
- emitm_movl_r_m(interp, pc, emit_EAX, emit_ESP, 0, 1, 4);
-
- /*interpreter*/
- emitm_movl_m_r(interp, pc, emit_EAX, emit_EBP, 0, 1, 8);
- emitm_movl_r_m(interp, pc, emit_EAX, emit_ESP, 0, 1, 0);
-
- if (sig && *sig)
- emitm_call_cfunc(pc, Parrot_init_arg_nci);
-
- while (*sig) {
- emitm_movl_i_m(pc, arg_count, emit_ESP, 0, 1, 8);
-
- switch (*sig) {
- case '0': /* null ptr or such - doesn't consume a reg */
- jit_emit_bxor_rr_i(interp, pc, emit_EAX, emit_EAX);
- emitm_movl_m_r(interp, pc, emit_EAX, emit_ESP, 0, 1, args_offset);
- break;
- case 'f':
- emitm_call_cfunc(pc, get_nci_N);
- emitm_fstps(interp, pc, emit_ESP, 0, 1, args_offset);
- break;
- case 'N':
- case 'd':
- emitm_call_cfunc(pc, get_nci_N);
- emitm_fstpl(interp, pc, emit_ESP, 0, 1, args_offset);
- args_offset += 4;
- break;
- case 'I': /* INTVAL */
- case 'l': /* long */
- case 'i': /* int */
- emitm_call_cfunc(pc, get_nci_I);
- emitm_movl_r_m(interp, pc, emit_EAX, emit_ESP, 0, 1, args_offset);
- break;
- case 't': /* string, pass a cstring */
- emitm_call_cfunc(pc, get_nci_S);
- emitm_movl_r_m(interp, pc, emit_EAX, emit_ESP, 0, 1, 4);
- emitm_call_cfunc(pc, string_to_cstring);
-
- emitm_movl_r_m(interp, pc, emit_EAX, emit_ESP, 0, 1, args_offset);
- /* save off temporary allocation address */
- emitm_movl_r_m(interp, pc, emit_EAX, emit_ESP, 0, 1, strings_offset);
- strings_offset += 4;
-
- /* reset ESP(4) */
- emitm_lea_m_r(interp, pc, emit_EAX, emit_ESP, 0, 1, st_offset);
- emitm_movl_r_m(interp, pc, emit_EAX, emit_ESP, 0, 1, 4);
- break;
- case 's': /* short: movswl intreg_o(base), %eax */
- emitm_call_cfunc(pc, get_nci_I);
- emitm_movswl_r_r(pc, emit_EAX, emit_EAX)
- emitm_movl_r_m(interp, pc, emit_EAX, emit_ESP, 0, 1, args_offset);
- break;
- case 'c': /* char: movsbl intreg_o(base), %eax */
- emitm_call_cfunc(pc, get_nci_I);
- emitm_movsbl_r_r(pc, emit_EAX, emit_EAX);
- emitm_movl_r_m(interp, pc, emit_EAX, emit_ESP, 0, 1, args_offset);
- break;
- case 'J': /* interpreter */
- emitm_movl_m_r(interp, pc, emit_EAX, emit_EBP, 0, 1, 8);
- emitm_movl_r_m(interp, pc, emit_EAX, emit_ESP, 0, 1, args_offset);
- arg_count--;
- break;
- case 'p': /* push pmc->data */
- emitm_call_cfunc(pc, get_nci_P);
-# if ! PMC_DATA_IN_EXT
- /* mov pmc, %edx
- * mov 8(%edx), %eax
- * push %eax
- */
- emitm_movl_m_r(interp, pc, emit_EAX, emit_EAX, 0, 1, offsetof(struct PMC, data));
-# else
- /* push pmc->pmc_ext->data
- * mov pmc, %edx
- * mov pmc_ext(%edx), %eax
- * mov data(%eax), %eax
- * push %eax
- */
- emitm_movl_m_r(interp, pc, emit_EAX, emit_EAX, 0, 1, offsetof(struct PMC, pmc_ext));
- emitm_movl_m_r(interp, pc, emit_EAX, emit_EAX, 0, 1, offsetof(struct PMC_EXT, data));
-# endif
- emitm_movl_r_m(interp, pc, emit_EAX, emit_ESP, 0, 1, args_offset);
- break;
- case 'O': /* push PMC * object in P2 */
- case 'P': /* push PMC * */
- case '@':
- emitm_call_cfunc(pc, get_nci_P);
-# if PARROT_CATCH_NULL
- /* PMCNULL is a global */
- jit_emit_cmp_rm_i(pc, emit_EAX, &PMCNULL);
- emitm_jxs(pc, emitm_jne, 2); /* skip the xor */
- jit_emit_bxor_rr_i(interp, pc, emit_EAX, emit_EAX);
-# endif
- emitm_movl_r_m(interp, pc, emit_EAX, emit_ESP, 0, 1, args_offset);
- break;
- case 'v':
- break;
- case 'V':
- emitm_call_cfunc(pc, get_nci_P);
- emitm_lea_m_r(interp, pc, emit_EAX, emit_EAX, 0, 1, offsetof(struct PMC, data));
- /* emitm_lea_m_r(interp, pc, emit_EAX, emit_EAX, 0, 1, 0); */
- emitm_movl_r_m(interp, pc, emit_EAX, emit_ESP, 0, 1, args_offset);
- break;
- case 'b': /* buffer (void*) pass PObj_bufstart(SReg) */
- emitm_call_cfunc(pc, get_nci_S);
- emitm_movl_m_r(interp, pc, emit_EAX, emit_EAX, 0, 1, (size_t) &PObj_bufstart((STRING *) 0));
- emitm_movl_r_m(interp, pc, emit_EAX, emit_ESP, 0, 1, args_offset);
- break;
- case 'B': /* buffer (void**) pass &PObj_bufstart(SReg) */
- emitm_call_cfunc(pc, get_nci_S);
- emitm_lea_m_r(interp, pc, emit_EAX, emit_EAX, 0, 1, (size_t) &PObj_bufstart((STRING *) 0));
- emitm_movl_r_m(interp, pc, emit_EAX, emit_ESP, 0, 1, args_offset);
- break;
- case 'S':
- emitm_call_cfunc(pc, get_nci_S);
- emitm_movl_r_m(interp, pc, emit_EAX, emit_ESP, 0, 1, args_offset);
- break;
-
-
- /* I have no idea how to handle these */
- case '2':
- case '3':
- case '4':
- mem_free_executable(jit_info.native_ptr);
- return NULL;
- break;
- /* This might be right. Or not... */
- /* we need the offset of PMC_int_val */
- emitm_call_cfunc(pc, get_nci_P);
- emitm_lea_m_r(interp, pc, emit_EAX, emit_EAX, 0, 1, (size_t) &PMC_int_val((PMC *) 0));
- emitm_movl_r_m(interp, pc, emit_EAX, emit_ESP, 0, 1, args_offset);
- break;
- default:
- Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_JIT_ERROR,
- "Unknown arg Signature %c\n", *sig);
- /*
- * oops unknown signature:
- * cleanup and try nci.c
- */
- mem_free_executable(jit_info.native_ptr);
- return NULL;
- }
- args_offset +=4;
- arg_count++;
- sig++;
- }
-
- emitm_addl_i_r(pc, 16, emit_ESP);
- /* get the pmc from stack - movl 12(%ebp), %eax */
- emitm_movl_m_r(interp, pc, emit_EAX, emit_EBP, 0, 1, 12);
- emitm_callm(pc, emit_EAX, emit_None, emit_None, 0);
- emitm_subl_i_r(pc, 16, emit_ESP);
-
- /* SAVE OFF EAX */
- emitm_movl_r_m(interp, pc, emit_EAX, emit_ESP, 0, 1, 8);
-
- /*&st*/
- emitm_lea_m_r(interp, pc, emit_EAX, emit_ESP, 0, 1, st_offset);
- emitm_movl_r_m(interp, pc, emit_EAX, emit_ESP, 0, 1, 4);
-
- /*interpreter*/
- emitm_movl_m_r(interp, pc, emit_EAX, emit_EBP, 0, 1, 8);
- emitm_movl_r_m(interp, pc, emit_EAX, emit_ESP, 0, 1, 0);
-
- /* RESTORE BACK EAX */
- emitm_movl_m_r(interp, pc, emit_EAX, emit_ESP, 0, 1, 8);
-
- /* now place return value in registers */
- /* first in signature is the return value */
- sig = (char *)signature->strstart; /* the result */
- switch (*sig) {
- /* I have no idea how to handle these */
- case '2':
- case '3':
- case '4':
- /* get integer from pointer - untested */
- emitm_movl_m_r(interp, pc, emit_EAX, emit_EAX, 0, 1, 0);
- if (*sig == 2) /* short */
- emitm_movswl_r_r(pc, emit_EAX, emit_EAX);
- emitm_call_cfunc(pc, set_nci_I);
- break;
- case 'f':
- case 'd':
- jit_emit_fstore_mb_n(interp, pc, emit_ESP, 8);
- emitm_call_cfunc(pc, set_nci_N);
- /* pop num from st(0) and mov to reg */
- break;
- case 's':
- /* movswl %ax, %eax */
- emitm_movswl_r_r(pc, emit_EAX, emit_EAX);
- emitm_movl_r_m(interp, pc, emit_EAX, emit_ESP, 0, 1, 8);
- emitm_call_cfunc(pc, set_nci_I);
- break;
- case 'c':
- /* movsbl %al, %eax */
- emitm_movsbl_r_r(pc, emit_EAX, emit_EAX);
- emitm_movl_r_m(interp, pc, emit_EAX, emit_ESP, 0, 1, 8);
- emitm_call_cfunc(pc, set_nci_I);
- break;
- case 'I': /* INTVAL */
- case 'l':
- case 'i':
- emitm_movl_r_m(interp, pc, emit_EAX, emit_ESP, 0, 1, 8);
- emitm_call_cfunc(pc, set_nci_I);
- break;
- case 'v': /* void - do nothing */
- break;
- case 'P':
- emitm_movl_r_m(interp, pc, emit_EAX, emit_ESP, 0, 1, 8);
- emitm_call_cfunc(pc, set_nci_P);
- break;
- case 'p': /* make a new unmanaged struct */
- /* save return value on stack */
-
- /* save pointer p */
- emitm_movl_r_m(interp, pc, emit_EAX, emit_ESP, 0, 1, 12);
-
- /* make new pmc */
- emitm_movl_i_m(pc, enum_class_UnManagedStruct, emit_ESP, 0, 1, 4);
- emitm_call_cfunc(pc, pmc_new);
-
- /* restore pointer p to EDX */
- emitm_movl_m_r(interp, pc, emit_EDX, emit_ESP, 0, 1, 12);
-
- /* copy UnManagedStruct to stack for set_nci_P call */
- emitm_movl_r_m(interp, pc, emit_EAX, emit_ESP, 0, 1, 8);
-
- /* eax = PMC, get return value into edx */
- /* stuff return value into pmc->data */
-
-# if ! PMC_DATA_IN_EXT
- /* mov %edx, (data) %eax */
- emitm_movl_r_m(interp, pc, emit_EDX, emit_EAX, 0, 1, offsetof(struct PMC, data));
-# else
- /* mov pmc_ext(%eax), %eax
- mov %edx, data(%eax) */
- emitm_movl_m_r(interp, pc, emit_EAX, emit_EAX, 0, 1, offsetof(struct PMC, pmc_ext));
- emitm_movl_r_m(interp, pc, emit_EDX, emit_EAX, 0, 1, offsetof(struct PMC_EXT, data));
-# endif
-
- /* reset ESP(4) */
- emitm_lea_m_r(interp, pc, emit_EAX, emit_ESP, 0, 1, st_offset);
- emitm_movl_r_m(interp, pc, emit_EAX, emit_ESP, 0, 1, 4);
-
- emitm_call_cfunc(pc, set_nci_P);
- break;
- case 'S':
- emitm_movl_r_m(interp, pc, emit_EAX, emit_ESP, 0, 1, 8);
- emitm_call_cfunc(pc, set_nci_S);
- break;
- case 't': /* string */
- /* EAX is char* */
- emitm_movl_i_m(pc, 0, emit_ESP, 0, 1, 8); /* len */
-
- /* overrights addres of st in ESP(4) */
- emitm_movl_r_m(interp, pc, emit_EAX, emit_ESP, 0, 1, 4);
-
- emitm_call_cfunc(pc, string_from_cstring);
-
- emitm_movl_r_m(interp, pc, emit_EAX, emit_ESP, 0, 1, 8);
-
- /* reset ESP(4) */
- emitm_lea_m_r(interp, pc, emit_EAX, emit_ESP, 0, 1, st_offset);
- emitm_movl_r_m(interp, pc, emit_EAX, emit_ESP, 0, 1, 4);
-
- emitm_call_cfunc(pc, set_nci_S);
- break;
- default:
- Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_JIT_ERROR,
- "Unknown return Signature %c\n", *sig);
- /*
- * oops unknown signature:
- * cleanup and try nci.c
- */
- mem_free_executable(jit_info.native_ptr);
- return NULL;
- }
-
- /* free temporary strings */
- strings_offset = st_offset + ST_SIZE_OF;
- for (i=0; i<strings; i++) {
- emitm_movl_m_r(interp, pc, emit_EAX, emit_ESP, 0, 1, strings_offset);
- emitm_movl_r_m(interp, pc, emit_EAX, emit_ESP, 0, 1, 0);
- emitm_call_cfunc(pc, string_cstring_free);
- }
-
- jit_emit_stack_frame_leave(pc);
- emitm_ret(pc);
- PARROT_ASSERT(pc - jit_info.arena.start <= JIT_ALLOC_SIZE);
- /* could shrink arena.start here to used size */
- PObj_active_destroy_SET(pmc_nci);
- return (void *)D2FPTR(jit_info.arena.start);
-}
-
#endif
#if JIT_EMIT == 0
diff --git a/tools/build/nativecall.pl b/tools/build/nativecall.pl
index 4532792..974f0d6 100644
--- a/tools/build/nativecall.pl
+++ b/tools/build/nativecall.pl
@@ -311,7 +311,7 @@ sub print_head {
/*
* helper funcs - get argument n
*/
-static INTVAL
+INTVAL
get_nci_I(PARROT_INTERP, ARGMOD(call_state *st), int n)
{
if (n >= st->src.n)
@@ -323,7 +323,7 @@ get_nci_I(PARROT_INTERP, ARGMOD(call_state *st), int n)
return UVal_int(st->val);
}
-static FLOATVAL
+FLOATVAL
get_nci_N(PARROT_INTERP, ARGMOD(call_state *st), int n)
{
if (n >= st->src.n)
@@ -337,7 +337,7 @@ get_nci_N(PARROT_INTERP, ARGMOD(call_state *st), int n)
PARROT_WARN_UNUSED_RESULT
PARROT_CANNOT_RETURN_NULL
-static STRING*
+STRING*
get_nci_S(PARROT_INTERP, ARGMOD(call_state *st), int n)
{
/* TODO or act like below? */
@@ -352,7 +352,7 @@ get_nci_S(PARROT_INTERP, ARGMOD(call_state *st), int n)
PARROT_WARN_UNUSED_RESULT
PARROT_CANNOT_RETURN_NULL
-static PMC*
+PMC*
get_nci_P(PARROT_INTERP, ARGMOD(call_state *st), int n)
{
/*
@@ -375,7 +375,7 @@ get_nci_P(PARROT_INTERP, ARGMOD(call_state *st), int n)
/*
* set return value
*/
-static void
+void
set_nci_I(PARROT_INTERP, ARGOUT(call_state *st), INTVAL val)
{
Parrot_init_ret_nci(interp, st, "I");
@@ -386,7 +386,7 @@ set_nci_I(PARROT_INTERP, ARGOUT(call_state *st), INTVAL val)
}
}
-static void
+void
set_nci_N(PARROT_INTERP, ARGOUT(call_state *st), FLOATVAL val)
{
Parrot_init_ret_nci(interp, st, "N");
@@ -397,7 +397,7 @@ set_nci_N(PARROT_INTERP, ARGOUT(call_state *st), FLOATVAL val)
}
}
-static void
+void
set_nci_S(PARROT_INTERP, ARGOUT(call_state *st), STRING *val)
{
Parrot_init_ret_nci(interp, st, "S");
@@ -408,7 +408,7 @@ set_nci_S(PARROT_INTERP, ARGOUT(call_state *st), STRING *val)
}
}
-static void
+void
set_nci_P(PARROT_INTERP, ARGOUT(call_state *st), PMC* val)
{
Parrot_init_ret_nci(interp, st, "P");