Add an ir_if simplification pass.
[mesa.git] / glsl_types.cpp
index e08307cb7f35c3c1ccd206937416752ca3c1d4da..c8d18b9ee7a058d58ed2e983466c9141186bd545 100644 (file)
  * DEALINGS IN THE SOFTWARE.
  */
 
+#include <cstdio>
 #include <stdlib.h>
 #include "glsl_symbol_table.h"
 #include "glsl_parser_extras.h"
 #include "glsl_types.h"
 #include "builtin_types.h"
+#include "hash_table.h"
 
 
+hash_table *glsl_type::array_types = NULL;
+
 static void
 add_types_to_symbol_table(glsl_symbol_table *symtab,
                          const struct glsl_type *types,
-                         unsigned num_types)
+                         unsigned num_types, bool warn)
 {
-   unsigned i;
+   (void) warn;
 
-   for (i = 0; i < num_types; i++) {
+   for (unsigned i = 0; i < num_types; i++) {
       symtab->add_type(types[i].name, & types[i]);
    }
 }
@@ -45,12 +49,15 @@ static void
 generate_110_types(glsl_symbol_table *symtab)
 {
    add_types_to_symbol_table(symtab, builtin_core_types,
-                            Elements(builtin_core_types));
+                            Elements(builtin_core_types),
+                            false);
    add_types_to_symbol_table(symtab, builtin_structure_types,
-                            Elements(builtin_structure_types));
+                            Elements(builtin_structure_types),
+                            false);
    add_types_to_symbol_table(symtab, builtin_110_deprecated_structure_types,
-                            Elements(builtin_110_deprecated_structure_types));
-   add_types_to_symbol_table(symtab, & void_type, 1);
+                            Elements(builtin_110_deprecated_structure_types),
+                            false);
+   add_types_to_symbol_table(symtab, & void_type, 1, false);
 }
 
 
@@ -60,7 +67,7 @@ generate_120_types(glsl_symbol_table *symtab)
    generate_110_types(symtab);
 
    add_types_to_symbol_table(symtab, builtin_120_types,
-                            Elements(builtin_120_types));
+                            Elements(builtin_120_types), false);
 }
 
 
@@ -70,7 +77,16 @@ generate_130_types(glsl_symbol_table *symtab)
    generate_120_types(symtab);
 
    add_types_to_symbol_table(symtab, builtin_130_types,
-                            Elements(builtin_130_types));
+                            Elements(builtin_130_types), false);
+}
+
+
+static void
+generate_ARB_texture_rectangle_types(glsl_symbol_table *symtab, bool warn)
+{
+   add_types_to_symbol_table(symtab, builtin_ARB_texture_rectangle_types,
+                            Elements(builtin_ARB_texture_rectangle_types),
+                            warn);
 }
 
 
@@ -91,6 +107,11 @@ _mesa_glsl_initialize_types(struct _mesa_glsl_parse_state *state)
       /* error */
       break;
    }
+
+   if (state->ARB_texture_rectangle_enable) {
+      generate_ARB_texture_rectangle_types(state->symbols,
+                                          state->ARB_texture_rectangle_warn);
+   }
 }
 
 
@@ -111,6 +132,37 @@ const glsl_type *glsl_type::get_base_type() const
 }
 
 
+ir_function *
+glsl_type::generate_constructor_prototype(glsl_symbol_table *symtab) const
+{
+   /* FINISHME: Add support for non-array types. */
+   assert(base_type == GLSL_TYPE_ARRAY);
+
+   /* Generate the function name and add it to the symbol table.
+    */
+   ir_function *const f = new ir_function(name);
+
+   bool added = symtab->add_function(name, f);
+   assert(added);
+
+   ir_function_signature *const sig = new ir_function_signature(this);
+   f->add_signature(sig);
+
+   for (unsigned i = 0; i < length; i++) {
+      char *const param_name = (char *) malloc(10);
+
+      snprintf(param_name, 10, "p%08X", i);
+
+      ir_variable *var = new ir_variable(fields.array, param_name);
+
+      var->mode = ir_var_in;
+      sig->parameters.push_tail(var);
+   }
+
+   return f;
+}
+
+
 /**
  * Generate the function intro for a constructor
  *
@@ -126,9 +178,10 @@ const glsl_type *glsl_type::get_base_type() const
  *                     parameters.  These are used later to avoid having to use
  *                     the symbol table.
  */
-static void
+static ir_label *
 generate_constructor_intro(const glsl_type *type, unsigned parameter_count,
-                          exec_list *parameters, exec_list *instructions,
+                          ir_function_signature *const signature,
+                          exec_list *instructions,
                           ir_variable **declarations)
 {
    /* Names of parameters used in vector and matrix constructors
@@ -142,27 +195,23 @@ generate_constructor_intro(const glsl_type *type, unsigned parameter_count,
 
    const glsl_type *const parameter_type = type->get_base_type();
 
-   ir_label *const label = new ir_label(type->name);
+   ir_label *const label = new ir_label(type->name, signature);
    instructions->push_tail(label);
 
    for (unsigned i = 0; i < parameter_count; i++) {
       ir_variable *var = new ir_variable(parameter_type, names[i]);
 
       var->mode = ir_var_in;
-      parameters->push_tail(var);
-
-      var = new ir_variable(parameter_type, names[i]);
-
-      var->mode = ir_var_in;
-      instructions->push_tail(var);
+      signature->parameters.push_tail(var);
 
       declarations[i] = var;
    }
 
    ir_variable *retval = new ir_variable(type, "__retval");
-   instructions->push_tail(retval);
+   signature->body.push_tail(retval);
 
    declarations[16] = retval;
+   return label;
 }
 
 
@@ -397,36 +446,39 @@ generate_constructor(glsl_symbol_table *symtab, const struct glsl_type *types,
        * appropriate from-scalars constructor.
        */
       ir_function_signature *const sig = new ir_function_signature(& types[i]);
-      f->signatures.push_tail(sig);
+      f->add_signature(sig);
 
-      generate_constructor_intro(& types[i], 1, & sig->parameters,
-                                instructions, declarations);
+      sig->definition =
+        generate_constructor_intro(& types[i], 1, sig,
+                                   instructions, declarations);
 
       if (types[i].is_vector()) {
-        generate_vec_body_from_scalar(instructions, declarations);
+        generate_vec_body_from_scalar(&sig->body, declarations);
 
         ir_function_signature *const vec_sig =
            new ir_function_signature(& types[i]);
-        f->signatures.push_tail(vec_sig);
+        f->add_signature(vec_sig);
 
-        generate_constructor_intro(& types[i], types[i].vector_elements,
-                                   & vec_sig->parameters, instructions,
-                                   declarations);
-        generate_vec_body_from_N_scalars(instructions, declarations);
+        vec_sig->definition =
+           generate_constructor_intro(& types[i], types[i].vector_elements,
+                                      vec_sig, instructions,
+                                      declarations);
+        generate_vec_body_from_N_scalars(&sig->body, declarations);
       } else {
         assert(types[i].is_matrix());
 
-        generate_mat_body_from_scalar(instructions, declarations);
+        generate_mat_body_from_scalar(&sig->body, declarations);
 
         ir_function_signature *const mat_sig =
            new ir_function_signature(& types[i]);
-        f->signatures.push_tail(mat_sig);
-
-        generate_constructor_intro(& types[i],
-                                   (types[i].vector_elements
-                                    * types[i].matrix_columns),
-                                   & mat_sig->parameters, instructions,
-                                   declarations);
+        f->add_signature(mat_sig);
+
+        mat_sig->definition =
+           generate_constructor_intro(& types[i],
+                                      (types[i].vector_elements
+                                       * types[i].matrix_columns),
+                                      mat_sig, instructions,
+                                      declarations);
         generate_mat_body_from_N_scalars(instructions, declarations);
       }
    }
@@ -482,13 +534,40 @@ _mesa_glsl_initialize_constructors(exec_list *instructions,
 }
 
 
+glsl_type::glsl_type(const glsl_type *array, unsigned length) :
+   base_type(GLSL_TYPE_ARRAY),
+   sampler_dimensionality(0), sampler_shadow(0), sampler_array(0),
+   sampler_type(0),
+   vector_elements(0), matrix_columns(0),
+   name(NULL), length(length)
+{
+   this->fields.array = array;
+
+   /* Allow a maximum of 10 characters for the array size.  This is enough
+    * for 32-bits of ~0.  The extra 3 are for the '[', ']', and terminating
+    * NUL.
+    */
+   const unsigned name_length = strlen(array->name) + 10 + 3;
+   char *const n = (char *) malloc(name_length);
+
+   if (length == 0)
+      snprintf(n, name_length, "%s[]", array->name);
+   else
+      snprintf(n, name_length, "%s[%u]", array->name, length);
+
+   this->name = n;
+}
+
+
 const glsl_type *
 glsl_type::get_instance(unsigned base_type, unsigned rows, unsigned columns)
 {
+   if (base_type == GLSL_TYPE_VOID)
+      return &void_type;
+
    if ((rows < 1) || (rows > 4) || (columns < 1) || (columns > 4))
       return error_type;
 
-
    /* Treat GLSL vectors as Nx1 matrices.
     */
    if (columns == 1) {
@@ -536,3 +615,60 @@ glsl_type::get_instance(unsigned base_type, unsigned rows, unsigned columns)
    assert(!"Should not get here.");
    return error_type;
 }
+
+
+int
+glsl_type::array_key_compare(const void *a, const void *b)
+{
+   const glsl_type *const key1 = (glsl_type *) a;
+   const glsl_type *const key2 = (glsl_type *) b;
+
+   /* Return zero is the types match (there is zero difference) or non-zero
+    * otherwise.
+    */
+   return ((key1->fields.array == key2->fields.array)
+          && (key1->length == key2->length)) ? 0 : 1;
+}
+
+
+unsigned
+glsl_type::array_key_hash(const void *a)
+{
+   const glsl_type *const key = (glsl_type *) a;
+
+   const struct {
+      const glsl_type *t;
+      unsigned l;
+      char nul;
+   } hash_key = {
+      key->fields.array,
+      key->length,
+      '\0'
+   };
+
+   return hash_table_string_hash(& hash_key);
+}
+
+
+const glsl_type *
+glsl_type::get_array_instance(const glsl_type *base, unsigned array_size)
+{
+   const glsl_type key(base, array_size);
+
+   if (array_types == NULL) {
+      array_types = hash_table_ctor(64, array_key_hash, array_key_compare);
+   }
+
+   const glsl_type *t = (glsl_type *) hash_table_find(array_types, & key);
+   if (t == NULL) {
+      t = new glsl_type(base, array_size);
+
+      hash_table_insert(array_types, (void *) t, t);
+   }
+
+   assert(t->base_type == GLSL_TYPE_ARRAY);
+   assert(t->length == array_size);
+   assert(t->fields.array == base);
+
+   return t;
+}