glsl2: Remove unnecessary glsl_symbol_table::get_function parameter return_constructors
[mesa.git] / src / glsl / ast_to_hir.cpp
index f5e93b025472b354ae155a0752e3e0c6d9b122ee..5bdf3da3676cb10e017d940565f1d968b8573ec2 100644 (file)
@@ -49,7 +49,7 @@
  * parser (and lexer) sources.
  */
 
-#include "main/imports.h"
+#include "main/core.h" /* for struct gl_extensions */
 #include "glsl_symbol_table.h"
 #include "glsl_parser_extras.h"
 #include "ast.h"
@@ -64,6 +64,21 @@ _mesa_ast_to_hir(exec_list *instructions, struct _mesa_glsl_parse_state *state)
 
    state->current_function = NULL;
 
+   /* Section 4.2 of the GLSL 1.20 specification states:
+    * "The built-in functions are scoped in a scope outside the global scope
+    *  users declare global variables in.  That is, a shader's global scope,
+    *  available for user-defined functions and global variables, is nested
+    *  inside the scope containing the built-in functions."
+    *
+    * Since built-in functions like ftransform() access built-in variables,
+    * it follows that those must be in the outer scope as well.
+    *
+    * We push scope here to create this nesting effect...but don't pop.
+    * This way, a shader's globals are still in the symbol table for use
+    * by the linker.
+    */
+   state->symbols->push_scope();
+
    foreach_list_typed (ast_node, ast, link, & state->translation_unit)
       ast->hir(instructions, state);
 }
@@ -282,8 +297,17 @@ arithmetic_result_type(ir_rvalue * &value_a, ir_rvalue * &value_b,
          * means the vector type of a row from A must be the same as the
          * vector the type of B.
          */
-        if (type_a->row_type() == type_b)
-           return type_b;
+        if (type_a->row_type() == type_b) {
+           /* The resulting vector has a number of elements equal to
+            * the number of rows of matrix A. */
+           const glsl_type *const type =
+              glsl_type::get_instance(type_a->base_type,
+                                      type_a->column_type()->vector_elements,
+                                      1);
+           assert(type != glsl_type::error_type);
+
+           return type;
+        }
       } else {
         assert(type_b->is_matrix());
 
@@ -292,8 +316,17 @@ arithmetic_result_type(ir_rvalue * &value_a, ir_rvalue * &value_b,
          * the type of A must be the same as the vector type of a column from
          * B.
          */
-        if (type_a == type_b->column_type())
-           return type_a;
+        if (type_a == type_b->column_type()) {
+           /* The resulting vector has a number of elements equal to
+            * the number of columns of matrix B. */
+           const glsl_type *const type =
+              glsl_type::get_instance(type_a->base_type,
+                                      type_b->row_type()->vector_elements,
+                                      1);
+           assert(type != glsl_type::error_type);
+
+           return type;
+        }
       }
 
       _mesa_glsl_error(loc, state, "size mismatch for matrix multiplication");
@@ -477,7 +510,6 @@ do_assignment(exec_list *instructions, struct _mesa_glsl_parse_state *state,
    bool error_emitted = (lhs->type->is_error() || rhs->type->is_error());
 
    if (!error_emitted) {
-      /* FINISHME: This does not handle 'foo.bar.a.b.c[5].d = 5' */
       if (!lhs->is_lvalue()) {
         _mesa_glsl_error(& lhs_loc, state, "non-lvalue in assignment");
         error_emitted = true;
@@ -511,9 +543,9 @@ do_assignment(exec_list *instructions, struct _mesa_glsl_parse_state *state,
                             var->max_array_access);
         }
 
-        var->type = glsl_type::get_array_instance(state,
-                                                  lhs->type->element_type(),
+        var->type = glsl_type::get_array_instance(lhs->type->element_type(),
                                                   rhs->type->array_size());
+        d->type = var->type;
       }
    }
 
@@ -527,7 +559,8 @@ do_assignment(exec_list *instructions, struct _mesa_glsl_parse_state *state,
     * temporary and return a deref of that temporary.  If the rvalue
     * ends up not being used, the temp will get copy-propagated out.
     */
-   ir_variable *var = new(ctx) ir_variable(rhs->type, "assignment_tmp");
+   ir_variable *var = new(ctx) ir_variable(rhs->type, "assignment_tmp",
+                                          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,
@@ -535,42 +568,21 @@ do_assignment(exec_list *instructions, struct _mesa_glsl_parse_state *state,
                                                  NULL));
    deref_var = new(ctx) ir_dereference_variable(var);
 
-   instructions->push_tail(new(ctx) ir_assignment(lhs,
-                                                 deref_var,
-                                                 NULL));
+   if (!error_emitted)
+      instructions->push_tail(new(ctx) ir_assignment(lhs, deref_var, NULL));
 
    return new(ctx) ir_dereference_variable(var);
 }
 
-
-/**
- * Generate a new temporary and add its declaration to the instruction stream
- */
-static ir_variable *
-generate_temporary(const glsl_type *type, exec_list *instructions,
-                  struct _mesa_glsl_parse_state *state)
-{
-   void *ctx = state;
-   char *name = (char *) malloc(sizeof(char) * 13);
-
-   snprintf(name, 13, "tmp_%08X", state->temp_index);
-   state->temp_index++;
-
-   ir_variable *const var = new(ctx) ir_variable(type, name);
-   instructions->push_tail(var);
-
-   return var;
-}
-
-
 static ir_rvalue *
 get_lvalue_copy(exec_list *instructions, ir_rvalue *lvalue)
 {
    void *ctx = talloc_parent(lvalue);
    ir_variable *var;
 
-   /* FINISHME: Give unique names to the temporaries. */
-   var = new(ctx) ir_variable(lvalue->type, "_post_incdec_tmp");
+   var = new(ctx) ir_variable(lvalue->type, "_post_incdec_tmp",
+                             ir_var_temporary);
+   instructions->push_tail(var);
    var->mode = ir_var_auto;
 
    instructions->push_tail(new(ctx) ir_assignment(new(ctx) ir_dereference_variable(var),
@@ -657,7 +669,7 @@ ast_expression::hir(exec_list *instructions,
       -1,               /* ast_sequence doesn't convert to ir_expression. */
    };
    ir_rvalue *result = NULL;
-   ir_rvalue *op[2];
+   ir_rvalue *op[3];
    const struct glsl_type *type = glsl_type::error_type;
    bool error_emitted = false;
    YYLTYPE loc;
@@ -679,9 +691,9 @@ ast_expression::hir(exec_list *instructions,
    case ast_plus:
       op[0] = this->subexpressions[0]->hir(instructions, state);
 
-      error_emitted = op[0]->type->is_error();
-      if (type->is_error())
-        op[0]->type = type;
+      type = unary_arithmetic_result_type(op[0]->type, state, & loc);
+
+      error_emitted = type->is_error();
 
       result = op[0];
       break;
@@ -790,9 +802,60 @@ ast_expression::hir(exec_list *instructions,
    case ast_bit_and:
    case ast_bit_xor:
    case ast_bit_or:
+      op[0] = this->subexpressions[0]->hir(instructions, state);
+      op[1] = this->subexpressions[1]->hir(instructions, state);
+
+      if (state->language_version < 130) {
+        _mesa_glsl_error(&loc, state, "bit-wise operations require GLSL 1.30");
+        error_emitted = true;
+      }
+
+      if (!op[0]->type->is_integer()) {
+        _mesa_glsl_error(&loc, state, "LHS of `%s' must be an integer",
+                         operator_string(this->oper));
+        error_emitted = true;
+      }
+
+      if (!op[1]->type->is_integer()) {
+        _mesa_glsl_error(&loc, state, "RHS of `%s' must be an integer",
+                         operator_string(this->oper));
+        error_emitted = true;
+      }
+
+      if (op[0]->type->base_type != op[1]->type->base_type) {
+        _mesa_glsl_error(&loc, state, "operands of `%s' must have the same "
+                         "base type", operator_string(this->oper));
+        error_emitted = true;
+      }
+
+      if (op[0]->type->is_vector() && op[1]->type->is_vector()
+         && op[0]->type->vector_elements != op[1]->type->vector_elements) {
+        _mesa_glsl_error(&loc, state, "operands of `%s' cannot be vectors of "
+                         "different sizes", operator_string(this->oper));
+        error_emitted = true;
+      }
+
+      type = op[0]->type->is_scalar() ? op[1]->type : op[0]->type;
+      result = new(ctx) ir_expression(operations[this->oper], type,
+                                     op[0], op[1]);
+      error_emitted = op[0]->type->is_error() || op[1]->type->is_error();
+      break;
+
    case ast_bit_not:
-      _mesa_glsl_error(& loc, state, "FINISHME: implement bit-wise operators");
-      error_emitted = true;
+      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");
+        error_emitted = true;
+      }
+
+      if (!op[0]->type->is_integer()) {
+        _mesa_glsl_error(&loc, state, "operand of `~' must be an integer");
+        error_emitted = true;
+      }
+
+      type = op[0]->type;
+      result = new(ctx) ir_expression(ir_unop_bit_not, type, op[0], NULL);
       break;
 
    case ast_logic_and: {
@@ -825,6 +888,11 @@ ast_expression::hir(exec_list *instructions,
         }
         type = glsl_type::bool_type;
       } else {
+        ir_variable *const tmp = new(ctx) ir_variable(glsl_type::bool_type,
+                                                      "and_tmp",
+                                                      ir_var_temporary);
+        instructions->push_tail(tmp);
+
         ir_if *const stmt = new(ctx) ir_if(op[0]);
         instructions->push_tail(stmt);
 
@@ -839,9 +907,6 @@ ast_expression::hir(exec_list *instructions,
            error_emitted = true;
         }
 
-        ir_variable *const tmp = generate_temporary(glsl_type::bool_type,
-                                                    instructions, state);
-
         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);
@@ -888,13 +953,15 @@ ast_expression::hir(exec_list *instructions,
         }
         type = glsl_type::bool_type;
       } else {
+        ir_variable *const tmp = new(ctx) ir_variable(glsl_type::bool_type,
+                                                      "or_tmp",
+                                                      ir_var_temporary);
+        instructions->push_tail(tmp);
+
         ir_if *const stmt = new(ctx) ir_if(op[0]);
         instructions->push_tail(stmt);
 
-        ir_variable *const tmp = generate_temporary(glsl_type::bool_type,
-                                                    instructions, state);
-
-        op[1] = this->subexpressions[1]->hir(&stmt->then_instructions, state);
+        op[1] = this->subexpressions[1]->hir(&stmt->else_instructions, state);
 
         if (!op[1]->type->is_boolean() || !op[1]->type->is_scalar()) {
            YYLTYPE loc = this->subexpressions[1]->get_location();
@@ -961,7 +1028,7 @@ ast_expression::hir(exec_list *instructions,
                                                   op[0], op[1]);
 
       result = do_assignment(instructions, state,
-                            op[0]->clone(NULL), temp_rhs,
+                            op[0]->clone(ctx, NULL), temp_rhs,
                             this->subexpressions[0]->get_location());
       type = result->type;
       error_emitted = (op[0]->type->is_error());
@@ -982,12 +1049,12 @@ ast_expression::hir(exec_list *instructions,
 
       assert(operations[this->oper] == ir_binop_mod);
 
-      struct ir_rvalue *temp_rhs;
+      ir_rvalue *temp_rhs;
       temp_rhs = new(ctx) ir_expression(operations[this->oper], type,
                                        op[0], op[1]);
 
       result = do_assignment(instructions, state,
-                            op[0]->clone(NULL), temp_rhs,
+                            op[0]->clone(ctx, NULL), temp_rhs,
                             this->subexpressions[0]->get_location());
       type = result->type;
       error_emitted = type->is_error();
@@ -1067,8 +1134,9 @@ ast_expression::hir(exec_list *instructions,
          && (cond_val != NULL) && (then_val != NULL) && (else_val != NULL)) {
         result = (cond_val->value.b[0]) ? then_val : else_val;
       } else {
-        ir_variable *const tmp = generate_temporary(type,
-                                                    instructions, state);
+        ir_variable *const tmp =
+           new(ctx) ir_variable(type, "conditional_tmp", ir_var_temporary);
+        instructions->push_tail(tmp);
 
         ir_if *const stmt = new(ctx) ir_if(op[0]);
         instructions->push_tail(stmt);
@@ -1102,12 +1170,12 @@ ast_expression::hir(exec_list *instructions,
 
       type = arithmetic_result_type(op[0], op[1], false, state, & loc);
 
-      struct ir_rvalue *temp_rhs;
+      ir_rvalue *temp_rhs;
       temp_rhs = new(ctx) ir_expression(operations[this->oper], type,
                                        op[0], op[1]);
 
       result = do_assignment(instructions, state,
-                            op[0]->clone(NULL), temp_rhs,
+                            op[0]->clone(ctx, NULL), temp_rhs,
                             this->subexpressions[0]->get_location());
       type = result->type;
       error_emitted = op[0]->type->is_error();
@@ -1126,17 +1194,17 @@ ast_expression::hir(exec_list *instructions,
 
       type = arithmetic_result_type(op[0], op[1], false, state, & loc);
 
-      struct ir_rvalue *temp_rhs;
+      ir_rvalue *temp_rhs;
       temp_rhs = new(ctx) ir_expression(operations[this->oper], type,
                                        op[0], op[1]);
 
       /* Get a temporary of a copy of the lvalue before it's modified.
        * This may get thrown away later.
        */
-      result = get_lvalue_copy(instructions, op[0]->clone(NULL));
+      result = get_lvalue_copy(instructions, op[0]->clone(ctx, NULL));
 
       (void)do_assignment(instructions, state,
-                         op[0]->clone(NULL), temp_rhs,
+                         op[0]->clone(ctx, NULL), temp_rhs,
                          this->subexpressions[0]->get_location());
 
       type = result->type;
@@ -1251,6 +1319,19 @@ ast_expression::hir(exec_list *instructions,
            if ((v != NULL) && (unsigned(idx) > v->max_array_access))
               v->max_array_access = idx;
         }
+      } else if (array->type->array_size() == 0) {
+        _mesa_glsl_error(&loc, state, "unsized array index must be constant");
+      } else {
+        if (array->type->is_array()) {
+           /* whole_variable_referenced can return NULL if the array is a
+            * member of a structure.  In this case it is safe to not update
+            * the max_array_access field because it is never used for fields
+            * of structures.
+            */
+           ir_variable *v = array->whole_variable_referenced();
+           if (v != NULL)
+              v->max_array_access = array->type->array_size();
+        }
       }
 
       if (error_emitted)
@@ -1418,7 +1499,7 @@ process_array_type(const glsl_type *base, ast_node *array_size,
       }
    }
 
-   return glsl_type::get_array_instance(state, base, length);
+   return glsl_type::get_array_instance(base, length);
 }
 
 
@@ -1446,7 +1527,7 @@ ast_type_specifier::glsl_type(const char **name,
 
 static void
 apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual,
-                                struct ir_variable *var,
+                                ir_variable *var,
                                 struct _mesa_glsl_parse_state *state,
                                 YYLTYPE *loc)
 {
@@ -1490,6 +1571,9 @@ 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.
+    */
    if (qual->in && qual->out)
       var->mode = ir_var_inout;
    else if (qual->attribute || qual->in
@@ -1499,33 +1583,6 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual,
       var->mode = ir_var_out;
    else if (qual->uniform)
       var->mode = ir_var_uniform;
-   else
-      var->mode = ir_var_auto;
-
-   if (qual->uniform)
-      var->shader_in = true;
-
-   /* Any 'in' or 'inout' variables at global scope must be marked as being
-    * shader inputs.  Likewise, any 'out' or 'inout' variables at global scope
-    * must be marked as being shader outputs.
-    */
-   if (state->current_function == NULL) {
-      switch (var->mode) {
-      case ir_var_in:
-      case ir_var_uniform:
-        var->shader_in = true;
-        break;
-      case ir_var_out:
-        var->shader_out = true;
-        break;
-      case ir_var_inout:
-        var->shader_in = true;
-        var->shader_out = true;
-        break;
-      default:
-        break;
-      }
-   }
 
    if (qual->flat)
       var->interpolation = ir_var_flat;
@@ -1534,6 +1591,19 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual,
    else
       var->interpolation = ir_var_smooth;
 
+   var->pixel_center_integer = qual->pixel_center_integer;
+   var->origin_upper_left = qual->origin_upper_left;
+   if ((qual->origin_upper_left || qual->pixel_center_integer)
+       && (strcmp(var->name, "gl_FragCoord") != 0)) {
+      const char *const qual_string = (qual->origin_upper_left)
+        ? "origin_upper_left" : "pixel_center_integer";
+
+      _mesa_glsl_error(loc, state,
+                      "layout qualifier `%s' can only be applied to "
+                      "fragment shader input `gl_FragCoord'",
+                      qual_string);
+   }
+
    if (var->type->is_array() && (state->language_version >= 120)) {
       var->array_lvalue = true;
    }
@@ -1624,7 +1694,7 @@ ast_declarator_list::hir(exec_list *instructions,
 
    foreach_list_typed (ast_declaration, decl, link, &this->declarations) {
       const struct glsl_type *var_type;
-      struct ir_variable *var;
+      ir_variable *var;
 
       /* FINISHME: Emit a warning if a variable declaration shadows a
        * FINISHME: declaration at a higher scope.
@@ -1649,7 +1719,7 @@ ast_declarator_list::hir(exec_list *instructions,
         var_type = decl_type;
       }
 
-      var = new(ctx) ir_variable(var_type, decl->identifier);
+      var = new(ctx) ir_variable(var_type, decl->identifier, ir_var_auto);
 
       /* From page 22 (page 28 of the PDF) of the GLSL 1.10 specification;
        *
@@ -1681,11 +1751,19 @@ ast_declarator_list::hir(exec_list *instructions,
                                       & loc);
 
       if (this->type->qualifier.invariant) {
-        if ((state->target == vertex_shader) && !var->shader_out) {
+        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
+            */
            _mesa_glsl_error(& loc, state,
                             "`%s' cannot be marked invariant, vertex shader "
                             "outputs only\n", var->name);
-        } else if ((state->target == fragment_shader) && !var->shader_in) {
+        } else if ((state->target == fragment_shader) &&
+                   !(var->mode == ir_var_in || var->mode == ir_var_inout)) {
+           /* FINISHME: Note that this doesn't work for invariant on
+            * a function signature inval
+            */
            _mesa_glsl_error(& loc, state,
                             "`%s' cannot be marked invariant, fragment shader "
                             "inputs only\n", var->name);
@@ -1772,6 +1850,13 @@ ast_declarator_list::hir(exec_list *instructions,
         }
       }
 
+      /* Process the initializer and add its instructions to a temporary
+       * list.  This list will be added to the instruction stream (below) after
+       * the declaration is added.  This is done because in some cases (such as
+       * redeclarations) the declaration may not actually be added to the
+       * instruction stream.
+       */
+      exec_list initializer_instructions;
       if (decl->initializer != NULL) {
         YYLTYPE initializer_loc = decl->initializer->get_location();
 
@@ -1801,23 +1886,42 @@ ast_declarator_list::hir(exec_list *instructions,
         }
 
         ir_dereference *const lhs = new(ctx) ir_dereference_variable(var);
-        ir_rvalue *rhs = decl->initializer->hir(instructions, state);
+        ir_rvalue *rhs = decl->initializer->hir(&initializer_instructions,
+                                                state);
 
         /* Calculate the constant value if this is a const or uniform
          * declaration.
          */
         if (this->type->qualifier.constant || this->type->qualifier.uniform) {
-           ir_constant *constant_value = rhs->constant_expression_value();
-           if (!constant_value) {
-              _mesa_glsl_error(& initializer_loc, state,
-                               "initializer of %s variable `%s' must be a "
-                               "constant expression",
-                               (this->type->qualifier.constant)
-                               ? "const" : "uniform",
-                               decl->identifier);
+           ir_rvalue *new_rhs = validate_assignment(state, var->type, rhs);
+           if (new_rhs != NULL) {
+              rhs = new_rhs;
+
+              ir_constant *constant_value = rhs->constant_expression_value();
+              if (!constant_value) {
+                 _mesa_glsl_error(& initializer_loc, state,
+                                  "initializer of %s variable `%s' must be a "
+                                  "constant expression",
+                                  (this->type->qualifier.constant)
+                                  ? "const" : "uniform",
+                                  decl->identifier);
+                 if (var->type->is_numeric()) {
+                    /* Reduce cascading errors. */
+                    var->constant_value = ir_constant::zero(ctx, var->type);
+                 }
+              } else {
+                 rhs = constant_value;
+                 var->constant_value = constant_value;
+              }
            } else {
-              rhs = constant_value;
-              var->constant_value = constant_value;
+              _mesa_glsl_error(&initializer_loc, state,
+                               "initializer of type %s cannot be assigned to "
+                               "variable of type %s",
+                               rhs->type->name, var->type->name);
+              if (var->type->is_numeric()) {
+                 /* Reduce cascading errors. */
+                 var->constant_value = ir_constant::zero(ctx, var->type);
+              }
            }
         }
 
@@ -1829,7 +1933,8 @@ ast_declarator_list::hir(exec_list *instructions,
            /* Never emit code to initialize a uniform.
             */
            if (!this->type->qualifier.uniform)
-              result = do_assignment(instructions, state, lhs, rhs,
+              result = do_assignment(&initializer_instructions, state,
+                                     lhs, rhs,
                                      this->get_location());
            var->read_only = temp;
         }
@@ -1846,22 +1951,23 @@ ast_declarator_list::hir(exec_list *instructions,
                          "const declaration of `%s' must be initialized");
       }
 
-      /* Attempt to add the variable to the symbol table.  If this fails, it
-       * means the variable has already been declared at this scope.  Arrays
-       * fudge this rule a little bit.
+      /* Check if this declaration is actually a re-declaration, either to
+       * resize an array or add qualifiers to an existing variable.
        *
-       * From page 24 (page 30 of the PDF) of the GLSL 1.50 spec,
-       *
-       *    "It is legal to declare an array without a size and then
-       *    later re-declare the same name as an array of the same
-       *    type and specify a size."
+       * This is allowed for variables in the current scope, or when at
+       * global scope (for built-ins in the implicit outer scope).
        */
-      if (state->symbols->name_declared_this_scope(decl->identifier)) {
-        ir_variable *const earlier =
-           state->symbols->get_variable(decl->identifier);
+      ir_variable *earlier = state->symbols->get_variable(decl->identifier);
+      if (earlier != NULL && (state->current_function == NULL ||
+         state->symbols->name_declared_this_scope(decl->identifier))) {
 
-        if ((earlier != NULL)
-            && (earlier->type->array_size() == 0)
+        /* From page 24 (page 30 of the PDF) of the GLSL 1.50 spec,
+         *
+         * "It is legal to declare an array without a size and then
+         *  later re-declare the same name as an array of the same
+         *  type and specify a size."
+         */
+        if ((earlier->type->array_size() == 0)
             && var->type->is_array()
             && (var->type->element_type() == earlier->type->element_type())) {
            /* FINISHME: This doesn't match the qualifiers on the two
@@ -1893,34 +1999,41 @@ ast_declarator_list::hir(exec_list *instructions,
            earlier->type = var->type;
            delete var;
            var = NULL;
+        } else if (state->extensions->ARB_fragment_coord_conventions
+                   && strcmp(var->name, "gl_FragCoord") == 0
+                   && earlier->type == var->type
+                   && earlier->mode == var->mode) {
+           /* Allow redeclaration of gl_FragCoord for ARB_fcc layout
+            * qualifiers.
+            */
+           earlier->origin_upper_left = var->origin_upper_left;
+           earlier->pixel_center_integer = var->pixel_center_integer;
         } else {
            YYLTYPE loc = this->get_location();
-
-           _mesa_glsl_error(& loc, state, "`%s' redeclared",
-                            decl->identifier);
+           _mesa_glsl_error(&loc, state, "`%s' redeclared", decl->identifier);
         }
 
         continue;
       }
 
-      /* From page 15 (page 21 of the PDF) of the GLSL 1.10 spec,
+      /* By now, we know it's a new variable declaration (we didn't hit the
+       * above "continue").
+       *
+       * From page 15 (page 21 of the PDF) of the GLSL 1.10 spec,
        *
        *   "Identifiers starting with "gl_" are reserved for use by
        *   OpenGL, and may not be declared in a shader as either a
        *   variable or a function."
        */
-      if (strncmp(decl->identifier, "gl_", 3) == 0) {
-        /* FINISHME: This should only trigger if we're not redefining
-         * FINISHME: a builtin (to add a qualifier, for example).
-         */
+      if (strncmp(decl->identifier, "gl_", 3) == 0)
         _mesa_glsl_error(& loc, state,
                          "identifier `%s' uses reserved `gl_' prefix",
                          decl->identifier);
-      }
 
-      instructions->push_tail(var);
-
-      /* Add the variable to the symbol table after processing the initializer.
+      /* Add the variable to the symbol table.  Note that the initializer's
+       * IR was already processed earlier (though it hasn't been emitted yet),
+       * without the variable in scope.
+       *
        * This differs from most C-like languages, but it follows the GLSL
        * specification.  From page 28 (page 34 of the PDF) of the GLSL 1.50
        * spec:
@@ -1929,9 +2042,22 @@ ast_declarator_list::hir(exec_list *instructions,
        *     after the initializer if present or immediately after the name
        *     being declared if not."
        */
-      const bool added_variable =
-        state->symbols->add_variable(var->name, var);
-      assert(added_variable);
+      if (!state->symbols->add_variable(var->name, var)) {
+        YYLTYPE loc = this->get_location();
+        _mesa_glsl_error(&loc, state, "name `%s' already taken in the "
+                         "current scope", decl->identifier);
+        continue;
+      }
+
+      /* Push the variable declaration to the top.  It means that all
+       * the variable declarations will appear in a funny
+       * last-to-first order, but otherwise we run into trouble if a
+       * function is prototyped, a global var is decled, then the
+       * function is defined with usage of the global var.  See
+       * glslparsertest's CorrectModule.frag.
+       */
+      instructions->push_head(var);
+      instructions->append_list(&initializer_instructions);
    }
 
 
@@ -1999,19 +2125,26 @@ ast_parameter_declarator::hir(exec_list *instructions,
       return NULL;
    }
 
-   is_void = false;
-   ir_variable *var = new(ctx) ir_variable(type, this->identifier);
-
-   /* FINISHME: Handle array declarations.  Note that this requires
-    * FINISHME: complete handling of constant expressions.
+   /* This only handles "vec4 foo[..]".  The earlier specifier->glsl_type(...)
+    * call already handled the "vec4[..] foo" case.
     */
+   if (this->is_array) {
+      type = process_array_type(type, this->array_size, state);
+   }
+
+   if (type->array_size() == 0) {
+      _mesa_glsl_error(&loc, state, "arrays passed as parameters must have "
+                      "a declared size.");
+      type = glsl_type::error_type;
+   }
+
+   is_void = false;
+   ir_variable *var = new(ctx) ir_variable(type, this->identifier, ir_var_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);
-   if (var->mode == ir_var_auto)
-      var->mode = ir_var_in;
 
    instructions->push_tail(var);
 
@@ -2060,6 +2193,37 @@ ast_function::hir(exec_list *instructions,
 
    const char *const name = identifier;
 
+   /* From page 21 (page 27 of the PDF) of the GLSL 1.20 spec,
+    *
+    *   "Function declarations (prototypes) cannot occur inside of functions;
+    *   they must be at global scope, or for the built-in functions, outside
+    *   the global scope."
+    *
+    * From page 27 (page 33 of the PDF) of the GLSL ES 1.00.16 spec,
+    *
+    *   "User defined functions may only be defined within the global scope."
+    *
+    * Note that this language does not appear in GLSL 1.10.
+    */
+   if ((state->current_function != NULL) && (state->language_version != 110)) {
+      YYLTYPE loc = this->get_location();
+      _mesa_glsl_error(&loc, state,
+                      "declaration of function `%s' not allowed within "
+                      "function body", name);
+   }
+
+   /* From page 15 (page 21 of the PDF) of the GLSL 1.10 spec,
+    *
+    *   "Identifiers starting with "gl_" are reserved for use by
+    *   OpenGL, and may not be declared in a shader as either a
+    *   variable or a function."
+    */
+   if (strncmp(name, "gl_", 3) == 0) {
+      YYLTYPE loc = this->get_location();
+      _mesa_glsl_error(&loc, state,
+                      "identifier `%s' uses reserved `gl_' prefix", name);
+   }
+
    /* Convert the list of function parameters to HIR now so that they can be
     * used below to compare this function's signature with previously seen
     * signatures for functions with the same name.
@@ -2072,7 +2236,13 @@ ast_function::hir(exec_list *instructions,
    const glsl_type *return_type =
       this->return_type->specifier->glsl_type(& return_type_name, state);
 
-   assert(return_type != NULL);
+   if (!return_type) {
+      YYLTYPE loc = this->get_location();
+      _mesa_glsl_error(&loc, state,
+                      "function `%s' has undeclared return type `%s'",
+                      name, return_type_name);
+      return_type = glsl_type::error_type;
+   }
 
    /* From page 56 (page 62 of the PDF) of the GLSL 1.30 spec:
     * "No qualifier is allowed on the return type of a function."
@@ -2088,8 +2258,8 @@ ast_function::hir(exec_list *instructions,
     * that the previously seen signature does not have an associated definition.
     */
    f = state->symbols->get_function(name);
-   if (f != NULL) {
-      ir_function_signature *sig = f->exact_matching_signature(&hir_parameters);
+   if (f != NULL && !f->is_builtin) {
+      sig = f->exact_matching_signature(&hir_parameters);
       if (sig != NULL) {
         const char *badvar = sig->qualifiers_match(&hir_parameters);
         if (badvar != NULL) {
@@ -2110,23 +2280,37 @@ ast_function::hir(exec_list *instructions,
            YYLTYPE loc = this->get_location();
 
            _mesa_glsl_error(& loc, state, "function `%s' redefined", name);
-           sig = NULL;
         }
       }
-   } else if (state->symbols->name_declared_this_scope(name)) {
-      /* 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);
-      sig = NULL;
    } else {
       f = new(ctx) ir_function(name);
-      state->symbols->add_function(f->name, f);
+      if (!state->symbols->add_function(f->name, 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 the new function header */
-      instructions->push_tail(f);
+      if (state->current_function == NULL)
+        instructions->push_tail(f);
+      else {
+        /* IR invariants disallow function declarations or definitions nested
+         * within other function definitions.  Insert the new ir_function
+         * block in the instruction sequence before the ir_function block
+         * containing the current ir_function_signature.
+         *
+         * This can only happen in a GLSL 1.10 shader.  In all other GLSL
+         * versions this nesting is disallowed.  There is a check for this at
+         * the top of this function.
+         */
+        ir_function *const curr =
+           const_cast<ir_function *>(state->current_function->function());
+
+        curr->insert_before(f);
+      }
    }
 
    /* Verify the return type of main() */
@@ -2168,6 +2352,8 @@ ast_function_definition::hir(exec_list *instructions,
    prototype->hir(instructions, state);
 
    ir_function_signature *signature = prototype->signature;
+   if (signature == NULL)
+      return NULL;
 
    assert(state->current_function == NULL);
    state->current_function = signature;
@@ -2302,6 +2488,16 @@ ast_jump_statement::hir(exec_list *instructions,
       } else {
         ir_loop *const loop = state->loop_or_switch_nesting->as_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 (loop != NULL) {
            ir_loop_jump *const jump =
               new(ctx) ir_loop_jump((mode == ast_break)
@@ -2346,11 +2542,17 @@ ast_selection_statement::hir(exec_list *instructions,
 
    ir_if *const stmt = new(ctx) ir_if(condition);
 
-   if (then_statement != NULL)
+   if (then_statement != NULL) {
+      state->symbols->push_scope();
       then_statement->hir(& stmt->then_instructions, state);
+      state->symbols->pop_scope();
+   }
 
-   if (else_statement != NULL)
+   if (else_statement != NULL) {
+      state->symbols->push_scope();
       else_statement->hir(& stmt->else_instructions, state);
+      state->symbols->pop_scope();
+   }
 
    instructions->push_tail(stmt);
 
@@ -2416,7 +2618,10 @@ ast_iteration_statement::hir(exec_list *instructions,
    /* 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;
+
    state->loop_or_switch_nesting = stmt;
+   state->loop_or_switch_nesting_ast = this;
 
    if (mode != ast_do_while)
       condition_to_hir(stmt, state);
@@ -2436,6 +2641,7 @@ ast_iteration_statement::hir(exec_list *instructions,
    /* Restore previous nesting before returning.
     */
    state->loop_or_switch_nesting = nesting;
+   state->loop_or_switch_nesting_ast = nesting_ast;
 
    /* Loops do not have r-values.
     */
@@ -2478,8 +2684,8 @@ ast_struct_specifier::hir(exec_list *instructions,
     * the types to HIR.  This ensures that structure definitions embedded in
     * other structure definitions are processed.
     */
-   glsl_struct_field *const fields = (glsl_struct_field *)
-      malloc(sizeof(*fields) * decl_count);
+   glsl_struct_field *const fields = talloc_array(state, glsl_struct_field,
+                                                 decl_count);
 
    unsigned i = 0;
    foreach_list_typed (ast_declarator_list, decl_list, link,
@@ -2527,15 +2733,6 @@ ast_struct_specifier::hir(exec_list *instructions,
    if (!state->symbols->add_type(name, t)) {
       _mesa_glsl_error(& loc, state, "struct `%s' previously defined", name);
    } else {
-      /* This logic is a bit tricky.  It is an error to declare a structure at
-       * global scope if there is also a function with the same name.
-       */
-      if ((state->current_function == NULL)
-         && (state->symbols->get_function(name) != NULL)) {
-        _mesa_glsl_error(& loc, state, "name `%s' previously defined", name);
-      } else {
-        t->generate_constructor(state->symbols);
-      }
 
       const glsl_type **s = (const glsl_type **)
         realloc(state->user_structures,