summaryrefslogtreecommitdiffstats
path: root/src/mesa/shader/slang/slang_vartable.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mesa/shader/slang/slang_vartable.c')
-rw-r--r--src/mesa/shader/slang/slang_vartable.c202
1 files changed, 202 insertions, 0 deletions
diff --git a/src/mesa/shader/slang/slang_vartable.c b/src/mesa/shader/slang/slang_vartable.c
new file mode 100644
index 00000000000..cd6a081e04b
--- /dev/null
+++ b/src/mesa/shader/slang/slang_vartable.c
@@ -0,0 +1,202 @@
+
+#include "imports.h"
+#include "slang_compile.h"
+#include "slang_compile_variable.h"
+#include "slang_vartable.h"
+
+
+static int dbg = 0;
+
+
+typedef enum {
+ FREE,
+ VAR,
+ TEMP
+} TempState;
+
+static int Level = 0;
+
+struct slang_var_table_
+{
+ int level;
+ int num_entries;
+ slang_variable **vars; /* array [num_entries] */
+
+ TempState temps[MAX_PROGRAM_TEMPS];
+
+ struct slang_var_table_ *parent;
+};
+
+
+
+/**
+ * Create new table, put at head, return ptr to it.
+ */
+slang_var_table *
+_slang_push_var_table(slang_var_table *parent)
+{
+ slang_var_table *t
+ = (slang_var_table *) _mesa_calloc(sizeof(slang_var_table));
+ if (t) {
+ t->level = Level++;
+ t->parent = parent;
+ if (parent) {
+ /* copy the info indicating which temp regs are in use */
+ memcpy(t->temps, parent->temps, sizeof(t->temps));
+ }
+ if (dbg) printf("Pushing level %d\n", t->level);
+ }
+ return t;
+}
+
+
+/**
+ * Destroy given table, return ptr to parent
+ */
+slang_var_table *
+_slang_pop_var_table(slang_var_table *t)
+{
+ slang_var_table *parent = t->parent;
+ int i;
+ if (dbg) printf("Popping level %d\n", t->level);
+ if (t->parent) {
+ for (i = 0; i < MAX_PROGRAM_TEMPS; i++) {
+ if (t->temps[i] && !t->parent->temps[i])
+ if (dbg) printf(" Free reg %d\n", i);
+ }
+ }
+ for (i = 0; i < t->num_entries; i++) {
+ if (dbg) printf(" Free var %s\n", (char*) t->vars[i]->a_name);
+ }
+
+ if (t->vars)
+ free(t->vars);
+ free(t);
+ Level--;
+ return parent;
+}
+
+
+/**
+ * Add a new variable to the given symbol table.
+ */
+void
+_slang_add_variable(slang_var_table *t, slang_variable *v)
+{
+ assert(t);
+ t->vars = realloc(t->vars, (t->num_entries + 1) * sizeof(slang_variable *));
+ t->vars[t->num_entries] = v;
+ t->num_entries++;
+}
+
+
+/**
+ * Look for variable by name in given table.
+ * If not found, parent table will be searched.
+ */
+slang_variable *
+_slang_find_variable(const slang_var_table *t, slang_atom name)
+{
+ while (1) {
+ int i;
+ for (i = 0; i < t->num_entries; i++) {
+ if (t->vars[i]->a_name == name)
+ return t->vars[i];
+ }
+ if (t->parent)
+ t = t->parent;
+ else
+ return NULL;
+ }
+}
+
+
+static GLint
+alloc_reg(slang_var_table *t, GLint size, GLboolean isTemp)
+{
+ const GLuint sz4 = (size + 3) / 4;
+ GLuint i, j;
+ assert(size > 0); /* number of floats */
+
+ for (i = 0; i < MAX_PROGRAM_TEMPS; i++) {
+ GLuint found = 0;
+ for (j = 0; j < sz4; j++) {
+ if (!t->temps[i + j]) {
+ found++;
+ }
+ else {
+ break;
+ }
+ }
+ if (found == sz4) {
+ /* found block of size/4 free regs */
+ for (j = 0; j < sz4; j++)
+ t->temps[i + j] = isTemp ? TEMP : VAR;
+ return i;
+ }
+ }
+ return -1;
+}
+
+
+/**
+ * Allocate temp register(s) for storing a variable.
+ */
+GLint
+_slang_alloc_var(slang_var_table *t, GLint size)
+{
+ int i = alloc_reg(t, size, GL_FALSE);
+ if (dbg) printf("Alloc var %d (level %d)\n", i, t->level);
+ return i;
+}
+
+
+void
+_slang_reserve_var(slang_var_table *t, GLint r, GLint size)
+{
+ const GLint sz4 = (size + 3) / 4;
+ GLint i;
+ for (i = 0; i < sz4; i++) {
+ t->temps[r + i] = VAR;
+ }
+}
+
+
+/**
+ * Allocate temp register(s) for storing an unnamed intermediate value.
+ */
+GLint
+_slang_alloc_temp(slang_var_table *t, GLint size)
+{
+ int i = alloc_reg(t, size, GL_TRUE);
+ if (dbg) printf("Alloc temp %d (level %d)\n", i, t->level);
+ return i;
+}
+
+
+void
+_slang_free_temp(slang_var_table *t, GLint r, GLint size)
+{
+ const GLuint sz4 = (size + 3) / 4;
+ GLuint i;
+ assert(size > 0);
+ assert(r >= 0);
+ assert(r < MAX_PROGRAM_TEMPS);
+ if (dbg) printf("Free temp %d (level %d)\n", r, t->level);
+ for (i = 0; i < sz4; i++) {
+ assert(t->temps[r + i] == TEMP);
+ t->temps[r + i] = FREE;
+ }
+}
+
+
+GLboolean
+_slang_is_temp(slang_var_table *t, GLint r)
+{
+ assert(r >= 0);
+ assert(r < MAX_PROGRAM_TEMPS);
+ if (t->temps[r] == TEMP)
+ return GL_TRUE;
+ else
+ return GL_FALSE;
+}