2010-04-07 14:38:03 -07:00
|
|
|
/*
|
|
|
|
|
* Copyright © 2010 Intel Corporation
|
|
|
|
|
*
|
|
|
|
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
|
|
|
* copy of this software and associated documentation files (the "Software"),
|
|
|
|
|
* to deal in the Software without restriction, including without limitation
|
|
|
|
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
|
|
|
* and/or sell copies of the Software, and to permit persons to whom the
|
|
|
|
|
* Software is furnished to do so, subject to the following conditions:
|
|
|
|
|
*
|
|
|
|
|
* The above copyright notice and this permission notice (including the next
|
|
|
|
|
* paragraph) shall be included in all copies or substantial portions of the
|
|
|
|
|
* Software.
|
|
|
|
|
*
|
|
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
|
|
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
|
|
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
|
|
|
* DEALINGS IN THE SOFTWARE.
|
|
|
|
|
*/
|
2010-06-22 10:38:52 -07:00
|
|
|
|
2010-06-17 15:15:35 -07:00
|
|
|
extern "C" {
|
|
|
|
|
#include <talloc.h>
|
|
|
|
|
}
|
|
|
|
|
|
2010-04-07 14:38:03 -07:00
|
|
|
#include "ir_reader.h"
|
|
|
|
|
#include "glsl_parser_extras.h"
|
|
|
|
|
#include "glsl_types.h"
|
|
|
|
|
#include "s_expression.h"
|
|
|
|
|
|
2010-09-05 00:58:34 -07:00
|
|
|
const static bool debug = false;
|
|
|
|
|
|
2010-04-21 15:47:34 -07:00
|
|
|
static void ir_read_error(_mesa_glsl_parse_state *, s_expression *,
|
|
|
|
|
const char *fmt, ...);
|
2010-04-10 01:06:44 -07:00
|
|
|
static const glsl_type *read_type(_mesa_glsl_parse_state *, s_expression *);
|
2010-04-09 17:40:51 -07:00
|
|
|
|
2010-04-21 17:52:36 -07:00
|
|
|
static void scan_for_prototypes(_mesa_glsl_parse_state *, exec_list *,
|
|
|
|
|
s_expression *);
|
2010-12-31 02:03:21 -08:00
|
|
|
static ir_function *read_function(_mesa_glsl_parse_state *, s_expression *,
|
2010-04-21 18:14:06 -07:00
|
|
|
bool skip_body);
|
2010-04-28 12:45:18 -07:00
|
|
|
static void read_function_sig(_mesa_glsl_parse_state *, ir_function *,
|
ir_reader: Add a pattern matching system and use it everywhere.
Previously, the IR reader was riddled with code that:
1. Checked for the right number of list elements (via a linked list walk)
2. Retrieved references to each component (via ->next->next pointers)
3. Downcasted as necessary to make sure that each sub-component was the
right type (i.e. symbol, int, list).
4. Checking that the tag (i.e. "declare") was correct.
This was all very ad-hoc and a bit ugly. Error checking had to be done
at both steps 1, 3, and 4. Most code didn't even check the tag, relying
on the caller to do so. Not all callers did.
The new pattern matching module performs the whole process in a single
straightforward function call, resulting in shorter, more readable code.
Unfortunately, MSVC does not support C99-style anonymous arrays, so the
pattern must be declared outside of the match call.
2010-11-03 12:47:06 -07:00
|
|
|
s_expression *, bool skip_body);
|
2010-04-21 17:52:36 -07:00
|
|
|
|
2010-04-10 01:45:08 -07:00
|
|
|
static void read_instructions(_mesa_glsl_parse_state *, exec_list *,
|
2010-04-12 16:02:48 -07:00
|
|
|
s_expression *, ir_loop *);
|
2010-04-09 17:40:51 -07:00
|
|
|
static ir_instruction *read_instruction(_mesa_glsl_parse_state *,
|
2010-04-12 16:02:48 -07:00
|
|
|
s_expression *, ir_loop *);
|
2010-12-31 02:03:21 -08:00
|
|
|
static ir_variable *read_declaration(_mesa_glsl_parse_state *, s_expression *);
|
|
|
|
|
static ir_if *read_if(_mesa_glsl_parse_state *, s_expression *, ir_loop *);
|
|
|
|
|
static ir_loop *read_loop(_mesa_glsl_parse_state *st, s_expression *);
|
|
|
|
|
static ir_return *read_return(_mesa_glsl_parse_state *, s_expression *);
|
2010-04-09 17:40:51 -07:00
|
|
|
|
2010-04-07 17:24:44 -07:00
|
|
|
static ir_rvalue *read_rvalue(_mesa_glsl_parse_state *, s_expression *);
|
2010-12-31 02:03:21 -08:00
|
|
|
static ir_assignment *read_assignment(_mesa_glsl_parse_state *, s_expression *);
|
|
|
|
|
static ir_expression *read_expression(_mesa_glsl_parse_state *, s_expression *);
|
|
|
|
|
static ir_call *read_call(_mesa_glsl_parse_state *, s_expression *);
|
|
|
|
|
static ir_swizzle *read_swizzle(_mesa_glsl_parse_state *, s_expression *);
|
|
|
|
|
static ir_constant *read_constant(_mesa_glsl_parse_state *, s_expression *);
|
|
|
|
|
static ir_texture *read_texture(_mesa_glsl_parse_state *, s_expression *);
|
2010-05-26 17:52:44 -07:00
|
|
|
|
|
|
|
|
static ir_dereference *read_dereference(_mesa_glsl_parse_state *,
|
|
|
|
|
s_expression *);
|
2010-10-30 22:29:07 -07:00
|
|
|
static ir_dereference_variable *
|
2010-12-31 02:03:21 -08:00
|
|
|
read_var_ref(_mesa_glsl_parse_state *, s_expression *);
|
2010-10-30 22:29:07 -07:00
|
|
|
static ir_dereference_array *
|
2010-12-31 02:03:21 -08:00
|
|
|
read_array_ref(_mesa_glsl_parse_state *, s_expression *);
|
2010-10-30 22:29:07 -07:00
|
|
|
static ir_dereference_record *
|
2010-12-31 02:03:21 -08:00
|
|
|
read_record_ref(_mesa_glsl_parse_state *, s_expression *);
|
2010-04-07 17:24:44 -07:00
|
|
|
|
2010-04-07 14:38:03 -07:00
|
|
|
void
|
|
|
|
|
_mesa_glsl_read_ir(_mesa_glsl_parse_state *state, exec_list *instructions,
|
2010-08-11 16:53:52 -07:00
|
|
|
const char *src, bool scan_for_protos)
|
2010-04-07 14:38:03 -07:00
|
|
|
{
|
2010-06-25 13:10:37 -07:00
|
|
|
s_expression *expr = s_expression::read_expression(state, src);
|
2010-04-07 14:38:03 -07:00
|
|
|
if (expr == NULL) {
|
2010-04-21 15:47:34 -07:00
|
|
|
ir_read_error(state, NULL, "couldn't parse S-Expression.");
|
2010-04-07 14:38:03 -07:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2010-08-11 16:53:52 -07:00
|
|
|
if (scan_for_protos) {
|
|
|
|
|
scan_for_prototypes(state, instructions, expr);
|
|
|
|
|
if (state->error)
|
|
|
|
|
return;
|
|
|
|
|
}
|
2010-04-21 17:52:36 -07:00
|
|
|
|
2010-04-12 16:02:48 -07:00
|
|
|
read_instructions(state, instructions, expr, NULL);
|
2010-06-25 13:10:37 -07:00
|
|
|
talloc_free(expr);
|
2010-09-04 01:09:43 -07:00
|
|
|
|
2010-09-05 00:58:34 -07:00
|
|
|
if (debug)
|
|
|
|
|
validate_ir_tree(instructions);
|
2010-04-07 14:38:03 -07:00
|
|
|
}
|
|
|
|
|
|
2010-04-07 17:24:44 -07:00
|
|
|
static void
|
2010-04-21 15:47:34 -07:00
|
|
|
ir_read_error(_mesa_glsl_parse_state *state, s_expression *expr,
|
|
|
|
|
const char *fmt, ...)
|
2010-04-07 17:24:44 -07:00
|
|
|
{
|
|
|
|
|
va_list ap;
|
|
|
|
|
|
2010-04-21 15:47:34 -07:00
|
|
|
state->error = true;
|
2010-04-07 17:24:44 -07:00
|
|
|
|
2010-09-04 01:05:51 -07:00
|
|
|
if (state->current_function != NULL)
|
|
|
|
|
state->info_log = talloc_asprintf_append(state->info_log,
|
|
|
|
|
"In function %s:\n",
|
|
|
|
|
state->current_function->function_name());
|
2010-06-17 15:15:35 -07:00
|
|
|
state->info_log = talloc_strdup_append(state->info_log, "error: ");
|
2010-04-07 17:24:44 -07:00
|
|
|
|
|
|
|
|
va_start(ap, fmt);
|
2010-06-17 15:15:35 -07:00
|
|
|
state->info_log = talloc_vasprintf_append(state->info_log, fmt, ap);
|
2010-04-07 17:24:44 -07:00
|
|
|
va_end(ap);
|
2010-06-17 15:15:35 -07:00
|
|
|
state->info_log = talloc_strdup_append(state->info_log, "\n");
|
2010-04-07 17:24:44 -07:00
|
|
|
|
2010-04-21 23:23:23 -07:00
|
|
|
if (expr != NULL) {
|
2010-06-17 15:15:35 -07:00
|
|
|
state->info_log = talloc_strdup_append(state->info_log,
|
|
|
|
|
"...in this context:\n ");
|
2010-04-21 23:23:23 -07:00
|
|
|
expr->print();
|
2010-06-17 15:15:35 -07:00
|
|
|
state->info_log = talloc_strdup_append(state->info_log, "\n\n");
|
2010-04-21 23:23:23 -07:00
|
|
|
}
|
2010-04-07 17:24:44 -07:00
|
|
|
}
|
|
|
|
|
|
2010-04-10 01:06:44 -07:00
|
|
|
static const glsl_type *
|
2010-04-07 17:24:44 -07:00
|
|
|
read_type(_mesa_glsl_parse_state *st, s_expression *expr)
|
|
|
|
|
{
|
ir_reader: Add a pattern matching system and use it everywhere.
Previously, the IR reader was riddled with code that:
1. Checked for the right number of list elements (via a linked list walk)
2. Retrieved references to each component (via ->next->next pointers)
3. Downcasted as necessary to make sure that each sub-component was the
right type (i.e. symbol, int, list).
4. Checking that the tag (i.e. "declare") was correct.
This was all very ad-hoc and a bit ugly. Error checking had to be done
at both steps 1, 3, and 4. Most code didn't even check the tag, relying
on the caller to do so. Not all callers did.
The new pattern matching module performs the whole process in a single
straightforward function call, resulting in shorter, more readable code.
Unfortunately, MSVC does not support C99-style anonymous arrays, so the
pattern must be declared outside of the match call.
2010-11-03 12:47:06 -07:00
|
|
|
s_expression *s_base_type;
|
|
|
|
|
s_int *s_size;
|
|
|
|
|
|
|
|
|
|
s_pattern pat[] = { "array", s_base_type, s_size };
|
|
|
|
|
if (MATCH(expr, pat)) {
|
|
|
|
|
const glsl_type *base_type = read_type(st, s_base_type);
|
|
|
|
|
if (base_type == NULL) {
|
|
|
|
|
ir_read_error(st, NULL, "when reading base type of array type");
|
2010-04-07 17:24:44 -07:00
|
|
|
return NULL;
|
|
|
|
|
}
|
2010-04-10 01:06:44 -07:00
|
|
|
|
ir_reader: Add a pattern matching system and use it everywhere.
Previously, the IR reader was riddled with code that:
1. Checked for the right number of list elements (via a linked list walk)
2. Retrieved references to each component (via ->next->next pointers)
3. Downcasted as necessary to make sure that each sub-component was the
right type (i.e. symbol, int, list).
4. Checking that the tag (i.e. "declare") was correct.
This was all very ad-hoc and a bit ugly. Error checking had to be done
at both steps 1, 3, and 4. Most code didn't even check the tag, relying
on the caller to do so. Not all callers did.
The new pattern matching module performs the whole process in a single
straightforward function call, resulting in shorter, more readable code.
Unfortunately, MSVC does not support C99-style anonymous arrays, so the
pattern must be declared outside of the match call.
2010-11-03 12:47:06 -07:00
|
|
|
return glsl_type::get_array_instance(base_type, s_size->value());
|
2010-04-07 17:24:44 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s_symbol *type_sym = SX_AS_SYMBOL(expr);
|
|
|
|
|
if (type_sym == NULL) {
|
ir_reader: Add a pattern matching system and use it everywhere.
Previously, the IR reader was riddled with code that:
1. Checked for the right number of list elements (via a linked list walk)
2. Retrieved references to each component (via ->next->next pointers)
3. Downcasted as necessary to make sure that each sub-component was the
right type (i.e. symbol, int, list).
4. Checking that the tag (i.e. "declare") was correct.
This was all very ad-hoc and a bit ugly. Error checking had to be done
at both steps 1, 3, and 4. Most code didn't even check the tag, relying
on the caller to do so. Not all callers did.
The new pattern matching module performs the whole process in a single
straightforward function call, resulting in shorter, more readable code.
Unfortunately, MSVC does not support C99-style anonymous arrays, so the
pattern must be declared outside of the match call.
2010-11-03 12:47:06 -07:00
|
|
|
ir_read_error(st, expr, "expected <type>");
|
2010-04-07 17:24:44 -07:00
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2010-04-10 01:06:44 -07:00
|
|
|
const glsl_type *type = st->symbols->get_type(type_sym->value());
|
2010-04-07 17:24:44 -07:00
|
|
|
if (type == NULL)
|
2010-04-21 15:47:34 -07:00
|
|
|
ir_read_error(st, expr, "invalid type: %s", type_sym->value());
|
2010-04-07 17:24:44 -07:00
|
|
|
|
|
|
|
|
return type;
|
|
|
|
|
}
|
|
|
|
|
|
2010-04-09 17:40:51 -07:00
|
|
|
|
2010-04-21 17:52:36 -07:00
|
|
|
static void
|
|
|
|
|
scan_for_prototypes(_mesa_glsl_parse_state *st, exec_list *instructions,
|
|
|
|
|
s_expression *expr)
|
|
|
|
|
{
|
|
|
|
|
s_list *list = SX_AS_LIST(expr);
|
|
|
|
|
if (list == NULL) {
|
|
|
|
|
ir_read_error(st, expr, "Expected (<instruction> ...); found an atom.");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
foreach_iter(exec_list_iterator, it, list->subexpressions) {
|
|
|
|
|
s_list *sub = SX_AS_LIST(it.get());
|
|
|
|
|
if (sub == NULL)
|
|
|
|
|
continue; // not a (function ...); ignore it.
|
|
|
|
|
|
|
|
|
|
s_symbol *tag = SX_AS_SYMBOL(sub->subexpressions.get_head());
|
|
|
|
|
if (tag == NULL || strcmp(tag->value(), "function") != 0)
|
|
|
|
|
continue; // not a (function ...); ignore it.
|
|
|
|
|
|
2010-04-21 18:14:06 -07:00
|
|
|
ir_function *f = read_function(st, sub, true);
|
|
|
|
|
if (f == NULL)
|
2010-04-21 17:52:36 -07:00
|
|
|
return;
|
2010-04-21 18:14:06 -07:00
|
|
|
instructions->push_tail(f);
|
2010-04-21 17:52:36 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2010-04-21 18:14:06 -07:00
|
|
|
static ir_function *
|
2010-12-31 02:03:21 -08:00
|
|
|
read_function(_mesa_glsl_parse_state *st, s_expression *expr, bool skip_body)
|
2010-04-21 17:52:36 -07:00
|
|
|
{
|
2010-06-25 13:14:37 -07:00
|
|
|
void *ctx = st;
|
2010-07-07 15:23:27 -07:00
|
|
|
bool added = false;
|
ir_reader: Add a pattern matching system and use it everywhere.
Previously, the IR reader was riddled with code that:
1. Checked for the right number of list elements (via a linked list walk)
2. Retrieved references to each component (via ->next->next pointers)
3. Downcasted as necessary to make sure that each sub-component was the
right type (i.e. symbol, int, list).
4. Checking that the tag (i.e. "declare") was correct.
This was all very ad-hoc and a bit ugly. Error checking had to be done
at both steps 1, 3, and 4. Most code didn't even check the tag, relying
on the caller to do so. Not all callers did.
The new pattern matching module performs the whole process in a single
straightforward function call, resulting in shorter, more readable code.
Unfortunately, MSVC does not support C99-style anonymous arrays, so the
pattern must be declared outside of the match call.
2010-11-03 12:47:06 -07:00
|
|
|
s_symbol *name;
|
2010-04-21 17:52:36 -07:00
|
|
|
|
ir_reader: Add a pattern matching system and use it everywhere.
Previously, the IR reader was riddled with code that:
1. Checked for the right number of list elements (via a linked list walk)
2. Retrieved references to each component (via ->next->next pointers)
3. Downcasted as necessary to make sure that each sub-component was the
right type (i.e. symbol, int, list).
4. Checking that the tag (i.e. "declare") was correct.
This was all very ad-hoc and a bit ugly. Error checking had to be done
at both steps 1, 3, and 4. Most code didn't even check the tag, relying
on the caller to do so. Not all callers did.
The new pattern matching module performs the whole process in a single
straightforward function call, resulting in shorter, more readable code.
Unfortunately, MSVC does not support C99-style anonymous arrays, so the
pattern must be declared outside of the match call.
2010-11-03 12:47:06 -07:00
|
|
|
s_pattern pat[] = { "function", name };
|
2010-12-31 02:03:21 -08:00
|
|
|
if (!PARTIAL_MATCH(expr, pat)) {
|
|
|
|
|
ir_read_error(st, expr, "Expected (function <name> (signature ...) ...)");
|
2010-04-21 18:14:06 -07:00
|
|
|
return NULL;
|
2010-04-21 17:52:36 -07:00
|
|
|
}
|
|
|
|
|
|
2010-04-21 18:14:06 -07:00
|
|
|
ir_function *f = st->symbols->get_function(name->value());
|
|
|
|
|
if (f == NULL) {
|
2010-06-23 18:11:51 -07:00
|
|
|
f = new(ctx) ir_function(name->value());
|
2010-11-05 06:08:45 -07:00
|
|
|
added = st->symbols->add_function(f);
|
2010-04-21 18:14:06 -07:00
|
|
|
assert(added);
|
2010-04-21 17:52:36 -07:00
|
|
|
}
|
|
|
|
|
|
2010-12-31 02:03:21 -08:00
|
|
|
exec_list_iterator it = ((s_list *) expr)->subexpressions.iterator();
|
2010-04-21 17:52:36 -07:00
|
|
|
it.next(); // skip "function" tag
|
|
|
|
|
it.next(); // skip function name
|
|
|
|
|
for (/* nothing */; it.has_next(); it.next()) {
|
ir_reader: Add a pattern matching system and use it everywhere.
Previously, the IR reader was riddled with code that:
1. Checked for the right number of list elements (via a linked list walk)
2. Retrieved references to each component (via ->next->next pointers)
3. Downcasted as necessary to make sure that each sub-component was the
right type (i.e. symbol, int, list).
4. Checking that the tag (i.e. "declare") was correct.
This was all very ad-hoc and a bit ugly. Error checking had to be done
at both steps 1, 3, and 4. Most code didn't even check the tag, relying
on the caller to do so. Not all callers did.
The new pattern matching module performs the whole process in a single
straightforward function call, resulting in shorter, more readable code.
Unfortunately, MSVC does not support C99-style anonymous arrays, so the
pattern must be declared outside of the match call.
2010-11-03 12:47:06 -07:00
|
|
|
s_expression *s_sig = (s_expression *) it.get();
|
|
|
|
|
read_function_sig(st, f, s_sig, skip_body);
|
2010-04-21 17:52:36 -07:00
|
|
|
}
|
2010-07-07 15:23:27 -07:00
|
|
|
return added ? f : NULL;
|
2010-04-21 17:52:36 -07:00
|
|
|
}
|
|
|
|
|
|
2010-04-28 12:45:18 -07:00
|
|
|
static void
|
ir_reader: Add a pattern matching system and use it everywhere.
Previously, the IR reader was riddled with code that:
1. Checked for the right number of list elements (via a linked list walk)
2. Retrieved references to each component (via ->next->next pointers)
3. Downcasted as necessary to make sure that each sub-component was the
right type (i.e. symbol, int, list).
4. Checking that the tag (i.e. "declare") was correct.
This was all very ad-hoc and a bit ugly. Error checking had to be done
at both steps 1, 3, and 4. Most code didn't even check the tag, relying
on the caller to do so. Not all callers did.
The new pattern matching module performs the whole process in a single
straightforward function call, resulting in shorter, more readable code.
Unfortunately, MSVC does not support C99-style anonymous arrays, so the
pattern must be declared outside of the match call.
2010-11-03 12:47:06 -07:00
|
|
|
read_function_sig(_mesa_glsl_parse_state *st, ir_function *f,
|
|
|
|
|
s_expression *expr, bool skip_body)
|
2010-04-21 17:52:36 -07:00
|
|
|
{
|
2010-06-25 13:14:37 -07:00
|
|
|
void *ctx = st;
|
ir_reader: Add a pattern matching system and use it everywhere.
Previously, the IR reader was riddled with code that:
1. Checked for the right number of list elements (via a linked list walk)
2. Retrieved references to each component (via ->next->next pointers)
3. Downcasted as necessary to make sure that each sub-component was the
right type (i.e. symbol, int, list).
4. Checking that the tag (i.e. "declare") was correct.
This was all very ad-hoc and a bit ugly. Error checking had to be done
at both steps 1, 3, and 4. Most code didn't even check the tag, relying
on the caller to do so. Not all callers did.
The new pattern matching module performs the whole process in a single
straightforward function call, resulting in shorter, more readable code.
Unfortunately, MSVC does not support C99-style anonymous arrays, so the
pattern must be declared outside of the match call.
2010-11-03 12:47:06 -07:00
|
|
|
s_expression *type_expr;
|
|
|
|
|
s_list *paramlist;
|
|
|
|
|
s_list *body_list;
|
|
|
|
|
|
|
|
|
|
s_pattern pat[] = { "signature", type_expr, paramlist, body_list };
|
|
|
|
|
if (!MATCH(expr, pat)) {
|
|
|
|
|
ir_read_error(st, expr, "Expected (signature <type> (parameters ...) "
|
2010-04-21 17:52:36 -07:00
|
|
|
"(<instruction> ...))");
|
2010-04-28 12:45:18 -07:00
|
|
|
return;
|
2010-04-21 17:52:36 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const glsl_type *return_type = read_type(st, type_expr);
|
|
|
|
|
if (return_type == NULL)
|
2010-04-28 12:45:18 -07:00
|
|
|
return;
|
2010-04-21 17:52:36 -07:00
|
|
|
|
|
|
|
|
s_symbol *paramtag = SX_AS_SYMBOL(paramlist->subexpressions.get_head());
|
|
|
|
|
if (paramtag == NULL || strcmp(paramtag->value(), "parameters") != 0) {
|
|
|
|
|
ir_read_error(st, paramlist, "Expected (parameters ...)");
|
2010-04-28 12:45:18 -07:00
|
|
|
return;
|
2010-04-21 17:52:36 -07:00
|
|
|
}
|
|
|
|
|
|
2010-04-28 12:45:18 -07:00
|
|
|
// Read the parameters list into a temporary place.
|
|
|
|
|
exec_list hir_parameters;
|
2010-04-21 18:14:06 -07:00
|
|
|
st->symbols->push_scope();
|
|
|
|
|
|
2010-04-21 17:52:36 -07:00
|
|
|
exec_list_iterator it = paramlist->subexpressions.iterator();
|
|
|
|
|
for (it.next() /* skip "parameters" */; it.has_next(); it.next()) {
|
2010-12-31 02:03:21 -08:00
|
|
|
ir_variable *var = read_declaration(st, (s_expression *) it.get());
|
2010-04-28 12:45:18 -07:00
|
|
|
if (var == NULL)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
hir_parameters.push_tail(var);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ir_function_signature *sig = f->exact_matching_signature(&hir_parameters);
|
2010-08-11 16:53:52 -07:00
|
|
|
if (sig == NULL && skip_body) {
|
|
|
|
|
/* If scanning for prototypes, generate a new signature. */
|
|
|
|
|
sig = new(ctx) ir_function_signature(return_type);
|
2010-09-05 01:48:11 -07:00
|
|
|
sig->is_builtin = true;
|
2010-08-11 16:53:52 -07:00
|
|
|
f->add_signature(sig);
|
|
|
|
|
} else if (sig != NULL) {
|
2010-04-28 12:45:18 -07:00
|
|
|
const char *badvar = sig->qualifiers_match(&hir_parameters);
|
|
|
|
|
if (badvar != NULL) {
|
ir_reader: Add a pattern matching system and use it everywhere.
Previously, the IR reader was riddled with code that:
1. Checked for the right number of list elements (via a linked list walk)
2. Retrieved references to each component (via ->next->next pointers)
3. Downcasted as necessary to make sure that each sub-component was the
right type (i.e. symbol, int, list).
4. Checking that the tag (i.e. "declare") was correct.
This was all very ad-hoc and a bit ugly. Error checking had to be done
at both steps 1, 3, and 4. Most code didn't even check the tag, relying
on the caller to do so. Not all callers did.
The new pattern matching module performs the whole process in a single
straightforward function call, resulting in shorter, more readable code.
Unfortunately, MSVC does not support C99-style anonymous arrays, so the
pattern must be declared outside of the match call.
2010-11-03 12:47:06 -07:00
|
|
|
ir_read_error(st, expr, "function `%s' parameter `%s' qualifiers "
|
2010-04-28 12:45:18 -07:00
|
|
|
"don't match prototype", f->name, badvar);
|
|
|
|
|
return;
|
2010-04-21 17:52:36 -07:00
|
|
|
}
|
|
|
|
|
|
2010-04-28 12:45:18 -07:00
|
|
|
if (sig->return_type != return_type) {
|
ir_reader: Add a pattern matching system and use it everywhere.
Previously, the IR reader was riddled with code that:
1. Checked for the right number of list elements (via a linked list walk)
2. Retrieved references to each component (via ->next->next pointers)
3. Downcasted as necessary to make sure that each sub-component was the
right type (i.e. symbol, int, list).
4. Checking that the tag (i.e. "declare") was correct.
This was all very ad-hoc and a bit ugly. Error checking had to be done
at both steps 1, 3, and 4. Most code didn't even check the tag, relying
on the caller to do so. Not all callers did.
The new pattern matching module performs the whole process in a single
straightforward function call, resulting in shorter, more readable code.
Unfortunately, MSVC does not support C99-style anonymous arrays, so the
pattern must be declared outside of the match call.
2010-11-03 12:47:06 -07:00
|
|
|
ir_read_error(st, expr, "function `%s' return type doesn't "
|
2010-04-28 12:45:18 -07:00
|
|
|
"match prototype", f->name);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
2010-08-11 16:53:52 -07:00
|
|
|
/* No prototype for this body exists - skip it. */
|
|
|
|
|
st->symbols->pop_scope();
|
|
|
|
|
return;
|
2010-04-21 17:52:36 -07:00
|
|
|
}
|
2010-08-11 16:53:52 -07:00
|
|
|
assert(sig != NULL);
|
2010-04-21 17:52:36 -07:00
|
|
|
|
2010-04-28 12:45:18 -07:00
|
|
|
sig->replace_parameters(&hir_parameters);
|
|
|
|
|
|
2010-08-12 13:17:53 -07:00
|
|
|
if (!skip_body && !body_list->subexpressions.is_empty()) {
|
2010-04-28 12:45:18 -07:00
|
|
|
if (sig->is_defined) {
|
ir_reader: Add a pattern matching system and use it everywhere.
Previously, the IR reader was riddled with code that:
1. Checked for the right number of list elements (via a linked list walk)
2. Retrieved references to each component (via ->next->next pointers)
3. Downcasted as necessary to make sure that each sub-component was the
right type (i.e. symbol, int, list).
4. Checking that the tag (i.e. "declare") was correct.
This was all very ad-hoc and a bit ugly. Error checking had to be done
at both steps 1, 3, and 4. Most code didn't even check the tag, relying
on the caller to do so. Not all callers did.
The new pattern matching module performs the whole process in a single
straightforward function call, resulting in shorter, more readable code.
Unfortunately, MSVC does not support C99-style anonymous arrays, so the
pattern must be declared outside of the match call.
2010-11-03 12:47:06 -07:00
|
|
|
ir_read_error(st, expr, "function %s redefined", f->name);
|
2010-04-28 12:45:18 -07:00
|
|
|
return;
|
|
|
|
|
}
|
2010-09-04 01:05:51 -07:00
|
|
|
st->current_function = sig;
|
2010-04-21 18:14:06 -07:00
|
|
|
read_instructions(st, &sig->body, body_list, NULL);
|
2010-09-04 01:05:51 -07:00
|
|
|
st->current_function = NULL;
|
2010-04-28 23:17:58 -07:00
|
|
|
sig->is_defined = true;
|
2010-04-28 12:45:18 -07:00
|
|
|
}
|
2010-04-21 18:14:06 -07:00
|
|
|
|
|
|
|
|
st->symbols->pop_scope();
|
2010-04-21 17:52:36 -07:00
|
|
|
}
|
|
|
|
|
|
2010-04-10 01:45:08 -07:00
|
|
|
static void
|
|
|
|
|
read_instructions(_mesa_glsl_parse_state *st, exec_list *instructions,
|
2010-04-12 16:02:48 -07:00
|
|
|
s_expression *expr, ir_loop *loop_ctx)
|
2010-04-10 01:45:08 -07:00
|
|
|
{
|
|
|
|
|
// Read in a list of instructions
|
|
|
|
|
s_list *list = SX_AS_LIST(expr);
|
|
|
|
|
if (list == NULL) {
|
2010-04-21 15:47:34 -07:00
|
|
|
ir_read_error(st, expr, "Expected (<instruction> ...); found an atom.");
|
2010-04-10 01:45:08 -07:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
foreach_iter(exec_list_iterator, it, list->subexpressions) {
|
|
|
|
|
s_expression *sub = (s_expression*) it.get();
|
2010-04-12 16:02:48 -07:00
|
|
|
ir_instruction *ir = read_instruction(st, sub, loop_ctx);
|
2010-09-04 01:55:55 -07:00
|
|
|
if (ir != NULL) {
|
|
|
|
|
/* Global variable declarations should be moved to the top, before
|
|
|
|
|
* any functions that might use them. Functions are added to the
|
|
|
|
|
* instruction stream when scanning for prototypes, so without this
|
|
|
|
|
* hack, they always appear before variable declarations.
|
|
|
|
|
*/
|
|
|
|
|
if (st->current_function == NULL && ir->as_variable() != NULL)
|
|
|
|
|
instructions->push_head(ir);
|
|
|
|
|
else
|
|
|
|
|
instructions->push_tail(ir);
|
|
|
|
|
}
|
2010-04-10 01:45:08 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2010-04-09 17:40:51 -07:00
|
|
|
static ir_instruction *
|
2010-04-12 16:02:48 -07:00
|
|
|
read_instruction(_mesa_glsl_parse_state *st, s_expression *expr,
|
|
|
|
|
ir_loop *loop_ctx)
|
2010-04-09 17:40:51 -07:00
|
|
|
{
|
2010-06-25 13:14:37 -07:00
|
|
|
void *ctx = st;
|
2010-04-12 16:02:48 -07:00
|
|
|
s_symbol *symbol = SX_AS_SYMBOL(expr);
|
|
|
|
|
if (symbol != NULL) {
|
|
|
|
|
if (strcmp(symbol->value(), "break") == 0 && loop_ctx != NULL)
|
2010-06-23 18:11:51 -07:00
|
|
|
return new(ctx) ir_loop_jump(ir_loop_jump::jump_break);
|
2010-04-12 16:02:48 -07:00
|
|
|
if (strcmp(symbol->value(), "continue") == 0 && loop_ctx != NULL)
|
2010-06-23 18:11:51 -07:00
|
|
|
return new(ctx) ir_loop_jump(ir_loop_jump::jump_continue);
|
2010-04-12 16:02:48 -07:00
|
|
|
}
|
|
|
|
|
|
2010-04-09 17:40:51 -07:00
|
|
|
s_list *list = SX_AS_LIST(expr);
|
2010-07-07 15:23:27 -07:00
|
|
|
if (list == NULL || list->subexpressions.is_empty()) {
|
|
|
|
|
ir_read_error(st, expr, "Invalid instruction.\n");
|
2010-04-09 17:40:51 -07:00
|
|
|
return NULL;
|
2010-07-07 15:23:27 -07:00
|
|
|
}
|
2010-04-09 17:40:51 -07:00
|
|
|
|
|
|
|
|
s_symbol *tag = SX_AS_SYMBOL(list->subexpressions.get_head());
|
|
|
|
|
if (tag == NULL) {
|
2010-04-21 15:47:34 -07:00
|
|
|
ir_read_error(st, expr, "expected instruction tag");
|
2010-04-09 17:40:51 -07:00
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ir_instruction *inst = NULL;
|
2010-04-12 14:25:41 -07:00
|
|
|
if (strcmp(tag->value(), "declare") == 0) {
|
2010-04-09 17:40:51 -07:00
|
|
|
inst = read_declaration(st, list);
|
2010-07-22 16:40:35 -07:00
|
|
|
} else if (strcmp(tag->value(), "assign") == 0) {
|
|
|
|
|
inst = read_assignment(st, list);
|
2010-04-12 14:25:41 -07:00
|
|
|
} else if (strcmp(tag->value(), "if") == 0) {
|
2010-04-12 16:02:48 -07:00
|
|
|
inst = read_if(st, list, loop_ctx);
|
2010-04-12 15:48:27 -07:00
|
|
|
} else if (strcmp(tag->value(), "loop") == 0) {
|
|
|
|
|
inst = read_loop(st, list);
|
2010-04-12 14:25:41 -07:00
|
|
|
} else if (strcmp(tag->value(), "return") == 0) {
|
2010-04-09 17:56:22 -07:00
|
|
|
inst = read_return(st, list);
|
2010-04-21 18:14:06 -07:00
|
|
|
} else if (strcmp(tag->value(), "function") == 0) {
|
|
|
|
|
inst = read_function(st, list, false);
|
2010-04-12 14:25:41 -07:00
|
|
|
} else {
|
|
|
|
|
inst = read_rvalue(st, list);
|
|
|
|
|
if (inst == NULL)
|
2010-04-21 23:23:23 -07:00
|
|
|
ir_read_error(st, NULL, "when reading instruction");
|
2010-04-12 14:25:41 -07:00
|
|
|
}
|
2010-04-09 17:40:51 -07:00
|
|
|
return inst;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static ir_variable *
|
2010-12-31 02:03:21 -08:00
|
|
|
read_declaration(_mesa_glsl_parse_state *st, s_expression *expr)
|
2010-04-09 17:40:51 -07:00
|
|
|
{
|
ir_reader: Add a pattern matching system and use it everywhere.
Previously, the IR reader was riddled with code that:
1. Checked for the right number of list elements (via a linked list walk)
2. Retrieved references to each component (via ->next->next pointers)
3. Downcasted as necessary to make sure that each sub-component was the
right type (i.e. symbol, int, list).
4. Checking that the tag (i.e. "declare") was correct.
This was all very ad-hoc and a bit ugly. Error checking had to be done
at both steps 1, 3, and 4. Most code didn't even check the tag, relying
on the caller to do so. Not all callers did.
The new pattern matching module performs the whole process in a single
straightforward function call, resulting in shorter, more readable code.
Unfortunately, MSVC does not support C99-style anonymous arrays, so the
pattern must be declared outside of the match call.
2010-11-03 12:47:06 -07:00
|
|
|
s_list *s_quals;
|
|
|
|
|
s_expression *s_type;
|
|
|
|
|
s_symbol *s_name;
|
|
|
|
|
|
|
|
|
|
s_pattern pat[] = { "declare", s_quals, s_type, s_name };
|
2010-12-31 02:03:21 -08:00
|
|
|
if (!MATCH(expr, pat)) {
|
|
|
|
|
ir_read_error(st, expr, "expected (declare (<qualifiers>) <type> "
|
2010-04-21 15:47:34 -07:00
|
|
|
"<name>)");
|
2010-04-09 17:40:51 -07:00
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
ir_reader: Add a pattern matching system and use it everywhere.
Previously, the IR reader was riddled with code that:
1. Checked for the right number of list elements (via a linked list walk)
2. Retrieved references to each component (via ->next->next pointers)
3. Downcasted as necessary to make sure that each sub-component was the
right type (i.e. symbol, int, list).
4. Checking that the tag (i.e. "declare") was correct.
This was all very ad-hoc and a bit ugly. Error checking had to be done
at both steps 1, 3, and 4. Most code didn't even check the tag, relying
on the caller to do so. Not all callers did.
The new pattern matching module performs the whole process in a single
straightforward function call, resulting in shorter, more readable code.
Unfortunately, MSVC does not support C99-style anonymous arrays, so the
pattern must be declared outside of the match call.
2010-11-03 12:47:06 -07:00
|
|
|
const glsl_type *type = read_type(st, s_type);
|
2010-04-09 17:40:51 -07:00
|
|
|
if (type == NULL)
|
|
|
|
|
return NULL;
|
|
|
|
|
|
ir_reader: Add a pattern matching system and use it everywhere.
Previously, the IR reader was riddled with code that:
1. Checked for the right number of list elements (via a linked list walk)
2. Retrieved references to each component (via ->next->next pointers)
3. Downcasted as necessary to make sure that each sub-component was the
right type (i.e. symbol, int, list).
4. Checking that the tag (i.e. "declare") was correct.
This was all very ad-hoc and a bit ugly. Error checking had to be done
at both steps 1, 3, and 4. Most code didn't even check the tag, relying
on the caller to do so. Not all callers did.
The new pattern matching module performs the whole process in a single
straightforward function call, resulting in shorter, more readable code.
Unfortunately, MSVC does not support C99-style anonymous arrays, so the
pattern must be declared outside of the match call.
2010-11-03 12:47:06 -07:00
|
|
|
ir_variable *var = new(st) ir_variable(type, s_name->value(), ir_var_auto);
|
2010-04-09 17:40:51 -07:00
|
|
|
|
ir_reader: Add a pattern matching system and use it everywhere.
Previously, the IR reader was riddled with code that:
1. Checked for the right number of list elements (via a linked list walk)
2. Retrieved references to each component (via ->next->next pointers)
3. Downcasted as necessary to make sure that each sub-component was the
right type (i.e. symbol, int, list).
4. Checking that the tag (i.e. "declare") was correct.
This was all very ad-hoc and a bit ugly. Error checking had to be done
at both steps 1, 3, and 4. Most code didn't even check the tag, relying
on the caller to do so. Not all callers did.
The new pattern matching module performs the whole process in a single
straightforward function call, resulting in shorter, more readable code.
Unfortunately, MSVC does not support C99-style anonymous arrays, so the
pattern must be declared outside of the match call.
2010-11-03 12:47:06 -07:00
|
|
|
foreach_iter(exec_list_iterator, it, s_quals->subexpressions) {
|
2010-04-09 17:40:51 -07:00
|
|
|
s_symbol *qualifier = SX_AS_SYMBOL(it.get());
|
|
|
|
|
if (qualifier == NULL) {
|
2010-12-31 02:03:21 -08:00
|
|
|
ir_read_error(st, expr, "qualifier list must contain only symbols");
|
2010-04-09 17:40:51 -07:00
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// FINISHME: Check for duplicate/conflicting qualifiers.
|
|
|
|
|
if (strcmp(qualifier->value(), "centroid") == 0) {
|
|
|
|
|
var->centroid = 1;
|
|
|
|
|
} else if (strcmp(qualifier->value(), "invariant") == 0) {
|
|
|
|
|
var->invariant = 1;
|
|
|
|
|
} else if (strcmp(qualifier->value(), "uniform") == 0) {
|
|
|
|
|
var->mode = ir_var_uniform;
|
|
|
|
|
} else if (strcmp(qualifier->value(), "auto") == 0) {
|
|
|
|
|
var->mode = ir_var_auto;
|
|
|
|
|
} else if (strcmp(qualifier->value(), "in") == 0) {
|
|
|
|
|
var->mode = ir_var_in;
|
|
|
|
|
} else if (strcmp(qualifier->value(), "out") == 0) {
|
|
|
|
|
var->mode = ir_var_out;
|
|
|
|
|
} else if (strcmp(qualifier->value(), "inout") == 0) {
|
|
|
|
|
var->mode = ir_var_inout;
|
|
|
|
|
} else if (strcmp(qualifier->value(), "smooth") == 0) {
|
|
|
|
|
var->interpolation = ir_var_smooth;
|
|
|
|
|
} else if (strcmp(qualifier->value(), "flat") == 0) {
|
|
|
|
|
var->interpolation = ir_var_flat;
|
|
|
|
|
} else if (strcmp(qualifier->value(), "noperspective") == 0) {
|
|
|
|
|
var->interpolation = ir_var_noperspective;
|
|
|
|
|
} else {
|
2010-12-31 02:03:21 -08:00
|
|
|
ir_read_error(st, expr, "unknown qualifier: %s", qualifier->value());
|
2010-04-09 17:40:51 -07:00
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Add the variable to the symbol table
|
2010-11-05 06:11:24 -07:00
|
|
|
st->symbols->add_variable(var);
|
2010-04-09 17:40:51 -07:00
|
|
|
|
|
|
|
|
return var;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2010-04-10 01:45:08 -07:00
|
|
|
static ir_if *
|
2010-12-31 02:03:21 -08:00
|
|
|
read_if(_mesa_glsl_parse_state *st, s_expression *expr, ir_loop *loop_ctx)
|
2010-04-10 01:45:08 -07:00
|
|
|
{
|
ir_reader: Add a pattern matching system and use it everywhere.
Previously, the IR reader was riddled with code that:
1. Checked for the right number of list elements (via a linked list walk)
2. Retrieved references to each component (via ->next->next pointers)
3. Downcasted as necessary to make sure that each sub-component was the
right type (i.e. symbol, int, list).
4. Checking that the tag (i.e. "declare") was correct.
This was all very ad-hoc and a bit ugly. Error checking had to be done
at both steps 1, 3, and 4. Most code didn't even check the tag, relying
on the caller to do so. Not all callers did.
The new pattern matching module performs the whole process in a single
straightforward function call, resulting in shorter, more readable code.
Unfortunately, MSVC does not support C99-style anonymous arrays, so the
pattern must be declared outside of the match call.
2010-11-03 12:47:06 -07:00
|
|
|
s_expression *s_cond;
|
|
|
|
|
s_expression *s_then;
|
|
|
|
|
s_expression *s_else;
|
|
|
|
|
|
|
|
|
|
s_pattern pat[] = { "if", s_cond, s_then, s_else };
|
2010-12-31 02:03:21 -08:00
|
|
|
if (!MATCH(expr, pat)) {
|
|
|
|
|
ir_read_error(st, expr, "expected (if <condition> (<then> ...) "
|
ir_reader: Add a pattern matching system and use it everywhere.
Previously, the IR reader was riddled with code that:
1. Checked for the right number of list elements (via a linked list walk)
2. Retrieved references to each component (via ->next->next pointers)
3. Downcasted as necessary to make sure that each sub-component was the
right type (i.e. symbol, int, list).
4. Checking that the tag (i.e. "declare") was correct.
This was all very ad-hoc and a bit ugly. Error checking had to be done
at both steps 1, 3, and 4. Most code didn't even check the tag, relying
on the caller to do so. Not all callers did.
The new pattern matching module performs the whole process in a single
straightforward function call, resulting in shorter, more readable code.
Unfortunately, MSVC does not support C99-style anonymous arrays, so the
pattern must be declared outside of the match call.
2010-11-03 12:47:06 -07:00
|
|
|
"(<else> ...))");
|
2010-04-10 01:45:08 -07:00
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
ir_reader: Add a pattern matching system and use it everywhere.
Previously, the IR reader was riddled with code that:
1. Checked for the right number of list elements (via a linked list walk)
2. Retrieved references to each component (via ->next->next pointers)
3. Downcasted as necessary to make sure that each sub-component was the
right type (i.e. symbol, int, list).
4. Checking that the tag (i.e. "declare") was correct.
This was all very ad-hoc and a bit ugly. Error checking had to be done
at both steps 1, 3, and 4. Most code didn't even check the tag, relying
on the caller to do so. Not all callers did.
The new pattern matching module performs the whole process in a single
straightforward function call, resulting in shorter, more readable code.
Unfortunately, MSVC does not support C99-style anonymous arrays, so the
pattern must be declared outside of the match call.
2010-11-03 12:47:06 -07:00
|
|
|
ir_rvalue *condition = read_rvalue(st, s_cond);
|
2010-04-10 01:45:08 -07:00
|
|
|
if (condition == NULL) {
|
2010-04-21 23:23:23 -07:00
|
|
|
ir_read_error(st, NULL, "when reading condition of (if ...)");
|
2010-04-10 01:45:08 -07:00
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
ir_reader: Add a pattern matching system and use it everywhere.
Previously, the IR reader was riddled with code that:
1. Checked for the right number of list elements (via a linked list walk)
2. Retrieved references to each component (via ->next->next pointers)
3. Downcasted as necessary to make sure that each sub-component was the
right type (i.e. symbol, int, list).
4. Checking that the tag (i.e. "declare") was correct.
This was all very ad-hoc and a bit ugly. Error checking had to be done
at both steps 1, 3, and 4. Most code didn't even check the tag, relying
on the caller to do so. Not all callers did.
The new pattern matching module performs the whole process in a single
straightforward function call, resulting in shorter, more readable code.
Unfortunately, MSVC does not support C99-style anonymous arrays, so the
pattern must be declared outside of the match call.
2010-11-03 12:47:06 -07:00
|
|
|
ir_if *iff = new(st) ir_if(condition);
|
2010-04-10 01:45:08 -07:00
|
|
|
|
ir_reader: Add a pattern matching system and use it everywhere.
Previously, the IR reader was riddled with code that:
1. Checked for the right number of list elements (via a linked list walk)
2. Retrieved references to each component (via ->next->next pointers)
3. Downcasted as necessary to make sure that each sub-component was the
right type (i.e. symbol, int, list).
4. Checking that the tag (i.e. "declare") was correct.
This was all very ad-hoc and a bit ugly. Error checking had to be done
at both steps 1, 3, and 4. Most code didn't even check the tag, relying
on the caller to do so. Not all callers did.
The new pattern matching module performs the whole process in a single
straightforward function call, resulting in shorter, more readable code.
Unfortunately, MSVC does not support C99-style anonymous arrays, so the
pattern must be declared outside of the match call.
2010-11-03 12:47:06 -07:00
|
|
|
read_instructions(st, &iff->then_instructions, s_then, loop_ctx);
|
|
|
|
|
read_instructions(st, &iff->else_instructions, s_else, loop_ctx);
|
2010-04-10 01:45:08 -07:00
|
|
|
if (st->error) {
|
|
|
|
|
delete iff;
|
|
|
|
|
iff = NULL;
|
|
|
|
|
}
|
|
|
|
|
return iff;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2010-04-12 15:48:27 -07:00
|
|
|
static ir_loop *
|
2010-12-31 02:03:21 -08:00
|
|
|
read_loop(_mesa_glsl_parse_state *st, s_expression *expr)
|
2010-04-12 15:48:27 -07:00
|
|
|
{
|
ir_reader: Add a pattern matching system and use it everywhere.
Previously, the IR reader was riddled with code that:
1. Checked for the right number of list elements (via a linked list walk)
2. Retrieved references to each component (via ->next->next pointers)
3. Downcasted as necessary to make sure that each sub-component was the
right type (i.e. symbol, int, list).
4. Checking that the tag (i.e. "declare") was correct.
This was all very ad-hoc and a bit ugly. Error checking had to be done
at both steps 1, 3, and 4. Most code didn't even check the tag, relying
on the caller to do so. Not all callers did.
The new pattern matching module performs the whole process in a single
straightforward function call, resulting in shorter, more readable code.
Unfortunately, MSVC does not support C99-style anonymous arrays, so the
pattern must be declared outside of the match call.
2010-11-03 12:47:06 -07:00
|
|
|
s_expression *s_counter, *s_from, *s_to, *s_inc, *s_body;
|
|
|
|
|
|
|
|
|
|
s_pattern pat[] = { "loop", s_counter, s_from, s_to, s_inc, s_body };
|
2010-12-31 02:03:21 -08:00
|
|
|
if (!MATCH(expr, pat)) {
|
|
|
|
|
ir_read_error(st, expr, "expected (loop <counter> <from> <to> "
|
2010-04-21 15:47:34 -07:00
|
|
|
"<increment> <body>)");
|
2010-04-12 15:48:27 -07:00
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// FINISHME: actually read the count/from/to fields.
|
|
|
|
|
|
ir_reader: Add a pattern matching system and use it everywhere.
Previously, the IR reader was riddled with code that:
1. Checked for the right number of list elements (via a linked list walk)
2. Retrieved references to each component (via ->next->next pointers)
3. Downcasted as necessary to make sure that each sub-component was the
right type (i.e. symbol, int, list).
4. Checking that the tag (i.e. "declare") was correct.
This was all very ad-hoc and a bit ugly. Error checking had to be done
at both steps 1, 3, and 4. Most code didn't even check the tag, relying
on the caller to do so. Not all callers did.
The new pattern matching module performs the whole process in a single
straightforward function call, resulting in shorter, more readable code.
Unfortunately, MSVC does not support C99-style anonymous arrays, so the
pattern must be declared outside of the match call.
2010-11-03 12:47:06 -07:00
|
|
|
ir_loop *loop = new(st) ir_loop;
|
|
|
|
|
read_instructions(st, &loop->body_instructions, s_body, loop);
|
2010-04-12 15:48:27 -07:00
|
|
|
if (st->error) {
|
|
|
|
|
delete loop;
|
|
|
|
|
loop = NULL;
|
|
|
|
|
}
|
|
|
|
|
return loop;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2010-04-09 17:56:22 -07:00
|
|
|
static ir_return *
|
2010-12-31 02:03:21 -08:00
|
|
|
read_return(_mesa_glsl_parse_state *st, s_expression *expr)
|
2010-04-09 17:56:22 -07:00
|
|
|
{
|
2010-12-31 02:03:21 -08:00
|
|
|
s_expression *s_retval;
|
ir_reader: Add a pattern matching system and use it everywhere.
Previously, the IR reader was riddled with code that:
1. Checked for the right number of list elements (via a linked list walk)
2. Retrieved references to each component (via ->next->next pointers)
3. Downcasted as necessary to make sure that each sub-component was the
right type (i.e. symbol, int, list).
4. Checking that the tag (i.e. "declare") was correct.
This was all very ad-hoc and a bit ugly. Error checking had to be done
at both steps 1, 3, and 4. Most code didn't even check the tag, relying
on the caller to do so. Not all callers did.
The new pattern matching module performs the whole process in a single
straightforward function call, resulting in shorter, more readable code.
Unfortunately, MSVC does not support C99-style anonymous arrays, so the
pattern must be declared outside of the match call.
2010-11-03 12:47:06 -07:00
|
|
|
|
2010-12-31 02:03:21 -08:00
|
|
|
s_pattern pat[] = { "return", s_retval};
|
|
|
|
|
if (!MATCH(expr, pat)) {
|
|
|
|
|
ir_read_error(st, expr, "expected (return <rvalue>)");
|
2010-04-09 17:56:22 -07:00
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2010-12-31 02:03:21 -08:00
|
|
|
ir_rvalue *retval = read_rvalue(st, s_retval);
|
2010-04-09 17:56:22 -07:00
|
|
|
if (retval == NULL) {
|
2010-04-21 23:23:23 -07:00
|
|
|
ir_read_error(st, NULL, "when reading return value");
|
2010-04-09 17:56:22 -07:00
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
ir_reader: Add a pattern matching system and use it everywhere.
Previously, the IR reader was riddled with code that:
1. Checked for the right number of list elements (via a linked list walk)
2. Retrieved references to each component (via ->next->next pointers)
3. Downcasted as necessary to make sure that each sub-component was the
right type (i.e. symbol, int, list).
4. Checking that the tag (i.e. "declare") was correct.
This was all very ad-hoc and a bit ugly. Error checking had to be done
at both steps 1, 3, and 4. Most code didn't even check the tag, relying
on the caller to do so. Not all callers did.
The new pattern matching module performs the whole process in a single
straightforward function call, resulting in shorter, more readable code.
Unfortunately, MSVC does not support C99-style anonymous arrays, so the
pattern must be declared outside of the match call.
2010-11-03 12:47:06 -07:00
|
|
|
return new(st) ir_return(retval);
|
2010-04-09 17:56:22 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2010-04-07 17:24:44 -07:00
|
|
|
static ir_rvalue *
|
|
|
|
|
read_rvalue(_mesa_glsl_parse_state *st, s_expression *expr)
|
|
|
|
|
{
|
|
|
|
|
s_list *list = SX_AS_LIST(expr);
|
|
|
|
|
if (list == NULL || list->subexpressions.is_empty())
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
s_symbol *tag = SX_AS_SYMBOL(list->subexpressions.get_head());
|
|
|
|
|
if (tag == NULL) {
|
2010-04-21 15:47:34 -07:00
|
|
|
ir_read_error(st, expr, "expected rvalue tag");
|
2010-04-07 17:24:44 -07:00
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2010-05-26 17:52:44 -07:00
|
|
|
ir_rvalue *rvalue = read_dereference(st, list);
|
|
|
|
|
if (rvalue != NULL || st->error)
|
|
|
|
|
return rvalue;
|
|
|
|
|
else if (strcmp(tag->value(), "swiz") == 0) {
|
2010-04-07 17:24:44 -07:00
|
|
|
rvalue = read_swizzle(st, list);
|
2010-04-12 14:27:39 -07:00
|
|
|
} else if (strcmp(tag->value(), "expression") == 0) {
|
2010-04-07 17:24:44 -07:00
|
|
|
rvalue = read_expression(st, list);
|
2010-04-28 12:54:21 -07:00
|
|
|
} else if (strcmp(tag->value(), "call") == 0) {
|
|
|
|
|
rvalue = read_call(st, list);
|
2010-04-12 14:27:39 -07:00
|
|
|
} else if (strcmp(tag->value(), "constant") == 0) {
|
2010-04-07 17:24:44 -07:00
|
|
|
rvalue = read_constant(st, list);
|
2010-04-12 14:27:39 -07:00
|
|
|
} else {
|
2010-05-26 17:55:10 -07:00
|
|
|
rvalue = read_texture(st, list);
|
|
|
|
|
if (rvalue == NULL && !st->error)
|
|
|
|
|
ir_read_error(st, expr, "unrecognized rvalue tag: %s", tag->value());
|
2010-04-12 14:27:39 -07:00
|
|
|
}
|
2010-04-07 17:24:44 -07:00
|
|
|
|
|
|
|
|
return rvalue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static ir_assignment *
|
2010-12-31 02:03:21 -08:00
|
|
|
read_assignment(_mesa_glsl_parse_state *st, s_expression *expr)
|
2010-04-07 17:24:44 -07:00
|
|
|
{
|
ir_reader: Add a pattern matching system and use it everywhere.
Previously, the IR reader was riddled with code that:
1. Checked for the right number of list elements (via a linked list walk)
2. Retrieved references to each component (via ->next->next pointers)
3. Downcasted as necessary to make sure that each sub-component was the
right type (i.e. symbol, int, list).
4. Checking that the tag (i.e. "declare") was correct.
This was all very ad-hoc and a bit ugly. Error checking had to be done
at both steps 1, 3, and 4. Most code didn't even check the tag, relying
on the caller to do so. Not all callers did.
The new pattern matching module performs the whole process in a single
straightforward function call, resulting in shorter, more readable code.
Unfortunately, MSVC does not support C99-style anonymous arrays, so the
pattern must be declared outside of the match call.
2010-11-03 12:47:06 -07:00
|
|
|
s_expression *cond_expr, *lhs_expr, *rhs_expr;
|
|
|
|
|
s_list *mask_list;
|
|
|
|
|
|
|
|
|
|
s_pattern pat[] = { "assign", cond_expr, mask_list, lhs_expr, rhs_expr };
|
2010-12-31 02:03:21 -08:00
|
|
|
if (!MATCH(expr, pat)) {
|
|
|
|
|
ir_read_error(st, expr, "expected (assign <condition> (<write mask>) "
|
2010-09-02 23:54:40 -07:00
|
|
|
"<lhs> <rhs>)");
|
2010-04-07 17:24:44 -07:00
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ir_rvalue *condition = read_rvalue(st, cond_expr);
|
|
|
|
|
if (condition == NULL) {
|
2010-04-21 23:23:23 -07:00
|
|
|
ir_read_error(st, NULL, "when reading condition of assignment");
|
2010-04-07 17:24:44 -07:00
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2010-09-02 23:54:40 -07:00
|
|
|
unsigned mask = 0;
|
|
|
|
|
|
ir_reader: Add a pattern matching system and use it everywhere.
Previously, the IR reader was riddled with code that:
1. Checked for the right number of list elements (via a linked list walk)
2. Retrieved references to each component (via ->next->next pointers)
3. Downcasted as necessary to make sure that each sub-component was the
right type (i.e. symbol, int, list).
4. Checking that the tag (i.e. "declare") was correct.
This was all very ad-hoc and a bit ugly. Error checking had to be done
at both steps 1, 3, and 4. Most code didn't even check the tag, relying
on the caller to do so. Not all callers did.
The new pattern matching module performs the whole process in a single
straightforward function call, resulting in shorter, more readable code.
Unfortunately, MSVC does not support C99-style anonymous arrays, so the
pattern must be declared outside of the match call.
2010-11-03 12:47:06 -07:00
|
|
|
s_symbol *mask_symbol;
|
|
|
|
|
s_pattern mask_pat[] = { mask_symbol };
|
|
|
|
|
if (MATCH(mask_list, mask_pat)) {
|
2010-09-02 23:54:40 -07:00
|
|
|
const char *mask_str = mask_symbol->value();
|
|
|
|
|
unsigned mask_length = strlen(mask_str);
|
|
|
|
|
if (mask_length > 4) {
|
2010-12-31 02:03:21 -08:00
|
|
|
ir_read_error(st, expr, "invalid write mask: %s", mask_str);
|
2010-09-02 23:54:40 -07:00
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const unsigned idx_map[] = { 3, 0, 1, 2 }; /* w=bit 3, x=0, y=1, z=2 */
|
|
|
|
|
|
|
|
|
|
for (unsigned i = 0; i < mask_length; i++) {
|
|
|
|
|
if (mask_str[i] < 'w' || mask_str[i] > 'z') {
|
2010-12-31 02:03:21 -08:00
|
|
|
ir_read_error(st, expr, "write mask contains invalid character: %c",
|
2010-09-02 23:54:40 -07:00
|
|
|
mask_str[i]);
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
mask |= 1 << idx_map[mask_str[i] - 'w'];
|
|
|
|
|
}
|
ir_reader: Add a pattern matching system and use it everywhere.
Previously, the IR reader was riddled with code that:
1. Checked for the right number of list elements (via a linked list walk)
2. Retrieved references to each component (via ->next->next pointers)
3. Downcasted as necessary to make sure that each sub-component was the
right type (i.e. symbol, int, list).
4. Checking that the tag (i.e. "declare") was correct.
This was all very ad-hoc and a bit ugly. Error checking had to be done
at both steps 1, 3, and 4. Most code didn't even check the tag, relying
on the caller to do so. Not all callers did.
The new pattern matching module performs the whole process in a single
straightforward function call, resulting in shorter, more readable code.
Unfortunately, MSVC does not support C99-style anonymous arrays, so the
pattern must be declared outside of the match call.
2010-11-03 12:47:06 -07:00
|
|
|
} else if (!mask_list->subexpressions.is_empty()) {
|
|
|
|
|
ir_read_error(st, mask_list, "expected () or (<write mask>)");
|
|
|
|
|
return NULL;
|
2010-09-02 23:54:40 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ir_dereference *lhs = read_dereference(st, lhs_expr);
|
2010-04-07 17:24:44 -07:00
|
|
|
if (lhs == NULL) {
|
2010-04-21 23:23:23 -07:00
|
|
|
ir_read_error(st, NULL, "when reading left-hand side of assignment");
|
2010-04-07 17:24:44 -07:00
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ir_rvalue *rhs = read_rvalue(st, rhs_expr);
|
|
|
|
|
if (rhs == NULL) {
|
2010-04-21 23:23:23 -07:00
|
|
|
ir_read_error(st, NULL, "when reading right-hand side of assignment");
|
2010-04-07 17:24:44 -07:00
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2010-09-02 23:54:40 -07:00
|
|
|
if (mask == 0 && (lhs->type->is_vector() || lhs->type->is_scalar())) {
|
2010-12-31 02:03:21 -08:00
|
|
|
ir_read_error(st, expr, "non-zero write mask required.");
|
2010-09-02 23:54:40 -07:00
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
ir_reader: Add a pattern matching system and use it everywhere.
Previously, the IR reader was riddled with code that:
1. Checked for the right number of list elements (via a linked list walk)
2. Retrieved references to each component (via ->next->next pointers)
3. Downcasted as necessary to make sure that each sub-component was the
right type (i.e. symbol, int, list).
4. Checking that the tag (i.e. "declare") was correct.
This was all very ad-hoc and a bit ugly. Error checking had to be done
at both steps 1, 3, and 4. Most code didn't even check the tag, relying
on the caller to do so. Not all callers did.
The new pattern matching module performs the whole process in a single
straightforward function call, resulting in shorter, more readable code.
Unfortunately, MSVC does not support C99-style anonymous arrays, so the
pattern must be declared outside of the match call.
2010-11-03 12:47:06 -07:00
|
|
|
return new(st) ir_assignment(lhs, rhs, condition, mask);
|
2010-04-07 17:24:44 -07:00
|
|
|
}
|
|
|
|
|
|
2010-04-28 12:54:21 -07:00
|
|
|
static ir_call *
|
2010-12-31 02:03:21 -08:00
|
|
|
read_call(_mesa_glsl_parse_state *st, s_expression *expr)
|
2010-04-28 12:54:21 -07:00
|
|
|
{
|
2010-06-25 13:14:37 -07:00
|
|
|
void *ctx = st;
|
ir_reader: Add a pattern matching system and use it everywhere.
Previously, the IR reader was riddled with code that:
1. Checked for the right number of list elements (via a linked list walk)
2. Retrieved references to each component (via ->next->next pointers)
3. Downcasted as necessary to make sure that each sub-component was the
right type (i.e. symbol, int, list).
4. Checking that the tag (i.e. "declare") was correct.
This was all very ad-hoc and a bit ugly. Error checking had to be done
at both steps 1, 3, and 4. Most code didn't even check the tag, relying
on the caller to do so. Not all callers did.
The new pattern matching module performs the whole process in a single
straightforward function call, resulting in shorter, more readable code.
Unfortunately, MSVC does not support C99-style anonymous arrays, so the
pattern must be declared outside of the match call.
2010-11-03 12:47:06 -07:00
|
|
|
s_symbol *name;
|
|
|
|
|
s_list *params;
|
2010-04-28 12:54:21 -07:00
|
|
|
|
ir_reader: Add a pattern matching system and use it everywhere.
Previously, the IR reader was riddled with code that:
1. Checked for the right number of list elements (via a linked list walk)
2. Retrieved references to each component (via ->next->next pointers)
3. Downcasted as necessary to make sure that each sub-component was the
right type (i.e. symbol, int, list).
4. Checking that the tag (i.e. "declare") was correct.
This was all very ad-hoc and a bit ugly. Error checking had to be done
at both steps 1, 3, and 4. Most code didn't even check the tag, relying
on the caller to do so. Not all callers did.
The new pattern matching module performs the whole process in a single
straightforward function call, resulting in shorter, more readable code.
Unfortunately, MSVC does not support C99-style anonymous arrays, so the
pattern must be declared outside of the match call.
2010-11-03 12:47:06 -07:00
|
|
|
s_pattern pat[] = { "call", name, params };
|
2010-12-31 02:03:21 -08:00
|
|
|
if (!MATCH(expr, pat)) {
|
|
|
|
|
ir_read_error(st, expr, "expected (call <name> (<param> ...))");
|
2010-04-28 12:54:21 -07:00
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
exec_list parameters;
|
|
|
|
|
|
|
|
|
|
foreach_iter(exec_list_iterator, it, params->subexpressions) {
|
|
|
|
|
s_expression *expr = (s_expression*) it.get();
|
|
|
|
|
ir_rvalue *param = read_rvalue(st, expr);
|
|
|
|
|
if (param == NULL) {
|
2010-12-31 02:03:21 -08:00
|
|
|
ir_read_error(st, expr, "when reading parameter to function call");
|
2010-04-28 12:54:21 -07:00
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
parameters.push_tail(param);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ir_function *f = st->symbols->get_function(name->value());
|
|
|
|
|
if (f == NULL) {
|
2010-12-31 02:03:21 -08:00
|
|
|
ir_read_error(st, expr, "found call to undefined function %s",
|
2010-04-28 12:54:21 -07:00
|
|
|
name->value());
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2010-07-18 17:45:16 -07:00
|
|
|
ir_function_signature *callee = f->matching_signature(¶meters);
|
2010-04-28 12:54:21 -07:00
|
|
|
if (callee == NULL) {
|
2010-12-31 02:03:21 -08:00
|
|
|
ir_read_error(st, expr, "couldn't find matching signature for function "
|
2010-04-28 12:54:21 -07:00
|
|
|
"%s", name->value());
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2010-06-23 18:11:51 -07:00
|
|
|
return new(ctx) ir_call(callee, ¶meters);
|
2010-04-28 12:54:21 -07:00
|
|
|
}
|
2010-04-07 17:24:44 -07:00
|
|
|
|
|
|
|
|
static ir_expression *
|
2010-12-31 02:03:21 -08:00
|
|
|
read_expression(_mesa_glsl_parse_state *st, s_expression *expr)
|
2010-04-07 17:24:44 -07:00
|
|
|
{
|
2010-06-25 13:14:37 -07:00
|
|
|
void *ctx = st;
|
ir_reader: Add a pattern matching system and use it everywhere.
Previously, the IR reader was riddled with code that:
1. Checked for the right number of list elements (via a linked list walk)
2. Retrieved references to each component (via ->next->next pointers)
3. Downcasted as necessary to make sure that each sub-component was the
right type (i.e. symbol, int, list).
4. Checking that the tag (i.e. "declare") was correct.
This was all very ad-hoc and a bit ugly. Error checking had to be done
at both steps 1, 3, and 4. Most code didn't even check the tag, relying
on the caller to do so. Not all callers did.
The new pattern matching module performs the whole process in a single
straightforward function call, resulting in shorter, more readable code.
Unfortunately, MSVC does not support C99-style anonymous arrays, so the
pattern must be declared outside of the match call.
2010-11-03 12:47:06 -07:00
|
|
|
s_expression *s_type;
|
|
|
|
|
s_symbol *s_op;
|
|
|
|
|
s_expression *s_arg1;
|
|
|
|
|
|
|
|
|
|
s_pattern pat[] = { "expression", s_type, s_op, s_arg1 };
|
2010-12-31 02:03:21 -08:00
|
|
|
if (!PARTIAL_MATCH(expr, pat)) {
|
|
|
|
|
ir_read_error(st, expr, "expected (expression <type> <operator> "
|
2010-04-21 15:47:34 -07:00
|
|
|
"<operand> [<operand>])");
|
2010-04-07 17:24:44 -07:00
|
|
|
return NULL;
|
|
|
|
|
}
|
ir_reader: Add a pattern matching system and use it everywhere.
Previously, the IR reader was riddled with code that:
1. Checked for the right number of list elements (via a linked list walk)
2. Retrieved references to each component (via ->next->next pointers)
3. Downcasted as necessary to make sure that each sub-component was the
right type (i.e. symbol, int, list).
4. Checking that the tag (i.e. "declare") was correct.
This was all very ad-hoc and a bit ugly. Error checking had to be done
at both steps 1, 3, and 4. Most code didn't even check the tag, relying
on the caller to do so. Not all callers did.
The new pattern matching module performs the whole process in a single
straightforward function call, resulting in shorter, more readable code.
Unfortunately, MSVC does not support C99-style anonymous arrays, so the
pattern must be declared outside of the match call.
2010-11-03 12:47:06 -07:00
|
|
|
s_expression *s_arg2 = (s_expression *) s_arg1->next; // may be tail sentinel
|
2010-04-07 17:24:44 -07:00
|
|
|
|
ir_reader: Add a pattern matching system and use it everywhere.
Previously, the IR reader was riddled with code that:
1. Checked for the right number of list elements (via a linked list walk)
2. Retrieved references to each component (via ->next->next pointers)
3. Downcasted as necessary to make sure that each sub-component was the
right type (i.e. symbol, int, list).
4. Checking that the tag (i.e. "declare") was correct.
This was all very ad-hoc and a bit ugly. Error checking had to be done
at both steps 1, 3, and 4. Most code didn't even check the tag, relying
on the caller to do so. Not all callers did.
The new pattern matching module performs the whole process in a single
straightforward function call, resulting in shorter, more readable code.
Unfortunately, MSVC does not support C99-style anonymous arrays, so the
pattern must be declared outside of the match call.
2010-11-03 12:47:06 -07:00
|
|
|
const glsl_type *type = read_type(st, s_type);
|
2010-04-07 17:24:44 -07:00
|
|
|
if (type == NULL)
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
/* Read the operator */
|
ir_reader: Add a pattern matching system and use it everywhere.
Previously, the IR reader was riddled with code that:
1. Checked for the right number of list elements (via a linked list walk)
2. Retrieved references to each component (via ->next->next pointers)
3. Downcasted as necessary to make sure that each sub-component was the
right type (i.e. symbol, int, list).
4. Checking that the tag (i.e. "declare") was correct.
This was all very ad-hoc and a bit ugly. Error checking had to be done
at both steps 1, 3, and 4. Most code didn't even check the tag, relying
on the caller to do so. Not all callers did.
The new pattern matching module performs the whole process in a single
straightforward function call, resulting in shorter, more readable code.
Unfortunately, MSVC does not support C99-style anonymous arrays, so the
pattern must be declared outside of the match call.
2010-11-03 12:47:06 -07:00
|
|
|
ir_expression_operation op = ir_expression::get_operator(s_op->value());
|
2010-04-07 17:24:44 -07:00
|
|
|
if (op == (ir_expression_operation) -1) {
|
2010-12-31 02:03:21 -08:00
|
|
|
ir_read_error(st, expr, "invalid operator: %s", s_op->value());
|
2010-04-07 17:24:44 -07:00
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
ir_reader: Add a pattern matching system and use it everywhere.
Previously, the IR reader was riddled with code that:
1. Checked for the right number of list elements (via a linked list walk)
2. Retrieved references to each component (via ->next->next pointers)
3. Downcasted as necessary to make sure that each sub-component was the
right type (i.e. symbol, int, list).
4. Checking that the tag (i.e. "declare") was correct.
This was all very ad-hoc and a bit ugly. Error checking had to be done
at both steps 1, 3, and 4. Most code didn't even check the tag, relying
on the caller to do so. Not all callers did.
The new pattern matching module performs the whole process in a single
straightforward function call, resulting in shorter, more readable code.
Unfortunately, MSVC does not support C99-style anonymous arrays, so the
pattern must be declared outside of the match call.
2010-11-03 12:47:06 -07:00
|
|
|
unsigned num_operands = ir_expression::get_num_operands(op);
|
|
|
|
|
if (num_operands == 1 && !s_arg1->next->is_tail_sentinel()) {
|
2010-12-31 02:03:21 -08:00
|
|
|
ir_read_error(st, expr, "expected (expression <type> %s <operand>)",
|
ir_reader: Add a pattern matching system and use it everywhere.
Previously, the IR reader was riddled with code that:
1. Checked for the right number of list elements (via a linked list walk)
2. Retrieved references to each component (via ->next->next pointers)
3. Downcasted as necessary to make sure that each sub-component was the
right type (i.e. symbol, int, list).
4. Checking that the tag (i.e. "declare") was correct.
This was all very ad-hoc and a bit ugly. Error checking had to be done
at both steps 1, 3, and 4. Most code didn't even check the tag, relying
on the caller to do so. Not all callers did.
The new pattern matching module performs the whole process in a single
straightforward function call, resulting in shorter, more readable code.
Unfortunately, MSVC does not support C99-style anonymous arrays, so the
pattern must be declared outside of the match call.
2010-11-03 12:47:06 -07:00
|
|
|
s_op->value());
|
|
|
|
|
return NULL;
|
2010-04-07 17:24:44 -07:00
|
|
|
}
|
|
|
|
|
|
ir_reader: Add a pattern matching system and use it everywhere.
Previously, the IR reader was riddled with code that:
1. Checked for the right number of list elements (via a linked list walk)
2. Retrieved references to each component (via ->next->next pointers)
3. Downcasted as necessary to make sure that each sub-component was the
right type (i.e. symbol, int, list).
4. Checking that the tag (i.e. "declare") was correct.
This was all very ad-hoc and a bit ugly. Error checking had to be done
at both steps 1, 3, and 4. Most code didn't even check the tag, relying
on the caller to do so. Not all callers did.
The new pattern matching module performs the whole process in a single
straightforward function call, resulting in shorter, more readable code.
Unfortunately, MSVC does not support C99-style anonymous arrays, so the
pattern must be declared outside of the match call.
2010-11-03 12:47:06 -07:00
|
|
|
ir_rvalue *arg1 = read_rvalue(st, s_arg1);
|
|
|
|
|
ir_rvalue *arg2 = NULL;
|
2010-04-07 17:24:44 -07:00
|
|
|
if (arg1 == NULL) {
|
2010-04-21 23:23:23 -07:00
|
|
|
ir_read_error(st, NULL, "when reading first operand of %s",
|
ir_reader: Add a pattern matching system and use it everywhere.
Previously, the IR reader was riddled with code that:
1. Checked for the right number of list elements (via a linked list walk)
2. Retrieved references to each component (via ->next->next pointers)
3. Downcasted as necessary to make sure that each sub-component was the
right type (i.e. symbol, int, list).
4. Checking that the tag (i.e. "declare") was correct.
This was all very ad-hoc and a bit ugly. Error checking had to be done
at both steps 1, 3, and 4. Most code didn't even check the tag, relying
on the caller to do so. Not all callers did.
The new pattern matching module performs the whole process in a single
straightforward function call, resulting in shorter, more readable code.
Unfortunately, MSVC does not support C99-style anonymous arrays, so the
pattern must be declared outside of the match call.
2010-11-03 12:47:06 -07:00
|
|
|
s_op->value());
|
2010-04-07 17:24:44 -07:00
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
ir_reader: Add a pattern matching system and use it everywhere.
Previously, the IR reader was riddled with code that:
1. Checked for the right number of list elements (via a linked list walk)
2. Retrieved references to each component (via ->next->next pointers)
3. Downcasted as necessary to make sure that each sub-component was the
right type (i.e. symbol, int, list).
4. Checking that the tag (i.e. "declare") was correct.
This was all very ad-hoc and a bit ugly. Error checking had to be done
at both steps 1, 3, and 4. Most code didn't even check the tag, relying
on the caller to do so. Not all callers did.
The new pattern matching module performs the whole process in a single
straightforward function call, resulting in shorter, more readable code.
Unfortunately, MSVC does not support C99-style anonymous arrays, so the
pattern must be declared outside of the match call.
2010-11-03 12:47:06 -07:00
|
|
|
if (num_operands == 2) {
|
|
|
|
|
if (s_arg2->is_tail_sentinel() || !s_arg2->next->is_tail_sentinel()) {
|
2010-12-31 02:03:21 -08:00
|
|
|
ir_read_error(st, expr, "expected (expression <type> %s <operand> "
|
ir_reader: Add a pattern matching system and use it everywhere.
Previously, the IR reader was riddled with code that:
1. Checked for the right number of list elements (via a linked list walk)
2. Retrieved references to each component (via ->next->next pointers)
3. Downcasted as necessary to make sure that each sub-component was the
right type (i.e. symbol, int, list).
4. Checking that the tag (i.e. "declare") was correct.
This was all very ad-hoc and a bit ugly. Error checking had to be done
at both steps 1, 3, and 4. Most code didn't even check the tag, relying
on the caller to do so. Not all callers did.
The new pattern matching module performs the whole process in a single
straightforward function call, resulting in shorter, more readable code.
Unfortunately, MSVC does not support C99-style anonymous arrays, so the
pattern must be declared outside of the match call.
2010-11-03 12:47:06 -07:00
|
|
|
"<operand>)", s_op->value());
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
arg2 = read_rvalue(st, s_arg2);
|
2010-04-07 17:24:44 -07:00
|
|
|
if (arg2 == NULL) {
|
2010-04-21 23:23:23 -07:00
|
|
|
ir_read_error(st, NULL, "when reading second operand of %s",
|
ir_reader: Add a pattern matching system and use it everywhere.
Previously, the IR reader was riddled with code that:
1. Checked for the right number of list elements (via a linked list walk)
2. Retrieved references to each component (via ->next->next pointers)
3. Downcasted as necessary to make sure that each sub-component was the
right type (i.e. symbol, int, list).
4. Checking that the tag (i.e. "declare") was correct.
This was all very ad-hoc and a bit ugly. Error checking had to be done
at both steps 1, 3, and 4. Most code didn't even check the tag, relying
on the caller to do so. Not all callers did.
The new pattern matching module performs the whole process in a single
straightforward function call, resulting in shorter, more readable code.
Unfortunately, MSVC does not support C99-style anonymous arrays, so the
pattern must be declared outside of the match call.
2010-11-03 12:47:06 -07:00
|
|
|
s_op->value());
|
2010-04-07 17:24:44 -07:00
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2010-06-23 18:11:51 -07:00
|
|
|
return new(ctx) ir_expression(op, type, arg1, arg2);
|
2010-04-07 17:24:44 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static ir_swizzle *
|
2010-12-31 02:03:21 -08:00
|
|
|
read_swizzle(_mesa_glsl_parse_state *st, s_expression *expr)
|
2010-04-07 17:24:44 -07:00
|
|
|
{
|
ir_reader: Add a pattern matching system and use it everywhere.
Previously, the IR reader was riddled with code that:
1. Checked for the right number of list elements (via a linked list walk)
2. Retrieved references to each component (via ->next->next pointers)
3. Downcasted as necessary to make sure that each sub-component was the
right type (i.e. symbol, int, list).
4. Checking that the tag (i.e. "declare") was correct.
This was all very ad-hoc and a bit ugly. Error checking had to be done
at both steps 1, 3, and 4. Most code didn't even check the tag, relying
on the caller to do so. Not all callers did.
The new pattern matching module performs the whole process in a single
straightforward function call, resulting in shorter, more readable code.
Unfortunately, MSVC does not support C99-style anonymous arrays, so the
pattern must be declared outside of the match call.
2010-11-03 12:47:06 -07:00
|
|
|
s_symbol *swiz;
|
|
|
|
|
s_expression *sub;
|
2010-04-07 17:24:44 -07:00
|
|
|
|
ir_reader: Add a pattern matching system and use it everywhere.
Previously, the IR reader was riddled with code that:
1. Checked for the right number of list elements (via a linked list walk)
2. Retrieved references to each component (via ->next->next pointers)
3. Downcasted as necessary to make sure that each sub-component was the
right type (i.e. symbol, int, list).
4. Checking that the tag (i.e. "declare") was correct.
This was all very ad-hoc and a bit ugly. Error checking had to be done
at both steps 1, 3, and 4. Most code didn't even check the tag, relying
on the caller to do so. Not all callers did.
The new pattern matching module performs the whole process in a single
straightforward function call, resulting in shorter, more readable code.
Unfortunately, MSVC does not support C99-style anonymous arrays, so the
pattern must be declared outside of the match call.
2010-11-03 12:47:06 -07:00
|
|
|
s_pattern pat[] = { "swiz", swiz, sub };
|
2010-12-31 02:03:21 -08:00
|
|
|
if (!MATCH(expr, pat)) {
|
|
|
|
|
ir_read_error(st, expr, "expected (swiz <swizzle> <rvalue>)");
|
2010-04-07 17:24:44 -07:00
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2010-04-21 23:15:08 -07:00
|
|
|
if (strlen(swiz->value()) > 4) {
|
2010-12-31 02:03:21 -08:00
|
|
|
ir_read_error(st, expr, "expected a valid swizzle; found %s",
|
2010-04-21 15:47:34 -07:00
|
|
|
swiz->value());
|
2010-04-07 17:24:44 -07:00
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ir_rvalue *rvalue = read_rvalue(st, sub);
|
|
|
|
|
if (rvalue == NULL)
|
|
|
|
|
return NULL;
|
|
|
|
|
|
2010-04-28 13:16:31 -07:00
|
|
|
ir_swizzle *ir = ir_swizzle::create(rvalue, swiz->value(),
|
|
|
|
|
rvalue->type->vector_elements);
|
|
|
|
|
if (ir == NULL)
|
2010-12-31 02:03:21 -08:00
|
|
|
ir_read_error(st, expr, "invalid swizzle");
|
2010-04-28 13:16:31 -07:00
|
|
|
|
|
|
|
|
return ir;
|
2010-04-07 17:24:44 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static ir_constant *
|
2010-12-31 02:03:21 -08:00
|
|
|
read_constant(_mesa_glsl_parse_state *st, s_expression *expr)
|
2010-04-07 17:24:44 -07:00
|
|
|
{
|
2010-06-25 13:14:37 -07:00
|
|
|
void *ctx = st;
|
ir_reader: Add a pattern matching system and use it everywhere.
Previously, the IR reader was riddled with code that:
1. Checked for the right number of list elements (via a linked list walk)
2. Retrieved references to each component (via ->next->next pointers)
3. Downcasted as necessary to make sure that each sub-component was the
right type (i.e. symbol, int, list).
4. Checking that the tag (i.e. "declare") was correct.
This was all very ad-hoc and a bit ugly. Error checking had to be done
at both steps 1, 3, and 4. Most code didn't even check the tag, relying
on the caller to do so. Not all callers did.
The new pattern matching module performs the whole process in a single
straightforward function call, resulting in shorter, more readable code.
Unfortunately, MSVC does not support C99-style anonymous arrays, so the
pattern must be declared outside of the match call.
2010-11-03 12:47:06 -07:00
|
|
|
s_expression *type_expr;
|
|
|
|
|
s_list *values;
|
|
|
|
|
|
|
|
|
|
s_pattern pat[] = { "constant", type_expr, values };
|
2010-12-31 02:03:21 -08:00
|
|
|
if (!MATCH(expr, pat)) {
|
|
|
|
|
ir_read_error(st, expr, "expected (constant <type> (...))");
|
2010-04-07 17:24:44 -07:00
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2010-04-10 01:06:44 -07:00
|
|
|
const glsl_type *type = read_type(st, type_expr);
|
2010-04-07 17:24:44 -07:00
|
|
|
if (type == NULL)
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
if (values == NULL) {
|
2010-12-31 02:03:21 -08:00
|
|
|
ir_read_error(st, expr, "expected (constant <type> (...))");
|
2010-04-07 17:24:44 -07:00
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2010-07-20 01:53:07 -07:00
|
|
|
if (type->is_array()) {
|
2010-12-31 01:48:02 -08:00
|
|
|
unsigned elements_supplied = 0;
|
2010-07-20 01:53:07 -07:00
|
|
|
exec_list elements;
|
|
|
|
|
foreach_iter(exec_list_iterator, it, values->subexpressions) {
|
2010-12-31 02:03:21 -08:00
|
|
|
s_expression *elt = (s_expression *) it.get();
|
2010-07-20 01:53:07 -07:00
|
|
|
ir_constant *ir_elt = read_constant(st, elt);
|
|
|
|
|
if (ir_elt == NULL)
|
|
|
|
|
return NULL;
|
|
|
|
|
elements.push_tail(ir_elt);
|
2010-12-31 01:48:02 -08:00
|
|
|
elements_supplied++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (elements_supplied != type->length) {
|
|
|
|
|
ir_read_error(st, values, "expected exactly %u array elements, "
|
|
|
|
|
"given %u", type->length, elements_supplied);
|
|
|
|
|
return NULL;
|
2010-07-20 01:53:07 -07:00
|
|
|
}
|
|
|
|
|
return new(ctx) ir_constant(type, &elements);
|
|
|
|
|
}
|
|
|
|
|
|
2010-04-07 17:24:44 -07:00
|
|
|
const glsl_type *const base_type = type->get_base_type();
|
|
|
|
|
|
2010-08-29 11:48:02 -07:00
|
|
|
ir_constant_data data = { { 0 } };
|
2010-04-07 17:24:44 -07:00
|
|
|
|
|
|
|
|
// Read in list of values (at most 16).
|
|
|
|
|
int k = 0;
|
|
|
|
|
foreach_iter(exec_list_iterator, it, values->subexpressions) {
|
|
|
|
|
if (k >= 16) {
|
2010-04-21 15:47:34 -07:00
|
|
|
ir_read_error(st, values, "expected at most 16 numbers");
|
2010-04-07 17:24:44 -07:00
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s_expression *expr = (s_expression*) it.get();
|
|
|
|
|
|
|
|
|
|
if (base_type->base_type == GLSL_TYPE_FLOAT) {
|
|
|
|
|
s_number *value = SX_AS_NUMBER(expr);
|
|
|
|
|
if (value == NULL) {
|
2010-04-21 15:47:34 -07:00
|
|
|
ir_read_error(st, values, "expected numbers");
|
2010-04-07 17:24:44 -07:00
|
|
|
return NULL;
|
|
|
|
|
}
|
2010-06-11 16:43:42 -07:00
|
|
|
data.f[k] = value->fvalue();
|
2010-04-07 17:24:44 -07:00
|
|
|
} else {
|
|
|
|
|
s_int *value = SX_AS_INT(expr);
|
|
|
|
|
if (value == NULL) {
|
2010-04-21 15:47:34 -07:00
|
|
|
ir_read_error(st, values, "expected integers");
|
2010-04-07 17:24:44 -07:00
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch (base_type->base_type) {
|
|
|
|
|
case GLSL_TYPE_UINT: {
|
2010-06-11 16:43:42 -07:00
|
|
|
data.u[k] = value->value();
|
2010-04-07 17:24:44 -07:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case GLSL_TYPE_INT: {
|
2010-06-11 16:43:42 -07:00
|
|
|
data.i[k] = value->value();
|
2010-04-07 17:24:44 -07:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case GLSL_TYPE_BOOL: {
|
2010-06-11 16:43:42 -07:00
|
|
|
data.b[k] = value->value();
|
2010-04-07 17:24:44 -07:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
default:
|
2010-04-21 15:47:34 -07:00
|
|
|
ir_read_error(st, values, "unsupported constant type");
|
2010-04-07 17:24:44 -07:00
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
++k;
|
|
|
|
|
}
|
2010-06-11 16:43:42 -07:00
|
|
|
|
2010-06-23 18:11:51 -07:00
|
|
|
return new(ctx) ir_constant(type, &data);
|
2010-04-07 17:24:44 -07:00
|
|
|
}
|
2010-04-12 14:27:39 -07:00
|
|
|
|
2010-05-26 17:52:44 -07:00
|
|
|
static ir_dereference *
|
|
|
|
|
read_dereference(_mesa_glsl_parse_state *st, s_expression *expr)
|
|
|
|
|
{
|
|
|
|
|
s_list *list = SX_AS_LIST(expr);
|
|
|
|
|
if (list == NULL || list->subexpressions.is_empty())
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
s_symbol *tag = SX_AS_SYMBOL(list->subexpressions.head);
|
|
|
|
|
assert(tag != NULL);
|
|
|
|
|
|
|
|
|
|
if (strcmp(tag->value(), "var_ref") == 0)
|
|
|
|
|
return read_var_ref(st, list);
|
|
|
|
|
if (strcmp(tag->value(), "array_ref") == 0)
|
|
|
|
|
return read_array_ref(st, list);
|
|
|
|
|
if (strcmp(tag->value(), "record_ref") == 0)
|
|
|
|
|
return read_record_ref(st, list);
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2010-10-30 22:29:07 -07:00
|
|
|
static ir_dereference_variable *
|
2010-12-31 02:03:21 -08:00
|
|
|
read_var_ref(_mesa_glsl_parse_state *st, s_expression *expr)
|
2010-04-12 14:27:39 -07:00
|
|
|
{
|
2010-06-25 13:14:37 -07:00
|
|
|
void *ctx = st;
|
ir_reader: Add a pattern matching system and use it everywhere.
Previously, the IR reader was riddled with code that:
1. Checked for the right number of list elements (via a linked list walk)
2. Retrieved references to each component (via ->next->next pointers)
3. Downcasted as necessary to make sure that each sub-component was the
right type (i.e. symbol, int, list).
4. Checking that the tag (i.e. "declare") was correct.
This was all very ad-hoc and a bit ugly. Error checking had to be done
at both steps 1, 3, and 4. Most code didn't even check the tag, relying
on the caller to do so. Not all callers did.
The new pattern matching module performs the whole process in a single
straightforward function call, resulting in shorter, more readable code.
Unfortunately, MSVC does not support C99-style anonymous arrays, so the
pattern must be declared outside of the match call.
2010-11-03 12:47:06 -07:00
|
|
|
s_symbol *var_name;
|
|
|
|
|
|
|
|
|
|
s_pattern pat[] = { "var_ref", var_name };
|
2010-12-31 02:03:21 -08:00
|
|
|
if (!MATCH(expr, pat)) {
|
|
|
|
|
ir_read_error(st, expr, "expected (var_ref <variable name>)");
|
2010-05-26 13:03:14 -07:00
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ir_variable *var = st->symbols->get_variable(var_name->value());
|
|
|
|
|
if (var == NULL) {
|
2010-12-31 02:03:21 -08:00
|
|
|
ir_read_error(st, expr, "undeclared variable: %s", var_name->value());
|
2010-04-12 14:27:39 -07:00
|
|
|
return NULL;
|
2010-05-26 13:03:14 -07:00
|
|
|
}
|
|
|
|
|
|
2010-06-23 18:11:51 -07:00
|
|
|
return new(ctx) ir_dereference_variable(var);
|
2010-04-12 14:27:39 -07:00
|
|
|
}
|
|
|
|
|
|
2010-10-30 22:29:07 -07:00
|
|
|
static ir_dereference_array *
|
2010-12-31 02:03:21 -08:00
|
|
|
read_array_ref(_mesa_glsl_parse_state *st, s_expression *expr)
|
2010-04-12 14:27:39 -07:00
|
|
|
{
|
2010-06-25 13:14:37 -07:00
|
|
|
void *ctx = st;
|
ir_reader: Add a pattern matching system and use it everywhere.
Previously, the IR reader was riddled with code that:
1. Checked for the right number of list elements (via a linked list walk)
2. Retrieved references to each component (via ->next->next pointers)
3. Downcasted as necessary to make sure that each sub-component was the
right type (i.e. symbol, int, list).
4. Checking that the tag (i.e. "declare") was correct.
This was all very ad-hoc and a bit ugly. Error checking had to be done
at both steps 1, 3, and 4. Most code didn't even check the tag, relying
on the caller to do so. Not all callers did.
The new pattern matching module performs the whole process in a single
straightforward function call, resulting in shorter, more readable code.
Unfortunately, MSVC does not support C99-style anonymous arrays, so the
pattern must be declared outside of the match call.
2010-11-03 12:47:06 -07:00
|
|
|
s_expression *subj_expr;
|
|
|
|
|
s_expression *idx_expr;
|
|
|
|
|
|
|
|
|
|
s_pattern pat[] = { "array_ref", subj_expr, idx_expr };
|
2010-12-31 02:03:21 -08:00
|
|
|
if (!MATCH(expr, pat)) {
|
|
|
|
|
ir_read_error(st, expr, "expected (array_ref <rvalue> <index>)");
|
2010-04-12 14:27:39 -07:00
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2010-05-26 13:03:14 -07:00
|
|
|
ir_rvalue *subject = read_rvalue(st, subj_expr);
|
|
|
|
|
if (subject == NULL) {
|
|
|
|
|
ir_read_error(st, NULL, "when reading the subject of an array_ref");
|
2010-04-12 14:27:39 -07:00
|
|
|
return NULL;
|
2010-05-26 13:03:14 -07:00
|
|
|
}
|
2010-04-12 14:27:39 -07:00
|
|
|
|
|
|
|
|
ir_rvalue *idx = read_rvalue(st, idx_expr);
|
2010-06-23 18:11:51 -07:00
|
|
|
return new(ctx) ir_dereference_array(subject, idx);
|
2010-04-12 14:27:39 -07:00
|
|
|
}
|
|
|
|
|
|
2010-10-30 22:29:07 -07:00
|
|
|
static ir_dereference_record *
|
2010-12-31 02:03:21 -08:00
|
|
|
read_record_ref(_mesa_glsl_parse_state *st, s_expression *expr)
|
2010-04-12 14:27:39 -07:00
|
|
|
{
|
2010-06-25 13:14:37 -07:00
|
|
|
void *ctx = st;
|
ir_reader: Add a pattern matching system and use it everywhere.
Previously, the IR reader was riddled with code that:
1. Checked for the right number of list elements (via a linked list walk)
2. Retrieved references to each component (via ->next->next pointers)
3. Downcasted as necessary to make sure that each sub-component was the
right type (i.e. symbol, int, list).
4. Checking that the tag (i.e. "declare") was correct.
This was all very ad-hoc and a bit ugly. Error checking had to be done
at both steps 1, 3, and 4. Most code didn't even check the tag, relying
on the caller to do so. Not all callers did.
The new pattern matching module performs the whole process in a single
straightforward function call, resulting in shorter, more readable code.
Unfortunately, MSVC does not support C99-style anonymous arrays, so the
pattern must be declared outside of the match call.
2010-11-03 12:47:06 -07:00
|
|
|
s_expression *subj_expr;
|
|
|
|
|
s_symbol *field;
|
|
|
|
|
|
|
|
|
|
s_pattern pat[] = { "record_ref", subj_expr, field };
|
2010-12-31 02:03:21 -08:00
|
|
|
if (!MATCH(expr, pat)) {
|
|
|
|
|
ir_read_error(st, expr, "expected (record_ref <rvalue> <field>)");
|
2010-05-26 15:20:59 -07:00
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ir_rvalue *subject = read_rvalue(st, subj_expr);
|
|
|
|
|
if (subject == NULL) {
|
|
|
|
|
ir_read_error(st, NULL, "when reading the subject of a record_ref");
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
2010-06-23 18:11:51 -07:00
|
|
|
return new(ctx) ir_dereference_record(subject, field->value());
|
2010-04-12 14:27:39 -07:00
|
|
|
}
|
2010-05-26 17:55:10 -07:00
|
|
|
|
|
|
|
|
static ir_texture *
|
2010-12-31 02:03:21 -08:00
|
|
|
read_texture(_mesa_glsl_parse_state *st, s_expression *expr)
|
2010-05-26 17:55:10 -07:00
|
|
|
{
|
ir_reader: Add a pattern matching system and use it everywhere.
Previously, the IR reader was riddled with code that:
1. Checked for the right number of list elements (via a linked list walk)
2. Retrieved references to each component (via ->next->next pointers)
3. Downcasted as necessary to make sure that each sub-component was the
right type (i.e. symbol, int, list).
4. Checking that the tag (i.e. "declare") was correct.
This was all very ad-hoc and a bit ugly. Error checking had to be done
at both steps 1, 3, and 4. Most code didn't even check the tag, relying
on the caller to do so. Not all callers did.
The new pattern matching module performs the whole process in a single
straightforward function call, resulting in shorter, more readable code.
Unfortunately, MSVC does not support C99-style anonymous arrays, so the
pattern must be declared outside of the match call.
2010-11-03 12:47:06 -07:00
|
|
|
s_symbol *tag = NULL;
|
|
|
|
|
s_expression *s_sampler = NULL;
|
|
|
|
|
s_expression *s_coord = NULL;
|
|
|
|
|
s_list *s_offset = NULL;
|
|
|
|
|
s_expression *s_proj = NULL;
|
|
|
|
|
s_list *s_shadow = NULL;
|
|
|
|
|
s_expression *s_lod = NULL;
|
|
|
|
|
|
|
|
|
|
ir_texture_opcode op;
|
|
|
|
|
|
|
|
|
|
s_pattern tex_pattern[] =
|
|
|
|
|
{ "tex", s_sampler, s_coord, s_offset, s_proj, s_shadow };
|
|
|
|
|
s_pattern txf_pattern[] =
|
|
|
|
|
{ "txf", s_sampler, s_coord, s_offset, s_lod };
|
|
|
|
|
s_pattern other_pattern[] =
|
|
|
|
|
{ tag, s_sampler, s_coord, s_offset, s_proj, s_shadow, s_lod };
|
|
|
|
|
|
2010-12-31 02:03:21 -08:00
|
|
|
if (MATCH(expr, tex_pattern)) {
|
ir_reader: Add a pattern matching system and use it everywhere.
Previously, the IR reader was riddled with code that:
1. Checked for the right number of list elements (via a linked list walk)
2. Retrieved references to each component (via ->next->next pointers)
3. Downcasted as necessary to make sure that each sub-component was the
right type (i.e. symbol, int, list).
4. Checking that the tag (i.e. "declare") was correct.
This was all very ad-hoc and a bit ugly. Error checking had to be done
at both steps 1, 3, and 4. Most code didn't even check the tag, relying
on the caller to do so. Not all callers did.
The new pattern matching module performs the whole process in a single
straightforward function call, resulting in shorter, more readable code.
Unfortunately, MSVC does not support C99-style anonymous arrays, so the
pattern must be declared outside of the match call.
2010-11-03 12:47:06 -07:00
|
|
|
op = ir_tex;
|
2010-12-31 02:03:21 -08:00
|
|
|
} else if (MATCH(expr, txf_pattern)) {
|
ir_reader: Add a pattern matching system and use it everywhere.
Previously, the IR reader was riddled with code that:
1. Checked for the right number of list elements (via a linked list walk)
2. Retrieved references to each component (via ->next->next pointers)
3. Downcasted as necessary to make sure that each sub-component was the
right type (i.e. symbol, int, list).
4. Checking that the tag (i.e. "declare") was correct.
This was all very ad-hoc and a bit ugly. Error checking had to be done
at both steps 1, 3, and 4. Most code didn't even check the tag, relying
on the caller to do so. Not all callers did.
The new pattern matching module performs the whole process in a single
straightforward function call, resulting in shorter, more readable code.
Unfortunately, MSVC does not support C99-style anonymous arrays, so the
pattern must be declared outside of the match call.
2010-11-03 12:47:06 -07:00
|
|
|
op = ir_txf;
|
2010-12-31 02:03:21 -08:00
|
|
|
} else if (MATCH(expr, other_pattern)) {
|
ir_reader: Add a pattern matching system and use it everywhere.
Previously, the IR reader was riddled with code that:
1. Checked for the right number of list elements (via a linked list walk)
2. Retrieved references to each component (via ->next->next pointers)
3. Downcasted as necessary to make sure that each sub-component was the
right type (i.e. symbol, int, list).
4. Checking that the tag (i.e. "declare") was correct.
This was all very ad-hoc and a bit ugly. Error checking had to be done
at both steps 1, 3, and 4. Most code didn't even check the tag, relying
on the caller to do so. Not all callers did.
The new pattern matching module performs the whole process in a single
straightforward function call, resulting in shorter, more readable code.
Unfortunately, MSVC does not support C99-style anonymous arrays, so the
pattern must be declared outside of the match call.
2010-11-03 12:47:06 -07:00
|
|
|
op = ir_texture::get_opcode(tag->value());
|
|
|
|
|
if (op == -1)
|
|
|
|
|
return NULL;
|
2010-05-26 17:55:10 -07:00
|
|
|
}
|
|
|
|
|
|
ir_reader: Add a pattern matching system and use it everywhere.
Previously, the IR reader was riddled with code that:
1. Checked for the right number of list elements (via a linked list walk)
2. Retrieved references to each component (via ->next->next pointers)
3. Downcasted as necessary to make sure that each sub-component was the
right type (i.e. symbol, int, list).
4. Checking that the tag (i.e. "declare") was correct.
This was all very ad-hoc and a bit ugly. Error checking had to be done
at both steps 1, 3, and 4. Most code didn't even check the tag, relying
on the caller to do so. Not all callers did.
The new pattern matching module performs the whole process in a single
straightforward function call, resulting in shorter, more readable code.
Unfortunately, MSVC does not support C99-style anonymous arrays, so the
pattern must be declared outside of the match call.
2010-11-03 12:47:06 -07:00
|
|
|
ir_texture *tex = new(st) ir_texture(op);
|
2010-05-26 17:55:10 -07:00
|
|
|
|
|
|
|
|
// Read sampler (must be a deref)
|
ir_reader: Add a pattern matching system and use it everywhere.
Previously, the IR reader was riddled with code that:
1. Checked for the right number of list elements (via a linked list walk)
2. Retrieved references to each component (via ->next->next pointers)
3. Downcasted as necessary to make sure that each sub-component was the
right type (i.e. symbol, int, list).
4. Checking that the tag (i.e. "declare") was correct.
This was all very ad-hoc and a bit ugly. Error checking had to be done
at both steps 1, 3, and 4. Most code didn't even check the tag, relying
on the caller to do so. Not all callers did.
The new pattern matching module performs the whole process in a single
straightforward function call, resulting in shorter, more readable code.
Unfortunately, MSVC does not support C99-style anonymous arrays, so the
pattern must be declared outside of the match call.
2010-11-03 12:47:06 -07:00
|
|
|
ir_dereference *sampler = read_dereference(st, s_sampler);
|
2010-06-03 15:07:34 -07:00
|
|
|
if (sampler == NULL) {
|
ir_reader: Add a pattern matching system and use it everywhere.
Previously, the IR reader was riddled with code that:
1. Checked for the right number of list elements (via a linked list walk)
2. Retrieved references to each component (via ->next->next pointers)
3. Downcasted as necessary to make sure that each sub-component was the
right type (i.e. symbol, int, list).
4. Checking that the tag (i.e. "declare") was correct.
This was all very ad-hoc and a bit ugly. Error checking had to be done
at both steps 1, 3, and 4. Most code didn't even check the tag, relying
on the caller to do so. Not all callers did.
The new pattern matching module performs the whole process in a single
straightforward function call, resulting in shorter, more readable code.
Unfortunately, MSVC does not support C99-style anonymous arrays, so the
pattern must be declared outside of the match call.
2010-11-03 12:47:06 -07:00
|
|
|
ir_read_error(st, NULL, "when reading sampler in (%s ...)",
|
|
|
|
|
tex->opcode_string());
|
2010-05-26 17:55:10 -07:00
|
|
|
return NULL;
|
|
|
|
|
}
|
2010-06-03 15:07:34 -07:00
|
|
|
tex->set_sampler(sampler);
|
2010-05-26 17:55:10 -07:00
|
|
|
|
|
|
|
|
// Read coordinate (any rvalue)
|
ir_reader: Add a pattern matching system and use it everywhere.
Previously, the IR reader was riddled with code that:
1. Checked for the right number of list elements (via a linked list walk)
2. Retrieved references to each component (via ->next->next pointers)
3. Downcasted as necessary to make sure that each sub-component was the
right type (i.e. symbol, int, list).
4. Checking that the tag (i.e. "declare") was correct.
This was all very ad-hoc and a bit ugly. Error checking had to be done
at both steps 1, 3, and 4. Most code didn't even check the tag, relying
on the caller to do so. Not all callers did.
The new pattern matching module performs the whole process in a single
straightforward function call, resulting in shorter, more readable code.
Unfortunately, MSVC does not support C99-style anonymous arrays, so the
pattern must be declared outside of the match call.
2010-11-03 12:47:06 -07:00
|
|
|
tex->coordinate = read_rvalue(st, s_coord);
|
2010-05-26 17:55:10 -07:00
|
|
|
if (tex->coordinate == NULL) {
|
|
|
|
|
ir_read_error(st, NULL, "when reading coordinate in (%s ...)",
|
ir_reader: Add a pattern matching system and use it everywhere.
Previously, the IR reader was riddled with code that:
1. Checked for the right number of list elements (via a linked list walk)
2. Retrieved references to each component (via ->next->next pointers)
3. Downcasted as necessary to make sure that each sub-component was the
right type (i.e. symbol, int, list).
4. Checking that the tag (i.e. "declare") was correct.
This was all very ad-hoc and a bit ugly. Error checking had to be done
at both steps 1, 3, and 4. Most code didn't even check the tag, relying
on the caller to do so. Not all callers did.
The new pattern matching module performs the whole process in a single
straightforward function call, resulting in shorter, more readable code.
Unfortunately, MSVC does not support C99-style anonymous arrays, so the
pattern must be declared outside of the match call.
2010-11-03 12:47:06 -07:00
|
|
|
tex->opcode_string());
|
2010-05-26 17:55:10 -07:00
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Read texel offset, i.e. (0 0 0)
|
ir_reader: Add a pattern matching system and use it everywhere.
Previously, the IR reader was riddled with code that:
1. Checked for the right number of list elements (via a linked list walk)
2. Retrieved references to each component (via ->next->next pointers)
3. Downcasted as necessary to make sure that each sub-component was the
right type (i.e. symbol, int, list).
4. Checking that the tag (i.e. "declare") was correct.
This was all very ad-hoc and a bit ugly. Error checking had to be done
at both steps 1, 3, and 4. Most code didn't even check the tag, relying
on the caller to do so. Not all callers did.
The new pattern matching module performs the whole process in a single
straightforward function call, resulting in shorter, more readable code.
Unfortunately, MSVC does not support C99-style anonymous arrays, so the
pattern must be declared outside of the match call.
2010-11-03 12:47:06 -07:00
|
|
|
s_int *offset_x;
|
|
|
|
|
s_int *offset_y;
|
|
|
|
|
s_int *offset_z;
|
|
|
|
|
s_pattern offset_pat[] = { offset_x, offset_y, offset_z };
|
|
|
|
|
if (!MATCH(s_offset, offset_pat)) {
|
|
|
|
|
ir_read_error(st, s_offset, "expected (<int> <int> <int>)");
|
2010-05-26 17:55:10 -07:00
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
tex->offsets[0] = offset_x->value();
|
|
|
|
|
tex->offsets[1] = offset_y->value();
|
|
|
|
|
tex->offsets[2] = offset_z->value();
|
|
|
|
|
|
ir_reader: Add a pattern matching system and use it everywhere.
Previously, the IR reader was riddled with code that:
1. Checked for the right number of list elements (via a linked list walk)
2. Retrieved references to each component (via ->next->next pointers)
3. Downcasted as necessary to make sure that each sub-component was the
right type (i.e. symbol, int, list).
4. Checking that the tag (i.e. "declare") was correct.
This was all very ad-hoc and a bit ugly. Error checking had to be done
at both steps 1, 3, and 4. Most code didn't even check the tag, relying
on the caller to do so. Not all callers did.
The new pattern matching module performs the whole process in a single
straightforward function call, resulting in shorter, more readable code.
Unfortunately, MSVC does not support C99-style anonymous arrays, so the
pattern must be declared outside of the match call.
2010-11-03 12:47:06 -07:00
|
|
|
if (op != ir_txf) {
|
|
|
|
|
s_int *proj_as_int = SX_AS_INT(s_proj);
|
2010-05-26 17:55:10 -07:00
|
|
|
if (proj_as_int && proj_as_int->value() == 1) {
|
|
|
|
|
tex->projector = NULL;
|
|
|
|
|
} else {
|
ir_reader: Add a pattern matching system and use it everywhere.
Previously, the IR reader was riddled with code that:
1. Checked for the right number of list elements (via a linked list walk)
2. Retrieved references to each component (via ->next->next pointers)
3. Downcasted as necessary to make sure that each sub-component was the
right type (i.e. symbol, int, list).
4. Checking that the tag (i.e. "declare") was correct.
This was all very ad-hoc and a bit ugly. Error checking had to be done
at both steps 1, 3, and 4. Most code didn't even check the tag, relying
on the caller to do so. Not all callers did.
The new pattern matching module performs the whole process in a single
straightforward function call, resulting in shorter, more readable code.
Unfortunately, MSVC does not support C99-style anonymous arrays, so the
pattern must be declared outside of the match call.
2010-11-03 12:47:06 -07:00
|
|
|
tex->projector = read_rvalue(st, s_proj);
|
2010-05-26 17:55:10 -07:00
|
|
|
if (tex->projector == NULL) {
|
|
|
|
|
ir_read_error(st, NULL, "when reading projective divide in (%s ..)",
|
ir_reader: Add a pattern matching system and use it everywhere.
Previously, the IR reader was riddled with code that:
1. Checked for the right number of list elements (via a linked list walk)
2. Retrieved references to each component (via ->next->next pointers)
3. Downcasted as necessary to make sure that each sub-component was the
right type (i.e. symbol, int, list).
4. Checking that the tag (i.e. "declare") was correct.
This was all very ad-hoc and a bit ugly. Error checking had to be done
at both steps 1, 3, and 4. Most code didn't even check the tag, relying
on the caller to do so. Not all callers did.
The new pattern matching module performs the whole process in a single
straightforward function call, resulting in shorter, more readable code.
Unfortunately, MSVC does not support C99-style anonymous arrays, so the
pattern must be declared outside of the match call.
2010-11-03 12:47:06 -07:00
|
|
|
tex->opcode_string());
|
2010-05-26 17:55:10 -07:00
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
ir_reader: Add a pattern matching system and use it everywhere.
Previously, the IR reader was riddled with code that:
1. Checked for the right number of list elements (via a linked list walk)
2. Retrieved references to each component (via ->next->next pointers)
3. Downcasted as necessary to make sure that each sub-component was the
right type (i.e. symbol, int, list).
4. Checking that the tag (i.e. "declare") was correct.
This was all very ad-hoc and a bit ugly. Error checking had to be done
at both steps 1, 3, and 4. Most code didn't even check the tag, relying
on the caller to do so. Not all callers did.
The new pattern matching module performs the whole process in a single
straightforward function call, resulting in shorter, more readable code.
Unfortunately, MSVC does not support C99-style anonymous arrays, so the
pattern must be declared outside of the match call.
2010-11-03 12:47:06 -07:00
|
|
|
if (s_shadow->subexpressions.is_empty()) {
|
|
|
|
|
tex->shadow_comparitor = NULL;
|
2010-05-26 17:55:10 -07:00
|
|
|
} else {
|
ir_reader: Add a pattern matching system and use it everywhere.
Previously, the IR reader was riddled with code that:
1. Checked for the right number of list elements (via a linked list walk)
2. Retrieved references to each component (via ->next->next pointers)
3. Downcasted as necessary to make sure that each sub-component was the
right type (i.e. symbol, int, list).
4. Checking that the tag (i.e. "declare") was correct.
This was all very ad-hoc and a bit ugly. Error checking had to be done
at both steps 1, 3, and 4. Most code didn't even check the tag, relying
on the caller to do so. Not all callers did.
The new pattern matching module performs the whole process in a single
straightforward function call, resulting in shorter, more readable code.
Unfortunately, MSVC does not support C99-style anonymous arrays, so the
pattern must be declared outside of the match call.
2010-11-03 12:47:06 -07:00
|
|
|
tex->shadow_comparitor = read_rvalue(st, s_shadow);
|
2010-05-26 17:55:10 -07:00
|
|
|
if (tex->shadow_comparitor == NULL) {
|
|
|
|
|
ir_read_error(st, NULL, "when reading shadow comparitor in (%s ..)",
|
ir_reader: Add a pattern matching system and use it everywhere.
Previously, the IR reader was riddled with code that:
1. Checked for the right number of list elements (via a linked list walk)
2. Retrieved references to each component (via ->next->next pointers)
3. Downcasted as necessary to make sure that each sub-component was the
right type (i.e. symbol, int, list).
4. Checking that the tag (i.e. "declare") was correct.
This was all very ad-hoc and a bit ugly. Error checking had to be done
at both steps 1, 3, and 4. Most code didn't even check the tag, relying
on the caller to do so. Not all callers did.
The new pattern matching module performs the whole process in a single
straightforward function call, resulting in shorter, more readable code.
Unfortunately, MSVC does not support C99-style anonymous arrays, so the
pattern must be declared outside of the match call.
2010-11-03 12:47:06 -07:00
|
|
|
tex->opcode_string());
|
2010-05-26 17:55:10 -07:00
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
}
|
ir_reader: Add a pattern matching system and use it everywhere.
Previously, the IR reader was riddled with code that:
1. Checked for the right number of list elements (via a linked list walk)
2. Retrieved references to each component (via ->next->next pointers)
3. Downcasted as necessary to make sure that each sub-component was the
right type (i.e. symbol, int, list).
4. Checking that the tag (i.e. "declare") was correct.
This was all very ad-hoc and a bit ugly. Error checking had to be done
at both steps 1, 3, and 4. Most code didn't even check the tag, relying
on the caller to do so. Not all callers did.
The new pattern matching module performs the whole process in a single
straightforward function call, resulting in shorter, more readable code.
Unfortunately, MSVC does not support C99-style anonymous arrays, so the
pattern must be declared outside of the match call.
2010-11-03 12:47:06 -07:00
|
|
|
}
|
2010-05-26 17:55:10 -07:00
|
|
|
|
ir_reader: Add a pattern matching system and use it everywhere.
Previously, the IR reader was riddled with code that:
1. Checked for the right number of list elements (via a linked list walk)
2. Retrieved references to each component (via ->next->next pointers)
3. Downcasted as necessary to make sure that each sub-component was the
right type (i.e. symbol, int, list).
4. Checking that the tag (i.e. "declare") was correct.
This was all very ad-hoc and a bit ugly. Error checking had to be done
at both steps 1, 3, and 4. Most code didn't even check the tag, relying
on the caller to do so. Not all callers did.
The new pattern matching module performs the whole process in a single
straightforward function call, resulting in shorter, more readable code.
Unfortunately, MSVC does not support C99-style anonymous arrays, so the
pattern must be declared outside of the match call.
2010-11-03 12:47:06 -07:00
|
|
|
switch (op) {
|
|
|
|
|
case ir_txb:
|
|
|
|
|
tex->lod_info.bias = read_rvalue(st, s_lod);
|
|
|
|
|
if (tex->lod_info.bias == NULL) {
|
|
|
|
|
ir_read_error(st, NULL, "when reading LOD bias in (txb ...)");
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case ir_txl:
|
|
|
|
|
case ir_txf:
|
|
|
|
|
tex->lod_info.lod = read_rvalue(st, s_lod);
|
|
|
|
|
if (tex->lod_info.lod == NULL) {
|
|
|
|
|
ir_read_error(st, NULL, "when reading LOD in (%s ...)",
|
|
|
|
|
tex->opcode_string());
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case ir_txd: {
|
|
|
|
|
s_expression *s_dx, *s_dy;
|
|
|
|
|
s_pattern dxdy_pat[] = { s_dx, s_dy };
|
|
|
|
|
if (!MATCH(s_lod, dxdy_pat)) {
|
|
|
|
|
ir_read_error(st, s_lod, "expected (dPdx dPdy) in (txd ...)");
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
tex->lod_info.grad.dPdx = read_rvalue(st, s_dx);
|
|
|
|
|
if (tex->lod_info.grad.dPdx == NULL) {
|
|
|
|
|
ir_read_error(st, NULL, "when reading dPdx in (txd ...)");
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
tex->lod_info.grad.dPdy = read_rvalue(st, s_dy);
|
|
|
|
|
if (tex->lod_info.grad.dPdy == NULL) {
|
|
|
|
|
ir_read_error(st, NULL, "when reading dPdy in (txd ...)");
|
|
|
|
|
return NULL;
|
2010-05-26 17:55:10 -07:00
|
|
|
}
|
ir_reader: Add a pattern matching system and use it everywhere.
Previously, the IR reader was riddled with code that:
1. Checked for the right number of list elements (via a linked list walk)
2. Retrieved references to each component (via ->next->next pointers)
3. Downcasted as necessary to make sure that each sub-component was the
right type (i.e. symbol, int, list).
4. Checking that the tag (i.e. "declare") was correct.
This was all very ad-hoc and a bit ugly. Error checking had to be done
at both steps 1, 3, and 4. Most code didn't even check the tag, relying
on the caller to do so. Not all callers did.
The new pattern matching module performs the whole process in a single
straightforward function call, resulting in shorter, more readable code.
Unfortunately, MSVC does not support C99-style anonymous arrays, so the
pattern must be declared outside of the match call.
2010-11-03 12:47:06 -07:00
|
|
|
break;
|
2010-05-26 17:55:10 -07:00
|
|
|
}
|
ir_reader: Add a pattern matching system and use it everywhere.
Previously, the IR reader was riddled with code that:
1. Checked for the right number of list elements (via a linked list walk)
2. Retrieved references to each component (via ->next->next pointers)
3. Downcasted as necessary to make sure that each sub-component was the
right type (i.e. symbol, int, list).
4. Checking that the tag (i.e. "declare") was correct.
This was all very ad-hoc and a bit ugly. Error checking had to be done
at both steps 1, 3, and 4. Most code didn't even check the tag, relying
on the caller to do so. Not all callers did.
The new pattern matching module performs the whole process in a single
straightforward function call, resulting in shorter, more readable code.
Unfortunately, MSVC does not support C99-style anonymous arrays, so the
pattern must be declared outside of the match call.
2010-11-03 12:47:06 -07:00
|
|
|
default:
|
|
|
|
|
// tex doesn't have any extra parameters.
|
|
|
|
|
break;
|
|
|
|
|
};
|
2010-05-26 17:55:10 -07:00
|
|
|
return tex;
|
|
|
|
|
}
|