glsl: A shader cannot redefine or overload built-in functions in GLSL ES 3.00
[mesa.git] / src / glsl / ast_to_hir.cpp
index 397a575501db2867b3017426849305f2049ead95..acb5c763c43c0cab7fb9aa0f7f24ed3bfe9f546f 100644 (file)
@@ -172,6 +172,7 @@ get_conversion_operation(const glsl_type *to, const glsl_type *from,
       switch (from->base_type) {
       case GLSL_TYPE_INT: return ir_unop_i2f;
       case GLSL_TYPE_UINT: return ir_unop_u2f;
+      case GLSL_TYPE_DOUBLE: return ir_unop_d2f;
       default: return (ir_expression_operation)0;
       }
 
@@ -183,6 +184,16 @@ get_conversion_operation(const glsl_type *to, const glsl_type *from,
          default: return (ir_expression_operation)0;
       }
 
+   case GLSL_TYPE_DOUBLE:
+      if (!state->has_double())
+         return (ir_expression_operation)0;
+      switch (from->base_type) {
+      case GLSL_TYPE_INT: return ir_unop_i2d;
+      case GLSL_TYPE_UINT: return ir_unop_u2d;
+      case GLSL_TYPE_FLOAT: return ir_unop_f2d;
+      default: return (ir_expression_operation)0;
+      }
+
    default: return (ir_expression_operation)0;
    }
 }
@@ -340,8 +351,10 @@ arithmetic_result_type(ir_rvalue * &value_a, ir_rvalue * &value_b,
     * type of both operands must be float.
     */
    assert(type_a->is_matrix() || type_b->is_matrix());
-   assert(type_a->base_type == GLSL_TYPE_FLOAT);
-   assert(type_b->base_type == GLSL_TYPE_FLOAT);
+   assert(type_a->base_type == GLSL_TYPE_FLOAT ||
+          type_a->base_type == GLSL_TYPE_DOUBLE);
+   assert(type_b->base_type == GLSL_TYPE_FLOAT ||
+          type_b->base_type == GLSL_TYPE_DOUBLE);
 
    /*   "* The operator is add (+), subtract (-), or divide (/), and the
     *      operands are matrices with the same number of rows and the same
@@ -912,7 +925,6 @@ get_lvalue_copy(exec_list *instructions, ir_rvalue *lvalue)
    var = new(ctx) ir_variable(lvalue->type, "_post_incdec_tmp",
                              ir_var_temporary);
    instructions->push_tail(var);
-   var->data.mode = ir_var_auto;
 
    instructions->push_tail(new(ctx) ir_assignment(new(ctx) ir_dereference_variable(var),
                                                  lvalue));
@@ -960,6 +972,7 @@ do_comparison(void *mem_ctx, int operation, ir_rvalue *op0, ir_rvalue *op1)
    case GLSL_TYPE_UINT:
    case GLSL_TYPE_INT:
    case GLSL_TYPE_BOOL:
+   case GLSL_TYPE_DOUBLE:
       return new(mem_ctx) ir_expression(operation, op0, op1);
 
    case GLSL_TYPE_ARRAY: {
@@ -1598,13 +1611,11 @@ ast_expression::do_hir(exec_list *instructions,
       }
 
       ir_constant *cond_val = op[0]->constant_expression_value();
-      ir_constant *then_val = op[1]->constant_expression_value();
-      ir_constant *else_val = op[2]->constant_expression_value();
 
       if (then_instructions.is_empty()
           && else_instructions.is_empty()
-          && (cond_val != NULL) && (then_val != NULL) && (else_val != NULL)) {
-         result = (cond_val->value.b[0]) ? then_val : else_val;
+          && cond_val != NULL) {
+         result = cond_val->value.b[0] ? op[1] : op[2];
       } else {
          ir_variable *const tmp =
             new(ctx) ir_variable(type, "conditional_tmp", ir_var_temporary);
@@ -1749,6 +1760,10 @@ ast_expression::do_hir(exec_list *instructions,
       result = new(ctx) ir_constant(bool(this->primary_expression.bool_constant));
       break;
 
+   case ast_double_constant:
+      result = new(ctx) ir_constant(this->primary_expression.double_constant);
+      break;
+
    case ast_sequence: {
       /* It should not be possible to generate a sequence in the AST without
        * any expressions in it.
@@ -2360,11 +2375,11 @@ apply_image_qualifier_to_variable(const struct ast_type_qualifier *qual,
                           "global variables");
       }
 
-      var->data.image.read_only |= qual->flags.q.read_only;
-      var->data.image.write_only |= qual->flags.q.write_only;
-      var->data.image.coherent |= qual->flags.q.coherent;
-      var->data.image._volatile |= qual->flags.q._volatile;
-      var->data.image.restrict_flag |= qual->flags.q.restrict_flag;
+      var->data.image_read_only |= qual->flags.q.read_only;
+      var->data.image_write_only |= qual->flags.q.write_only;
+      var->data.image_coherent |= qual->flags.q.coherent;
+      var->data.image_volatile |= qual->flags.q._volatile;
+      var->data.image_restrict |= qual->flags.q.restrict_flag;
       var->data.read_only = true;
 
       if (qual->flags.q.explicit_image_format) {
@@ -2378,7 +2393,7 @@ apply_image_qualifier_to_variable(const struct ast_type_qualifier *qual,
                              "base data type of the image");
          }
 
-         var->data.image.format = qual->image_format;
+         var->data.image_format = qual->image_format;
       } else {
          if (var->data.mode == ir_var_uniform && !qual->flags.q.write_only) {
             _mesa_glsl_error(loc, state, "uniforms not qualified with "
@@ -2386,7 +2401,7 @@ apply_image_qualifier_to_variable(const struct ast_type_qualifier *qual,
                              "qualifier");
          }
 
-         var->data.image.format = GL_NONE;
+         var->data.image_format = GL_NONE;
       }
    }
 }
@@ -2499,6 +2514,7 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual,
    /* If there is no qualifier that changes the mode of the variable, leave
     * the setting alone.
     */
+   assert(var->data.mode != ir_var_temporary);
    if (qual->flags.q.in && qual->flags.q.out)
       var->data.mode = ir_var_function_inout;
    else if (qual->flags.q.in)
@@ -2562,6 +2578,8 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual,
          _mesa_glsl_error(loc, state,
                           "varying variables may not be of type struct");
          break;
+      case GLSL_TYPE_DOUBLE:
+         break;
       default:
          _mesa_glsl_error(loc, state, "illegal type for a varying variable");
          break;
@@ -3202,6 +3220,41 @@ validate_identifier(const char *identifier, YYLTYPE loc,
    }
 }
 
+static bool
+precision_qualifier_allowed(const glsl_type *type)
+{
+   /* Precision qualifiers apply to floating point, integer and sampler
+    * types.
+    *
+    * Section 4.5.2 (Precision Qualifiers) of the GLSL 1.30 spec says:
+    *    "Any floating point or any integer declaration can have the type
+    *    preceded by one of these precision qualifiers [...] Literal
+    *    constants do not have precision qualifiers. Neither do Boolean
+    *    variables.
+    *
+    * Section 4.5 (Precision and Precision Qualifiers) of the GLSL 1.30
+    * spec also says:
+    *
+    *     "Precision qualifiers are added for code portability with OpenGL
+    *     ES, not for functionality. They have the same syntax as in OpenGL
+    *     ES."
+    *
+    * Section 8 (Built-In Functions) of the GLSL ES 1.00 spec says:
+    *
+    *     "uniform lowp sampler2D sampler;
+    *     highp vec2 coord;
+    *     ...
+    *     lowp vec4 col = texture2D (sampler, coord);
+    *                                            // texture2D returns lowp"
+    *
+    * From this, we infer that GLSL 1.30 (and later) should allow precision
+    * qualifiers on sampler types just like float and integer types.
+    */
+   return type->is_float()
+       || type->is_integer()
+       || type->is_record()
+       || type->is_sampler();
+}
 
 ir_rvalue *
 ast_declarator_list::hir(exec_list *instructions,
@@ -3568,6 +3621,51 @@ ast_declarator_list::hir(exec_list *instructions,
 
             handle_geometry_shader_input_decl(state, loc, var);
          }
+      } else if (var->data.mode == ir_var_shader_out) {
+         const glsl_type *check_type = var->type->without_array();
+
+         /* From section 4.3.6 (Output variables) of the GLSL 4.40 spec:
+          *
+          *     It is a compile-time error to declare a vertex, tessellation
+          *     evaluation, tessellation control, or geometry shader output
+          *     that contains any of the following:
+          *
+          *     * A Boolean type (bool, bvec2 ...)
+          *     * An opaque type
+          */
+         if (check_type->is_boolean() || check_type->contains_opaque())
+            _mesa_glsl_error(&loc, state,
+                             "%s shader output cannot have type %s",
+                             _mesa_shader_stage_to_string(state->stage),
+                             check_type->name);
+
+         /* From section 4.3.6 (Output variables) of the GLSL 4.40 spec:
+          *
+          *     It is a compile-time error to declare a fragment shader output
+          *     that contains any of the following:
+          *
+          *     * A Boolean type (bool, bvec2 ...)
+          *     * A double-precision scalar or vector (double, dvec2 ...)
+          *     * An opaque type
+          *     * Any matrix type
+          *     * A structure
+          */
+         if (state->stage == MESA_SHADER_FRAGMENT) {
+            if (check_type->is_record() || check_type->is_matrix())
+               _mesa_glsl_error(&loc, state,
+                                "fragment shader output "
+                                "cannot have struct or array type");
+            switch (check_type->base_type) {
+            case GLSL_TYPE_UINT:
+            case GLSL_TYPE_INT:
+            case GLSL_TYPE_FLOAT:
+               break;
+            default:
+               _mesa_glsl_error(&loc, state,
+                                "fragment shader output cannot have "
+                                "type %s", check_type->name);
+            }
+         }
       }
 
       /* Integer fragment inputs must be qualified with 'flat'.  In GLSL ES,
@@ -3612,6 +3710,15 @@ ast_declarator_list::hir(exec_list *instructions,
                           var_type);
       }
 
+      /* Double fragment inputs must be qualified with 'flat'. */
+      if (var->type->contains_double() &&
+          var->data.interpolation != INTERP_QUALIFIER_FLAT &&
+          state->stage == MESA_SHADER_FRAGMENT &&
+          var->data.mode == ir_var_shader_in) {
+         _mesa_glsl_error(&loc, state, "if a fragment input is (or contains) "
+                          "a double, then it must be qualified with 'flat'",
+                          var_type);
+      }
 
       /* Interpolation qualifiers cannot be applied to 'centroid' and
        * 'centroid varying'.
@@ -3689,41 +3796,13 @@ ast_declarator_list::hir(exec_list *instructions,
       }
 
 
-      /* Precision qualifiers apply to floating point, integer and sampler
-       * types.
-       *
-       * Section 4.5.2 (Precision Qualifiers) of the GLSL 1.30 spec says:
-       *    "Any floating point or any integer declaration can have the type
-       *    preceded by one of these precision qualifiers [...] Literal
-       *    constants do not have precision qualifiers. Neither do Boolean
-       *    variables.
-       *
-       * Section 4.5 (Precision and Precision Qualifiers) of the GLSL 1.30
-       * spec also says:
-       *
-       *     "Precision qualifiers are added for code portability with OpenGL
-       *     ES, not for functionality. They have the same syntax as in OpenGL
-       *     ES."
-       *
-       * Section 8 (Built-In Functions) of the GLSL ES 1.00 spec says:
-       *
-       *     "uniform lowp sampler2D sampler;
-       *     highp vec2 coord;
-       *     ...
-       *     lowp vec4 col = texture2D (sampler, coord);
-       *                                            // texture2D returns lowp"
-       *
-       * From this, we infer that GLSL 1.30 (and later) should allow precision
-       * qualifiers on sampler types just like float and integer types.
+      /* If a precision qualifier is allowed on a type, it is allowed on
+       * an array of that type.
        */
-      if (this->type->qualifier.precision != ast_precision_none
-          && !var->type->is_float()
-          && !var->type->is_integer()
-          && !var->type->is_record()
-          && !var->type->is_sampler()
-          && !(var->type->is_array()
-               && (var->type->fields.array->is_float()
-                   || var->type->fields.array->is_integer()))) {
+      if (!(this->type->qualifier.precision == ast_precision_none
+          || precision_qualifier_allowed(var->type)
+          || (var->type->is_array()
+             && precision_qualifier_allowed(var->type->fields.array)))) {
 
          _mesa_glsl_error(&loc, state,
                           "precision qualifiers apply only to floating point"
@@ -3760,7 +3839,7 @@ ast_declarator_list::hir(exec_list *instructions,
              earlier->data.how_declared == ir_var_declared_in_block) {
             _mesa_glsl_error(&loc, state,
                              "`%s' has already been redeclared using "
-                             "gl_PerVertex", var->name);
+                             "gl_PerVertex", earlier->name);
          }
          earlier->data.how_declared = ir_var_declared_normally;
       }
@@ -4110,12 +4189,48 @@ ast_function::hir(exec_list *instructions,
                        name);
    }
 
+   /* Create an ir_function if one doesn't already exist. */
+   f = state->symbols->get_function(name);
+   if (f == NULL) {
+      f = new(ctx) ir_function(name);
+      if (!state->symbols->add_function(f)) {
+         /* This function name shadows a non-function use of the same name. */
+         YYLTYPE loc = this->get_location();
+
+         _mesa_glsl_error(&loc, state, "function name `%s' conflicts with "
+                          "non-function", name);
+         return NULL;
+      }
+
+      emit_function(state, f);
+   }
+
+   /* From GLSL ES 3.0 spec, chapter 6.1 "Function Definitions", page 71:
+    *
+    * "A shader cannot redefine or overload built-in functions."
+    *
+    * While in GLSL ES 1.0 specification, chapter 8 "Built-in Functions":
+    *
+    * "User code can overload the built-in functions but cannot redefine
+    * them."
+    */
+   if (state->es_shader && state->language_version >= 300) {
+      /* Local shader has no exact candidates; check the built-ins. */
+      _mesa_glsl_initialize_builtin_functions();
+      if (_mesa_glsl_find_builtin_function_by_name(state, name)) {
+         YYLTYPE loc = this->get_location();
+         _mesa_glsl_error(& loc, state,
+                          "A shader cannot redefine or overload built-in "
+                          "function `%s' in GLSL ES 3.00", name);
+         return NULL;
+      }
+   }
+
    /* Verify that this function's signature either doesn't match a previously
     * seen signature for a function with the same name, or, if a match is found,
     * that the previously seen signature does not have an associated definition.
     */
-   f = state->symbols->get_function(name);
-   if (f != NULL && (state->es_shader || f->has_user_signature())) {
+   if (state->es_shader || f->has_user_signature()) {
       sig = f->exact_matching_signature(state, &hir_parameters);
       if (sig != NULL) {
          const char *badvar = sig->qualifiers_match(&hir_parameters);
@@ -4146,18 +4261,6 @@ ast_function::hir(exec_list *instructions,
             }
          }
       }
-   } else {
-      f = new(ctx) ir_function(name);
-      if (!state->symbols->add_function(f)) {
-         /* This function name shadows a non-function use of the same name. */
-         YYLTYPE loc = this->get_location();
-
-         _mesa_glsl_error(&loc, state, "function name `%s' conflicts with "
-                          "non-function", name);
-         return NULL;
-      }
-
-      emit_function(state, f);
    }
 
    /* Verify the return type of main() */
@@ -4363,7 +4466,7 @@ ast_jump_statement::hir(exec_list *instructions,
           * loop.
           */
          if (state->loop_nesting_ast != NULL &&
-             mode == ast_continue) {
+             mode == ast_continue && !state->switch_state.is_switch_innermost) {
             if (state->loop_nesting_ast->rest_expression) {
                state->loop_nesting_ast->rest_expression->hir(instructions,
                                                              state);
@@ -4375,19 +4478,27 @@ ast_jump_statement::hir(exec_list *instructions,
          }
 
          if (state->switch_state.is_switch_innermost &&
+             mode == ast_continue) {
+            /* Set 'continue_inside' to true. */
+            ir_rvalue *const true_val = new (ctx) ir_constant(true);
+            ir_dereference_variable *deref_continue_inside_var =
+               new(ctx) ir_dereference_variable(state->switch_state.continue_inside);
+            instructions->push_tail(new(ctx) ir_assignment(deref_continue_inside_var,
+                                                           true_val));
+
+            /* Break out from the switch, continue for the loop will
+             * be called right after switch. */
+            ir_loop_jump *const jump =
+               new(ctx) ir_loop_jump(ir_loop_jump::jump_break);
+            instructions->push_tail(jump);
+
+         } else if (state->switch_state.is_switch_innermost &&
              mode == ast_break) {
-            /* Force break out of switch by setting is_break switch state.
-             */
-            ir_variable *const is_break_var = state->switch_state.is_break_var;
-            ir_dereference_variable *const deref_is_break_var =
-               new(ctx) ir_dereference_variable(is_break_var);
-            ir_constant *const true_val = new(ctx) ir_constant(true);
-            ir_assignment *const set_break_var =
-               new(ctx) ir_assignment(deref_is_break_var, true_val);
-           
-            instructions->push_tail(set_break_var);
-         }
-         else {
+            /* Force break out of switch by inserting a break. */
+            ir_loop_jump *const jump =
+               new(ctx) ir_loop_jump(ir_loop_jump::jump_break);
+            instructions->push_tail(jump);
+         } else {
             ir_loop_jump *const jump =
                new(ctx) ir_loop_jump((mode == ast_break)
                   ? ir_loop_jump::jump_break
@@ -4499,19 +4610,19 @@ ast_switch_statement::hir(exec_list *instructions,
    instructions->push_tail(new(ctx) ir_assignment(deref_is_fallthru_var,
                                                   is_fallthru_val));
 
-   /* Initalize is_break state to false.
+   /* Initialize continue_inside state to false.
     */
-   ir_rvalue *const is_break_val = new (ctx) ir_constant(false);
-   state->switch_state.is_break_var =
+   state->switch_state.continue_inside =
       new(ctx) ir_variable(glsl_type::bool_type,
-                           "switch_is_break_tmp",
+                           "continue_inside_tmp",
                            ir_var_temporary);
-   instructions->push_tail(state->switch_state.is_break_var);
+   instructions->push_tail(state->switch_state.continue_inside);
 
-   ir_dereference_variable *deref_is_break_var =
-      new(ctx) ir_dereference_variable(state->switch_state.is_break_var);
-   instructions->push_tail(new(ctx) ir_assignment(deref_is_break_var,
-                                                  is_break_val));
+   ir_rvalue *const false_val = new (ctx) ir_constant(false);
+   ir_dereference_variable *deref_continue_inside_var =
+      new(ctx) ir_dereference_variable(state->switch_state.continue_inside);
+   instructions->push_tail(new(ctx) ir_assignment(deref_continue_inside_var,
+                                                  false_val));
 
    state->switch_state.run_default =
       new(ctx) ir_variable(glsl_type::bool_type,
@@ -4519,13 +4630,42 @@ ast_switch_statement::hir(exec_list *instructions,
                              ir_var_temporary);
    instructions->push_tail(state->switch_state.run_default);
 
+   /* Loop around the switch is used for flow control. */
+   ir_loop * loop = new(ctx) ir_loop();
+   instructions->push_tail(loop);
+
    /* Cache test expression.
     */
-   test_to_hir(instructions, state);
+   test_to_hir(&loop->body_instructions, state);
 
    /* Emit code for body of switch stmt.
     */
-   body->hir(instructions, state);
+   body->hir(&loop->body_instructions, state);
+
+   /* Insert a break at the end to exit loop. */
+   ir_loop_jump *jump = new(ctx) ir_loop_jump(ir_loop_jump::jump_break);
+   loop->body_instructions.push_tail(jump);
+
+   /* If we are inside loop, check if continue got called inside switch. */
+   if (state->loop_nesting_ast != NULL) {
+      ir_dereference_variable *deref_continue_inside =
+         new(ctx) ir_dereference_variable(state->switch_state.continue_inside);
+      ir_if *irif = new(ctx) ir_if(deref_continue_inside);
+      ir_loop_jump *jump = new(ctx) ir_loop_jump(ir_loop_jump::jump_continue);
+
+      if (state->loop_nesting_ast != NULL) {
+         if (state->loop_nesting_ast->rest_expression) {
+            state->loop_nesting_ast->rest_expression->hir(&irif->then_instructions,
+                                                          state);
+         }
+         if (state->loop_nesting_ast->mode ==
+             ast_iteration_statement::ast_do_while) {
+            state->loop_nesting_ast->condition_to_hir(&irif->then_instructions, state);
+         }
+      }
+      irif->then_instructions.push_tail(jump);
+      instructions->push_tail(irif);
+   }
 
    hash_table_dtor(state->switch_state.labels_ht);
 
@@ -4649,18 +4789,6 @@ ast_case_statement::hir(exec_list *instructions,
 {
    labels->hir(instructions, state);
 
-   /* Conditionally set fallthru state based on break state. */
-   ir_constant *const false_val = new(state) ir_constant(false);
-   ir_dereference_variable *const deref_is_fallthru_var =
-      new(state) ir_dereference_variable(state->switch_state.is_fallthru_var);
-   ir_dereference_variable *const deref_is_break_var =
-      new(state) ir_dereference_variable(state->switch_state.is_break_var);
-   ir_assignment *const reset_fallthru_on_break =
-      new(state) ir_assignment(deref_is_fallthru_var,
-                               false_val,
-                               deref_is_break_var);
-   instructions->push_tail(reset_fallthru_on_break);
-
    /* Guard case statements depending on fallthru state. */
    ir_dereference_variable *const deref_fallthru_guard =
       new(state) ir_dereference_variable(state->switch_state.is_fallthru_var);
@@ -5021,7 +5149,7 @@ ast_type_specifier::hir(exec_list *instructions,
           */
          ir_variable *const junk =
             new(state) ir_variable(type, "#default precision",
-                                   ir_var_temporary);
+                                   ir_var_auto);
 
          state->symbols->add_variable(junk);
       }
@@ -5072,7 +5200,7 @@ ast_process_structure_or_interface_block(exec_list *instructions,
                                          YYLTYPE &loc,
                                          glsl_struct_field **fields_ret,
                                          bool is_interface,
-                                         bool block_row_major,
+                                         enum glsl_matrix_layout matrix_layout,
                                          bool allow_reserved_names,
                                          ir_variable_mode var_mode)
 {
@@ -5168,6 +5296,13 @@ ast_process_structure_or_interface_block(exec_list *instructions,
                              "members");
          }
 
+         if (qual->flags.q.constant) {
+            YYLTYPE loc = decl_list->get_location();
+            _mesa_glsl_error(&loc, state,
+                             "const storage qualifier cannot be applied "
+                             "to struct or interface block members");
+         }
+
          field_type = process_array_type(&loc, decl_type,
                                          decl->array_specifier, state);
          fields[i].type = field_type;
@@ -5203,12 +5338,29 @@ ast_process_structure_or_interface_block(exec_list *instructions,
                              "in uniform blocks or structures.");
          }
 
-         if (field_type->without_array()->is_matrix()) {
-            fields[i].row_major = block_row_major;
+         /* Propogate row- / column-major information down the fields of the
+          * structure or interface block.  Structures need this data because
+          * the structure may contain a structure that contains ... a matrix
+          * that need the proper layout.
+          */
+         if (field_type->without_array()->is_matrix()
+             || field_type->without_array()->is_record()) {
+            /* If no layout is specified for the field, inherit the layout
+             * from the block.
+             */
+            fields[i].matrix_layout = matrix_layout;
+
             if (qual->flags.q.row_major)
-               fields[i].row_major = true;
+               fields[i].matrix_layout = GLSL_MATRIX_LAYOUT_ROW_MAJOR;
             else if (qual->flags.q.column_major)
-               fields[i].row_major = false;
+               fields[i].matrix_layout = GLSL_MATRIX_LAYOUT_COLUMN_MAJOR;
+
+            /* If we're processing an interface block, the matrix layout must
+             * be decided by this point.
+             */
+            assert(!is_interface
+                   || fields[i].matrix_layout == GLSL_MATRIX_LAYOUT_ROW_MAJOR
+                   || fields[i].matrix_layout == GLSL_MATRIX_LAYOUT_COLUMN_MAJOR);
          }
 
          i++;
@@ -5263,7 +5415,7 @@ ast_struct_specifier::hir(exec_list *instructions,
                                                loc,
                                                &fields,
                                                false,
-                                               false,
+                                               GLSL_MATRIX_LAYOUT_INHERITED,
                                                false /* allow_reserved_names */,
                                                ir_var_auto);
 
@@ -5331,6 +5483,14 @@ ast_interface_block::hir(exec_list *instructions,
 {
    YYLTYPE loc = this->get_location();
 
+   /* Interface blocks must be declared at global scope */
+   if (state->current_function != NULL) {
+      _mesa_glsl_error(&loc, state,
+                       "Interface block `%s' must be declared "
+                       "at global scope",
+                       this->block_name);
+   }
+
    /* The ast_interface_block has a list of ast_declarator_lists.  We
     * need to turn those into ir_variables with an association
     * with this uniform block.
@@ -5363,8 +5523,13 @@ ast_interface_block::hir(exec_list *instructions,
       assert(!"interface block layout qualifier not found!");
    }
 
+   enum glsl_matrix_layout matrix_layout = GLSL_MATRIX_LAYOUT_INHERITED;
+   if (this->layout.flags.q.row_major)
+      matrix_layout = GLSL_MATRIX_LAYOUT_ROW_MAJOR;
+   else if (this->layout.flags.q.column_major)
+      matrix_layout = GLSL_MATRIX_LAYOUT_COLUMN_MAJOR;
+
    bool redeclaring_per_vertex = strcmp(this->block_name, "gl_PerVertex") == 0;
-   bool block_row_major = this->layout.flags.q.row_major;
    exec_list declared_variables;
    glsl_struct_field *fields;
 
@@ -5380,15 +5545,29 @@ ast_interface_block::hir(exec_list *instructions,
                                                loc,
                                                &fields,
                                                true,
-                                               block_row_major,
+                                               matrix_layout,
                                                redeclaring_per_vertex,
                                                var_mode);
 
    state->struct_specifier_depth--;
 
-   if (!redeclaring_per_vertex)
+   if (!redeclaring_per_vertex) {
       validate_identifier(this->block_name, loc, state);
 
+      /* From section 4.3.9 ("Interface Blocks") of the GLSL 4.50 spec:
+       *
+       *     "Block names have no other use within a shader beyond interface
+       *     matching; it is a compile-time error to use a block name at global
+       *     scope for anything other than as a block name."
+       */
+      ir_variable *var = state->symbols->get_variable(this->block_name);
+      if (var && !var->type->is_interface()) {
+         _mesa_glsl_error(&loc, state, "Block name `%s' is "
+                          "already used in the scope.",
+                          this->block_name);
+      }
+   }
+
    const glsl_type *earlier_per_vertex = NULL;
    if (redeclaring_per_vertex) {
       /* Find the previous declaration of gl_PerVertex.  If we're redeclaring
@@ -5430,7 +5609,7 @@ ast_interface_block::hir(exec_list *instructions,
          }
          if (this->instance_name != NULL) {
             _mesa_glsl_error(&loc, state,
-                             "gl_PerVertex input may not be redeclared with "
+                             "gl_PerVertex output may not be redeclared with "
                              "an instance name");
          }
          break;
@@ -5588,6 +5767,9 @@ ast_interface_block::hir(exec_list *instructions,
                                       var_mode);
       }
 
+      var->data.matrix_layout = matrix_layout == GLSL_MATRIX_LAYOUT_INHERITED
+         ? GLSL_MATRIX_LAYOUT_COLUMN_MAJOR : matrix_layout;
+
       if (state->stage == MESA_SHADER_GEOMETRY && var_mode == ir_var_shader_in)
          handle_geometry_shader_input_decl(state, loc, var);
 
@@ -5628,6 +5810,13 @@ ast_interface_block::hir(exec_list *instructions,
          var->data.sample = fields[i].sample;
          var->init_interface_type(block_type);
 
+         if (fields[i].matrix_layout == GLSL_MATRIX_LAYOUT_INHERITED) {
+            var->data.matrix_layout = matrix_layout == GLSL_MATRIX_LAYOUT_INHERITED
+               ? GLSL_MATRIX_LAYOUT_COLUMN_MAJOR : matrix_layout;
+         } else {
+            var->data.matrix_layout = fields[i].matrix_layout;
+         }
+
          if (fields[i].stream != -1 &&
              ((unsigned)fields[i].stream) != this->layout.stream) {
             _mesa_glsl_error(&loc, state,
@@ -5639,17 +5828,21 @@ ast_interface_block::hir(exec_list *instructions,
 
          var->data.stream = this->layout.stream;
 
+         /* Examine var name here since var may get deleted in the next call */
+         bool var_is_gl_id = is_gl_identifier(var->name);
+
          if (redeclaring_per_vertex) {
             ir_variable *earlier =
                get_variable_being_redeclared(var, loc, state,
                                              true /* allow_all_redeclarations */);
-            if (!is_gl_identifier(var->name) || earlier == NULL) {
+            if (!var_is_gl_id || earlier == NULL) {
                _mesa_glsl_error(&loc, state,
                                 "redeclaration of gl_PerVertex can only "
                                 "include built-in variables");
             } else if (earlier->data.how_declared == ir_var_declared_normally) {
                _mesa_glsl_error(&loc, state,
-                                "`%s' has already been redeclared", var->name);
+                                "`%s' has already been redeclared",
+                                earlier->name);
             } else {
                earlier->data.how_declared = ir_var_declared_in_block;
                earlier->reinit_interface_type(block_type);
@@ -5837,7 +6030,7 @@ ast_cs_input_layout::hir(exec_list *instructions,
     * declare it earlier).
     */
    ir_variable *var = new(state->symbols)
-      ir_variable(glsl_type::ivec3_type, "gl_WorkGroupSize", ir_var_auto);
+      ir_variable(glsl_type::uvec3_type, "gl_WorkGroupSize", ir_var_auto);
    var->data.how_declared = ir_var_declared_implicitly;
    var->data.read_only = true;
    instructions->push_tail(var);
@@ -5845,10 +6038,10 @@ ast_cs_input_layout::hir(exec_list *instructions,
    ir_constant_data data;
    memset(&data, 0, sizeof(data));
    for (int i = 0; i < 3; i++)
-      data.i[i] = this->local_size[i];
-   var->constant_value = new(var) ir_constant(glsl_type::ivec3_type, &data);
+      data.u[i] = this->local_size[i];
+   var->constant_value = new(var) ir_constant(glsl_type::uvec3_type, &data);
    var->constant_initializer =
-      new(var) ir_constant(glsl_type::ivec3_type, &data);
+      new(var) ir_constant(glsl_type::uvec3_type, &data);
    var->data.has_initializer = true;
 
    return NULL;