]> Nishi Git Mirror - gwion.git/commitdiff
:art: small updates [skip ci]
authorJérémie Astor <fennecdjay@gmail.com>
Sun, 6 Jun 2021 16:46:48 +0000 (18:46 +0200)
committerJérémie Astor <fennecdjay@gmail.com>
Sun, 6 Jun 2021 16:46:48 +0000 (18:46 +0200)
Makefile
include/opcode.h
include/vm.h
opcode.txt
src/emit/emit.c
src/lib/union.c
src/vm/gack.c
src/vm/vm.c
src/vm/vm_code.c

index 1aef858825a53785db0d7fb56be7e095f5ce588c..a72065ea866a5e4eea626999b14f77e80150e1a7 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -101,7 +101,7 @@ gwion-fuzz:
 clean_core:
        @rm -f core.* *vgcore.*
 
-clean-all:
+clean-all: clean
                ${MAKE} -s -C libcmdapp clean
                ${MAKE} -s -C fmt clean
                ${MAKE} -s -C ast clean
index 7eec1cff7ae7a66d75d9b5d892c157229ce57780..96d7997be0377a62291cec62759d1db66394464a 100644 (file)
@@ -127,12 +127,14 @@ enum {
   eCastI2F,
   eCastF2I,
   eTime_Advance,
+  eRecurs,
   eSetCode,
   eRegMove,
   eReg2Mem,
   eReg2Mem4,
   eOverflow,
   eFuncUsrEnd,
+  eFuncUsrEnd2,
   eFuncMemberEnd,
   eSporkIni,
   eForkIni,
@@ -326,12 +328,14 @@ enum {
 #define  CastI2F              (f_instr)eCastI2F
 #define  CastF2I              (f_instr)eCastF2I
 #define  Time_Advance         (f_instr)eTime_Advance
+#define  Recurs               (f_instr)eRecurs
 #define  SetCode              (f_instr)eSetCode
 #define  RegMove              (f_instr)eRegMove
 #define  Reg2Mem              (f_instr)eReg2Mem
 #define  Reg2Mem4             (f_instr)eReg2Mem4
 #define  Overflow             (f_instr)eOverflow
 #define  FuncUsrEnd           (f_instr)eFuncUsrEnd
+#define  FuncUsrEnd2          (f_instr)eFuncUsrEnd2
 #define  FuncMemberEnd        (f_instr)eFuncMemberEnd
 #define  SporkIni             (f_instr)eSporkIni
 #define  ForkIni              (f_instr)eForkIni
index a10821d72db79d062ceddc52cb1724bba0ebc505..8d90a8cb68a21c688d7ab7a16887f622ea672664 100644 (file)
@@ -31,6 +31,11 @@ struct VM_Code_ {
   bool is_memoize;
 };
 
+struct frame_t {
+  uint32_t push, pc;
+  VM_Code code;
+};
+
 typedef struct Shreduler_* Shreduler;
 typedef struct Emitter_   * Emitter;
 typedef struct VM_Shred_* VM_Shred;
index cbb5d5d75b0d1adc767276dff765aaf2f9688faf..169fa167bd5aa1456d845cc7a54ecd345dab8365 100644 (file)
@@ -124,12 +124,14 @@ float_int_r_div
 CastI2F
 CastF2I
 Time_Advance
+Recurs
 SetCode
 RegMove
 Reg2Mem
 Reg2Mem4
 Overflow
 FuncUsrEnd
+FuncUsrEnd2
 FuncMemberEnd
 SporkIni
 ForkIni
index 8199a6e63b8e3bc1ab36b546129230e7176a8775..526e4d9608d9f9386cca5ace22a571c3b73d01ab 100644 (file)
@@ -1071,8 +1071,13 @@ ANN static m_bool _emit_exp_call(const Emitter emit, const Exp_Call* exp_call) {
     return emit_inline(emit, f, exp_call);
 #endif
 */
-  CHECK_BB(prepare_call(emit, exp_call));
+  // skip when recursing
   const Type t = actual_type(emit->gwion, exp_call->func->type);
+  const Func f  = t->info->func;
+  if(is_fptr(emit->gwion, t) || f != emit->env->func || f->value_ref->from->owner_class || strstr(emit->code->name, "ork~"))
+    CHECK_BB(prepare_call(emit, exp_call));
+  else
+    CHECK_BB(emit_func_args(emit, exp_call));
   if(isa(t, emit->gwion->type[et_function]) > 0)
     CHECK_BB(emit_exp_call1(emit, t->info->func));
   else {
@@ -1243,12 +1248,19 @@ ANN static void tmpl_prelude(const Emitter emit, const Func f) {
 
 ANN static Instr get_prelude(const Emitter emit, const Func f) {
   const Type t = actual_type(emit->gwion, f->value_ref->type);
+  const bool fp = is_fptr(emit->gwion, t);
   if(is_fptr(emit->gwion, t)) {
     if(f->def->base->tmpl)
       tmpl_prelude(emit, f);
   }
-  const Instr instr = emit_add_instr(emit, SetCode);
+  if(fp || f != emit->env->func || f->value_ref->from->owner_class || strstr(emit->code->name, "ork~")) {
+    const Instr instr = emit_add_instr(emit, SetCode);
+    instr->m_val2 = 1;
+    return instr;
+  }
+  const Instr instr = emit_add_instr(emit, Recurs);
   instr->m_val2 = 1;
+  instr->m_val = SZ_INT;
   return instr;
 }
 
@@ -1305,7 +1317,7 @@ ANN static m_bool me_arg(MemoizeEmitter *me) {
 
 ANN static Instr emit_call(const Emitter emit, const Func f) {
   const Instr prelude = get_prelude(emit, f);
-  prelude->m_val = -f->def->stack_depth - SZ_INT;
+  prelude->m_val += -f->def->stack_depth - SZ_INT;
   const m_uint member = vflag(f->value_ref, vflag_member) ? SZ_INT : 0;
   if(member) {
     const Instr instr = emit_add_instr(emit, Reg2Mem);
@@ -1313,8 +1325,11 @@ ANN static Instr emit_call(const Emitter emit, const Func f) {
     ++prelude->m_val2;
   }
   if(f->def->stack_depth - member) {
+//  if(is_fptr(emit->gwion, t) || f != emit->env->func || f->value_ref->from->owner_class || strstr(emit->code->name, "ork~"))
+{
     emit_args(emit, f);
     ++prelude->m_val2;
+}
   }
   return emit_add_instr(emit, Overflow);
 }
@@ -1329,11 +1344,11 @@ ANN m_bool emit_exp_call1(const Emitter emit, const Func f) {
       if(emit->env->func != f)
         CHECK_BB(emit_template_code(emit, f));
       else { // recursive function. (maybe should be used only for global funcs)
-        const Instr back = (Instr) vector_size(&emit->code->instr) ?
+      /*  const Instr back = (Instr) vector_size(&emit->code->instr) ?
             (Instr)vector_back(&emit->code->instr) : emit_add_instr(emit, RegPushImm);
         back->opcode = eOP_MAX;
         back->execute = SetRecurs;
-        back->m_val = 0;
+        back->m_val = 0;*/
       }
     } else if(emit->env->func != f && !f->value_ref->from->owner_class && !f->code && !is_fptr(emit->gwion, f->value_ref->type)) {
       if(fbflag(f->def->base, fbflag_op)) {
index 611a2b305c551c3cf6a0096a10f45095d4675fe9..74bfef01157906d3dbbcaea67e96f803031fa68b 100644 (file)
@@ -111,13 +111,13 @@ static OP_CHECK(opck_union_ctor) {
   if(!name || !name->next || name->next->next)
     ERR_N(name->pos, "Union constructor takes two arguments, "
          "'id' and 'value'");
-    if(name->exp_type != ae_exp_primary ||
-        name->d.prim.prim_type != ae_prim_id)
-    return NULL;
-    const Exp val = name->next;
-    const Type base = actual_type(env->gwion, call->func->type);
-    const Map map = &base->nspc->info->value->map;
-    for(m_uint i = 0; i < map_size(map); ++i) {
+  if(name->exp_type != ae_exp_primary ||
+      name->d.prim.prim_type != ae_prim_id)
+  return NULL;
+  const Exp val = name->next;
+  const Type base = actual_type(env->gwion, call->func->type);
+  const Map map = &base->nspc->info->value->map;
+  for(m_uint i = 0; i < map_size(map); ++i) {
     if(VKEY(map, i) == (m_uint)name->d.prim.d.var) {
       const Value v = (Value)VVAL(map, i);
       name->d.prim.prim_type = ae_prim_num;
index 932357ba438080170ad9e4909046f426fbeb5d0b..4ffa777edf3531c9a60df37876b82c0aa9395f40 100644 (file)
@@ -47,12 +47,11 @@ ANN2(2) int gw_asprintf(MemPool mp, char **str, const char *fmt, ...) {
 }
 
 ANN static void prepare_call(const VM_Shred shred, const m_uint offset) {
-  shred->mem += offset;
-  *(m_uint*)(shred->mem  + SZ_INT) = offset + SZ_INT;
-  *(VM_Code*)(shred->mem + SZ_INT*2) = shred->code;
-  *(m_uint*)(shred->mem  + SZ_INT*3) = shred->pc;
-  *(m_uint*)(shred->mem  + SZ_INT*4) = SZ_INT;
-  shred->mem += SZ_INT*5;
+  shred->mem += offset + SZ_INT + sizeof(struct frame_t);
+  register struct frame_t *frame = (struct frame_t*)(shred->mem - sizeof(struct frame_t));
+  frame->push = offset + SZ_INT;
+  frame->code = shred->code;
+  frame->pc   = shred->pc;
   shred->pc = 0;
 }
 
index deaff7b4d23a1c5847d4d9a28820eaf815a8d1f2..42d674467f986535aec9f1971f02ddb34b2d94b9 100644 (file)
@@ -40,10 +40,11 @@ uint32_t gw_rand(uint32_t s[2]) {
   return ret;
 }
 
-ANN static inline void shred_unwind(VM_Shred shred) {
-  shred->pc   = *(m_uint*) (shred->mem - SZ_INT * 2);
-  shred->code = *(VM_Code*)(shred->mem - SZ_INT * 3);
-  shred->mem -= (*(m_uint*)(shred->mem - SZ_INT * 4) + SZ_INT * 4);
+ANN static inline void shred_unwind(const VM_Shred shred) {
+  register struct frame_t *frame = &*(struct frame_t*)(shred->mem - sizeof(struct frame_t));
+  shred->code = frame->code;
+  shred->pc   = frame->pc;
+  shred->mem -= (frame->push + sizeof(struct frame_t));
 }
 
 ANN static bool unwind(VM_Shred shred, const Symbol effect, const m_uint size) {
@@ -402,8 +403,7 @@ ANN void vm_run(const VM* vm) { // lgtm [cpp/use-of-goto]
     &&firassign, &&firadd, &&firsub, &&firmul, &&firdiv,
     &&itof, &&ftoi,
     &&timeadv,
-    &&setcode,
-    &&regmove, &&regtomem, &&regtomemother, &&overflow, &&funcusrend, &&funcmemberend,
+    &&recurs, &&setcode, &&regmove, &&regtomem, &&regtomemother, &&overflow, &&funcusrend, &&funcusrend2, &&funcmemberend,
     &&sporkini, &&forkini, &&sporkfunc, &&sporkmemberfptr, &&sporkexp, &&sporkend,
     &&brancheqint, &&branchneint, &&brancheqfloat, &&branchnefloat, &&unroll,
     &&arrayappend, &&autounrollinit, &&autoloop, &&arraytop, &&arrayaccess, &&arrayget, &&arrayaddr,
@@ -547,10 +547,10 @@ regpushmaybe:
   DISPATCH();
 funcreturn:
 {
-  register const m_uint pc = *(m_uint*)(mem-SZ_INT*2);
-  bytecode = (code = *(VM_Code*)(mem-SZ_INT*3))->bytecode;
-  mem -= (*(m_uint*)(mem-SZ_INT*4) + SZ_INT*4);
-  PC_DISPATCH(pc);
+  register struct frame_t frame = *(struct frame_t*)(mem - sizeof(struct frame_t));
+  bytecode = (code = frame.code)->bytecode;
+  mem -= (frame.push + sizeof(struct frame_t));
+  PC_DISPATCH(frame.pc);
 }
 _goto:
   PC_DISPATCH(VAL);
@@ -709,16 +709,22 @@ timeadv:
   *(m_float*)(reg-SZ_FLOAT) += vm->bbq->pos;
   VM_OUT
   break;
+recurs:
+{
+  register const uint push = *(m_uint*)reg + code->stack_depth;
+  mem += push + sizeof(struct frame_t);
+  *(struct frame_t*)(mem - sizeof(struct frame_t)) = (struct frame_t){.code=code,.pc=VAL2,.push=push};
+  reg += (m_int)VAL;
+  next = eFuncUsrEnd2;
+}
+  DISPATCH();
 setcode:
 PRAGMA_PUSH()
   a.code = *(VM_Code*)(reg - SZ_INT);
   if(!a.code->builtin) {
-    register const m_uint push = *(m_uint*)reg + *(m_uint*)(mem-SZ_INT);
-    mem += push;
-    *(m_uint*)  mem = push; mem += SZ_INT;
-    *(VM_Code*) mem = code; mem += SZ_INT;
-    *(m_uint*)  mem = PC + VAL2; mem += SZ_INT;
-    *(m_uint*) mem = a.code->stack_depth; mem += SZ_INT;
+    register const uint push = *(m_uint*)reg + code->stack_depth;
+    mem += push + sizeof(struct frame_t);
+    *(struct frame_t*)(mem - sizeof(struct frame_t)) = (struct frame_t){.code=code,.pc=PC+VAL2,.push=push};
     next = eFuncUsrEnd;
   } else {
     mem += *(m_uint*)reg;
@@ -748,6 +754,9 @@ PRAGMA_PUSH()
   byte = bytecode = (code = a.code)->bytecode;
 PRAGMA_POP()
   SDISPATCH();
+funcusrend2:
+  byte = bytecode;
+  SDISPATCH();
 funcmemberend:
   VM_OUT
   {
index 77418999b1a412e799e15fbe8e07e4f82b059abf..8deb304d5aee9d03df0db37535ace57d6fa454e0 100644 (file)
@@ -141,6 +141,9 @@ ANN static m_bit* tobytecode(MemPool p, const VM_Code code) {
             map_set(&code->handlers, j, new_pc);
         }
         *(m_uint*)(data + SZ_INT) = new_pc;
+      } else if(opcode == eRecurs /*|| opcode == eSetCode*/) {
+        *(m_uint*)(final + j * BYTECODE_SZ + SZ_INT*2) =
+          instr->m_val2 += j+1;
       }
       setpc(data, j);
       ++j;