summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrian <[email protected]>2007-01-28 12:49:47 -0700
committerBrian <[email protected]>2007-01-28 12:49:47 -0700
commit4de6fac4daecac25bb3f4339610312022b457b46 (patch)
tree5b05109132bca7c6a9ede0fe80da0d3ed70e8c06
parent602dc1a63888af10b2ae491bdbb3afcb28004770 (diff)
Lots of vartable clean-ups, fixes. Report an error message when we run out
of registers, rather than crash.
-rw-r--r--src/mesa/shader/slang/slang_codegen.c8
-rw-r--r--src/mesa/shader/slang/slang_compile.c15
-rw-r--r--src/mesa/shader/slang/slang_emit.c33
-rw-r--r--src/mesa/shader/slang/slang_vartable.c198
-rw-r--r--src/mesa/shader/slang/slang_vartable.h10
5 files changed, 168 insertions, 96 deletions
diff --git a/src/mesa/shader/slang/slang_codegen.c b/src/mesa/shader/slang/slang_codegen.c
index ff42db9def5..3dc4fb36e71 100644
--- a/src/mesa/shader/slang/slang_codegen.c
+++ b/src/mesa/shader/slang/slang_codegen.c
@@ -2141,13 +2141,13 @@ _slang_gen_operation(slang_assemble_ctx * A, slang_operation *oper)
{
slang_ir_node *n;
- A->vartable = _slang_push_var_table(A->vartable);
+ _slang_push_var_table(A->vartable);
oper->type = slang_oper_block_no_new_scope; /* temp change */
n = _slang_gen_operation(A, oper);
oper->type = slang_oper_block_new_scope; /* restore */
- A->vartable = _slang_pop_var_table(A->vartable);
+ _slang_pop_var_table(A->vartable);
if (n)
n = new_node(IR_SCOPE, n, NULL);
@@ -2640,7 +2640,7 @@ _slang_codegen_function(slang_assemble_ctx * A, slang_function * fun)
A->CurFunction->end_label = slang_atom_pool_gen(A->atoms, "__endOfFunc_main_");
/* push new vartable scope */
- A->vartable = _slang_push_var_table(A->vartable);
+ _slang_push_var_table(A->vartable);
/* Generate IR tree for the function body code */
n = _slang_gen_operation(A, fun->body);
@@ -2648,7 +2648,7 @@ _slang_codegen_function(slang_assemble_ctx * A, slang_function * fun)
n = new_node(IR_SCOPE, n, NULL);
/* pop vartable, restore previous */
- A->vartable = _slang_pop_var_table(A->vartable);
+ _slang_pop_var_table(A->vartable);
if (!n) {
/* XXX record error */
diff --git a/src/mesa/shader/slang/slang_compile.c b/src/mesa/shader/slang/slang_compile.c
index c459eb29e74..43f8a303698 100644
--- a/src/mesa/shader/slang/slang_compile.c
+++ b/src/mesa/shader/slang/slang_compile.c
@@ -1978,8 +1978,20 @@ static GLboolean
parse_code_unit(slang_parse_ctx * C, slang_code_unit * unit,
struct gl_program *program)
{
+ GET_CURRENT_CONTEXT(ctx);
slang_output_ctx o;
GLboolean success;
+ GLuint maxRegs;
+
+ if (unit->type == slang_unit_fragment_builtin ||
+ unit->type == slang_unit_fragment_shader) {
+ maxRegs = ctx->Const.FragmentProgram.MaxTemps;
+ }
+ else {
+ assert(unit->type == slang_unit_vertex_builtin ||
+ unit->type == slang_unit_vertex_shader);
+ maxRegs = ctx->Const.VertexProgram.MaxTemps;
+ }
/* setup output context */
o.funs = &unit->funs;
@@ -1989,7 +2001,8 @@ parse_code_unit(slang_parse_ctx * C, slang_code_unit * unit,
o.global_pool = &unit->object->varpool;
o.machine = &unit->object->machine;
o.program = program;
- o.vartable = _slang_push_var_table(NULL);
+ o.vartable = _slang_new_var_table(maxRegs);
+ _slang_push_var_table(o.vartable);
/* parse individual functions and declarations */
while (*C->I != EXTERNAL_NULL) {
diff --git a/src/mesa/shader/slang/slang_emit.c b/src/mesa/shader/slang/slang_emit.c
index a4c1c2fad70..e9cbb895f85 100644
--- a/src/mesa/shader/slang/slang_emit.c
+++ b/src/mesa/shader/slang/slang_emit.c
@@ -332,14 +332,17 @@ slang_print_ir(const slang_ir_node *n, int indent)
* Allocate temporary storage for an intermediate result (such as for
* a multiply or add, etc.
*/
-static void
+static GLboolean
alloc_temp_storage(slang_var_table *vt, slang_ir_node *n, GLint size)
{
assert(!n->Var);
assert(!n->Store);
assert(size > 0);
n->Store = _slang_new_ir_storage(PROGRAM_TEMPORARY, -1, size);
- (void) _slang_alloc_temp(vt, n->Store);
+ if (!_slang_alloc_temp(vt, n->Store)) {
+ RETURN_ERROR("Ran out of registers, too many temporaries", 0);
+ }
+ return GL_TRUE;
}
@@ -634,7 +637,8 @@ emit_binop(slang_var_table *vt, slang_ir_node *n, struct gl_program *prog)
}
if (!n->Store) {
- alloc_temp_storage(vt, n, info->ResultSize);
+ if (!alloc_temp_storage(vt, n, info->ResultSize))
+ return NULL;
}
storage_to_dst_reg(&inst->DstReg, n->Store, n->Writemask);
@@ -667,7 +671,8 @@ emit_unop(slang_var_table *vt, slang_ir_node *n, struct gl_program *prog)
free_temp_storage(vt, n->Children[0]);
if (!n->Store) {
- alloc_temp_storage(vt, n, info->ResultSize);
+ if (!alloc_temp_storage(vt, n, info->ResultSize))
+ return NULL;
}
storage_to_dst_reg(&inst->DstReg, n->Store, n->Writemask);
@@ -691,7 +696,8 @@ emit_negation(slang_var_table *vt, slang_ir_node *n, struct gl_program *prog)
emit(vt, n->Children[0], prog);
if (!n->Store)
- alloc_temp_storage(vt, n, n->Children[0]->Store->Size);
+ if (!alloc_temp_storage(vt, n, n->Children[0]->Store->Size))
+ return NULL;
inst = new_instruction(prog, OPCODE_MOV);
storage_to_dst_reg(&inst->DstReg, n->Store, n->Writemask);
@@ -768,7 +774,8 @@ emit_tex(slang_var_table *vt, slang_ir_node *n, struct gl_program *prog)
}
if (!n->Store)
- alloc_temp_storage(vt, n, 4);
+ if (!alloc_temp_storage(vt, n, 4))
+ return NULL;
storage_to_dst_reg(&inst->DstReg, n->Store, n->Writemask);
@@ -880,7 +887,8 @@ emit_cond(slang_var_table *vt, slang_ir_node *n, struct gl_program *prog)
* Note: must use full 4-component vector since all four
* condition codes must be set identically.
*/
- alloc_temp_storage(vt, n, 4);
+ if (!alloc_temp_storage(vt, n, 4))
+ return NULL;
inst = new_instruction(prog, OPCODE_MOV);
inst->CondUpdate = GL_TRUE;
storage_to_dst_reg(&inst->DstReg, n->Store, n->Writemask);
@@ -912,9 +920,9 @@ emit(slang_var_table *vt, slang_ir_node *n, struct gl_program *prog)
case IR_SCOPE:
/* new variable scope */
- vt = _slang_push_var_table(vt);
+ _slang_push_var_table(vt);
inst = emit(vt, n->Children[0], prog);
- vt = _slang_pop_var_table(vt);
+ _slang_pop_var_table(vt);
return inst;
case IR_VAR_DECL:
@@ -925,19 +933,20 @@ emit(slang_var_table *vt, slang_ir_node *n, struct gl_program *prog)
assert(n->Store->Index < 0);
if (!n->Var || n->Var->isTemp) {
/* a nameless/temporary variable, will be freed after first use */
- (void) _slang_alloc_temp(vt, n->Store);
+ if (!_slang_alloc_temp(vt, n->Store))
+ RETURN_ERROR("Ran out of registers, too many temporaries", 0);
}
else {
/* a regular variable */
_slang_add_variable(vt, n->Var);
- (void) _slang_alloc_var(vt, n->Store);
+ if (!_slang_alloc_var(vt, n->Store))
+ RETURN_ERROR("Ran out of registers, too many variables", 0);
/*
printf("IR_VAR_DECL %s %d store %p\n",
(char*) n->Var->a_name, n->Store->Index, (void*) n->Store);
*/
assert(n->Var->aux == n->Store);
}
- assert(n->Store->Index >= 0);
break;
case IR_VAR:
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;
diff --git a/src/mesa/shader/slang/slang_vartable.h b/src/mesa/shader/slang/slang_vartable.h
index 51c2a1f77c5..8a3b992c969 100644
--- a/src/mesa/shader/slang/slang_vartable.h
+++ b/src/mesa/shader/slang/slang_vartable.h
@@ -9,9 +9,15 @@ typedef struct slang_var_table_ slang_var_table;
struct slang_variable_;
extern slang_var_table *
+_slang_new_var_table(GLuint maxRegisters);
+
+extern void
+_slang_delete_var_table(slang_var_table *vt);
+
+extern void
_slang_push_var_table(slang_var_table *parent);
-extern slang_var_table *
+extern void
_slang_pop_var_table(slang_var_table *t);
extern void
@@ -30,7 +36,7 @@ extern void
_slang_free_temp(slang_var_table *t, struct _slang_ir_storage *store);
extern GLboolean
-_slang_is_temp(slang_var_table *t, struct _slang_ir_storage *store);
+_slang_is_temp(const slang_var_table *t, const struct _slang_ir_storage *store);
#endif /* SLANG_VARTABLE_H */