mesa: move nvprogram.[ch] to main/
[mesa.git] / src / mesa / shader / slang / slang_vartable.c
index e3efa179085167068548a541ae3132c6f62e4d5e..e07e3a226a517ce5d7d677f7afa2305687cb17fd 100644 (file)
@@ -1,10 +1,13 @@
 
-#include "imports.h"
+#include "main/imports.h"
+#include "shader/program.h"
+#include "shader/prog_print.h"
 #include "slang_compile.h"
 #include "slang_compile_variable.h"
+#include "slang_emit.h"
+#include "slang_mem.h"
 #include "slang_vartable.h"
 #include "slang_ir.h"
-#include "prog_instruction.h"
 
 
 static int dbg = 0;
@@ -27,7 +30,7 @@ struct table
    slang_variable **Vars;  /* array [NumVars] */
 
    TempState Temps[MAX_PROGRAM_TEMPS * 4];  /* per-component state */
-   int ValSize[MAX_PROGRAM_TEMPS];     /* For debug only */
+   int ValSize[MAX_PROGRAM_TEMPS * 4];     /**< For debug only */
 
    struct table *Parent;  /** Parent scope table */
 };
@@ -49,7 +52,7 @@ slang_var_table *
 _slang_new_var_table(GLuint maxRegisters)
 {
    slang_var_table *vt
-      = (slang_var_table *) _mesa_calloc(sizeof(slang_var_table));
+      = (slang_var_table *) _slang_alloc(sizeof(slang_var_table));
    if (vt) {
       vt->MaxRegisters = maxRegisters;
    }
@@ -64,20 +67,19 @@ _slang_delete_var_table(slang_var_table *vt)
       _mesa_problem(NULL, "non-empty var table in _slang_delete_var_table()");
       return;
    }
-   _mesa_free(vt);
+   _slang_free(vt);
 }
 
 
 
 /**
- * Create new table, put at head, return ptr to it.
- * XXX we should take a maxTemps parameter to indicate how many temporaries
- * are available for the current shader/program target.
+ * Create new table on top of vartable stack.
+ * Used when we enter a {} block.
  */
 void
 _slang_push_var_table(slang_var_table *vt)
 {
-   struct table *t = (struct table *) _mesa_calloc(sizeof(struct table));
+   struct table *t = (struct table *) _slang_alloc(sizeof(struct table));
    if (t) {
       t->Level = vt->CurLevel++;
       t->Parent = vt->Top;
@@ -93,7 +95,8 @@ _slang_push_var_table(slang_var_table *vt)
 
 
 /**
- * Destroy given table, return ptr to Parent
+ * Pop top entry from variable table.
+ * Used when we leave a {} block.
  */
 void
 _slang_pop_var_table(slang_var_table *vt)
@@ -105,22 +108,30 @@ _slang_pop_var_table(slang_var_table *vt)
 
    /* free the storage allocated for each variable */
    for (i = 0; i < t->NumVars; i++) {
-      slang_ir_storage *store = (slang_ir_storage *) t->Vars[i]->aux;
+      slang_ir_storage *store = t->Vars[i]->store;
       GLint j;
       GLuint comp;
-      if (dbg) printf("  Free var %s, size %d at %d\n",
+      if (dbg) printf("  Free var %s, size %d at %d.%s\n",
                       (char*) t->Vars[i]->a_name, store->Size,
-                      store->Index);
+                      store->Index,
+                      _mesa_swizzle_string(store->Swizzle, 0, 0));
+
+      if (store->File == PROGRAM_SAMPLER) {
+         /* samplers have no storage */
+         continue;
+      }
 
       if (store->Size == 1)
          comp = GET_SWZ(store->Swizzle, 0);
       else
          comp = 0;
 
-      assert(store->Index >= 0);
-      for (j = 0; j < store->Size; j++) {
-         assert(t->Temps[store->Index * 4 + j + comp] == VAR);
-         t->Temps[store->Index * 4 + j + comp] = FREE;
+      /* store->Index may be -1 if we run out of registers */
+      if (store->Index >= 0) {
+         for (j = 0; j < store->Size; j++) {
+            assert(t->Temps[store->Index * 4 + j + comp] == VAR);
+            t->Temps[store->Index * 4 + j + comp] = FREE;
+         }
       }
       store->Index = -1;
    }
@@ -128,7 +139,7 @@ _slang_pop_var_table(slang_var_table *vt)
       /* just verify that any remaining allocations in this scope 
        * were for temps
        */
-      for (i = 0; i < vt->MaxRegisters * 4; i++) {
+      for (i = 0; i < (int) vt->MaxRegisters * 4; i++) {
          if (t->Temps[i] != FREE && t->Parent->Temps[i] == FREE) {
             if (dbg) printf("  Free reg %d\n", i/4);
             assert(t->Temps[i] == TEMP);
@@ -136,17 +147,19 @@ _slang_pop_var_table(slang_var_table *vt)
       }
    }
 
-   if (t->Vars)
-      free(t->Vars);
+   if (t->Vars) {
+      _slang_free(t->Vars);
+      t->Vars = NULL;
+   }
 
    vt->Top = t->Parent;
-   free(t);
+   _slang_free(t);
    vt->CurLevel--;
 }
 
 
 /**
- * Add a new variable to the given symbol table.
+ * Add a new variable to the given var/symbol table.
  */
 void
 _slang_add_variable(slang_var_table *vt, slang_variable *v)
@@ -155,8 +168,11 @@ _slang_add_variable(slang_var_table *vt, slang_variable *v)
    assert(vt);
    t = vt->Top;
    assert(t);
-   if (dbg) printf("Adding var %s\n", (char *) v->a_name);
-   t->Vars = realloc(t->Vars, (t->NumVars + 1) * sizeof(slang_variable *));
+   if (dbg) printf("Adding var %s, store %p\n", (char *) v->a_name, (void *) v->store);
+   t->Vars = (slang_variable **)
+      _slang_realloc(t->Vars,
+                     t->NumVars * sizeof(slang_variable *),
+                     (t->NumVars + 1) * sizeof(slang_variable *));
    t->Vars[t->NumVars] = v;
    t->NumVars++;
 }
@@ -200,7 +216,8 @@ alloc_reg(slang_var_table *vt, GLint size, GLboolean isTemp)
 
    for (i = 0; i <= vt->MaxRegisters * 4 - size; i += step) {
       GLuint found = 0;
-      for (j = 0; j < size; j++) {
+      for (j = 0; j < (GLuint) size; j++) {
+         assert(i + j < 4 * MAX_PROGRAM_TEMPS);
          if (i + j < vt->MaxRegisters * 4 && t->Temps[i + j] == FREE) {
             found++;
          }
@@ -212,12 +229,17 @@ alloc_reg(slang_var_table *vt, GLint size, GLboolean isTemp)
          /* found block of size free regs */
          if (size > 1)
             assert(i % 4 == 0);
-         for (j = 0; j < size; j++)
+         for (j = 0; j < (GLuint) size; j++) {
+            assert(i + j < 4 * MAX_PROGRAM_TEMPS);
             t->Temps[i + j] = isTemp ? TEMP : VAR;
+         }
+         assert(i < MAX_PROGRAM_TEMPS * 4);
          t->ValSize[i] = size;
          return i;
       }
    }
+
+   /* if we get here, we ran out of registers */
    return -1;
 }
 
@@ -232,22 +254,28 @@ GLboolean
 _slang_alloc_var(slang_var_table *vt, slang_ir_storage *store)
 {
    struct table *t = vt->Top;
-   const int i = alloc_reg(vt, store->Size, GL_FALSE);
+   int i;
+
+   if (store->File == PROGRAM_SAMPLER) {
+      /* don't really allocate storage */
+      store->Index = 0;
+      return GL_TRUE;
+   }
+
+   i = alloc_reg(vt, store->Size, GL_FALSE);
    if (i < 0)
       return GL_FALSE;
 
    store->Index = i / 4;
-   if (store->Size == 1) {
-      const GLuint comp = i % 4;
-      store->Swizzle = MAKE_SWIZZLE4(comp, comp, comp, comp);
-      if (dbg) printf("Alloc var sz %d at %d.%c (level %d)\n",
-                      store->Size, store->Index, "xyzw"[comp], t->Level);
-   }
-   else {
-      store->Swizzle = SWIZZLE_NOOP;
-      if (dbg) printf("Alloc var sz %d at %d.xyzw (level %d)\n",
-                      store->Size, store->Index, t->Level);
-   }
+   store->Swizzle = _slang_var_swizzle(store->Size, i % 4);
+
+   if (dbg)
+      printf("Alloc var storage sz %d at %d.%s (level %d) store %p\n",
+             store->Size, store->Index,
+             _mesa_swizzle_string(store->Swizzle, 0, 0),
+             t->Level,
+             (void*) store);
+
    return GL_TRUE;
 }
 
@@ -264,18 +292,16 @@ _slang_alloc_temp(slang_var_table *vt, slang_ir_storage *store)
    if (i < 0)
       return GL_FALSE;
 
+   assert(store->Index < 0);
+
    store->Index = i / 4;
-   if (store->Size == 1) {
-      const GLuint comp = i % 4;
-      store->Swizzle = MAKE_SWIZZLE4(comp, comp, comp, comp);
-      if (dbg) printf("Alloc temp sz %d at %d.%c (level %d)\n",
-                      store->Size, store->Index, "xyzw"[comp], t->Level);
-   }
-   else {
-      store->Swizzle = SWIZZLE_NOOP;
-      if (dbg) printf("Alloc temp sz %d at %d.xyzw (level %d)\n",
-                      store->Size, store->Index, t->Level);
-   }
+   store->Swizzle = _slang_var_swizzle(store->Size, i % 4);
+
+   if (dbg) printf("Alloc temp sz %d at %d.%s (level %d) store %p\n",
+                   store->Size, store->Index,
+                   _mesa_swizzle_string(store->Swizzle, 0, 0), t->Level,
+                   (void *) store);
+
    return GL_TRUE;
 }
 
@@ -285,23 +311,31 @@ _slang_free_temp(slang_var_table *vt, slang_ir_storage *store)
 {
    struct table *t = vt->Top;
    GLuint i;
-   GLuint r = store->Index;
+   GLint r = store->Index;
    assert(store->Size > 0);
    assert(r >= 0);
-   assert(r + store->Size <= vt->MaxRegisters * 4);
-   if (dbg) printf("Free temp sz %d at %d (level %d)\n", store->Size, r, t->Level);
+   assert((GLuint)r + store->Size <= vt->MaxRegisters * 4);
+   if (dbg) printf("Free temp sz %d at %d.%s (level %d) store %p\n",
+                   store->Size, r,
+                   _mesa_swizzle_string(store->Swizzle, 0, 0),
+                   t->Level, (void *) store);
    if (store->Size == 1) {
       const GLuint comp = GET_SWZ(store->Swizzle, 0);
+      /* we can actually fail some of these assertions because of the
+       * troublesome IR_SWIZZLE handling.
+       */
+#if 0
       assert(store->Swizzle == MAKE_SWIZZLE4(comp, comp, comp, comp));
       assert(comp < 4);
       assert(t->ValSize[r * 4 + comp] == 1);
+#endif
       assert(t->Temps[r * 4 + comp] == TEMP);
       t->Temps[r * 4 + comp] = FREE;
    }
    else {
       /*assert(store->Swizzle == SWIZZLE_NOOP);*/
       assert(t->ValSize[r*4] == store->Size);
-      for (i = 0; i < store->Size; i++) {
+      for (i = 0; i < (GLuint) store->Size; i++) {
          assert(t->Temps[r * 4 + i] == TEMP);
          t->Temps[r * 4 + i] = FREE;
       }
@@ -313,9 +347,9 @@ GLboolean
 _slang_is_temp(const slang_var_table *vt, const slang_ir_storage *store)
 {
    struct table *t = vt->Top;
-   assert(store->Index >= 0);
-   assert(store->Index < vt->MaxRegisters);
    GLuint comp;
+   assert(store->Index >= 0);
+   assert(store->Index < (int) vt->MaxRegisters);
    if (store->Swizzle == SWIZZLE_NOOP)
       comp = 0;
    else