1f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/*
2f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Copyright © 2010 Intel Corporation
3f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
4f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Permission is hereby granted, free of charge, to any person obtaining a
5f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * copy of this software and associated documentation files (the "Software"),
6f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * to deal in the Software without restriction, including without limitation
7f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * and/or sell copies of the Software, and to permit persons to whom the
9f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Software is furnished to do so, subject to the following conditions:
10f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
11f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * The above copyright notice and this permission notice (including the next
12f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * paragraph) shall be included in all copies or substantial portions of the
13f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Software.
14f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
15f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * DEALINGS IN THE SOFTWARE.
22f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
23f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
24f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "ir_reader.h"
25f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "glsl_parser_extras.h"
26f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "glsl_types.h"
27f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "s_expression.h"
28f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
29f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgconst static bool debug = false;
30f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
31f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgclass ir_reader {
32f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgpublic:
33f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   ir_reader(_mesa_glsl_parse_state *);
34f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
35f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   void read(exec_list *instructions, const char *src, bool scan_for_protos);
36f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
37f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgprivate:
38f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   void *mem_ctx;
39f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   _mesa_glsl_parse_state *state;
40f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
41f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   void ir_read_error(s_expression *, const char *fmt, ...);
42f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
43f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   const glsl_type *read_type(s_expression *);
44f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
45f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   void scan_for_prototypes(exec_list *, s_expression *);
46f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   ir_function *read_function(s_expression *, bool skip_body);
47f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   void read_function_sig(ir_function *, s_expression *, bool skip_body);
48f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
49f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   void read_instructions(exec_list *, s_expression *, ir_loop *);
50f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   ir_instruction *read_instruction(s_expression *, ir_loop *);
51f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   ir_variable *read_declaration(s_expression *);
52f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   ir_if *read_if(s_expression *, ir_loop *);
53f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   ir_loop *read_loop(s_expression *);
54f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   ir_call *read_call(s_expression *);
55f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   ir_return *read_return(s_expression *);
56f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   ir_rvalue *read_rvalue(s_expression *);
57f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   ir_assignment *read_assignment(s_expression *);
58f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   ir_expression *read_expression(s_expression *);
59f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   ir_swizzle *read_swizzle(s_expression *);
60f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   ir_constant *read_constant(s_expression *);
61f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   ir_texture *read_texture(s_expression *);
62f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
63f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   ir_dereference *read_dereference(s_expression *);
64f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   ir_dereference_variable *read_var_ref(s_expression *);
65f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org};
66f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
67f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgir_reader::ir_reader(_mesa_glsl_parse_state *state) : state(state)
68f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
69f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   this->mem_ctx = state;
70f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
71f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
72f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid
73f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org_mesa_glsl_read_ir(_mesa_glsl_parse_state *state, exec_list *instructions,
74f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		   const char *src, bool scan_for_protos)
75f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
76f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   ir_reader r(state);
77f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   r.read(instructions, src, scan_for_protos);
78f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
79f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
80f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid
81f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgir_reader::read(exec_list *instructions, const char *src, bool scan_for_protos)
82f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
83f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   void *sx_mem_ctx = ralloc_context(NULL);
84f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   s_expression *expr = s_expression::read_expression(sx_mem_ctx, src);
85f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (expr == NULL) {
86f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ir_read_error(NULL, "couldn't parse S-Expression.");
87f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return;
88f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
89f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
90f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (scan_for_protos) {
91f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      scan_for_prototypes(instructions, expr);
92f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (state->error)
93f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 return;
94f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
95f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
96f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   read_instructions(instructions, expr, NULL);
97f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   ralloc_free(sx_mem_ctx);
98f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
99f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (debug)
100f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      validate_ir_tree(instructions);
101f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
102f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
103f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid
104f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgir_reader::ir_read_error(s_expression *expr, const char *fmt, ...)
105f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
106f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   va_list ap;
107f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
108f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   state->error = true;
109f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
110f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (state->current_function != NULL)
111f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ralloc_asprintf_append(&state->info_log, "In function %s:\n",
112f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			     state->current_function->function_name());
113f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   ralloc_strcat(&state->info_log, "error: ");
114f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
115f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   va_start(ap, fmt);
116f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   ralloc_vasprintf_append(&state->info_log, fmt, ap);
117f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   va_end(ap);
118f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   ralloc_strcat(&state->info_log, "\n");
119f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
120f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (expr != NULL) {
121f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ralloc_strcat(&state->info_log, "...in this context:\n   ");
122f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      expr->print();
123f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ralloc_strcat(&state->info_log, "\n\n");
124f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
125f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
126f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
127f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgconst glsl_type *
128f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgir_reader::read_type(s_expression *expr)
129f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
130f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   s_expression *s_base_type;
131f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   s_int *s_size;
132f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
133f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   s_pattern pat[] = { "array", s_base_type, s_size };
134f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (MATCH(expr, pat)) {
135f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      const glsl_type *base_type = read_type(s_base_type);
136f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (base_type == NULL) {
137f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 ir_read_error(NULL, "when reading base type of array type");
138f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 return NULL;
139f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
140f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
141f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return glsl_type::get_array_instance(base_type, s_size->value());
142f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
143f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
144f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   s_symbol *type_sym = SX_AS_SYMBOL(expr);
145f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (type_sym == NULL) {
146f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ir_read_error(expr, "expected <type>");
147f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return NULL;
148f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
149f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
150f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   const glsl_type *type = state->symbols->get_type(type_sym->value());
151f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (type == NULL)
152f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ir_read_error(expr, "invalid type: %s", type_sym->value());
153f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
154f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return type;
155f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
156f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
157f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
158f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid
159f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgir_reader::scan_for_prototypes(exec_list *instructions, s_expression *expr)
160f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
161f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   s_list *list = SX_AS_LIST(expr);
162f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (list == NULL) {
163f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ir_read_error(expr, "Expected (<instruction> ...); found an atom.");
164f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return;
165f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
166f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
167f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   foreach_iter(exec_list_iterator, it, list->subexpressions) {
168f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      s_list *sub = SX_AS_LIST(it.get());
169f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (sub == NULL)
170f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 continue; // not a (function ...); ignore it.
171f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
172f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      s_symbol *tag = SX_AS_SYMBOL(sub->subexpressions.get_head());
173f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (tag == NULL || strcmp(tag->value(), "function") != 0)
174f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 continue; // not a (function ...); ignore it.
175f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
176f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ir_function *f = read_function(sub, true);
177f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (f == NULL)
178f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 return;
179f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      instructions->push_tail(f);
180f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
181f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
182f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
183f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgir_function *
184f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgir_reader::read_function(s_expression *expr, bool skip_body)
185f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
186f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   bool added = false;
187f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   s_symbol *name;
188f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
189f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   s_pattern pat[] = { "function", name };
190f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (!PARTIAL_MATCH(expr, pat)) {
191f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ir_read_error(expr, "Expected (function <name> (signature ...) ...)");
192f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return NULL;
193f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
194f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
195f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   ir_function *f = state->symbols->get_function(name->value());
196f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (f == NULL) {
197f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      f = new(mem_ctx) ir_function(name->value());
198f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      added = state->symbols->add_function(f);
199f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      assert(added);
200f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
201f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
202f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   exec_list_iterator it = ((s_list *) expr)->subexpressions.iterator();
203f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   it.next(); // skip "function" tag
204f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   it.next(); // skip function name
205f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   for (/* nothing */; it.has_next(); it.next()) {
206f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      s_expression *s_sig = (s_expression *) it.get();
207f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      read_function_sig(f, s_sig, skip_body);
208f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
209f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return added ? f : NULL;
210f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
211f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
212f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid
213f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgir_reader::read_function_sig(ir_function *f, s_expression *expr, bool skip_body)
214f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
215f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   s_expression *type_expr;
216f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   s_list *paramlist;
217f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   s_list *body_list;
218f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
219f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   s_pattern pat[] = { "signature", type_expr, paramlist, body_list };
220f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (!MATCH(expr, pat)) {
221f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ir_read_error(expr, "Expected (signature <type> (parameters ...) "
222f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			  "(<instruction> ...))");
223f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return;
224f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
225f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
226f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   const glsl_type *return_type = read_type(type_expr);
227f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (return_type == NULL)
228f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return;
229f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
230f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   s_symbol *paramtag = SX_AS_SYMBOL(paramlist->subexpressions.get_head());
231f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (paramtag == NULL || strcmp(paramtag->value(), "parameters") != 0) {
232f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ir_read_error(paramlist, "Expected (parameters ...)");
233f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return;
234f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
235f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
236f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   // Read the parameters list into a temporary place.
237f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   exec_list hir_parameters;
238f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   state->symbols->push_scope();
239f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
240f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   exec_list_iterator it = paramlist->subexpressions.iterator();
241f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   for (it.next() /* skip "parameters" */; it.has_next(); it.next()) {
242f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ir_variable *var = read_declaration((s_expression *) it.get());
243f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (var == NULL)
244f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 return;
245f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
246f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      hir_parameters.push_tail(var);
247f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
248f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
249f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   ir_function_signature *sig = f->exact_matching_signature(&hir_parameters);
250f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (sig == NULL && skip_body) {
251f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      /* If scanning for prototypes, generate a new signature. */
252f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      sig = new(mem_ctx) ir_function_signature(return_type);
253f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      sig->is_builtin = true;
254f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      f->add_signature(sig);
255f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   } else if (sig != NULL) {
256f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      const char *badvar = sig->qualifiers_match(&hir_parameters);
257f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (badvar != NULL) {
258f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 ir_read_error(expr, "function `%s' parameter `%s' qualifiers "
259f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		       "don't match prototype", f->name, badvar);
260f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 return;
261f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
262f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
263f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (sig->return_type != return_type) {
264f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 ir_read_error(expr, "function `%s' return type doesn't "
265f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		       "match prototype", f->name);
266f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 return;
267f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
268f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   } else {
269f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      /* No prototype for this body exists - skip it. */
270f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      state->symbols->pop_scope();
271f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return;
272f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
273f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   assert(sig != NULL);
274f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
275f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   sig->replace_parameters(&hir_parameters);
276f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
277f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (!skip_body && !body_list->subexpressions.is_empty()) {
278f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (sig->is_defined) {
279f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 ir_read_error(expr, "function %s redefined", f->name);
280f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 return;
281f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
282f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      state->current_function = sig;
283f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      read_instructions(&sig->body, body_list, NULL);
284f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      state->current_function = NULL;
285f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      sig->is_defined = true;
286f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
287f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
288f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   state->symbols->pop_scope();
289f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
290f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
291f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid
292f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgir_reader::read_instructions(exec_list *instructions, s_expression *expr,
293f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			     ir_loop *loop_ctx)
294f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
295f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   // Read in a list of instructions
296f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   s_list *list = SX_AS_LIST(expr);
297f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (list == NULL) {
298f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ir_read_error(expr, "Expected (<instruction> ...); found an atom.");
299f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return;
300f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
301f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
302f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   foreach_iter(exec_list_iterator, it, list->subexpressions) {
303f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      s_expression *sub = (s_expression*) it.get();
304f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ir_instruction *ir = read_instruction(sub, loop_ctx);
305f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (ir != NULL) {
306f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 /* Global variable declarations should be moved to the top, before
307f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	  * any functions that might use them.  Functions are added to the
308f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	  * instruction stream when scanning for prototypes, so without this
309f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	  * hack, they always appear before variable declarations.
310f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	  */
311f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 if (state->current_function == NULL && ir->as_variable() != NULL)
312f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    instructions->push_head(ir);
313f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 else
314f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    instructions->push_tail(ir);
315f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
316f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
317f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
318f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
319f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
320f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgir_instruction *
321f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgir_reader::read_instruction(s_expression *expr, ir_loop *loop_ctx)
322f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
323f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   s_symbol *symbol = SX_AS_SYMBOL(expr);
324f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (symbol != NULL) {
325f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (strcmp(symbol->value(), "break") == 0 && loop_ctx != NULL)
326f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 return new(mem_ctx) ir_loop_jump(ir_loop_jump::jump_break);
327f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (strcmp(symbol->value(), "continue") == 0 && loop_ctx != NULL)
328f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 return new(mem_ctx) ir_loop_jump(ir_loop_jump::jump_continue);
329f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
330f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
331f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   s_list *list = SX_AS_LIST(expr);
332f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (list == NULL || list->subexpressions.is_empty()) {
333f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ir_read_error(expr, "Invalid instruction.\n");
334f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return NULL;
335f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
336f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
337f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   s_symbol *tag = SX_AS_SYMBOL(list->subexpressions.get_head());
338f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (tag == NULL) {
339f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ir_read_error(expr, "expected instruction tag");
340f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return NULL;
341f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
342f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
343f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   ir_instruction *inst = NULL;
344f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (strcmp(tag->value(), "declare") == 0) {
345f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      inst = read_declaration(list);
346f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   } else if (strcmp(tag->value(), "assign") == 0) {
347f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      inst = read_assignment(list);
348f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   } else if (strcmp(tag->value(), "if") == 0) {
349f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      inst = read_if(list, loop_ctx);
350f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   } else if (strcmp(tag->value(), "loop") == 0) {
351f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      inst = read_loop(list);
352f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   } else if (strcmp(tag->value(), "call") == 0) {
353f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      inst = read_call(list);
354f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   } else if (strcmp(tag->value(), "return") == 0) {
355f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      inst = read_return(list);
356f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   } else if (strcmp(tag->value(), "function") == 0) {
357f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      inst = read_function(list, false);
358f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   } else {
359f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      inst = read_rvalue(list);
360f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (inst == NULL)
361f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 ir_read_error(NULL, "when reading instruction");
362f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
363f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return inst;
364f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
365f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
366f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgir_variable *
367f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgir_reader::read_declaration(s_expression *expr)
368f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
369f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   s_list *s_quals;
370f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   s_expression *s_type;
371f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   s_symbol *s_name;
372f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
373f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   s_pattern pat[] = { "declare", s_quals, s_type, s_name };
374f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (!MATCH(expr, pat)) {
375f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ir_read_error(expr, "expected (declare (<qualifiers>) <type> <name>)");
376f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return NULL;
377f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
378f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
379f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   const glsl_type *type = read_type(s_type);
380f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (type == NULL)
381f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return NULL;
382f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
383f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   ir_variable *var = new(mem_ctx) ir_variable(type, s_name->value(),
384f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					       ir_var_auto);
385f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
386f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   foreach_iter(exec_list_iterator, it, s_quals->subexpressions) {
387f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      s_symbol *qualifier = SX_AS_SYMBOL(it.get());
388f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (qualifier == NULL) {
389f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 ir_read_error(expr, "qualifier list must contain only symbols");
390f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 return NULL;
391f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
392f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
393f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      // FINISHME: Check for duplicate/conflicting qualifiers.
394f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (strcmp(qualifier->value(), "centroid") == 0) {
395f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 var->centroid = 1;
396f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      } else if (strcmp(qualifier->value(), "invariant") == 0) {
397f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 var->invariant = 1;
398f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      } else if (strcmp(qualifier->value(), "uniform") == 0) {
399f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 var->mode = ir_var_uniform;
400f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      } else if (strcmp(qualifier->value(), "auto") == 0) {
401f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 var->mode = ir_var_auto;
402f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      } else if (strcmp(qualifier->value(), "in") == 0) {
403f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 var->mode = ir_var_in;
404f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      } else if (strcmp(qualifier->value(), "const_in") == 0) {
405f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 var->mode = ir_var_const_in;
406f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      } else if (strcmp(qualifier->value(), "out") == 0) {
407f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 var->mode = ir_var_out;
408f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      } else if (strcmp(qualifier->value(), "inout") == 0) {
409f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 var->mode = ir_var_inout;
410f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      } else if (strcmp(qualifier->value(), "temporary") == 0) {
411f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 var->mode = ir_var_temporary;
412f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      } else if (strcmp(qualifier->value(), "smooth") == 0) {
413f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 var->interpolation = INTERP_QUALIFIER_SMOOTH;
414f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      } else if (strcmp(qualifier->value(), "flat") == 0) {
415f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 var->interpolation = INTERP_QUALIFIER_FLAT;
416f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      } else if (strcmp(qualifier->value(), "noperspective") == 0) {
417f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 var->interpolation = INTERP_QUALIFIER_NOPERSPECTIVE;
418f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      } else {
419f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 ir_read_error(expr, "unknown qualifier: %s", qualifier->value());
420f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 return NULL;
421f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
422f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
423f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
424f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   // Add the variable to the symbol table
425f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   state->symbols->add_variable(var);
426f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
427f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return var;
428f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
429f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
430f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
431f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgir_if *
432f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgir_reader::read_if(s_expression *expr, ir_loop *loop_ctx)
433f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
434f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   s_expression *s_cond;
435f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   s_expression *s_then;
436f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   s_expression *s_else;
437f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
438f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   s_pattern pat[] = { "if", s_cond, s_then, s_else };
439f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (!MATCH(expr, pat)) {
440f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ir_read_error(expr, "expected (if <condition> (<then>...) (<else>...))");
441f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return NULL;
442f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
443f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
444f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   ir_rvalue *condition = read_rvalue(s_cond);
445f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (condition == NULL) {
446f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ir_read_error(NULL, "when reading condition of (if ...)");
447f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return NULL;
448f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
449f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
450f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   ir_if *iff = new(mem_ctx) ir_if(condition);
451f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
452f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   read_instructions(&iff->then_instructions, s_then, loop_ctx);
453f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   read_instructions(&iff->else_instructions, s_else, loop_ctx);
454f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (state->error) {
455f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      delete iff;
456f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      iff = NULL;
457f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
458f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return iff;
459f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
460f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
461f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
462f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgir_loop *
463f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgir_reader::read_loop(s_expression *expr)
464f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
465f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   s_expression *s_counter, *s_from, *s_to, *s_inc, *s_body;
466f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
467f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   s_pattern pat[] = { "loop", s_counter, s_from, s_to, s_inc, s_body };
468f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (!MATCH(expr, pat)) {
469f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ir_read_error(expr, "expected (loop <counter> <from> <to> "
470f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			  "<increment> <body>)");
471f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return NULL;
472f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
473f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
474f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   // FINISHME: actually read the count/from/to fields.
475f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
476f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   ir_loop *loop = new(mem_ctx) ir_loop;
477f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   read_instructions(&loop->body_instructions, s_body, loop);
478f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (state->error) {
479f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      delete loop;
480f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      loop = NULL;
481f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
482f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return loop;
483f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
484f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
485f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
486f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgir_return *
487f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgir_reader::read_return(s_expression *expr)
488f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
489f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   s_expression *s_retval;
490f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
491f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   s_pattern return_value_pat[] = { "return", s_retval};
492f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   s_pattern return_void_pat[] = { "return" };
493f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (MATCH(expr, return_value_pat)) {
494f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ir_rvalue *retval = read_rvalue(s_retval);
495f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (retval == NULL) {
496f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         ir_read_error(NULL, "when reading return value");
497f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         return NULL;
498f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
499f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return new(mem_ctx) ir_return(retval);
500f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   } else if (MATCH(expr, return_void_pat)) {
501f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return new(mem_ctx) ir_return;
502f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   } else {
503f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ir_read_error(expr, "expected (return <rvalue>) or (return)");
504f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return NULL;
505f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
506f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
507f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
508f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
509f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgir_rvalue *
510f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgir_reader::read_rvalue(s_expression *expr)
511f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
512f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   s_list *list = SX_AS_LIST(expr);
513f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (list == NULL || list->subexpressions.is_empty())
514f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return NULL;
515f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
516f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   s_symbol *tag = SX_AS_SYMBOL(list->subexpressions.get_head());
517f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (tag == NULL) {
518f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ir_read_error(expr, "expected rvalue tag");
519f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return NULL;
520f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
521f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
522f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   ir_rvalue *rvalue = read_dereference(list);
523f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (rvalue != NULL || state->error)
524f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return rvalue;
525f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   else if (strcmp(tag->value(), "swiz") == 0) {
526f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      rvalue = read_swizzle(list);
527f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   } else if (strcmp(tag->value(), "expression") == 0) {
528f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      rvalue = read_expression(list);
529f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   } else if (strcmp(tag->value(), "constant") == 0) {
530f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      rvalue = read_constant(list);
531f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   } else {
532f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      rvalue = read_texture(list);
533f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (rvalue == NULL && !state->error)
534f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 ir_read_error(expr, "unrecognized rvalue tag: %s", tag->value());
535f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
536f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
537f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return rvalue;
538f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
539f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
540f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgir_assignment *
541f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgir_reader::read_assignment(s_expression *expr)
542f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
543f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   s_expression *cond_expr = NULL;
544f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   s_expression *lhs_expr, *rhs_expr;
545f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   s_list       *mask_list;
546f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
547f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   s_pattern pat4[] = { "assign",            mask_list, lhs_expr, rhs_expr };
548f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   s_pattern pat5[] = { "assign", cond_expr, mask_list, lhs_expr, rhs_expr };
549f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (!MATCH(expr, pat4) && !MATCH(expr, pat5)) {
550f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ir_read_error(expr, "expected (assign [<condition>] (<write mask>) "
551f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			  "<lhs> <rhs>)");
552f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return NULL;
553f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
554f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
555f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   ir_rvalue *condition = NULL;
556f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (cond_expr != NULL) {
557f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      condition = read_rvalue(cond_expr);
558f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (condition == NULL) {
559f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 ir_read_error(NULL, "when reading condition of assignment");
560f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 return NULL;
561f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
562f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
563f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
564f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   unsigned mask = 0;
565f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
566f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   s_symbol *mask_symbol;
567f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   s_pattern mask_pat[] = { mask_symbol };
568f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (MATCH(mask_list, mask_pat)) {
569f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      const char *mask_str = mask_symbol->value();
570f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      unsigned mask_length = strlen(mask_str);
571f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (mask_length > 4) {
572f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 ir_read_error(expr, "invalid write mask: %s", mask_str);
573f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 return NULL;
574f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
575f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
576f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      const unsigned idx_map[] = { 3, 0, 1, 2 }; /* w=bit 3, x=0, y=1, z=2 */
577f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
578f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      for (unsigned i = 0; i < mask_length; i++) {
579f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 if (mask_str[i] < 'w' || mask_str[i] > 'z') {
580f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    ir_read_error(expr, "write mask contains invalid character: %c",
581f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			  mask_str[i]);
582f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    return NULL;
583f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 }
584f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 mask |= 1 << idx_map[mask_str[i] - 'w'];
585f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
586f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   } else if (!mask_list->subexpressions.is_empty()) {
587f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ir_read_error(mask_list, "expected () or (<write mask>)");
588f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return NULL;
589f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
590f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
591f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   ir_dereference *lhs = read_dereference(lhs_expr);
592f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (lhs == NULL) {
593f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ir_read_error(NULL, "when reading left-hand side of assignment");
594f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return NULL;
595f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
596f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
597f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   ir_rvalue *rhs = read_rvalue(rhs_expr);
598f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (rhs == NULL) {
599f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ir_read_error(NULL, "when reading right-hand side of assignment");
600f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return NULL;
601f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
602f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
603f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (mask == 0 && (lhs->type->is_vector() || lhs->type->is_scalar())) {
604f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ir_read_error(expr, "non-zero write mask required.");
605f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return NULL;
606f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
607f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
608f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return new(mem_ctx) ir_assignment(lhs, rhs, condition, mask);
609f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
610f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
611f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgir_call *
612f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgir_reader::read_call(s_expression *expr)
613f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
614f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   s_symbol *name;
615f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   s_list *params;
616f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   s_list *s_return = NULL;
617f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
618f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   ir_dereference_variable *return_deref = NULL;
619f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
620f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   s_pattern void_pat[] = { "call", name, params };
621f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   s_pattern non_void_pat[] = { "call", name, s_return, params };
622f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (MATCH(expr, non_void_pat)) {
623f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return_deref = read_var_ref(s_return);
624f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (return_deref == NULL) {
625f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 ir_read_error(s_return, "when reading a call's return storage");
626f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 return NULL;
627f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
628f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   } else if (!MATCH(expr, void_pat)) {
629f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ir_read_error(expr, "expected (call <name> [<deref>] (<param> ...))");
630f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return NULL;
631f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
632f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
633f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   exec_list parameters;
634f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
635f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   foreach_iter(exec_list_iterator, it, params->subexpressions) {
636f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      s_expression *expr = (s_expression*) it.get();
637f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ir_rvalue *param = read_rvalue(expr);
638f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (param == NULL) {
639f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 ir_read_error(expr, "when reading parameter to function call");
640f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 return NULL;
641f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
642f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      parameters.push_tail(param);
643f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
644f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
645f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   ir_function *f = state->symbols->get_function(name->value());
646f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (f == NULL) {
647f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ir_read_error(expr, "found call to undefined function %s",
648f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		    name->value());
649f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return NULL;
650f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
651f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
652f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   ir_function_signature *callee = f->matching_signature(&parameters);
653f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (callee == NULL) {
654f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ir_read_error(expr, "couldn't find matching signature for function "
655f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                    "%s", name->value());
656f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return NULL;
657f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
658f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
659f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (callee->return_type == glsl_type::void_type && return_deref) {
660f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ir_read_error(expr, "call has return value storage but void type");
661f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return NULL;
662f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   } else if (callee->return_type != glsl_type::void_type && !return_deref) {
663f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ir_read_error(expr, "call has non-void type but no return value storage");
664f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return NULL;
665f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
666f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
667f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return new(mem_ctx) ir_call(callee, return_deref, &parameters);
668f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
669f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
670f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgir_expression *
671f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgir_reader::read_expression(s_expression *expr)
672f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
673f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   s_expression *s_type;
674f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   s_symbol *s_op;
675f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   s_expression *s_arg1;
676f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
677f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   s_pattern pat[] = { "expression", s_type, s_op, s_arg1 };
678f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (!PARTIAL_MATCH(expr, pat)) {
679f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ir_read_error(expr, "expected (expression <type> <operator> "
680f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			  "<operand> [<operand>])");
681f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return NULL;
682f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
683f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   s_expression *s_arg2 = (s_expression *) s_arg1->next; // may be tail sentinel
684f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
685f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   const glsl_type *type = read_type(s_type);
686f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (type == NULL)
687f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return NULL;
688f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
689f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /* Read the operator */
690f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   ir_expression_operation op = ir_expression::get_operator(s_op->value());
691f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (op == (ir_expression_operation) -1) {
692f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ir_read_error(expr, "invalid operator: %s", s_op->value());
693f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return NULL;
694f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
695f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
696f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   unsigned num_operands = ir_expression::get_num_operands(op);
697f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (num_operands == 1 && !s_arg1->next->is_tail_sentinel()) {
698f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ir_read_error(expr, "expected (expression <type> %s <operand>)",
699f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		    s_op->value());
700f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return NULL;
701f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
702f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
703f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   ir_rvalue *arg1 = read_rvalue(s_arg1);
704f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   ir_rvalue *arg2 = NULL;
705f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (arg1 == NULL) {
706f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ir_read_error(NULL, "when reading first operand of %s", s_op->value());
707f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return NULL;
708f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
709f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
710f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (num_operands == 2) {
711f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (s_arg2->is_tail_sentinel() || !s_arg2->next->is_tail_sentinel()) {
712f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 ir_read_error(expr, "expected (expression <type> %s <operand> "
713f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			     "<operand>)", s_op->value());
714f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 return NULL;
715f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
716f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      arg2 = read_rvalue(s_arg2);
717f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (arg2 == NULL) {
718f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 ir_read_error(NULL, "when reading second operand of %s",
719f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		       s_op->value());
720f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 return NULL;
721f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
722f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
723f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
724f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return new(mem_ctx) ir_expression(op, type, arg1, arg2);
725f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
726f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
727f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgir_swizzle *
728f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgir_reader::read_swizzle(s_expression *expr)
729f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
730f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   s_symbol *swiz;
731f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   s_expression *sub;
732f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
733f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   s_pattern pat[] = { "swiz", swiz, sub };
734f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (!MATCH(expr, pat)) {
735f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ir_read_error(expr, "expected (swiz <swizzle> <rvalue>)");
736f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return NULL;
737f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
738f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
739f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (strlen(swiz->value()) > 4) {
740f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ir_read_error(expr, "expected a valid swizzle; found %s", swiz->value());
741f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return NULL;
742f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
743f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
744f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   ir_rvalue *rvalue = read_rvalue(sub);
745f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (rvalue == NULL)
746f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return NULL;
747f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
748f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   ir_swizzle *ir = ir_swizzle::create(rvalue, swiz->value(),
749f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				       rvalue->type->vector_elements);
750f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (ir == NULL)
751f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ir_read_error(expr, "invalid swizzle");
752f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
753f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return ir;
754f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
755f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
756f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgir_constant *
757f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgir_reader::read_constant(s_expression *expr)
758f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
759f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   s_expression *type_expr;
760f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   s_list *values;
761f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
762f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   s_pattern pat[] = { "constant", type_expr, values };
763f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (!MATCH(expr, pat)) {
764f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ir_read_error(expr, "expected (constant <type> (...))");
765f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return NULL;
766f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
767f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
768f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   const glsl_type *type = read_type(type_expr);
769f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (type == NULL)
770f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return NULL;
771f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
772f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (values == NULL) {
773f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ir_read_error(expr, "expected (constant <type> (...))");
774f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return NULL;
775f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
776f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
777f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (type->is_array()) {
778f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      unsigned elements_supplied = 0;
779f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      exec_list elements;
780f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      foreach_iter(exec_list_iterator, it, values->subexpressions) {
781f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 s_expression *elt = (s_expression *) it.get();
782f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 ir_constant *ir_elt = read_constant(elt);
783f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 if (ir_elt == NULL)
784f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    return NULL;
785f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 elements.push_tail(ir_elt);
786f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 elements_supplied++;
787f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
788f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
789f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (elements_supplied != type->length) {
790f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 ir_read_error(values, "expected exactly %u array elements, "
791f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		       "given %u", type->length, elements_supplied);
792f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 return NULL;
793f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
794f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return new(mem_ctx) ir_constant(type, &elements);
795f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
796f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
797f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   ir_constant_data data = { { 0 } };
798f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
799f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   // Read in list of values (at most 16).
800f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   unsigned k = 0;
801f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   foreach_iter(exec_list_iterator, it, values->subexpressions) {
802f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (k >= 16) {
803f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 ir_read_error(values, "expected at most 16 numbers");
804f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 return NULL;
805f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
806f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
807f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      s_expression *expr = (s_expression*) it.get();
808f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
809f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (type->base_type == GLSL_TYPE_FLOAT) {
810f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 s_number *value = SX_AS_NUMBER(expr);
811f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 if (value == NULL) {
812f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    ir_read_error(values, "expected numbers");
813f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    return NULL;
814f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 }
815f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 data.f[k] = value->fvalue();
816f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      } else {
817f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 s_int *value = SX_AS_INT(expr);
818f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 if (value == NULL) {
819f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    ir_read_error(values, "expected integers");
820f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    return NULL;
821f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 }
822f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
823f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 switch (type->base_type) {
824f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 case GLSL_TYPE_UINT: {
825f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    data.u[k] = value->value();
826f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    break;
827f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 }
828f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 case GLSL_TYPE_INT: {
829f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    data.i[k] = value->value();
830f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    break;
831f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 }
832f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 case GLSL_TYPE_BOOL: {
833f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    data.b[k] = value->value();
834f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    break;
835f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 }
836f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 default:
837f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    ir_read_error(values, "unsupported constant type");
838f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    return NULL;
839f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 }
840f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
841f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ++k;
842f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
843f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (k != type->components()) {
844f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ir_read_error(values, "expected %u constant values, found %u",
845f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		    type->components(), k);
846f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return NULL;
847f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
848f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
849f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return new(mem_ctx) ir_constant(type, &data);
850f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
851f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
852f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgir_dereference_variable *
853f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgir_reader::read_var_ref(s_expression *expr)
854f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
855f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   s_symbol *s_var;
856f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   s_pattern var_pat[] = { "var_ref", s_var };
857f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
858f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (MATCH(expr, var_pat)) {
859f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ir_variable *var = state->symbols->get_variable(s_var->value());
860f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (var == NULL) {
861f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 ir_read_error(expr, "undeclared variable: %s", s_var->value());
862f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 return NULL;
863f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
864f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return new(mem_ctx) ir_dereference_variable(var);
865f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
866f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return NULL;
867f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
868f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
869f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgir_dereference *
870f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgir_reader::read_dereference(s_expression *expr)
871f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
872f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   s_expression *s_subject;
873f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   s_expression *s_index;
874f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   s_symbol *s_field;
875f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
876f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   s_pattern array_pat[] = { "array_ref", s_subject, s_index };
877f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   s_pattern record_pat[] = { "record_ref", s_subject, s_field };
878f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
879f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   ir_dereference_variable *var_ref = read_var_ref(expr);
880f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (var_ref != NULL) {
881f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return var_ref;
882f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   } else if (MATCH(expr, array_pat)) {
883f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ir_rvalue *subject = read_rvalue(s_subject);
884f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (subject == NULL) {
885f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 ir_read_error(NULL, "when reading the subject of an array_ref");
886f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 return NULL;
887f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
888f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
889f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ir_rvalue *idx = read_rvalue(s_index);
890f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (subject == NULL) {
891f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 ir_read_error(NULL, "when reading the index of an array_ref");
892f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 return NULL;
893f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
894f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return new(mem_ctx) ir_dereference_array(subject, idx);
895f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   } else if (MATCH(expr, record_pat)) {
896f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ir_rvalue *subject = read_rvalue(s_subject);
897f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (subject == NULL) {
898f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 ir_read_error(NULL, "when reading the subject of a record_ref");
899f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 return NULL;
900f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
901f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return new(mem_ctx) ir_dereference_record(subject, s_field->value());
902f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
903f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return NULL;
904f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
905f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
906f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgir_texture *
907f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgir_reader::read_texture(s_expression *expr)
908f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
909f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   s_symbol *tag = NULL;
910f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   s_expression *s_type = NULL;
911f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   s_expression *s_sampler = NULL;
912f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   s_expression *s_coord = NULL;
913f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   s_expression *s_offset = NULL;
914f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   s_expression *s_proj = NULL;
915f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   s_list *s_shadow = NULL;
916f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   s_expression *s_lod = NULL;
917f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
918f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   ir_texture_opcode op = ir_tex; /* silence warning */
919f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
920f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   s_pattern tex_pattern[] =
921f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      { "tex", s_type, s_sampler, s_coord, s_offset, s_proj, s_shadow };
922f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   s_pattern txf_pattern[] =
923f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      { "txf", s_type, s_sampler, s_coord, s_offset, s_lod };
924f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   s_pattern txs_pattern[] =
925f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      { "txs", s_type, s_sampler, s_lod };
926f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   s_pattern other_pattern[] =
927f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      { tag, s_type, s_sampler, s_coord, s_offset, s_proj, s_shadow, s_lod };
928f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
929f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (MATCH(expr, tex_pattern)) {
930f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      op = ir_tex;
931f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   } else if (MATCH(expr, txf_pattern)) {
932f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      op = ir_txf;
933f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   } else if (MATCH(expr, txs_pattern)) {
934f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      op = ir_txs;
935f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   } else if (MATCH(expr, other_pattern)) {
936f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      op = ir_texture::get_opcode(tag->value());
937f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (op == -1)
938f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 return NULL;
939f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   } else {
940f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ir_read_error(NULL, "unexpected texture pattern");
941f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return NULL;
942f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
943f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
944f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   ir_texture *tex = new(mem_ctx) ir_texture(op);
945f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
946f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   // Read return type
947f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   const glsl_type *type = read_type(s_type);
948f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (type == NULL) {
949f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ir_read_error(NULL, "when reading type in (%s ...)",
950f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		    tex->opcode_string());
951f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return NULL;
952f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
953f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
954f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   // Read sampler (must be a deref)
955f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   ir_dereference *sampler = read_dereference(s_sampler);
956f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (sampler == NULL) {
957f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ir_read_error(NULL, "when reading sampler in (%s ...)",
958f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		    tex->opcode_string());
959f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return NULL;
960f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
961f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   tex->set_sampler(sampler, type);
962f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
963f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (op != ir_txs) {
964f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      // Read coordinate (any rvalue)
965f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      tex->coordinate = read_rvalue(s_coord);
966f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (tex->coordinate == NULL) {
967f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 ir_read_error(NULL, "when reading coordinate in (%s ...)",
968f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		       tex->opcode_string());
969f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 return NULL;
970f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
971f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
972f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      // Read texel offset - either 0 or an rvalue.
973f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      s_int *si_offset = SX_AS_INT(s_offset);
974f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (si_offset == NULL || si_offset->value() != 0) {
975f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 tex->offset = read_rvalue(s_offset);
976f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 if (tex->offset == NULL) {
977f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    ir_read_error(s_offset, "expected 0 or an expression");
978f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    return NULL;
979f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 }
980f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
981f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
982f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
983f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (op != ir_txf && op != ir_txs) {
984f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      s_int *proj_as_int = SX_AS_INT(s_proj);
985f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (proj_as_int && proj_as_int->value() == 1) {
986f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 tex->projector = NULL;
987f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      } else {
988f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 tex->projector = read_rvalue(s_proj);
989f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 if (tex->projector == NULL) {
990f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    ir_read_error(NULL, "when reading projective divide in (%s ..)",
991f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	                  tex->opcode_string());
992f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    return NULL;
993f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 }
994f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
995f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
996f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (s_shadow->subexpressions.is_empty()) {
997f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 tex->shadow_comparitor = NULL;
998f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      } else {
999f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 tex->shadow_comparitor = read_rvalue(s_shadow);
1000f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 if (tex->shadow_comparitor == NULL) {
1001f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    ir_read_error(NULL, "when reading shadow comparitor in (%s ..)",
1002f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			  tex->opcode_string());
1003f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    return NULL;
1004f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 }
1005f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
1006f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
1007f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1008f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   switch (op) {
1009f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case ir_txb:
1010f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      tex->lod_info.bias = read_rvalue(s_lod);
1011f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (tex->lod_info.bias == NULL) {
1012f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 ir_read_error(NULL, "when reading LOD bias in (txb ...)");
1013f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 return NULL;
1014f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
1015f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
1016f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case ir_txl:
1017f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case ir_txf:
1018f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case ir_txs:
1019f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      tex->lod_info.lod = read_rvalue(s_lod);
1020f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (tex->lod_info.lod == NULL) {
1021f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 ir_read_error(NULL, "when reading LOD in (%s ...)",
1022f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		       tex->opcode_string());
1023f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 return NULL;
1024f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
1025f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
1026f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case ir_txd: {
1027f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      s_expression *s_dx, *s_dy;
1028f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      s_pattern dxdy_pat[] = { s_dx, s_dy };
1029f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (!MATCH(s_lod, dxdy_pat)) {
1030f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 ir_read_error(s_lod, "expected (dPdx dPdy) in (txd ...)");
1031f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 return NULL;
1032f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
1033f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      tex->lod_info.grad.dPdx = read_rvalue(s_dx);
1034f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (tex->lod_info.grad.dPdx == NULL) {
1035f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 ir_read_error(NULL, "when reading dPdx in (txd ...)");
1036f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 return NULL;
1037f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
1038f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      tex->lod_info.grad.dPdy = read_rvalue(s_dy);
1039f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (tex->lod_info.grad.dPdy == NULL) {
1040f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 ir_read_error(NULL, "when reading dPdy in (txd ...)");
1041f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 return NULL;
1042f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
1043f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
1044f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
1045f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   default:
1046f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      // tex doesn't have any extra parameters.
1047f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
1048f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   };
1049f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return tex;
1050f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
1051