]> de.git.xonotic.org Git - xonotic/gmqcc.git/blobdiff - exec.c
Merge branch 'master' into blub/bc3
[xonotic/gmqcc.git] / exec.c
diff --git a/exec.c b/exec.c
index be2e8c2e5f0fb34df51f4c5e493e063952e884d4..4a1ad09d8d600786df401b16f822a499173af020 100644 (file)
--- a/exec.c
+++ b/exec.c
@@ -4,7 +4,25 @@
 
 #include "gmqcc.h"
 
-#include "exec.h"
+MEM_VEC_FUNCTIONS(qc_program,   prog_section_statement, code)
+MEM_VEC_FUNCTIONS(qc_program,   prog_section_def,       defs)
+MEM_VEC_FUNCTIONS(qc_program,   prog_section_def,       fields)
+MEM_VEC_FUNCTIONS(qc_program,   prog_section_function,  functions)
+MEM_VEC_FUNCTIONS(qc_program,   char,                   strings)
+MEM_VEC_FUN_APPEND(qc_program,  char,                   strings)
+MEM_VEC_FUN_RESIZE(qc_program,  char,                   strings)
+MEM_VEC_FUNCTIONS(qc_program,   qcint,                  globals)
+MEM_VEC_FUNCTIONS(qc_program,   qcint,                  entitydata)
+
+MEM_VEC_FUNCTIONS(qc_program,   qcint,         localstack)
+MEM_VEC_FUN_APPEND(qc_program,  qcint,         localstack)
+MEM_VEC_FUN_RESIZE(qc_program,  qcint,         localstack)
+MEM_VEC_FUNCTIONS(qc_program,   qc_exec_stack, stack)
+
+MEM_VEC_FUNCTIONS(qc_program,   size_t, profile)
+MEM_VEC_FUN_RESIZE(qc_program,  size_t, profile)
+
+MEM_VEC_FUNCTIONS(qc_program,   prog_builtin, builtins)
 
 static void loaderror(const char *fmt, ...)
 {
@@ -118,6 +136,11 @@ void prog_delete(qc_program *prog)
     MEM_VECTOR_CLEAR(prog, localstack);
     MEM_VECTOR_CLEAR(prog, stack);
     MEM_VECTOR_CLEAR(prog, profile);
+
+    if (prog->builtins_alloc) {
+        MEM_VECTOR_CLEAR(prog, builtins);
+    }
+    /* otherwise the builtins were statically allocated */
     mem_d(prog);
 }
 
@@ -299,25 +322,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");
@@ -329,19 +376,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;
 }
 
@@ -396,6 +458,19 @@ cleanup:
  */
 
 #if defined(QCVM_EXECUTOR)
+static int qc_print(qc_program *prog)
+{
+    qcany *str = (qcany*)(prog->globals + OFS_PARM0);
+    printf("%s", prog_getstring(prog, str->string));
+    return 0;
+}
+
+static prog_builtin qc_builtins[] = {
+    NULL,
+    &qc_print
+};
+static size_t qc_builtins_count = sizeof(qc_builtins) / sizeof(qc_builtins[0]);
+
 int main(int argc, char **argv)
 {
     size_t      i;
@@ -413,6 +488,10 @@ int main(int argc, char **argv)
         exit(1);
     }
 
+    prog->builtins       = qc_builtins;
+    prog->builtins_count = qc_builtins_count;
+    prog->builtins_alloc = 0;
+
     for (i = 1; i < prog->functions_count; ++i) {
         const char *name = prog_getstring(prog, prog->functions[i].name);
         printf("Found function: %s\n", name);