]> git.xonotic.org Git - xonotic/gmqcc.git/commitdiff
Adopt dp's function-local backup strategy and add parameter-copying to EnterFunction
authorWolfgang (Blub) Bumiller <blub@speed.at>
Fri, 29 Jun 2012 14:04:24 +0000 (16:04 +0200)
committerWolfgang (Blub) Bumiller <blub@speed.at>
Fri, 29 Jun 2012 14:04:24 +0000 (16:04 +0200)
exec.c

diff --git a/exec.c b/exec.c
index e76eb4b8178f82f81df48a878134b22417d8d02b..63d0e17773a8d5a0e1fd8a8822c372cb95414829 100644 (file)
--- a/exec.c
+++ b/exec.c
@@ -315,25 +315,49 @@ static void prog_print_statement(qc_program *prog, prog_section_statement *st)
 static qcint prog_enterfunction(qc_program *prog, prog_section_function *func)
 {
     qc_exec_stack st;
-    prog_section_function *cur = NULL;
-
-    if (prog->stack_count)
-        cur = prog->stack[prog->stack_count-1].function;
+    size_t p, parampos;
 
     /* back up locals */
     st.localsp  = prog->localstack_count;
     st.stmt     = prog->statement;
     st.function = func;
 
-    if (cur)
+#ifdef QCVM_BACKUP_STRATEGY_CALLER_VARS
+    if (prog->stack_count)
     {
-        qcint *globals = prog->globals + cur->firstlocal;
-        if (!qc_program_localstack_append(prog, globals, cur->locals))
+        prog_section_function *cur;
+        cur = prog->stack[prog->stack_count-1].function;
+        if (cur)
+        {
+            qcint *globals = prog->globals + cur->firstlocal;
+            if (!qc_program_localstack_append(prog, globals, cur->locals))
+            {
+                printf("out of memory\n");
+                exit(1);
+            }
+        }
+    }
+#else
+    {
+        qcint *globals = prog->globals + func->firstlocal;
+        if (!qc_program_localstack_append(prog, globals, func->locals))
         {
             printf("out of memory\n");
             exit(1);
         }
     }
+#endif
+
+    /* copy parameters */
+    parampos = func->firstlocal;
+    for (p = 0; p < func->nargs; ++p)
+    {
+        size_t s;
+        for (s = 0; s < func->argsize[p]; ++s) {
+            prog->globals[parampos] = prog->globals[OFS_PARM0 + 3*p + s];
+            ++parampos;
+        }
+    }
 
     if (!qc_program_stack_add(prog, st)) {
         printf("out of memory\n");
@@ -345,19 +369,34 @@ static qcint prog_enterfunction(qc_program *prog, prog_section_function *func)
 
 static qcint prog_leavefunction(qc_program *prog)
 {
+    prog_section_function *prev = NULL;
+    size_t oldsp;
+
     qc_exec_stack st = prog->stack[prog->stack_count-1];
-    if (!qc_program_stack_remove(prog, prog->stack_count-1)) {
-        printf("out of memory\n");
-        exit(1);
-    }
 
-    if (st.localsp != prog->localstack_count) {
-        if (!qc_program_localstack_resize(prog, st.localsp)) {
+#ifdef QCVM_BACKUP_STRATEGY_CALLER_VARS
+    if (prog->stack_count > 1) {
+        prev  = prog->stack[prog->stack_count-2].function;
+        oldsp = prog->stack[prog->stack_count-2].localsp;
+    }
+#else
+    prev  = prog->stack[prog->stack_count-1].function;
+    oldsp = prog->stack[prog->stack_count-1].localsp;
+#endif
+    if (prev) {
+        qcint *globals = prog->globals + prev->firstlocal;
+        memcpy(globals, prog->localstack + oldsp, prev->locals);
+        if (!qc_program_localstack_resize(prog, oldsp)) {
             printf("out of memory\n");
             exit(1);
         }
     }
 
+    if (!qc_program_stack_remove(prog, prog->stack_count-1)) {
+        printf("out of memory\n");
+        exit(1);
+    }
+
     return st.stmt;
 }