i965: Add chipset limits for Haswell GT1/GT2.
[mesa.git] / src / glsl / ast_to_hir.cpp
index a60711d8055fbf7dfa52f20b5e8aa8431c18260f..49093d88f8e6f8a215397978364eccb2dad0940a 100644 (file)
 #include "glsl_parser_extras.h"
 #include "ast.h"
 #include "glsl_types.h"
+#include "program/hash_table.h"
 #include "ir.h"
 
+static void
+detect_conflicting_assignments(struct _mesa_glsl_parse_state *state,
+                              exec_list *instructions);
+
 void
 _mesa_ast_to_hir(exec_list *instructions, struct _mesa_glsl_parse_state *state)
 {
    _mesa_glsl_initialize_variables(instructions, state);
 
-   state->symbols->language_version = state->language_version;
+   state->symbols->separate_function_namespace = state->language_version == 110;
 
    state->current_function = NULL;
 
@@ -86,6 +91,7 @@ _mesa_ast_to_hir(exec_list *instructions, struct _mesa_glsl_parse_state *state)
       ast->hir(instructions, state);
 
    detect_recursion_unlinked(state, instructions);
+   detect_conflicting_assignments(state, instructions);
 
    state->toplevel_ir = NULL;
 }
@@ -115,7 +121,7 @@ apply_implicit_conversion(const glsl_type *to, ir_rvalue * &from,
    /* This conversion was added in GLSL 1.20.  If the compilation mode is
     * GLSL 1.10, the conversion is skipped.
     */
-   if (state->language_version < 120)
+   if (!state->is_version(120, 0))
       return false;
 
    /* From page 27 (page 33 of the PDF) of the GLSL 1.50 spec:
@@ -384,8 +390,7 @@ bit_logic_result_type(const struct glsl_type *type_a,
                       ast_operators op,
                       struct _mesa_glsl_parse_state *state, YYLTYPE *loc)
 {
-    if (state->language_version < 130) {
-       _mesa_glsl_error(loc, state, "bit operations require GLSL 1.30");
+    if (!state->check_bitwise_operations_allowed(loc)) {
        return glsl_type::error_type;
     }
 
@@ -440,10 +445,7 @@ modulus_result_type(const struct glsl_type *type_a,
                    const struct glsl_type *type_b,
                    struct _mesa_glsl_parse_state *state, YYLTYPE *loc)
 {
-   if (state->language_version < 130) {
-      _mesa_glsl_error(loc, state,
-                       "operator '%%' is reserved in %s",
-                       state->version_string);
+   if (!state->check_version(130, 300, loc, "operator '%%' is reserved")) {
       return glsl_type::error_type;
    }
 
@@ -547,8 +549,7 @@ shift_result_type(const struct glsl_type *type_a,
                   ast_operators op,
                   struct _mesa_glsl_parse_state *state, YYLTYPE *loc)
 {
-   if (state->language_version < 130) {
-      _mesa_glsl_error(loc, state, "bit operations require GLSL 1.30");
+   if (!state->check_bitwise_operations_allowed(loc)) {
       return glsl_type::error_type;
    }
 
@@ -664,29 +665,41 @@ mark_whole_array_access(ir_rvalue *access)
 
 ir_rvalue *
 do_assignment(exec_list *instructions, struct _mesa_glsl_parse_state *state,
+             const char *non_lvalue_description,
              ir_rvalue *lhs, ir_rvalue *rhs, bool is_initializer,
              YYLTYPE lhs_loc)
 {
    void *ctx = state;
    bool error_emitted = (lhs->type->is_error() || rhs->type->is_error());
 
+   ir_variable *lhs_var = lhs->variable_referenced();
+   if (lhs_var)
+      lhs_var->assigned = true;
+
    if (!error_emitted) {
-      if (lhs->variable_referenced() != NULL
-          && lhs->variable_referenced()->read_only) {
+      if (non_lvalue_description != NULL) {
+         _mesa_glsl_error(&lhs_loc, state,
+                          "assignment to %s",
+                         non_lvalue_description);
+        error_emitted = true;
+      } else if (lhs->variable_referenced() != NULL
+                && lhs->variable_referenced()->read_only) {
          _mesa_glsl_error(&lhs_loc, state,
                           "assignment to read-only variable '%s'",
                           lhs->variable_referenced()->name);
          error_emitted = true;
 
-      } else if (state->language_version <= 110 && lhs->type->is_array()) {
+      } else if (lhs->type->is_array() &&
+                 !state->check_version(120, 300, &lhs_loc,
+                                       "whole array assignment forbidden")) {
         /* From page 32 (page 38 of the PDF) of the GLSL 1.10 spec:
          *
          *    "Other binary or unary expressions, non-dereferenced
          *     arrays, function names, swizzles with repeated fields,
          *     and constants cannot be l-values."
+          *
+          * The restriction on arrays is lifted in GLSL 1.20 and GLSL ES 3.00.
          */
-        _mesa_glsl_error(&lhs_loc, state, "whole array assignment is not "
-                         "allowed in GLSL 1.10 or GLSL ES 1.00.");
         error_emitted = true;
       } else if (!lhs->is_lvalue()) {
         _mesa_glsl_error(& lhs_loc, state, "non-lvalue in assignment");
@@ -744,13 +757,11 @@ do_assignment(exec_list *instructions, struct _mesa_glsl_parse_state *state,
                                           ir_var_temporary);
    ir_dereference_variable *deref_var = new(ctx) ir_dereference_variable(var);
    instructions->push_tail(var);
-   instructions->push_tail(new(ctx) ir_assignment(deref_var,
-                                                 rhs,
-                                                 NULL));
+   instructions->push_tail(new(ctx) ir_assignment(deref_var, rhs));
    deref_var = new(ctx) ir_dereference_variable(var);
 
    if (!error_emitted)
-      instructions->push_tail(new(ctx) ir_assignment(lhs, deref_var, NULL));
+      instructions->push_tail(new(ctx) ir_assignment(lhs, deref_var));
 
    return new(ctx) ir_dereference_variable(var);
 }
@@ -767,12 +778,7 @@ get_lvalue_copy(exec_list *instructions, ir_rvalue *lvalue)
    var->mode = ir_var_auto;
 
    instructions->push_tail(new(ctx) ir_assignment(new(ctx) ir_dereference_variable(var),
-                                                 lvalue, NULL));
-
-   /* Once we've created this temporary, mark it read only so it's no
-    * longer considered an lvalue.
-    */
-   var->read_only = true;
+                                                 lvalue));
 
    return new(ctx) ir_dereference_variable(var);
 }
@@ -851,14 +857,11 @@ do_comparison(void *mem_ctx, int operation, ir_rvalue *op0, ir_rvalue *op1)
    case GLSL_TYPE_ERROR:
    case GLSL_TYPE_VOID:
    case GLSL_TYPE_SAMPLER:
+   case GLSL_TYPE_INTERFACE:
       /* I assume a comparison of a struct containing a sampler just
        * ignores the sampler present in the type.
        */
       break;
-
-   default:
-      assert(!"Should not get here.");
-      break;
    }
 
    if (cmp == NULL)
@@ -935,6 +938,28 @@ check_builtin_array_max_size(const char *name, unsigned size,
    return false;
 }
 
+/**
+ * Create the constant 1, of a which is appropriate for incrementing and
+ * decrementing values of the given GLSL type.  For example, if type is vec4,
+ * this creates a constant value of 1.0 having type float.
+ *
+ * If the given type is invalid for increment and decrement operators, return
+ * a floating point 1--the error will be detected later.
+ */
+static ir_rvalue *
+constant_one_for_inc_dec(void *ctx, const glsl_type *type)
+{
+   switch (type->base_type) {
+   case GLSL_TYPE_UINT:
+      return new(ctx) ir_constant((unsigned) 1);
+   case GLSL_TYPE_INT:
+      return new(ctx) ir_constant(1);
+   default:
+   case GLSL_TYPE_FLOAT:
+      return new(ctx) ir_constant(1.0f);
+   }
+}
+
 ir_rvalue *
 ast_expression::hir(exec_list *instructions,
                    struct _mesa_glsl_parse_state *state)
@@ -1008,7 +1033,9 @@ ast_expression::hir(exec_list *instructions,
       op[0] = this->subexpressions[0]->hir(instructions, state);
       op[1] = this->subexpressions[1]->hir(instructions, state);
 
-      result = do_assignment(instructions, state, op[0], op[1], false,
+      result = do_assignment(instructions, state,
+                            this->subexpressions[0]->non_lvalue_description,
+                            op[0], op[1], false,
                             this->subexpressions[0]->get_location());
       error_emitted = result->type->is_error();
       break;
@@ -1066,9 +1093,7 @@ ast_expression::hir(exec_list *instructions,
 
    case ast_lshift:
    case ast_rshift:
-       if (state->language_version < 130) {
-          _mesa_glsl_error(&loc, state, "operator %s requires GLSL 1.30",
-              operator_string(this->oper));
+       if (!state->check_bitwise_operations_allowed(&loc)) {
           error_emitted = true;
        }
 
@@ -1122,10 +1147,9 @@ ast_expression::hir(exec_list *instructions,
         _mesa_glsl_error(& loc, state, "operands of `%s' must have the same "
                          "type", (this->oper == ast_equal) ? "==" : "!=");
         error_emitted = true;
-      } else if ((state->language_version <= 110)
-                && (op[0]->type->is_array() || op[1]->type->is_array())) {
-        _mesa_glsl_error(& loc, state, "array comparisons forbidden in "
-                         "GLSL 1.10");
+      } else if ((op[0]->type->is_array() || op[1]->type->is_array()) &&
+                 !state->check_version(120, 300, &loc,
+                                       "array comparisons forbidden")) {
         error_emitted = true;
       }
 
@@ -1152,8 +1176,7 @@ ast_expression::hir(exec_list *instructions,
    case ast_bit_not:
       op[0] = this->subexpressions[0]->hir(instructions, state);
 
-      if (state->language_version < 130) {
-        _mesa_glsl_error(&loc, state, "bit-wise operations require GLSL 1.30");
+      if (!state->check_bitwise_operations_allowed(&loc)) {
         error_emitted = true;
       }
 
@@ -1162,7 +1185,7 @@ ast_expression::hir(exec_list *instructions,
         error_emitted = true;
       }
 
-      type = op[0]->type;
+      type = error_emitted ? glsl_type::error_type : op[0]->type;
       result = new(ctx) ir_expression(ir_unop_bit_not, type, op[0], NULL);
       break;
 
@@ -1173,15 +1196,9 @@ ast_expression::hir(exec_list *instructions,
       op[1] = get_scalar_boolean_operand(&rhs_instructions, state, this, 1,
                                         "RHS", &error_emitted);
 
-      ir_constant *op0_const = op[0]->constant_expression_value();
-      if (op0_const) {
-        if (op0_const->value.b[0]) {
-           instructions->append_list(&rhs_instructions);
-           result = op[1];
-        } else {
-           result = op0_const;
-        }
-        type = glsl_type::bool_type;
+      if (rhs_instructions.is_empty()) {
+        result = new(ctx) ir_expression(ir_binop_logic_and, op[0], op[1]);
+        type = result->type;
       } else {
         ir_variable *const tmp = new(ctx) ir_variable(glsl_type::bool_type,
                                                       "and_tmp",
@@ -1194,12 +1211,12 @@ ast_expression::hir(exec_list *instructions,
         stmt->then_instructions.append_list(&rhs_instructions);
         ir_dereference *const then_deref = new(ctx) ir_dereference_variable(tmp);
         ir_assignment *const then_assign =
-           new(ctx) ir_assignment(then_deref, op[1], NULL);
+           new(ctx) ir_assignment(then_deref, op[1]);
         stmt->then_instructions.push_tail(then_assign);
 
         ir_dereference *const else_deref = new(ctx) ir_dereference_variable(tmp);
         ir_assignment *const else_assign =
-           new(ctx) ir_assignment(else_deref, new(ctx) ir_constant(false), NULL);
+           new(ctx) ir_assignment(else_deref, new(ctx) ir_constant(false));
         stmt->else_instructions.push_tail(else_assign);
 
         result = new(ctx) ir_dereference_variable(tmp);
@@ -1215,14 +1232,9 @@ ast_expression::hir(exec_list *instructions,
       op[1] = get_scalar_boolean_operand(&rhs_instructions, state, this, 1,
                                         "RHS", &error_emitted);
 
-      ir_constant *op0_const = op[0]->constant_expression_value();
-      if (op0_const) {
-        if (op0_const->value.b[0]) {
-           result = op0_const;
-        } else {
-           result = op[1];
-        }
-        type = glsl_type::bool_type;
+      if (rhs_instructions.is_empty()) {
+        result = new(ctx) ir_expression(ir_binop_logic_or, op[0], op[1]);
+        type = result->type;
       } else {
         ir_variable *const tmp = new(ctx) ir_variable(glsl_type::bool_type,
                                                       "or_tmp",
@@ -1234,13 +1246,13 @@ ast_expression::hir(exec_list *instructions,
 
         ir_dereference *const then_deref = new(ctx) ir_dereference_variable(tmp);
         ir_assignment *const then_assign =
-           new(ctx) ir_assignment(then_deref, new(ctx) ir_constant(true), NULL);
+           new(ctx) ir_assignment(then_deref, new(ctx) ir_constant(true));
         stmt->then_instructions.push_tail(then_assign);
 
         stmt->else_instructions.append_list(&rhs_instructions);
         ir_dereference *const else_deref = new(ctx) ir_dereference_variable(tmp);
         ir_assignment *const else_assign =
-           new(ctx) ir_assignment(else_deref, op[1], NULL);
+           new(ctx) ir_assignment(else_deref, op[1]);
         stmt->else_instructions.push_tail(else_assign);
 
         result = new(ctx) ir_dereference_variable(tmp);
@@ -1288,6 +1300,7 @@ ast_expression::hir(exec_list *instructions,
                                                   op[0], op[1]);
 
       result = do_assignment(instructions, state,
+                            this->subexpressions[0]->non_lvalue_description,
                             op[0]->clone(ctx, NULL), temp_rhs, false,
                             this->subexpressions[0]->get_location());
       error_emitted = (op[0]->type->is_error());
@@ -1313,6 +1326,7 @@ ast_expression::hir(exec_list *instructions,
                                        op[0], op[1]);
 
       result = do_assignment(instructions, state,
+                            this->subexpressions[0]->non_lvalue_description,
                             op[0]->clone(ctx, NULL), temp_rhs, false,
                             this->subexpressions[0]->get_location());
       error_emitted = type->is_error();
@@ -1327,8 +1341,9 @@ ast_expression::hir(exec_list *instructions,
                                &loc);
       ir_rvalue *temp_rhs = new(ctx) ir_expression(operations[this->oper],
                                                    type, op[0], op[1]);
-      result = do_assignment(instructions, state, op[0]->clone(ctx, NULL),
-                             temp_rhs, false,
+      result = do_assignment(instructions, state,
+                            this->subexpressions[0]->non_lvalue_description,
+                            op[0]->clone(ctx, NULL), temp_rhs, false,
                              this->subexpressions[0]->get_location());
       error_emitted = op[0]->type->is_error() || op[1]->type->is_error();
       break;
@@ -1343,8 +1358,9 @@ ast_expression::hir(exec_list *instructions,
                                    state, &loc);
       ir_rvalue *temp_rhs = new(ctx) ir_expression(operations[this->oper],
                                                    type, op[0], op[1]);
-      result = do_assignment(instructions, state, op[0]->clone(ctx, NULL),
-                             temp_rhs, false,
+      result = do_assignment(instructions, state,
+                            this->subexpressions[0]->non_lvalue_description,
+                            op[0]->clone(ctx, NULL), temp_rhs, false,
                              this->subexpressions[0]->get_location());
       error_emitted = op[0]->type->is_error() || op[1]->type->is_error();
       break;
@@ -1398,9 +1414,10 @@ ast_expression::hir(exec_list *instructions,
        *    "The second and third expressions must be the same type, but can
        *    be of any type other than an array."
        */
-      if ((state->language_version <= 110) && type->is_array()) {
-        _mesa_glsl_error(& loc, state, "Second and third operands of ?: "
-                         "operator must not be arrays.");
+      if (type->is_array() &&
+          !state->check_version(120, 300, &loc,
+                                "Second and third operands of ?: operator "
+                                "cannot be arrays")) {
         error_emitted = true;
       }
 
@@ -1424,14 +1441,14 @@ ast_expression::hir(exec_list *instructions,
         ir_dereference *const then_deref =
            new(ctx) ir_dereference_variable(tmp);
         ir_assignment *const then_assign =
-           new(ctx) ir_assignment(then_deref, op[1], NULL);
+           new(ctx) ir_assignment(then_deref, op[1]);
         stmt->then_instructions.push_tail(then_assign);
 
         else_instructions.move_nodes_to(& stmt->else_instructions);
         ir_dereference *const else_deref =
            new(ctx) ir_dereference_variable(tmp);
         ir_assignment *const else_assign =
-           new(ctx) ir_assignment(else_deref, op[2], NULL);
+           new(ctx) ir_assignment(else_deref, op[2]);
         stmt->else_instructions.push_tail(else_assign);
 
         result = new(ctx) ir_dereference_variable(tmp);
@@ -1441,11 +1458,11 @@ ast_expression::hir(exec_list *instructions,
 
    case ast_pre_inc:
    case ast_pre_dec: {
+      this->non_lvalue_description = (this->oper == ast_pre_inc)
+        ? "pre-increment operation" : "pre-decrement operation";
+
       op[0] = this->subexpressions[0]->hir(instructions, state);
-      if (op[0]->type->base_type == GLSL_TYPE_FLOAT)
-        op[1] = new(ctx) ir_constant(1.0f);
-      else
-        op[1] = new(ctx) ir_constant(1);
+      op[1] = constant_one_for_inc_dec(ctx, op[0]->type);
 
       type = arithmetic_result_type(op[0], op[1], false, state, & loc);
 
@@ -1454,6 +1471,7 @@ ast_expression::hir(exec_list *instructions,
                                        op[0], op[1]);
 
       result = do_assignment(instructions, state,
+                            this->subexpressions[0]->non_lvalue_description,
                             op[0]->clone(ctx, NULL), temp_rhs, false,
                             this->subexpressions[0]->get_location());
       error_emitted = op[0]->type->is_error();
@@ -1462,11 +1480,10 @@ ast_expression::hir(exec_list *instructions,
 
    case ast_post_inc:
    case ast_post_dec: {
+      this->non_lvalue_description = (this->oper == ast_post_inc)
+        ? "post-increment operation" : "post-decrement operation";
       op[0] = this->subexpressions[0]->hir(instructions, state);
-      if (op[0]->type->base_type == GLSL_TYPE_FLOAT)
-        op[1] = new(ctx) ir_constant(1.0f);
-      else
-        op[1] = new(ctx) ir_constant(1);
+      op[1] = constant_one_for_inc_dec(ctx, op[0]->type);
 
       error_emitted = op[0]->type->is_error() || op[1]->type->is_error();
 
@@ -1482,6 +1499,7 @@ ast_expression::hir(exec_list *instructions,
       result = get_lvalue_copy(instructions, op[0]->clone(ctx, NULL));
 
       (void)do_assignment(instructions, state,
+                         this->subexpressions[0]->non_lvalue_description,
                          op[0]->clone(ctx, NULL), temp_rhs, false,
                          this->subexpressions[0]->get_location());
 
@@ -1604,6 +1622,15 @@ ast_expression::hir(exec_list *instructions,
         }
       } else if (array->type->array_size() == 0) {
         _mesa_glsl_error(&loc, state, "unsized array index must be constant");
+      } else if (array->type->is_array()
+                 && array->type->fields.array->is_interface()) {
+         /* Page 46 in section 4.3.7 of the OpenGL ES 3.00 spec says:
+          *
+          *     "All indexes used to index a uniform block array must be
+          *     constant integral expressions."
+          */
+         _mesa_glsl_error(&loc, state,
+                          "uniform block array index must be constant");
       } else {
         if (array->type->is_array()) {
            /* whole_variable_referenced can return NULL if the array is a
@@ -1633,15 +1660,18 @@ ast_expression::hir(exec_list *instructions,
           array->type->element_type()->is_sampler() &&
           const_index == NULL) {
 
-        if (state->language_version == 100) {
-           _mesa_glsl_warning(&loc, state,
-                              "sampler arrays indexed with non-constant "
-                              "expressions is optional in GLSL ES 1.00");
-        } else if (state->language_version < 130) {
-           _mesa_glsl_warning(&loc, state,
-                              "sampler arrays indexed with non-constant "
-                              "expressions is forbidden in GLSL 1.30 and "
-                              "later");
+         if (!state->is_version(130, 100)) {
+            if (state->es_shader) {
+               _mesa_glsl_warning(&loc, state,
+                                  "sampler arrays indexed with non-constant "
+                                  "expressions is optional in %s",
+                                  state->get_version_string());
+            } else {
+               _mesa_glsl_warning(&loc, state,
+                                  "sampler arrays indexed with non-constant "
+                                  "expressions will be forbidden in GLSL 1.30 and "
+                                  "later");
+            }
         } else {
            _mesa_glsl_error(&loc, state,
                             "sampler arrays indexed with non-constant "
@@ -1672,14 +1702,14 @@ ast_expression::hir(exec_list *instructions,
       ir_variable *var = 
         state->symbols->get_variable(this->primary_expression.identifier);
 
-      result = new(ctx) ir_dereference_variable(var);
-
       if (var != NULL) {
         var->used = true;
+        result = new(ctx) ir_dereference_variable(var);
       } else {
         _mesa_glsl_error(& loc, state, "`%s' undeclared",
                          this->primary_expression.identifier);
 
+        result = ir_rvalue::error_value(ctx);
         error_emitted = true;
       }
       break;
@@ -1886,11 +1916,61 @@ ast_type_specifier::glsl_type(const char **name,
 }
 
 
+/**
+ * Determine whether a toplevel variable declaration declares a varying.  This
+ * function operates by examining the variable's mode and the shader target,
+ * so it correctly identifies linkage variables regardless of whether they are
+ * declared using the deprecated "varying" syntax or the new "in/out" syntax.
+ *
+ * Passing a non-toplevel variable declaration (e.g. a function parameter) to
+ * this function will produce undefined results.
+ */
+static bool
+is_varying_var(ir_variable *var, _mesa_glsl_parser_targets target)
+{
+   switch (target) {
+   case vertex_shader:
+      return var->mode == ir_var_shader_out;
+   case fragment_shader:
+      return var->mode == ir_var_shader_in;
+   default:
+      return var->mode == ir_var_shader_out || var->mode == ir_var_shader_in;
+   }
+}
+
+
+/**
+ * Matrix layout qualifiers are only allowed on certain types
+ */
+static void
+validate_matrix_layout_for_type(struct _mesa_glsl_parse_state *state,
+                               YYLTYPE *loc,
+                               const glsl_type *type)
+{
+   if (!type->is_matrix() && !type->is_record()) {
+      _mesa_glsl_error(loc, state,
+                       "uniform block layout qualifiers row_major and "
+                       "column_major can only be applied to matrix and "
+                       "structure types");
+   } else if (type->is_record()) {
+      /* We allow 'layout(row_major)' on structure types because it's the only
+       * way to get row-major layouts on matrices contained in structures.
+       */
+      _mesa_glsl_warning(loc, state,
+                         "uniform block layout qualifiers row_major and "
+                         "column_major applied to structure types is not "
+                         "strictly conformant and my be rejected by other "
+                         "compilers");
+   }
+}
+
 static void
 apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual,
                                 ir_variable *var,
                                 struct _mesa_glsl_parse_state *state,
-                                YYLTYPE *loc)
+                                YYLTYPE *loc,
+                                bool ubo_qualifiers_valid,
+                                 bool is_parameter)
 {
    if (qual->flags.q.invariant) {
       if (var->used) {
@@ -1919,53 +1999,84 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual,
                       _mesa_glsl_shader_target_name(state->target));
    }
 
-   /* From page 25 (page 31 of the PDF) of the GLSL 1.10 spec:
-    *
-    *     "The varying qualifier can be used only with the data types
-    *     float, vec2, vec3, vec4, mat2, mat3, and mat4, or arrays of
-    *     these."
-    */
-   if (qual->flags.q.varying) {
-      const glsl_type *non_array_type;
-
-      if (var->type && var->type->is_array())
-        non_array_type = var->type->fields.array;
-      else
-        non_array_type = var->type;
-
-      if (non_array_type && non_array_type->base_type != GLSL_TYPE_FLOAT) {
-        var->type = glsl_type::error_type;
-        _mesa_glsl_error(loc, state,
-                         "varying variables must be of base type float");
-      }
-   }
-
    /* If there is no qualifier that changes the mode of the variable, leave
     * the setting alone.
     */
    if (qual->flags.q.in && qual->flags.q.out)
-      var->mode = ir_var_inout;
-   else if (qual->flags.q.attribute || qual->flags.q.in
+      var->mode = ir_var_function_inout;
+   else if (qual->flags.q.in)
+      var->mode = is_parameter ? ir_var_function_in : ir_var_shader_in;
+   else if (qual->flags.q.attribute
            || (qual->flags.q.varying && (state->target == fragment_shader)))
-      var->mode = ir_var_in;
-   else if (qual->flags.q.out
-           || (qual->flags.q.varying && (state->target == vertex_shader)))
-      var->mode = ir_var_out;
+      var->mode = ir_var_shader_in;
+   else if (qual->flags.q.out)
+      var->mode = is_parameter ? ir_var_function_out : ir_var_shader_out;
+   else if (qual->flags.q.varying && (state->target == vertex_shader))
+      var->mode = ir_var_shader_out;
    else if (qual->flags.q.uniform)
       var->mode = ir_var_uniform;
 
+   if (!is_parameter && is_varying_var(var, state->target)) {
+      /* This variable is being used to link data between shader stages (in
+       * pre-glsl-1.30 parlance, it's a "varying").  Check that it has a type
+       * that is allowed for such purposes.
+       *
+       * From page 25 (page 31 of the PDF) of the GLSL 1.10 spec:
+       *
+       *     "The varying qualifier can be used only with the data types
+       *     float, vec2, vec3, vec4, mat2, mat3, and mat4, or arrays of
+       *     these."
+       *
+       * This was relaxed in GLSL version 1.30 and GLSL ES version 3.00.  From
+       * page 31 (page 37 of the PDF) of the GLSL 1.30 spec:
+       *
+       *     "Fragment inputs can only be signed and unsigned integers and
+       *     integer vectors, float, floating-point vectors, matrices, or
+       *     arrays of these. Structures cannot be input.
+       *
+       * Similar text exists in the section on vertex shader outputs.
+       *
+       * Similar text exists in the GLSL ES 3.00 spec, except that the GLSL ES
+       * 3.00 spec allows structs as well.  Varying structs are also allowed
+       * in GLSL 1.50.
+       */
+      switch (var->type->get_scalar_type()->base_type) {
+      case GLSL_TYPE_FLOAT:
+         /* Ok in all GLSL versions */
+         break;
+      case GLSL_TYPE_UINT:
+      case GLSL_TYPE_INT:
+         if (state->is_version(130, 300))
+            break;
+         _mesa_glsl_error(loc, state,
+                          "varying variables must be of base type float in %s",
+                          state->get_version_string());
+         break;
+      case GLSL_TYPE_STRUCT:
+         if (state->is_version(150, 300))
+            break;
+         _mesa_glsl_error(loc, state,
+                          "varying variables may not be of type struct");
+         break;
+      default:
+         _mesa_glsl_error(loc, state, "illegal type for a varying variable");
+         break;
+      }
+   }
+
    if (state->all_invariant && (state->current_function == NULL)) {
       switch (state->target) {
       case vertex_shader:
-        if (var->mode == ir_var_out)
+        if (var->mode == ir_var_shader_out)
            var->invariant = true;
         break;
       case geometry_shader:
-        if ((var->mode == ir_var_in) || (var->mode == ir_var_out))
+        if ((var->mode == ir_var_shader_in)
+             || (var->mode == ir_var_shader_out))
            var->invariant = true;
         break;
       case fragment_shader:
-        if (var->mode == ir_var_in)
+        if (var->mode == ir_var_shader_in)
            var->invariant = true;
         break;
       }
@@ -1980,6 +2091,15 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual,
    else
       var->interpolation = INTERP_QUALIFIER_NONE;
 
+   if (var->interpolation != INTERP_QUALIFIER_NONE &&
+       !(state->target == vertex_shader && var->mode == ir_var_shader_out) &&
+       !(state->target == fragment_shader && var->mode == ir_var_shader_in)) {
+      _mesa_glsl_error(loc, state,
+                      "interpolation qualifier `%s' can only be applied to "
+                      "vertex shader outputs and fragment shader inputs.",
+                      var->interpolation_string());
+   }
+
    var->pixel_center_integer = qual->flags.q.pixel_center_integer;
    var->origin_upper_left = qual->flags.q.origin_upper_left;
    if ((qual->flags.q.origin_upper_left || qual->flags.q.pixel_center_integer)
@@ -2006,7 +2126,7 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual,
        */
       switch (state->target) {
       case vertex_shader:
-        if (!global_scope || (var->mode != ir_var_in)) {
+        if (!global_scope || (var->mode != ir_var_shader_in)) {
            fail = true;
            string = "input";
         }
@@ -2019,7 +2139,7 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual,
         break;
 
       case fragment_shader:
-        if (!global_scope || (var->mode != ir_var_out)) {
+        if (!global_scope || (var->mode != ir_var_shader_out)) {
            fail = true;
            string = "output";
         }
@@ -2049,14 +2169,36 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual,
         } else {
            var->location = qual->location;
         }
+
+        if (qual->flags.q.explicit_index) {
+            /* From the GLSL 4.30 specification, section 4.4.2 (Output
+             * Layout Qualifiers):
+             *
+             * "It is also a compile-time error if a fragment shader
+             *  sets a layout index to less than 0 or greater than 1."
+             *
+             * Older specifications don't mandate a behavior; we take
+             * this as a clarification and always generate the error.
+             */
+            if (qual->index < 0 || qual->index > 1) {
+               _mesa_glsl_error(loc, state,
+                                "explicit index may only be 0 or 1\n");
+            } else {
+               var->explicit_index = true;
+               var->index = qual->index;
+            }
+        }
       }
+   } else if (qual->flags.q.explicit_index) {
+        _mesa_glsl_error(loc, state,
+                         "explicit index requires explicit location\n");
    }
 
    /* Does the declaration use the 'layout' keyword?
     */
    const bool uses_layout = qual->flags.q.pixel_center_integer
       || qual->flags.q.origin_upper_left
-      || qual->flags.q.explicit_location;
+      || qual->flags.q.explicit_location; /* no need for index since it relies on location */
 
    /* Does the declaration use the deprecated 'attribute' or 'varying'
     * keywords?
@@ -2074,6 +2216,7 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual,
     * The following extension do not allow the deprecated keywords:
     *
     *    GL_AMD_conservative_depth
+    *    GL_ARB_conservative_depth
     *    GL_ARB_gpu_shader5
     *    GL_ARB_separate_shader_objects
     *    GL_ARB_tesselation_shader
@@ -2106,9 +2249,11 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual,
       + qual->flags.q.depth_less
       + qual->flags.q.depth_unchanged;
    if (depth_layout_count > 0
-       && !state->AMD_conservative_depth_enable) {
+       && !state->AMD_conservative_depth_enable
+       && !state->ARB_conservative_depth_enable) {
        _mesa_glsl_error(loc, state,
-                        "extension GL_AMD_conservative_depth must be enabled "
+                        "extension GL_AMD_conservative_depth or "
+                        "GL_ARB_conservative_depth must be enabled "
                        "to use depth layout qualifiers");
    } else if (depth_layout_count > 0
               && strcmp(var->name, "gl_FragDepth") != 0) {
@@ -2131,6 +2276,25 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual,
        var->depth_layout = ir_depth_layout_unchanged;
    else
        var->depth_layout = ir_depth_layout_none;
+
+   if (qual->flags.q.std140 ||
+       qual->flags.q.packed ||
+       qual->flags.q.shared) {
+      _mesa_glsl_error(loc, state,
+                       "uniform block layout qualifiers std140, packed, and "
+                      "shared can only be applied to uniform blocks, not "
+                      "members");
+   }
+
+   if (qual->flags.q.row_major || qual->flags.q.column_major) {
+      if (!ubo_qualifiers_valid) {
+        _mesa_glsl_error(loc, state,
+                         "uniform block layout qualifiers row_major and "
+                         "column_major can only be applied to uniform block "
+                         "members");
+      } else
+        validate_matrix_layout_for_type(state, loc, var->type);
+   }
 }
 
 /**
@@ -2209,7 +2373,7 @@ get_variable_being_redeclared(ir_variable *var, ast_declaration *decl,
        *    * gl_Color
        *    * gl_SecondaryColor
        */
-   } else if (state->language_version >= 130
+   } else if (state->is_version(130, 0)
              && (strcmp(var->name, "gl_FrontColor") == 0
                  || strcmp(var->name, "gl_BackColor") == 0
                  || strcmp(var->name, "gl_FrontSecondaryColor") == 0
@@ -2221,7 +2385,8 @@ get_variable_being_redeclared(ir_variable *var, ast_declaration *decl,
       earlier->interpolation = var->interpolation;
 
       /* Layout qualifiers for gl_FragDepth. */
-   } else if (state->AMD_conservative_depth_enable
+   } else if ((state->AMD_conservative_depth_enable ||
+               state->ARB_conservative_depth_enable)
              && strcmp(var->name, "gl_FragDepth") == 0
              && earlier->type == var->type
              && earlier->mode == var->mode) {
@@ -2275,10 +2440,9 @@ process_initializer(ir_variable *var, ast_declaration *decl,
     *    directly by an application via API commands, or indirectly by
     *    OpenGL."
     */
-   if ((state->language_version <= 110)
-       && (var->mode == ir_var_uniform)) {
-      _mesa_glsl_error(& initializer_loc, state,
-                      "cannot initialize uniforms in GLSL 1.10");
+   if (var->mode == ir_var_uniform) {
+      state->check_version(120, 0, &initializer_loc,
+                           "cannot initialize uniforms");
    }
 
    if (var->type->is_sampler()) {
@@ -2286,7 +2450,7 @@ process_initializer(ir_variable *var, ast_declaration *decl,
                       "cannot initialize samplers");
    }
 
-   if ((var->mode == ir_var_in) && (state->current_function == NULL)) {
+   if ((var->mode == ir_var_shader_in) && (state->current_function == NULL)) {
       _mesa_glsl_error(& initializer_loc, state,
                       "cannot initialize %s shader input / %s",
                       _mesa_glsl_shader_target_name(state->target),
@@ -2345,12 +2509,16 @@ process_initializer(ir_variable *var, ast_declaration *decl,
       const glsl_type *initializer_type;
       if (!type->qualifier.flags.q.uniform) {
         result = do_assignment(initializer_instructions, state,
+                               NULL,
                                lhs, rhs, true,
                                type->get_location());
         initializer_type = result->type;
       } else
         initializer_type = rhs->type;
 
+      var->constant_initializer = rhs->constant_expression_value();
+      var->has_initializer = true;
+
       /* If the declared variable is an unsized array, it must inherrit
        * its full type from the initializer.  A declaration such as
        *
@@ -2421,12 +2589,12 @@ ast_declarator_list::hir(exec_list *instructions,
                             "Undeclared variable `%s' cannot be marked "
                             "invariant\n", decl->identifier);
         } else if ((state->target == vertex_shader)
-              && (earlier->mode != ir_var_out)) {
+              && (earlier->mode != ir_var_shader_out)) {
            _mesa_glsl_error(& loc, state,
                             "`%s' cannot be marked invariant, vertex shader "
                             "outputs only\n", decl->identifier);
         } else if ((state->target == fragment_shader)
-              && (earlier->mode != ir_var_in)) {
+              && (earlier->mode != ir_var_shader_in)) {
            _mesa_glsl_error(& loc, state,
                             "`%s' cannot be marked invariant, fragment shader "
                             "inputs only\n", decl->identifier);
@@ -2455,14 +2623,32 @@ ast_declarator_list::hir(exec_list *instructions,
 
    decl_type = this->type->specifier->glsl_type(& type_name, state);
    if (this->declarations.is_empty()) {
-      if (decl_type != NULL) {
-        /* Warn if this empty declaration is not for declaring a structure.
-         */
-        if (this->type->specifier->structure == NULL) {
+      /* If there is no structure involved in the program text, there are two
+       * possible scenarios:
+       *
+       * - The program text contained something like 'vec4;'.  This is an
+       *   empty declaration.  It is valid but weird.  Emit a warning.
+       *
+       * - The program text contained something like 'S;' and 'S' is not the
+       *   name of a known structure type.  This is both invalid and weird.
+       *   Emit an error.
+       *
+       * Note that if decl_type is NULL and there is a structure involved,
+       * there must have been some sort of error with the structure.  In this
+       * case we assume that an error was already generated on this line of
+       * code for the structure.  There is no need to generate an additional,
+       * confusing error.
+       */
+      assert(this->type->specifier->structure == NULL || decl_type != NULL
+            || state->error);
+      if (this->type->specifier->structure == NULL) {
+        if (decl_type != NULL) {
            _mesa_glsl_warning(&loc, state, "empty declaration");
+        } else {
+           _mesa_glsl_error(&loc, state,
+                            "invalid type `%s' in empty declaration",
+                            type_name);
         }
-      } else {
-           _mesa_glsl_error(& loc, state, "incomplete declaration");
       }
    }
 
@@ -2506,41 +2692,38 @@ ast_declarator_list::hir(exec_list *instructions,
        *
        *     Local variables can only use the qualifier const."
        *
-       * This is relaxed in GLSL 1.30.  It is also relaxed by any extension
-       * that adds the 'layout' keyword.
+       * This is relaxed in GLSL 1.30 and GLSL ES 3.00.  It is also relaxed by
+       * any extension that adds the 'layout' keyword.
        */
-      if ((state->language_version < 130)
+      if (!state->is_version(130, 300)
          && !state->ARB_explicit_attrib_location_enable
          && !state->ARB_fragment_coord_conventions_enable) {
         if (this->type->qualifier.flags.q.out) {
            _mesa_glsl_error(& loc, state,
                             "`out' qualifier in declaration of `%s' "
                             "only valid for function parameters in %s.",
-                            decl->identifier, state->version_string);
+                            decl->identifier, state->get_version_string());
         }
         if (this->type->qualifier.flags.q.in) {
            _mesa_glsl_error(& loc, state,
                             "`in' qualifier in declaration of `%s' "
                             "only valid for function parameters in %s.",
-                            decl->identifier, state->version_string);
+                            decl->identifier, state->get_version_string());
         }
         /* FINISHME: Test for other invalid qualifiers. */
       }
 
       apply_type_qualifier_to_variable(& this->type->qualifier, var, state,
-                                      & loc);
+                                      & loc, this->ubo_qualifiers_valid, false);
 
       if (this->type->qualifier.flags.q.invariant) {
-        if ((state->target == vertex_shader) && !(var->mode == ir_var_out ||
-                                                  var->mode == ir_var_inout)) {
-           /* FINISHME: Note that this doesn't work for invariant on
-            * a function signature outval
-            */
+        if ((state->target == vertex_shader) &&
+             var->mode != ir_var_shader_out) {
            _mesa_glsl_error(& loc, state,
                             "`%s' cannot be marked invariant, vertex shader "
                             "outputs only\n", var->name);
         } else if ((state->target == fragment_shader) &&
-                   !(var->mode == ir_var_in || var->mode == ir_var_inout)) {
+                   var->mode != ir_var_shader_in) {
            /* FINISHME: Note that this doesn't work for invariant on
             * a function signature inval
             */
@@ -2577,7 +2760,7 @@ ast_declarator_list::hir(exec_list *instructions,
                             "global scope%s",
                             mode, var->name, extra);
         }
-      } else if (var->mode == ir_var_in) {
+      } else if (var->mode == ir_var_shader_in) {
          var->read_only = true;
 
         if (state->target == vertex_shader) {
@@ -2601,6 +2784,13 @@ ast_declarator_list::hir(exec_list *instructions,
             *    "The attribute qualifier can be used only with float,
             *    floating-point vectors, and matrices. Attribute variables
             *    cannot be declared as arrays or structures."
+             *
+             * From page 33 (page 39 of the PDF) of the GLSL ES 3.00 spec:
+             *
+             *    "Vertex shader inputs can only be float, floating-point
+             *    vectors, matrices, signed and unsigned integers and integer
+             *    vectors. Vertex shader inputs cannot be arrays or
+             *    structures."
             */
            const glsl_type *check_type = var->type->is_array()
               ? var->type->fields.array : var->type;
@@ -2610,7 +2800,7 @@ ast_declarator_list::hir(exec_list *instructions,
               break;
            case GLSL_TYPE_UINT:
            case GLSL_TYPE_INT:
-              if (state->language_version > 120)
+              if (state->is_version(120, 300))
                  break;
               /* FALLTHROUGH */
            default:
@@ -2622,11 +2812,10 @@ ast_declarator_list::hir(exec_list *instructions,
               error_emitted = true;
            }
 
-           if (!error_emitted && (state->language_version <= 130)
-               && var->type->is_array()) {
-              _mesa_glsl_error(& loc, state,
-                               "vertex shader input / attribute cannot have "
-                               "array type");
+           if (!error_emitted && var->type->is_array() &&
+                !state->check_version(140, 0, &loc,
+                                      "vertex shader input / attribute "
+                                      "cannot have array type")) {
               error_emitted = true;
            }
         }
@@ -2638,12 +2827,20 @@ ast_declarator_list::hir(exec_list *instructions,
        *    "If a vertex output is a signed or unsigned integer or integer
        *    vector, then it must be qualified with the interpolation qualifier
        *    flat."
+       *
+       * From section 4.3.4 of the GLSL 3.00 ES spec:
+       *    "Fragment shader inputs that are signed or unsigned integers or
+       *    integer vectors must be qualified with the interpolation qualifier
+       *    flat."
+       *
+       * Since vertex outputs and fragment inputs must have matching
+       * qualifiers, these two requirements are equivalent.
        */
-      if (state->language_version >= 130
+      if (state->is_version(130, 300)
           && state->target == vertex_shader
           && state->current_function == NULL
           && var->type->is_integer()
-          && var->mode == ir_var_out
+          && var->mode == ir_var_shader_out
           && var->interpolation != INTERP_QUALIFIER_FLAT) {
 
          _mesa_glsl_error(&loc, state, "If a vertex output is an integer, "
@@ -2658,8 +2855,10 @@ ast_declarator_list::hir(exec_list *instructions,
        *    "interpolation qualifiers may only precede the qualifiers in,
        *    centroid in, out, or centroid out in a declaration. They do not apply
        *    to the deprecated storage qualifiers varying or centroid varying."
+       *
+       * These deprecated storage qualifiers do not exist in GLSL ES 3.00.
        */
-      if (state->language_version >= 130
+      if (state->is_version(130, 0)
           && this->type->qualifier.has_interpolation()
           && this->type->qualifier.flags.q.varying) {
 
@@ -2684,8 +2883,14 @@ ast_declarator_list::hir(exec_list *instructions,
        *    "Outputs from a vertex shader (out) and inputs to a fragment
        *    shader (in) can be further qualified with one or more of these
        *    interpolation qualifiers"
+       *
+       * From page 31 (page 37 of the PDF) of the GLSL ES 3.00 spec:
+       *    "These interpolation qualifiers may only precede the qualifiers
+       *    in, centroid in, out, or centroid out in a declaration. They do
+       *    not apply to inputs into a vertex shader or outputs from a
+       *    fragment shader."
        */
-      if (state->language_version >= 130
+      if (state->is_version(130, 300)
           && this->type->qualifier.has_interpolation()) {
 
          const char *i = this->type->qualifier.interpolation_string();
@@ -2714,8 +2919,12 @@ ast_declarator_list::hir(exec_list *instructions,
 
       /* From section 4.3.4 of the GLSL 1.30 spec:
        *    "It is an error to use centroid in in a vertex shader."
+       *
+       * From section 4.3.4 of the GLSL ES 3.00 spec:
+       *    "It is an error to use centroid in or interpolation qualifiers in
+       *    a vertex shader input."
        */
-      if (state->language_version >= 130
+      if (state->is_version(130, 300)
           && this->type->qualifier.flags.q.centroid
           && this->type->qualifier.flags.q.in
           && state->target == vertex_shader) {
@@ -2727,13 +2936,8 @@ ast_declarator_list::hir(exec_list *instructions,
 
       /* Precision qualifiers exists only in GLSL versions 1.00 and >= 1.30.
        */
-      if (this->type->specifier->precision != ast_precision_none
-          && state->language_version != 100
-          && state->language_version < 130) {
-
-         _mesa_glsl_error(&loc, state,
-                          "precision qualifiers are supported only in GLSL ES "
-                          "1.00, and GLSL 1.30 and later");
+      if (this->type->specifier->precision != ast_precision_none) {
+         state->check_precision_qualifiers_allowed(&loc);
       }
 
 
@@ -2940,12 +3144,14 @@ ast_parameter_declarator::hir(exec_list *instructions,
    }
 
    is_void = false;
-   ir_variable *var = new(ctx) ir_variable(type, this->identifier, ir_var_in);
+   ir_variable *var = new(ctx)
+      ir_variable(type, this->identifier, ir_var_function_in);
 
    /* Apply any specified qualifiers to the parameter declaration.  Note that
     * for function parameters the default mode is 'in'.
     */
-   apply_type_qualifier_to_variable(& this->type->qualifier, var, state, & loc);
+   apply_type_qualifier_to_variable(& this->type->qualifier, var, state, & loc,
+                                   false, true);
 
    /* From page 17 (page 23 of the PDF) of the GLSL 1.20 spec:
     *
@@ -2953,7 +3159,7 @@ ast_parameter_declarator::hir(exec_list *instructions,
     *    as out or inout function parameters, nor can they be assigned
     *    into."
     */
-   if ((var->mode == ir_var_inout || var->mode == ir_var_out)
+   if ((var->mode == ir_var_function_inout || var->mode == ir_var_function_out)
        && type->contains_sampler()) {
       _mesa_glsl_error(&loc, state, "out and inout parameters cannot contain samplers");
       type = glsl_type::error_type;
@@ -2973,9 +3179,10 @@ ast_parameter_declarator::hir(exec_list *instructions,
     * So for GLSL 1.10, passing an array as an out or inout parameter is not
     * allowed.  This restriction is removed in GLSL 1.20, and in GLSL ES.
     */
-   if ((var->mode == ir_var_inout || var->mode == ir_var_out)
-       && type->is_array() && state->language_version == 110) {
-      _mesa_glsl_error(&loc, state, "Arrays cannot be out or inout parameters in GLSL 1.10");
+   if ((var->mode == ir_var_function_inout || var->mode == ir_var_function_out)
+       && type->is_array()
+       && !state->check_version(120, 100, &loc,
+                                "Arrays cannot be out or inout parameters")) {
       type = glsl_type::error_type;
    }
 
@@ -3058,7 +3265,8 @@ ast_function::hir(exec_list *instructions,
     *
     * Note that this language does not appear in GLSL 1.10.
     */
-   if ((state->current_function != NULL) && (state->language_version != 110)) {
+   if ((state->current_function != NULL) &&
+       state->is_version(120, 100)) {
       YYLTYPE loc = this->get_location();
       _mesa_glsl_error(&loc, state,
                       "declaration of function `%s' not allowed within "
@@ -3318,34 +3526,47 @@ ast_jump_statement::hir(exec_list *instructions,
 
    case ast_break:
    case ast_continue:
-      /* FINISHME: Handle switch-statements.  They cannot contain 'continue',
-       * FINISHME: and they use a different IR instruction for 'break'.
-       */
-      /* FINISHME: Correctly handle the nesting.  If a switch-statement is
-       * FINISHME: inside a loop, a 'continue' is valid and will bind to the
-       * FINISHME: loop.
-       */
-      if (state->loop_or_switch_nesting == NULL) {
+      if (mode == ast_continue &&
+         state->loop_nesting_ast == NULL) {
         YYLTYPE loc = this->get_location();
 
         _mesa_glsl_error(& loc, state,
-                         "`%s' may only appear in a loop",
-                         (mode == ast_break) ? "break" : "continue");
-      } else {
-        ir_loop *const loop = state->loop_or_switch_nesting->as_loop();
+                         "continue may only appear in a loop");
+      } else if (mode == ast_break &&
+                state->loop_nesting_ast == NULL &&
+                state->switch_state.switch_nesting_ast == NULL) {
+        YYLTYPE loc = this->get_location();
 
-        /* Inline the for loop expression again, since we don't know
-         * where near the end of the loop body the normal copy of it
+        _mesa_glsl_error(& loc, state,
+                         "break may only appear in a loop or a switch");
+      } else {
+        /* For a loop, inline the for loop expression again,
+         * since we don't know where near the end of
+         * the loop body the normal copy of it
          * is going to be placed.
          */
-        if (mode == ast_continue &&
-            state->loop_or_switch_nesting_ast->rest_expression) {
-           state->loop_or_switch_nesting_ast->rest_expression->hir(instructions,
-                                                                   state);
+        if (state->loop_nesting_ast != NULL &&
+            mode == ast_continue &&
+            state->loop_nesting_ast->rest_expression) {
+           state->loop_nesting_ast->rest_expression->hir(instructions,
+                                                         state);
         }
 
-        if (loop != NULL) {
-           ir_loop_jump *const jump =
+        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 {
+           ir_loop_jump *const jump = 
               new(ctx) ir_loop_jump((mode == ast_break)
                                     ? ir_loop_jump::jump_break
                                     : ir_loop_jump::jump_continue);
@@ -3408,6 +3629,256 @@ ast_selection_statement::hir(exec_list *instructions,
 }
 
 
+ir_rvalue *
+ast_switch_statement::hir(exec_list *instructions,
+                         struct _mesa_glsl_parse_state *state)
+{
+   void *ctx = state;
+
+   ir_rvalue *const test_expression =
+      this->test_expression->hir(instructions, state);
+
+   /* From page 66 (page 55 of the PDF) of the GLSL 1.50 spec:
+    *
+    *    "The type of init-expression in a switch statement must be a 
+    *     scalar integer." 
+    */
+   if (!test_expression->type->is_scalar() ||
+       !test_expression->type->is_integer()) {
+      YYLTYPE loc = this->test_expression->get_location();
+
+      _mesa_glsl_error(& loc,
+                      state,
+                      "switch-statement expression must be scalar "
+                      "integer");
+   }
+
+   /* Track the switch-statement nesting in a stack-like manner.
+    */
+   struct glsl_switch_state saved = state->switch_state;
+
+   state->switch_state.is_switch_innermost = true;
+   state->switch_state.switch_nesting_ast = this;
+   state->switch_state.labels_ht = hash_table_ctor(0, hash_table_pointer_hash,
+                                                  hash_table_pointer_compare);
+   state->switch_state.previous_default = NULL;
+
+   /* Initalize is_fallthru state to false.
+    */
+   ir_rvalue *const is_fallthru_val = new (ctx) ir_constant(false);
+   state->switch_state.is_fallthru_var =
+      new(ctx) ir_variable(glsl_type::bool_type,
+                          "switch_is_fallthru_tmp",
+                          ir_var_temporary);
+   instructions->push_tail(state->switch_state.is_fallthru_var);
+
+   ir_dereference_variable *deref_is_fallthru_var =
+      new(ctx) ir_dereference_variable(state->switch_state.is_fallthru_var);
+   instructions->push_tail(new(ctx) ir_assignment(deref_is_fallthru_var,
+                                                 is_fallthru_val));
+
+   /* Initalize is_break state to false.
+    */
+   ir_rvalue *const is_break_val = new (ctx) ir_constant(false);
+   state->switch_state.is_break_var = new(ctx) ir_variable(glsl_type::bool_type,
+                                                          "switch_is_break_tmp",
+                                                          ir_var_temporary);
+   instructions->push_tail(state->switch_state.is_break_var);
+
+   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));
+
+   /* Cache test expression.
+    */
+   test_to_hir(instructions, state);
+
+   /* Emit code for body of switch stmt.
+    */
+   body->hir(instructions, state);
+
+   hash_table_dtor(state->switch_state.labels_ht);
+
+   state->switch_state = saved;
+
+   /* Switch statements do not have r-values. */
+   return NULL;
+}
+
+
+void
+ast_switch_statement::test_to_hir(exec_list *instructions,
+                                 struct _mesa_glsl_parse_state *state)
+{
+   void *ctx = state;
+
+   /* Cache value of test expression. */
+   ir_rvalue *const test_val =
+      test_expression->hir(instructions,
+                          state);
+
+   state->switch_state.test_var = new(ctx) ir_variable(test_val->type,
+                                                      "switch_test_tmp",
+                                                      ir_var_temporary);
+   ir_dereference_variable *deref_test_var =
+      new(ctx) ir_dereference_variable(state->switch_state.test_var);
+
+   instructions->push_tail(state->switch_state.test_var);
+   instructions->push_tail(new(ctx) ir_assignment(deref_test_var, test_val));
+}
+
+
+ir_rvalue *
+ast_switch_body::hir(exec_list *instructions,
+                    struct _mesa_glsl_parse_state *state)
+{
+   if (stmts != NULL)
+      stmts->hir(instructions, state);
+
+   /* Switch bodies do not have r-values. */
+   return NULL;
+}
+
+ir_rvalue *
+ast_case_statement_list::hir(exec_list *instructions,
+                            struct _mesa_glsl_parse_state *state)
+{
+   foreach_list_typed (ast_case_statement, case_stmt, link, & this->cases)
+      case_stmt->hir(instructions, state);
+
+   /* Case statements do not have r-values. */
+   return NULL;
+}
+
+ir_rvalue *
+ast_case_statement::hir(exec_list *instructions,
+                       struct _mesa_glsl_parse_state *state)
+{
+   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);
+   ir_if *const test_fallthru = new(state) ir_if(deref_fallthru_guard);
+
+   foreach_list_typed (ast_node, stmt, link, & this->stmts)
+      stmt->hir(& test_fallthru->then_instructions, state);
+
+   instructions->push_tail(test_fallthru);
+
+   /* Case statements do not have r-values. */
+   return NULL;
+}
+
+
+ir_rvalue *
+ast_case_label_list::hir(exec_list *instructions,
+                        struct _mesa_glsl_parse_state *state)
+{
+   foreach_list_typed (ast_case_label, label, link, & this->labels)
+      label->hir(instructions, state);
+
+   /* Case labels do not have r-values. */
+   return NULL;
+}
+
+ir_rvalue *
+ast_case_label::hir(exec_list *instructions,
+                   struct _mesa_glsl_parse_state *state)
+{
+   void *ctx = state;
+
+   ir_dereference_variable *deref_fallthru_var =
+      new(ctx) ir_dereference_variable(state->switch_state.is_fallthru_var);
+
+   ir_rvalue *const true_val = new(ctx) ir_constant(true);
+
+   /* If not default case, ... */
+   if (this->test_value != NULL) {
+      /* Conditionally set fallthru state based on
+       * comparison of cached test expression value to case label.
+       */
+      ir_rvalue *const label_rval = this->test_value->hir(instructions, state);
+      ir_constant *label_const = label_rval->constant_expression_value();
+
+      if (!label_const) {
+        YYLTYPE loc = this->test_value->get_location();
+
+        _mesa_glsl_error(& loc, state,
+                         "switch statement case label must be a "
+                         "constant expression");
+
+        /* Stuff a dummy value in to allow processing to continue. */
+        label_const = new(ctx) ir_constant(0);
+      } else {
+        ast_expression *previous_label = (ast_expression *)
+           hash_table_find(state->switch_state.labels_ht,
+                           (void *)(uintptr_t)label_const->value.u[0]);
+
+        if (previous_label) {
+           YYLTYPE loc = this->test_value->get_location();
+           _mesa_glsl_error(& loc, state,
+                            "duplicate case value");
+
+           loc = previous_label->get_location();
+           _mesa_glsl_error(& loc, state,
+                            "this is the previous case label");
+        } else {
+           hash_table_insert(state->switch_state.labels_ht,
+                             this->test_value,
+                             (void *)(uintptr_t)label_const->value.u[0]);
+        }
+      }
+
+      ir_dereference_variable *deref_test_var =
+        new(ctx) ir_dereference_variable(state->switch_state.test_var);
+
+      ir_rvalue *const test_cond = new(ctx) ir_expression(ir_binop_all_equal,
+                                                         label_const,
+                                                         deref_test_var);
+
+      ir_assignment *set_fallthru_on_test =
+        new(ctx) ir_assignment(deref_fallthru_var,
+                               true_val,
+                               test_cond);
+
+      instructions->push_tail(set_fallthru_on_test);
+   } else { /* default case */
+      if (state->switch_state.previous_default) {
+        YYLTYPE loc = this->get_location();
+        _mesa_glsl_error(& loc, state,
+                         "multiple default labels in one switch");
+
+        loc = state->switch_state.previous_default->get_location();
+        _mesa_glsl_error(& loc, state,
+                         "this is the first default label");
+      }
+      state->switch_state.previous_default = this;
+
+      /* Set falltrhu state. */
+      ir_assignment *set_fallthru =
+        new(ctx) ir_assignment(deref_fallthru_var, true_val);
+
+      instructions->push_tail(set_fallthru);
+   }
+
+   /* Case statements do not have r-values. */
+   return NULL;
+}
+
 void
 ast_iteration_statement::condition_to_hir(ir_loop *stmt,
                                          struct _mesa_glsl_parse_state *state)
@@ -3429,8 +3900,7 @@ ast_iteration_statement::condition_to_hir(ir_loop *stmt,
          * like 'if (!condition) break;' as the loop termination condition.
          */
         ir_rvalue *const not_cond =
-           new(ctx) ir_expression(ir_unop_logic_not, glsl_type::bool_type, cond,
-                                  NULL);
+           new(ctx) ir_expression(ir_unop_logic_not, cond);
 
         ir_if *const if_stmt = new(ctx) ir_if(not_cond);
 
@@ -3461,13 +3931,16 @@ ast_iteration_statement::hir(exec_list *instructions,
    ir_loop *const stmt = new(ctx) ir_loop();
    instructions->push_tail(stmt);
 
-   /* Track the current loop and / or switch-statement nesting.
-    */
-   ir_instruction *const nesting = state->loop_or_switch_nesting;
-   ast_iteration_statement *nesting_ast = state->loop_or_switch_nesting_ast;
+   /* Track the current loop nesting. */
+   ast_iteration_statement *nesting_ast = state->loop_nesting_ast;
 
-   state->loop_or_switch_nesting = stmt;
-   state->loop_or_switch_nesting_ast = this;
+   state->loop_nesting_ast = this;
+
+   /* Likewise, indicate that following code is closest to a loop,
+    * NOT closest to a switch.
+    */
+   bool saved_is_switch_innermost = state->switch_state.is_switch_innermost;
+   state->switch_state.is_switch_innermost = false;
 
    if (mode != ast_do_while)
       condition_to_hir(stmt, state);
@@ -3484,10 +3957,9 @@ ast_iteration_statement::hir(exec_list *instructions,
    if (mode != ast_do_while)
       state->symbols->pop_scope();
 
-   /* Restore previous nesting before returning.
-    */
-   state->loop_or_switch_nesting = nesting;
-   state->loop_or_switch_nesting_ast = nesting_ast;
+   /* Restore previous nesting before returning. */
+   state->loop_nesting_ast = nesting_ast;
+   state->switch_state.is_switch_innermost = saved_is_switch_innermost;
 
    /* Loops do not have r-values.
     */
@@ -3505,11 +3977,7 @@ ast_type_specifier::hir(exec_list *instructions,
    YYLTYPE loc = this->get_location();
 
    if (this->precision != ast_precision_none
-       && state->language_version != 100
-       && state->language_version < 130) {
-      _mesa_glsl_error(&loc, state,
-                       "precision qualifiers exist only in "
-                       "GLSL ES 1.00, and GLSL 1.30 and later");
+       && !state->check_precision_qualifiers_allowed(&loc)) {
       return NULL;
    }
    if (this->precision != ast_precision_none
@@ -3539,8 +4007,8 @@ ast_type_specifier::hir(exec_list *instructions,
                           "arrays");
          return NULL;
       }
-      if (this->type_specifier != ast_float
-          && this->type_specifier != ast_int) {
+      if (strcmp(this->type_name, "float") != 0 &&
+         strcmp(this->type_name, "int") != 0) {
          _mesa_glsl_error(&loc, state,
                           "default precision statements apply only to types "
                           "float and int");
@@ -3558,35 +4026,50 @@ ast_type_specifier::hir(exec_list *instructions,
 }
 
 
-ir_rvalue *
-ast_struct_specifier::hir(exec_list *instructions,
-                         struct _mesa_glsl_parse_state *state)
+/**
+ * Process a structure or interface block tree into an array of structure fields
+ *
+ * After parsing, where there are some syntax differnces, structures and
+ * interface blocks are almost identical.  They are similar enough that the
+ * AST for each can be processed the same way into a set of
+ * \c glsl_struct_field to describe the members.
+ *
+ * \return
+ * The number of fields processed.  A pointer to the array structure fields is
+ * stored in \c *fields_ret.
+ */
+unsigned
+ast_process_structure_or_interface_block(exec_list *instructions,
+                                        struct _mesa_glsl_parse_state *state,
+                                        exec_list *declarations,
+                                        YYLTYPE &loc,
+                                        glsl_struct_field **fields_ret,
+                                         bool is_interface,
+                                         bool block_row_major)
 {
    unsigned decl_count = 0;
 
-   /* Make an initial pass over the list of structure fields to determine how
+   /* Make an initial pass over the list of fields to determine how
     * many there are.  Each element in this list is an ast_declarator_list.
     * This means that we actually need to count the number of elements in the
     * 'declarations' list in each of the elements.
     */
-   foreach_list_typed (ast_declarator_list, decl_list, link,
-                      &this->declarations) {
+   foreach_list_typed (ast_declarator_list, decl_list, link, declarations) {
       foreach_list_const (decl_ptr, & decl_list->declarations) {
         decl_count++;
       }
    }
 
-   /* Allocate storage for the structure fields and process the field
+   /* Allocate storage for the fields and process the field
     * declarations.  As the declarations are processed, try to also convert
     * the types to HIR.  This ensures that structure definitions embedded in
-    * other structure definitions are processed.
+    * other structure definitions or in interface blocks are processed.
     */
    glsl_struct_field *const fields = ralloc_array(state, glsl_struct_field,
                                                  decl_count);
 
    unsigned i = 0;
-   foreach_list_typed (ast_declarator_list, decl_list, link,
-                      &this->declarations) {
+   foreach_list_typed (ast_declarator_list, decl_list, link, declarations) {
       const char *type_name;
 
       decl_list->type->specifier->hir(instructions, state);
@@ -3595,7 +4078,6 @@ ast_struct_specifier::hir(exec_list *instructions,
        * embedded structure definitions have been removed from the language.
        */
       if (state->es_shader && decl_list->type->specifier->structure != NULL) {
-        YYLTYPE loc = this->get_location();
         _mesa_glsl_error(&loc, state, "Embedded structure definitions are "
                          "not allowed in GLSL ES 1.00.");
       }
@@ -3605,25 +4087,88 @@ ast_struct_specifier::hir(exec_list *instructions,
 
       foreach_list_typed (ast_declaration, decl, link,
                          &decl_list->declarations) {
-        const struct glsl_type *field_type = decl_type;
+         /* From the GL_ARB_uniform_buffer_object spec:
+          *
+          *     "Sampler types are not allowed inside of uniform
+          *      blocks. All other types, arrays, and structures
+          *      allowed for uniforms are allowed within a uniform
+          *      block."
+          */
+         const struct glsl_type *field_type = decl_type;
+
+         if (is_interface && field_type->contains_sampler()) {
+            YYLTYPE loc = decl_list->get_location();
+            _mesa_glsl_error(&loc, state,
+                             "Uniform in non-default uniform block contains sampler\n");
+         }
+
+         const struct ast_type_qualifier *const qual =
+            & decl_list->type->qualifier;
+         if (qual->flags.q.std140 ||
+             qual->flags.q.packed ||
+             qual->flags.q.shared) {
+            _mesa_glsl_error(&loc, state,
+                             "uniform block layout qualifiers std140, packed, and "
+                             "shared can only be applied to uniform blocks, not "
+                             "members");
+         }
+
         if (decl->is_array) {
-           YYLTYPE loc = decl->get_location();
            field_type = process_array_type(&loc, decl_type, decl->array_size,
                                            state);
         }
         fields[i].type = (field_type != NULL)
            ? field_type : glsl_type::error_type;
         fields[i].name = decl->identifier;
+
+         if (qual->flags.q.row_major || qual->flags.q.column_major) {
+            if (!field_type->is_matrix() && !field_type->is_record()) {
+               _mesa_glsl_error(&loc, state,
+                                "uniform block layout qualifiers row_major and "
+                                "column_major can only be applied to matrix and "
+                                "structure types");
+            } else
+               validate_matrix_layout_for_type(state, &loc, field_type);
+         }
+
+         if (field_type->is_matrix() ||
+             (field_type->is_array() && field_type->fields.array->is_matrix())) {
+            fields[i].row_major = block_row_major;
+            if (qual->flags.q.row_major)
+               fields[i].row_major = true;
+            else if (qual->flags.q.column_major)
+               fields[i].row_major = false;
+         }
+
         i++;
       }
    }
 
    assert(i == decl_count);
 
+   *fields_ret = fields;
+   return decl_count;
+}
+
+
+ir_rvalue *
+ast_struct_specifier::hir(exec_list *instructions,
+                         struct _mesa_glsl_parse_state *state)
+{
+   YYLTYPE loc = this->get_location();
+   glsl_struct_field *fields;
+   unsigned decl_count =
+      ast_process_structure_or_interface_block(instructions,
+                                              state,
+                                              &this->declarations,
+                                              loc,
+                                              &fields,
+                                               false,
+                                               false);
+
    const glsl_type *t =
       glsl_type::get_record_instance(fields, decl_count, this->name);
 
-   YYLTYPE loc = this->get_location();
    if (!state->symbols->add_type(name, t)) {
       _mesa_glsl_error(& loc, state, "struct `%s' previously defined", name);
    } else {
@@ -3641,3 +4186,161 @@ ast_struct_specifier::hir(exec_list *instructions,
     */
    return NULL;
 }
+
+ir_rvalue *
+ast_uniform_block::hir(exec_list *instructions,
+                      struct _mesa_glsl_parse_state *state)
+{
+   YYLTYPE loc = this->get_location();
+
+   /* The ast_uniform_block has a list of ast_declarator_lists.  We
+    * need to turn those into ir_variables with an association
+    * with this uniform block.
+    */
+   enum glsl_interface_packing packing;
+   if (this->layout.flags.q.shared) {
+      packing = GLSL_INTERFACE_PACKING_SHARED;
+   } else if (this->layout.flags.q.packed) {
+      packing = GLSL_INTERFACE_PACKING_PACKED;
+   } else {
+      /* The default layout is std140.
+       */
+      packing = GLSL_INTERFACE_PACKING_STD140;
+   }
+
+   bool block_row_major = this->layout.flags.q.row_major;
+   exec_list declared_variables;
+   glsl_struct_field *fields;
+   unsigned int num_variables =
+      ast_process_structure_or_interface_block(&declared_variables,
+                                               state,
+                                               &this->declarations,
+                                               loc,
+                                               &fields,
+                                               true,
+                                               block_row_major);
+
+   const glsl_type *block_type =
+      glsl_type::get_interface_instance(fields,
+                                        num_variables,
+                                        packing,
+                                        this->block_name);
+
+   if (!state->symbols->add_type(block_type->name, block_type)) {
+      YYLTYPE loc = this->get_location();
+      _mesa_glsl_error(&loc, state, "Uniform block name `%s' already taken in "
+                       "the current scope.\n", this->block_name);
+   }
+
+   /* Since interface blocks cannot contain statements, it should be
+    * impossible for the block to generate any instructions.
+    */
+   assert(declared_variables.is_empty());
+
+   /* Page 39 (page 45 of the PDF) of section 4.3.7 in the GLSL ES 3.00 spec
+    * says:
+    *
+    *     "If an instance name (instance-name) is used, then it puts all the
+    *     members inside a scope within its own name space, accessed with the
+    *     field selector ( . ) operator (analogously to structures)."
+    */
+   if (this->instance_name) {
+      ir_variable *var;
+
+      if (this->array_size != NULL) {
+         const glsl_type *block_array_type =
+            process_array_type(&loc, block_type, this->array_size, state);
+
+         var = new(state) ir_variable(block_array_type,
+                                      this->instance_name,
+                                      ir_var_uniform);
+      } else {
+         var = new(state) ir_variable(block_type,
+                                      this->instance_name,
+                                      ir_var_uniform);
+      }
+
+      var->interface_type = block_type;
+      state->symbols->add_variable(var);
+      instructions->push_tail(var);
+   } else {
+      /* In order to have an array size, the block must also be declared with
+       * an instane name.
+       */
+      assert(this->array_size == NULL);
+
+      for (unsigned i = 0; i < num_variables; i++) {
+         ir_variable *var =
+            new(state) ir_variable(fields[i].type,
+                                   ralloc_strdup(state, fields[i].name),
+                                   ir_var_uniform);
+         var->interface_type = block_type;
+
+         state->symbols->add_variable(var);
+         instructions->push_tail(var);
+      }
+   }
+
+   return NULL;
+}
+
+static void
+detect_conflicting_assignments(struct _mesa_glsl_parse_state *state,
+                              exec_list *instructions)
+{
+   bool gl_FragColor_assigned = false;
+   bool gl_FragData_assigned = false;
+   bool user_defined_fs_output_assigned = false;
+   ir_variable *user_defined_fs_output = NULL;
+
+   /* It would be nice to have proper location information. */
+   YYLTYPE loc;
+   memset(&loc, 0, sizeof(loc));
+
+   foreach_list(node, instructions) {
+      ir_variable *var = ((ir_instruction *)node)->as_variable();
+
+      if (!var || !var->assigned)
+        continue;
+
+      if (strcmp(var->name, "gl_FragColor") == 0)
+        gl_FragColor_assigned = true;
+      else if (strcmp(var->name, "gl_FragData") == 0)
+        gl_FragData_assigned = true;
+      else if (strncmp(var->name, "gl_", 3) != 0) {
+        if (state->target == fragment_shader &&
+            var->mode == ir_var_shader_out) {
+           user_defined_fs_output_assigned = true;
+           user_defined_fs_output = var;
+        }
+      }
+   }
+
+   /* From the GLSL 1.30 spec:
+    *
+    *     "If a shader statically assigns a value to gl_FragColor, it
+    *      may not assign a value to any element of gl_FragData. If a
+    *      shader statically writes a value to any element of
+    *      gl_FragData, it may not assign a value to
+    *      gl_FragColor. That is, a shader may assign values to either
+    *      gl_FragColor or gl_FragData, but not both. Multiple shaders
+    *      linked together must also consistently write just one of
+    *      these variables.  Similarly, if user declared output
+    *      variables are in use (statically assigned to), then the
+    *      built-in variables gl_FragColor and gl_FragData may not be
+    *      assigned to. These incorrect usages all generate compile
+    *      time errors."
+    */
+   if (gl_FragColor_assigned && gl_FragData_assigned) {
+      _mesa_glsl_error(&loc, state, "fragment shader writes to both "
+                      "`gl_FragColor' and `gl_FragData'\n");
+   } else if (gl_FragColor_assigned && user_defined_fs_output_assigned) {
+      _mesa_glsl_error(&loc, state, "fragment shader writes to both "
+                      "`gl_FragColor' and `%s'\n",
+                      user_defined_fs_output->name);
+   } else if (gl_FragData_assigned && user_defined_fs_output_assigned) {
+      _mesa_glsl_error(&loc, state, "fragment shader writes to both "
+                      "`gl_FragData' and `%s'\n",
+                      user_defined_fs_output->name);
+   }
+}