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.c198
1 files changed, 121 insertions, 77 deletions
diff --git a/src/mesa/shader/slang/slang_vartable.c b/src/mesa/shader/slang/slang_vartable.c
index 02714554282..12996966704 100644
--- a/src/mesa/shader/slang/slang_vartable.c
+++ b/src/mesa/shader/slang/slang_vartable.c
@@ -16,96 +16,132 @@ typedef enum {
TEMP
} TempState;
-static int Level = 0;
-struct slang_var_table_
+/**
+ * Variable/register info for one variable scope.
+ */
+struct table
{
- int level;
- int num_entries;
- slang_variable **vars; /* array [num_entries] */
+ int Level;
+ int NumVars;
+ slang_variable **Vars; /* array [NumVars] */
- TempState temps[MAX_PROGRAM_TEMPS * 4]; /* per-component state */
- int size[MAX_PROGRAM_TEMPS]; /* For debug only */
+ TempState Temps[MAX_PROGRAM_TEMPS * 4]; /* per-component state */
+ int ValSize[MAX_PROGRAM_TEMPS]; /* For debug only */
- struct slang_var_table_ *parent;
+ struct table *Parent; /** Parent scope table */
};
+/**
+ * A variable table is a stack of tables, one per scope.
+ */
+struct slang_var_table_
+{
+ GLint CurLevel;
+ GLuint MaxRegisters;
+ struct table *Top; /**< Table at top of stack */
+};
+
+
+
+slang_var_table *
+_slang_new_var_table(GLuint maxRegisters)
+{
+ slang_var_table *vt
+ = (slang_var_table *) _mesa_calloc(sizeof(slang_var_table));
+ if (vt) {
+ vt->MaxRegisters = maxRegisters;
+ }
+ return vt;
+}
+
+
+void
+_slang_delete_var_table(slang_var_table *vt)
+{
+ if (vt->Top) {
+ _mesa_problem(NULL, "non-empty var table in _slang_delete_var_table()");
+ return;
+ }
+ _mesa_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.
*/
-slang_var_table *
-_slang_push_var_table(slang_var_table *parent)
+void
+_slang_push_var_table(slang_var_table *vt)
{
- slang_var_table *t
- = (slang_var_table *) _mesa_calloc(sizeof(slang_var_table));
+ struct table *t = (struct table *) _mesa_calloc(sizeof(struct table));
if (t) {
- t->level = Level++;
- t->parent = parent;
- if (parent) {
+ t->Level = vt->CurLevel++;
+ t->Parent = vt->Top;
+ if (t->Parent) {
/* copy the info indicating which temp regs are in use */
- memcpy(t->temps, parent->temps, sizeof(t->temps));
- memcpy(t->size, parent->size, sizeof(t->size));
+ memcpy(t->Temps, t->Parent->Temps, sizeof(t->Temps));
+ memcpy(t->ValSize, t->Parent->ValSize, sizeof(t->ValSize));
}
- if (dbg) printf("Pushing level %d\n", t->level);
+ vt->Top = t;
+ if (dbg) printf("Pushing level %d\n", t->Level);
}
- return t;
}
/**
- * Destroy given table, return ptr to parent
+ * Destroy given table, return ptr to Parent
*/
-slang_var_table *
-_slang_pop_var_table(slang_var_table *t)
+void
+_slang_pop_var_table(slang_var_table *vt)
{
- slang_var_table *parent = t->parent;
+ struct table *t = vt->Top;
int i;
- if (dbg) printf("Popping level %d\n", t->level);
+ if (dbg) printf("Popping level %d\n", t->Level);
/* free the storage allocated for each variable */
- for (i = 0; i < t->num_entries; i++) {
- slang_ir_storage *store = (slang_ir_storage *) t->vars[i]->aux;
+ for (i = 0; i < t->NumVars; i++) {
+ slang_ir_storage *store = (slang_ir_storage *) t->Vars[i]->aux;
GLint j;
- const GLuint sz = store->Size;
GLuint comp;
if (dbg) printf(" Free var %s, size %d at %d\n",
- (char*) t->vars[i]->a_name, store->Size,
+ (char*) t->Vars[i]->a_name, store->Size,
store->Index);
- if (sz == 1)
+ if (store->Size == 1)
comp = GET_SWZ(store->Swizzle, 0);
else
comp = 0;
assert(store->Index >= 0);
- for (j = 0; j < sz; j++) {
- assert(t->temps[store->Index * 4 + j + comp] == VAR);
- t->temps[store->Index * 4 + j + comp] = FREE;
+ 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;
}
- if (t->parent) {
+ if (t->Parent) {
/* just verify that any remaining allocations in this scope
* were for temps
*/
- for (i = 0; i < MAX_PROGRAM_TEMPS * 4; i++) {
- if (t->temps[i] != FREE && t->parent->temps[i] == FREE) {
+ for (i = 0; i < 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);
+ assert(t->Temps[i] == TEMP);
}
}
}
- if (t->vars)
- free(t->vars);
+ if (t->Vars)
+ free(t->Vars);
+
+ vt->Top = t->Parent;
free(t);
- Level--;
- return parent;
+ vt->CurLevel--;
}
@@ -113,31 +149,35 @@ _slang_pop_var_table(slang_var_table *t)
* Add a new variable to the given symbol table.
*/
void
-_slang_add_variable(slang_var_table *t, slang_variable *v)
+_slang_add_variable(slang_var_table *vt, slang_variable *v)
{
+ struct table *t;
+ assert(vt);
+ t = vt->Top;
assert(t);
if (dbg) printf("Adding var %s\n", (char *) v->a_name);
- t->vars = realloc(t->vars, (t->num_entries + 1) * sizeof(slang_variable *));
- t->vars[t->num_entries] = v;
- t->num_entries++;
+ t->Vars = realloc(t->Vars, (t->NumVars + 1) * sizeof(slang_variable *));
+ t->Vars[t->NumVars] = v;
+ t->NumVars++;
}
/**
* Look for variable by name in given table.
- * If not found, parent table will be searched.
+ * If not found, Parent table will be searched.
*/
slang_variable *
-_slang_find_variable(const slang_var_table *t, slang_atom name)
+_slang_find_variable(const slang_var_table *vt, slang_atom name)
{
+ struct table *t = vt->Top;
while (1) {
int i;
- for (i = 0; i < t->num_entries; i++) {
- if (t->vars[i]->a_name == name)
- return t->vars[i];
+ for (i = 0; i < t->NumVars; i++) {
+ if (t->Vars[i]->a_name == name)
+ return t->Vars[i];
}
- if (t->parent)
- t = t->parent;
+ if (t->Parent)
+ t = t->Parent;
else
return NULL;
}
@@ -150,17 +190,18 @@ _slang_find_variable(const slang_var_table *t, slang_atom name)
* \return position for var, measured in floats
*/
static GLint
-alloc_reg(slang_var_table *t, GLint size, GLboolean isTemp)
+alloc_reg(slang_var_table *vt, GLint size, GLboolean isTemp)
{
+ struct table *t = vt->Top;
/* if size == 1, allocate anywhere, else, pos must be multiple of 4 */
const GLuint step = (size == 1) ? 1 : 4;
GLuint i, j;
assert(size > 0); /* number of floats */
- for (i = 0; i < MAX_PROGRAM_TEMPS - size; i += step) {
+ for (i = 0; i <= vt->MaxRegisters * 4 - size; i += step) {
GLuint found = 0;
for (j = 0; j < size; j++) {
- if (i + j < MAX_PROGRAM_TEMPS && t->temps[i + j] == FREE) {
+ if (i + j < vt->MaxRegisters * 4 && t->Temps[i + j] == FREE) {
found++;
}
else {
@@ -172,9 +213,8 @@ alloc_reg(slang_var_table *t, GLint size, GLboolean isTemp)
if (size > 1)
assert(i % 4 == 0);
for (j = 0; j < size; j++)
- t->temps[i + j] = isTemp ? TEMP : VAR;
- printf("t->size[%d] = %d\n", i, size);
- t->size[i] = size;
+ t->Temps[i + j] = isTemp ? TEMP : VAR;
+ t->ValSize[i] = size;
return i;
}
}
@@ -189,9 +229,10 @@ alloc_reg(slang_var_table *t, GLint size, GLboolean isTemp)
* \return register allocated, or -1
*/
GLboolean
-_slang_alloc_var(slang_var_table *t, slang_ir_storage *store)
+_slang_alloc_var(slang_var_table *vt, slang_ir_storage *store)
{
- const int i = alloc_reg(t, store->Size, GL_FALSE);
+ struct table *t = vt->Top;
+ const int i = alloc_reg(vt, store->Size, GL_FALSE);
if (i < 0)
return GL_FALSE;
@@ -200,12 +241,12 @@ _slang_alloc_var(slang_var_table *t, slang_ir_storage *store)
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);
+ 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->Size, store->Index, t->Level);
}
return GL_TRUE;
}
@@ -216,9 +257,10 @@ _slang_alloc_var(slang_var_table *t, slang_ir_storage *store)
* Allocate temp register(s) for storing an unnamed intermediate value.
*/
GLboolean
-_slang_alloc_temp(slang_var_table *t, slang_ir_storage *store)
+_slang_alloc_temp(slang_var_table *vt, slang_ir_storage *store)
{
- const int i = alloc_reg(t, store->Size, GL_TRUE);
+ struct table *t = vt->Top;
+ const int i = alloc_reg(vt, store->Size, GL_TRUE);
if (i < 0)
return GL_FALSE;
@@ -227,57 +269,59 @@ _slang_alloc_temp(slang_var_table *t, slang_ir_storage *store)
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);
+ 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->Size, store->Index, t->Level);
}
return GL_TRUE;
}
void
-_slang_free_temp(slang_var_table *t, slang_ir_storage *store)
+_slang_free_temp(slang_var_table *vt, slang_ir_storage *store)
{
+ struct table *t = vt->Top;
GLuint i;
GLuint r = store->Index;
assert(store->Size > 0);
assert(r >= 0);
- assert(r + store->Size <= MAX_PROGRAM_TEMPS);
- if (dbg) printf("Free temp sz %d at %d (level %d)\n", store->Size, r, t->level);
+ assert(r + store->Size <= vt->MaxRegisters * 4);
+ if (dbg) printf("Free temp sz %d at %d (level %d)\n", store->Size, r, t->Level);
if (store->Size == 1) {
const GLuint comp = GET_SWZ(store->Swizzle, 0);
assert(store->Swizzle == MAKE_SWIZZLE4(comp, comp, comp, comp));
assert(comp < 4);
- assert(t->size[r * 4 + comp] == 1);
- assert(t->temps[r * 4 + comp] == TEMP);
- t->temps[r * 4 + comp] = FREE;
+ assert(t->ValSize[r * 4 + comp] == 1);
+ assert(t->Temps[r * 4 + comp] == TEMP);
+ t->Temps[r * 4 + comp] = FREE;
}
else {
assert(store->Swizzle == SWIZZLE_NOOP);
- assert(t->size[r*4] == store->Size);
+ assert(t->ValSize[r*4] == store->Size);
for (i = 0; i < store->Size; i++) {
- assert(t->temps[r * 4 + i] == TEMP);
- t->temps[r * 4 + i] = FREE;
+ assert(t->Temps[r * 4 + i] == TEMP);
+ t->Temps[r * 4 + i] = FREE;
}
}
}
GLboolean
-_slang_is_temp(slang_var_table *t, slang_ir_storage *store)
+_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 < MAX_PROGRAM_TEMPS);
+ assert(store->Index < vt->MaxRegisters);
GLuint comp;
if (store->Swizzle == SWIZZLE_NOOP)
comp = 0;
else
comp = GET_SWZ(store->Swizzle, 0);
- if (t->temps[store->Index * 4 + comp] == TEMP)
+ if (t->Temps[store->Index * 4 + comp] == TEMP)
return GL_TRUE;
else
return GL_FALSE;