mesa: more re-org of variable declarations in glsl compiler
authorBrian Paul <brian.paul@tungstengraphics.com>
Tue, 16 Dec 2008 01:18:08 +0000 (18:18 -0700)
committerBrian Paul <brianp@vmware.com>
Tue, 6 Jan 2009 16:13:54 +0000 (09:13 -0700)
(cherry picked from commit 49543d7177fabc848822431891266e33bc13c818)

src/mesa/shader/slang/slang_codegen.c

index ace87d7cd849f3a99b534923133441fa1a21b3ce..9fb23946b7499281d40c880b0031d4ef8908c0dc 100644 (file)
@@ -666,18 +666,9 @@ new_if(slang_ir_node *cond, slang_ir_node *ifPart, slang_ir_node *elsePart)
 static slang_ir_node *
 new_var(slang_assemble_ctx *A, slang_variable *var)
 {
-   slang_ir_node *n;
-   if (!var)
-      return NULL;
-
-   assert(var->declared);
-
-   n = new_node0(IR_VAR);
+   slang_ir_node *n = new_node0(IR_VAR);
    if (n) {
       _slang_attach_storage(n, var);
-      /*
-      printf("new_var %s store=%p\n", (char*)name, (void*) n->Store);
-      */
    }
    return n;
 }
@@ -2709,11 +2700,11 @@ make_constant_array(slang_assemble_ctx *A,
 /**
  * Generate IR node for allocating/declaring a variable (either a local or
  * a global).
- * Generally, this involves allocating slang_ir_storage for the variable,
- * choosing a register file (temporary, constant, etc).  For ordinary
- * variables we do not yet allocate storage though.  We do that when we
- * find the first actual use of the variable to avoid allocating temp regs
- * that will never get used.
+ * Generally, this involves allocating an slang_ir_storage instance for the
+ * variable, choosing a register file (temporary, constant, etc).
+ * For ordinary variables we do not yet allocate storage though.  We do that
+ * when we find the first actual use of the variable to avoid allocating temp
+ * regs that will never get used.
  * At this time, uniforms are always allocated space in this function.
  *
  * \param initializer  Optional initializer expression for the variable.
@@ -2726,58 +2717,69 @@ _slang_gen_var_decl(slang_assemble_ctx *A, slang_variable *var,
    const GLenum datatype = _slang_gltype_from_specifier(&var->type.specifier);
    slang_ir_node *varDecl, *n;
    slang_ir_storage *store;
+   GLint size, totalSize;  /* if array then totalSize > size */
+   enum register_file file;
 
    /*assert(!var->declared);*/
    var->declared = GL_TRUE;
 
-   varDecl = new_node0(IR_VAR_DECL);
-   if (!varDecl)
-      return NULL;
-
-   _slang_attach_storage(varDecl, var);
-   assert(var->store);
-   assert(varDecl->Store == var->store);
-   assert(varDecl->Store);
-   assert(varDecl->Store->Index < 0);
-   store = var->store;
-
-   assert(store == varDecl->Store);
-
    /* determine GPU register file for simple cases */
    if (is_sampler_type(&var->type)) {
-      store->File = PROGRAM_SAMPLER;
+      file = PROGRAM_SAMPLER;
    }
    else if (var->type.qualifier == SLANG_QUAL_UNIFORM) {
-      store->File = PROGRAM_UNIFORM;
+      file = PROGRAM_UNIFORM;
    }
    else {
-      store->File = PROGRAM_TEMPORARY;
+      file = PROGRAM_TEMPORARY;
    }
 
-   store->Size = _slang_sizeof_type_specifier(&varDecl->Var->type.specifier);
-   if (store->Size <= 0) {
-      slang_info_log_error(A->log, "invalid declaration for '%s'",
-                           (char*) var->a_name);
+   size = _slang_sizeof_type_specifier(&var->type.specifier);
+   if (size <= 0) {
+      slang_info_log_error(A->log, "invalid declaration for '%s'", varName);
       return NULL;
    }
 
+   totalSize = size;
    if (var->type.array_len > 0) {
       /* the type is an array, ex: float[4] x; */
-      GLint sz = (store->Size + 3) & ~3;
+      GLint sz = (totalSize + 3) & ~3;
       /* total size = element size * array length */
       sz *= var->type.array_len;
-      store->Size = sz;
+      totalSize = sz;
    }
 
    if (var->array_len > 0) {
       /* this is an array, ex: float x[4]; */
       /* round up the element size to a multiple of 4 */
-      GLint sz = (store->Size + 3) & ~3;
+      GLint sz = (totalSize + 3) & ~3;
       /* total size = element size * array length */
       sz *= var->array_len;
-      store->Size = sz;
+      totalSize = sz;
    }
 
+   /* Allocate IR node for the declaration */
+   varDecl = new_node0(IR_VAR_DECL);
+   if (!varDecl)
+      return NULL;
+
+   _slang_attach_storage(varDecl, var); /* undefined storage at first */
+   assert(var->store);
+   assert(varDecl->Store == var->store);
+   assert(varDecl->Store);
+   assert(varDecl->Store->Index < 0);
+   store = var->store;
+
+   assert(store == varDecl->Store);
+
+
+   /* Fill in storage fields which we now know.  store->Index/Swizzle may be
+    * set for some cases below.  Otherwise, store->Index/Swizzle will be set
+    * during code emit.
+    */
+   store->File = file;
+   store->Size = totalSize;
+
    /* if there's an initializer, generate IR for the expression */
    if (initializer) {
       slang_ir_node *varRef, *init;
@@ -2798,7 +2800,7 @@ _slang_gen_var_decl(slang_assemble_ctx *A, slang_variable *var,
       /* IR for the variable we're initializing */
       varRef = new_var(A, var);
       if (!varRef) {
-         slang_info_log_error(A->log, "undefined variable '%s'", varName);
+         slang_info_log_error(A->log, "out of memory");
          return NULL;
       }
 
@@ -2812,8 +2814,8 @@ _slang_gen_var_decl(slang_assemble_ctx *A, slang_variable *var,
          if (initializer->type == SLANG_OPER_CALL &&
              initializer->array_constructor) {
             /* array initializer */
-            make_constant_array(A, var, initializer);
-            return varRef;
+            if (make_constant_array(A, var, initializer))
+               return varRef;
          }
          else if (initializer->type == SLANG_OPER_LITERAL_FLOAT ||
                   initializer->type == SLANG_OPER_LITERAL_INT) {
@@ -2821,9 +2823,9 @@ _slang_gen_var_decl(slang_assemble_ctx *A, slang_variable *var,
             if (store->File == PROGRAM_UNIFORM) {
                store->Index = _mesa_add_uniform(A->program->Parameters,
                                                 varName,
-                                                store->Size, datatype,
+                                                totalSize, datatype,
                                                 initializer->literal);
-               /* XXX fix store->Swizzle here */
+               store->Swizzle = _slang_var_swizzle(size, 0);
                return varRef;
             }
 #if 0
@@ -2832,8 +2834,8 @@ _slang_gen_var_decl(slang_assemble_ctx *A, slang_variable *var,
                store->Index = _mesa_add_named_constant(A->program->Parameters,
                                                        varName,
                                                        initializer->literal,
-                                                       store->Size);
-               /* XXX fix swizzle here */
+                                                       totalSize);
+               store->Swizzle = _slang_var_swizzle(size, 0);
                return varRef;
             }
 #endif
@@ -2846,7 +2848,7 @@ _slang_gen_var_decl(slang_assemble_ctx *A, slang_variable *var,
          return NULL;
 
       /* XXX remove this when type checking is added above */
-      if (init->Store && varRef->Store->Size != init->Store->Size) {
+      if (init->Store && init->Store->Size != totalSize) {
          slang_info_log_error(A->log, "invalid assignment (wrong types)");
          return NULL;
       }
@@ -2861,10 +2863,10 @@ _slang_gen_var_decl(slang_assemble_ctx *A, slang_variable *var,
    }
 
    if (store->File == PROGRAM_UNIFORM && store->Index < 0) {
-      /* */
+      /* always need to allocate storage for uniforms at this point */
       store->Index = _mesa_add_uniform(A->program->Parameters, varName,
-                                       store->Size, datatype, NULL);
-      store->Swizzle = _slang_var_swizzle(store->Size, 0);
+                                       totalSize, datatype, NULL);
+      store->Swizzle = _slang_var_swizzle(size, 0);
    }
 
 #if 0
@@ -3249,11 +3251,13 @@ _slang_gen_variable(slang_assemble_ctx * A, slang_operation *oper)
     */
    slang_atom name = oper->var ? oper->var->a_name : oper->a_id;
    slang_variable *var = _slang_variable_locate(oper->locals, name, GL_TRUE);
-   slang_ir_node *n = new_var(A, var);
-   if (!n) {
+   slang_ir_node *n;
+   if (!var) {
       slang_info_log_error(A->log, "undefined variable '%s'", (char *) name);
       return NULL;
    }
+   assert(var->declared);
+   n = new_var(A, var);
    return n;
 }