Hugo Musso Gualandi 5 år sedan
förälder
incheckning
52e148a069
1 ändrade filer med 36 tillägg och 1 borttagningar
  1. 36 1
      src/luaot.c

+ 36 - 1
src/luaot.c

@@ -1042,7 +1042,42 @@ void create_function(Proto *p)
                 println("    ProtectNT(luaD_call(L, ra, nresults));");
                 break;
             }
-            // case OP_TAILCAL
+            case OP_TAILCALL: {
+                println("    int b = GETARG_B(i);  /* number of arguments + 1 (function) */");
+                println("    int nparams1 = GETARG_C(i);");
+                println("    /* delat is virtual 'func' - real 'func' (vararg functions) */");
+                println("    int delta = (nparams1) ? ci->u.l.nextraargs + nparams1 : 0;");
+                println("    if (b != 0)");
+                println("      L->top = ra + b;");
+                println("    else  /* previous instruction set top */");
+                println("      b = cast_int(L->top - ra);");
+                println("    savepc(ci);  /* some calls here can raise errors */");
+                println("    if (TESTARG_k(i)) {");
+                println("      /* close upvalues from current call; the compiler ensures");
+                println("         that there are no to-be-closed variables here, so this");
+                println("         call cannot change the stack */");
+                println("      luaF_close(L, base, NOCLOSINGMETH);");
+                println("      lua_assert(base == ci->func + 1);");
+                println("    }");
+                println("    if (!ttisfunction(s2v(ra))) {  /* not a function? */");
+                println("      luaD_tryfuncTM(L, ra);  /* try '__call' metamethod */");
+                println("      b++;  /* there is now one extra argument */");
+                println("    }");
+                println("    if (!ttisLclosure(s2v(ra))) {  /* C function? */");
+                println("      luaD_call(L, ra, LUA_MULTRET);  /* call it */");
+                println("      updatetrap(ci);");
+                println("      updatestack(ci);  /* stack may have been relocated */");
+                println("      ci->func -= delta;");
+                println("      luaD_poscall(L, ci, cast_int(L->top - ra));");
+                println("      return;");
+                println("    }");
+                println("    else {  /* Lua tail call */");
+                println("      ci->func -= delta;");
+                println("      luaD_pretailcall(L, ci, ra, b);  /* prepare call frame */");
+                println("      goto tailcall;");
+                println("    }");
+                break;
+            }
             case OP_RETURN: {
                 println("    int n = GETARG_B(i) - 1;  /* number of results */");
                 println("    int nparams1 = GETARG_C(i);");