diff options
| author | Brian <brian@yutani.localnet.net> | 2007-01-28 12:49:47 -0700 | 
|---|---|---|
| committer | Brian <brian@yutani.localnet.net> | 2007-01-28 12:49:47 -0700 | 
| commit | 4de6fac4daecac25bb3f4339610312022b457b46 (patch) | |
| tree | 5b05109132bca7c6a9ede0fe80da0d3ed70e8c06 /src | |
| parent | 602dc1a63888af10b2ae491bdbb3afcb28004770 (diff) | |
Lots of vartable clean-ups, fixes.  Report an error message when we run out
of registers, rather than crash.
Diffstat (limited to 'src')
| -rw-r--r-- | src/mesa/shader/slang/slang_codegen.c | 8 | ||||
| -rw-r--r-- | src/mesa/shader/slang/slang_compile.c | 15 | ||||
| -rw-r--r-- | src/mesa/shader/slang/slang_emit.c | 33 | ||||
| -rw-r--r-- | src/mesa/shader/slang/slang_vartable.c | 198 | ||||
| -rw-r--r-- | src/mesa/shader/slang/slang_vartable.h | 10 | 
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 ff42db9def..3dc4fb36e7 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 c459eb29e7..43f8a30369 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 a4c1c2fad7..e9cbb895f8 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 0271455428..1299696670 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 51c2a1f77c..8a3b992c96 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 */  | 
