Attach a pointer to variable names in LIR dumping.
[mesa.git] / ast_to_hir.cpp
index 704f2745a74d0745114a786f8be0aa24cee438f9..25bbe2f2defa9c1ea143168b9788b43cc98be13a 100644 (file)
@@ -48,7 +48,7 @@
  * As a result, my preference is to put as little C code as possible in the
  * parser (and lexer) sources.
  */
-#include <stdio.h>
+
 #include "main/imports.h"
 #include "glsl_symbol_table.h"
 #include "glsl_parser_extras.h"
 void
 _mesa_ast_to_hir(exec_list *instructions, struct _mesa_glsl_parse_state *state)
 {
-   struct simple_node *ptr;
-
    _mesa_glsl_initialize_variables(instructions, state);
    _mesa_glsl_initialize_constructors(instructions, state);
    _mesa_glsl_initialize_functions(instructions, state);
 
    state->current_function = NULL;
 
-   foreach (ptr, & state->translation_unit) {
-      ((ast_node *)ptr)->hir(instructions, state);
-   }
+   foreach_list_typed (ast_node, ast, link, & state->translation_unit)
+      ast->hir(instructions, state);
 }
 
 
@@ -135,8 +132,8 @@ arithmetic_result_type(ir_rvalue * &value_a, ir_rvalue * &value_b,
                       bool multiply,
                       struct _mesa_glsl_parse_state *state, YYLTYPE *loc)
 {
-   const glsl_type *const type_a = value_a->type;
-   const glsl_type *const type_b = value_b->type;
+   const glsl_type *type_a = value_a->type;
+   const glsl_type *type_b = value_b->type;
 
    /* From GLSL 1.50 spec, page 56:
     *
@@ -162,7 +159,9 @@ arithmetic_result_type(ir_rvalue * &value_a, ir_rvalue * &value_b,
                       "arithmetic operator");
       return glsl_type::error_type;
    }
-      
+   type_a = value_a->type;
+   type_b = value_b->type;
+
    /*    "If the operands are integer types, they must both be signed or
     *    both be unsigned."
     *
@@ -365,8 +364,8 @@ static const struct glsl_type *
 relational_result_type(ir_rvalue * &value_a, ir_rvalue * &value_b,
                       struct _mesa_glsl_parse_state *state, YYLTYPE *loc)
 {
-   const glsl_type *const type_a = value_a->type;
-   const glsl_type *const type_b = value_b->type;
+   const glsl_type *type_a = value_a->type;
+   const glsl_type *type_b = value_b->type;
 
    /* From GLSL 1.50 spec, page 56:
     *    "The relational operators greater than (>), less than (<), greater
@@ -394,6 +393,8 @@ relational_result_type(ir_rvalue * &value_a, ir_rvalue * &value_b,
                       "relational operator");
       return glsl_type::error_type;
    }
+   type_a = value_a->type;
+   type_b = value_b->type;
 
    if (type_a->base_type != type_b->base_type) {
       _mesa_glsl_error(loc, state, "base type mismatch");
@@ -423,9 +424,10 @@ relational_result_type(ir_rvalue * &value_a, ir_rvalue * &value_b,
  * type-check return values.
  */
 ir_rvalue *
-validate_assignment(const glsl_type *lhs_type, ir_rvalue *rhs)
+validate_assignment(struct _mesa_glsl_parse_state *state,
+                   const glsl_type *lhs_type, ir_rvalue *rhs)
 {
-   const glsl_type *const rhs_type = rhs->type;
+   const glsl_type *rhs_type = rhs->type;
 
    /* If there is already some error in the RHS, just return it.  Anything
     * else will lead to an avalanche of error message back to the user.
@@ -450,7 +452,13 @@ validate_assignment(const glsl_type *lhs_type, ir_rvalue *rhs)
       return rhs;
    }
 
-   /* FINISHME: Check for and apply automatic conversions. */
+   /* Check for implicit conversion in GLSL 1.20 */
+   if (apply_implicit_conversion(lhs_type, rhs, state)) {
+      rhs_type = rhs->type;
+      if (rhs_type == lhs_type)
+        return rhs;
+   }
+
    return NULL;
 }
 
@@ -469,7 +477,7 @@ do_assignment(exec_list *instructions, struct _mesa_glsl_parse_state *state,
       }
    }
 
-   ir_rvalue *new_rhs = validate_assignment(lhs->type, rhs);
+   ir_rvalue *new_rhs = validate_assignment(state, lhs->type, rhs);
    if (new_rhs == NULL) {
       _mesa_glsl_error(& lhs_loc, state, "type mismatch");
    } else {
@@ -485,7 +493,7 @@ do_assignment(exec_list *instructions, struct _mesa_glsl_parse_state *state,
 
         assert(d != NULL);
 
-        ir_variable *const var = d->var->as_variable();
+        ir_variable *const var = d->variable_referenced();
 
         assert(var != NULL);
 
@@ -501,10 +509,27 @@ do_assignment(exec_list *instructions, struct _mesa_glsl_parse_state *state,
       }
    }
 
-   ir_instruction *tmp = new ir_assignment(lhs, rhs, NULL);
-   instructions->push_tail(tmp);
+   /* Most callers of do_assignment (assign, add_assign, pre_inc/dec,
+    * but not post_inc) need the converted assigned value as an rvalue
+    * to handle things like:
+    *
+    * i = j += 1;
+    *
+    * So we always just store the computed value being assigned to a
+    * 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 ir_variable(rhs->type, "assignment_tmp");
+   instructions->push_tail(var);
+   instructions->push_tail(new ir_assignment(new ir_dereference_variable(var),
+                                            rhs,
+                                            NULL));
 
-   return rhs;
+   instructions->push_tail(new ir_assignment(lhs,
+                                            new ir_dereference_variable(var),
+                                            NULL));
+
+   return new ir_dereference_variable(var);
 }
 
 
@@ -528,25 +553,23 @@ generate_temporary(const glsl_type *type, exec_list *instructions,
 
 
 static ir_rvalue *
-get_lvalue_copy(exec_list *instructions, struct _mesa_glsl_parse_state *state,
-               ir_rvalue *lvalue, YYLTYPE loc)
+get_lvalue_copy(exec_list *instructions, ir_rvalue *lvalue)
 {
    ir_variable *var;
-   ir_rvalue *var_deref;
 
    /* FINISHME: Give unique names to the temporaries. */
-   var = new ir_variable(lvalue->type, "_internal_tmp");
+   var = new ir_variable(lvalue->type, "_post_incdec_tmp");
    var->mode = ir_var_auto;
 
-   var_deref = new ir_dereference(var);
-   do_assignment(instructions, state, var_deref, lvalue, loc);
+   instructions->push_tail(new ir_assignment(new 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;
 
-   return var_deref;
+   return new ir_dereference_variable(var);
 }
 
 
@@ -622,13 +645,11 @@ ast_expression::hir(exec_list *instructions,
    };
    ir_rvalue *result = NULL;
    ir_rvalue *op[2];
-   struct simple_node op_list;
    const struct glsl_type *type = glsl_type::error_type;
    bool error_emitted = false;
    YYLTYPE loc;
 
    loc = this->get_location();
-   make_empty_list(& op_list);
 
    switch (this->oper) {
    case ast_assign: {
@@ -808,17 +829,17 @@ ast_expression::hir(exec_list *instructions,
         ir_variable *const tmp = generate_temporary(glsl_type::bool_type,
                                                     instructions, state);
 
-        ir_dereference *const then_deref = new ir_dereference(tmp);
+        ir_dereference *const then_deref = new ir_dereference_variable(tmp);
         ir_assignment *const then_assign =
            new ir_assignment(then_deref, op[1], NULL);
         stmt->then_instructions.push_tail(then_assign);
 
-        ir_dereference *const else_deref = new ir_dereference(tmp);
+        ir_dereference *const else_deref = new ir_dereference_variable(tmp);
         ir_assignment *const else_assign =
            new ir_assignment(else_deref, new ir_constant(false), NULL);
         stmt->else_instructions.push_tail(else_assign);
 
-        result = new ir_dereference(tmp);
+        result = new ir_dereference_variable(tmp);
         type = tmp->type;
       }
       break;
@@ -870,17 +891,17 @@ ast_expression::hir(exec_list *instructions,
            error_emitted = true;
         }
 
-        ir_dereference *const then_deref = new ir_dereference(tmp);
+        ir_dereference *const then_deref = new ir_dereference_variable(tmp);
         ir_assignment *const then_assign =
            new ir_assignment(then_deref, new ir_constant(true), NULL);
         stmt->then_instructions.push_tail(then_assign);
 
-        ir_dereference *const else_deref = new ir_dereference(tmp);
+        ir_dereference *const else_deref = new ir_dereference_variable(tmp);
         ir_assignment *const else_assign =
            new ir_assignment(else_deref, op[1], NULL);
         stmt->else_instructions.push_tail(else_assign);
 
-        result = new ir_dereference(tmp);
+        result = new ir_dereference_variable(tmp);
         type = tmp->type;
       }
       break;
@@ -926,7 +947,8 @@ ast_expression::hir(exec_list *instructions,
       ir_rvalue *temp_rhs = new ir_expression(operations[this->oper], type,
                                              op[0], op[1]);
 
-      result = do_assignment(instructions, state, op[0], temp_rhs,
+      result = do_assignment(instructions, state,
+                            (ir_rvalue *)op[0]->clone(NULL), temp_rhs,
                             this->subexpressions[0]->get_location());
       type = result->type;
       error_emitted = (op[0]->type->is_error());
@@ -951,7 +973,8 @@ ast_expression::hir(exec_list *instructions,
       temp_rhs = new ir_expression(operations[this->oper], type,
                                   op[0], op[1]);
 
-      result = do_assignment(instructions, state, op[0], temp_rhs,
+      result = do_assignment(instructions, state,
+                            (ir_rvalue *)op[0]->clone(NULL), temp_rhs,
                             this->subexpressions[0]->get_location());
       type = result->type;
       error_emitted = type->is_error();
@@ -994,23 +1017,11 @@ ast_expression::hir(exec_list *instructions,
        * the if-statement assigns a value to the anonymous temporary.  This
        * temporary is the r-value of the expression.
        */
-      ir_variable *const tmp = generate_temporary(glsl_type::error_type,
-                                                 instructions, state);
-
-      ir_if *const stmt = new ir_if(op[0]);
-      instructions->push_tail(stmt);
-
-      op[1] = this->subexpressions[1]->hir(& stmt->then_instructions, state);
-      ir_dereference *const then_deref = new ir_dereference(tmp);
-      ir_assignment *const then_assign =
-        new ir_assignment(then_deref, op[1], NULL);
-      stmt->then_instructions.push_tail(then_assign);
+      exec_list then_instructions;
+      exec_list else_instructions;
 
-      op[2] = this->subexpressions[2]->hir(& stmt->else_instructions, state);
-      ir_dereference *const else_deref = new ir_dereference(tmp);
-      ir_assignment *const else_assign =
-        new ir_assignment(else_deref, op[2], NULL);
-      stmt->else_instructions.push_tail(else_assign);
+      op[1] = this->subexpressions[1]->hir(&then_instructions, state);
+      op[2] = this->subexpressions[2]->hir(&else_instructions, state);
 
       /* From page 59 (page 65 of the PDF) of the GLSL 1.50 spec:
        *
@@ -1029,12 +1040,40 @@ ast_expression::hir(exec_list *instructions,
         _mesa_glsl_error(& loc, state, "Second and third operands of ?: "
                          "operator must have matching types.");
         error_emitted = true;
+        type = glsl_type::error_type;
       } else {
-        tmp->type = op[1]->type;
+        type = op[1]->type;
       }
 
-      result = new ir_dereference(tmp);
-      type = tmp->type;
+      ir_constant *cond_val = op[0]->constant_expression_value();
+      ir_constant *then_val = op[1]->constant_expression_value();
+      ir_constant *else_val = op[2]->constant_expression_value();
+
+      if (then_instructions.is_empty()
+         && else_instructions.is_empty()
+         && (cond_val != NULL) && (then_val != NULL) && (else_val != NULL)) {
+        result = (cond_val->value.b[0]) ? then_val : else_val;
+      } else {
+        ir_variable *const tmp = generate_temporary(type,
+                                                    instructions, state);
+
+        ir_if *const stmt = new ir_if(op[0]);
+        instructions->push_tail(stmt);
+
+        then_instructions.move_nodes_to(& stmt->then_instructions);
+        ir_dereference *const then_deref = new ir_dereference_variable(tmp);
+        ir_assignment *const then_assign =
+           new ir_assignment(then_deref, op[1], NULL);
+        stmt->then_instructions.push_tail(then_assign);
+
+        else_instructions.move_nodes_to(& stmt->else_instructions);
+        ir_dereference *const else_deref = new ir_dereference_variable(tmp);
+        ir_assignment *const else_assign =
+           new ir_assignment(else_deref, op[2], NULL);
+        stmt->else_instructions.push_tail(else_assign);
+
+        result = new ir_dereference_variable(tmp);
+      }
       break;
    }
 
@@ -1052,7 +1091,8 @@ ast_expression::hir(exec_list *instructions,
       temp_rhs = new ir_expression(operations[this->oper], type,
                                   op[0], op[1]);
 
-      result = do_assignment(instructions, state, op[0], temp_rhs,
+      result = do_assignment(instructions, state,
+                            (ir_rvalue *)op[0]->clone(NULL), temp_rhs,
                             this->subexpressions[0]->get_location());
       type = result->type;
       error_emitted = op[0]->type->is_error();
@@ -1078,10 +1118,10 @@ ast_expression::hir(exec_list *instructions,
       /* Get a temporary of a copy of the lvalue before it's modified.
        * This may get thrown away later.
        */
-      result = get_lvalue_copy(instructions, state, op[0],
-                              this->subexpressions[0]->get_location());
+      result = get_lvalue_copy(instructions, (ir_rvalue *)op[0]->clone(NULL));
 
-      (void)do_assignment(instructions, state, op[0], temp_rhs,
+      (void)do_assignment(instructions, state,
+                         (ir_rvalue *)op[0]->clone(NULL), temp_rhs,
                          this->subexpressions[0]->get_location());
 
       type = result->type;
@@ -1102,18 +1142,9 @@ ast_expression::hir(exec_list *instructions,
 
       error_emitted = op[0]->type->is_error() || op[1]->type->is_error();
 
-      ir_dereference *const lhs = op[0]->as_dereference();
-      ir_instruction *array;
-      if ((lhs != NULL)
-         && (lhs->mode == ir_dereference::ir_reference_variable)) {
-        result = new ir_dereference(lhs->var, op[1]);
+      ir_rvalue *const array = op[0];
 
-        delete op[0];
-        array = lhs->var;
-      } else {
-        result = new ir_dereference(op[0], op[1]);
-        array = op[0];
-      }
+      result = new ir_dereference_array(op[0], op[1]);
 
       /* Do not use op[0] after this point.  Use array.
        */
@@ -1195,7 +1226,13 @@ ast_expression::hir(exec_list *instructions,
         }
 
         if (array->type->is_array()) {
-           ir_variable *const v = array->as_variable();
+           /* If the array is a variable dereference, it dereferences the
+            * whole array, by definition.  Use this to get the variable.
+            *
+            * FINISHME: Should some methods for getting / setting / testing
+            * FINISHME: array access limits be added to ir_dereference?
+            */
+           ir_variable *const v = array->whole_variable_referenced();
            if ((v != NULL) && (unsigned(idx) > v->max_array_access))
               v->max_array_access = idx;
         }
@@ -1223,7 +1260,7 @@ ast_expression::hir(exec_list *instructions,
       ir_variable *var = 
         state->symbols->get_variable(this->primary_expression.identifier);
 
-      result = new ir_dereference(var);
+      result = new ir_dereference_variable(var);
 
       if (var != NULL) {
         type = result->type;
@@ -1238,39 +1275,37 @@ ast_expression::hir(exec_list *instructions,
 
    case ast_int_constant:
       type = glsl_type::int_type;
-      result = new ir_constant(type, & this->primary_expression);
+      result = new ir_constant(this->primary_expression.int_constant);
       break;
 
    case ast_uint_constant:
       type = glsl_type::uint_type;
-      result = new ir_constant(type, & this->primary_expression);
+      result = new ir_constant(this->primary_expression.uint_constant);
       break;
 
    case ast_float_constant:
       type = glsl_type::float_type;
-      result = new ir_constant(type, & this->primary_expression);
+      result = new ir_constant(this->primary_expression.float_constant);
       break;
 
    case ast_bool_constant:
       type = glsl_type::bool_type;
-      result = new ir_constant(type, & this->primary_expression);
+      result = new ir_constant(bool(this->primary_expression.bool_constant));
       break;
 
    case ast_sequence: {
-      struct simple_node *ptr;
-
       /* It should not be possible to generate a sequence in the AST without
        * any expressions in it.
        */
-      assert(!is_empty_list(&this->expressions));
+      assert(!this->expressions.is_empty());
 
       /* The r-value of a sequence is the last expression in the sequence.  If
        * the other expressions in the sequence do not have side-effects (and
        * therefore add instructions to the instruction list), they get dropped
        * on the floor.
        */
-      foreach (ptr, &this->expressions)
-        result = ((ast_node *)ptr)->hir(instructions, state);
+      foreach_list_typed (ast_node, ast, link, &this->expressions)
+        result = ast->hir(instructions, state);
 
       type = result->type;
 
@@ -1314,14 +1349,11 @@ ir_rvalue *
 ast_compound_statement::hir(exec_list *instructions,
                            struct _mesa_glsl_parse_state *state)
 {
-   struct simple_node *ptr;
-
-
    if (new_scope)
       state->symbols->push_scope();
 
-   foreach (ptr, &statements)
-      ((ast_node *)ptr)->hir(instructions, state);
+   foreach_list_typed (ast_node, ast, link, &this->statements)
+      ast->hir(instructions, state);
 
    if (new_scope)
       state->symbols->pop_scope();
@@ -1428,10 +1460,19 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual,
     *     float, vec2, vec3, vec4, mat2, mat3, and mat4, or arrays of
     *     these."
     */
-   if (qual->varying && var->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 (qual->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 (qual->in && qual->out)
@@ -1448,11 +1489,27 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual,
 
    if (qual->uniform)
       var->shader_in = true;
-   if (qual->varying) {
-      if (qual->in)
+
+   /* 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;
-      if (qual->out)
+        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)
@@ -1472,10 +1529,10 @@ ir_rvalue *
 ast_declarator_list::hir(exec_list *instructions,
                         struct _mesa_glsl_parse_state *state)
 {
-   struct simple_node *ptr;
    const struct glsl_type *decl_type;
    const char *type_name = NULL;
    ir_rvalue *result = NULL;
+   YYLTYPE loc = this->get_location();
 
    /* The type specifier may contain a structure definition.  Process that
     * before any of the variable declarations.
@@ -1488,12 +1545,26 @@ ast_declarator_list::hir(exec_list *instructions,
     */
 
    decl_type = this->type->specifier->glsl_type(& type_name, state);
+   if (this->declarations.is_empty()) {
+      /* There are only two valid cases where the declaration list can be
+       * empty.
+       *
+       * 1. The declaration is setting the default precision of a built-in
+       *    type (e.g., 'precision highp vec4;').
+       *
+       * 2. Adding 'invariant' to an existing vertex shader output.
+       */
 
-   foreach (ptr, &this->declarations) {
-      struct ast_declaration *const decl = (struct ast_declaration * )ptr;
+      if (this->type->qualifier.invariant) {
+      } else if (decl_type != NULL) {
+      } else {
+           _mesa_glsl_error(& loc, state, "incomplete declaration");
+      }
+   }
+
+   foreach_list_typed (ast_declaration, decl, link, &this->declarations) {
       const struct glsl_type *var_type;
       struct ir_variable *var;
-      YYLTYPE loc = this->get_location();
 
       /* FINISHME: Emit a warning if a variable declaration shadows a
        * FINISHME: declaration at a higher scope.
@@ -1718,18 +1789,20 @@ ast_declarator_list::hir(exec_list *instructions,
                             ? "attribute" : "varying");
         }
 
-        ir_dereference *const lhs = new ir_dereference(var);
+        ir_dereference *const lhs = new ir_dereference_variable(var);
         ir_rvalue *rhs = decl->initializer->hir(instructions, state);
 
-        /* Calculate the constant value if this is a const
+        /* Calculate the constant value if this is a const or uniform
          * declaration.
          */
-        if (this->type->qualifier.constant) {
+        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 const variable `%s' must be a "
+                               "initializer of %s variable `%s' must be a "
                                "constant expression",
+                               (this->type->qualifier.constant)
+                               ? "const" : "uniform",
                                decl->identifier);
            } else {
               rhs = constant_value;
@@ -1741,8 +1814,12 @@ ast_declarator_list::hir(exec_list *instructions,
            bool temp = var->read_only;
            if (this->type->qualifier.constant)
               var->read_only = false;
-           result = do_assignment(instructions, state, lhs, rhs,
-                                  this->get_location());
+
+           /* Never emit code to initialize a uniform.
+            */
+           if (!this->type->qualifier.uniform)
+              result = do_assignment(instructions, state, lhs, rhs,
+                                     this->get_location());
            var->read_only = temp;
         }
       }
@@ -1859,17 +1936,15 @@ ast_parameter_declarator::hir(exec_list *instructions,
 
 
 void
-ast_parameter_declarator::parameters_to_hir(struct simple_node *ast_parameters,
+ast_parameter_declarator::parameters_to_hir(exec_list *ast_parameters,
                                            bool formal,
                                            exec_list *ir_parameters,
                                            _mesa_glsl_parse_state *state)
 {
-   struct simple_node *ptr;
    ast_parameter_declarator *void_param = NULL;
    unsigned count = 0;
 
-   foreach (ptr, ast_parameters) {
-      ast_parameter_declarator *param = (ast_parameter_declarator *)ptr;
+   foreach_list_typed (ast_parameter_declarator, param, link, ast_parameters) {
       param->formal_parameter = formal;
       param->hir(ir_parameters, state);
 
@@ -2114,8 +2189,7 @@ ast_jump_statement::hir(exec_list *instructions,
 
         if (loop != NULL) {
            ir_loop_jump *const jump =
-              new ir_loop_jump(loop,
-                               (mode == ast_break)
+              new ir_loop_jump((mode == ast_break)
                                ? ir_loop_jump::jump_break
                                : ir_loop_jump::jump_continue);
            instructions->push_tail(jump);
@@ -2155,21 +2229,11 @@ ast_selection_statement::hir(exec_list *instructions,
 
    ir_if *const stmt = new ir_if(condition);
 
-   if (then_statement != NULL) {
-      ast_node *node = (ast_node *) then_statement;
-      do {
-        node->hir(& stmt->then_instructions, state);
-        node = (ast_node *) node->next;
-      } while (node != then_statement);
-   }
+   if (then_statement != NULL)
+      then_statement->hir(& stmt->then_instructions, state);
 
-   if (else_statement != NULL) {
-      ast_node *node = (ast_node *) else_statement;
-      do {
-        node->hir(& stmt->else_instructions, state);
-        node = (ast_node *) node->next;
-      } while (node != else_statement);
-   }
+   if (else_statement != NULL)
+      else_statement->hir(& stmt->else_instructions, state);
 
    instructions->push_tail(stmt);
 
@@ -2204,7 +2268,7 @@ ast_iteration_statement::condition_to_hir(ir_loop *stmt,
         ir_if *const if_stmt = new ir_if(not_cond);
 
         ir_jump *const break_stmt =
-           new ir_loop_jump(stmt, ir_loop_jump::jump_break);
+           new ir_loop_jump(ir_loop_jump::jump_break);
 
         if_stmt->then_instructions.push_tail(break_stmt);
         stmt->body_instructions.push_tail(if_stmt);
@@ -2236,13 +2300,8 @@ ast_iteration_statement::hir(exec_list *instructions,
    if (mode != ast_do_while)
       condition_to_hir(stmt, state);
 
-   if (body != NULL) {
-      ast_node *node = (ast_node *) body;
-      do {
-        node->hir(& stmt->body_instructions, state);
-        node = (ast_node *) node->next;
-      } while (node != body);
-   }
+   if (body != NULL)
+      body->hir(& stmt->body_instructions, state);
 
    if (rest_expression != NULL)
       rest_expression->hir(& stmt->body_instructions, state);
@@ -2278,7 +2337,6 @@ ir_rvalue *
 ast_struct_specifier::hir(exec_list *instructions,
                          struct _mesa_glsl_parse_state *state)
 {
-   simple_node *ptr;
    unsigned decl_count = 0;
 
    /* Make an initial pass over the list of structure fields to determine how
@@ -2286,11 +2344,9 @@ ast_struct_specifier::hir(exec_list *instructions,
     * This means that we actually need to count the number of elements in the
     * 'declarations' list in each of the elements.
     */
-   foreach (ptr, & this->declarations) {
-      ast_declarator_list *decl_list = (ast_declarator_list *) ptr;
-      simple_node *decl_ptr;
-
-      foreach (decl_ptr, & decl_list->declarations) {
+   foreach_list_typed (ast_declarator_list, decl_list, link,
+                      &this->declarations) {
+      foreach_list_const (decl_ptr, & decl_list->declarations) {
         decl_count++;
       }
    }
@@ -2305,9 +2361,8 @@ ast_struct_specifier::hir(exec_list *instructions,
       malloc(sizeof(*fields) * decl_count);
 
    unsigned i = 0;
-   foreach (ptr, & this->declarations) {
-      ast_declarator_list *decl_list = (ast_declarator_list *) ptr;
-      simple_node *decl_ptr;
+   foreach_list_typed (ast_declarator_list, decl_list, link,
+                      &this->declarations) {
       const char *type_name;
 
       decl_list->type->specifier->hir(instructions, state);
@@ -2315,8 +2370,8 @@ ast_struct_specifier::hir(exec_list *instructions,
       const glsl_type *decl_type =
         decl_list->type->specifier->glsl_type(& type_name, state);
 
-      foreach (decl_ptr, & decl_list->declarations) {
-        ast_declaration *const decl = (ast_declaration *) decl_ptr;
+      foreach_list_typed (ast_declaration, decl, link,
+                         &decl_list->declarations) {
         const struct glsl_type *const field_type =
            (decl->is_array)
            ? process_array_type(decl_type, decl->array_size, state)
@@ -2346,7 +2401,30 @@ ast_struct_specifier::hir(exec_list *instructions,
 
    glsl_type *t = new glsl_type(fields, decl_count, name);
 
-   state->symbols->add_type(name, t);
+   YYLTYPE loc = this->get_location();
+   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,
+                sizeof(state->user_structures[0]) *
+                (state->num_user_structures + 1));
+      if (s != NULL) {
+        s[state->num_user_structures] = t;
+        state->user_structures = s;
+        state->num_user_structures++;
+      }
+   }
 
    /* Structure type definitions do not have r-values.
     */