11591693c7b415e9869157c711fe11263c95d74eDavid Li/*
21591693c7b415e9869157c711fe11263c95d74eDavid Li * Copyright © 2010 Intel Corporation
31591693c7b415e9869157c711fe11263c95d74eDavid Li *
41591693c7b415e9869157c711fe11263c95d74eDavid Li * Permission is hereby granted, free of charge, to any person obtaining a
51591693c7b415e9869157c711fe11263c95d74eDavid Li * copy of this software and associated documentation files (the "Software"),
61591693c7b415e9869157c711fe11263c95d74eDavid Li * to deal in the Software without restriction, including without limitation
71591693c7b415e9869157c711fe11263c95d74eDavid Li * the rights to use, copy, modify, merge, publish, distribute, sublicense,
81591693c7b415e9869157c711fe11263c95d74eDavid Li * and/or sell copies of the Software, and to permit persons to whom the
91591693c7b415e9869157c711fe11263c95d74eDavid Li * Software is furnished to do so, subject to the following conditions:
101591693c7b415e9869157c711fe11263c95d74eDavid Li *
111591693c7b415e9869157c711fe11263c95d74eDavid Li * The above copyright notice and this permission notice (including the next
121591693c7b415e9869157c711fe11263c95d74eDavid Li * paragraph) shall be included in all copies or substantial portions of the
131591693c7b415e9869157c711fe11263c95d74eDavid Li * Software.
141591693c7b415e9869157c711fe11263c95d74eDavid Li *
151591693c7b415e9869157c711fe11263c95d74eDavid Li * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
161591693c7b415e9869157c711fe11263c95d74eDavid Li * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
171591693c7b415e9869157c711fe11263c95d74eDavid Li * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
181591693c7b415e9869157c711fe11263c95d74eDavid Li * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
191591693c7b415e9869157c711fe11263c95d74eDavid Li * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
201591693c7b415e9869157c711fe11263c95d74eDavid Li * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
211591693c7b415e9869157c711fe11263c95d74eDavid Li * DEALINGS IN THE SOFTWARE.
221591693c7b415e9869157c711fe11263c95d74eDavid Li */
231591693c7b415e9869157c711fe11263c95d74eDavid Li
241591693c7b415e9869157c711fe11263c95d74eDavid Li#include <cstdarg>
251591693c7b415e9869157c711fe11263c95d74eDavid Li
261591693c7b415e9869157c711fe11263c95d74eDavid Liextern "C" {
27d50d9a90a0df4d706421850e17c0fbd85bf710eeDavid Li#include <hieralloc.h>
281591693c7b415e9869157c711fe11263c95d74eDavid Li}
291591693c7b415e9869157c711fe11263c95d74eDavid Li
301591693c7b415e9869157c711fe11263c95d74eDavid Li#include "ir_reader.h"
311591693c7b415e9869157c711fe11263c95d74eDavid Li#include "glsl_parser_extras.h"
321591693c7b415e9869157c711fe11263c95d74eDavid Li#include "glsl_types.h"
331591693c7b415e9869157c711fe11263c95d74eDavid Li#include "s_expression.h"
341591693c7b415e9869157c711fe11263c95d74eDavid Li
351591693c7b415e9869157c711fe11263c95d74eDavid Liconst static bool debug = false;
361591693c7b415e9869157c711fe11263c95d74eDavid Li
371591693c7b415e9869157c711fe11263c95d74eDavid Listatic void ir_read_error(_mesa_glsl_parse_state *, s_expression *,
381591693c7b415e9869157c711fe11263c95d74eDavid Li			  const char *fmt, ...);
391591693c7b415e9869157c711fe11263c95d74eDavid Listatic const glsl_type *read_type(_mesa_glsl_parse_state *, s_expression *);
401591693c7b415e9869157c711fe11263c95d74eDavid Li
411591693c7b415e9869157c711fe11263c95d74eDavid Listatic void scan_for_prototypes(_mesa_glsl_parse_state *, exec_list *,
421591693c7b415e9869157c711fe11263c95d74eDavid Li			        s_expression *);
431591693c7b415e9869157c711fe11263c95d74eDavid Listatic ir_function *read_function(_mesa_glsl_parse_state *, s_list *,
441591693c7b415e9869157c711fe11263c95d74eDavid Li				  bool skip_body);
451591693c7b415e9869157c711fe11263c95d74eDavid Listatic void read_function_sig(_mesa_glsl_parse_state *, ir_function *,
461591693c7b415e9869157c711fe11263c95d74eDavid Li			      s_list *, bool skip_body);
471591693c7b415e9869157c711fe11263c95d74eDavid Li
481591693c7b415e9869157c711fe11263c95d74eDavid Listatic void read_instructions(_mesa_glsl_parse_state *, exec_list *,
491591693c7b415e9869157c711fe11263c95d74eDavid Li			      s_expression *, ir_loop *);
501591693c7b415e9869157c711fe11263c95d74eDavid Listatic ir_instruction *read_instruction(_mesa_glsl_parse_state *,
511591693c7b415e9869157c711fe11263c95d74eDavid Li				        s_expression *, ir_loop *);
521591693c7b415e9869157c711fe11263c95d74eDavid Listatic ir_variable *read_declaration(_mesa_glsl_parse_state *, s_list *);
531591693c7b415e9869157c711fe11263c95d74eDavid Listatic ir_if *read_if(_mesa_glsl_parse_state *, s_list *, ir_loop *);
541591693c7b415e9869157c711fe11263c95d74eDavid Listatic ir_loop *read_loop(_mesa_glsl_parse_state *st, s_list *list);
551591693c7b415e9869157c711fe11263c95d74eDavid Listatic ir_return *read_return(_mesa_glsl_parse_state *, s_list *);
561591693c7b415e9869157c711fe11263c95d74eDavid Li
571591693c7b415e9869157c711fe11263c95d74eDavid Listatic ir_rvalue *read_rvalue(_mesa_glsl_parse_state *, s_expression *);
581591693c7b415e9869157c711fe11263c95d74eDavid Listatic ir_assignment *read_assignment(_mesa_glsl_parse_state *, s_list *);
591591693c7b415e9869157c711fe11263c95d74eDavid Listatic ir_expression *read_expression(_mesa_glsl_parse_state *, s_list *);
601591693c7b415e9869157c711fe11263c95d74eDavid Listatic ir_call *read_call(_mesa_glsl_parse_state *, s_list *);
611591693c7b415e9869157c711fe11263c95d74eDavid Listatic ir_swizzle *read_swizzle(_mesa_glsl_parse_state *, s_list *);
621591693c7b415e9869157c711fe11263c95d74eDavid Listatic ir_constant *read_constant(_mesa_glsl_parse_state *, s_list *);
631591693c7b415e9869157c711fe11263c95d74eDavid Listatic ir_texture *read_texture(_mesa_glsl_parse_state *, s_list *);
641591693c7b415e9869157c711fe11263c95d74eDavid Li
651591693c7b415e9869157c711fe11263c95d74eDavid Listatic ir_dereference *read_dereference(_mesa_glsl_parse_state *,
661591693c7b415e9869157c711fe11263c95d74eDavid Li				        s_expression *);
671591693c7b415e9869157c711fe11263c95d74eDavid Listatic ir_dereference_variable *
681591693c7b415e9869157c711fe11263c95d74eDavid Liread_var_ref(_mesa_glsl_parse_state *, s_list *);
691591693c7b415e9869157c711fe11263c95d74eDavid Listatic ir_dereference_array *
701591693c7b415e9869157c711fe11263c95d74eDavid Liread_array_ref(_mesa_glsl_parse_state *, s_list *);
711591693c7b415e9869157c711fe11263c95d74eDavid Listatic ir_dereference_record *
721591693c7b415e9869157c711fe11263c95d74eDavid Liread_record_ref(_mesa_glsl_parse_state *, s_list *);
731591693c7b415e9869157c711fe11263c95d74eDavid Li
741591693c7b415e9869157c711fe11263c95d74eDavid Livoid
751591693c7b415e9869157c711fe11263c95d74eDavid Li_mesa_glsl_read_ir(_mesa_glsl_parse_state *state, exec_list *instructions,
761591693c7b415e9869157c711fe11263c95d74eDavid Li		   const char *src, bool scan_for_protos)
771591693c7b415e9869157c711fe11263c95d74eDavid Li{
781591693c7b415e9869157c711fe11263c95d74eDavid Li   s_expression *expr = s_expression::read_expression(state, src);
791591693c7b415e9869157c711fe11263c95d74eDavid Li   if (expr == NULL) {
801591693c7b415e9869157c711fe11263c95d74eDavid Li      ir_read_error(state, NULL, "couldn't parse S-Expression.");
811591693c7b415e9869157c711fe11263c95d74eDavid Li      return;
821591693c7b415e9869157c711fe11263c95d74eDavid Li   }
831591693c7b415e9869157c711fe11263c95d74eDavid Li
841591693c7b415e9869157c711fe11263c95d74eDavid Li   if (scan_for_protos) {
851591693c7b415e9869157c711fe11263c95d74eDavid Li      scan_for_prototypes(state, instructions, expr);
861591693c7b415e9869157c711fe11263c95d74eDavid Li      if (state->error)
871591693c7b415e9869157c711fe11263c95d74eDavid Li	 return;
881591693c7b415e9869157c711fe11263c95d74eDavid Li   }
891591693c7b415e9869157c711fe11263c95d74eDavid Li
901591693c7b415e9869157c711fe11263c95d74eDavid Li   read_instructions(state, instructions, expr, NULL);
91d50d9a90a0df4d706421850e17c0fbd85bf710eeDavid Li   hieralloc_free(expr);
921591693c7b415e9869157c711fe11263c95d74eDavid Li
931591693c7b415e9869157c711fe11263c95d74eDavid Li   if (debug)
941591693c7b415e9869157c711fe11263c95d74eDavid Li      validate_ir_tree(instructions);
951591693c7b415e9869157c711fe11263c95d74eDavid Li}
961591693c7b415e9869157c711fe11263c95d74eDavid Li
971591693c7b415e9869157c711fe11263c95d74eDavid Listatic void
981591693c7b415e9869157c711fe11263c95d74eDavid Liir_read_error(_mesa_glsl_parse_state *state, s_expression *expr,
991591693c7b415e9869157c711fe11263c95d74eDavid Li	      const char *fmt, ...)
1001591693c7b415e9869157c711fe11263c95d74eDavid Li{
1011591693c7b415e9869157c711fe11263c95d74eDavid Li   va_list ap;
1021591693c7b415e9869157c711fe11263c95d74eDavid Li
1031591693c7b415e9869157c711fe11263c95d74eDavid Li   state->error = true;
1041591693c7b415e9869157c711fe11263c95d74eDavid Li
1051591693c7b415e9869157c711fe11263c95d74eDavid Li   if (state->current_function != NULL)
106d50d9a90a0df4d706421850e17c0fbd85bf710eeDavid Li      state->info_log = hieralloc_asprintf_append(state->info_log,
1071591693c7b415e9869157c711fe11263c95d74eDavid Li			   "In function %s:\n",
1081591693c7b415e9869157c711fe11263c95d74eDavid Li			   state->current_function->function_name());
109d50d9a90a0df4d706421850e17c0fbd85bf710eeDavid Li   state->info_log = hieralloc_strdup_append(state->info_log, "error: ");
1101591693c7b415e9869157c711fe11263c95d74eDavid Li
1111591693c7b415e9869157c711fe11263c95d74eDavid Li   va_start(ap, fmt);
112d50d9a90a0df4d706421850e17c0fbd85bf710eeDavid Li   state->info_log = hieralloc_vasprintf_append(state->info_log, fmt, ap);
1131591693c7b415e9869157c711fe11263c95d74eDavid Li   va_end(ap);
114d50d9a90a0df4d706421850e17c0fbd85bf710eeDavid Li   state->info_log = hieralloc_strdup_append(state->info_log, "\n");
1151591693c7b415e9869157c711fe11263c95d74eDavid Li
1161591693c7b415e9869157c711fe11263c95d74eDavid Li   if (expr != NULL) {
117d50d9a90a0df4d706421850e17c0fbd85bf710eeDavid Li      state->info_log = hieralloc_strdup_append(state->info_log,
1181591693c7b415e9869157c711fe11263c95d74eDavid Li					     "...in this context:\n   ");
1191591693c7b415e9869157c711fe11263c95d74eDavid Li      expr->print();
120d50d9a90a0df4d706421850e17c0fbd85bf710eeDavid Li      state->info_log = hieralloc_strdup_append(state->info_log, "\n\n");
1211591693c7b415e9869157c711fe11263c95d74eDavid Li   }
1221591693c7b415e9869157c711fe11263c95d74eDavid Li}
1231591693c7b415e9869157c711fe11263c95d74eDavid Li
1241591693c7b415e9869157c711fe11263c95d74eDavid Listatic const glsl_type *
1251591693c7b415e9869157c711fe11263c95d74eDavid Liread_type(_mesa_glsl_parse_state *st, s_expression *expr)
1261591693c7b415e9869157c711fe11263c95d74eDavid Li{
1271591693c7b415e9869157c711fe11263c95d74eDavid Li   s_list *list = SX_AS_LIST(expr);
1281591693c7b415e9869157c711fe11263c95d74eDavid Li   if (list != NULL) {
1291591693c7b415e9869157c711fe11263c95d74eDavid Li      s_symbol *type_sym = SX_AS_SYMBOL(list->subexpressions.get_head());
1301591693c7b415e9869157c711fe11263c95d74eDavid Li      if (type_sym == NULL) {
1311591693c7b415e9869157c711fe11263c95d74eDavid Li	 ir_read_error(st, expr, "expected type (array ...) or (struct ...)");
1321591693c7b415e9869157c711fe11263c95d74eDavid Li	 return NULL;
1331591693c7b415e9869157c711fe11263c95d74eDavid Li      }
1341591693c7b415e9869157c711fe11263c95d74eDavid Li      if (strcmp(type_sym->value(), "array") == 0) {
1351591693c7b415e9869157c711fe11263c95d74eDavid Li	 if (list->length() != 3) {
1361591693c7b415e9869157c711fe11263c95d74eDavid Li	    ir_read_error(st, expr, "expected type (array <type> <int>)");
1371591693c7b415e9869157c711fe11263c95d74eDavid Li	    return NULL;
1381591693c7b415e9869157c711fe11263c95d74eDavid Li	 }
1391591693c7b415e9869157c711fe11263c95d74eDavid Li
1401591693c7b415e9869157c711fe11263c95d74eDavid Li	 // Read base type
1411591693c7b415e9869157c711fe11263c95d74eDavid Li	 s_expression *base_expr = (s_expression*) type_sym->next;
1421591693c7b415e9869157c711fe11263c95d74eDavid Li	 const glsl_type *base_type = read_type(st, base_expr);
1431591693c7b415e9869157c711fe11263c95d74eDavid Li	 if (base_type == NULL) {
1441591693c7b415e9869157c711fe11263c95d74eDavid Li	    ir_read_error(st, NULL, "when reading base type of array");
1451591693c7b415e9869157c711fe11263c95d74eDavid Li	    return NULL;
1461591693c7b415e9869157c711fe11263c95d74eDavid Li	 }
1471591693c7b415e9869157c711fe11263c95d74eDavid Li
1481591693c7b415e9869157c711fe11263c95d74eDavid Li	 // Read array size
1491591693c7b415e9869157c711fe11263c95d74eDavid Li	 s_int *size = SX_AS_INT(base_expr->next);
1501591693c7b415e9869157c711fe11263c95d74eDavid Li	 if (size == NULL) {
1511591693c7b415e9869157c711fe11263c95d74eDavid Li	    ir_read_error(st, expr, "found non-integer array size");
1521591693c7b415e9869157c711fe11263c95d74eDavid Li	    return NULL;
1531591693c7b415e9869157c711fe11263c95d74eDavid Li	 }
1541591693c7b415e9869157c711fe11263c95d74eDavid Li
1551591693c7b415e9869157c711fe11263c95d74eDavid Li	 return glsl_type::get_array_instance(base_type, size->value());
1561591693c7b415e9869157c711fe11263c95d74eDavid Li      } else if (strcmp(type_sym->value(), "struct") == 0) {
1571591693c7b415e9869157c711fe11263c95d74eDavid Li	 assert(false); // FINISHME
1581591693c7b415e9869157c711fe11263c95d74eDavid Li      } else {
1591591693c7b415e9869157c711fe11263c95d74eDavid Li	 ir_read_error(st, expr, "expected (array ...) or (struct ...); "
1601591693c7b415e9869157c711fe11263c95d74eDavid Li				 "found (%s ...)", type_sym->value());
1611591693c7b415e9869157c711fe11263c95d74eDavid Li	 return NULL;
1621591693c7b415e9869157c711fe11263c95d74eDavid Li      }
1631591693c7b415e9869157c711fe11263c95d74eDavid Li   }
1641591693c7b415e9869157c711fe11263c95d74eDavid Li
1651591693c7b415e9869157c711fe11263c95d74eDavid Li   s_symbol *type_sym = SX_AS_SYMBOL(expr);
1661591693c7b415e9869157c711fe11263c95d74eDavid Li   if (type_sym == NULL) {
1671591693c7b415e9869157c711fe11263c95d74eDavid Li      ir_read_error(st, expr, "expected <type> (symbol or list)");
1681591693c7b415e9869157c711fe11263c95d74eDavid Li      return NULL;
1691591693c7b415e9869157c711fe11263c95d74eDavid Li   }
1701591693c7b415e9869157c711fe11263c95d74eDavid Li
1711591693c7b415e9869157c711fe11263c95d74eDavid Li   const glsl_type *type = st->symbols->get_type(type_sym->value());
1721591693c7b415e9869157c711fe11263c95d74eDavid Li   if (type == NULL)
1731591693c7b415e9869157c711fe11263c95d74eDavid Li      ir_read_error(st, expr, "invalid type: %s", type_sym->value());
1741591693c7b415e9869157c711fe11263c95d74eDavid Li
1751591693c7b415e9869157c711fe11263c95d74eDavid Li   return type;
1761591693c7b415e9869157c711fe11263c95d74eDavid Li}
1771591693c7b415e9869157c711fe11263c95d74eDavid Li
1781591693c7b415e9869157c711fe11263c95d74eDavid Li
1791591693c7b415e9869157c711fe11263c95d74eDavid Listatic void
1801591693c7b415e9869157c711fe11263c95d74eDavid Liscan_for_prototypes(_mesa_glsl_parse_state *st, exec_list *instructions,
1811591693c7b415e9869157c711fe11263c95d74eDavid Li		    s_expression *expr)
1821591693c7b415e9869157c711fe11263c95d74eDavid Li{
1831591693c7b415e9869157c711fe11263c95d74eDavid Li   s_list *list = SX_AS_LIST(expr);
1841591693c7b415e9869157c711fe11263c95d74eDavid Li   if (list == NULL) {
1851591693c7b415e9869157c711fe11263c95d74eDavid Li      ir_read_error(st, expr, "Expected (<instruction> ...); found an atom.");
1861591693c7b415e9869157c711fe11263c95d74eDavid Li      return;
1871591693c7b415e9869157c711fe11263c95d74eDavid Li   }
1881591693c7b415e9869157c711fe11263c95d74eDavid Li
1891591693c7b415e9869157c711fe11263c95d74eDavid Li   foreach_iter(exec_list_iterator, it, list->subexpressions) {
1901591693c7b415e9869157c711fe11263c95d74eDavid Li      s_list *sub = SX_AS_LIST(it.get());
1911591693c7b415e9869157c711fe11263c95d74eDavid Li      if (sub == NULL)
1921591693c7b415e9869157c711fe11263c95d74eDavid Li	 continue; // not a (function ...); ignore it.
1931591693c7b415e9869157c711fe11263c95d74eDavid Li
1941591693c7b415e9869157c711fe11263c95d74eDavid Li      s_symbol *tag = SX_AS_SYMBOL(sub->subexpressions.get_head());
1951591693c7b415e9869157c711fe11263c95d74eDavid Li      if (tag == NULL || strcmp(tag->value(), "function") != 0)
1961591693c7b415e9869157c711fe11263c95d74eDavid Li	 continue; // not a (function ...); ignore it.
1971591693c7b415e9869157c711fe11263c95d74eDavid Li
1981591693c7b415e9869157c711fe11263c95d74eDavid Li      ir_function *f = read_function(st, sub, true);
1991591693c7b415e9869157c711fe11263c95d74eDavid Li      if (f == NULL)
2001591693c7b415e9869157c711fe11263c95d74eDavid Li	 return;
2011591693c7b415e9869157c711fe11263c95d74eDavid Li      instructions->push_tail(f);
2021591693c7b415e9869157c711fe11263c95d74eDavid Li   }
2031591693c7b415e9869157c711fe11263c95d74eDavid Li}
2041591693c7b415e9869157c711fe11263c95d74eDavid Li
2051591693c7b415e9869157c711fe11263c95d74eDavid Listatic ir_function *
2061591693c7b415e9869157c711fe11263c95d74eDavid Liread_function(_mesa_glsl_parse_state *st, s_list *list, bool skip_body)
2071591693c7b415e9869157c711fe11263c95d74eDavid Li{
2081591693c7b415e9869157c711fe11263c95d74eDavid Li   void *ctx = st;
2091591693c7b415e9869157c711fe11263c95d74eDavid Li   bool added = false;
2101591693c7b415e9869157c711fe11263c95d74eDavid Li   if (list->length() < 3) {
2111591693c7b415e9869157c711fe11263c95d74eDavid Li      ir_read_error(st, list, "Expected (function <name> (signature ...) ...)");
2121591693c7b415e9869157c711fe11263c95d74eDavid Li      return NULL;
2131591693c7b415e9869157c711fe11263c95d74eDavid Li   }
2141591693c7b415e9869157c711fe11263c95d74eDavid Li
2151591693c7b415e9869157c711fe11263c95d74eDavid Li   s_symbol *name = SX_AS_SYMBOL(list->subexpressions.head->next);
2161591693c7b415e9869157c711fe11263c95d74eDavid Li   if (name == NULL) {
2171591693c7b415e9869157c711fe11263c95d74eDavid Li      ir_read_error(st, list, "Expected (function <name> ...)");
2181591693c7b415e9869157c711fe11263c95d74eDavid Li      return NULL;
2191591693c7b415e9869157c711fe11263c95d74eDavid Li   }
2201591693c7b415e9869157c711fe11263c95d74eDavid Li
2211591693c7b415e9869157c711fe11263c95d74eDavid Li   ir_function *f = st->symbols->get_function(name->value());
2221591693c7b415e9869157c711fe11263c95d74eDavid Li   if (f == NULL) {
2231591693c7b415e9869157c711fe11263c95d74eDavid Li      f = new(ctx) ir_function(name->value());
2241591693c7b415e9869157c711fe11263c95d74eDavid Li      added = st->symbols->add_function(f);
2251591693c7b415e9869157c711fe11263c95d74eDavid Li      assert(added);
2261591693c7b415e9869157c711fe11263c95d74eDavid Li   }
2271591693c7b415e9869157c711fe11263c95d74eDavid Li
2281591693c7b415e9869157c711fe11263c95d74eDavid Li   exec_list_iterator it = list->subexpressions.iterator();
2291591693c7b415e9869157c711fe11263c95d74eDavid Li   it.next(); // skip "function" tag
2301591693c7b415e9869157c711fe11263c95d74eDavid Li   it.next(); // skip function name
2311591693c7b415e9869157c711fe11263c95d74eDavid Li   for (/* nothing */; it.has_next(); it.next()) {
2321591693c7b415e9869157c711fe11263c95d74eDavid Li      s_list *siglist = SX_AS_LIST(it.get());
2331591693c7b415e9869157c711fe11263c95d74eDavid Li      if (siglist == NULL) {
2341591693c7b415e9869157c711fe11263c95d74eDavid Li	 ir_read_error(st, list, "Expected (function (signature ...) ...)");
2351591693c7b415e9869157c711fe11263c95d74eDavid Li	 return NULL;
2361591693c7b415e9869157c711fe11263c95d74eDavid Li      }
2371591693c7b415e9869157c711fe11263c95d74eDavid Li
2381591693c7b415e9869157c711fe11263c95d74eDavid Li      s_symbol *tag = SX_AS_SYMBOL(siglist->subexpressions.get_head());
2391591693c7b415e9869157c711fe11263c95d74eDavid Li      if (tag == NULL || strcmp(tag->value(), "signature") != 0) {
2401591693c7b415e9869157c711fe11263c95d74eDavid Li	 ir_read_error(st, siglist, "Expected (signature ...)");
2411591693c7b415e9869157c711fe11263c95d74eDavid Li	 return NULL;
2421591693c7b415e9869157c711fe11263c95d74eDavid Li      }
2431591693c7b415e9869157c711fe11263c95d74eDavid Li
2441591693c7b415e9869157c711fe11263c95d74eDavid Li      read_function_sig(st, f, siglist, skip_body);
2451591693c7b415e9869157c711fe11263c95d74eDavid Li   }
2461591693c7b415e9869157c711fe11263c95d74eDavid Li   return added ? f : NULL;
2471591693c7b415e9869157c711fe11263c95d74eDavid Li}
2481591693c7b415e9869157c711fe11263c95d74eDavid Li
2491591693c7b415e9869157c711fe11263c95d74eDavid Listatic void
2501591693c7b415e9869157c711fe11263c95d74eDavid Liread_function_sig(_mesa_glsl_parse_state *st, ir_function *f, s_list *list,
2511591693c7b415e9869157c711fe11263c95d74eDavid Li		  bool skip_body)
2521591693c7b415e9869157c711fe11263c95d74eDavid Li{
2531591693c7b415e9869157c711fe11263c95d74eDavid Li   void *ctx = st;
2541591693c7b415e9869157c711fe11263c95d74eDavid Li   if (list->length() != 4) {
2551591693c7b415e9869157c711fe11263c95d74eDavid Li      ir_read_error(st, list, "Expected (signature <type> (parameters ...) "
2561591693c7b415e9869157c711fe11263c95d74eDavid Li			      "(<instruction> ...))");
2571591693c7b415e9869157c711fe11263c95d74eDavid Li      return;
2581591693c7b415e9869157c711fe11263c95d74eDavid Li   }
2591591693c7b415e9869157c711fe11263c95d74eDavid Li
2601591693c7b415e9869157c711fe11263c95d74eDavid Li   s_expression *type_expr = (s_expression*) list->subexpressions.head->next;
2611591693c7b415e9869157c711fe11263c95d74eDavid Li   const glsl_type *return_type = read_type(st, type_expr);
2621591693c7b415e9869157c711fe11263c95d74eDavid Li   if (return_type == NULL)
2631591693c7b415e9869157c711fe11263c95d74eDavid Li      return;
2641591693c7b415e9869157c711fe11263c95d74eDavid Li
2651591693c7b415e9869157c711fe11263c95d74eDavid Li   s_list *paramlist = SX_AS_LIST(type_expr->next);
2661591693c7b415e9869157c711fe11263c95d74eDavid Li   s_list *body_list = SX_AS_LIST(type_expr->next->next);
2671591693c7b415e9869157c711fe11263c95d74eDavid Li   if (paramlist == NULL || body_list == NULL) {
2681591693c7b415e9869157c711fe11263c95d74eDavid Li      ir_read_error(st, list, "Expected (signature <type> (parameters ...) "
2691591693c7b415e9869157c711fe11263c95d74eDavid Li			      "(<instruction> ...))");
2701591693c7b415e9869157c711fe11263c95d74eDavid Li      return;
2711591693c7b415e9869157c711fe11263c95d74eDavid Li   }
2721591693c7b415e9869157c711fe11263c95d74eDavid Li   s_symbol *paramtag = SX_AS_SYMBOL(paramlist->subexpressions.get_head());
2731591693c7b415e9869157c711fe11263c95d74eDavid Li   if (paramtag == NULL || strcmp(paramtag->value(), "parameters") != 0) {
2741591693c7b415e9869157c711fe11263c95d74eDavid Li      ir_read_error(st, paramlist, "Expected (parameters ...)");
2751591693c7b415e9869157c711fe11263c95d74eDavid Li      return;
2761591693c7b415e9869157c711fe11263c95d74eDavid Li   }
2771591693c7b415e9869157c711fe11263c95d74eDavid Li
2781591693c7b415e9869157c711fe11263c95d74eDavid Li   // Read the parameters list into a temporary place.
2791591693c7b415e9869157c711fe11263c95d74eDavid Li   exec_list hir_parameters;
2801591693c7b415e9869157c711fe11263c95d74eDavid Li   st->symbols->push_scope();
2811591693c7b415e9869157c711fe11263c95d74eDavid Li
2821591693c7b415e9869157c711fe11263c95d74eDavid Li   exec_list_iterator it = paramlist->subexpressions.iterator();
2831591693c7b415e9869157c711fe11263c95d74eDavid Li   for (it.next() /* skip "parameters" */; it.has_next(); it.next()) {
2841591693c7b415e9869157c711fe11263c95d74eDavid Li      s_list *decl = SX_AS_LIST(it.get());
2851591693c7b415e9869157c711fe11263c95d74eDavid Li      ir_variable *var = read_declaration(st, decl);
2861591693c7b415e9869157c711fe11263c95d74eDavid Li      if (var == NULL)
2871591693c7b415e9869157c711fe11263c95d74eDavid Li	 return;
2881591693c7b415e9869157c711fe11263c95d74eDavid Li
2891591693c7b415e9869157c711fe11263c95d74eDavid Li      hir_parameters.push_tail(var);
2901591693c7b415e9869157c711fe11263c95d74eDavid Li   }
2911591693c7b415e9869157c711fe11263c95d74eDavid Li
2921591693c7b415e9869157c711fe11263c95d74eDavid Li   ir_function_signature *sig = f->exact_matching_signature(&hir_parameters);
2931591693c7b415e9869157c711fe11263c95d74eDavid Li   if (sig == NULL && skip_body) {
2941591693c7b415e9869157c711fe11263c95d74eDavid Li      /* If scanning for prototypes, generate a new signature. */
2951591693c7b415e9869157c711fe11263c95d74eDavid Li      sig = new(ctx) ir_function_signature(return_type);
2961591693c7b415e9869157c711fe11263c95d74eDavid Li      sig->is_builtin = true;
2971591693c7b415e9869157c711fe11263c95d74eDavid Li      f->add_signature(sig);
2981591693c7b415e9869157c711fe11263c95d74eDavid Li   } else if (sig != NULL) {
2991591693c7b415e9869157c711fe11263c95d74eDavid Li      const char *badvar = sig->qualifiers_match(&hir_parameters);
3001591693c7b415e9869157c711fe11263c95d74eDavid Li      if (badvar != NULL) {
3011591693c7b415e9869157c711fe11263c95d74eDavid Li	 ir_read_error(st, list, "function `%s' parameter `%s' qualifiers "
3021591693c7b415e9869157c711fe11263c95d74eDavid Li		       "don't match prototype", f->name, badvar);
3031591693c7b415e9869157c711fe11263c95d74eDavid Li	 return;
3041591693c7b415e9869157c711fe11263c95d74eDavid Li      }
3051591693c7b415e9869157c711fe11263c95d74eDavid Li
3061591693c7b415e9869157c711fe11263c95d74eDavid Li      if (sig->return_type != return_type) {
3071591693c7b415e9869157c711fe11263c95d74eDavid Li	 ir_read_error(st, list, "function `%s' return type doesn't "
3081591693c7b415e9869157c711fe11263c95d74eDavid Li		       "match prototype", f->name);
3091591693c7b415e9869157c711fe11263c95d74eDavid Li	 return;
3101591693c7b415e9869157c711fe11263c95d74eDavid Li      }
3111591693c7b415e9869157c711fe11263c95d74eDavid Li   } else {
3121591693c7b415e9869157c711fe11263c95d74eDavid Li      /* No prototype for this body exists - skip it. */
3131591693c7b415e9869157c711fe11263c95d74eDavid Li      st->symbols->pop_scope();
3141591693c7b415e9869157c711fe11263c95d74eDavid Li      return;
3151591693c7b415e9869157c711fe11263c95d74eDavid Li   }
3161591693c7b415e9869157c711fe11263c95d74eDavid Li   assert(sig != NULL);
3171591693c7b415e9869157c711fe11263c95d74eDavid Li
3181591693c7b415e9869157c711fe11263c95d74eDavid Li   sig->replace_parameters(&hir_parameters);
3191591693c7b415e9869157c711fe11263c95d74eDavid Li
3201591693c7b415e9869157c711fe11263c95d74eDavid Li   if (!skip_body && !body_list->subexpressions.is_empty()) {
3211591693c7b415e9869157c711fe11263c95d74eDavid Li      if (sig->is_defined) {
3221591693c7b415e9869157c711fe11263c95d74eDavid Li	 ir_read_error(st, list, "function %s redefined", f->name);
3231591693c7b415e9869157c711fe11263c95d74eDavid Li	 return;
3241591693c7b415e9869157c711fe11263c95d74eDavid Li      }
3251591693c7b415e9869157c711fe11263c95d74eDavid Li      st->current_function = sig;
3261591693c7b415e9869157c711fe11263c95d74eDavid Li      read_instructions(st, &sig->body, body_list, NULL);
3271591693c7b415e9869157c711fe11263c95d74eDavid Li      st->current_function = NULL;
3281591693c7b415e9869157c711fe11263c95d74eDavid Li      sig->is_defined = true;
3291591693c7b415e9869157c711fe11263c95d74eDavid Li   }
3301591693c7b415e9869157c711fe11263c95d74eDavid Li
3311591693c7b415e9869157c711fe11263c95d74eDavid Li   st->symbols->pop_scope();
3321591693c7b415e9869157c711fe11263c95d74eDavid Li}
3331591693c7b415e9869157c711fe11263c95d74eDavid Li
3341591693c7b415e9869157c711fe11263c95d74eDavid Listatic void
3351591693c7b415e9869157c711fe11263c95d74eDavid Liread_instructions(_mesa_glsl_parse_state *st, exec_list *instructions,
3361591693c7b415e9869157c711fe11263c95d74eDavid Li		  s_expression *expr, ir_loop *loop_ctx)
3371591693c7b415e9869157c711fe11263c95d74eDavid Li{
3381591693c7b415e9869157c711fe11263c95d74eDavid Li   // Read in a list of instructions
3391591693c7b415e9869157c711fe11263c95d74eDavid Li   s_list *list = SX_AS_LIST(expr);
3401591693c7b415e9869157c711fe11263c95d74eDavid Li   if (list == NULL) {
3411591693c7b415e9869157c711fe11263c95d74eDavid Li      ir_read_error(st, expr, "Expected (<instruction> ...); found an atom.");
3421591693c7b415e9869157c711fe11263c95d74eDavid Li      return;
3431591693c7b415e9869157c711fe11263c95d74eDavid Li   }
3441591693c7b415e9869157c711fe11263c95d74eDavid Li
3451591693c7b415e9869157c711fe11263c95d74eDavid Li   foreach_iter(exec_list_iterator, it, list->subexpressions) {
3461591693c7b415e9869157c711fe11263c95d74eDavid Li      s_expression *sub = (s_expression*) it.get();
3471591693c7b415e9869157c711fe11263c95d74eDavid Li      ir_instruction *ir = read_instruction(st, sub, loop_ctx);
3481591693c7b415e9869157c711fe11263c95d74eDavid Li      if (ir != NULL) {
3491591693c7b415e9869157c711fe11263c95d74eDavid Li	 /* Global variable declarations should be moved to the top, before
3501591693c7b415e9869157c711fe11263c95d74eDavid Li	  * any functions that might use them.  Functions are added to the
3511591693c7b415e9869157c711fe11263c95d74eDavid Li	  * instruction stream when scanning for prototypes, so without this
3521591693c7b415e9869157c711fe11263c95d74eDavid Li	  * hack, they always appear before variable declarations.
3531591693c7b415e9869157c711fe11263c95d74eDavid Li	  */
3541591693c7b415e9869157c711fe11263c95d74eDavid Li	 if (st->current_function == NULL && ir->as_variable() != NULL)
3551591693c7b415e9869157c711fe11263c95d74eDavid Li	    instructions->push_head(ir);
3561591693c7b415e9869157c711fe11263c95d74eDavid Li	 else
3571591693c7b415e9869157c711fe11263c95d74eDavid Li	    instructions->push_tail(ir);
3581591693c7b415e9869157c711fe11263c95d74eDavid Li      }
3591591693c7b415e9869157c711fe11263c95d74eDavid Li   }
3601591693c7b415e9869157c711fe11263c95d74eDavid Li}
3611591693c7b415e9869157c711fe11263c95d74eDavid Li
3621591693c7b415e9869157c711fe11263c95d74eDavid Li
3631591693c7b415e9869157c711fe11263c95d74eDavid Listatic ir_instruction *
3641591693c7b415e9869157c711fe11263c95d74eDavid Liread_instruction(_mesa_glsl_parse_state *st, s_expression *expr,
3651591693c7b415e9869157c711fe11263c95d74eDavid Li	         ir_loop *loop_ctx)
3661591693c7b415e9869157c711fe11263c95d74eDavid Li{
3671591693c7b415e9869157c711fe11263c95d74eDavid Li   void *ctx = st;
3681591693c7b415e9869157c711fe11263c95d74eDavid Li   s_symbol *symbol = SX_AS_SYMBOL(expr);
3691591693c7b415e9869157c711fe11263c95d74eDavid Li   if (symbol != NULL) {
3701591693c7b415e9869157c711fe11263c95d74eDavid Li      if (strcmp(symbol->value(), "break") == 0 && loop_ctx != NULL)
3711591693c7b415e9869157c711fe11263c95d74eDavid Li	 return new(ctx) ir_loop_jump(ir_loop_jump::jump_break);
3721591693c7b415e9869157c711fe11263c95d74eDavid Li      if (strcmp(symbol->value(), "continue") == 0 && loop_ctx != NULL)
3731591693c7b415e9869157c711fe11263c95d74eDavid Li	 return new(ctx) ir_loop_jump(ir_loop_jump::jump_continue);
3741591693c7b415e9869157c711fe11263c95d74eDavid Li   }
3751591693c7b415e9869157c711fe11263c95d74eDavid Li
3761591693c7b415e9869157c711fe11263c95d74eDavid Li   s_list *list = SX_AS_LIST(expr);
3771591693c7b415e9869157c711fe11263c95d74eDavid Li   if (list == NULL || list->subexpressions.is_empty()) {
3781591693c7b415e9869157c711fe11263c95d74eDavid Li      ir_read_error(st, expr, "Invalid instruction.\n");
3791591693c7b415e9869157c711fe11263c95d74eDavid Li      return NULL;
3801591693c7b415e9869157c711fe11263c95d74eDavid Li   }
3811591693c7b415e9869157c711fe11263c95d74eDavid Li
3821591693c7b415e9869157c711fe11263c95d74eDavid Li   s_symbol *tag = SX_AS_SYMBOL(list->subexpressions.get_head());
3831591693c7b415e9869157c711fe11263c95d74eDavid Li   if (tag == NULL) {
3841591693c7b415e9869157c711fe11263c95d74eDavid Li      ir_read_error(st, expr, "expected instruction tag");
3851591693c7b415e9869157c711fe11263c95d74eDavid Li      return NULL;
3861591693c7b415e9869157c711fe11263c95d74eDavid Li   }
3871591693c7b415e9869157c711fe11263c95d74eDavid Li
3881591693c7b415e9869157c711fe11263c95d74eDavid Li   ir_instruction *inst = NULL;
3891591693c7b415e9869157c711fe11263c95d74eDavid Li   if (strcmp(tag->value(), "declare") == 0) {
3901591693c7b415e9869157c711fe11263c95d74eDavid Li      inst = read_declaration(st, list);
3911591693c7b415e9869157c711fe11263c95d74eDavid Li   } else if (strcmp(tag->value(), "assign") == 0) {
3921591693c7b415e9869157c711fe11263c95d74eDavid Li      inst = read_assignment(st, list);
3931591693c7b415e9869157c711fe11263c95d74eDavid Li   } else if (strcmp(tag->value(), "if") == 0) {
3941591693c7b415e9869157c711fe11263c95d74eDavid Li      inst = read_if(st, list, loop_ctx);
3951591693c7b415e9869157c711fe11263c95d74eDavid Li   } else if (strcmp(tag->value(), "loop") == 0) {
3961591693c7b415e9869157c711fe11263c95d74eDavid Li      inst = read_loop(st, list);
3971591693c7b415e9869157c711fe11263c95d74eDavid Li   } else if (strcmp(tag->value(), "return") == 0) {
3981591693c7b415e9869157c711fe11263c95d74eDavid Li      inst = read_return(st, list);
3991591693c7b415e9869157c711fe11263c95d74eDavid Li   } else if (strcmp(tag->value(), "function") == 0) {
4001591693c7b415e9869157c711fe11263c95d74eDavid Li      inst = read_function(st, list, false);
4011591693c7b415e9869157c711fe11263c95d74eDavid Li   } else {
4021591693c7b415e9869157c711fe11263c95d74eDavid Li      inst = read_rvalue(st, list);
4031591693c7b415e9869157c711fe11263c95d74eDavid Li      if (inst == NULL)
4041591693c7b415e9869157c711fe11263c95d74eDavid Li	 ir_read_error(st, NULL, "when reading instruction");
4051591693c7b415e9869157c711fe11263c95d74eDavid Li   }
4061591693c7b415e9869157c711fe11263c95d74eDavid Li   return inst;
4071591693c7b415e9869157c711fe11263c95d74eDavid Li}
4081591693c7b415e9869157c711fe11263c95d74eDavid Li
4091591693c7b415e9869157c711fe11263c95d74eDavid Li
4101591693c7b415e9869157c711fe11263c95d74eDavid Listatic ir_variable *
4111591693c7b415e9869157c711fe11263c95d74eDavid Liread_declaration(_mesa_glsl_parse_state *st, s_list *list)
4121591693c7b415e9869157c711fe11263c95d74eDavid Li{
4131591693c7b415e9869157c711fe11263c95d74eDavid Li   void *ctx = st;
4141591693c7b415e9869157c711fe11263c95d74eDavid Li   if (list->length() != 4) {
4151591693c7b415e9869157c711fe11263c95d74eDavid Li      ir_read_error(st, list, "expected (declare (<qualifiers>) <type> "
4161591693c7b415e9869157c711fe11263c95d74eDavid Li			      "<name>)");
4171591693c7b415e9869157c711fe11263c95d74eDavid Li      return NULL;
4181591693c7b415e9869157c711fe11263c95d74eDavid Li   }
4191591693c7b415e9869157c711fe11263c95d74eDavid Li
4201591693c7b415e9869157c711fe11263c95d74eDavid Li   s_list *quals = SX_AS_LIST(list->subexpressions.head->next);
4211591693c7b415e9869157c711fe11263c95d74eDavid Li   if (quals == NULL) {
4221591693c7b415e9869157c711fe11263c95d74eDavid Li      ir_read_error(st, list, "expected a list of variable qualifiers");
4231591693c7b415e9869157c711fe11263c95d74eDavid Li      return NULL;
4241591693c7b415e9869157c711fe11263c95d74eDavid Li   }
4251591693c7b415e9869157c711fe11263c95d74eDavid Li
4261591693c7b415e9869157c711fe11263c95d74eDavid Li   s_expression *type_expr = (s_expression*) quals->next;
4271591693c7b415e9869157c711fe11263c95d74eDavid Li   const glsl_type *type = read_type(st, type_expr);
4281591693c7b415e9869157c711fe11263c95d74eDavid Li   if (type == NULL)
4291591693c7b415e9869157c711fe11263c95d74eDavid Li      return NULL;
4301591693c7b415e9869157c711fe11263c95d74eDavid Li
4311591693c7b415e9869157c711fe11263c95d74eDavid Li   s_symbol *var_name = SX_AS_SYMBOL(type_expr->next);
4321591693c7b415e9869157c711fe11263c95d74eDavid Li   if (var_name == NULL) {
4331591693c7b415e9869157c711fe11263c95d74eDavid Li      ir_read_error(st, list, "expected variable name, found non-symbol");
4341591693c7b415e9869157c711fe11263c95d74eDavid Li      return NULL;
4351591693c7b415e9869157c711fe11263c95d74eDavid Li   }
4361591693c7b415e9869157c711fe11263c95d74eDavid Li
4371591693c7b415e9869157c711fe11263c95d74eDavid Li   ir_variable *var = new(ctx) ir_variable(type, var_name->value(),
4381591693c7b415e9869157c711fe11263c95d74eDavid Li					   ir_var_auto);
4391591693c7b415e9869157c711fe11263c95d74eDavid Li
4401591693c7b415e9869157c711fe11263c95d74eDavid Li   foreach_iter(exec_list_iterator, it, quals->subexpressions) {
4411591693c7b415e9869157c711fe11263c95d74eDavid Li      s_symbol *qualifier = SX_AS_SYMBOL(it.get());
4421591693c7b415e9869157c711fe11263c95d74eDavid Li      if (qualifier == NULL) {
4431591693c7b415e9869157c711fe11263c95d74eDavid Li	 ir_read_error(st, list, "qualifier list must contain only symbols");
4441591693c7b415e9869157c711fe11263c95d74eDavid Li	 delete var;
4451591693c7b415e9869157c711fe11263c95d74eDavid Li	 return NULL;
4461591693c7b415e9869157c711fe11263c95d74eDavid Li      }
4471591693c7b415e9869157c711fe11263c95d74eDavid Li
4481591693c7b415e9869157c711fe11263c95d74eDavid Li      // FINISHME: Check for duplicate/conflicting qualifiers.
4491591693c7b415e9869157c711fe11263c95d74eDavid Li      if (strcmp(qualifier->value(), "centroid") == 0) {
4501591693c7b415e9869157c711fe11263c95d74eDavid Li	 var->centroid = 1;
4511591693c7b415e9869157c711fe11263c95d74eDavid Li      } else if (strcmp(qualifier->value(), "invariant") == 0) {
4521591693c7b415e9869157c711fe11263c95d74eDavid Li	 var->invariant = 1;
4531591693c7b415e9869157c711fe11263c95d74eDavid Li      } else if (strcmp(qualifier->value(), "uniform") == 0) {
4541591693c7b415e9869157c711fe11263c95d74eDavid Li	 var->mode = ir_var_uniform;
4551591693c7b415e9869157c711fe11263c95d74eDavid Li      } else if (strcmp(qualifier->value(), "auto") == 0) {
4561591693c7b415e9869157c711fe11263c95d74eDavid Li	 var->mode = ir_var_auto;
4571591693c7b415e9869157c711fe11263c95d74eDavid Li      } else if (strcmp(qualifier->value(), "in") == 0) {
4581591693c7b415e9869157c711fe11263c95d74eDavid Li	 var->mode = ir_var_in;
4591591693c7b415e9869157c711fe11263c95d74eDavid Li      } else if (strcmp(qualifier->value(), "out") == 0) {
4601591693c7b415e9869157c711fe11263c95d74eDavid Li	 var->mode = ir_var_out;
4611591693c7b415e9869157c711fe11263c95d74eDavid Li      } else if (strcmp(qualifier->value(), "inout") == 0) {
4621591693c7b415e9869157c711fe11263c95d74eDavid Li	 var->mode = ir_var_inout;
4631591693c7b415e9869157c711fe11263c95d74eDavid Li      } else if (strcmp(qualifier->value(), "smooth") == 0) {
4641591693c7b415e9869157c711fe11263c95d74eDavid Li	 var->interpolation = ir_var_smooth;
4651591693c7b415e9869157c711fe11263c95d74eDavid Li      } else if (strcmp(qualifier->value(), "flat") == 0) {
4661591693c7b415e9869157c711fe11263c95d74eDavid Li	 var->interpolation = ir_var_flat;
4671591693c7b415e9869157c711fe11263c95d74eDavid Li      } else if (strcmp(qualifier->value(), "noperspective") == 0) {
4681591693c7b415e9869157c711fe11263c95d74eDavid Li	 var->interpolation = ir_var_noperspective;
4691591693c7b415e9869157c711fe11263c95d74eDavid Li      } else {
4701591693c7b415e9869157c711fe11263c95d74eDavid Li	 ir_read_error(st, list, "unknown qualifier: %s", qualifier->value());
4711591693c7b415e9869157c711fe11263c95d74eDavid Li	 delete var;
4721591693c7b415e9869157c711fe11263c95d74eDavid Li	 return NULL;
4731591693c7b415e9869157c711fe11263c95d74eDavid Li      }
4741591693c7b415e9869157c711fe11263c95d74eDavid Li   }
4751591693c7b415e9869157c711fe11263c95d74eDavid Li
4761591693c7b415e9869157c711fe11263c95d74eDavid Li   // Add the variable to the symbol table
4771591693c7b415e9869157c711fe11263c95d74eDavid Li   st->symbols->add_variable(var);
4781591693c7b415e9869157c711fe11263c95d74eDavid Li
4791591693c7b415e9869157c711fe11263c95d74eDavid Li   return var;
4801591693c7b415e9869157c711fe11263c95d74eDavid Li}
4811591693c7b415e9869157c711fe11263c95d74eDavid Li
4821591693c7b415e9869157c711fe11263c95d74eDavid Li
4831591693c7b415e9869157c711fe11263c95d74eDavid Listatic ir_if *
4841591693c7b415e9869157c711fe11263c95d74eDavid Liread_if(_mesa_glsl_parse_state *st, s_list *list, ir_loop *loop_ctx)
4851591693c7b415e9869157c711fe11263c95d74eDavid Li{
4861591693c7b415e9869157c711fe11263c95d74eDavid Li   void *ctx = st;
4871591693c7b415e9869157c711fe11263c95d74eDavid Li   if (list->length() != 4) {
4881591693c7b415e9869157c711fe11263c95d74eDavid Li      ir_read_error(st, list, "expected (if <condition> (<then> ...) "
4891591693c7b415e9869157c711fe11263c95d74eDavid Li                          "(<else> ...))");
4901591693c7b415e9869157c711fe11263c95d74eDavid Li      return NULL;
4911591693c7b415e9869157c711fe11263c95d74eDavid Li   }
4921591693c7b415e9869157c711fe11263c95d74eDavid Li
4931591693c7b415e9869157c711fe11263c95d74eDavid Li   s_expression *cond_expr = (s_expression*) list->subexpressions.head->next;
4941591693c7b415e9869157c711fe11263c95d74eDavid Li   ir_rvalue *condition = read_rvalue(st, cond_expr);
4951591693c7b415e9869157c711fe11263c95d74eDavid Li   if (condition == NULL) {
4961591693c7b415e9869157c711fe11263c95d74eDavid Li      ir_read_error(st, NULL, "when reading condition of (if ...)");
4971591693c7b415e9869157c711fe11263c95d74eDavid Li      return NULL;
4981591693c7b415e9869157c711fe11263c95d74eDavid Li   }
4991591693c7b415e9869157c711fe11263c95d74eDavid Li
5001591693c7b415e9869157c711fe11263c95d74eDavid Li   s_expression *then_expr = (s_expression*) cond_expr->next;
5011591693c7b415e9869157c711fe11263c95d74eDavid Li   s_expression *else_expr = (s_expression*) then_expr->next;
5021591693c7b415e9869157c711fe11263c95d74eDavid Li
5031591693c7b415e9869157c711fe11263c95d74eDavid Li   ir_if *iff = new(ctx) ir_if(condition);
5041591693c7b415e9869157c711fe11263c95d74eDavid Li
5051591693c7b415e9869157c711fe11263c95d74eDavid Li   read_instructions(st, &iff->then_instructions, then_expr, loop_ctx);
5061591693c7b415e9869157c711fe11263c95d74eDavid Li   read_instructions(st, &iff->else_instructions, else_expr, loop_ctx);
5071591693c7b415e9869157c711fe11263c95d74eDavid Li   if (st->error) {
5081591693c7b415e9869157c711fe11263c95d74eDavid Li      delete iff;
5091591693c7b415e9869157c711fe11263c95d74eDavid Li      iff = NULL;
5101591693c7b415e9869157c711fe11263c95d74eDavid Li   }
5111591693c7b415e9869157c711fe11263c95d74eDavid Li   return iff;
5121591693c7b415e9869157c711fe11263c95d74eDavid Li}
5131591693c7b415e9869157c711fe11263c95d74eDavid Li
5141591693c7b415e9869157c711fe11263c95d74eDavid Li
5151591693c7b415e9869157c711fe11263c95d74eDavid Listatic ir_loop *
5161591693c7b415e9869157c711fe11263c95d74eDavid Liread_loop(_mesa_glsl_parse_state *st, s_list *list)
5171591693c7b415e9869157c711fe11263c95d74eDavid Li{
5181591693c7b415e9869157c711fe11263c95d74eDavid Li   void *ctx = st;
5191591693c7b415e9869157c711fe11263c95d74eDavid Li   if (list->length() != 6) {
5201591693c7b415e9869157c711fe11263c95d74eDavid Li      ir_read_error(st, list, "expected (loop <counter> <from> <to> "
5211591693c7b415e9869157c711fe11263c95d74eDavid Li			      "<increment> <body>)");
5221591693c7b415e9869157c711fe11263c95d74eDavid Li      return NULL;
5231591693c7b415e9869157c711fe11263c95d74eDavid Li   }
5241591693c7b415e9869157c711fe11263c95d74eDavid Li
5251591693c7b415e9869157c711fe11263c95d74eDavid Li   s_expression *count_expr = (s_expression*) list->subexpressions.head->next;
5261591693c7b415e9869157c711fe11263c95d74eDavid Li   s_expression *from_expr  = (s_expression*) count_expr->next;
5271591693c7b415e9869157c711fe11263c95d74eDavid Li   s_expression *to_expr    = (s_expression*) from_expr->next;
5281591693c7b415e9869157c711fe11263c95d74eDavid Li   s_expression *inc_expr   = (s_expression*) to_expr->next;
5291591693c7b415e9869157c711fe11263c95d74eDavid Li   s_expression *body_expr  = (s_expression*) inc_expr->next;
5301591693c7b415e9869157c711fe11263c95d74eDavid Li
5311591693c7b415e9869157c711fe11263c95d74eDavid Li   // FINISHME: actually read the count/from/to fields.
5321591693c7b415e9869157c711fe11263c95d74eDavid Li
5331591693c7b415e9869157c711fe11263c95d74eDavid Li   ir_loop *loop = new(ctx) ir_loop;
5341591693c7b415e9869157c711fe11263c95d74eDavid Li   read_instructions(st, &loop->body_instructions, body_expr, loop);
5351591693c7b415e9869157c711fe11263c95d74eDavid Li   if (st->error) {
5361591693c7b415e9869157c711fe11263c95d74eDavid Li      delete loop;
5371591693c7b415e9869157c711fe11263c95d74eDavid Li      loop = NULL;
5381591693c7b415e9869157c711fe11263c95d74eDavid Li   }
5391591693c7b415e9869157c711fe11263c95d74eDavid Li   return loop;
5401591693c7b415e9869157c711fe11263c95d74eDavid Li}
5411591693c7b415e9869157c711fe11263c95d74eDavid Li
5421591693c7b415e9869157c711fe11263c95d74eDavid Li
5431591693c7b415e9869157c711fe11263c95d74eDavid Listatic ir_return *
5441591693c7b415e9869157c711fe11263c95d74eDavid Liread_return(_mesa_glsl_parse_state *st, s_list *list)
5451591693c7b415e9869157c711fe11263c95d74eDavid Li{
5461591693c7b415e9869157c711fe11263c95d74eDavid Li   void *ctx = st;
5471591693c7b415e9869157c711fe11263c95d74eDavid Li   if (list->length() != 2) {
5481591693c7b415e9869157c711fe11263c95d74eDavid Li      ir_read_error(st, list, "expected (return <rvalue>)");
5491591693c7b415e9869157c711fe11263c95d74eDavid Li      return NULL;
5501591693c7b415e9869157c711fe11263c95d74eDavid Li   }
5511591693c7b415e9869157c711fe11263c95d74eDavid Li
5521591693c7b415e9869157c711fe11263c95d74eDavid Li   s_expression *expr = (s_expression*) list->subexpressions.head->next;
5531591693c7b415e9869157c711fe11263c95d74eDavid Li
5541591693c7b415e9869157c711fe11263c95d74eDavid Li   ir_rvalue *retval = read_rvalue(st, expr);
5551591693c7b415e9869157c711fe11263c95d74eDavid Li   if (retval == NULL) {
5561591693c7b415e9869157c711fe11263c95d74eDavid Li      ir_read_error(st, NULL, "when reading return value");
5571591693c7b415e9869157c711fe11263c95d74eDavid Li      return NULL;
5581591693c7b415e9869157c711fe11263c95d74eDavid Li   }
5591591693c7b415e9869157c711fe11263c95d74eDavid Li
5601591693c7b415e9869157c711fe11263c95d74eDavid Li   return new(ctx) ir_return(retval);
5611591693c7b415e9869157c711fe11263c95d74eDavid Li}
5621591693c7b415e9869157c711fe11263c95d74eDavid Li
5631591693c7b415e9869157c711fe11263c95d74eDavid Li
5641591693c7b415e9869157c711fe11263c95d74eDavid Listatic ir_rvalue *
5651591693c7b415e9869157c711fe11263c95d74eDavid Liread_rvalue(_mesa_glsl_parse_state *st, s_expression *expr)
5661591693c7b415e9869157c711fe11263c95d74eDavid Li{
5671591693c7b415e9869157c711fe11263c95d74eDavid Li   s_list *list = SX_AS_LIST(expr);
5681591693c7b415e9869157c711fe11263c95d74eDavid Li   if (list == NULL || list->subexpressions.is_empty())
5691591693c7b415e9869157c711fe11263c95d74eDavid Li      return NULL;
5701591693c7b415e9869157c711fe11263c95d74eDavid Li
5711591693c7b415e9869157c711fe11263c95d74eDavid Li   s_symbol *tag = SX_AS_SYMBOL(list->subexpressions.get_head());
5721591693c7b415e9869157c711fe11263c95d74eDavid Li   if (tag == NULL) {
5731591693c7b415e9869157c711fe11263c95d74eDavid Li      ir_read_error(st, expr, "expected rvalue tag");
5741591693c7b415e9869157c711fe11263c95d74eDavid Li      return NULL;
5751591693c7b415e9869157c711fe11263c95d74eDavid Li   }
5761591693c7b415e9869157c711fe11263c95d74eDavid Li
5771591693c7b415e9869157c711fe11263c95d74eDavid Li   ir_rvalue *rvalue = read_dereference(st, list);
5781591693c7b415e9869157c711fe11263c95d74eDavid Li   if (rvalue != NULL || st->error)
5791591693c7b415e9869157c711fe11263c95d74eDavid Li      return rvalue;
5801591693c7b415e9869157c711fe11263c95d74eDavid Li   else if (strcmp(tag->value(), "swiz") == 0) {
5811591693c7b415e9869157c711fe11263c95d74eDavid Li      rvalue = read_swizzle(st, list);
5821591693c7b415e9869157c711fe11263c95d74eDavid Li   } else if (strcmp(tag->value(), "expression") == 0) {
5831591693c7b415e9869157c711fe11263c95d74eDavid Li      rvalue = read_expression(st, list);
5841591693c7b415e9869157c711fe11263c95d74eDavid Li   } else if (strcmp(tag->value(), "call") == 0) {
5851591693c7b415e9869157c711fe11263c95d74eDavid Li      rvalue = read_call(st, list);
5861591693c7b415e9869157c711fe11263c95d74eDavid Li   } else if (strcmp(tag->value(), "constant") == 0) {
5871591693c7b415e9869157c711fe11263c95d74eDavid Li      rvalue = read_constant(st, list);
5881591693c7b415e9869157c711fe11263c95d74eDavid Li   } else {
5891591693c7b415e9869157c711fe11263c95d74eDavid Li      rvalue = read_texture(st, list);
5901591693c7b415e9869157c711fe11263c95d74eDavid Li      if (rvalue == NULL && !st->error)
5911591693c7b415e9869157c711fe11263c95d74eDavid Li	 ir_read_error(st, expr, "unrecognized rvalue tag: %s", tag->value());
5921591693c7b415e9869157c711fe11263c95d74eDavid Li   }
5931591693c7b415e9869157c711fe11263c95d74eDavid Li
5941591693c7b415e9869157c711fe11263c95d74eDavid Li   return rvalue;
5951591693c7b415e9869157c711fe11263c95d74eDavid Li}
5961591693c7b415e9869157c711fe11263c95d74eDavid Li
5971591693c7b415e9869157c711fe11263c95d74eDavid Listatic ir_assignment *
5981591693c7b415e9869157c711fe11263c95d74eDavid Liread_assignment(_mesa_glsl_parse_state *st, s_list *list)
5991591693c7b415e9869157c711fe11263c95d74eDavid Li{
6001591693c7b415e9869157c711fe11263c95d74eDavid Li   void *ctx = st;
6011591693c7b415e9869157c711fe11263c95d74eDavid Li   if (list->length() != 5) {
6021591693c7b415e9869157c711fe11263c95d74eDavid Li      ir_read_error(st, list, "expected (assign <condition> (<write mask>) "
6031591693c7b415e9869157c711fe11263c95d74eDavid Li			      "<lhs> <rhs>)");
6041591693c7b415e9869157c711fe11263c95d74eDavid Li      return NULL;
6051591693c7b415e9869157c711fe11263c95d74eDavid Li   }
6061591693c7b415e9869157c711fe11263c95d74eDavid Li
6071591693c7b415e9869157c711fe11263c95d74eDavid Li   s_expression *cond_expr = (s_expression*) list->subexpressions.head->next;
6081591693c7b415e9869157c711fe11263c95d74eDavid Li   s_list       *mask_list = SX_AS_LIST(cond_expr->next);
6091591693c7b415e9869157c711fe11263c95d74eDavid Li   s_expression *lhs_expr  = (s_expression*) cond_expr->next->next;
6101591693c7b415e9869157c711fe11263c95d74eDavid Li   s_expression *rhs_expr  = (s_expression*) lhs_expr->next;
6111591693c7b415e9869157c711fe11263c95d74eDavid Li
6121591693c7b415e9869157c711fe11263c95d74eDavid Li   ir_rvalue *condition = read_rvalue(st, cond_expr);
6131591693c7b415e9869157c711fe11263c95d74eDavid Li   if (condition == NULL) {
6141591693c7b415e9869157c711fe11263c95d74eDavid Li      ir_read_error(st, NULL, "when reading condition of assignment");
6151591693c7b415e9869157c711fe11263c95d74eDavid Li      return NULL;
6161591693c7b415e9869157c711fe11263c95d74eDavid Li   }
6171591693c7b415e9869157c711fe11263c95d74eDavid Li
6181591693c7b415e9869157c711fe11263c95d74eDavid Li   if (mask_list == NULL || mask_list->length() > 1) {
6191591693c7b415e9869157c711fe11263c95d74eDavid Li      ir_read_error(st, mask_list, "expected () or (<write mask>)");
6201591693c7b415e9869157c711fe11263c95d74eDavid Li      return NULL;
6211591693c7b415e9869157c711fe11263c95d74eDavid Li   }
6221591693c7b415e9869157c711fe11263c95d74eDavid Li
6231591693c7b415e9869157c711fe11263c95d74eDavid Li   unsigned mask = 0;
6241591693c7b415e9869157c711fe11263c95d74eDavid Li   if (mask_list->length() == 1) {
6251591693c7b415e9869157c711fe11263c95d74eDavid Li      s_symbol *mask_symbol = SX_AS_SYMBOL(mask_list->subexpressions.head);
6261591693c7b415e9869157c711fe11263c95d74eDavid Li      if (mask_symbol == NULL) {
6271591693c7b415e9869157c711fe11263c95d74eDavid Li	 ir_read_error(st, list, "expected a write mask; found non-symbol");
6281591693c7b415e9869157c711fe11263c95d74eDavid Li	 return NULL;
6291591693c7b415e9869157c711fe11263c95d74eDavid Li      }
6301591693c7b415e9869157c711fe11263c95d74eDavid Li
6311591693c7b415e9869157c711fe11263c95d74eDavid Li      const char *mask_str = mask_symbol->value();
6321591693c7b415e9869157c711fe11263c95d74eDavid Li      unsigned mask_length = strlen(mask_str);
6331591693c7b415e9869157c711fe11263c95d74eDavid Li      if (mask_length > 4) {
6341591693c7b415e9869157c711fe11263c95d74eDavid Li	 ir_read_error(st, list, "invalid write mask: %s", mask_str);
6351591693c7b415e9869157c711fe11263c95d74eDavid Li	 return NULL;
6361591693c7b415e9869157c711fe11263c95d74eDavid Li      }
6371591693c7b415e9869157c711fe11263c95d74eDavid Li
6381591693c7b415e9869157c711fe11263c95d74eDavid Li      const unsigned idx_map[] = { 3, 0, 1, 2 }; /* w=bit 3, x=0, y=1, z=2 */
6391591693c7b415e9869157c711fe11263c95d74eDavid Li
6401591693c7b415e9869157c711fe11263c95d74eDavid Li      for (unsigned i = 0; i < mask_length; i++) {
6411591693c7b415e9869157c711fe11263c95d74eDavid Li	 if (mask_str[i] < 'w' || mask_str[i] > 'z') {
6421591693c7b415e9869157c711fe11263c95d74eDavid Li	    ir_read_error(st, list, "write mask contains invalid character: %c",
6431591693c7b415e9869157c711fe11263c95d74eDavid Li			  mask_str[i]);
6441591693c7b415e9869157c711fe11263c95d74eDavid Li	    return NULL;
6451591693c7b415e9869157c711fe11263c95d74eDavid Li	 }
6461591693c7b415e9869157c711fe11263c95d74eDavid Li	 mask |= 1 << idx_map[mask_str[i] - 'w'];
6471591693c7b415e9869157c711fe11263c95d74eDavid Li      }
6481591693c7b415e9869157c711fe11263c95d74eDavid Li   }
6491591693c7b415e9869157c711fe11263c95d74eDavid Li
6501591693c7b415e9869157c711fe11263c95d74eDavid Li   ir_dereference *lhs = read_dereference(st, lhs_expr);
6511591693c7b415e9869157c711fe11263c95d74eDavid Li   if (lhs == NULL) {
6521591693c7b415e9869157c711fe11263c95d74eDavid Li      ir_read_error(st, NULL, "when reading left-hand side of assignment");
6531591693c7b415e9869157c711fe11263c95d74eDavid Li      return NULL;
6541591693c7b415e9869157c711fe11263c95d74eDavid Li   }
6551591693c7b415e9869157c711fe11263c95d74eDavid Li
6561591693c7b415e9869157c711fe11263c95d74eDavid Li   ir_rvalue *rhs = read_rvalue(st, rhs_expr);
6571591693c7b415e9869157c711fe11263c95d74eDavid Li   if (rhs == NULL) {
6581591693c7b415e9869157c711fe11263c95d74eDavid Li      ir_read_error(st, NULL, "when reading right-hand side of assignment");
6591591693c7b415e9869157c711fe11263c95d74eDavid Li      return NULL;
6601591693c7b415e9869157c711fe11263c95d74eDavid Li   }
6611591693c7b415e9869157c711fe11263c95d74eDavid Li
6621591693c7b415e9869157c711fe11263c95d74eDavid Li   if (mask == 0 && (lhs->type->is_vector() || lhs->type->is_scalar())) {
6631591693c7b415e9869157c711fe11263c95d74eDavid Li      ir_read_error(st, list, "non-zero write mask required.");
6641591693c7b415e9869157c711fe11263c95d74eDavid Li      return NULL;
6651591693c7b415e9869157c711fe11263c95d74eDavid Li   }
6661591693c7b415e9869157c711fe11263c95d74eDavid Li
6671591693c7b415e9869157c711fe11263c95d74eDavid Li   return new(ctx) ir_assignment(lhs, rhs, condition, mask);
6681591693c7b415e9869157c711fe11263c95d74eDavid Li}
6691591693c7b415e9869157c711fe11263c95d74eDavid Li
6701591693c7b415e9869157c711fe11263c95d74eDavid Listatic ir_call *
6711591693c7b415e9869157c711fe11263c95d74eDavid Liread_call(_mesa_glsl_parse_state *st, s_list *list)
6721591693c7b415e9869157c711fe11263c95d74eDavid Li{
6731591693c7b415e9869157c711fe11263c95d74eDavid Li   void *ctx = st;
6741591693c7b415e9869157c711fe11263c95d74eDavid Li   if (list->length() != 3) {
6751591693c7b415e9869157c711fe11263c95d74eDavid Li      ir_read_error(st, list, "expected (call <name> (<param> ...))");
6761591693c7b415e9869157c711fe11263c95d74eDavid Li      return NULL;
6771591693c7b415e9869157c711fe11263c95d74eDavid Li   }
6781591693c7b415e9869157c711fe11263c95d74eDavid Li
6791591693c7b415e9869157c711fe11263c95d74eDavid Li   s_symbol *name = SX_AS_SYMBOL(list->subexpressions.head->next);
6801591693c7b415e9869157c711fe11263c95d74eDavid Li   s_list *params = SX_AS_LIST(list->subexpressions.head->next->next);
6811591693c7b415e9869157c711fe11263c95d74eDavid Li   if (name == NULL || params == NULL) {
6821591693c7b415e9869157c711fe11263c95d74eDavid Li      ir_read_error(st, list, "expected (call <name> (<param> ...))");
6831591693c7b415e9869157c711fe11263c95d74eDavid Li      return NULL;
6841591693c7b415e9869157c711fe11263c95d74eDavid Li   }
6851591693c7b415e9869157c711fe11263c95d74eDavid Li
6861591693c7b415e9869157c711fe11263c95d74eDavid Li   exec_list parameters;
6871591693c7b415e9869157c711fe11263c95d74eDavid Li
6881591693c7b415e9869157c711fe11263c95d74eDavid Li   foreach_iter(exec_list_iterator, it, params->subexpressions) {
6891591693c7b415e9869157c711fe11263c95d74eDavid Li      s_expression *expr = (s_expression*) it.get();
6901591693c7b415e9869157c711fe11263c95d74eDavid Li      ir_rvalue *param = read_rvalue(st, expr);
6911591693c7b415e9869157c711fe11263c95d74eDavid Li      if (param == NULL) {
6921591693c7b415e9869157c711fe11263c95d74eDavid Li	 ir_read_error(st, list, "when reading parameter to function call");
6931591693c7b415e9869157c711fe11263c95d74eDavid Li	 return NULL;
6941591693c7b415e9869157c711fe11263c95d74eDavid Li      }
6951591693c7b415e9869157c711fe11263c95d74eDavid Li      parameters.push_tail(param);
6961591693c7b415e9869157c711fe11263c95d74eDavid Li   }
6971591693c7b415e9869157c711fe11263c95d74eDavid Li
6981591693c7b415e9869157c711fe11263c95d74eDavid Li   ir_function *f = st->symbols->get_function(name->value());
6991591693c7b415e9869157c711fe11263c95d74eDavid Li   if (f == NULL) {
7001591693c7b415e9869157c711fe11263c95d74eDavid Li      ir_read_error(st, list, "found call to undefined function %s",
7011591693c7b415e9869157c711fe11263c95d74eDavid Li		    name->value());
7021591693c7b415e9869157c711fe11263c95d74eDavid Li      return NULL;
7031591693c7b415e9869157c711fe11263c95d74eDavid Li   }
7041591693c7b415e9869157c711fe11263c95d74eDavid Li
7051591693c7b415e9869157c711fe11263c95d74eDavid Li   ir_function_signature *callee = f->matching_signature(&parameters);
7061591693c7b415e9869157c711fe11263c95d74eDavid Li   if (callee == NULL) {
7071591693c7b415e9869157c711fe11263c95d74eDavid Li      ir_read_error(st, list, "couldn't find matching signature for function "
7081591693c7b415e9869157c711fe11263c95d74eDavid Li                    "%s", name->value());
7091591693c7b415e9869157c711fe11263c95d74eDavid Li      return NULL;
7101591693c7b415e9869157c711fe11263c95d74eDavid Li   }
7111591693c7b415e9869157c711fe11263c95d74eDavid Li
7121591693c7b415e9869157c711fe11263c95d74eDavid Li   return new(ctx) ir_call(callee, &parameters);
7131591693c7b415e9869157c711fe11263c95d74eDavid Li}
7141591693c7b415e9869157c711fe11263c95d74eDavid Li
7151591693c7b415e9869157c711fe11263c95d74eDavid Listatic ir_expression *
7161591693c7b415e9869157c711fe11263c95d74eDavid Liread_expression(_mesa_glsl_parse_state *st, s_list *list)
7171591693c7b415e9869157c711fe11263c95d74eDavid Li{
7181591693c7b415e9869157c711fe11263c95d74eDavid Li   void *ctx = st;
7191591693c7b415e9869157c711fe11263c95d74eDavid Li   const unsigned list_length = list->length();
7201591693c7b415e9869157c711fe11263c95d74eDavid Li   if (list_length < 4) {
7211591693c7b415e9869157c711fe11263c95d74eDavid Li      ir_read_error(st, list, "expected (expression <type> <operator> "
7221591693c7b415e9869157c711fe11263c95d74eDavid Li			      "<operand> [<operand>])");
7231591693c7b415e9869157c711fe11263c95d74eDavid Li      return NULL;
7241591693c7b415e9869157c711fe11263c95d74eDavid Li   }
7251591693c7b415e9869157c711fe11263c95d74eDavid Li
7261591693c7b415e9869157c711fe11263c95d74eDavid Li   s_expression *type_expr = (s_expression*) list->subexpressions.head->next;
7271591693c7b415e9869157c711fe11263c95d74eDavid Li   const glsl_type *type = read_type(st, type_expr);
7281591693c7b415e9869157c711fe11263c95d74eDavid Li   if (type == NULL)
7291591693c7b415e9869157c711fe11263c95d74eDavid Li      return NULL;
7301591693c7b415e9869157c711fe11263c95d74eDavid Li
7311591693c7b415e9869157c711fe11263c95d74eDavid Li   /* Read the operator */
7321591693c7b415e9869157c711fe11263c95d74eDavid Li   s_symbol *op_sym = SX_AS_SYMBOL(type_expr->next);
7331591693c7b415e9869157c711fe11263c95d74eDavid Li   if (op_sym == NULL) {
7341591693c7b415e9869157c711fe11263c95d74eDavid Li      ir_read_error(st, list, "expected operator, found non-symbol");
7351591693c7b415e9869157c711fe11263c95d74eDavid Li      return NULL;
7361591693c7b415e9869157c711fe11263c95d74eDavid Li   }
7371591693c7b415e9869157c711fe11263c95d74eDavid Li
7381591693c7b415e9869157c711fe11263c95d74eDavid Li   ir_expression_operation op = ir_expression::get_operator(op_sym->value());
7391591693c7b415e9869157c711fe11263c95d74eDavid Li   if (op == (ir_expression_operation) -1) {
7401591693c7b415e9869157c711fe11263c95d74eDavid Li      ir_read_error(st, list, "invalid operator: %s", op_sym->value());
7411591693c7b415e9869157c711fe11263c95d74eDavid Li      return NULL;
7421591693c7b415e9869157c711fe11263c95d74eDavid Li   }
7431591693c7b415e9869157c711fe11263c95d74eDavid Li
7441591693c7b415e9869157c711fe11263c95d74eDavid Li   /* Now that we know the operator, check for the right number of operands */
7451591693c7b415e9869157c711fe11263c95d74eDavid Li   if (ir_expression::get_num_operands(op) == 2) {
7461591693c7b415e9869157c711fe11263c95d74eDavid Li      if (list_length != 5) {
7471591693c7b415e9869157c711fe11263c95d74eDavid Li	 ir_read_error(st, list, "expected (expression <type> %s <operand> "
7481591693c7b415e9869157c711fe11263c95d74eDavid Li				 " <operand>)", op_sym->value());
7491591693c7b415e9869157c711fe11263c95d74eDavid Li	 return NULL;
7501591693c7b415e9869157c711fe11263c95d74eDavid Li      }
7511591693c7b415e9869157c711fe11263c95d74eDavid Li   } else {
7521591693c7b415e9869157c711fe11263c95d74eDavid Li      if (list_length != 4) {
7531591693c7b415e9869157c711fe11263c95d74eDavid Li	 ir_read_error(st, list, "expected (expression <type> %s <operand>)",
7541591693c7b415e9869157c711fe11263c95d74eDavid Li		       op_sym->value());
7551591693c7b415e9869157c711fe11263c95d74eDavid Li	 return NULL;
7561591693c7b415e9869157c711fe11263c95d74eDavid Li      }
7571591693c7b415e9869157c711fe11263c95d74eDavid Li   }
7581591693c7b415e9869157c711fe11263c95d74eDavid Li
7591591693c7b415e9869157c711fe11263c95d74eDavid Li   s_expression *exp1 = (s_expression*) (op_sym->next);
7601591693c7b415e9869157c711fe11263c95d74eDavid Li   ir_rvalue *arg1 = read_rvalue(st, exp1);
7611591693c7b415e9869157c711fe11263c95d74eDavid Li   if (arg1 == NULL) {
7621591693c7b415e9869157c711fe11263c95d74eDavid Li      ir_read_error(st, NULL, "when reading first operand of %s",
7631591693c7b415e9869157c711fe11263c95d74eDavid Li		    op_sym->value());
7641591693c7b415e9869157c711fe11263c95d74eDavid Li      return NULL;
7651591693c7b415e9869157c711fe11263c95d74eDavid Li   }
7661591693c7b415e9869157c711fe11263c95d74eDavid Li
7671591693c7b415e9869157c711fe11263c95d74eDavid Li   ir_rvalue *arg2 = NULL;
7681591693c7b415e9869157c711fe11263c95d74eDavid Li   if (ir_expression::get_num_operands(op) == 2) {
7691591693c7b415e9869157c711fe11263c95d74eDavid Li      s_expression *exp2 = (s_expression*) (exp1->next);
7701591693c7b415e9869157c711fe11263c95d74eDavid Li      arg2 = read_rvalue(st, exp2);
7711591693c7b415e9869157c711fe11263c95d74eDavid Li      if (arg2 == NULL) {
7721591693c7b415e9869157c711fe11263c95d74eDavid Li	 ir_read_error(st, NULL, "when reading second operand of %s",
7731591693c7b415e9869157c711fe11263c95d74eDavid Li		       op_sym->value());
7741591693c7b415e9869157c711fe11263c95d74eDavid Li	 return NULL;
7751591693c7b415e9869157c711fe11263c95d74eDavid Li      }
7761591693c7b415e9869157c711fe11263c95d74eDavid Li   }
7771591693c7b415e9869157c711fe11263c95d74eDavid Li
7781591693c7b415e9869157c711fe11263c95d74eDavid Li   return new(ctx) ir_expression(op, type, arg1, arg2);
7791591693c7b415e9869157c711fe11263c95d74eDavid Li}
7801591693c7b415e9869157c711fe11263c95d74eDavid Li
7811591693c7b415e9869157c711fe11263c95d74eDavid Listatic ir_swizzle *
7821591693c7b415e9869157c711fe11263c95d74eDavid Liread_swizzle(_mesa_glsl_parse_state *st, s_list *list)
7831591693c7b415e9869157c711fe11263c95d74eDavid Li{
7841591693c7b415e9869157c711fe11263c95d74eDavid Li   if (list->length() != 3) {
7851591693c7b415e9869157c711fe11263c95d74eDavid Li      ir_read_error(st, list, "expected (swiz <swizzle> <rvalue>)");
7861591693c7b415e9869157c711fe11263c95d74eDavid Li      return NULL;
7871591693c7b415e9869157c711fe11263c95d74eDavid Li   }
7881591693c7b415e9869157c711fe11263c95d74eDavid Li
7891591693c7b415e9869157c711fe11263c95d74eDavid Li   s_symbol *swiz = SX_AS_SYMBOL(list->subexpressions.head->next);
7901591693c7b415e9869157c711fe11263c95d74eDavid Li   if (swiz == NULL) {
7911591693c7b415e9869157c711fe11263c95d74eDavid Li      ir_read_error(st, list, "expected a valid swizzle; found non-symbol");
7921591693c7b415e9869157c711fe11263c95d74eDavid Li      return NULL;
7931591693c7b415e9869157c711fe11263c95d74eDavid Li   }
7941591693c7b415e9869157c711fe11263c95d74eDavid Li
7951591693c7b415e9869157c711fe11263c95d74eDavid Li   if (strlen(swiz->value()) > 4) {
7961591693c7b415e9869157c711fe11263c95d74eDavid Li      ir_read_error(st, list, "expected a valid swizzle; found %s",
7971591693c7b415e9869157c711fe11263c95d74eDavid Li		    swiz->value());
7981591693c7b415e9869157c711fe11263c95d74eDavid Li      return NULL;
7991591693c7b415e9869157c711fe11263c95d74eDavid Li   }
8001591693c7b415e9869157c711fe11263c95d74eDavid Li
8011591693c7b415e9869157c711fe11263c95d74eDavid Li   s_expression *sub = (s_expression*) swiz->next;
8021591693c7b415e9869157c711fe11263c95d74eDavid Li   ir_rvalue *rvalue = read_rvalue(st, sub);
8031591693c7b415e9869157c711fe11263c95d74eDavid Li   if (rvalue == NULL)
8041591693c7b415e9869157c711fe11263c95d74eDavid Li      return NULL;
8051591693c7b415e9869157c711fe11263c95d74eDavid Li
8061591693c7b415e9869157c711fe11263c95d74eDavid Li   ir_swizzle *ir = ir_swizzle::create(rvalue, swiz->value(),
8071591693c7b415e9869157c711fe11263c95d74eDavid Li				       rvalue->type->vector_elements);
8081591693c7b415e9869157c711fe11263c95d74eDavid Li   if (ir == NULL)
8091591693c7b415e9869157c711fe11263c95d74eDavid Li      ir_read_error(st, list, "invalid swizzle");
8101591693c7b415e9869157c711fe11263c95d74eDavid Li
8111591693c7b415e9869157c711fe11263c95d74eDavid Li   return ir;
8121591693c7b415e9869157c711fe11263c95d74eDavid Li}
8131591693c7b415e9869157c711fe11263c95d74eDavid Li
8141591693c7b415e9869157c711fe11263c95d74eDavid Listatic ir_constant *
8151591693c7b415e9869157c711fe11263c95d74eDavid Liread_constant(_mesa_glsl_parse_state *st, s_list *list)
8161591693c7b415e9869157c711fe11263c95d74eDavid Li{
8171591693c7b415e9869157c711fe11263c95d74eDavid Li   void *ctx = st;
8181591693c7b415e9869157c711fe11263c95d74eDavid Li   if (list->length() != 3) {
8191591693c7b415e9869157c711fe11263c95d74eDavid Li      ir_read_error(st, list, "expected (constant <type> (...))");
8201591693c7b415e9869157c711fe11263c95d74eDavid Li      return NULL;
8211591693c7b415e9869157c711fe11263c95d74eDavid Li   }
8221591693c7b415e9869157c711fe11263c95d74eDavid Li
8231591693c7b415e9869157c711fe11263c95d74eDavid Li   s_expression *type_expr = (s_expression*) list->subexpressions.head->next;
8241591693c7b415e9869157c711fe11263c95d74eDavid Li   const glsl_type *type = read_type(st, type_expr);
8251591693c7b415e9869157c711fe11263c95d74eDavid Li   if (type == NULL)
8261591693c7b415e9869157c711fe11263c95d74eDavid Li      return NULL;
8271591693c7b415e9869157c711fe11263c95d74eDavid Li
8281591693c7b415e9869157c711fe11263c95d74eDavid Li   s_list *values = SX_AS_LIST(type_expr->next);
8291591693c7b415e9869157c711fe11263c95d74eDavid Li   if (values == NULL) {
8301591693c7b415e9869157c711fe11263c95d74eDavid Li      ir_read_error(st, list, "expected (constant <type> (...))");
8311591693c7b415e9869157c711fe11263c95d74eDavid Li      return NULL;
8321591693c7b415e9869157c711fe11263c95d74eDavid Li   }
8331591693c7b415e9869157c711fe11263c95d74eDavid Li
8341591693c7b415e9869157c711fe11263c95d74eDavid Li   if (type->is_array()) {
8351591693c7b415e9869157c711fe11263c95d74eDavid Li      const unsigned elements_supplied = values->length();
8361591693c7b415e9869157c711fe11263c95d74eDavid Li      if (elements_supplied != type->length) {
8371591693c7b415e9869157c711fe11263c95d74eDavid Li	 ir_read_error(st, values, "expected exactly %u array elements, "
8381591693c7b415e9869157c711fe11263c95d74eDavid Li		       "given %u", type->length, elements_supplied);
8391591693c7b415e9869157c711fe11263c95d74eDavid Li	 return NULL;
8401591693c7b415e9869157c711fe11263c95d74eDavid Li      }
8411591693c7b415e9869157c711fe11263c95d74eDavid Li
8421591693c7b415e9869157c711fe11263c95d74eDavid Li      exec_list elements;
8431591693c7b415e9869157c711fe11263c95d74eDavid Li      foreach_iter(exec_list_iterator, it, values->subexpressions) {
8441591693c7b415e9869157c711fe11263c95d74eDavid Li	 s_expression *expr = (s_expression *) it.get();
8451591693c7b415e9869157c711fe11263c95d74eDavid Li	 s_list *elt = SX_AS_LIST(expr);
8461591693c7b415e9869157c711fe11263c95d74eDavid Li	 if (elt == NULL) {
8471591693c7b415e9869157c711fe11263c95d74eDavid Li	    ir_read_error(st, expr, "expected (constant ...) array element");
8481591693c7b415e9869157c711fe11263c95d74eDavid Li	    return NULL;
8491591693c7b415e9869157c711fe11263c95d74eDavid Li	 }
8501591693c7b415e9869157c711fe11263c95d74eDavid Li
8511591693c7b415e9869157c711fe11263c95d74eDavid Li	 ir_constant *ir_elt = read_constant(st, elt);
8521591693c7b415e9869157c711fe11263c95d74eDavid Li	 if (ir_elt == NULL)
8531591693c7b415e9869157c711fe11263c95d74eDavid Li	    return NULL;
8541591693c7b415e9869157c711fe11263c95d74eDavid Li	 elements.push_tail(ir_elt);
8551591693c7b415e9869157c711fe11263c95d74eDavid Li      }
8561591693c7b415e9869157c711fe11263c95d74eDavid Li      return new(ctx) ir_constant(type, &elements);
8571591693c7b415e9869157c711fe11263c95d74eDavid Li   }
8581591693c7b415e9869157c711fe11263c95d74eDavid Li
8591591693c7b415e9869157c711fe11263c95d74eDavid Li   const glsl_type *const base_type = type->get_base_type();
8601591693c7b415e9869157c711fe11263c95d74eDavid Li
8611591693c7b415e9869157c711fe11263c95d74eDavid Li   ir_constant_data data = { { 0 } };
8621591693c7b415e9869157c711fe11263c95d74eDavid Li
8631591693c7b415e9869157c711fe11263c95d74eDavid Li   // Read in list of values (at most 16).
8641591693c7b415e9869157c711fe11263c95d74eDavid Li   int k = 0;
8651591693c7b415e9869157c711fe11263c95d74eDavid Li   foreach_iter(exec_list_iterator, it, values->subexpressions) {
8661591693c7b415e9869157c711fe11263c95d74eDavid Li      if (k >= 16) {
8671591693c7b415e9869157c711fe11263c95d74eDavid Li	 ir_read_error(st, values, "expected at most 16 numbers");
8681591693c7b415e9869157c711fe11263c95d74eDavid Li	 return NULL;
8691591693c7b415e9869157c711fe11263c95d74eDavid Li      }
8701591693c7b415e9869157c711fe11263c95d74eDavid Li
8711591693c7b415e9869157c711fe11263c95d74eDavid Li      s_expression *expr = (s_expression*) it.get();
8721591693c7b415e9869157c711fe11263c95d74eDavid Li
8731591693c7b415e9869157c711fe11263c95d74eDavid Li      if (base_type->base_type == GLSL_TYPE_FLOAT) {
8741591693c7b415e9869157c711fe11263c95d74eDavid Li	 s_number *value = SX_AS_NUMBER(expr);
8751591693c7b415e9869157c711fe11263c95d74eDavid Li	 if (value == NULL) {
8761591693c7b415e9869157c711fe11263c95d74eDavid Li	    ir_read_error(st, values, "expected numbers");
8771591693c7b415e9869157c711fe11263c95d74eDavid Li	    return NULL;
8781591693c7b415e9869157c711fe11263c95d74eDavid Li	 }
8791591693c7b415e9869157c711fe11263c95d74eDavid Li	 data.f[k] = value->fvalue();
8801591693c7b415e9869157c711fe11263c95d74eDavid Li      } else {
8811591693c7b415e9869157c711fe11263c95d74eDavid Li	 s_int *value = SX_AS_INT(expr);
8821591693c7b415e9869157c711fe11263c95d74eDavid Li	 if (value == NULL) {
8831591693c7b415e9869157c711fe11263c95d74eDavid Li	    ir_read_error(st, values, "expected integers");
8841591693c7b415e9869157c711fe11263c95d74eDavid Li	    return NULL;
8851591693c7b415e9869157c711fe11263c95d74eDavid Li	 }
8861591693c7b415e9869157c711fe11263c95d74eDavid Li
8871591693c7b415e9869157c711fe11263c95d74eDavid Li	 switch (base_type->base_type) {
8881591693c7b415e9869157c711fe11263c95d74eDavid Li	 case GLSL_TYPE_UINT: {
8891591693c7b415e9869157c711fe11263c95d74eDavid Li	    data.u[k] = value->value();
8901591693c7b415e9869157c711fe11263c95d74eDavid Li	    break;
8911591693c7b415e9869157c711fe11263c95d74eDavid Li	 }
8921591693c7b415e9869157c711fe11263c95d74eDavid Li	 case GLSL_TYPE_INT: {
8931591693c7b415e9869157c711fe11263c95d74eDavid Li	    data.i[k] = value->value();
8941591693c7b415e9869157c711fe11263c95d74eDavid Li	    break;
8951591693c7b415e9869157c711fe11263c95d74eDavid Li	 }
8961591693c7b415e9869157c711fe11263c95d74eDavid Li	 case GLSL_TYPE_BOOL: {
8971591693c7b415e9869157c711fe11263c95d74eDavid Li	    data.b[k] = value->value();
8981591693c7b415e9869157c711fe11263c95d74eDavid Li	    break;
8991591693c7b415e9869157c711fe11263c95d74eDavid Li	 }
9001591693c7b415e9869157c711fe11263c95d74eDavid Li	 default:
9011591693c7b415e9869157c711fe11263c95d74eDavid Li	    ir_read_error(st, values, "unsupported constant type");
9021591693c7b415e9869157c711fe11263c95d74eDavid Li	    return NULL;
9031591693c7b415e9869157c711fe11263c95d74eDavid Li	 }
9041591693c7b415e9869157c711fe11263c95d74eDavid Li      }
9051591693c7b415e9869157c711fe11263c95d74eDavid Li      ++k;
9061591693c7b415e9869157c711fe11263c95d74eDavid Li   }
9071591693c7b415e9869157c711fe11263c95d74eDavid Li
9081591693c7b415e9869157c711fe11263c95d74eDavid Li   return new(ctx) ir_constant(type, &data);
9091591693c7b415e9869157c711fe11263c95d74eDavid Li}
9101591693c7b415e9869157c711fe11263c95d74eDavid Li
9111591693c7b415e9869157c711fe11263c95d74eDavid Listatic ir_dereference *
9121591693c7b415e9869157c711fe11263c95d74eDavid Liread_dereference(_mesa_glsl_parse_state *st, s_expression *expr)
9131591693c7b415e9869157c711fe11263c95d74eDavid Li{
9141591693c7b415e9869157c711fe11263c95d74eDavid Li   s_list *list = SX_AS_LIST(expr);
9151591693c7b415e9869157c711fe11263c95d74eDavid Li   if (list == NULL || list->subexpressions.is_empty())
9161591693c7b415e9869157c711fe11263c95d74eDavid Li      return NULL;
9171591693c7b415e9869157c711fe11263c95d74eDavid Li
9181591693c7b415e9869157c711fe11263c95d74eDavid Li   s_symbol *tag = SX_AS_SYMBOL(list->subexpressions.head);
9191591693c7b415e9869157c711fe11263c95d74eDavid Li   assert(tag != NULL);
9201591693c7b415e9869157c711fe11263c95d74eDavid Li
9211591693c7b415e9869157c711fe11263c95d74eDavid Li   if (strcmp(tag->value(), "var_ref") == 0)
9221591693c7b415e9869157c711fe11263c95d74eDavid Li      return read_var_ref(st, list);
9231591693c7b415e9869157c711fe11263c95d74eDavid Li   if (strcmp(tag->value(), "array_ref") == 0)
9241591693c7b415e9869157c711fe11263c95d74eDavid Li      return read_array_ref(st, list);
9251591693c7b415e9869157c711fe11263c95d74eDavid Li   if (strcmp(tag->value(), "record_ref") == 0)
9261591693c7b415e9869157c711fe11263c95d74eDavid Li      return read_record_ref(st, list);
9271591693c7b415e9869157c711fe11263c95d74eDavid Li   return NULL;
9281591693c7b415e9869157c711fe11263c95d74eDavid Li}
9291591693c7b415e9869157c711fe11263c95d74eDavid Li
9301591693c7b415e9869157c711fe11263c95d74eDavid Listatic ir_dereference_variable *
9311591693c7b415e9869157c711fe11263c95d74eDavid Liread_var_ref(_mesa_glsl_parse_state *st, s_list *list)
9321591693c7b415e9869157c711fe11263c95d74eDavid Li{
9331591693c7b415e9869157c711fe11263c95d74eDavid Li   void *ctx = st;
9341591693c7b415e9869157c711fe11263c95d74eDavid Li   if (list->length() != 2) {
9351591693c7b415e9869157c711fe11263c95d74eDavid Li      ir_read_error(st, list, "expected (var_ref <variable name>)");
9361591693c7b415e9869157c711fe11263c95d74eDavid Li      return NULL;
9371591693c7b415e9869157c711fe11263c95d74eDavid Li   }
9381591693c7b415e9869157c711fe11263c95d74eDavid Li   s_symbol *var_name = SX_AS_SYMBOL(list->subexpressions.head->next);
9391591693c7b415e9869157c711fe11263c95d74eDavid Li   if (var_name == NULL) {
9401591693c7b415e9869157c711fe11263c95d74eDavid Li      ir_read_error(st, list, "expected (var_ref <variable name>)");
9411591693c7b415e9869157c711fe11263c95d74eDavid Li      return NULL;
9421591693c7b415e9869157c711fe11263c95d74eDavid Li   }
9431591693c7b415e9869157c711fe11263c95d74eDavid Li
9441591693c7b415e9869157c711fe11263c95d74eDavid Li   ir_variable *var = st->symbols->get_variable(var_name->value());
9451591693c7b415e9869157c711fe11263c95d74eDavid Li   if (var == NULL) {
9461591693c7b415e9869157c711fe11263c95d74eDavid Li      ir_read_error(st, list, "undeclared variable: %s", var_name->value());
9471591693c7b415e9869157c711fe11263c95d74eDavid Li      return NULL;
9481591693c7b415e9869157c711fe11263c95d74eDavid Li   }
9491591693c7b415e9869157c711fe11263c95d74eDavid Li
9501591693c7b415e9869157c711fe11263c95d74eDavid Li   return new(ctx) ir_dereference_variable(var);
9511591693c7b415e9869157c711fe11263c95d74eDavid Li}
9521591693c7b415e9869157c711fe11263c95d74eDavid Li
9531591693c7b415e9869157c711fe11263c95d74eDavid Listatic ir_dereference_array *
9541591693c7b415e9869157c711fe11263c95d74eDavid Liread_array_ref(_mesa_glsl_parse_state *st, s_list *list)
9551591693c7b415e9869157c711fe11263c95d74eDavid Li{
9561591693c7b415e9869157c711fe11263c95d74eDavid Li   void *ctx = st;
9571591693c7b415e9869157c711fe11263c95d74eDavid Li   if (list->length() != 3) {
9581591693c7b415e9869157c711fe11263c95d74eDavid Li      ir_read_error(st, list, "expected (array_ref <rvalue> <index>)");
9591591693c7b415e9869157c711fe11263c95d74eDavid Li      return NULL;
9601591693c7b415e9869157c711fe11263c95d74eDavid Li   }
9611591693c7b415e9869157c711fe11263c95d74eDavid Li
9621591693c7b415e9869157c711fe11263c95d74eDavid Li   s_expression *subj_expr = (s_expression*) list->subexpressions.head->next;
9631591693c7b415e9869157c711fe11263c95d74eDavid Li   ir_rvalue *subject = read_rvalue(st, subj_expr);
9641591693c7b415e9869157c711fe11263c95d74eDavid Li   if (subject == NULL) {
9651591693c7b415e9869157c711fe11263c95d74eDavid Li      ir_read_error(st, NULL, "when reading the subject of an array_ref");
9661591693c7b415e9869157c711fe11263c95d74eDavid Li      return NULL;
9671591693c7b415e9869157c711fe11263c95d74eDavid Li   }
9681591693c7b415e9869157c711fe11263c95d74eDavid Li
9691591693c7b415e9869157c711fe11263c95d74eDavid Li   s_expression *idx_expr = (s_expression*) subj_expr->next;
9701591693c7b415e9869157c711fe11263c95d74eDavid Li   ir_rvalue *idx = read_rvalue(st, idx_expr);
9711591693c7b415e9869157c711fe11263c95d74eDavid Li   return new(ctx) ir_dereference_array(subject, idx);
9721591693c7b415e9869157c711fe11263c95d74eDavid Li}
9731591693c7b415e9869157c711fe11263c95d74eDavid Li
9741591693c7b415e9869157c711fe11263c95d74eDavid Listatic ir_dereference_record *
9751591693c7b415e9869157c711fe11263c95d74eDavid Liread_record_ref(_mesa_glsl_parse_state *st, s_list *list)
9761591693c7b415e9869157c711fe11263c95d74eDavid Li{
9771591693c7b415e9869157c711fe11263c95d74eDavid Li   void *ctx = st;
9781591693c7b415e9869157c711fe11263c95d74eDavid Li   if (list->length() != 3) {
9791591693c7b415e9869157c711fe11263c95d74eDavid Li      ir_read_error(st, list, "expected (record_ref <rvalue> <field>)");
9801591693c7b415e9869157c711fe11263c95d74eDavid Li      return NULL;
9811591693c7b415e9869157c711fe11263c95d74eDavid Li   }
9821591693c7b415e9869157c711fe11263c95d74eDavid Li
9831591693c7b415e9869157c711fe11263c95d74eDavid Li   s_expression *subj_expr = (s_expression*) list->subexpressions.head->next;
9841591693c7b415e9869157c711fe11263c95d74eDavid Li   ir_rvalue *subject = read_rvalue(st, subj_expr);
9851591693c7b415e9869157c711fe11263c95d74eDavid Li   if (subject == NULL) {
9861591693c7b415e9869157c711fe11263c95d74eDavid Li      ir_read_error(st, NULL, "when reading the subject of a record_ref");
9871591693c7b415e9869157c711fe11263c95d74eDavid Li      return NULL;
9881591693c7b415e9869157c711fe11263c95d74eDavid Li   }
9891591693c7b415e9869157c711fe11263c95d74eDavid Li
9901591693c7b415e9869157c711fe11263c95d74eDavid Li   s_symbol *field = SX_AS_SYMBOL(subj_expr->next);
9911591693c7b415e9869157c711fe11263c95d74eDavid Li   if (field == NULL) {
9921591693c7b415e9869157c711fe11263c95d74eDavid Li      ir_read_error(st, list, "expected (record_ref ... <field name>)");
9931591693c7b415e9869157c711fe11263c95d74eDavid Li      return NULL;
9941591693c7b415e9869157c711fe11263c95d74eDavid Li   }
9951591693c7b415e9869157c711fe11263c95d74eDavid Li   return new(ctx) ir_dereference_record(subject, field->value());
9961591693c7b415e9869157c711fe11263c95d74eDavid Li}
9971591693c7b415e9869157c711fe11263c95d74eDavid Li
9981591693c7b415e9869157c711fe11263c95d74eDavid Listatic bool
9991591693c7b415e9869157c711fe11263c95d74eDavid Livalid_texture_list_length(ir_texture_opcode op, s_list *list)
10001591693c7b415e9869157c711fe11263c95d74eDavid Li{
10011591693c7b415e9869157c711fe11263c95d74eDavid Li   unsigned required_length = 7;
10021591693c7b415e9869157c711fe11263c95d74eDavid Li   if (op == ir_txf)
10031591693c7b415e9869157c711fe11263c95d74eDavid Li      required_length = 5;
10041591693c7b415e9869157c711fe11263c95d74eDavid Li   else if (op == ir_tex)
10051591693c7b415e9869157c711fe11263c95d74eDavid Li      required_length = 6;
10061591693c7b415e9869157c711fe11263c95d74eDavid Li
10071591693c7b415e9869157c711fe11263c95d74eDavid Li   return list->length() == required_length;
10081591693c7b415e9869157c711fe11263c95d74eDavid Li}
10091591693c7b415e9869157c711fe11263c95d74eDavid Li
10101591693c7b415e9869157c711fe11263c95d74eDavid Listatic ir_texture *
10111591693c7b415e9869157c711fe11263c95d74eDavid Liread_texture(_mesa_glsl_parse_state *st, s_list *list)
10121591693c7b415e9869157c711fe11263c95d74eDavid Li{
10131591693c7b415e9869157c711fe11263c95d74eDavid Li   void *ctx = st;
10141591693c7b415e9869157c711fe11263c95d74eDavid Li   s_symbol *tag = SX_AS_SYMBOL(list->subexpressions.head);
10151591693c7b415e9869157c711fe11263c95d74eDavid Li   assert(tag != NULL);
10161591693c7b415e9869157c711fe11263c95d74eDavid Li
10171591693c7b415e9869157c711fe11263c95d74eDavid Li   ir_texture_opcode op = ir_texture::get_opcode(tag->value());
10181591693c7b415e9869157c711fe11263c95d74eDavid Li   if (op == (ir_texture_opcode) -1)
10191591693c7b415e9869157c711fe11263c95d74eDavid Li      return NULL;
10201591693c7b415e9869157c711fe11263c95d74eDavid Li
10211591693c7b415e9869157c711fe11263c95d74eDavid Li   if (!valid_texture_list_length(op, list)) {
10221591693c7b415e9869157c711fe11263c95d74eDavid Li      ir_read_error(st, NULL, "invalid list size in (%s ...)", tag->value());
10231591693c7b415e9869157c711fe11263c95d74eDavid Li      return NULL;
10241591693c7b415e9869157c711fe11263c95d74eDavid Li   }
10251591693c7b415e9869157c711fe11263c95d74eDavid Li
10261591693c7b415e9869157c711fe11263c95d74eDavid Li   ir_texture *tex = new(ctx) ir_texture(op);
10271591693c7b415e9869157c711fe11263c95d74eDavid Li
10281591693c7b415e9869157c711fe11263c95d74eDavid Li   // Read sampler (must be a deref)
10291591693c7b415e9869157c711fe11263c95d74eDavid Li   s_expression *sampler_expr = (s_expression *) tag->next;
10301591693c7b415e9869157c711fe11263c95d74eDavid Li   ir_dereference *sampler = read_dereference(st, sampler_expr);
10311591693c7b415e9869157c711fe11263c95d74eDavid Li   if (sampler == NULL) {
10321591693c7b415e9869157c711fe11263c95d74eDavid Li      ir_read_error(st, NULL, "when reading sampler in (%s ...)", tag->value());
10331591693c7b415e9869157c711fe11263c95d74eDavid Li      return NULL;
10341591693c7b415e9869157c711fe11263c95d74eDavid Li   }
10351591693c7b415e9869157c711fe11263c95d74eDavid Li   tex->set_sampler(sampler);
10361591693c7b415e9869157c711fe11263c95d74eDavid Li
10371591693c7b415e9869157c711fe11263c95d74eDavid Li   // Read coordinate (any rvalue)
10381591693c7b415e9869157c711fe11263c95d74eDavid Li   s_expression *coordinate_expr = (s_expression *) sampler_expr->next;
10391591693c7b415e9869157c711fe11263c95d74eDavid Li   tex->coordinate = read_rvalue(st, coordinate_expr);
10401591693c7b415e9869157c711fe11263c95d74eDavid Li   if (tex->coordinate == NULL) {
10411591693c7b415e9869157c711fe11263c95d74eDavid Li      ir_read_error(st, NULL, "when reading coordinate in (%s ...)",
10421591693c7b415e9869157c711fe11263c95d74eDavid Li		    tag->value());
10431591693c7b415e9869157c711fe11263c95d74eDavid Li      return NULL;
10441591693c7b415e9869157c711fe11263c95d74eDavid Li   }
10451591693c7b415e9869157c711fe11263c95d74eDavid Li
10461591693c7b415e9869157c711fe11263c95d74eDavid Li   // Read texel offset, i.e. (0 0 0)
10471591693c7b415e9869157c711fe11263c95d74eDavid Li   s_list *offset_list = SX_AS_LIST(coordinate_expr->next);
10481591693c7b415e9869157c711fe11263c95d74eDavid Li   if (offset_list == NULL || offset_list->length() != 3) {
10491591693c7b415e9869157c711fe11263c95d74eDavid Li      ir_read_error(st, offset_list, "expected (<int> <int> <int>)");
10501591693c7b415e9869157c711fe11263c95d74eDavid Li      return NULL;
10511591693c7b415e9869157c711fe11263c95d74eDavid Li   }
10521591693c7b415e9869157c711fe11263c95d74eDavid Li   s_int *offset_x = SX_AS_INT(offset_list->subexpressions.head);
10531591693c7b415e9869157c711fe11263c95d74eDavid Li   s_int *offset_y = SX_AS_INT(offset_list->subexpressions.head->next);
10541591693c7b415e9869157c711fe11263c95d74eDavid Li   s_int *offset_z = SX_AS_INT(offset_list->subexpressions.head->next->next);
10551591693c7b415e9869157c711fe11263c95d74eDavid Li   if (offset_x == NULL || offset_y == NULL || offset_z == NULL) {
10561591693c7b415e9869157c711fe11263c95d74eDavid Li      ir_read_error(st, offset_list, "expected (<int> <int> <int>)");
10571591693c7b415e9869157c711fe11263c95d74eDavid Li      return NULL;
10581591693c7b415e9869157c711fe11263c95d74eDavid Li   }
10591591693c7b415e9869157c711fe11263c95d74eDavid Li   tex->offsets[0] = offset_x->value();
10601591693c7b415e9869157c711fe11263c95d74eDavid Li   tex->offsets[1] = offset_y->value();
10611591693c7b415e9869157c711fe11263c95d74eDavid Li   tex->offsets[2] = offset_z->value();
10621591693c7b415e9869157c711fe11263c95d74eDavid Li
10631591693c7b415e9869157c711fe11263c95d74eDavid Li   if (op == ir_txf) {
10641591693c7b415e9869157c711fe11263c95d74eDavid Li      s_expression *lod_expr = (s_expression *) offset_list->next;
10651591693c7b415e9869157c711fe11263c95d74eDavid Li      tex->lod_info.lod = read_rvalue(st, lod_expr);
10661591693c7b415e9869157c711fe11263c95d74eDavid Li      if (tex->lod_info.lod == NULL) {
10671591693c7b415e9869157c711fe11263c95d74eDavid Li	 ir_read_error(st, NULL, "when reading LOD in (txf ...)");
10681591693c7b415e9869157c711fe11263c95d74eDavid Li	 return NULL;
10691591693c7b415e9869157c711fe11263c95d74eDavid Li      }
10701591693c7b415e9869157c711fe11263c95d74eDavid Li   } else {
10711591693c7b415e9869157c711fe11263c95d74eDavid Li      s_expression *proj_expr = (s_expression *) offset_list->next;
10721591693c7b415e9869157c711fe11263c95d74eDavid Li      s_int *proj_as_int = SX_AS_INT(proj_expr);
10731591693c7b415e9869157c711fe11263c95d74eDavid Li      if (proj_as_int && proj_as_int->value() == 1) {
10741591693c7b415e9869157c711fe11263c95d74eDavid Li	 tex->projector = NULL;
10751591693c7b415e9869157c711fe11263c95d74eDavid Li      } else {
10761591693c7b415e9869157c711fe11263c95d74eDavid Li	 tex->projector = read_rvalue(st, proj_expr);
10771591693c7b415e9869157c711fe11263c95d74eDavid Li	 if (tex->projector == NULL) {
10781591693c7b415e9869157c711fe11263c95d74eDavid Li	    ir_read_error(st, NULL, "when reading projective divide in (%s ..)",
10791591693c7b415e9869157c711fe11263c95d74eDavid Li	                  tag->value());
10801591693c7b415e9869157c711fe11263c95d74eDavid Li	    return NULL;
10811591693c7b415e9869157c711fe11263c95d74eDavid Li	 }
10821591693c7b415e9869157c711fe11263c95d74eDavid Li      }
10831591693c7b415e9869157c711fe11263c95d74eDavid Li
10841591693c7b415e9869157c711fe11263c95d74eDavid Li      s_list *shadow_list = SX_AS_LIST(proj_expr->next);
10851591693c7b415e9869157c711fe11263c95d74eDavid Li      if (shadow_list == NULL) {
10861591693c7b415e9869157c711fe11263c95d74eDavid Li	 ir_read_error(st, NULL, "shadow comparitor must be a list");
10871591693c7b415e9869157c711fe11263c95d74eDavid Li	 return NULL;
10881591693c7b415e9869157c711fe11263c95d74eDavid Li      }
10891591693c7b415e9869157c711fe11263c95d74eDavid Li      if (shadow_list->subexpressions.is_empty()) {
10901591693c7b415e9869157c711fe11263c95d74eDavid Li	 tex->shadow_comparitor= NULL;
10911591693c7b415e9869157c711fe11263c95d74eDavid Li      } else {
10921591693c7b415e9869157c711fe11263c95d74eDavid Li	 tex->shadow_comparitor = read_rvalue(st, shadow_list);
10931591693c7b415e9869157c711fe11263c95d74eDavid Li	 if (tex->shadow_comparitor == NULL) {
10941591693c7b415e9869157c711fe11263c95d74eDavid Li	    ir_read_error(st, NULL, "when reading shadow comparitor in (%s ..)",
10951591693c7b415e9869157c711fe11263c95d74eDavid Li			  tag->value());
10961591693c7b415e9869157c711fe11263c95d74eDavid Li	    return NULL;
10971591693c7b415e9869157c711fe11263c95d74eDavid Li	 }
10981591693c7b415e9869157c711fe11263c95d74eDavid Li      }
10991591693c7b415e9869157c711fe11263c95d74eDavid Li      s_expression *lod_expr = (s_expression *) shadow_list->next;
11001591693c7b415e9869157c711fe11263c95d74eDavid Li
11011591693c7b415e9869157c711fe11263c95d74eDavid Li      switch (op) {
11021591693c7b415e9869157c711fe11263c95d74eDavid Li      case ir_txb:
11031591693c7b415e9869157c711fe11263c95d74eDavid Li	 tex->lod_info.bias = read_rvalue(st, lod_expr);
11041591693c7b415e9869157c711fe11263c95d74eDavid Li	 if (tex->lod_info.bias == NULL) {
11051591693c7b415e9869157c711fe11263c95d74eDavid Li	    ir_read_error(st, NULL, "when reading LOD bias in (txb ...)");
11061591693c7b415e9869157c711fe11263c95d74eDavid Li	    return NULL;
11071591693c7b415e9869157c711fe11263c95d74eDavid Li	 }
11081591693c7b415e9869157c711fe11263c95d74eDavid Li	 break;
11091591693c7b415e9869157c711fe11263c95d74eDavid Li      case ir_txl:
11101591693c7b415e9869157c711fe11263c95d74eDavid Li	 tex->lod_info.lod = read_rvalue(st, lod_expr);
11111591693c7b415e9869157c711fe11263c95d74eDavid Li	 if (tex->lod_info.lod == NULL) {
11121591693c7b415e9869157c711fe11263c95d74eDavid Li	    ir_read_error(st, NULL, "when reading LOD in (txl ...)");
11131591693c7b415e9869157c711fe11263c95d74eDavid Li	    return NULL;
11141591693c7b415e9869157c711fe11263c95d74eDavid Li	 }
11151591693c7b415e9869157c711fe11263c95d74eDavid Li	 break;
11161591693c7b415e9869157c711fe11263c95d74eDavid Li      case ir_txd: {
11171591693c7b415e9869157c711fe11263c95d74eDavid Li	 s_list *lod_list = SX_AS_LIST(lod_expr);
11181591693c7b415e9869157c711fe11263c95d74eDavid Li	 if (lod_list->length() != 2) {
11191591693c7b415e9869157c711fe11263c95d74eDavid Li	    ir_read_error(st, lod_expr, "expected (dPdx dPdy) in (txd ...)");
11201591693c7b415e9869157c711fe11263c95d74eDavid Li	    return NULL;
11211591693c7b415e9869157c711fe11263c95d74eDavid Li	 }
11221591693c7b415e9869157c711fe11263c95d74eDavid Li	 s_expression *dx_expr = (s_expression *) lod_list->subexpressions.head;
11231591693c7b415e9869157c711fe11263c95d74eDavid Li	 s_expression *dy_expr = (s_expression *) dx_expr->next;
11241591693c7b415e9869157c711fe11263c95d74eDavid Li
11251591693c7b415e9869157c711fe11263c95d74eDavid Li	 tex->lod_info.grad.dPdx = read_rvalue(st, dx_expr);
11261591693c7b415e9869157c711fe11263c95d74eDavid Li	 if (tex->lod_info.grad.dPdx == NULL) {
11271591693c7b415e9869157c711fe11263c95d74eDavid Li	    ir_read_error(st, NULL, "when reading dPdx in (txd ...)");
11281591693c7b415e9869157c711fe11263c95d74eDavid Li	    return NULL;
11291591693c7b415e9869157c711fe11263c95d74eDavid Li	 }
11301591693c7b415e9869157c711fe11263c95d74eDavid Li	 tex->lod_info.grad.dPdy = read_rvalue(st, dy_expr);
11311591693c7b415e9869157c711fe11263c95d74eDavid Li	 if (tex->lod_info.grad.dPdy == NULL) {
11321591693c7b415e9869157c711fe11263c95d74eDavid Li	    ir_read_error(st, NULL, "when reading dPdy in (txd ...)");
11331591693c7b415e9869157c711fe11263c95d74eDavid Li	    return NULL;
11341591693c7b415e9869157c711fe11263c95d74eDavid Li	 }
11351591693c7b415e9869157c711fe11263c95d74eDavid Li	 break;
11361591693c7b415e9869157c711fe11263c95d74eDavid Li      }
11371591693c7b415e9869157c711fe11263c95d74eDavid Li      default:
11381591693c7b415e9869157c711fe11263c95d74eDavid Li	 // tex doesn't have any extra parameters and txf was handled earlier.
11391591693c7b415e9869157c711fe11263c95d74eDavid Li	 break;
11401591693c7b415e9869157c711fe11263c95d74eDavid Li      };
11411591693c7b415e9869157c711fe11263c95d74eDavid Li   }
11421591693c7b415e9869157c711fe11263c95d74eDavid Li   return tex;
11431591693c7b415e9869157c711fe11263c95d74eDavid Li}
1144