Rename .cc files to .cpp
authorIan Romanick <ian.d.romanick@intel.com>
Tue, 23 Feb 2010 02:43:08 +0000 (18:43 -0800)
committerIan Romanick <ian.d.romanick@intel.com>
Tue, 23 Feb 2010 02:43:08 +0000 (18:43 -0800)
Makefile
ast_to_hir.cc [deleted file]
ast_to_hir.cpp [new file with mode: 0644]
glsl_parser_extras.cc [deleted file]
glsl_parser_extras.cpp [new file with mode: 0644]
hir_field_selection.cc [deleted file]
hir_field_selection.cpp [new file with mode: 0644]
ir.cc [deleted file]
ir.cpp [new file with mode: 0644]

index 2f2142ed131f7186b7dacbdf9785cc591aeb7f8f..0d9017c3069cd0652b9beef55b24bc0a57caf7f4 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 CSRCS = symbol_table.c hash_table.c glsl_types.c 
-CCSRCS = glsl_parser.tab.cc glsl_lexer.cc glsl_parser_extras.cc
-#      ast_to_hir.cc ir.cc hir_field_selection.cc
-OBJS = $(CSRCS:.c=.o)  $(CCSRCS:.cc=.o)
+CCSRCS = glsl_parser.tab.cpp glsl_lexer.cpp glsl_parser_extras.cpp
+#      ast_to_hir.cpp ir.cpp hir_field_selection.cpp
+OBJS = $(CSRCS:.c=.o)  $(CCSRCS:.cpp=.o)
 
 CC = gcc
 CXX = g++
@@ -15,26 +15,26 @@ LDLAGS   = -ggdb3
 glsl: $(OBJS)
        $(CXX) $(LDLAGS) $(OBJS) -o glsl
 
-glsl_parser.tab.cc glsl_parser.tab.h: glsl_parser.y
+glsl_parser.tab.cpp glsl_parser.tab.h: glsl_parser.y
        bison --report-file=glsl_parser.output -v -d \
-           --output=glsl_parser.tab.cc \
+           --output=glsl_parser.tab.cpp \
            --name-prefix=_mesa_glsl_ $< && \
-       mv glsl_parser.tab.hh glsl_parser.tab.h
+       mv glsl_parser.tab.hpp glsl_parser.tab.h
 
-glsl_lexer.cc: glsl_lexer.l
-       flex --outfile="glsl_lexer.cc" $<
+glsl_lexer.cpp: glsl_lexer.l
+       flex --outfile="glsl_lexer.cpp" $<
 
-glsl_parser_tab.o: glsl_parser.tab.cc
+glsl_parser_tab.o: glsl_parser.tab.cpp
 glsl_types.o: glsl_types.c glsl_types.h builtin_types.h
-glsl_lexer.o: glsl_lexer.cc glsl_parser.tab.h glsl_parser_extras.h ast.h
+glsl_lexer.o: glsl_lexer.cpp glsl_parser.tab.h glsl_parser_extras.h ast.h
 glsl_parser.o:  glsl_parser_extras.h ast.h
-ast_to_hir.o: ast_to_hir.cc symbol_table.h glsl_parser_extras.h ast.h glsl_types.h ir.h
+ast_to_hir.o: ast_to_hir.cpp symbol_table.h glsl_parser_extras.h ast.h glsl_types.h ir.h
 
 builtin_types.h: builtin_types.sh
        ./builtin_types.sh > builtin_types.h
 
 clean:
        rm -f $(OBJS) glsl
-       rm -f glsl_lexer.cc glsl_parser.tab.{cc,h,hh} glsl_parser.output
+       rm -f glsl_lexer.cpp glsl_parser.tab.{cpp,h,hpp} glsl_parser.output
        rm -f builtin_types.h
        rm -f *~
\ No newline at end of file
diff --git a/ast_to_hir.cc b/ast_to_hir.cc
deleted file mode 100644 (file)
index 8474a46..0000000
+++ /dev/null
@@ -1,1172 +0,0 @@
-/*
- * Copyright © 2010 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-
-/**
- * \file ast_to_hir.c
- * Convert abstract syntax to to high-level intermediate reprensentation (HIR).
- *
- * During the conversion to HIR, the majority of the symantic checking is
- * preformed on the program.  This includes:
- *
- *    * Symbol table management
- *    * Type checking
- *    * Function binding
- *
- * The majority of this work could be done during parsing, and the parser could
- * probably generate HIR directly.  However, this results in frequent changes
- * to the parser code.  Since we do not assume that every system this complier
- * is built on will have Flex and Bison installed, we have to store the code
- * generated by these tools in our version control system.  In other parts of
- * the system we've seen problems where a parser was changed but the generated
- * code was not committed, merge conflicts where created because two developers
- * had slightly different versions of Bison installed, etc.
- *
- * I have also noticed that running Bison generated parsers in GDB is very
- * irritating.  When you get a segfault on '$$ = $1->foo', you can't very
- * well 'print $1' in GDB.
- *
- * 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 "symbol_table.h"
-#include "glsl_parser_extras.h"
-#include "ast.h"
-#include "glsl_types.h"
-#include "ir.h"
-
-void
-_mesa_generate_hir_from_ast(struct _mesa_glsl_parse_state *state)
-{
-   struct simple_node *ptr;
-
-   foreach (ptr, & state->translation_unit) {
-      if (1) {
-      }
-   }
-}
-
-
-static const struct glsl_type *
-arithmetic_result_type(const struct glsl_type *type_a,
-                      const struct glsl_type *type_b,
-                      bool multiply,
-                      struct _mesa_glsl_parse_state *state)
-{
-   /* From GLSL 1.50 spec, page 56:
-    *
-    *    "The arithmetic binary operators add (+), subtract (-),
-    *    multiply (*), and divide (/) operate on integer and
-    *    floating-point scalars, vectors, and matrices."
-    */
-   if (! is_numeric_base_type(type_a->base_type)
-       || ! is_numeric_base_type(type_b->base_type)) {
-      return glsl_error_type;
-   }
-
-
-   /*    "If one operand is floating-point based and the other is
-    *    not, then the conversions from Section 4.1.10 "Implicit
-    *    Conversions" are applied to the non-floating-point-based operand."
-    *
-    * 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 ((type_a->base_type == GLSL_TYPE_FLOAT)
-         && (type_b->base_type != GLSL_TYPE_FLOAT)) {
-      } else if ((type_a->base_type != GLSL_TYPE_FLOAT)
-                && (type_b->base_type == GLSL_TYPE_FLOAT)) {
-      }
-   }
-      
-   /*    "If the operands are integer types, they must both be signed or
-    *    both be unsigned."
-    *
-    * From this rule and the preceeding conversion it can be inferred that
-    * both types must be GLSL_TYPE_FLOAT, or GLSL_TYPE_UINT, or GLSL_TYPE_INT.
-    * The is_numeric_base_type check above already filtered out the case
-    * where either type is not one of these, so now the base types need only
-    * be tested for equality.
-    */
-   if (type_a->base_type != type_b->base_type) {
-      return glsl_error_type;
-   }
-
-   /*    "All arithmetic binary operators result in the same fundamental type
-    *    (signed integer, unsigned integer, or floating-point) as the
-    *    operands they operate on, after operand type conversion. After
-    *    conversion, the following cases are valid
-    *
-    *    * The two operands are scalars. In this case the operation is
-    *      applied, resulting in a scalar."
-    */
-   if (is_glsl_type_scalar(type_a) && is_glsl_type_scalar(type_b))
-      return type_a;
-
-   /*   "* One operand is a scalar, and the other is a vector or matrix.
-    *      In this case, the scalar operation is applied independently to each
-    *      component of the vector or matrix, resulting in the same size
-    *      vector or matrix."
-    */
-   if (is_glsl_type_scalar(type_a)) {
-      if (!is_glsl_type_scalar(type_b))
-        return type_b;
-   } else if (is_glsl_type_scalar(type_b)) {
-      return type_a;
-   }
-
-   /* All of the combinations of <scalar, scalar>, <vector, scalar>,
-    * <scalar, vector>, <scalar, matrix>, and <matrix, scalar> have been
-    * handled.
-    */
-   assert(type_a->vector_elements > 1);
-   assert(type_b->vector_elements > 1);
-
-   /*   "* The two operands are vectors of the same size. In this case, the
-    *      operation is done component-wise resulting in the same size
-    *      vector."
-    */
-   if (is_glsl_type_vector(type_a) && is_glsl_type_vector(type_b)) {
-      if (type_a->vector_elements == type_b->vector_elements)
-        return type_a;
-      else
-        return glsl_error_type;
-   }
-
-   /* All of the combinations of <scalar, scalar>, <vector, scalar>,
-    * <scalar, vector>, <scalar, matrix>, <matrix, scalar>, and
-    * <vector, vector> have been handled.  At least one of the operands must
-    * be matrix.  Further, since there are no integer matrix types, the base
-    * type of both operands must be float.
-    */
-   assert((type_a->matrix_rows > 1) || (type_b->matrix_rows > 1));
-   assert(type_a->base_type == GLSL_TYPE_FLOAT);
-   assert(type_b->base_type == GLSL_TYPE_FLOAT);
-
-   /*   "* The operator is add (+), subtract (-), or divide (/), and the
-    *      operands are matrices with the same number of rows and the same
-    *      number of columns. In this case, the operation is done component-
-    *      wise resulting in the same size matrix."
-    *    * The operator is multiply (*), where both operands are matrices or
-    *      one operand is a vector and the other a matrix. A right vector
-    *      operand is treated as a column vector and a left vector operand as a
-    *      row vector. In all these cases, it is required that the number of
-    *      columns of the left operand is equal to the number of rows of the
-    *      right operand. Then, the multiply (*) operation does a linear
-    *      algebraic multiply, yielding an object that has the same number of
-    *      rows as the left operand and the same number of columns as the right
-    *      operand. Section 5.10 "Vector and Matrix Operations" explains in
-    *      more detail how vectors and matrices are operated on."
-    */
-   if (! multiply) {
-      if (is_glsl_type_matrix(type_a) && is_glsl_type_matrix(type_b)
-         && (type_a->vector_elements == type_b->vector_elements)
-         && (type_a->matrix_rows == type_b->matrix_rows))
-        return type_a;
-      else
-        return glsl_error_type;
-   } else {
-      if (is_glsl_type_matrix(type_a) && is_glsl_type_matrix(type_b)) {
-        if (type_a->vector_elements == type_b->matrix_rows) {
-           char type_name[7];
-           const struct glsl_type *t;
-
-           type_name[0] = 'm';
-           type_name[1] = 'a';
-           type_name[2] = 't';
-
-           if (type_a->matrix_rows == type_b->vector_elements) {
-              type_name[3] = '0' + type_a->matrix_rows;
-              type_name[4] = '\0';
-           } else {
-              type_name[3] = '0' + type_a->matrix_rows;
-              type_name[4] = 'x';
-              type_name[5] = '0' + type_b->vector_elements;
-              type_name[6] = '\0';
-           }
-
-           t = _mesa_symbol_table_find_symbol(state->symbols, 0, type_name);
-           return (t != NULL) ? t : glsl_error_type;
-        }
-      } else if (is_glsl_type_matrix(type_a)) {
-        /* A is a matrix and B is a column vector.  Columns of A must match
-         * rows of B.
-         */
-        if (type_a->vector_elements == type_b->vector_elements)
-           return type_b;
-      } else {
-        assert(is_glsl_type_matrix(type_b));
-
-        /* A is a row vector and B is a matrix.  Columns of A must match
-         * rows of B.
-         */
-        if (type_a->vector_elements == type_b->matrix_rows)
-           return type_a;
-      }
-   }
-
-
-   /*    "All other cases are illegal."
-    */
-   return glsl_error_type;
-}
-
-
-static const struct glsl_type *
-unary_arithmetic_result_type(const struct glsl_type *type)
-{
-   /* From GLSL 1.50 spec, page 57:
-    *
-    *    "The arithmetic unary operators negate (-), post- and pre-increment
-    *     and decrement (-- and ++) operate on integer or floating-point
-    *     values (including vectors and matrices). All unary operators work
-    *     component-wise on their operands. These result with the same type
-    *     they operated on."
-    */
-   if (!is_numeric_base_type(type->base_type))
-      return glsl_error_type;
-
-   return type;
-}
-
-
-static const struct glsl_type *
-modulus_result_type(const struct glsl_type *type_a,
-                   const struct glsl_type *type_b)
-{
-   /* From GLSL 1.50 spec, page 56:
-    *    "The operator modulus (%) operates on signed or unsigned integers or
-    *    integer vectors. The operand types must both be signed or both be
-    *    unsigned."
-    */
-   if (! is_integer_base_type(type_a->base_type)
-       || ! is_integer_base_type(type_b->base_type)
-       || (type_a->base_type != type_b->base_type)) {
-      return glsl_error_type;
-   }
-
-   /*    "The operands cannot be vectors of differing size. If one operand is
-    *    a scalar and the other vector, then the scalar is applied component-
-    *    wise to the vector, resulting in the same type as the vector. If both
-    *    are vectors of the same size, the result is computed component-wise."
-    */
-   if (is_glsl_type_vector(type_a)) {
-      if (!is_glsl_type_vector(type_b)
-         || (type_a->vector_elements == type_b->vector_elements))
-        return type_a;
-   } else
-      return type_b;
-
-   /*    "The operator modulus (%) is not defined for any other data types
-    *    (non-integer types)."
-    */
-   return glsl_error_type;
-}
-
-
-static const struct glsl_type *
-relational_result_type(const struct glsl_type *type_a,
-                      const struct glsl_type *type_b,
-                      struct _mesa_glsl_parse_state *state)
-{
-   /* From GLSL 1.50 spec, page 56:
-    *    "The relational operators greater than (>), less than (<), greater
-    *    than or equal (>=), and less than or equal (<=) operate only on
-    *    scalar integer and scalar floating-point expressions."
-    */
-   if (! is_numeric_base_type(type_a->base_type)
-       || ! is_numeric_base_type(type_b->base_type)
-       || ! is_glsl_type_scalar(type_a) 
-       || ! is_glsl_type_scalar(type_b))
-      return glsl_error_type;
-
-   /*    "Either the operands' types must match, or the conversions from
-    *    Section 4.1.10 "Implicit Conversions" will be applied to the integer
-    *    operand, after which the types must match."
-    *
-    * 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 ((type_a->base_type == GLSL_TYPE_FLOAT)
-         && (type_b->base_type != GLSL_TYPE_FLOAT)) {
-        /* FINISHME: Generate the implicit type conversion. */
-      } else if ((type_a->base_type != GLSL_TYPE_FLOAT)
-                && (type_b->base_type == GLSL_TYPE_FLOAT)) {
-        /* FINISHME: Generate the implicit type conversion. */
-      }
-   }
-
-   if (type_a->base_type != type_b->base_type)
-      return glsl_error_type;
-
-   /*    "The result is scalar Boolean."
-    */
-   return glsl_bool_type;
-}
-
-
-struct ir_instruction *
-ast_expression_to_hir(const struct ast_node *ast,
-                     struct simple_node *instructions,
-                     struct _mesa_glsl_parse_state *state)
-{
-   const struct ast_expression *expr =
-      (struct ast_expression *) ast;
-   static const int operations[AST_NUM_OPERATORS] = {
-      -1,               /* ast_assign doesn't convert to ir_expression. */
-      -1,               /* ast_plus doesn't convert to ir_expression. */
-      ir_unop_neg,
-      ir_binop_add,
-      ir_binop_sub,
-      ir_binop_mul,
-      ir_binop_div,
-      ir_binop_mod,
-      ir_binop_lshift,
-      ir_binop_rshift,
-      ir_binop_less,
-      ir_binop_greater,
-      ir_binop_lequal,
-      ir_binop_gequal,
-      ir_binop_equal,
-      ir_binop_nequal,
-      ir_binop_bit_and,
-      ir_binop_bit_xor,
-      ir_binop_bit_or,
-      ir_unop_bit_not,
-      ir_binop_logic_and,
-      ir_binop_logic_xor,
-      ir_binop_logic_or,
-      ir_unop_logic_not,
-
-      /* Note: The following block of expression types actually convert
-       * to multiple IR instructions.
-       */
-      ir_binop_mul,     /* ast_mul_assign */
-      ir_binop_div,     /* ast_div_assign */
-      ir_binop_mod,     /* ast_mod_assign */
-      ir_binop_add,     /* ast_add_assign */
-      ir_binop_sub,     /* ast_sub_assign */
-      ir_binop_lshift,  /* ast_ls_assign */
-      ir_binop_rshift,  /* ast_rs_assign */
-      ir_binop_bit_and, /* ast_and_assign */
-      ir_binop_bit_xor, /* ast_xor_assign */
-      ir_binop_bit_or,  /* ast_or_assign */
-
-      -1,               /* ast_conditional doesn't convert to ir_expression. */
-      -1,               /* ast_pre_inc doesn't convert to ir_expression. */
-      -1,               /* ast_pre_dec doesn't convert to ir_expression. */
-      -1,               /* ast_post_inc doesn't convert to ir_expression. */
-      -1,               /* ast_post_dec doesn't convert to ir_expression. */
-      -1,               /* ast_field_selection doesn't conv to ir_expression. */
-      -1,               /* ast_array_index doesn't convert to ir_expression. */
-      -1,               /* ast_function_call doesn't conv to ir_expression. */
-      -1,               /* ast_identifier doesn't convert to ir_expression. */
-      -1,               /* ast_int_constant doesn't convert to ir_expression. */
-      -1,               /* ast_uint_constant doesn't conv to ir_expression. */
-      -1,               /* ast_float_constant doesn't conv to ir_expression. */
-      -1,               /* ast_bool_constant doesn't conv to ir_expression. */
-      -1,               /* ast_sequence doesn't convert to ir_expression. */
-   };
-   struct ir_instruction *result = NULL;
-   struct ir_instruction *op[2];
-   struct simple_node op_list;
-   const struct glsl_type *type = glsl_error_type;
-   bool error_emitted = false;
-   YYLTYPE loc;
-
-   loc = ast->get_location();
-   make_empty_list(& op_list);
-
-   switch (expr->oper) {
-   case ast_assign:
-      op[0] = _mesa_ast_to_hir(expr->subexpressions[0], instructions, state);
-      op[1] = _mesa_ast_to_hir(expr->subexpressions[1], instructions, state);
-
-      error_emitted = ((op[0]->type == glsl_error_type)
-                      || (op[1]->type == glsl_error_type));
-
-      type = op[0]->type;
-      if (!error_emitted) {
-        YYLTYPE loc;
-
-        /* FINISHME: This does not handle 'foo.bar.a.b.c[5].d = 5' */
-        loc = expr->subexpressions[0]->get_location();
-        if (op[0]->mode != ir_op_dereference) {
-           _mesa_glsl_error(& loc, state, "invalid lvalue in assignment");
-           error_emitted = true;
-
-           type = glsl_error_type;
-        } else {
-           const struct ir_dereference *const ref =
-              (struct ir_dereference *) op[0];
-           const struct ir_variable *const var =
-              (struct ir_variable *) ref->var;
-
-           if ((var != NULL)
-               && (var->mode == ir_op_var_decl)
-               && (var->read_only)) {
-              _mesa_glsl_error(& loc, state, "cannot assign to read-only "
-                               "variable `%s'", var->name);
-              error_emitted = true;
-
-              type = glsl_error_type;
-           }
-        }
-      }
-
-      /* FINISHME: Check that the LHS and RHS have matching types. */
-      /* FINISHME: For GLSL 1.10, check that the types are not arrays. */
-
-      result = new ir_assignment(op[0], op[1], NULL);
-      break;
-
-   case ast_plus:
-      op[0] = _mesa_ast_to_hir(expr->subexpressions[0], instructions, state);
-
-      error_emitted = (op[0]->type == glsl_error_type);
-      if (type == glsl_error_type)
-        op[0]->type = type;
-
-      result = op[0];
-      break;
-
-   case ast_neg:
-      op[0] = _mesa_ast_to_hir(expr->subexpressions[0], instructions, state);
-
-      type = unary_arithmetic_result_type(op[0]->type);
-
-      error_emitted = (op[0]->type == glsl_error_type);
-
-      result = new ir_expression(operations[expr->oper], type,
-                                op[0], NULL);
-      break;
-
-   case ast_add:
-   case ast_sub:
-   case ast_mul:
-   case ast_div:
-      op[0] = _mesa_ast_to_hir(expr->subexpressions[0], instructions, state);
-      op[1] = _mesa_ast_to_hir(expr->subexpressions[1], instructions, state);
-
-      type = arithmetic_result_type(op[0]->type, op[1]->type,
-                                   (expr->operr == ast_mul),
-                                   state);
-
-      result = new ir_expression(operations[expr->oper], type,
-                                op[0], op[1]);
-      break;
-
-   case ast_mod:
-      op[0] = _mesa_ast_to_hir(expr->subexpressions[0], instructions, state);
-      op[1] = _mesa_ast_to_hir(expr->subexpressions[1], instructions, state);
-
-      error_emitted = ((op[0]->type == glsl_error_type)
-                      || (op[1]->type == glsl_error_type));
-
-      type = modulus_result_type(op[0]->type, op[1]->type);
-
-      assert(operations[expr->oper] == ir_binop_mod);
-
-      result = new ir_expression(operations[expr->oper], type,
-                                op[0], op[1]);
-      break;
-
-   case ast_lshift:
-   case ast_rshift:
-      /* FINISHME: Implement bit-shift operators. */
-      break;
-
-   case ast_less:
-   case ast_greater:
-   case ast_lequal:
-   case ast_gequal:
-      op[0] = _mesa_ast_to_hir(expr->subexpressions[0], instructions, state);
-      op[1] = _mesa_ast_to_hir(expr->subexpressions[1], instructions, state);
-
-      error_emitted = ((op[0]->type == glsl_error_type)
-                      || (op[1]->type == glsl_error_type));
-
-      type = relational_result_type(op[0]->type, op[1]->type, state);
-
-      /* The relational operators must either generate an error or result
-       * in a scalar boolean.  See page 57 of the GLSL 1.50 spec.
-       */
-      assert((type == glsl_error_type)
-            || ((type->base_type == GLSL_TYPE_BOOL)
-                && is_glsl_type_scalar(type)));
-
-      result = new ir_expression(operations[expr->oper], type,
-                                op[0], op[1]);
-      break;
-
-   case ast_nequal:
-   case ast_equal:
-      /* FINISHME: Implement equality operators. */
-      break;
-
-   case ast_bit_and:
-   case ast_bit_xor:
-   case ast_bit_or:
-   case ast_bit_not:
-      /* FINISHME: Implement bit-wise operators. */
-      break;
-
-   case ast_logic_and:
-   case ast_logic_xor:
-   case ast_logic_or:
-   case ast_logic_not:
-      /* FINISHME: Implement logical operators. */
-      break;
-
-   case ast_mul_assign:
-   case ast_div_assign:
-   case ast_add_assign:
-   case ast_sub_assign: {
-      struct ir_instruction *temp_rhs;
-
-      op[0] = _mesa_ast_to_hir(expr->subexpressions[0], instructions, state);
-      op[1] = _mesa_ast_to_hir(expr->subexpressions[1], instructions, state);
-
-      error_emitted = ((op[0]->type == glsl_error_type)
-                      || (op[1]->type == glsl_error_type));
-
-      type = arithmetic_result_type(op[0]->type, op[1]->type,
-                                   (expr->oper == ast_mul_assign),
-                                   state);
-
-      temp_rhs = new ir_expression(operations[expr->oper], type,
-                                  op[0], op[1]);
-
-      /* FINISHME: Check that the LHS is assignable. */
-
-      /* We still have to test that the LHS and RHS have matching type.  For
-       * example, the following GLSL code should generate a type error:
-       *
-       *    mat4 m; vec4 v; m *= v;
-       *
-       * The type of (m*v) is a vec4, but the type of m is a mat4.
-       *
-       * FINISHME: Is multiplication between a matrix and a vector the only
-       * FINISHME: case that resuls in mismatched types?
-       */
-      /* FINISHME: Check that the LHS and RHS have matching types. */
-
-      /* GLSL 1.10 does not allow array assignment.  However, we don't have to
-       * explicitly test for this because none of the binary expression
-       * operators allow array operands either.
-       */
-
-      /* FINISHME: This is wrong.  The operation should assign to a new
-       * FINISHME: temporary.  This assignment should then be added to the
-       * FINISHME: instruction list.  Another assignment to the real
-       * FINISHME: destination should be generated.  The temporary should then
-       * FINISHME: be returned as the r-value.
-       */
-      result = new ir_assignment(op[0], temp_rhs, NULL);
-      break;
-   }
-
-   case ast_mod_assign:
-
-   case ast_ls_assign:
-   case ast_rs_assign:
-
-   case ast_and_assign:
-   case ast_xor_assign:
-   case ast_or_assign:
-
-   case ast_conditional:
-
-   case ast_pre_inc:
-   case ast_pre_dec:
-
-   case ast_post_inc:
-   case ast_post_dec:
-      break;
-
-   case ast_field_selection:
-      result = _mesa_ast_field_selection_to_hir(expr, instructions, state);
-      type = result->type;
-      break;
-
-   case ast_array_index:
-      break;
-
-   case ast_function_call:
-      /* There are three sorts of function calls.
-       *
-       * 1. contstructors - The first subexpression is an ast_type_specifier.
-       * 2. methods - Only the .length() method of array types.
-       * 3. functions - Calls to regular old functions.
-       *
-       * Method calls are actually detected when the ast_field_selection
-       * expression is handled.
-       */
-      result = _mesa_ast_function_call_to_hir(expr->subexpressions[0],
-                                             expr->subexpressions[1],
-                                             state);
-      type = result->type;
-      break;
-
-   case ast_identifier: {
-      /* ast_identifier can appear several places in a full abstract syntax
-       * tree.  This particular use must be at location specified in the grammar
-       * as 'variable_identifier'.
-       */
-      struct ir_variable *var =
-        _mesa_symbol_table_find_symbol(state->symbols, 0,
-                                       expr->primary_expression.identifier);
-
-      result = new ir_dereference(var);
-
-      if (var != NULL) {
-        type = result->type;
-      } else {
-        _mesa_glsl_error(& loc, NULL, "`%s' undeclared",
-                         expr->primary_expression.identifier);
-
-        error_emitted = true;
-      }
-      break;
-   }
-
-   case ast_int_constant:
-      type = glsl_int_type;
-      result = new ir_constant(type, & expr->primary_expression);
-      break;
-
-   case ast_uint_constant:
-      type = glsl_uint_type;
-      result = new ir_constant(type, & expr->primary_expression);
-      break;
-
-   case ast_float_constant:
-      type = glsl_float_type;
-      result = new ir_constant(type, & expr->primary_expression);
-      break;
-
-   case ast_bool_constant:
-      type = glsl_bool_type;
-      result = new ir_constant(type, & expr->primary_expression);
-      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(&expr->expressions));
-
-      /* 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, &expr->expressions)
-        result = _mesa_ast_to_hir(ptr, instructions, state);
-
-      type = result->type;
-
-      /* Any errors should have already been emitted in the loop above.
-       */
-      error_emitted = true;
-      break;
-   }
-   }
-
-   if (is_error_type(type) && !error_emitted)
-      _mesa_glsl_error(& loc, NULL, "type mismatch");
-
-   return result;
-}
-
-
-struct ir_instruction *
-ast_expression_statement_to_hir(const struct ast_node *ast,
-                               struct simple_node *instructions,
-                               struct _mesa_glsl_parse_state *state)
-{
-   const struct ast_expression_statement *stmt =
-      (struct ast_expression_statement *) ast;
-
-   /* It is possible to have expression statements that don't have an
-    * expression.  This is the solitary semicolon:
-    *
-    * for (i = 0; i < 5; i++)
-    *     ;
-    *
-    * In this case the expression will be NULL.  Test for NULL and don't do
-    * anything in that case.
-    */
-   if (stmt->expression != NULL)
-      _mesa_ast_to_hir(stmt->expression, instructions, state);
-
-   /* Statements do not have r-values.
-    */
-   return NULL;
-}
-
-
-struct ir_instruction *
-ast_compound_statement_to_hir(const struct ast_node *ast,
-                             struct simple_node *instructions,
-                             struct _mesa_glsl_parse_state *state)
-{
-   const struct ast_compound_statement *stmt =
-      (struct ast_compound_statement *) ast;
-   struct simple_node *ptr;
-
-
-   if (stmt->new_scope)
-      _mesa_symbol_table_push_scope(state->symbols);
-
-   foreach (ptr, &stmt->statements)
-      _mesa_ast_to_hir(ptr, instructions, state);
-
-   if (stmt->new_scope)
-      _mesa_symbol_table_pop_scope(state->symbols);
-
-   /* Compound statements do not have r-values.
-    */
-   return NULL;
-}
-
-
-static const struct glsl_type *
-type_specifier_to_glsl_type(const struct ast_type_specifier *spec,
-                           const char **name,
-                           struct _mesa_glsl_parse_state *state)
-{
-   static const char *const type_names[] = {
-      "void",
-      "float",
-      "int",
-      "uint",
-      "bool",
-      "vec2",
-      "vec3",
-      "vec4",
-      "bvec2",
-      "bvec3",
-      "bvec4",
-      "ivec2",
-      "ivec3",
-      "ivec4",
-      "uvec2",
-      "uvec3",
-      "uvec4",
-      "mat2",
-      "mat2x3",
-      "mat2x4",
-      "mat3x2",
-      "mat3",
-      "mat3x4",
-      "mat4x2",
-      "mat4x3",
-      "mat4",
-      "sampler1D",
-      "sampler2D",
-      "sampler3D",
-      "samplerCube",
-      "sampler1DShadow",
-      "sampler2DShadow",
-      "samplerCubeShadow",
-      "sampler1DArray",
-      "sampler2DArray",
-      "sampler1DArrayShadow",
-      "sampler2DArrayShadow",
-      "isampler1D",
-      "isampler2D",
-      "isampler3D",
-      "isamplerCube",
-      "isampler1DArray",
-      "isampler2DArray",
-      "usampler1D",
-      "usampler2D",
-      "usampler3D",
-      "usamplerCube",
-      "usampler1DArray",
-      "usampler2DArray",
-
-      NULL, /* ast_struct */
-      NULL  /* ast_type_name */
-   };
-   struct glsl_type *type;
-   const char *type_name = NULL;
-
-   if (spec->type_specifier == ast_struct) {
-      /* FINISHME: Handle annonymous structures. */
-      type = NULL;
-   } else {
-      type_name = (spec->type_specifier == ast_type_name)
-        ? spec->type_name : type_names[spec->type_specifier];
-
-      type = _mesa_symbol_table_find_symbol(state->symbols, 0, type_name);
-      *name = type_name;
-
-      /* FINISHME: Handle array declarations.  Note that this requires complete
-       * FINSIHME: handling of constant expressions.
-       */
-   }
-
-   return type;
-}
-
-
-static void
-apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual,
-                                struct ir_variable *var,
-                                struct _mesa_glsl_parse_state *state)
-{
-   if (qual->invariant)
-      var->invariant = 1;
-
-   /* FINISHME: Mark 'in' variables at global scope as read-only. */
-   if (qual->constant || qual->attribute || qual->uniform
-       || (qual->varying && (state->target == fragment_shader)))
-      var->read_only = 1;
-
-   if (qual->centroid)
-      var->centroid = 1;
-
-   if (qual->in && qual->out)
-      var->mode = ir_var_inout;
-   else if (qual->attribute || qual->in
-           || (qual->varying && (state->target == fragment_shader)))
-      var->mode = ir_var_in;
-   else if (qual->out)
-      var->mode = ir_var_out;
-   else if (qual->uniform)
-      var->mode = ir_var_uniform;
-   else
-      var->mode = ir_var_auto;
-
-   if (qual->flat)
-      var->interpolation = ir_var_flat;
-   else if (qual->noperspective)
-      var->interpolation = ir_var_noperspective;
-   else
-      var->interpolation = ir_var_smooth;
-}
-
-
-struct ir_instruction *
-ast_declarator_list_to_hir(const struct ast_node *ast,
-                          struct simple_node *instructions,
-                          struct _mesa_glsl_parse_state *state)
-{
-   const struct ast_declarator_list *dlist = (struct ast_declarator_list *) ast;
-   struct simple_node *ptr;
-   const struct glsl_type *decl_type;
-   const char *type_name = NULL;
-
-
-   /* FINISHME: Handle vertex shader "invariant" declarations that do not
-    * FINISHME: include a type.  These re-declare built-in variables to be
-    * FINISHME: invariant.
-    */
-
-   decl_type = type_specifier_to_glsl_type(dlist->type->specifier,
-                                          & type_name, state);
-
-   foreach (ptr, &dlist->declarations) {
-      struct ast_declaration *const decl = (struct ast_declaration * )ptr;
-      const struct glsl_type *var_type;
-      struct ir_variable *var;
-
-
-      /* FINISHME: Emit a warning if a variable declaration shadows a
-       * FINISHME: declaration at a higher scope.
-       */
-
-      if (decl_type == NULL) {
-        YYLTYPE loc;
-
-        loc = ast->get_location();
-        if (type_name != NULL) {
-           _mesa_glsl_error(& loc, state,
-                            "invalid type `%s' in declaration of `%s'",
-                            type_name, decl->identifier);
-        } else {
-           _mesa_glsl_error(& loc, state,
-                            "invalid type in declaration of `%s'",
-                            decl->identifier);
-        }
-        continue;
-      }
-
-      if (decl->is_array) {
-        /* FINISHME: Handle array declarations.  Note that this requires
-         * FINISHME: complete handling of constant expressions.
-         */
-
-        /* FINISHME: Reject delcarations of multidimensional arrays. */
-      } else {
-        var_type = decl_type;
-      }
-
-      var = new ir_variable(var_type, decl->identifier);
-
-      /* FINSIHME: Variables that are attribute, uniform, varying, in, or
-       * FINISHME: out varibles must be declared either at global scope or
-       * FINISHME: in a parameter list (in and out only).
-       */
-
-      apply_type_qualifier_to_variable(& dlist->type->qualifier, var, state);
-
-      /* Attempt to add the variable to the symbol table.  If this fails, it
-       * means the variable has already been declared at this scope.
-       */
-      if (_mesa_symbol_table_add_symbol(state->symbols, 0, decl->identifier,
-                                       var) != 0) {
-        YYLTYPE loc = ast->get_location();
-
-        _mesa_glsl_error(& loc, state, "`%s' redeclared",
-                         decl->identifier);
-        continue;
-      }
-
-      insert_at_tail(instructions, (struct simple_node *) var);
-
-      /* FINISHME: Process the declaration initializer. */
-   }
-
-   /* Variable declarations do not have r-values.
-    */
-   return NULL;
-}
-
-
-struct ir_instruction *
-ast_parameter_declarator_to_hir(const struct ast_node *ast,
-                               struct simple_node *instructions,
-                               struct _mesa_glsl_parse_state *state)
-{
-   const struct ast_parameter_declarator *decl =
-      (struct ast_parameter_declarator *) ast;
-   struct ir_variable *var;
-   const struct glsl_type *type;
-   const char *name = NULL;
-
-
-   type = type_specifier_to_glsl_type(decl->type->specifier, & name, state);
-
-   if (type == NULL) {
-      YYLTYPE loc = ast->get_location();
-      if (name != NULL) {
-        _mesa_glsl_error(& loc, state,
-                         "invalid type `%s' in declaration of `%s'",
-                         name, decl->identifier);
-      } else {
-        _mesa_glsl_error(& loc, state,
-                         "invalid type in declaration of `%s'",
-                         decl->identifier);
-      }
-
-      type = glsl_error_type;
-   }
-
-   var = new ir_variable(type, decl->identifier);
-
-   /* FINISHME: Handle array declarations.  Note that this requires
-    * FINISHME: complete handling of constant expressions.
-    */
-
-   apply_type_qualifier_to_variable(& decl->type->qualifier, var, state);
-
-   insert_at_tail(instructions, var);
-
-   /* Parameter declarations do not have r-values.
-    */
-   return NULL;
-}
-
-
-static void
-ast_function_parameters_to_hir(struct simple_node *ast_parameters,
-                              struct simple_node *ir_parameters,
-                              struct _mesa_glsl_parse_state *state)
-{
-   struct simple_node *ptr;
-
-   foreach (ptr, ast_parameters) {
-      _mesa_ast_to_hir(ptr, ir_parameters, state);
-   }
-}
-
-
-static bool
-parameter_lists_match(struct simple_node *list_a, struct simple_node *list_b)
-{
-   struct simple_node *node_a;
-   struct simple_node *node_b;
-
-   node_b = first_elem(list_b);
-   foreach (node_a, list_a) {
-      /* If all of the parameters from the other parameter list have been
-       * exhausted, the lists have different length and, by definition,
-       * do not match.
-       */
-      if (at_end(list_b, node_b))
-        return false;
-
-      /* If the types of the parameters do not match, the parameters lists
-       * are different.
-       */
-      /* FINISHME */
-
-
-      node_b = next_elem(node_b);
-   }
-
-   return true;
-}
-
-
-struct ir_instruction *
-ast_function_definition_to_hir(const struct ast_node *ast,
-                              struct simple_node *instructions,
-                              struct _mesa_glsl_parse_state *state)
-{
-   const struct ast_function_definition *func =
-      (struct ast_function_definition *) ast;
-   struct ir_label *label;
-   struct simple_node *ptr;
-   struct simple_node *tmp;
-   struct ir_function_signature *signature = NULL;
-   struct ir_function *f = NULL;
-   struct simple_node parameters;
-
-
-   /* 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.
-    */
-   make_empty_list(& parameters);
-   ast_function_parameters_to_hir(& func->prototype->parameters, & parameters,
-                                 state);
-
-
-   /* Verify that this function's signature either doesn't match a previously
-    * seen signature for a function with the same name, or, if a match is found,
-    * that the previously seen signature does not have an associated definition.
-    */
-   f = _mesa_symbol_table_find_symbol(state->symbols, 0,
-                                     func->prototype->identifier);
-   if (f != NULL) {
-      foreach (ptr, & f->signatures) {
-        signature = (struct ir_function_signature *) ptr;
-
-        /* Compare the parameter list of the function being defined to the
-         * existing function.  If the parameter lists match, then the return
-         * type must also match and the existing function must not have a
-         * definition.
-         */
-        if (parameter_lists_match(& parameters, & signature->parameters)) {
-           /* FINISHME: Compare return types. */
-
-           if (signature->definition != NULL) {
-              YYLTYPE loc = ast->get_location();
-
-              _mesa_glsl_error(& loc, state, "function `%s' redefined",
-                               func->prototype->identifier);
-              signature = NULL;
-              break;
-           }
-        }
-
-        signature = NULL;
-      }
-
-   } else {
-      f = new ir_function();
-      f->name = func->prototype->identifier;
-
-      _mesa_symbol_table_add_symbol(state->symbols, 0, f->name, f);
-   }
-
-
-   /* Finish storing the information about this new function in its signature.
-    */
-   if (signature == NULL) {
-      signature = new ir_function_signature();
-      insert_at_tail(& f->signatures, (struct simple_node *) signature);
-   } else {
-      /* Destroy all of the previous parameter information.  The previous
-       * parameter information comes from the function prototype, and it can
-       * either include invalid parameter names or may not have names at all.
-       */
-      foreach_s(ptr, tmp, & signature->parameters) {
-        assert(((struct ir_instruction *)ptr)->mode == ir_op_var_decl);
-
-        remove_from_list(ptr);
-        free(ptr);
-      }
-   }
-
-
-   ast_function_parameters_to_hir(& func->prototype->parameters,
-                                 & signature->parameters,
-                                 state);
-   /* FINISHME: Set signature->return_type */
-
-   label = new ir_label(func->prototype->identifier);
-   if (signature->definition == NULL) {
-      signature->definition = label;
-   }
-   insert_at_tail(instructions, label);
-
-   /* Add the function parameters to the symbol table.  During this step the
-    * parameter declarations are also moved from the temporary "parameters" list
-    * to the instruction list.  There are other more efficient ways to do this,
-    * but they involve ugly linked-list gymnastics.
-    */
-   _mesa_symbol_table_push_scope(state->symbols);
-   foreach_s(ptr, tmp, & parameters) {
-      struct ir_variable *const var = (struct ir_variable *) ptr;
-
-      assert(var->mode == ir_op_var_decl);
-
-      remove_from_list(ptr);
-      insert_at_tail(instructions, ptr);
-
-      _mesa_symbol_table_add_symbol(state->symbols, 0, var->name, var);
-   }
-
-   /* Convert the body of the function to HIR, and append the resulting
-    * instructions to the list that currently consists of the function label
-    * and the function parameters.
-    */
-   _mesa_ast_to_hir(func->body, instructions, state);
-
-   _mesa_symbol_table_pop_scope(state->symbols);
-
-
-   /* Function definitions do not have r-values.
-    */
-   return NULL;
-}
diff --git a/ast_to_hir.cpp b/ast_to_hir.cpp
new file mode 100644 (file)
index 0000000..8474a46
--- /dev/null
@@ -0,0 +1,1172 @@
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * \file ast_to_hir.c
+ * Convert abstract syntax to to high-level intermediate reprensentation (HIR).
+ *
+ * During the conversion to HIR, the majority of the symantic checking is
+ * preformed on the program.  This includes:
+ *
+ *    * Symbol table management
+ *    * Type checking
+ *    * Function binding
+ *
+ * The majority of this work could be done during parsing, and the parser could
+ * probably generate HIR directly.  However, this results in frequent changes
+ * to the parser code.  Since we do not assume that every system this complier
+ * is built on will have Flex and Bison installed, we have to store the code
+ * generated by these tools in our version control system.  In other parts of
+ * the system we've seen problems where a parser was changed but the generated
+ * code was not committed, merge conflicts where created because two developers
+ * had slightly different versions of Bison installed, etc.
+ *
+ * I have also noticed that running Bison generated parsers in GDB is very
+ * irritating.  When you get a segfault on '$$ = $1->foo', you can't very
+ * well 'print $1' in GDB.
+ *
+ * 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 "symbol_table.h"
+#include "glsl_parser_extras.h"
+#include "ast.h"
+#include "glsl_types.h"
+#include "ir.h"
+
+void
+_mesa_generate_hir_from_ast(struct _mesa_glsl_parse_state *state)
+{
+   struct simple_node *ptr;
+
+   foreach (ptr, & state->translation_unit) {
+      if (1) {
+      }
+   }
+}
+
+
+static const struct glsl_type *
+arithmetic_result_type(const struct glsl_type *type_a,
+                      const struct glsl_type *type_b,
+                      bool multiply,
+                      struct _mesa_glsl_parse_state *state)
+{
+   /* From GLSL 1.50 spec, page 56:
+    *
+    *    "The arithmetic binary operators add (+), subtract (-),
+    *    multiply (*), and divide (/) operate on integer and
+    *    floating-point scalars, vectors, and matrices."
+    */
+   if (! is_numeric_base_type(type_a->base_type)
+       || ! is_numeric_base_type(type_b->base_type)) {
+      return glsl_error_type;
+   }
+
+
+   /*    "If one operand is floating-point based and the other is
+    *    not, then the conversions from Section 4.1.10 "Implicit
+    *    Conversions" are applied to the non-floating-point-based operand."
+    *
+    * 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 ((type_a->base_type == GLSL_TYPE_FLOAT)
+         && (type_b->base_type != GLSL_TYPE_FLOAT)) {
+      } else if ((type_a->base_type != GLSL_TYPE_FLOAT)
+                && (type_b->base_type == GLSL_TYPE_FLOAT)) {
+      }
+   }
+      
+   /*    "If the operands are integer types, they must both be signed or
+    *    both be unsigned."
+    *
+    * From this rule and the preceeding conversion it can be inferred that
+    * both types must be GLSL_TYPE_FLOAT, or GLSL_TYPE_UINT, or GLSL_TYPE_INT.
+    * The is_numeric_base_type check above already filtered out the case
+    * where either type is not one of these, so now the base types need only
+    * be tested for equality.
+    */
+   if (type_a->base_type != type_b->base_type) {
+      return glsl_error_type;
+   }
+
+   /*    "All arithmetic binary operators result in the same fundamental type
+    *    (signed integer, unsigned integer, or floating-point) as the
+    *    operands they operate on, after operand type conversion. After
+    *    conversion, the following cases are valid
+    *
+    *    * The two operands are scalars. In this case the operation is
+    *      applied, resulting in a scalar."
+    */
+   if (is_glsl_type_scalar(type_a) && is_glsl_type_scalar(type_b))
+      return type_a;
+
+   /*   "* One operand is a scalar, and the other is a vector or matrix.
+    *      In this case, the scalar operation is applied independently to each
+    *      component of the vector or matrix, resulting in the same size
+    *      vector or matrix."
+    */
+   if (is_glsl_type_scalar(type_a)) {
+      if (!is_glsl_type_scalar(type_b))
+        return type_b;
+   } else if (is_glsl_type_scalar(type_b)) {
+      return type_a;
+   }
+
+   /* All of the combinations of <scalar, scalar>, <vector, scalar>,
+    * <scalar, vector>, <scalar, matrix>, and <matrix, scalar> have been
+    * handled.
+    */
+   assert(type_a->vector_elements > 1);
+   assert(type_b->vector_elements > 1);
+
+   /*   "* The two operands are vectors of the same size. In this case, the
+    *      operation is done component-wise resulting in the same size
+    *      vector."
+    */
+   if (is_glsl_type_vector(type_a) && is_glsl_type_vector(type_b)) {
+      if (type_a->vector_elements == type_b->vector_elements)
+        return type_a;
+      else
+        return glsl_error_type;
+   }
+
+   /* All of the combinations of <scalar, scalar>, <vector, scalar>,
+    * <scalar, vector>, <scalar, matrix>, <matrix, scalar>, and
+    * <vector, vector> have been handled.  At least one of the operands must
+    * be matrix.  Further, since there are no integer matrix types, the base
+    * type of both operands must be float.
+    */
+   assert((type_a->matrix_rows > 1) || (type_b->matrix_rows > 1));
+   assert(type_a->base_type == GLSL_TYPE_FLOAT);
+   assert(type_b->base_type == GLSL_TYPE_FLOAT);
+
+   /*   "* The operator is add (+), subtract (-), or divide (/), and the
+    *      operands are matrices with the same number of rows and the same
+    *      number of columns. In this case, the operation is done component-
+    *      wise resulting in the same size matrix."
+    *    * The operator is multiply (*), where both operands are matrices or
+    *      one operand is a vector and the other a matrix. A right vector
+    *      operand is treated as a column vector and a left vector operand as a
+    *      row vector. In all these cases, it is required that the number of
+    *      columns of the left operand is equal to the number of rows of the
+    *      right operand. Then, the multiply (*) operation does a linear
+    *      algebraic multiply, yielding an object that has the same number of
+    *      rows as the left operand and the same number of columns as the right
+    *      operand. Section 5.10 "Vector and Matrix Operations" explains in
+    *      more detail how vectors and matrices are operated on."
+    */
+   if (! multiply) {
+      if (is_glsl_type_matrix(type_a) && is_glsl_type_matrix(type_b)
+         && (type_a->vector_elements == type_b->vector_elements)
+         && (type_a->matrix_rows == type_b->matrix_rows))
+        return type_a;
+      else
+        return glsl_error_type;
+   } else {
+      if (is_glsl_type_matrix(type_a) && is_glsl_type_matrix(type_b)) {
+        if (type_a->vector_elements == type_b->matrix_rows) {
+           char type_name[7];
+           const struct glsl_type *t;
+
+           type_name[0] = 'm';
+           type_name[1] = 'a';
+           type_name[2] = 't';
+
+           if (type_a->matrix_rows == type_b->vector_elements) {
+              type_name[3] = '0' + type_a->matrix_rows;
+              type_name[4] = '\0';
+           } else {
+              type_name[3] = '0' + type_a->matrix_rows;
+              type_name[4] = 'x';
+              type_name[5] = '0' + type_b->vector_elements;
+              type_name[6] = '\0';
+           }
+
+           t = _mesa_symbol_table_find_symbol(state->symbols, 0, type_name);
+           return (t != NULL) ? t : glsl_error_type;
+        }
+      } else if (is_glsl_type_matrix(type_a)) {
+        /* A is a matrix and B is a column vector.  Columns of A must match
+         * rows of B.
+         */
+        if (type_a->vector_elements == type_b->vector_elements)
+           return type_b;
+      } else {
+        assert(is_glsl_type_matrix(type_b));
+
+        /* A is a row vector and B is a matrix.  Columns of A must match
+         * rows of B.
+         */
+        if (type_a->vector_elements == type_b->matrix_rows)
+           return type_a;
+      }
+   }
+
+
+   /*    "All other cases are illegal."
+    */
+   return glsl_error_type;
+}
+
+
+static const struct glsl_type *
+unary_arithmetic_result_type(const struct glsl_type *type)
+{
+   /* From GLSL 1.50 spec, page 57:
+    *
+    *    "The arithmetic unary operators negate (-), post- and pre-increment
+    *     and decrement (-- and ++) operate on integer or floating-point
+    *     values (including vectors and matrices). All unary operators work
+    *     component-wise on their operands. These result with the same type
+    *     they operated on."
+    */
+   if (!is_numeric_base_type(type->base_type))
+      return glsl_error_type;
+
+   return type;
+}
+
+
+static const struct glsl_type *
+modulus_result_type(const struct glsl_type *type_a,
+                   const struct glsl_type *type_b)
+{
+   /* From GLSL 1.50 spec, page 56:
+    *    "The operator modulus (%) operates on signed or unsigned integers or
+    *    integer vectors. The operand types must both be signed or both be
+    *    unsigned."
+    */
+   if (! is_integer_base_type(type_a->base_type)
+       || ! is_integer_base_type(type_b->base_type)
+       || (type_a->base_type != type_b->base_type)) {
+      return glsl_error_type;
+   }
+
+   /*    "The operands cannot be vectors of differing size. If one operand is
+    *    a scalar and the other vector, then the scalar is applied component-
+    *    wise to the vector, resulting in the same type as the vector. If both
+    *    are vectors of the same size, the result is computed component-wise."
+    */
+   if (is_glsl_type_vector(type_a)) {
+      if (!is_glsl_type_vector(type_b)
+         || (type_a->vector_elements == type_b->vector_elements))
+        return type_a;
+   } else
+      return type_b;
+
+   /*    "The operator modulus (%) is not defined for any other data types
+    *    (non-integer types)."
+    */
+   return glsl_error_type;
+}
+
+
+static const struct glsl_type *
+relational_result_type(const struct glsl_type *type_a,
+                      const struct glsl_type *type_b,
+                      struct _mesa_glsl_parse_state *state)
+{
+   /* From GLSL 1.50 spec, page 56:
+    *    "The relational operators greater than (>), less than (<), greater
+    *    than or equal (>=), and less than or equal (<=) operate only on
+    *    scalar integer and scalar floating-point expressions."
+    */
+   if (! is_numeric_base_type(type_a->base_type)
+       || ! is_numeric_base_type(type_b->base_type)
+       || ! is_glsl_type_scalar(type_a) 
+       || ! is_glsl_type_scalar(type_b))
+      return glsl_error_type;
+
+   /*    "Either the operands' types must match, or the conversions from
+    *    Section 4.1.10 "Implicit Conversions" will be applied to the integer
+    *    operand, after which the types must match."
+    *
+    * 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 ((type_a->base_type == GLSL_TYPE_FLOAT)
+         && (type_b->base_type != GLSL_TYPE_FLOAT)) {
+        /* FINISHME: Generate the implicit type conversion. */
+      } else if ((type_a->base_type != GLSL_TYPE_FLOAT)
+                && (type_b->base_type == GLSL_TYPE_FLOAT)) {
+        /* FINISHME: Generate the implicit type conversion. */
+      }
+   }
+
+   if (type_a->base_type != type_b->base_type)
+      return glsl_error_type;
+
+   /*    "The result is scalar Boolean."
+    */
+   return glsl_bool_type;
+}
+
+
+struct ir_instruction *
+ast_expression_to_hir(const struct ast_node *ast,
+                     struct simple_node *instructions,
+                     struct _mesa_glsl_parse_state *state)
+{
+   const struct ast_expression *expr =
+      (struct ast_expression *) ast;
+   static const int operations[AST_NUM_OPERATORS] = {
+      -1,               /* ast_assign doesn't convert to ir_expression. */
+      -1,               /* ast_plus doesn't convert to ir_expression. */
+      ir_unop_neg,
+      ir_binop_add,
+      ir_binop_sub,
+      ir_binop_mul,
+      ir_binop_div,
+      ir_binop_mod,
+      ir_binop_lshift,
+      ir_binop_rshift,
+      ir_binop_less,
+      ir_binop_greater,
+      ir_binop_lequal,
+      ir_binop_gequal,
+      ir_binop_equal,
+      ir_binop_nequal,
+      ir_binop_bit_and,
+      ir_binop_bit_xor,
+      ir_binop_bit_or,
+      ir_unop_bit_not,
+      ir_binop_logic_and,
+      ir_binop_logic_xor,
+      ir_binop_logic_or,
+      ir_unop_logic_not,
+
+      /* Note: The following block of expression types actually convert
+       * to multiple IR instructions.
+       */
+      ir_binop_mul,     /* ast_mul_assign */
+      ir_binop_div,     /* ast_div_assign */
+      ir_binop_mod,     /* ast_mod_assign */
+      ir_binop_add,     /* ast_add_assign */
+      ir_binop_sub,     /* ast_sub_assign */
+      ir_binop_lshift,  /* ast_ls_assign */
+      ir_binop_rshift,  /* ast_rs_assign */
+      ir_binop_bit_and, /* ast_and_assign */
+      ir_binop_bit_xor, /* ast_xor_assign */
+      ir_binop_bit_or,  /* ast_or_assign */
+
+      -1,               /* ast_conditional doesn't convert to ir_expression. */
+      -1,               /* ast_pre_inc doesn't convert to ir_expression. */
+      -1,               /* ast_pre_dec doesn't convert to ir_expression. */
+      -1,               /* ast_post_inc doesn't convert to ir_expression. */
+      -1,               /* ast_post_dec doesn't convert to ir_expression. */
+      -1,               /* ast_field_selection doesn't conv to ir_expression. */
+      -1,               /* ast_array_index doesn't convert to ir_expression. */
+      -1,               /* ast_function_call doesn't conv to ir_expression. */
+      -1,               /* ast_identifier doesn't convert to ir_expression. */
+      -1,               /* ast_int_constant doesn't convert to ir_expression. */
+      -1,               /* ast_uint_constant doesn't conv to ir_expression. */
+      -1,               /* ast_float_constant doesn't conv to ir_expression. */
+      -1,               /* ast_bool_constant doesn't conv to ir_expression. */
+      -1,               /* ast_sequence doesn't convert to ir_expression. */
+   };
+   struct ir_instruction *result = NULL;
+   struct ir_instruction *op[2];
+   struct simple_node op_list;
+   const struct glsl_type *type = glsl_error_type;
+   bool error_emitted = false;
+   YYLTYPE loc;
+
+   loc = ast->get_location();
+   make_empty_list(& op_list);
+
+   switch (expr->oper) {
+   case ast_assign:
+      op[0] = _mesa_ast_to_hir(expr->subexpressions[0], instructions, state);
+      op[1] = _mesa_ast_to_hir(expr->subexpressions[1], instructions, state);
+
+      error_emitted = ((op[0]->type == glsl_error_type)
+                      || (op[1]->type == glsl_error_type));
+
+      type = op[0]->type;
+      if (!error_emitted) {
+        YYLTYPE loc;
+
+        /* FINISHME: This does not handle 'foo.bar.a.b.c[5].d = 5' */
+        loc = expr->subexpressions[0]->get_location();
+        if (op[0]->mode != ir_op_dereference) {
+           _mesa_glsl_error(& loc, state, "invalid lvalue in assignment");
+           error_emitted = true;
+
+           type = glsl_error_type;
+        } else {
+           const struct ir_dereference *const ref =
+              (struct ir_dereference *) op[0];
+           const struct ir_variable *const var =
+              (struct ir_variable *) ref->var;
+
+           if ((var != NULL)
+               && (var->mode == ir_op_var_decl)
+               && (var->read_only)) {
+              _mesa_glsl_error(& loc, state, "cannot assign to read-only "
+                               "variable `%s'", var->name);
+              error_emitted = true;
+
+              type = glsl_error_type;
+           }
+        }
+      }
+
+      /* FINISHME: Check that the LHS and RHS have matching types. */
+      /* FINISHME: For GLSL 1.10, check that the types are not arrays. */
+
+      result = new ir_assignment(op[0], op[1], NULL);
+      break;
+
+   case ast_plus:
+      op[0] = _mesa_ast_to_hir(expr->subexpressions[0], instructions, state);
+
+      error_emitted = (op[0]->type == glsl_error_type);
+      if (type == glsl_error_type)
+        op[0]->type = type;
+
+      result = op[0];
+      break;
+
+   case ast_neg:
+      op[0] = _mesa_ast_to_hir(expr->subexpressions[0], instructions, state);
+
+      type = unary_arithmetic_result_type(op[0]->type);
+
+      error_emitted = (op[0]->type == glsl_error_type);
+
+      result = new ir_expression(operations[expr->oper], type,
+                                op[0], NULL);
+      break;
+
+   case ast_add:
+   case ast_sub:
+   case ast_mul:
+   case ast_div:
+      op[0] = _mesa_ast_to_hir(expr->subexpressions[0], instructions, state);
+      op[1] = _mesa_ast_to_hir(expr->subexpressions[1], instructions, state);
+
+      type = arithmetic_result_type(op[0]->type, op[1]->type,
+                                   (expr->operr == ast_mul),
+                                   state);
+
+      result = new ir_expression(operations[expr->oper], type,
+                                op[0], op[1]);
+      break;
+
+   case ast_mod:
+      op[0] = _mesa_ast_to_hir(expr->subexpressions[0], instructions, state);
+      op[1] = _mesa_ast_to_hir(expr->subexpressions[1], instructions, state);
+
+      error_emitted = ((op[0]->type == glsl_error_type)
+                      || (op[1]->type == glsl_error_type));
+
+      type = modulus_result_type(op[0]->type, op[1]->type);
+
+      assert(operations[expr->oper] == ir_binop_mod);
+
+      result = new ir_expression(operations[expr->oper], type,
+                                op[0], op[1]);
+      break;
+
+   case ast_lshift:
+   case ast_rshift:
+      /* FINISHME: Implement bit-shift operators. */
+      break;
+
+   case ast_less:
+   case ast_greater:
+   case ast_lequal:
+   case ast_gequal:
+      op[0] = _mesa_ast_to_hir(expr->subexpressions[0], instructions, state);
+      op[1] = _mesa_ast_to_hir(expr->subexpressions[1], instructions, state);
+
+      error_emitted = ((op[0]->type == glsl_error_type)
+                      || (op[1]->type == glsl_error_type));
+
+      type = relational_result_type(op[0]->type, op[1]->type, state);
+
+      /* The relational operators must either generate an error or result
+       * in a scalar boolean.  See page 57 of the GLSL 1.50 spec.
+       */
+      assert((type == glsl_error_type)
+            || ((type->base_type == GLSL_TYPE_BOOL)
+                && is_glsl_type_scalar(type)));
+
+      result = new ir_expression(operations[expr->oper], type,
+                                op[0], op[1]);
+      break;
+
+   case ast_nequal:
+   case ast_equal:
+      /* FINISHME: Implement equality operators. */
+      break;
+
+   case ast_bit_and:
+   case ast_bit_xor:
+   case ast_bit_or:
+   case ast_bit_not:
+      /* FINISHME: Implement bit-wise operators. */
+      break;
+
+   case ast_logic_and:
+   case ast_logic_xor:
+   case ast_logic_or:
+   case ast_logic_not:
+      /* FINISHME: Implement logical operators. */
+      break;
+
+   case ast_mul_assign:
+   case ast_div_assign:
+   case ast_add_assign:
+   case ast_sub_assign: {
+      struct ir_instruction *temp_rhs;
+
+      op[0] = _mesa_ast_to_hir(expr->subexpressions[0], instructions, state);
+      op[1] = _mesa_ast_to_hir(expr->subexpressions[1], instructions, state);
+
+      error_emitted = ((op[0]->type == glsl_error_type)
+                      || (op[1]->type == glsl_error_type));
+
+      type = arithmetic_result_type(op[0]->type, op[1]->type,
+                                   (expr->oper == ast_mul_assign),
+                                   state);
+
+      temp_rhs = new ir_expression(operations[expr->oper], type,
+                                  op[0], op[1]);
+
+      /* FINISHME: Check that the LHS is assignable. */
+
+      /* We still have to test that the LHS and RHS have matching type.  For
+       * example, the following GLSL code should generate a type error:
+       *
+       *    mat4 m; vec4 v; m *= v;
+       *
+       * The type of (m*v) is a vec4, but the type of m is a mat4.
+       *
+       * FINISHME: Is multiplication between a matrix and a vector the only
+       * FINISHME: case that resuls in mismatched types?
+       */
+      /* FINISHME: Check that the LHS and RHS have matching types. */
+
+      /* GLSL 1.10 does not allow array assignment.  However, we don't have to
+       * explicitly test for this because none of the binary expression
+       * operators allow array operands either.
+       */
+
+      /* FINISHME: This is wrong.  The operation should assign to a new
+       * FINISHME: temporary.  This assignment should then be added to the
+       * FINISHME: instruction list.  Another assignment to the real
+       * FINISHME: destination should be generated.  The temporary should then
+       * FINISHME: be returned as the r-value.
+       */
+      result = new ir_assignment(op[0], temp_rhs, NULL);
+      break;
+   }
+
+   case ast_mod_assign:
+
+   case ast_ls_assign:
+   case ast_rs_assign:
+
+   case ast_and_assign:
+   case ast_xor_assign:
+   case ast_or_assign:
+
+   case ast_conditional:
+
+   case ast_pre_inc:
+   case ast_pre_dec:
+
+   case ast_post_inc:
+   case ast_post_dec:
+      break;
+
+   case ast_field_selection:
+      result = _mesa_ast_field_selection_to_hir(expr, instructions, state);
+      type = result->type;
+      break;
+
+   case ast_array_index:
+      break;
+
+   case ast_function_call:
+      /* There are three sorts of function calls.
+       *
+       * 1. contstructors - The first subexpression is an ast_type_specifier.
+       * 2. methods - Only the .length() method of array types.
+       * 3. functions - Calls to regular old functions.
+       *
+       * Method calls are actually detected when the ast_field_selection
+       * expression is handled.
+       */
+      result = _mesa_ast_function_call_to_hir(expr->subexpressions[0],
+                                             expr->subexpressions[1],
+                                             state);
+      type = result->type;
+      break;
+
+   case ast_identifier: {
+      /* ast_identifier can appear several places in a full abstract syntax
+       * tree.  This particular use must be at location specified in the grammar
+       * as 'variable_identifier'.
+       */
+      struct ir_variable *var =
+        _mesa_symbol_table_find_symbol(state->symbols, 0,
+                                       expr->primary_expression.identifier);
+
+      result = new ir_dereference(var);
+
+      if (var != NULL) {
+        type = result->type;
+      } else {
+        _mesa_glsl_error(& loc, NULL, "`%s' undeclared",
+                         expr->primary_expression.identifier);
+
+        error_emitted = true;
+      }
+      break;
+   }
+
+   case ast_int_constant:
+      type = glsl_int_type;
+      result = new ir_constant(type, & expr->primary_expression);
+      break;
+
+   case ast_uint_constant:
+      type = glsl_uint_type;
+      result = new ir_constant(type, & expr->primary_expression);
+      break;
+
+   case ast_float_constant:
+      type = glsl_float_type;
+      result = new ir_constant(type, & expr->primary_expression);
+      break;
+
+   case ast_bool_constant:
+      type = glsl_bool_type;
+      result = new ir_constant(type, & expr->primary_expression);
+      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(&expr->expressions));
+
+      /* 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, &expr->expressions)
+        result = _mesa_ast_to_hir(ptr, instructions, state);
+
+      type = result->type;
+
+      /* Any errors should have already been emitted in the loop above.
+       */
+      error_emitted = true;
+      break;
+   }
+   }
+
+   if (is_error_type(type) && !error_emitted)
+      _mesa_glsl_error(& loc, NULL, "type mismatch");
+
+   return result;
+}
+
+
+struct ir_instruction *
+ast_expression_statement_to_hir(const struct ast_node *ast,
+                               struct simple_node *instructions,
+                               struct _mesa_glsl_parse_state *state)
+{
+   const struct ast_expression_statement *stmt =
+      (struct ast_expression_statement *) ast;
+
+   /* It is possible to have expression statements that don't have an
+    * expression.  This is the solitary semicolon:
+    *
+    * for (i = 0; i < 5; i++)
+    *     ;
+    *
+    * In this case the expression will be NULL.  Test for NULL and don't do
+    * anything in that case.
+    */
+   if (stmt->expression != NULL)
+      _mesa_ast_to_hir(stmt->expression, instructions, state);
+
+   /* Statements do not have r-values.
+    */
+   return NULL;
+}
+
+
+struct ir_instruction *
+ast_compound_statement_to_hir(const struct ast_node *ast,
+                             struct simple_node *instructions,
+                             struct _mesa_glsl_parse_state *state)
+{
+   const struct ast_compound_statement *stmt =
+      (struct ast_compound_statement *) ast;
+   struct simple_node *ptr;
+
+
+   if (stmt->new_scope)
+      _mesa_symbol_table_push_scope(state->symbols);
+
+   foreach (ptr, &stmt->statements)
+      _mesa_ast_to_hir(ptr, instructions, state);
+
+   if (stmt->new_scope)
+      _mesa_symbol_table_pop_scope(state->symbols);
+
+   /* Compound statements do not have r-values.
+    */
+   return NULL;
+}
+
+
+static const struct glsl_type *
+type_specifier_to_glsl_type(const struct ast_type_specifier *spec,
+                           const char **name,
+                           struct _mesa_glsl_parse_state *state)
+{
+   static const char *const type_names[] = {
+      "void",
+      "float",
+      "int",
+      "uint",
+      "bool",
+      "vec2",
+      "vec3",
+      "vec4",
+      "bvec2",
+      "bvec3",
+      "bvec4",
+      "ivec2",
+      "ivec3",
+      "ivec4",
+      "uvec2",
+      "uvec3",
+      "uvec4",
+      "mat2",
+      "mat2x3",
+      "mat2x4",
+      "mat3x2",
+      "mat3",
+      "mat3x4",
+      "mat4x2",
+      "mat4x3",
+      "mat4",
+      "sampler1D",
+      "sampler2D",
+      "sampler3D",
+      "samplerCube",
+      "sampler1DShadow",
+      "sampler2DShadow",
+      "samplerCubeShadow",
+      "sampler1DArray",
+      "sampler2DArray",
+      "sampler1DArrayShadow",
+      "sampler2DArrayShadow",
+      "isampler1D",
+      "isampler2D",
+      "isampler3D",
+      "isamplerCube",
+      "isampler1DArray",
+      "isampler2DArray",
+      "usampler1D",
+      "usampler2D",
+      "usampler3D",
+      "usamplerCube",
+      "usampler1DArray",
+      "usampler2DArray",
+
+      NULL, /* ast_struct */
+      NULL  /* ast_type_name */
+   };
+   struct glsl_type *type;
+   const char *type_name = NULL;
+
+   if (spec->type_specifier == ast_struct) {
+      /* FINISHME: Handle annonymous structures. */
+      type = NULL;
+   } else {
+      type_name = (spec->type_specifier == ast_type_name)
+        ? spec->type_name : type_names[spec->type_specifier];
+
+      type = _mesa_symbol_table_find_symbol(state->symbols, 0, type_name);
+      *name = type_name;
+
+      /* FINISHME: Handle array declarations.  Note that this requires complete
+       * FINSIHME: handling of constant expressions.
+       */
+   }
+
+   return type;
+}
+
+
+static void
+apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual,
+                                struct ir_variable *var,
+                                struct _mesa_glsl_parse_state *state)
+{
+   if (qual->invariant)
+      var->invariant = 1;
+
+   /* FINISHME: Mark 'in' variables at global scope as read-only. */
+   if (qual->constant || qual->attribute || qual->uniform
+       || (qual->varying && (state->target == fragment_shader)))
+      var->read_only = 1;
+
+   if (qual->centroid)
+      var->centroid = 1;
+
+   if (qual->in && qual->out)
+      var->mode = ir_var_inout;
+   else if (qual->attribute || qual->in
+           || (qual->varying && (state->target == fragment_shader)))
+      var->mode = ir_var_in;
+   else if (qual->out)
+      var->mode = ir_var_out;
+   else if (qual->uniform)
+      var->mode = ir_var_uniform;
+   else
+      var->mode = ir_var_auto;
+
+   if (qual->flat)
+      var->interpolation = ir_var_flat;
+   else if (qual->noperspective)
+      var->interpolation = ir_var_noperspective;
+   else
+      var->interpolation = ir_var_smooth;
+}
+
+
+struct ir_instruction *
+ast_declarator_list_to_hir(const struct ast_node *ast,
+                          struct simple_node *instructions,
+                          struct _mesa_glsl_parse_state *state)
+{
+   const struct ast_declarator_list *dlist = (struct ast_declarator_list *) ast;
+   struct simple_node *ptr;
+   const struct glsl_type *decl_type;
+   const char *type_name = NULL;
+
+
+   /* FINISHME: Handle vertex shader "invariant" declarations that do not
+    * FINISHME: include a type.  These re-declare built-in variables to be
+    * FINISHME: invariant.
+    */
+
+   decl_type = type_specifier_to_glsl_type(dlist->type->specifier,
+                                          & type_name, state);
+
+   foreach (ptr, &dlist->declarations) {
+      struct ast_declaration *const decl = (struct ast_declaration * )ptr;
+      const struct glsl_type *var_type;
+      struct ir_variable *var;
+
+
+      /* FINISHME: Emit a warning if a variable declaration shadows a
+       * FINISHME: declaration at a higher scope.
+       */
+
+      if (decl_type == NULL) {
+        YYLTYPE loc;
+
+        loc = ast->get_location();
+        if (type_name != NULL) {
+           _mesa_glsl_error(& loc, state,
+                            "invalid type `%s' in declaration of `%s'",
+                            type_name, decl->identifier);
+        } else {
+           _mesa_glsl_error(& loc, state,
+                            "invalid type in declaration of `%s'",
+                            decl->identifier);
+        }
+        continue;
+      }
+
+      if (decl->is_array) {
+        /* FINISHME: Handle array declarations.  Note that this requires
+         * FINISHME: complete handling of constant expressions.
+         */
+
+        /* FINISHME: Reject delcarations of multidimensional arrays. */
+      } else {
+        var_type = decl_type;
+      }
+
+      var = new ir_variable(var_type, decl->identifier);
+
+      /* FINSIHME: Variables that are attribute, uniform, varying, in, or
+       * FINISHME: out varibles must be declared either at global scope or
+       * FINISHME: in a parameter list (in and out only).
+       */
+
+      apply_type_qualifier_to_variable(& dlist->type->qualifier, var, state);
+
+      /* Attempt to add the variable to the symbol table.  If this fails, it
+       * means the variable has already been declared at this scope.
+       */
+      if (_mesa_symbol_table_add_symbol(state->symbols, 0, decl->identifier,
+                                       var) != 0) {
+        YYLTYPE loc = ast->get_location();
+
+        _mesa_glsl_error(& loc, state, "`%s' redeclared",
+                         decl->identifier);
+        continue;
+      }
+
+      insert_at_tail(instructions, (struct simple_node *) var);
+
+      /* FINISHME: Process the declaration initializer. */
+   }
+
+   /* Variable declarations do not have r-values.
+    */
+   return NULL;
+}
+
+
+struct ir_instruction *
+ast_parameter_declarator_to_hir(const struct ast_node *ast,
+                               struct simple_node *instructions,
+                               struct _mesa_glsl_parse_state *state)
+{
+   const struct ast_parameter_declarator *decl =
+      (struct ast_parameter_declarator *) ast;
+   struct ir_variable *var;
+   const struct glsl_type *type;
+   const char *name = NULL;
+
+
+   type = type_specifier_to_glsl_type(decl->type->specifier, & name, state);
+
+   if (type == NULL) {
+      YYLTYPE loc = ast->get_location();
+      if (name != NULL) {
+        _mesa_glsl_error(& loc, state,
+                         "invalid type `%s' in declaration of `%s'",
+                         name, decl->identifier);
+      } else {
+        _mesa_glsl_error(& loc, state,
+                         "invalid type in declaration of `%s'",
+                         decl->identifier);
+      }
+
+      type = glsl_error_type;
+   }
+
+   var = new ir_variable(type, decl->identifier);
+
+   /* FINISHME: Handle array declarations.  Note that this requires
+    * FINISHME: complete handling of constant expressions.
+    */
+
+   apply_type_qualifier_to_variable(& decl->type->qualifier, var, state);
+
+   insert_at_tail(instructions, var);
+
+   /* Parameter declarations do not have r-values.
+    */
+   return NULL;
+}
+
+
+static void
+ast_function_parameters_to_hir(struct simple_node *ast_parameters,
+                              struct simple_node *ir_parameters,
+                              struct _mesa_glsl_parse_state *state)
+{
+   struct simple_node *ptr;
+
+   foreach (ptr, ast_parameters) {
+      _mesa_ast_to_hir(ptr, ir_parameters, state);
+   }
+}
+
+
+static bool
+parameter_lists_match(struct simple_node *list_a, struct simple_node *list_b)
+{
+   struct simple_node *node_a;
+   struct simple_node *node_b;
+
+   node_b = first_elem(list_b);
+   foreach (node_a, list_a) {
+      /* If all of the parameters from the other parameter list have been
+       * exhausted, the lists have different length and, by definition,
+       * do not match.
+       */
+      if (at_end(list_b, node_b))
+        return false;
+
+      /* If the types of the parameters do not match, the parameters lists
+       * are different.
+       */
+      /* FINISHME */
+
+
+      node_b = next_elem(node_b);
+   }
+
+   return true;
+}
+
+
+struct ir_instruction *
+ast_function_definition_to_hir(const struct ast_node *ast,
+                              struct simple_node *instructions,
+                              struct _mesa_glsl_parse_state *state)
+{
+   const struct ast_function_definition *func =
+      (struct ast_function_definition *) ast;
+   struct ir_label *label;
+   struct simple_node *ptr;
+   struct simple_node *tmp;
+   struct ir_function_signature *signature = NULL;
+   struct ir_function *f = NULL;
+   struct simple_node parameters;
+
+
+   /* 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.
+    */
+   make_empty_list(& parameters);
+   ast_function_parameters_to_hir(& func->prototype->parameters, & parameters,
+                                 state);
+
+
+   /* Verify that this function's signature either doesn't match a previously
+    * seen signature for a function with the same name, or, if a match is found,
+    * that the previously seen signature does not have an associated definition.
+    */
+   f = _mesa_symbol_table_find_symbol(state->symbols, 0,
+                                     func->prototype->identifier);
+   if (f != NULL) {
+      foreach (ptr, & f->signatures) {
+        signature = (struct ir_function_signature *) ptr;
+
+        /* Compare the parameter list of the function being defined to the
+         * existing function.  If the parameter lists match, then the return
+         * type must also match and the existing function must not have a
+         * definition.
+         */
+        if (parameter_lists_match(& parameters, & signature->parameters)) {
+           /* FINISHME: Compare return types. */
+
+           if (signature->definition != NULL) {
+              YYLTYPE loc = ast->get_location();
+
+              _mesa_glsl_error(& loc, state, "function `%s' redefined",
+                               func->prototype->identifier);
+              signature = NULL;
+              break;
+           }
+        }
+
+        signature = NULL;
+      }
+
+   } else {
+      f = new ir_function();
+      f->name = func->prototype->identifier;
+
+      _mesa_symbol_table_add_symbol(state->symbols, 0, f->name, f);
+   }
+
+
+   /* Finish storing the information about this new function in its signature.
+    */
+   if (signature == NULL) {
+      signature = new ir_function_signature();
+      insert_at_tail(& f->signatures, (struct simple_node *) signature);
+   } else {
+      /* Destroy all of the previous parameter information.  The previous
+       * parameter information comes from the function prototype, and it can
+       * either include invalid parameter names or may not have names at all.
+       */
+      foreach_s(ptr, tmp, & signature->parameters) {
+        assert(((struct ir_instruction *)ptr)->mode == ir_op_var_decl);
+
+        remove_from_list(ptr);
+        free(ptr);
+      }
+   }
+
+
+   ast_function_parameters_to_hir(& func->prototype->parameters,
+                                 & signature->parameters,
+                                 state);
+   /* FINISHME: Set signature->return_type */
+
+   label = new ir_label(func->prototype->identifier);
+   if (signature->definition == NULL) {
+      signature->definition = label;
+   }
+   insert_at_tail(instructions, label);
+
+   /* Add the function parameters to the symbol table.  During this step the
+    * parameter declarations are also moved from the temporary "parameters" list
+    * to the instruction list.  There are other more efficient ways to do this,
+    * but they involve ugly linked-list gymnastics.
+    */
+   _mesa_symbol_table_push_scope(state->symbols);
+   foreach_s(ptr, tmp, & parameters) {
+      struct ir_variable *const var = (struct ir_variable *) ptr;
+
+      assert(var->mode == ir_op_var_decl);
+
+      remove_from_list(ptr);
+      insert_at_tail(instructions, ptr);
+
+      _mesa_symbol_table_add_symbol(state->symbols, 0, var->name, var);
+   }
+
+   /* Convert the body of the function to HIR, and append the resulting
+    * instructions to the list that currently consists of the function label
+    * and the function parameters.
+    */
+   _mesa_ast_to_hir(func->body, instructions, state);
+
+   _mesa_symbol_table_pop_scope(state->symbols);
+
+
+   /* Function definitions do not have r-values.
+    */
+   return NULL;
+}
diff --git a/glsl_parser_extras.cc b/glsl_parser_extras.cc
deleted file mode 100644 (file)
index 36a6ca8..0000000
+++ /dev/null
@@ -1,771 +0,0 @@
-/*
- * Copyright © 2008, 2009 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-#include <stdio.h>
-#include <stdarg.h>
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-    
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-
-#include "ast.h"
-#include "glsl_parser_extras.h"
-#include "glsl_parser.tab.h"
-#include "symbol_table.h"
-
-void
-_mesa_glsl_error(YYLTYPE *locp, void *state, const char *fmt, ...)
-{
-   char buf[1024];
-   int len;
-   va_list ap;
-
-   (void) state;
-   len = snprintf(buf, sizeof(buf), "%u:%u(%u): error: ",
-                 locp->source, locp->first_line, locp->first_column);
-
-   va_start(ap, fmt);
-   vsnprintf(buf + len, sizeof(buf) - len, fmt, ap);
-   va_end(ap);
-
-   printf("%s\n", buf);
-}
-
-
-ast_node::~ast_node()
-{
-   /* empty */
-}
-
-
-void
-_mesa_ast_type_qualifier_print(const struct ast_type_qualifier *q)
-{
-   if (q->constant)
-      printf("const ");
-
-   if (q->invariant)
-      printf("invariant ");
-
-   if (q->attribute)
-      printf("attribute ");
-
-   if (q->varying)
-      printf("varying ");
-
-   if (q->in && q->out) 
-      printf("inout ");
-   else {
-      if (q->in)
-        printf("in ");
-
-      if (q->out)
-        printf("out ");
-   }
-
-   if (q->centroid)
-      printf("centroid ");
-   if (q->uniform)
-      printf("uniform ");
-   if (q->smooth)
-      printf("smooth ");
-   if (q->flat)
-      printf("flat ");
-   if (q->noperspective)
-      printf("noperspective ");
-}
-
-
-void
-ast_node::print(void) const
-{
-   printf("node_%d ", type);
-}
-
-
-ast_node::ast_node(void)
-{
-   make_empty_list(this);
-}
-
-void
-ast_type_specifier::print(void) const
-{
-   switch (type_specifier) {
-   case ast_void: printf("void "); break;
-   case ast_float: printf("float "); break;
-   case ast_int: printf("int "); break;
-   case ast_uint: printf("uint "); break;
-   case ast_bool: printf("bool "); break;
-   case ast_vec2: printf("vec2 "); break;
-   case ast_vec3: printf("vec3 "); break;
-   case ast_vec4: printf("vec4 "); break;
-   case ast_bvec2: printf("bvec2 "); break;
-   case ast_bvec3: printf("bvec3 "); break;
-   case ast_bvec4: printf("bvec4 "); break;
-   case ast_ivec2: printf("ivec2 "); break;
-   case ast_ivec3: printf("ivec3 "); break;
-   case ast_ivec4: printf("ivec4 "); break;
-   case ast_uvec2: printf("uvec2 "); break;
-   case ast_uvec3: printf("uvec3 "); break;
-   case ast_uvec4: printf("uvec4 "); break;
-   case ast_mat2: printf("mat2 "); break;
-   case ast_mat2x3: printf("mat2x3 "); break;
-   case ast_mat2x4: printf("mat2x4 "); break;
-   case ast_mat3x2: printf("mat3x2 "); break;
-   case ast_mat3: printf("mat3 "); break;
-   case ast_mat3x4: printf("mat3x4 "); break;
-   case ast_mat4x2: printf("mat4x2 "); break;
-   case ast_mat4x3: printf("mat4x3 "); break;
-   case ast_mat4: printf("mat4 "); break;
-   case ast_sampler1d: printf("sampler1d "); break;
-   case ast_sampler2d: printf("sampler2d "); break;
-   case ast_sampler3d: printf("sampler3d "); break;
-   case ast_samplercube: printf("samplercube "); break;
-   case ast_sampler1dshadow: printf("sampler1dshadow "); break;
-   case ast_sampler2dshadow: printf("sampler2dshadow "); break;
-   case ast_samplercubeshadow: printf("samplercubeshadow "); break;
-   case ast_sampler1darray: printf("sampler1darray "); break;
-   case ast_sampler2darray: printf("sampler2darray "); break;
-   case ast_sampler1darrayshadow: printf("sampler1darrayshadow "); break;
-   case ast_sampler2darrayshadow: printf("sampler2darrayshadow "); break;
-   case ast_isampler1d: printf("isampler1d "); break;
-   case ast_isampler2d: printf("isampler2d "); break;
-   case ast_isampler3d: printf("isampler3d "); break;
-   case ast_isamplercube: printf("isamplercube "); break;
-   case ast_isampler1darray: printf("isampler1darray "); break;
-   case ast_isampler2darray: printf("isampler2darray "); break;
-   case ast_usampler1d: printf("usampler1d "); break;
-   case ast_usampler2d: printf("usampler2d "); break;
-   case ast_usampler3d: printf("usampler3d "); break;
-   case ast_usamplercube: printf("usamplercube "); break;
-   case ast_usampler1darray: printf("usampler1darray "); break;
-   case ast_usampler2darray: printf("usampler2darray "); break;
-
-   case ast_struct:
-      structure->print();
-      break;
-
-   case ast_type_name: printf("%s ", type_name); break;
-   }
-
-   if (is_array) {
-      printf("[ ");
-
-      if (array_size) {
-        array_size->print();
-      }
-
-      printf("] ");
-   }
-}
-
-static void
-ast_opt_array_size_print(bool is_array, const ast_expression *array_size)
-{
-   if (is_array) {
-      printf("[ ");
-
-      if (array_size)
-        array_size->print();
-
-      printf("] ");
-   }
-}
-
-
-ast_type_specifier::ast_type_specifier(int specifier)
-{
-   type_specifier = ast_types(specifier);
-}
-
-
-void
-ast_compound_statement::print(void) const
-{
-   const struct simple_node *ptr;
-
-   printf("{\n");
-   
-   foreach(ptr, & statements) {
-      _mesa_ast_print(ptr);
-   }
-
-   printf("}\n");
-}
-
-
-ast_compound_statement::ast_compound_statement(int new_scope,
-                                              ast_node *statements)
-{
-   this->new_scope = new_scope;
-   make_empty_list(& this->statements);
-
-   if (statements != NULL) {
-      /* This seems odd, but it works.  The simple_list is,
-       * basically, a circular list.  insert_at_tail adds
-       * the specified node to the list before the current
-       * head.
-       */
-      insert_at_tail((struct simple_node *) statements,
-                    & this->statements);
-   }
-}
-
-
-void
-ast_expression::print(void) const
-{
-   static const char *const operators[] = {
-      "=",
-      "+",
-      "-",
-      "+",
-      "-",
-      "*",
-      "/",
-      "%",
-      "<<",
-      ">>",
-      "<",
-      ">",
-      "<=",
-      ">=",
-      "==",
-      "!=",
-      "&",
-      "^",
-      "|",
-      "~",
-      "&&",
-      "^^",
-      "!",
-
-      "*=",
-      "/=",
-      "%=",
-      "+=",
-      "-=",
-      "<<=",
-      ">>=",
-      "&=",
-      "^=",
-      "|=",
-
-      "?:",
-      "++",
-      "--",
-      "++",
-      "--",
-      ".",
-   };
-
-
-   switch (oper) {
-   case ast_assign:
-   case ast_add:
-   case ast_sub:
-   case ast_mul:
-   case ast_div:
-   case ast_mod:
-   case ast_lshift:
-   case ast_rshift:
-   case ast_less:
-   case ast_greater:
-   case ast_lequal:
-   case ast_gequal:
-   case ast_equal:
-   case ast_nequal:
-   case ast_bit_and:
-   case ast_bit_xor:
-   case ast_bit_or:
-   case ast_logic_and:
-   case ast_logic_xor:
-   case ast_logic_or:
-   case ast_mul_assign:
-   case ast_div_assign:
-   case ast_mod_assign:
-   case ast_add_assign:
-   case ast_sub_assign:
-   case ast_ls_assign:
-   case ast_rs_assign:
-   case ast_and_assign:
-   case ast_xor_assign:
-   case ast_or_assign:
-      subexpressions[0]->print();
-      printf("%s ", operators[oper]);
-      subexpressions[1]->print();
-      break;
-
-   case ast_field_selection:
-      subexpressions[0]->print();
-      printf(". %s ", primary_expression.identifier);
-      break;
-
-   case ast_plus:
-   case ast_neg:
-   case ast_bit_not:
-   case ast_logic_not:
-   case ast_pre_inc:
-   case ast_pre_dec:
-      printf("%s ", operators[oper]);
-      subexpressions[0]->print();
-      break;
-
-   case ast_post_inc:
-   case ast_post_dec:
-      subexpressions[0]->print();
-      printf("%s ", operators[oper]);
-      break;
-
-   case ast_conditional:
-      subexpressions[0]->print();
-      printf("? ");
-      subexpressions[1]->print();
-      printf(": ");
-      subexpressions[1]->print();
-      break;
-
-   case ast_array_index:
-      subexpressions[0]->print();
-      printf("[ ");
-      subexpressions[1]->print();
-      printf("] ");
-      break;
-
-   case ast_function_call: {
-      ast_expression *parameters = subexpressions[1];
-
-      subexpressions[0]->print();
-      printf("( ");
-
-      if (parameters != NULL) {
-        struct simple_node *ptr;
-
-        parameters->print();
-        foreach (ptr, (struct simple_node *) parameters) {
-           printf(", ");
-           _mesa_ast_print(ptr);
-        }
-      }
-
-      printf(") ");
-      break;
-   }
-
-   case ast_identifier:
-      printf("%s ", primary_expression.identifier);
-      break;
-
-   case ast_int_constant:
-      printf("%d ", primary_expression.int_constant);
-      break;
-
-   case ast_uint_constant:
-      printf("%u ", primary_expression.uint_constant);
-      break;
-
-   case ast_float_constant:
-      printf("%f ", primary_expression.float_constant);
-      break;
-
-   case ast_bool_constant:
-      printf("%s ",
-            primary_expression.bool_constant
-            ? "true" : "false");
-      break;
-
-   case ast_sequence: {
-      struct simple_node *ptr;
-      struct simple_node *const head = first_elem(& expressions);
-      
-      printf("( ");
-      foreach (ptr, & expressions) {
-        if (ptr != head)
-           printf(", ");
-
-        _mesa_ast_print(ptr);
-      }
-      printf(") ");
-      break;
-   }
-   }
-}
-
-ast_expression::ast_expression(int oper,
-                              ast_expression *ex0,
-                              ast_expression *ex1,
-                              ast_expression *ex2)
-{
-   this->oper = ast_operators(oper);
-   this->subexpressions[0] = ex0;
-   this->subexpressions[1] = ex1;
-   this->subexpressions[2] = ex2;
-   make_empty_list(& expressions);
-}
-
-
-void
-ast_expression_statement::print(void) const
-{
-   if (expression)
-      expression->print();
-
-   printf("; ");
-}
-
-
-ast_expression_statement::ast_expression_statement(ast_expression *ex) :
-   expression(ex)
-{
-   /* empty */
-}
-
-
-void
-ast_function::print(void) const
-{
-   struct simple_node *ptr;
-
-   return_type->print();
-   printf(" %s (", identifier);
-
-   foreach(ptr, & parameters) {
-      _mesa_ast_print(ptr);
-   }
-
-   printf(")");
-}
-
-
-ast_function::ast_function(void)
-{
-   make_empty_list(& parameters);
-}
-
-
-void
-ast_fully_specified_type::print(void) const
-{
-   _mesa_ast_type_qualifier_print(& qualifier);
-   specifier->print();
-}
-
-
-void
-ast_parameter_declarator::print(void) const
-{
-   type->print();
-   if (identifier)
-      printf("%s ", identifier);
-   ast_opt_array_size_print(is_array, array_size);
-}
-
-
-void
-ast_function_definition::print(void) const
-{
-   prototype->print();
-   body->print();
-}
-
-
-void
-ast_declaration::print(void) const
-{
-   printf("%s ", identifier);
-   ast_opt_array_size_print(is_array, array_size);
-
-   if (initializer) {
-      printf("= ");
-      initializer->print();
-   }
-}
-
-
-ast_declaration::ast_declaration(char *identifier, int is_array,
-                                ast_expression *array_size,
-                                ast_expression *initializer)
-{
-   this->identifier = identifier;
-   this->is_array = is_array;
-   this->array_size = array_size;
-   this->initializer = initializer;
-}
-
-
-void
-ast_declarator_list::print(void) const
-{
-   struct simple_node *head;
-   struct simple_node *ptr;
-
-   assert(type || invariant);
-
-   if (type)
-      type->print();
-   else
-      printf("invariant ");
-
-   head = first_elem(& declarations);
-   foreach (ptr, & declarations) {
-      if (ptr != head)
-        printf(", ");
-
-      _mesa_ast_print(ptr);
-   }
-
-   printf("; ");
-}
-
-
-ast_declarator_list::ast_declarator_list(ast_fully_specified_type *type)
-{
-   this->type = type;
-   make_empty_list(& this->declarations);
-}
-
-void
-ast_jump_statement::print(void) const
-{
-   switch (mode) {
-   case ast_continue:
-      printf("continue; ");
-      break;
-   case ast_break:
-      printf("break; ");
-      break;
-   case ast_return:
-      printf("return ");
-      if (opt_return_value)
-        opt_return_value->print();
-
-      printf("; ");
-      break;
-   case ast_discard:
-      printf("discard; ");
-      break;
-   }
-}
-
-
-ast_jump_statement::ast_jump_statement(int mode, ast_expression *return_value)
-{
-   this->mode = ast_jump_modes(mode);
-
-   if (mode == ast_return)
-      opt_return_value = return_value;
-}
-
-
-void
-ast_selection_statement::print(void) const
-{
-   printf("if ( ");
-   condition->print();
-   printf(") ");
-
-   then_statement->print();
-
-   if (else_statement) {
-      printf("else ");
-      else_statement->print();
-   }
-   
-}
-
-
-ast_selection_statement::ast_selection_statement(ast_expression *condition,
-                                                ast_node *then_statement,
-                                                ast_node *else_statement)
-{
-   this->condition = condition;
-   this->then_statement = then_statement;
-   this->else_statement = else_statement;
-}
-
-
-void
-ast_iteration_statement::print(void) const
-{
-   switch (mode) {
-   case ast_for:
-      printf("for( ");
-      if (init_statement)
-        init_statement->print();
-      printf("; ");
-
-      if (condition)
-        condition->print();
-      printf("; ");
-
-      if (rest_expression)
-        rest_expression->print();
-      printf(") ");
-
-      body->print();
-      break;
-
-   case ast_while:
-      printf("while ( ");
-      if (condition)
-        condition->print();
-      printf(") ");
-      body->print();
-      break;
-
-   case ast_do_while:
-      printf("do ");
-      body->print();
-      printf("while ( ");
-      if (condition)
-        condition->print();
-      printf("); ");
-      break;
-   }
-}
-
-
-ast_iteration_statement::ast_iteration_statement(int mode,
-                                                ast_node *init,
-                                                ast_node *condition,
-                                                ast_expression *rest_expression,
-                                                ast_node *body)
-{
-   this->mode = ast_iteration_modes(mode);
-   this->init_statement = init;
-   this->condition = condition;
-   this->rest_expression = rest_expression;
-   this->body = body;
-}
-
-
-void
-ast_struct_specifier::print(void) const
-{
-   struct simple_node *ptr;
-
-   printf("struct %s { ", name);
-   foreach (ptr, & declarations) {
-      _mesa_ast_print(ptr);
-   }
-   printf("} ");
-}
-
-
-ast_struct_specifier::ast_struct_specifier(char *identifier,
-                                          ast_node *declarator_list)
-{
-   name = identifier;
-
-   /* This seems odd, but it works.  The simple_list is,
-    * basically, a circular list.  insert_at_tail adds
-    * the specified node to the list before the current
-    * head.
-    */
-   insert_at_tail((struct simple_node *) declarator_list,
-                 & declarations);
-}
-
-
-static char *
-load_text_file(const char *file_name, size_t *size)
-{
-       char *text = NULL;
-       struct stat st;
-       ssize_t total_read = 0;
-       int fd = open(file_name, O_RDONLY);
-
-       *size = 0;
-       if (fd < 0) {
-               return NULL;
-       }
-
-       if (fstat(fd, & st) == 0) {
-          text = (char *) malloc(st.st_size + 1);
-               if (text != NULL) {
-                       do {
-                               ssize_t bytes = read(fd, text + total_read,
-                                                    st.st_size - total_read);
-                               if (bytes < 0) {
-                                       free(text);
-                                       text = NULL;
-                                       break;
-                               }
-
-                               if (bytes == 0) {
-                                       break;
-                               }
-
-                               total_read += bytes;
-                       } while (total_read < st.st_size);
-
-                       text[total_read] = '\0';
-                       *size = total_read;
-               }
-       }
-
-       close(fd);
-
-       return text;
-}
-
-
-int
-main(int argc, char **argv)
-{
-   struct _mesa_glsl_parse_state state;
-   char *shader;
-   size_t shader_len;
-   struct simple_node *ptr;
-   struct simple_node instructions;
-
-   (void) argc;
-   shader = load_text_file(argv[1], & shader_len);
-
-   state.scanner = NULL;
-   make_empty_list(& state.translation_unit);
-   state.symbols = _mesa_symbol_table_ctor();
-
-   _mesa_glsl_lexer_ctor(& state, shader, shader_len);
-   _mesa_glsl_parse(& state);
-   _mesa_glsl_lexer_dtor(& state);
-
-   foreach (ptr, & state.translation_unit) {
-      _mesa_ast_print(ptr);
-   }
-
-#if 0
-   make_empty_list(& instructions);
-   foreach (ptr, & state.translation_unit) {
-      _mesa_ast_to_hir(ptr, &instructions, &state);
-   }
-#endif
-
-   _mesa_symbol_table_dtor(state.symbols);
-
-   return 0;
-}
diff --git a/glsl_parser_extras.cpp b/glsl_parser_extras.cpp
new file mode 100644 (file)
index 0000000..36a6ca8
--- /dev/null
@@ -0,0 +1,771 @@
+/*
+ * Copyright © 2008, 2009 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+    
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include "ast.h"
+#include "glsl_parser_extras.h"
+#include "glsl_parser.tab.h"
+#include "symbol_table.h"
+
+void
+_mesa_glsl_error(YYLTYPE *locp, void *state, const char *fmt, ...)
+{
+   char buf[1024];
+   int len;
+   va_list ap;
+
+   (void) state;
+   len = snprintf(buf, sizeof(buf), "%u:%u(%u): error: ",
+                 locp->source, locp->first_line, locp->first_column);
+
+   va_start(ap, fmt);
+   vsnprintf(buf + len, sizeof(buf) - len, fmt, ap);
+   va_end(ap);
+
+   printf("%s\n", buf);
+}
+
+
+ast_node::~ast_node()
+{
+   /* empty */
+}
+
+
+void
+_mesa_ast_type_qualifier_print(const struct ast_type_qualifier *q)
+{
+   if (q->constant)
+      printf("const ");
+
+   if (q->invariant)
+      printf("invariant ");
+
+   if (q->attribute)
+      printf("attribute ");
+
+   if (q->varying)
+      printf("varying ");
+
+   if (q->in && q->out) 
+      printf("inout ");
+   else {
+      if (q->in)
+        printf("in ");
+
+      if (q->out)
+        printf("out ");
+   }
+
+   if (q->centroid)
+      printf("centroid ");
+   if (q->uniform)
+      printf("uniform ");
+   if (q->smooth)
+      printf("smooth ");
+   if (q->flat)
+      printf("flat ");
+   if (q->noperspective)
+      printf("noperspective ");
+}
+
+
+void
+ast_node::print(void) const
+{
+   printf("node_%d ", type);
+}
+
+
+ast_node::ast_node(void)
+{
+   make_empty_list(this);
+}
+
+void
+ast_type_specifier::print(void) const
+{
+   switch (type_specifier) {
+   case ast_void: printf("void "); break;
+   case ast_float: printf("float "); break;
+   case ast_int: printf("int "); break;
+   case ast_uint: printf("uint "); break;
+   case ast_bool: printf("bool "); break;
+   case ast_vec2: printf("vec2 "); break;
+   case ast_vec3: printf("vec3 "); break;
+   case ast_vec4: printf("vec4 "); break;
+   case ast_bvec2: printf("bvec2 "); break;
+   case ast_bvec3: printf("bvec3 "); break;
+   case ast_bvec4: printf("bvec4 "); break;
+   case ast_ivec2: printf("ivec2 "); break;
+   case ast_ivec3: printf("ivec3 "); break;
+   case ast_ivec4: printf("ivec4 "); break;
+   case ast_uvec2: printf("uvec2 "); break;
+   case ast_uvec3: printf("uvec3 "); break;
+   case ast_uvec4: printf("uvec4 "); break;
+   case ast_mat2: printf("mat2 "); break;
+   case ast_mat2x3: printf("mat2x3 "); break;
+   case ast_mat2x4: printf("mat2x4 "); break;
+   case ast_mat3x2: printf("mat3x2 "); break;
+   case ast_mat3: printf("mat3 "); break;
+   case ast_mat3x4: printf("mat3x4 "); break;
+   case ast_mat4x2: printf("mat4x2 "); break;
+   case ast_mat4x3: printf("mat4x3 "); break;
+   case ast_mat4: printf("mat4 "); break;
+   case ast_sampler1d: printf("sampler1d "); break;
+   case ast_sampler2d: printf("sampler2d "); break;
+   case ast_sampler3d: printf("sampler3d "); break;
+   case ast_samplercube: printf("samplercube "); break;
+   case ast_sampler1dshadow: printf("sampler1dshadow "); break;
+   case ast_sampler2dshadow: printf("sampler2dshadow "); break;
+   case ast_samplercubeshadow: printf("samplercubeshadow "); break;
+   case ast_sampler1darray: printf("sampler1darray "); break;
+   case ast_sampler2darray: printf("sampler2darray "); break;
+   case ast_sampler1darrayshadow: printf("sampler1darrayshadow "); break;
+   case ast_sampler2darrayshadow: printf("sampler2darrayshadow "); break;
+   case ast_isampler1d: printf("isampler1d "); break;
+   case ast_isampler2d: printf("isampler2d "); break;
+   case ast_isampler3d: printf("isampler3d "); break;
+   case ast_isamplercube: printf("isamplercube "); break;
+   case ast_isampler1darray: printf("isampler1darray "); break;
+   case ast_isampler2darray: printf("isampler2darray "); break;
+   case ast_usampler1d: printf("usampler1d "); break;
+   case ast_usampler2d: printf("usampler2d "); break;
+   case ast_usampler3d: printf("usampler3d "); break;
+   case ast_usamplercube: printf("usamplercube "); break;
+   case ast_usampler1darray: printf("usampler1darray "); break;
+   case ast_usampler2darray: printf("usampler2darray "); break;
+
+   case ast_struct:
+      structure->print();
+      break;
+
+   case ast_type_name: printf("%s ", type_name); break;
+   }
+
+   if (is_array) {
+      printf("[ ");
+
+      if (array_size) {
+        array_size->print();
+      }
+
+      printf("] ");
+   }
+}
+
+static void
+ast_opt_array_size_print(bool is_array, const ast_expression *array_size)
+{
+   if (is_array) {
+      printf("[ ");
+
+      if (array_size)
+        array_size->print();
+
+      printf("] ");
+   }
+}
+
+
+ast_type_specifier::ast_type_specifier(int specifier)
+{
+   type_specifier = ast_types(specifier);
+}
+
+
+void
+ast_compound_statement::print(void) const
+{
+   const struct simple_node *ptr;
+
+   printf("{\n");
+   
+   foreach(ptr, & statements) {
+      _mesa_ast_print(ptr);
+   }
+
+   printf("}\n");
+}
+
+
+ast_compound_statement::ast_compound_statement(int new_scope,
+                                              ast_node *statements)
+{
+   this->new_scope = new_scope;
+   make_empty_list(& this->statements);
+
+   if (statements != NULL) {
+      /* This seems odd, but it works.  The simple_list is,
+       * basically, a circular list.  insert_at_tail adds
+       * the specified node to the list before the current
+       * head.
+       */
+      insert_at_tail((struct simple_node *) statements,
+                    & this->statements);
+   }
+}
+
+
+void
+ast_expression::print(void) const
+{
+   static const char *const operators[] = {
+      "=",
+      "+",
+      "-",
+      "+",
+      "-",
+      "*",
+      "/",
+      "%",
+      "<<",
+      ">>",
+      "<",
+      ">",
+      "<=",
+      ">=",
+      "==",
+      "!=",
+      "&",
+      "^",
+      "|",
+      "~",
+      "&&",
+      "^^",
+      "!",
+
+      "*=",
+      "/=",
+      "%=",
+      "+=",
+      "-=",
+      "<<=",
+      ">>=",
+      "&=",
+      "^=",
+      "|=",
+
+      "?:",
+      "++",
+      "--",
+      "++",
+      "--",
+      ".",
+   };
+
+
+   switch (oper) {
+   case ast_assign:
+   case ast_add:
+   case ast_sub:
+   case ast_mul:
+   case ast_div:
+   case ast_mod:
+   case ast_lshift:
+   case ast_rshift:
+   case ast_less:
+   case ast_greater:
+   case ast_lequal:
+   case ast_gequal:
+   case ast_equal:
+   case ast_nequal:
+   case ast_bit_and:
+   case ast_bit_xor:
+   case ast_bit_or:
+   case ast_logic_and:
+   case ast_logic_xor:
+   case ast_logic_or:
+   case ast_mul_assign:
+   case ast_div_assign:
+   case ast_mod_assign:
+   case ast_add_assign:
+   case ast_sub_assign:
+   case ast_ls_assign:
+   case ast_rs_assign:
+   case ast_and_assign:
+   case ast_xor_assign:
+   case ast_or_assign:
+      subexpressions[0]->print();
+      printf("%s ", operators[oper]);
+      subexpressions[1]->print();
+      break;
+
+   case ast_field_selection:
+      subexpressions[0]->print();
+      printf(". %s ", primary_expression.identifier);
+      break;
+
+   case ast_plus:
+   case ast_neg:
+   case ast_bit_not:
+   case ast_logic_not:
+   case ast_pre_inc:
+   case ast_pre_dec:
+      printf("%s ", operators[oper]);
+      subexpressions[0]->print();
+      break;
+
+   case ast_post_inc:
+   case ast_post_dec:
+      subexpressions[0]->print();
+      printf("%s ", operators[oper]);
+      break;
+
+   case ast_conditional:
+      subexpressions[0]->print();
+      printf("? ");
+      subexpressions[1]->print();
+      printf(": ");
+      subexpressions[1]->print();
+      break;
+
+   case ast_array_index:
+      subexpressions[0]->print();
+      printf("[ ");
+      subexpressions[1]->print();
+      printf("] ");
+      break;
+
+   case ast_function_call: {
+      ast_expression *parameters = subexpressions[1];
+
+      subexpressions[0]->print();
+      printf("( ");
+
+      if (parameters != NULL) {
+        struct simple_node *ptr;
+
+        parameters->print();
+        foreach (ptr, (struct simple_node *) parameters) {
+           printf(", ");
+           _mesa_ast_print(ptr);
+        }
+      }
+
+      printf(") ");
+      break;
+   }
+
+   case ast_identifier:
+      printf("%s ", primary_expression.identifier);
+      break;
+
+   case ast_int_constant:
+      printf("%d ", primary_expression.int_constant);
+      break;
+
+   case ast_uint_constant:
+      printf("%u ", primary_expression.uint_constant);
+      break;
+
+   case ast_float_constant:
+      printf("%f ", primary_expression.float_constant);
+      break;
+
+   case ast_bool_constant:
+      printf("%s ",
+            primary_expression.bool_constant
+            ? "true" : "false");
+      break;
+
+   case ast_sequence: {
+      struct simple_node *ptr;
+      struct simple_node *const head = first_elem(& expressions);
+      
+      printf("( ");
+      foreach (ptr, & expressions) {
+        if (ptr != head)
+           printf(", ");
+
+        _mesa_ast_print(ptr);
+      }
+      printf(") ");
+      break;
+   }
+   }
+}
+
+ast_expression::ast_expression(int oper,
+                              ast_expression *ex0,
+                              ast_expression *ex1,
+                              ast_expression *ex2)
+{
+   this->oper = ast_operators(oper);
+   this->subexpressions[0] = ex0;
+   this->subexpressions[1] = ex1;
+   this->subexpressions[2] = ex2;
+   make_empty_list(& expressions);
+}
+
+
+void
+ast_expression_statement::print(void) const
+{
+   if (expression)
+      expression->print();
+
+   printf("; ");
+}
+
+
+ast_expression_statement::ast_expression_statement(ast_expression *ex) :
+   expression(ex)
+{
+   /* empty */
+}
+
+
+void
+ast_function::print(void) const
+{
+   struct simple_node *ptr;
+
+   return_type->print();
+   printf(" %s (", identifier);
+
+   foreach(ptr, & parameters) {
+      _mesa_ast_print(ptr);
+   }
+
+   printf(")");
+}
+
+
+ast_function::ast_function(void)
+{
+   make_empty_list(& parameters);
+}
+
+
+void
+ast_fully_specified_type::print(void) const
+{
+   _mesa_ast_type_qualifier_print(& qualifier);
+   specifier->print();
+}
+
+
+void
+ast_parameter_declarator::print(void) const
+{
+   type->print();
+   if (identifier)
+      printf("%s ", identifier);
+   ast_opt_array_size_print(is_array, array_size);
+}
+
+
+void
+ast_function_definition::print(void) const
+{
+   prototype->print();
+   body->print();
+}
+
+
+void
+ast_declaration::print(void) const
+{
+   printf("%s ", identifier);
+   ast_opt_array_size_print(is_array, array_size);
+
+   if (initializer) {
+      printf("= ");
+      initializer->print();
+   }
+}
+
+
+ast_declaration::ast_declaration(char *identifier, int is_array,
+                                ast_expression *array_size,
+                                ast_expression *initializer)
+{
+   this->identifier = identifier;
+   this->is_array = is_array;
+   this->array_size = array_size;
+   this->initializer = initializer;
+}
+
+
+void
+ast_declarator_list::print(void) const
+{
+   struct simple_node *head;
+   struct simple_node *ptr;
+
+   assert(type || invariant);
+
+   if (type)
+      type->print();
+   else
+      printf("invariant ");
+
+   head = first_elem(& declarations);
+   foreach (ptr, & declarations) {
+      if (ptr != head)
+        printf(", ");
+
+      _mesa_ast_print(ptr);
+   }
+
+   printf("; ");
+}
+
+
+ast_declarator_list::ast_declarator_list(ast_fully_specified_type *type)
+{
+   this->type = type;
+   make_empty_list(& this->declarations);
+}
+
+void
+ast_jump_statement::print(void) const
+{
+   switch (mode) {
+   case ast_continue:
+      printf("continue; ");
+      break;
+   case ast_break:
+      printf("break; ");
+      break;
+   case ast_return:
+      printf("return ");
+      if (opt_return_value)
+        opt_return_value->print();
+
+      printf("; ");
+      break;
+   case ast_discard:
+      printf("discard; ");
+      break;
+   }
+}
+
+
+ast_jump_statement::ast_jump_statement(int mode, ast_expression *return_value)
+{
+   this->mode = ast_jump_modes(mode);
+
+   if (mode == ast_return)
+      opt_return_value = return_value;
+}
+
+
+void
+ast_selection_statement::print(void) const
+{
+   printf("if ( ");
+   condition->print();
+   printf(") ");
+
+   then_statement->print();
+
+   if (else_statement) {
+      printf("else ");
+      else_statement->print();
+   }
+   
+}
+
+
+ast_selection_statement::ast_selection_statement(ast_expression *condition,
+                                                ast_node *then_statement,
+                                                ast_node *else_statement)
+{
+   this->condition = condition;
+   this->then_statement = then_statement;
+   this->else_statement = else_statement;
+}
+
+
+void
+ast_iteration_statement::print(void) const
+{
+   switch (mode) {
+   case ast_for:
+      printf("for( ");
+      if (init_statement)
+        init_statement->print();
+      printf("; ");
+
+      if (condition)
+        condition->print();
+      printf("; ");
+
+      if (rest_expression)
+        rest_expression->print();
+      printf(") ");
+
+      body->print();
+      break;
+
+   case ast_while:
+      printf("while ( ");
+      if (condition)
+        condition->print();
+      printf(") ");
+      body->print();
+      break;
+
+   case ast_do_while:
+      printf("do ");
+      body->print();
+      printf("while ( ");
+      if (condition)
+        condition->print();
+      printf("); ");
+      break;
+   }
+}
+
+
+ast_iteration_statement::ast_iteration_statement(int mode,
+                                                ast_node *init,
+                                                ast_node *condition,
+                                                ast_expression *rest_expression,
+                                                ast_node *body)
+{
+   this->mode = ast_iteration_modes(mode);
+   this->init_statement = init;
+   this->condition = condition;
+   this->rest_expression = rest_expression;
+   this->body = body;
+}
+
+
+void
+ast_struct_specifier::print(void) const
+{
+   struct simple_node *ptr;
+
+   printf("struct %s { ", name);
+   foreach (ptr, & declarations) {
+      _mesa_ast_print(ptr);
+   }
+   printf("} ");
+}
+
+
+ast_struct_specifier::ast_struct_specifier(char *identifier,
+                                          ast_node *declarator_list)
+{
+   name = identifier;
+
+   /* This seems odd, but it works.  The simple_list is,
+    * basically, a circular list.  insert_at_tail adds
+    * the specified node to the list before the current
+    * head.
+    */
+   insert_at_tail((struct simple_node *) declarator_list,
+                 & declarations);
+}
+
+
+static char *
+load_text_file(const char *file_name, size_t *size)
+{
+       char *text = NULL;
+       struct stat st;
+       ssize_t total_read = 0;
+       int fd = open(file_name, O_RDONLY);
+
+       *size = 0;
+       if (fd < 0) {
+               return NULL;
+       }
+
+       if (fstat(fd, & st) == 0) {
+          text = (char *) malloc(st.st_size + 1);
+               if (text != NULL) {
+                       do {
+                               ssize_t bytes = read(fd, text + total_read,
+                                                    st.st_size - total_read);
+                               if (bytes < 0) {
+                                       free(text);
+                                       text = NULL;
+                                       break;
+                               }
+
+                               if (bytes == 0) {
+                                       break;
+                               }
+
+                               total_read += bytes;
+                       } while (total_read < st.st_size);
+
+                       text[total_read] = '\0';
+                       *size = total_read;
+               }
+       }
+
+       close(fd);
+
+       return text;
+}
+
+
+int
+main(int argc, char **argv)
+{
+   struct _mesa_glsl_parse_state state;
+   char *shader;
+   size_t shader_len;
+   struct simple_node *ptr;
+   struct simple_node instructions;
+
+   (void) argc;
+   shader = load_text_file(argv[1], & shader_len);
+
+   state.scanner = NULL;
+   make_empty_list(& state.translation_unit);
+   state.symbols = _mesa_symbol_table_ctor();
+
+   _mesa_glsl_lexer_ctor(& state, shader, shader_len);
+   _mesa_glsl_parse(& state);
+   _mesa_glsl_lexer_dtor(& state);
+
+   foreach (ptr, & state.translation_unit) {
+      _mesa_ast_print(ptr);
+   }
+
+#if 0
+   make_empty_list(& instructions);
+   foreach (ptr, & state.translation_unit) {
+      _mesa_ast_to_hir(ptr, &instructions, &state);
+   }
+#endif
+
+   _mesa_symbol_table_dtor(state.symbols);
+
+   return 0;
+}
diff --git a/hir_field_selection.cc b/hir_field_selection.cc
deleted file mode 100644 (file)
index 295cbaf..0000000
+++ /dev/null
@@ -1,187 +0,0 @@
-/*
- * Copyright © 2010 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-#include <stdio.h>
-#include "main/imports.h"
-#include "symbol_table.h"
-#include "glsl_parser_extras.h"
-#include "ast.h"
-#include "glsl_types.h"
-#include "ir.h"
-
-#define X 1
-#define R 5
-#define S 9
-#define I 13
-
-static bool
-generate_swizzle(const char *str, struct ir_swizzle_mask *swiz,
-                unsigned vector_length)
-{
-   /* For each possible swizzle character, this table encodes the value in
-    * \c idx_map that represents the 0th element of the vector.  For invalid
-    * swizzle characters (e.g., 'k'), a special value is used that will allow
-    * detection of errors.
-    */
-   unsigned char base_idx[26] = {
-   /* a  b  c  d  e  f  g  h  i  j  k  l  m */
-      R, R, I, I, I, I, R, I, I, I, I, I, I,
-   /* n  o  p  q  r  s  t  u  v  w  x  y  z */
-      I, I, S, S, R, S, S, I, I, X, X, X, X
-   };
-
-   /* Each valid swizzle character has an entry in the previous table.  This
-    * table encodes the base index encoded in the previous table plus the actual
-    * index of the swizzle character.  When processing swizzles, the first
-    * character in the string is indexed in the previous table.  Each character
-    * in the string is indexed in this table, and the value found there has the
-    * value form the first table subtracted.  The result must be on the range
-    * [0,3].
-    *
-    * For example, the string "wzyx" will get X from the first table.  Each of
-    * the charcaters will get X+3, X+2, X+1, and X+0 from this table.  After
-    * subtraction, the swizzle values are { 3, 2, 1, 0 }.
-    *
-    * The string "wzrg" will get X from the first table.  Each of the characters
-    * will get X+3, X+2, R+0, and R+1 from this table.  After subtraction, the
-    * swizzle values are { 3, 2, 4, 5 }.  Since 4 and 5 are outside the range
-    * [0,3], the error is detected.
-    */
-   unsigned char idx_map[26] = {
-   /* a    b    c    d    e    f    g    h    i    j    k    l    m */
-      R+3, R+2, 0,   0,   0,   0,   R+1, 0,   0,   0,   0,   0,   0,
-   /* n    o    p    q    r    s    t    u    v    w    x    y    z */
-      0,   0,   S+2, S+3, R+0, S+0, S+1, 0,   0,   X+3, X+0, X+1, X+2
-   };
-
-   int swiz_idx[4] = { 0, 0, 0, 0 };
-   unsigned base;
-   unsigned dup_mask = 0;
-   unsigned seen_mask = 0;
-   unsigned i;
-
-
-   /* Validate the first character in the swizzle string and look up the base
-    * index value as described above.
-    */
-   if ((str[0] < 'a') || (str[0] > 'z'))
-      return FALSE;
-
-   base = base_idx[str[0] - 'a'];
-
-
-   for (i = 0; (i < 4) && (str[i] != '\0'); i++) {
-      unsigned bit;
-
-      /* Validate the next character, and, as described above, convert it to a
-       * swizzle index.
-       */
-      if ((str[i] < 'a') || (str[i] > 'z'))
-        return FALSE;
-
-      swiz_idx[i] = idx_map[str[0] - 'a'] - base;
-      if ((swiz_idx[i] < 0) || (swiz_idx[i] >= (int) vector_length))
-        return FALSE;
-
-
-      /* Track a bit-mask of the swizzle index values that have been seen.  If
-       * a value is seen more than once, set the "duplicate" flag.
-       */
-      bit = (1U << swiz_idx[i]);
-      dup_mask |= seen_mask & bit;
-      seen_mask |= bit;
-   }
-
-   if (str[i] != '\0')
-        return FALSE;
-
-   swiz->x = swiz_idx[0];
-   swiz->y = swiz_idx[1];
-   swiz->z = swiz_idx[2];
-   swiz->w = swiz_idx[3];
-   swiz->num_components = i;
-   swiz->has_duplicates = (dup_mask != 0);
-
-   return TRUE;
-}
-
-
-struct ir_instruction *
-_mesa_ast_field_selection_to_hir(const ast_expression *expr,
-                                simple_node *instructions,
-                                struct _mesa_glsl_parse_state *state)
-{
-   ir_instruction *op;
-   ir_dereference *deref;
-   YYLTYPE loc;
-
-
-   op = _mesa_ast_to_hir(expr->subexpressions[0], instructions, state);
-   deref = new ir_dereference(op);
-
-   /* Initially assume that the resulting type of the field selection is an
-    * error.  This make the error paths below a bit easier to follow.
-    */
-   deref->type = glsl_error_type;
-
-   /* If processing the thing being dereferenced generated an error, bail out
-    * now.  Doing so prevents spurious error messages from being logged below.
-    */
-   if (is_error_type(op->type))
-      return (struct ir_instruction *) deref;
-
-   /* There are two kinds of field selection.  There is the selection of a
-    * specific field from a structure, and there is the selection of a
-    * swizzle / mask from a vector.  Which is which is determined entirely
-    * by the base type of the thing to which the field selection operator is
-    * being applied.
-    */
-   _mesa_ast_get_location(expr, & loc);
-   if (is_glsl_type_vector(op->type)) {
-      if (generate_swizzle(expr->primary_expression.identifier, 
-                          & deref->selector.swizzle,
-                          op->type->vector_elements)) {
-        /* Based on the number of elements in the swizzle and the base type
-         * (i.e., float, int, unsigned, or bool) of the vector being swizzled,
-         * generate the type of the resulting value.
-         */
-        deref->type =
-           _mesa_glsl_get_vector_type(op->type->base_type,
-                                      deref->selector.swizzle.num_components);
-      } else {
-        /* FINISHME: Logging of error messages should be moved into
-         * FINISHME: generate_swizzle.  This allows the generation of more
-         * FINISHME: specific error messages.
-         */
-        _mesa_glsl_error(& loc, state, "Invalid swizzle / mask `%s'",
-                         expr->primary_expression.identifier);
-      }
-   } else if (op->type->base_type == GLSL_TYPE_STRUCT) {
-      /* FINISHME: Handle field selection from structures. */
-   } else {
-      _mesa_glsl_error(& loc, state, "Cannot access field `%s' of "
-                      "non-structure / non-vector.",
-                      expr->primary_expression.identifier);
-   }
-
-   return (struct ir_instruction *) deref;
-}
diff --git a/hir_field_selection.cpp b/hir_field_selection.cpp
new file mode 100644 (file)
index 0000000..295cbaf
--- /dev/null
@@ -0,0 +1,187 @@
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+#include <stdio.h>
+#include "main/imports.h"
+#include "symbol_table.h"
+#include "glsl_parser_extras.h"
+#include "ast.h"
+#include "glsl_types.h"
+#include "ir.h"
+
+#define X 1
+#define R 5
+#define S 9
+#define I 13
+
+static bool
+generate_swizzle(const char *str, struct ir_swizzle_mask *swiz,
+                unsigned vector_length)
+{
+   /* For each possible swizzle character, this table encodes the value in
+    * \c idx_map that represents the 0th element of the vector.  For invalid
+    * swizzle characters (e.g., 'k'), a special value is used that will allow
+    * detection of errors.
+    */
+   unsigned char base_idx[26] = {
+   /* a  b  c  d  e  f  g  h  i  j  k  l  m */
+      R, R, I, I, I, I, R, I, I, I, I, I, I,
+   /* n  o  p  q  r  s  t  u  v  w  x  y  z */
+      I, I, S, S, R, S, S, I, I, X, X, X, X
+   };
+
+   /* Each valid swizzle character has an entry in the previous table.  This
+    * table encodes the base index encoded in the previous table plus the actual
+    * index of the swizzle character.  When processing swizzles, the first
+    * character in the string is indexed in the previous table.  Each character
+    * in the string is indexed in this table, and the value found there has the
+    * value form the first table subtracted.  The result must be on the range
+    * [0,3].
+    *
+    * For example, the string "wzyx" will get X from the first table.  Each of
+    * the charcaters will get X+3, X+2, X+1, and X+0 from this table.  After
+    * subtraction, the swizzle values are { 3, 2, 1, 0 }.
+    *
+    * The string "wzrg" will get X from the first table.  Each of the characters
+    * will get X+3, X+2, R+0, and R+1 from this table.  After subtraction, the
+    * swizzle values are { 3, 2, 4, 5 }.  Since 4 and 5 are outside the range
+    * [0,3], the error is detected.
+    */
+   unsigned char idx_map[26] = {
+   /* a    b    c    d    e    f    g    h    i    j    k    l    m */
+      R+3, R+2, 0,   0,   0,   0,   R+1, 0,   0,   0,   0,   0,   0,
+   /* n    o    p    q    r    s    t    u    v    w    x    y    z */
+      0,   0,   S+2, S+3, R+0, S+0, S+1, 0,   0,   X+3, X+0, X+1, X+2
+   };
+
+   int swiz_idx[4] = { 0, 0, 0, 0 };
+   unsigned base;
+   unsigned dup_mask = 0;
+   unsigned seen_mask = 0;
+   unsigned i;
+
+
+   /* Validate the first character in the swizzle string and look up the base
+    * index value as described above.
+    */
+   if ((str[0] < 'a') || (str[0] > 'z'))
+      return FALSE;
+
+   base = base_idx[str[0] - 'a'];
+
+
+   for (i = 0; (i < 4) && (str[i] != '\0'); i++) {
+      unsigned bit;
+
+      /* Validate the next character, and, as described above, convert it to a
+       * swizzle index.
+       */
+      if ((str[i] < 'a') || (str[i] > 'z'))
+        return FALSE;
+
+      swiz_idx[i] = idx_map[str[0] - 'a'] - base;
+      if ((swiz_idx[i] < 0) || (swiz_idx[i] >= (int) vector_length))
+        return FALSE;
+
+
+      /* Track a bit-mask of the swizzle index values that have been seen.  If
+       * a value is seen more than once, set the "duplicate" flag.
+       */
+      bit = (1U << swiz_idx[i]);
+      dup_mask |= seen_mask & bit;
+      seen_mask |= bit;
+   }
+
+   if (str[i] != '\0')
+        return FALSE;
+
+   swiz->x = swiz_idx[0];
+   swiz->y = swiz_idx[1];
+   swiz->z = swiz_idx[2];
+   swiz->w = swiz_idx[3];
+   swiz->num_components = i;
+   swiz->has_duplicates = (dup_mask != 0);
+
+   return TRUE;
+}
+
+
+struct ir_instruction *
+_mesa_ast_field_selection_to_hir(const ast_expression *expr,
+                                simple_node *instructions,
+                                struct _mesa_glsl_parse_state *state)
+{
+   ir_instruction *op;
+   ir_dereference *deref;
+   YYLTYPE loc;
+
+
+   op = _mesa_ast_to_hir(expr->subexpressions[0], instructions, state);
+   deref = new ir_dereference(op);
+
+   /* Initially assume that the resulting type of the field selection is an
+    * error.  This make the error paths below a bit easier to follow.
+    */
+   deref->type = glsl_error_type;
+
+   /* If processing the thing being dereferenced generated an error, bail out
+    * now.  Doing so prevents spurious error messages from being logged below.
+    */
+   if (is_error_type(op->type))
+      return (struct ir_instruction *) deref;
+
+   /* There are two kinds of field selection.  There is the selection of a
+    * specific field from a structure, and there is the selection of a
+    * swizzle / mask from a vector.  Which is which is determined entirely
+    * by the base type of the thing to which the field selection operator is
+    * being applied.
+    */
+   _mesa_ast_get_location(expr, & loc);
+   if (is_glsl_type_vector(op->type)) {
+      if (generate_swizzle(expr->primary_expression.identifier, 
+                          & deref->selector.swizzle,
+                          op->type->vector_elements)) {
+        /* Based on the number of elements in the swizzle and the base type
+         * (i.e., float, int, unsigned, or bool) of the vector being swizzled,
+         * generate the type of the resulting value.
+         */
+        deref->type =
+           _mesa_glsl_get_vector_type(op->type->base_type,
+                                      deref->selector.swizzle.num_components);
+      } else {
+        /* FINISHME: Logging of error messages should be moved into
+         * FINISHME: generate_swizzle.  This allows the generation of more
+         * FINISHME: specific error messages.
+         */
+        _mesa_glsl_error(& loc, state, "Invalid swizzle / mask `%s'",
+                         expr->primary_expression.identifier);
+      }
+   } else if (op->type->base_type == GLSL_TYPE_STRUCT) {
+      /* FINISHME: Handle field selection from structures. */
+   } else {
+      _mesa_glsl_error(& loc, state, "Cannot access field `%s' of "
+                      "non-structure / non-vector.",
+                      expr->primary_expression.identifier);
+   }
+
+   return (struct ir_instruction *) deref;
+}
diff --git a/ir.cc b/ir.cc
deleted file mode 100644 (file)
index 7bd7854..0000000
--- a/ir.cc
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * Copyright © 2010 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-#include <string.h>
-#include "main/imports.h"
-#include "main/simple_list.h"
-#include "ir.h"
-#include "glsl_types.h"
-
-ir_instruction::ir_instruction(int mode)
-{
-   this->mode = mode;
-   make_empty_list(this);
-}
-
-
-ir_assignment::ir_assignment(ir_instruction *lhs, ir_instruction *rhs,
-                            ir_expression *condition)
-   : ir_instruction(ir_op_assign)
-{
-   this->lhs = (ir_dereference *) lhs;
-   this->rhs = rhs;
-   this->condition = condition;
-}
-
-
-ir_expression::ir_expression(int op, const struct glsl_type *type,
-                            ir_instruction *op0, ir_instruction *op1)
-   : ir_instruction(ir_op_expression)
-{
-   this->type = type;
-   this->operation = ir_expression_operation(op);
-   this->operands[0] = op0;
-   this->operands[1] = op1;
-}
-
-
-ir_label::ir_label(const char *label)
-   : ir_instruction(ir_op_label), label(label)
-{
-   /* empty */
-}
-
-
-ir_constant::ir_constant(const struct glsl_type *type, const void *data)
-   : ir_instruction(ir_op_constant)
-{
-   const unsigned elements = 
-      ((type->vector_elements == 0) ? 1 : type->vector_elements)
-      * ((type->matrix_rows == 0) ? 1 : type->matrix_rows);
-   unsigned size = 0;
-
-   this->type = type;
-   switch (type->base_type) {
-   case GLSL_TYPE_UINT:  size = sizeof(this->value.u[0]); break;
-   case GLSL_TYPE_INT:   size = sizeof(this->value.i[0]); break;
-   case GLSL_TYPE_FLOAT: size = sizeof(this->value.f[0]); break;
-   case GLSL_TYPE_BOOL:  size = sizeof(this->value.b[0]); break;
-   default:
-      /* FINISHME: What to do?  Exceptions are not the answer.
-       */
-      break;
-   }
-
-   memcpy(& this->value, data, size * elements);
-}
-
-
-ir_dereference::ir_dereference(ir_instruction *var)
-   : ir_instruction(ir_op_dereference)
-{
-   this->mode = ir_reference_variable;
-   this->var = var;
-   this->type = (var != NULL) ? var->type : glsl_error_type;
-}
-
-
-ir_variable::ir_variable(const struct glsl_type *type, const char *name)
-   : ir_instruction(ir_op_var_decl)
-{
-   this->type = type;
-   this->name = name;
-}
-
-
-ir_function_signature::ir_function_signature(void)
-   : ir_instruction(ir_op_func_sig)
-{
-   make_empty_list(& parameters);
-}
-
-
-ir_function::ir_function(void)
-   : ir_instruction(ir_op_func)
-{
-   make_empty_list(& signatures);
-}
diff --git a/ir.cpp b/ir.cpp
new file mode 100644 (file)
index 0000000..7bd7854
--- /dev/null
+++ b/ir.cpp
@@ -0,0 +1,116 @@
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+#include <string.h>
+#include "main/imports.h"
+#include "main/simple_list.h"
+#include "ir.h"
+#include "glsl_types.h"
+
+ir_instruction::ir_instruction(int mode)
+{
+   this->mode = mode;
+   make_empty_list(this);
+}
+
+
+ir_assignment::ir_assignment(ir_instruction *lhs, ir_instruction *rhs,
+                            ir_expression *condition)
+   : ir_instruction(ir_op_assign)
+{
+   this->lhs = (ir_dereference *) lhs;
+   this->rhs = rhs;
+   this->condition = condition;
+}
+
+
+ir_expression::ir_expression(int op, const struct glsl_type *type,
+                            ir_instruction *op0, ir_instruction *op1)
+   : ir_instruction(ir_op_expression)
+{
+   this->type = type;
+   this->operation = ir_expression_operation(op);
+   this->operands[0] = op0;
+   this->operands[1] = op1;
+}
+
+
+ir_label::ir_label(const char *label)
+   : ir_instruction(ir_op_label), label(label)
+{
+   /* empty */
+}
+
+
+ir_constant::ir_constant(const struct glsl_type *type, const void *data)
+   : ir_instruction(ir_op_constant)
+{
+   const unsigned elements = 
+      ((type->vector_elements == 0) ? 1 : type->vector_elements)
+      * ((type->matrix_rows == 0) ? 1 : type->matrix_rows);
+   unsigned size = 0;
+
+   this->type = type;
+   switch (type->base_type) {
+   case GLSL_TYPE_UINT:  size = sizeof(this->value.u[0]); break;
+   case GLSL_TYPE_INT:   size = sizeof(this->value.i[0]); break;
+   case GLSL_TYPE_FLOAT: size = sizeof(this->value.f[0]); break;
+   case GLSL_TYPE_BOOL:  size = sizeof(this->value.b[0]); break;
+   default:
+      /* FINISHME: What to do?  Exceptions are not the answer.
+       */
+      break;
+   }
+
+   memcpy(& this->value, data, size * elements);
+}
+
+
+ir_dereference::ir_dereference(ir_instruction *var)
+   : ir_instruction(ir_op_dereference)
+{
+   this->mode = ir_reference_variable;
+   this->var = var;
+   this->type = (var != NULL) ? var->type : glsl_error_type;
+}
+
+
+ir_variable::ir_variable(const struct glsl_type *type, const char *name)
+   : ir_instruction(ir_op_var_decl)
+{
+   this->type = type;
+   this->name = name;
+}
+
+
+ir_function_signature::ir_function_signature(void)
+   : ir_instruction(ir_op_func_sig)
+{
+   make_empty_list(& parameters);
+}
+
+
+ir_function::ir_function(void)
+   : ir_instruction(ir_op_func)
+{
+   make_empty_list(& signatures);
+}