Author: leo
Date: Sat Feb  4 08:45:43 2006
New Revision: 11419

Modified:
   trunk/src/ops/ops.num
   trunk/src/ops/pic.ops
   trunk/src/pic.c
Log:
Interpreter hard core - callr PIC opcode 1

* create new callr opcode that is able to call C functions
  very similar to interface functions
* the plan is to JIT some simple PIR subs on-the-fly
* call a test function to check if arg passing is ok
* just one result and void arguments for now

Please make realclean (and rm *.pbc) due to inserted opcode.


Modified: trunk/src/ops/ops.num
==============================================================================
--- trunk/src/ops/ops.num       (original)
+++ trunk/src/ops/ops.num       Sat Feb  4 08:45:43 2006
@@ -1212,3 +1212,4 @@ find_global_p_p_s              1181
 find_global_p_p_sc             1182
 find_name_p_s                  1183
 find_name_p_sc                 1184
+pic_callr___pc                 1185

Modified: trunk/src/ops/pic.ops
==============================================================================
--- trunk/src/ops/pic.ops       (original)
+++ trunk/src/ops/pic.ops       Sat Feb  4 08:45:43 2006
@@ -6,6 +6,8 @@
 
 #include "parrot/oplib/ops.h"
 
+typedef opcode_t* (*interface_f)(Interp*, INTVAL*, void **);
+
 VERSION = PARROT_VERSION;
 
 =head1 NAME
@@ -230,6 +232,50 @@ inline op pic_set_returns__(inconst PMC)
     goto OFFSET(0);
 }
 
+=item B<pic_callr__>(inconst PMC)
+
+Call the function $1 as C<pc = func(interp, 0, **args)>. args[0] holds the
+address of the function result, args[1..] are function arguments, both
+according to the C<get_results> and C<set_args> opcodes. The function is
+a C interface function (or NCI) or a JITed PIR function. args[n] holds the
+C<pc> of the next opcode and is usually just returned.
+
+=cut
+
+inline op pic_callr__(inconst PMC) :pic {
+    Parrot_MIC *mic;
+    Parrot_PIC_lru *lru;
+    void *args[6];      /* TODO ARG_MAX */
+    parrot_context_t *ctx;
+    opcode_t *pc;
+    void **pred_pc;
+    PMC *sig;
+    INTVAL *bitp, n_args;
+
+    ctx = CONTEXT(interpreter->ctx);
+    mic = (Parrot_MIC *) cur_opcode[1];
+    pc = ctx->current_results;
+    if (pc) {
+       pred_pc = (void**) pc - ctx->pred_offset;
+        args[0] = (_reg_base + ((opcode_t*)pred_pc)[2]);
+       assert((sig = (PMC*)(pred_pc[1])) &&
+                    PObj_is_PMC_TEST(sig) &&
+                    sig->vtable->base_type == enum_class_FixedIntegerArray &&
+                    VTABLE_elements(interpreter, sig) == 1);
+    }
+    else
+        args[0] = NULL;
+    /* TODO set_args */
+    n_args = 0;
+    /* set_args (); set_p_pc; get_results (1), x; invokecc_p */
+    pc = CUR_OPCODE + 2 + n_args + 3 + 3 + 2;    
+    args[1 + n_args] = pc;
+    lru = &mic->lru;
+    /* TODO verify $1 didn't change */
+    pc = ((interface_f)lru->f.real_function)(interpreter, NULL, args);
+    goto ADDRESS(pc);
+}
+
 =back
 
 =cut

Modified: trunk/src/pic.c
==============================================================================
--- trunk/src/pic.c     (original)
+++ trunk/src/pic.c     Sat Feb  4 08:45:43 2006
@@ -83,6 +83,8 @@ lookup of the cache has to be done in th
 #  include "parrot/oplib/core_ops_cgp.h"
 #endif
 
+#define PIC_TEST 0
+
 /* needs a Makefile dependency */
 /* #include "pmc/pmc_integer.h" */
 
@@ -169,6 +171,7 @@ parrot_PIC_op_is_cached(Interp *interpre
         case PARROT_OP_infix_ic_p_p: return 1;
         case PARROT_OP_get_params_pc: return 1;
         case PARROT_OP_set_returns_pc: return 1;
+        case PARROT_OP_set_args_pc: return 1;
     }
     return 0;
 }
@@ -475,6 +478,99 @@ is_pic_param(Interp *interpreter, void *
     return 1;
 }
 
+#if PIC_TEST
+/*
+ * just for testing the whole scheme ...
+
+.sub main :main
+    .local int i
+    i = __pic_test()
+    print i
+    print "\n"
+.end
+.sub __pic_test
+    .return (10)
+.end
+
+... prints 42, if PIC_TEST is 1, because the C function is called
+    with -C and -S runcores.
+*/
+
+static opcode_t *
+pic_test_func(Interp *interpreter, INTVAL *sig_bits, void **args)
+{
+    opcode_t *pc;
+    INTVAL *result;
+
+    result = (INTVAL*) args[0];
+    *result = 42;
+    pc = args[1];
+    return pc;
+}
+#endif
+
+static int
+is_pic_func(Interp *interpreter, void **pc, Parrot_MIC *mic, int core_type)
+{
+    PMC *sub, *sig;
+    char *base;
+    parrot_context_t *ctx;
+    opcode_t *op, n;
+#if PIC_TEST
+    STRING *name;
+#endif
+    
+    /*
+     * if we have these opcodes
+     *
+     *   set_args '(..)' ...
+     *   set_p_pc Px, PFunx
+     *   get_results '(..)' ...
+     *   invokecc_p Px
+     *
+     * and all args are matching the called sub and we don't have
+     * too many args, and only INTVAL or FLOATVAL, the 
+     * whole sequence is replaced by the C<callr> pic opcode.  
+     *
+     * Oh, I forgot to mention - the to-be-called C function is of
+     * course compiled on-the-fly by the JIT compiler ;)
+     *
+     * pc is at set_args
+     */
+
+    base = (char*)interpreter->ctx.bp.regs_i;
+    ctx = CONTEXT(interpreter->ctx);
+    sig = (PMC*)(pc[1]);
+    assert(PObj_is_PMC_TEST(sig));
+    assert(sig->vtable->base_type == enum_class_FixedIntegerArray);
+    n = VTABLE_elements(interpreter, sig);
+    interpreter->current_args = (opcode_t*)pc + ctx->pred_offset;
+    pc += 2 + n;
+    op = (opcode_t*)pc + ctx->pred_offset;
+    if (*op != PARROT_OP_set_p_pc)
+        return 0;
+    do_prederef(pc, interpreter, core_type);
+    sub = (PMC*)(pc[2]);
+    assert(PObj_is_PMC_TEST(sub)); 
+    if (sub->vtable->base_type != enum_class_Sub)
+        return 0;
+    pc += 3;    /* results */
+    op = (opcode_t*)pc + ctx->pred_offset;
+    if (*op != PARROT_OP_get_results_pc)
+        return 0;
+    do_prederef(pc, interpreter, core_type);
+    ctx->current_results = (opcode_t*)pc + ctx->pred_offset;
+#if PIC_TEST
+    name = VTABLE_get_string(interpreter, sub);
+    if (memcmp((char*) name->strstart, "__pic_test", 10) == 0) {
+        
+        mic->lru.f.real_function = (funcptr_t) pic_test_func;
+        return 1;
+    }
+#endif
+    return 0;
+}
+
 void
 parrot_PIC_prederef(Interp *interpreter, opcode_t op, void **pc_pred, int core)
 {
@@ -529,6 +625,12 @@ parrot_PIC_prederef(Interp *interpreter,
                 op = PARROT_OP_pic_set_returns___pc;
             }
             break;
+        case PARROT_OP_set_args_pc:
+            if (is_pic_func(interpreter, pc_pred, mic, core)) {
+                pc_pred[1] = (void*) mic;
+                op = PARROT_OP_pic_callr___pc;
+            }
+            break;
     }
     /*
      * rewrite opcode

Reply via email to