]> Nishi Git Mirror - gwion.git/commitdiff
:art: Improve vararg
authorJérémie Astor <astor.jeremie@wanadoo.fr>
Sun, 31 May 2020 18:06:13 +0000 (20:06 +0200)
committerJérémie Astor <astor.jeremie@wanadoo.fr>
Sun, 31 May 2020 18:06:13 +0000 (20:06 +0200)
src/emit/emit.c
src/lib/vararg.c

index 1341f71acd7643ba921f7386994f3ff41cfbde5b..330c636dc9747364ac5d3b7f8241c7f566236d55 100644 (file)
@@ -1422,11 +1422,6 @@ ANN static m_bool emit_stmt_flow(const Emitter emit, const Stmt_Flow stmt) {
   return ret;
 }
 
-ANN static Instr variadic_state0(const Emitter emit, const Stmt_VarLoop stmt) {
-  CHECK_BO(emit_exp(emit, stmt->exp))
-  return emit_add_instr(emit, BranchEqInt);
-}
-
 ANN static m_bool variadic_state(const Emitter emit, const Stmt_VarLoop stmt, const m_uint status) {
   regpushi(emit, status);
   CHECK_BB(emit_exp(emit, stmt->exp))
@@ -1439,9 +1434,10 @@ ANN static m_bool variadic_state(const Emitter emit, const Stmt_VarLoop stmt, co
 }
 
 ANN static m_bool emit_stmt_varloop(const Emitter emit, const Stmt_VarLoop stmt) {
-  DECL_OB(const Instr,state, = variadic_state0(emit, stmt))
   CHECK_BB(variadic_state(emit, stmt, 1))
   CHECK_BB(emit_exp(emit, stmt->exp))
+  const Instr member = emit_add_instr(emit, DotMember4);
+  member->m_val = SZ_INT*2;
   const Instr instr = emit_add_instr(emit, BranchEqInt);
   const m_uint pc = emit_code_size(emit);
   emit_stmt(emit, stmt->body, 1);
@@ -1449,7 +1445,7 @@ ANN static m_bool emit_stmt_varloop(const Emitter emit, const Stmt_VarLoop stmt)
   emit_vararg_end(emit, pc);
   instr->m_val = emit_code_size(emit);
   CHECK_BB(variadic_state(emit, stmt, 0))
-  state->m_val = instr->m_val = emit_code_size(emit);
+  instr->m_val = emit_code_size(emit);
   return GW_OK;
 }
 
index 0ff2228989c28c6e7a987a3101257e57ccb440b5..aa1db9f9ab87d247850a9e19b53c895e4ddb40a7 100644 (file)
@@ -16,7 +16,7 @@
 #include "gack.h"
 
 void free_vararg(MemPool p, struct Vararg_* arg) {
-  if(arg->l) {
+  if(arg->t.ptr) {
     xfree(arg->d);
     vector_release(&arg->t);
   }
@@ -25,7 +25,7 @@ void free_vararg(MemPool p, struct Vararg_* arg) {
 
 static DTOR(vararg_dtor) {
   struct Vararg_ *arg = *(struct Vararg_**)o->data;
-  if(arg->l) {
+  if(*(m_uint*)(o->data + SZ_INT*2)) {
     m_uint offset = 0;
     for(m_uint i = 0; i < vector_size(&arg->t); ++i) {
       const Type t = (Type)vector_at(&arg->t, i);
@@ -41,8 +41,7 @@ static MFUN(mfun_vararg_cpy) {
   struct Vararg_ *src =  *(struct Vararg_**)o->data;
   struct Vararg_* arg = mp_calloc(shred->info->mp, Vararg);
   vector_copy2(&src->t, &arg->t);
-  arg->l = src->l;
-  arg->d = (m_bit*)xmalloc(round2szint(arg->l));
+  arg->d = (m_bit*)xmalloc(round2szint(*(m_uint*)(o->data + SZ_INT*2)));
   m_uint offset = 0;
   for(m_uint i = 0; i < vector_size(&arg->t); ++i) {
     const Type t = (Type)vector_at(&arg->t, arg->i);
@@ -56,6 +55,7 @@ static MFUN(mfun_vararg_cpy) {
   arg->o = src->o;
   const M_Object obj = new_object(shred->info->mp, shred, o->type_ref);
   *(struct Vararg_**)obj->data = arg;
+  *(m_uint*)(obj->data + SZ_INT*2) = *(m_uint*)(o->data + SZ_INT*2);
   *(M_Object*)RETURN = obj;
 }
 
@@ -64,8 +64,9 @@ INSTR(VarargIni) {
   struct Vararg_* arg = mp_calloc(shred->info->mp, Vararg);
   *(struct Vararg_**)o->data = arg;
   POP_REG(shred, instr->m_val - SZ_INT)
-  if((arg->l = instr->m_val)) {
-    arg->d = (m_bit*)xmalloc(round2szint(arg->l));
+//  if((arg->l = instr->m_val)) {
+  if((*(m_uint*)(o->data + SZ_INT * 2) = instr->m_val)) {
+    arg->d = (m_bit*)xmalloc(round2szint(instr->m_val));
     const Vector kinds = (Vector)instr->m_val2;
     vector_copy2(kinds, &arg->t);
     m_uint offset = 0;
@@ -80,15 +81,14 @@ INSTR(VarargIni) {
       offset += t->size;
     }
     arg->s = vector_size(kinds);
-    *(M_Object*)REG(-SZ_INT) = o;
-  } else
-    *(M_Object*)REG(-SZ_INT) = NULL;
+  }
+  *(M_Object*)REG(-SZ_INT) = o;
 }
 
 static INSTR(VarargEnd) {
   const M_Object o = *(M_Object*)REG(0);
   struct Vararg_* arg = *(struct Vararg_**)o->data;
-  arg->o += ((Type)vector_at(&arg->t, arg->i))->size;
+  arg->o += arg->t.ptr ? ((Type)vector_at(&arg->t, arg->i))->size : 0;
   if(++arg->i < arg->s)
     shred->pc = instr->m_val;
   else
@@ -104,6 +104,8 @@ static INSTR(VarargCast) {
   const M_Object o = *(M_Object*)REG(-SZ_INT);
   if(!*(m_uint*)(o->data + SZ_INT))
          Except(shred, "Using Vararg outside varloop");
+  if(!*(m_uint*)(o->data + SZ_INT*2))
+         Except(shred, "Using Vararg cast on empty vararg");
   struct Vararg_* arg = *(struct Vararg_**)o->data;
   const Type t = (Type)instr->m_val;
   if(isa((Type)vector_at(&arg->t, arg->i), t) < 0)
@@ -157,6 +159,8 @@ GWION_IMPORT(vararg) {
   CHECK_BB(gwi_item_end(gwi, ae_flag_none, NULL))
   CHECK_BB(gwi_item_ini(gwi, "int", "@inLoop"))
   CHECK_BB(gwi_item_end(gwi, ae_flag_none, NULL))
+  CHECK_BB(gwi_item_ini(gwi, "int", "@len"))
+  CHECK_BB(gwi_item_end(gwi, ae_flag_none, NULL))
   CHECK_BB(gwi_func_ini(gwi, "Vararg", "cpy"))
   CHECK_BB(gwi_func_end(gwi, mfun_vararg_cpy, ae_flag_none))
   GWI_BB(gwi_class_end(gwi))