glsl: tidy up IR after loop unrolling
[mesa.git] / src / compiler / glsl_types.cpp
index 17ebf07acbc127d014618677089174476de57227..99cc696c19bfa08f0983e655361b7fbec42b5a29 100644 (file)
 #include "util/hash_table.h"
 
 
-mtx_t glsl_type::mutex = _MTX_INITIALIZER_NP;
+mtx_t glsl_type::mem_mutex = _MTX_INITIALIZER_NP;
+mtx_t glsl_type::hash_mutex = _MTX_INITIALIZER_NP;
 hash_table *glsl_type::array_types = NULL;
 hash_table *glsl_type::record_types = NULL;
 hash_table *glsl_type::interface_types = NULL;
+hash_table *glsl_type::function_types = NULL;
 hash_table *glsl_type::subroutine_types = NULL;
 void *glsl_type::mem_ctx = NULL;
 
@@ -39,7 +41,7 @@ void
 glsl_type::init_ralloc_type_ctx(void)
 {
    if (glsl_type::mem_ctx == NULL) {
-      glsl_type::mem_ctx = ralloc_autofree_context();
+      glsl_type::mem_ctx = ralloc_context(NULL);
       assert(glsl_type::mem_ctx != NULL);
    }
 }
@@ -50,17 +52,24 @@ glsl_type::glsl_type(GLenum gl_type,
    gl_type(gl_type),
    base_type(base_type),
    sampler_dimensionality(0), sampler_shadow(0), sampler_array(0),
-   sampler_type(0), interface_packing(0),
+   sampled_type(0), interface_packing(0), interface_row_major(0),
    vector_elements(vector_elements), matrix_columns(matrix_columns),
    length(0)
 {
-   mtx_lock(&glsl_type::mutex);
+   /* Values of these types must fit in the two bits of
+    * glsl_type::sampled_type.
+    */
+   STATIC_ASSERT((unsigned(GLSL_TYPE_UINT)  & 3) == unsigned(GLSL_TYPE_UINT));
+   STATIC_ASSERT((unsigned(GLSL_TYPE_INT)   & 3) == unsigned(GLSL_TYPE_INT));
+   STATIC_ASSERT((unsigned(GLSL_TYPE_FLOAT) & 3) == unsigned(GLSL_TYPE_FLOAT));
+
+   mtx_lock(&glsl_type::mem_mutex);
 
    init_ralloc_type_ctx();
    assert(name != NULL);
    this->name = ralloc_strdup(this->mem_ctx, name);
 
-   mtx_unlock(&glsl_type::mutex);
+   mtx_unlock(&glsl_type::mem_mutex);
 
    /* Neither dimension is zero or both dimensions are zero.
     */
@@ -74,25 +83,20 @@ glsl_type::glsl_type(GLenum gl_type, glsl_base_type base_type,
    gl_type(gl_type),
    base_type(base_type),
    sampler_dimensionality(dim), sampler_shadow(shadow),
-   sampler_array(array), sampler_type(type), interface_packing(0),
-   length(0)
+   sampler_array(array), sampled_type(type), interface_packing(0),
+   interface_row_major(0), length(0)
 {
-   mtx_lock(&glsl_type::mutex);
+   mtx_lock(&glsl_type::mem_mutex);
 
    init_ralloc_type_ctx();
    assert(name != NULL);
    this->name = ralloc_strdup(this->mem_ctx, name);
 
-   mtx_unlock(&glsl_type::mutex);
+   mtx_unlock(&glsl_type::mem_mutex);
 
    memset(& fields, 0, sizeof(fields));
 
-   if (base_type == GLSL_TYPE_SAMPLER) {
-      /* Samplers take no storage whatsoever. */
-      matrix_columns = vector_elements = 0;
-   } else {
-      matrix_columns = vector_elements = 1;
-   }
+   matrix_columns = vector_elements = 1;
 }
 
 glsl_type::glsl_type(const glsl_struct_field *fields, unsigned num_fields,
@@ -100,13 +104,13 @@ glsl_type::glsl_type(const glsl_struct_field *fields, unsigned num_fields,
    gl_type(0),
    base_type(GLSL_TYPE_STRUCT),
    sampler_dimensionality(0), sampler_shadow(0), sampler_array(0),
-   sampler_type(0), interface_packing(0),
+   sampled_type(0), interface_packing(0), interface_row_major(0),
    vector_elements(0), matrix_columns(0),
    length(num_fields)
 {
    unsigned int i;
 
-   mtx_lock(&glsl_type::mutex);
+   mtx_lock(&glsl_type::mem_mutex);
 
    init_ralloc_type_ctx();
    assert(name != NULL);
@@ -115,74 +119,90 @@ glsl_type::glsl_type(const glsl_struct_field *fields, unsigned num_fields,
                                          glsl_struct_field, length);
 
    for (i = 0; i < length; i++) {
-      this->fields.structure[i].type = fields[i].type;
+      this->fields.structure[i] = fields[i];
       this->fields.structure[i].name = ralloc_strdup(this->fields.structure,
                                                      fields[i].name);
-      this->fields.structure[i].location = fields[i].location;
-      this->fields.structure[i].interpolation = fields[i].interpolation;
-      this->fields.structure[i].centroid = fields[i].centroid;
-      this->fields.structure[i].sample = fields[i].sample;
-      this->fields.structure[i].matrix_layout = fields[i].matrix_layout;
-      this->fields.structure[i].patch = fields[i].patch;
-      this->fields.structure[i].image_read_only = fields[i].image_read_only;
-      this->fields.structure[i].image_write_only = fields[i].image_write_only;
-      this->fields.structure[i].image_coherent = fields[i].image_coherent;
-      this->fields.structure[i].image_volatile = fields[i].image_volatile;
-      this->fields.structure[i].image_restrict = fields[i].image_restrict;
-      this->fields.structure[i].precision = fields[i].precision;
    }
 
-   mtx_unlock(&glsl_type::mutex);
+   mtx_unlock(&glsl_type::mem_mutex);
 }
 
 glsl_type::glsl_type(const glsl_struct_field *fields, unsigned num_fields,
-                     enum glsl_interface_packing packing, const char *name) :
+                     enum glsl_interface_packing packing,
+                     bool row_major, const char *name) :
    gl_type(0),
    base_type(GLSL_TYPE_INTERFACE),
    sampler_dimensionality(0), sampler_shadow(0), sampler_array(0),
-   sampler_type(0), interface_packing((unsigned) packing),
+   sampled_type(0), interface_packing((unsigned) packing),
+   interface_row_major((unsigned) row_major),
    vector_elements(0), matrix_columns(0),
    length(num_fields)
 {
    unsigned int i;
 
-   mtx_lock(&glsl_type::mutex);
+   mtx_lock(&glsl_type::mem_mutex);
 
    init_ralloc_type_ctx();
    assert(name != NULL);
    this->name = ralloc_strdup(this->mem_ctx, name);
-   this->fields.structure = ralloc_array(this->mem_ctx,
-                                         glsl_struct_field, length);
+   this->fields.structure = rzalloc_array(this->mem_ctx,
+                                          glsl_struct_field, length);
    for (i = 0; i < length; i++) {
-      this->fields.structure[i].type = fields[i].type;
+      this->fields.structure[i] = fields[i];
       this->fields.structure[i].name = ralloc_strdup(this->fields.structure,
                                                      fields[i].name);
-      this->fields.structure[i].location = fields[i].location;
-      this->fields.structure[i].interpolation = fields[i].interpolation;
-      this->fields.structure[i].centroid = fields[i].centroid;
-      this->fields.structure[i].sample = fields[i].sample;
-      this->fields.structure[i].matrix_layout = fields[i].matrix_layout;
-      this->fields.structure[i].patch = fields[i].patch;
-      this->fields.structure[i].precision = fields[i].precision;
    }
 
-   mtx_unlock(&glsl_type::mutex);
+   mtx_unlock(&glsl_type::mem_mutex);
+}
+
+glsl_type::glsl_type(const glsl_type *return_type,
+                     const glsl_function_param *params, unsigned num_params) :
+   gl_type(0),
+   base_type(GLSL_TYPE_FUNCTION),
+   sampler_dimensionality(0), sampler_shadow(0), sampler_array(0),
+   sampled_type(0), interface_packing(0), interface_row_major(0),
+   vector_elements(0), matrix_columns(0),
+   length(num_params)
+{
+   unsigned int i;
+
+   mtx_lock(&glsl_type::mem_mutex);
+
+   init_ralloc_type_ctx();
+
+   this->fields.parameters = rzalloc_array(this->mem_ctx,
+                                           glsl_function_param, num_params + 1);
+
+   /* We store the return type as the first parameter */
+   this->fields.parameters[0].type = return_type;
+   this->fields.parameters[0].in = false;
+   this->fields.parameters[0].out = true;
+
+   /* We store the i'th parameter in slot i+1 */
+   for (i = 0; i < length; i++) {
+      this->fields.parameters[i + 1].type = params[i].type;
+      this->fields.parameters[i + 1].in = params[i].in;
+      this->fields.parameters[i + 1].out = params[i].out;
+   }
+
+   mtx_unlock(&glsl_type::mem_mutex);
 }
 
 glsl_type::glsl_type(const char *subroutine_name) :
    gl_type(0),
    base_type(GLSL_TYPE_SUBROUTINE),
    sampler_dimensionality(0), sampler_shadow(0), sampler_array(0),
-   sampler_type(0), interface_packing(0),
+   sampled_type(0), interface_packing(0), interface_row_major(0),
    vector_elements(1), matrix_columns(1),
    length(0)
 {
-   mtx_lock(&glsl_type::mutex);
+   mtx_lock(&glsl_type::mem_mutex);
 
    init_ralloc_type_ctx();
    assert(subroutine_name != NULL);
    this->name = ralloc_strdup(this->mem_ctx, subroutine_name);
-   mtx_unlock(&glsl_type::mutex);
+   mtx_unlock(&glsl_type::mem_mutex);
 }
 
 bool
@@ -190,7 +210,7 @@ glsl_type::contains_sampler() const
 {
    if (this->is_array()) {
       return this->fields.array->contains_sampler();
-   } else if (this->is_record()) {
+   } else if (this->is_record() || this->is_interface()) {
       for (unsigned int i = 0; i < this->length; i++) {
          if (this->fields.structure[i].type->contains_sampler())
             return true;
@@ -201,13 +221,26 @@ glsl_type::contains_sampler() const
    }
 }
 
+bool
+glsl_type::contains_array() const
+{
+   if (this->is_record() || this->is_interface()) {
+      for (unsigned int i = 0; i < this->length; i++) {
+         if (this->fields.structure[i].type->contains_array())
+            return true;
+      }
+      return false;
+   } else {
+      return this->is_array();
+   }
+}
 
 bool
 glsl_type::contains_integer() const
 {
    if (this->is_array()) {
       return this->fields.array->contains_integer();
-   } else if (this->is_record()) {
+   } else if (this->is_record() || this->is_interface()) {
       for (unsigned int i = 0; i < this->length; i++) {
          if (this->fields.structure[i].type->contains_integer())
             return true;
@@ -223,7 +256,7 @@ glsl_type::contains_double() const
 {
    if (this->is_array()) {
       return this->fields.array->contains_double();
-   } else if (this->is_record()) {
+   } else if (this->is_record() || this->is_interface()) {
       for (unsigned int i = 0; i < this->length; i++) {
          if (this->fields.structure[i].type->contains_double())
             return true;
@@ -244,6 +277,7 @@ glsl_type::contains_opaque() const {
    case GLSL_TYPE_ARRAY:
       return fields.array->contains_opaque();
    case GLSL_TYPE_STRUCT:
+   case GLSL_TYPE_INTERFACE:
       for (unsigned int i = 0; i < length; i++) {
          if (fields.structure[i].type->contains_opaque())
             return true;
@@ -259,7 +293,7 @@ glsl_type::contains_subroutine() const
 {
    if (this->is_array()) {
       return this->fields.array->contains_subroutine();
-   } else if (this->is_record()) {
+   } else if (this->is_record() || this->is_interface()) {
       for (unsigned int i = 0; i < this->length; i++) {
          if (this->fields.structure[i].type->contains_subroutine())
             return true;
@@ -275,7 +309,7 @@ glsl_type::sampler_index() const
 {
    const glsl_type *const t = (this->is_array()) ? this->fields.array : this;
 
-   assert(t->is_sampler());
+   assert(t->is_sampler() || t->is_image());
 
    switch (t->sampler_dimensionality) {
    case GLSL_SAMPLER_DIM_1D:
@@ -305,7 +339,7 @@ glsl_type::contains_image() const
 {
    if (this->is_array()) {
       return this->fields.array->contains_image();
-   } else if (this->is_record()) {
+   } else if (this->is_record() || this->is_interface()) {
       for (unsigned int i = 0; i < this->length; i++) {
          if (this->fields.structure[i].type->contains_image())
             return true;
@@ -329,6 +363,10 @@ const glsl_type *glsl_type::get_base_type() const
       return double_type;
    case GLSL_TYPE_BOOL:
       return bool_type;
+   case GLSL_TYPE_UINT64:
+      return uint64_t_type;
+   case GLSL_TYPE_INT64:
+      return int64_t_type;
    default:
       return error_type;
    }
@@ -355,6 +393,10 @@ const glsl_type *glsl_type::get_scalar_type() const
       return double_type;
    case GLSL_TYPE_BOOL:
       return bool_type;
+   case GLSL_TYPE_UINT64:
+      return uint64_t_type;
+   case GLSL_TYPE_INT64:
+      return int64_t_type;
    default:
       /* Handle everything else */
       return type;
@@ -383,13 +425,26 @@ _mesa_glsl_release_types(void)
       _mesa_hash_table_destroy(glsl_type::interface_types, NULL);
       glsl_type::interface_types = NULL;
    }
+
+   if (glsl_type::function_types != NULL) {
+      _mesa_hash_table_destroy(glsl_type::function_types, NULL);
+      glsl_type::function_types = NULL;
+   }
+
+   if (glsl_type::subroutine_types != NULL) {
+      _mesa_hash_table_destroy(glsl_type::subroutine_types, NULL);
+      glsl_type::subroutine_types = NULL;
+   }
+
+   ralloc_free(glsl_type::mem_ctx);
+   glsl_type::mem_ctx = NULL;
 }
 
 
 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), interface_packing(0),
+   sampled_type(0), interface_packing(0), interface_row_major(0),
    vector_elements(0), matrix_columns(0),
    length(length), name(NULL)
 {
@@ -406,9 +461,9 @@ glsl_type::glsl_type(const glsl_type *array, unsigned length) :
     */
    const unsigned name_length = strlen(array->name) + 10 + 3;
 
-   mtx_lock(&glsl_type::mutex);
+   mtx_lock(&glsl_type::mem_mutex);
    char *const n = (char *) ralloc_size(this->mem_ctx, name_length);
-   mtx_unlock(&glsl_type::mutex);
+   mtx_unlock(&glsl_type::mem_mutex);
 
    if (length == 0)
       snprintf(n, name_length, "%s[]", array->name);
@@ -494,6 +549,31 @@ glsl_type::bvec(unsigned components)
 }
 
 
+const glsl_type *
+glsl_type::i64vec(unsigned components)
+{
+   if (components == 0 || components > 4)
+      return error_type;
+
+   static const glsl_type *const ts[] = {
+      int64_t_type, i64vec2_type, i64vec3_type, i64vec4_type
+   };
+   return ts[components - 1];
+}
+
+
+const glsl_type *
+glsl_type::u64vec(unsigned components)
+{
+   if (components == 0 || components > 4)
+      return error_type;
+
+   static const glsl_type *const ts[] = {
+      uint64_t_type, u64vec2_type, u64vec3_type, u64vec4_type
+   };
+   return ts[components - 1];
+}
+
 const glsl_type *
 glsl_type::get_instance(unsigned base_type, unsigned rows, unsigned columns)
 {
@@ -517,6 +597,10 @@ glsl_type::get_instance(unsigned base_type, unsigned rows, unsigned columns)
          return dvec(rows);
       case GLSL_TYPE_BOOL:
          return bvec(rows);
+      case GLSL_TYPE_UINT64:
+         return u64vec(rows);
+      case GLSL_TYPE_INT64:
+         return i64vec(rows);
       default:
          return error_type;
       }
@@ -618,6 +702,9 @@ glsl_type::get_sampler_instance(enum glsl_sampler_dim dim,
             return error_type;
          else
             return samplerExternalOES_type;
+      case GLSL_SAMPLER_DIM_SUBPASS:
+      case GLSL_SAMPLER_DIM_SUBPASS_MS:
+         return error_type;
       }
    case GLSL_TYPE_INT:
       if (shadow)
@@ -645,6 +732,9 @@ glsl_type::get_sampler_instance(enum glsl_sampler_dim dim,
          return (array ? isampler2DMSArray_type : isampler2DMS_type);
       case GLSL_SAMPLER_DIM_EXTERNAL:
          return error_type;
+      case GLSL_SAMPLER_DIM_SUBPASS:
+      case GLSL_SAMPLER_DIM_SUBPASS_MS:
+         return error_type;
       }
    case GLSL_TYPE_UINT:
       if (shadow)
@@ -672,6 +762,108 @@ glsl_type::get_sampler_instance(enum glsl_sampler_dim dim,
          return (array ? usampler2DMSArray_type : usampler2DMS_type);
       case GLSL_SAMPLER_DIM_EXTERNAL:
          return error_type;
+      case GLSL_SAMPLER_DIM_SUBPASS:
+      case GLSL_SAMPLER_DIM_SUBPASS_MS:
+         return error_type;
+      }
+   default:
+      return error_type;
+   }
+
+   unreachable("switch statement above should be complete");
+}
+
+const glsl_type *
+glsl_type::get_image_instance(enum glsl_sampler_dim dim,
+                              bool array, glsl_base_type type)
+{
+   switch (type) {
+   case GLSL_TYPE_FLOAT:
+      switch (dim) {
+      case GLSL_SAMPLER_DIM_1D:
+         return (array ? image1DArray_type : image1D_type);
+      case GLSL_SAMPLER_DIM_2D:
+         return (array ? image2DArray_type : image2D_type);
+      case GLSL_SAMPLER_DIM_3D:
+         return image3D_type;
+      case GLSL_SAMPLER_DIM_CUBE:
+         return (array ? imageCubeArray_type : imageCube_type);
+      case GLSL_SAMPLER_DIM_RECT:
+         if (array)
+            return error_type;
+         else
+            return image2DRect_type;
+      case GLSL_SAMPLER_DIM_BUF:
+         if (array)
+            return error_type;
+         else
+            return imageBuffer_type;
+      case GLSL_SAMPLER_DIM_MS:
+         return (array ? image2DMSArray_type : image2DMS_type);
+      case GLSL_SAMPLER_DIM_SUBPASS:
+         return subpassInput_type;
+      case GLSL_SAMPLER_DIM_SUBPASS_MS:
+         return subpassInputMS_type;
+      case GLSL_SAMPLER_DIM_EXTERNAL:
+         return error_type;
+      }
+   case GLSL_TYPE_INT:
+      switch (dim) {
+      case GLSL_SAMPLER_DIM_1D:
+         return (array ? iimage1DArray_type : iimage1D_type);
+      case GLSL_SAMPLER_DIM_2D:
+         return (array ? iimage2DArray_type : iimage2D_type);
+      case GLSL_SAMPLER_DIM_3D:
+         if (array)
+            return error_type;
+         return iimage3D_type;
+      case GLSL_SAMPLER_DIM_CUBE:
+         return (array ? iimageCubeArray_type : iimageCube_type);
+      case GLSL_SAMPLER_DIM_RECT:
+         if (array)
+            return error_type;
+         return iimage2DRect_type;
+      case GLSL_SAMPLER_DIM_BUF:
+         if (array)
+            return error_type;
+         return iimageBuffer_type;
+      case GLSL_SAMPLER_DIM_MS:
+         return (array ? iimage2DMSArray_type : iimage2DMS_type);
+      case GLSL_SAMPLER_DIM_SUBPASS:
+         return isubpassInput_type;
+      case GLSL_SAMPLER_DIM_SUBPASS_MS:
+         return isubpassInputMS_type;
+      case GLSL_SAMPLER_DIM_EXTERNAL:
+         return error_type;
+      }
+   case GLSL_TYPE_UINT:
+      switch (dim) {
+      case GLSL_SAMPLER_DIM_1D:
+         return (array ? uimage1DArray_type : uimage1D_type);
+      case GLSL_SAMPLER_DIM_2D:
+         return (array ? uimage2DArray_type : uimage2D_type);
+      case GLSL_SAMPLER_DIM_3D:
+         if (array)
+            return error_type;
+         return uimage3D_type;
+      case GLSL_SAMPLER_DIM_CUBE:
+         return (array ? uimageCubeArray_type : uimageCube_type);
+      case GLSL_SAMPLER_DIM_RECT:
+         if (array)
+            return error_type;
+         return uimage2DRect_type;
+      case GLSL_SAMPLER_DIM_BUF:
+         if (array)
+            return error_type;
+         return uimageBuffer_type;
+      case GLSL_SAMPLER_DIM_MS:
+         return (array ? uimage2DMSArray_type : uimage2DMS_type);
+      case GLSL_SAMPLER_DIM_SUBPASS:
+         return usubpassInput_type;
+      case GLSL_SAMPLER_DIM_SUBPASS_MS:
+         return usubpassInputMS_type;
+      case GLSL_SAMPLER_DIM_EXTERNAL:
+         return error_type;
       }
    default:
       return error_type;
@@ -691,7 +883,7 @@ glsl_type::get_array_instance(const glsl_type *base, unsigned array_size)
    char key[128];
    snprintf(key, sizeof(key), "%p[%u]", (void *) base, array_size);
 
-   mtx_lock(&glsl_type::mutex);
+   mtx_lock(&glsl_type::hash_mutex);
 
    if (array_types == NULL) {
       array_types = _mesa_hash_table_create(NULL, _mesa_key_hash_string,
@@ -700,9 +892,7 @@ glsl_type::get_array_instance(const glsl_type *base, unsigned array_size)
 
    const struct hash_entry *entry = _mesa_hash_table_search(array_types, key);
    if (entry == NULL) {
-      mtx_unlock(&glsl_type::mutex);
       const glsl_type *t = new glsl_type(base, array_size);
-      mtx_lock(&glsl_type::mutex);
 
       entry = _mesa_hash_table_insert(array_types,
                                       ralloc_strdup(mem_ctx, key),
@@ -713,14 +903,14 @@ glsl_type::get_array_instance(const glsl_type *base, unsigned array_size)
    assert(((glsl_type *) entry->data)->length == array_size);
    assert(((glsl_type *) entry->data)->fields.array == base);
 
-   mtx_unlock(&glsl_type::mutex);
+   mtx_unlock(&glsl_type::hash_mutex);
 
    return (glsl_type *) entry->data;
 }
 
 
 bool
-glsl_type::record_compare(const glsl_type *b) const
+glsl_type::record_compare(const glsl_type *b, bool match_locations) const
 {
    if (this->length != b->length)
       return false;
@@ -728,19 +918,18 @@ glsl_type::record_compare(const glsl_type *b) const
    if (this->interface_packing != b->interface_packing)
       return false;
 
+   if (this->interface_row_major != b->interface_row_major)
+      return false;
+
    /* From the GLSL 4.20 specification (Sec 4.2):
     *
     *     "Structures must have the same name, sequence of type names, and
     *     type definitions, and field names to be considered the same type."
     *
     * GLSL ES behaves the same (Ver 1.00 Sec 4.2.4, Ver 3.00 Sec 4.2.5).
-    *
-    * Note that we cannot force type name check when comparing unnamed
-    * structure types, these have a unique name assigned during parsing.
     */
-   if (!this->is_anonymous() && !b->is_anonymous())
-      if (strcmp(this->name, b->name) != 0)
-         return false;
+   if (strcmp(this->name, b->name) != 0)
+      return false;
 
    for (unsigned i = 0; i < this->length; i++) {
       if (this->fields.structure[i].type != b->fields.structure[i].type)
@@ -751,9 +940,12 @@ glsl_type::record_compare(const glsl_type *b) const
       if (this->fields.structure[i].matrix_layout
          != b->fields.structure[i].matrix_layout)
         return false;
-      if (this->fields.structure[i].location
+      if (match_locations && this->fields.structure[i].location
           != b->fields.structure[i].location)
          return false;
+      if (this->fields.structure[i].offset
+          != b->fields.structure[i].offset)
+         return false;
       if (this->fields.structure[i].interpolation
           != b->fields.structure[i].interpolation)
          return false;
@@ -766,24 +958,36 @@ glsl_type::record_compare(const glsl_type *b) const
       if (this->fields.structure[i].patch
           != b->fields.structure[i].patch)
          return false;
-      if (this->fields.structure[i].image_read_only
-          != b->fields.structure[i].image_read_only)
+      if (this->fields.structure[i].memory_read_only
+          != b->fields.structure[i].memory_read_only)
+         return false;
+      if (this->fields.structure[i].memory_write_only
+          != b->fields.structure[i].memory_write_only)
          return false;
-      if (this->fields.structure[i].image_write_only
-          != b->fields.structure[i].image_write_only)
+      if (this->fields.structure[i].memory_coherent
+          != b->fields.structure[i].memory_coherent)
          return false;
-      if (this->fields.structure[i].image_coherent
-          != b->fields.structure[i].image_coherent)
+      if (this->fields.structure[i].memory_volatile
+          != b->fields.structure[i].memory_volatile)
          return false;
-      if (this->fields.structure[i].image_volatile
-          != b->fields.structure[i].image_volatile)
+      if (this->fields.structure[i].memory_restrict
+          != b->fields.structure[i].memory_restrict)
          return false;
-      if (this->fields.structure[i].image_restrict
-          != b->fields.structure[i].image_restrict)
+      if (this->fields.structure[i].image_format
+          != b->fields.structure[i].image_format)
          return false;
       if (this->fields.structure[i].precision
           != b->fields.structure[i].precision)
          return false;
+      if (this->fields.structure[i].explicit_xfb_buffer
+          != b->fields.structure[i].explicit_xfb_buffer)
+         return false;
+      if (this->fields.structure[i].xfb_buffer
+          != b->fields.structure[i].xfb_buffer)
+         return false;
+      if (this->fields.structure[i].xfb_stride
+          != b->fields.structure[i].xfb_stride)
+         return false;
    }
 
    return true;
@@ -831,7 +1035,7 @@ glsl_type::get_record_instance(const glsl_struct_field *fields,
 {
    const glsl_type key(fields, num_fields, name);
 
-   mtx_lock(&glsl_type::mutex);
+   mtx_lock(&glsl_type::hash_mutex);
 
    if (record_types == NULL) {
       record_types = _mesa_hash_table_create(NULL, record_key_hash,
@@ -841,9 +1045,7 @@ glsl_type::get_record_instance(const glsl_struct_field *fields,
    const struct hash_entry *entry = _mesa_hash_table_search(record_types,
                                                             &key);
    if (entry == NULL) {
-      mtx_unlock(&glsl_type::mutex);
       const glsl_type *t = new glsl_type(fields, num_fields, name);
-      mtx_lock(&glsl_type::mutex);
 
       entry = _mesa_hash_table_insert(record_types, t, (void *) t);
    }
@@ -852,7 +1054,7 @@ glsl_type::get_record_instance(const glsl_struct_field *fields,
    assert(((glsl_type *) entry->data)->length == num_fields);
    assert(strcmp(((glsl_type *) entry->data)->name, name) == 0);
 
-   mtx_unlock(&glsl_type::mutex);
+   mtx_unlock(&glsl_type::hash_mutex);
 
    return (glsl_type *) entry->data;
 }
@@ -862,11 +1064,12 @@ const glsl_type *
 glsl_type::get_interface_instance(const glsl_struct_field *fields,
                                   unsigned num_fields,
                                   enum glsl_interface_packing packing,
+                                  bool row_major,
                                   const char *block_name)
 {
-   const glsl_type key(fields, num_fields, packing, block_name);
+   const glsl_type key(fields, num_fields, packing, row_major, block_name);
 
-   mtx_lock(&glsl_type::mutex);
+   mtx_lock(&glsl_type::hash_mutex);
 
    if (interface_types == NULL) {
       interface_types = _mesa_hash_table_create(NULL, record_key_hash,
@@ -876,10 +1079,8 @@ glsl_type::get_interface_instance(const glsl_struct_field *fields,
    const struct hash_entry *entry = _mesa_hash_table_search(interface_types,
                                                             &key);
    if (entry == NULL) {
-      mtx_unlock(&glsl_type::mutex);
       const glsl_type *t = new glsl_type(fields, num_fields,
-                                         packing, block_name);
-      mtx_lock(&glsl_type::mutex);
+                                         packing, row_major, block_name);
 
       entry = _mesa_hash_table_insert(interface_types, t, (void *) t);
    }
@@ -888,7 +1089,7 @@ glsl_type::get_interface_instance(const glsl_struct_field *fields,
    assert(((glsl_type *) entry->data)->length == num_fields);
    assert(strcmp(((glsl_type *) entry->data)->name, block_name) == 0);
 
-   mtx_unlock(&glsl_type::mutex);
+   mtx_unlock(&glsl_type::hash_mutex);
 
    return (glsl_type *) entry->data;
 }
@@ -898,7 +1099,7 @@ glsl_type::get_subroutine_instance(const char *subroutine_name)
 {
    const glsl_type key(subroutine_name);
 
-   mtx_lock(&glsl_type::mutex);
+   mtx_lock(&glsl_type::hash_mutex);
 
    if (subroutine_types == NULL) {
       subroutine_types = _mesa_hash_table_create(NULL, record_key_hash,
@@ -908,9 +1109,7 @@ glsl_type::get_subroutine_instance(const char *subroutine_name)
    const struct hash_entry *entry = _mesa_hash_table_search(subroutine_types,
                                                             &key);
    if (entry == NULL) {
-      mtx_unlock(&glsl_type::mutex);
       const glsl_type *t = new glsl_type(subroutine_name);
-      mtx_lock(&glsl_type::mutex);
 
       entry = _mesa_hash_table_insert(subroutine_types, t, (void *) t);
    }
@@ -918,12 +1117,66 @@ glsl_type::get_subroutine_instance(const char *subroutine_name)
    assert(((glsl_type *) entry->data)->base_type == GLSL_TYPE_SUBROUTINE);
    assert(strcmp(((glsl_type *) entry->data)->name, subroutine_name) == 0);
 
-   mtx_unlock(&glsl_type::mutex);
+   mtx_unlock(&glsl_type::hash_mutex);
 
    return (glsl_type *) entry->data;
 }
 
 
+static bool
+function_key_compare(const void *a, const void *b)
+{
+   const glsl_type *const key1 = (glsl_type *) a;
+   const glsl_type *const key2 = (glsl_type *) b;
+
+   if (key1->length != key2->length)
+      return false;
+
+   return memcmp(key1->fields.parameters, key2->fields.parameters,
+                 (key1->length + 1) * sizeof(*key1->fields.parameters)) == 0;
+}
+
+
+static uint32_t
+function_key_hash(const void *a)
+{
+   const glsl_type *const key = (glsl_type *) a;
+   return _mesa_hash_data(key->fields.parameters,
+                          (key->length + 1) * sizeof(*key->fields.parameters));
+}
+
+const glsl_type *
+glsl_type::get_function_instance(const glsl_type *return_type,
+                                 const glsl_function_param *params,
+                                 unsigned num_params)
+{
+   const glsl_type key(return_type, params, num_params);
+
+   mtx_lock(&glsl_type::hash_mutex);
+
+   if (function_types == NULL) {
+      function_types = _mesa_hash_table_create(NULL, function_key_hash,
+                                               function_key_compare);
+   }
+
+   struct hash_entry *entry = _mesa_hash_table_search(function_types, &key);
+   if (entry == NULL) {
+      const glsl_type *t = new glsl_type(return_type, params, num_params);
+
+      entry = _mesa_hash_table_insert(function_types, t, (void *) t);
+   }
+
+   const glsl_type *t = (const glsl_type *)entry->data;
+
+   assert(t->base_type == GLSL_TYPE_FUNCTION);
+   assert(t->length == num_params);
+
+   mtx_unlock(&glsl_type::hash_mutex);
+
+   return t;
+}
+
+
 const glsl_type *
 glsl_type::get_mul_type(const glsl_type *type_a, const glsl_type *type_b)
 {
@@ -1034,6 +1287,8 @@ glsl_type::component_slots() const
       return this->components();
 
    case GLSL_TYPE_DOUBLE:
+   case GLSL_TYPE_UINT64:
+   case GLSL_TYPE_INT64:
       return 2 * this->components();
 
    case GLSL_TYPE_STRUCT:
@@ -1049,11 +1304,14 @@ glsl_type::component_slots() const
    case GLSL_TYPE_ARRAY:
       return this->length * this->fields.array->component_slots();
 
+   case GLSL_TYPE_SAMPLER:
    case GLSL_TYPE_IMAGE:
-      return 1;
+      return 2;
+
    case GLSL_TYPE_SUBROUTINE:
-     return 1;
-   case GLSL_TYPE_SAMPLER:
+      return 1;
+
+   case GLSL_TYPE_FUNCTION:
    case GLSL_TYPE_ATOMIC_UINT:
    case GLSL_TYPE_VOID:
    case GLSL_TYPE_ERROR:
@@ -1114,6 +1372,8 @@ glsl_type::uniform_locations() const
    case GLSL_TYPE_INT:
    case GLSL_TYPE_FLOAT:
    case GLSL_TYPE_DOUBLE:
+   case GLSL_TYPE_UINT64:
+   case GLSL_TYPE_INT64:
    case GLSL_TYPE_BOOL:
    case GLSL_TYPE_SAMPLER:
    case GLSL_TYPE_IMAGE:
@@ -1132,6 +1392,40 @@ glsl_type::uniform_locations() const
    }
 }
 
+unsigned
+glsl_type::varying_count() const
+{
+   unsigned size = 0;
+
+   switch (this->base_type) {
+   case GLSL_TYPE_UINT:
+   case GLSL_TYPE_INT:
+   case GLSL_TYPE_FLOAT:
+   case GLSL_TYPE_DOUBLE:
+   case GLSL_TYPE_BOOL:
+   case GLSL_TYPE_UINT64:
+   case GLSL_TYPE_INT64:
+      return 1;
+
+   case GLSL_TYPE_STRUCT:
+   case GLSL_TYPE_INTERFACE:
+      for (unsigned i = 0; i < this->length; i++)
+         size += this->fields.structure[i].type->varying_count();
+      return size;
+   case GLSL_TYPE_ARRAY:
+      /* Don't count innermost array elements */
+      if (this->without_array()->is_record() ||
+          this->without_array()->is_interface() ||
+          this->fields.array->is_array())
+         return this->length * this->fields.array->varying_count();
+      else
+         return this->fields.array->varying_count();
+   default:
+      assert(!"unsupported varying type");
+      return 0;
+   }
+}
+
 bool
 glsl_type::can_implicitly_convert_to(const glsl_type *desired,
                                      _mesa_glsl_parse_state *state) const
@@ -1139,6 +1433,13 @@ glsl_type::can_implicitly_convert_to(const glsl_type *desired,
    if (this == desired)
       return true;
 
+   /* GLSL 1.10 and ESSL do not allow implicit conversions. If there is no
+    * state, we're doing intra-stage function linking where these checks have
+    * already been done.
+    */
+   if (state && (state->es_shader || !state->is_version(120, 0)))
+      return false;
+
    /* There is no conversion among matrix types. */
    if (this->matrix_columns > 1 || desired->matrix_columns > 1)
       return false;
@@ -1151,11 +1452,14 @@ glsl_type::can_implicitly_convert_to(const glsl_type *desired,
    if (desired->is_float() && this->is_integer())
       return true;
 
-   /* With GLSL 4.0 / ARB_gpu_shader5, int can be converted to uint.
-    * Note that state may be NULL here, when resolving function calls in the
-    * linker. By this time, all the state-dependent checks have already
-    * happened though, so allow anything that's allowed in any shader version. */
-   if ((!state || state->is_version(400, 0) || state->ARB_gpu_shader5_enable) &&
+   /* With GLSL 4.0, ARB_gpu_shader5, or MESA_shader_integer_functions, int
+    * can be converted to uint.  Note that state may be NULL here, when
+    * resolving function calls in the linker. By this time, all the
+    * state-dependent checks have already happened though, so allow anything
+    * that's allowed in any shader version.
+    */
+   if ((!state || state->is_version(400, 0) || state->ARB_gpu_shader5_enable ||
+        state->MESA_shader_integer_functions_enable) &&
          desired->base_type == GLSL_TYPE_UINT && this->base_type == GLSL_TYPE_INT)
       return true;
 
@@ -1177,7 +1481,7 @@ glsl_type::can_implicitly_convert_to(const glsl_type *desired,
 unsigned
 glsl_type::std140_base_alignment(bool row_major) const
 {
-   unsigned N = is_double() ? 8 : 4;
+   unsigned N = is_64bit() ? 8 : 4;
 
    /* (1) If the member is a scalar consuming <N> basic machine units, the
     *     base alignment is <N>.
@@ -1295,7 +1599,7 @@ glsl_type::std140_base_alignment(bool row_major) const
 unsigned
 glsl_type::std140_size(bool row_major) const
 {
-   unsigned N = is_double() ? 8 : 4;
+   unsigned N = is_64bit() ? 8 : 4;
 
    /* (1) If the member is a scalar consuming <N> basic machine units, the
     *     base alignment is <N>.
@@ -1432,7 +1736,7 @@ unsigned
 glsl_type::std430_base_alignment(bool row_major) const
 {
 
-   unsigned N = is_double() ? 8 : 4;
+   unsigned N = is_64bit() ? 8 : 4;
 
    /* (1) If the member is a scalar consuming <N> basic machine units, the
     *     base alignment is <N>.
@@ -1541,7 +1845,7 @@ glsl_type::std430_base_alignment(bool row_major) const
 unsigned
 glsl_type::std430_array_stride(bool row_major) const
 {
-   unsigned N = is_double() ? 8 : 4;
+   unsigned N = is_64bit() ? 8 : 4;
 
    /* Notice that the array stride of a vec3 is not 3 * N but 4 * N.
     * See OpenGL 4.30 spec, section 7.6.2.2 "Standard Uniform Block Layout"
@@ -1559,7 +1863,7 @@ glsl_type::std430_array_stride(bool row_major) const
 unsigned
 glsl_type::std430_size(bool row_major) const
 {
-   unsigned N = is_double() ? 8 : 4;
+   unsigned N = is_64bit() ? 8 : 4;
 
    /* OpenGL 4.30 spec, section 7.6.2.2 "Standard Uniform Block Layout":
     *
@@ -1640,7 +1944,7 @@ glsl_type::std430_size(bool row_major) const
 }
 
 unsigned
-glsl_type::count_attribute_slots(bool vertex_input_slots) const
+glsl_type::count_attribute_slots(bool is_vertex_input) const
 {
    /* From page 31 (page 37 of the PDF) of the GLSL 1.50 spec:
     *
@@ -1672,9 +1976,13 @@ glsl_type::count_attribute_slots(bool vertex_input_slots) const
    case GLSL_TYPE_INT:
    case GLSL_TYPE_FLOAT:
    case GLSL_TYPE_BOOL:
+   case GLSL_TYPE_SAMPLER:
+   case GLSL_TYPE_IMAGE:
       return this->matrix_columns;
    case GLSL_TYPE_DOUBLE:
-      if (this->vector_elements > 2 && !vertex_input_slots)
+   case GLSL_TYPE_UINT64:
+   case GLSL_TYPE_INT64:
+      if (this->vector_elements > 2 && !is_vertex_input)
          return this->matrix_columns * 2;
       else
          return this->matrix_columns;
@@ -1683,19 +1991,20 @@ glsl_type::count_attribute_slots(bool vertex_input_slots) const
       unsigned size = 0;
 
       for (unsigned i = 0; i < this->length; i++)
-         size += this->fields.structure[i].type->count_attribute_slots(vertex_input_slots);
+         size += this->fields.structure[i].type->count_attribute_slots(is_vertex_input);
 
       return size;
    }
 
    case GLSL_TYPE_ARRAY:
-      return this->length * this->fields.array->count_attribute_slots(vertex_input_slots);
+      return this->length * this->fields.array->count_attribute_slots(is_vertex_input);
 
-   case GLSL_TYPE_SAMPLER:
-   case GLSL_TYPE_IMAGE:
+   case GLSL_TYPE_SUBROUTINE:
+      return 1;
+
+   case GLSL_TYPE_FUNCTION:
    case GLSL_TYPE_ATOMIC_UINT:
    case GLSL_TYPE_VOID:
-   case GLSL_TYPE_SUBROUTINE:
    case GLSL_TYPE_ERROR:
       break;
    }
@@ -1719,6 +2028,7 @@ glsl_type::coordinate_components() const
    case GLSL_SAMPLER_DIM_RECT:
    case GLSL_SAMPLER_DIM_MS:
    case GLSL_SAMPLER_DIM_EXTERNAL:
+   case GLSL_SAMPLER_DIM_SUBPASS:
       size = 2;
       break;
    case GLSL_SAMPLER_DIM_3D:
@@ -1736,8 +2046,7 @@ glsl_type::coordinate_components() const
     * cubemap faces.
     */
    if (sampler_array &&
-       !(base_type == GLSL_TYPE_IMAGE &&
-         sampler_dimensionality == GLSL_SAMPLER_DIM_CUBE))
+       !(is_image() && sampler_dimensionality == GLSL_SAMPLER_DIM_CUBE))
       size += 1;
 
    return size;