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-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;
|
|
|
|
|
|
2011-01-01 01:17:59 -08:00
|
|
|
class ir_reader {
|
|
|
|
|
public:
|
|
|
|
|
ir_reader(_mesa_glsl_parse_state *);
|
|
|
|
|
|
|
|
|
|
void read(exec_list *instructions, const char *src, bool scan_for_protos);
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
void *mem_ctx;
|
|
|
|
|
_mesa_glsl_parse_state *state;
|
|
|
|
|
|
|
|
|
|
void ir_read_error(s_expression *, const char *fmt, ...);
|
|
|
|
|
|
|
|
|
|
const glsl_type *read_type(s_expression *);
|
|
|
|
|
|
|
|
|
|
void scan_for_prototypes(exec_list *, s_expression *);
|
|
|
|
|
ir_function *read_function(s_expression *, bool skip_body);
|
|
|
|
|
void read_function_sig(ir_function *, s_expression *, bool skip_body);
|
|
|
|
|
|
|
|
|
|
void read_instructions(exec_list *, s_expression *, ir_loop *);
|
|
|
|
|
ir_instruction *read_instruction(s_expression *, ir_loop *);
|
|
|
|
|
ir_variable *read_declaration(s_expression *);
|
|
|
|
|
ir_if *read_if(s_expression *, ir_loop *);
|
|
|
|
|
ir_loop *read_loop(s_expression *);
|
|
|
|
|
ir_return *read_return(s_expression *);
|
|
|
|
|
ir_rvalue *read_rvalue(s_expression *);
|
|
|
|
|
ir_assignment *read_assignment(s_expression *);
|
|
|
|
|
ir_expression *read_expression(s_expression *);
|
|
|
|
|
ir_call *read_call(s_expression *);
|
|
|
|
|
ir_swizzle *read_swizzle(s_expression *);
|
|
|
|
|
ir_constant *read_constant(s_expression *);
|
|
|
|
|
ir_texture *read_texture(s_expression *);
|
|
|
|
|
|
|
|
|
|
ir_dereference *read_dereference(s_expression *);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
ir_reader::ir_reader(_mesa_glsl_parse_state *state) : state(state)
|
|
|
|
|
{
|
|
|
|
|
this->mem_ctx = state;
|
|
|
|
|
}
|
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
|
|
|
{
|
2011-01-01 01:17:59 -08:00
|
|
|
ir_reader r(state);
|
|
|
|
|
r.read(instructions, src, scan_for_protos);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
ir_reader::read(exec_list *instructions, const char *src, bool scan_for_protos)
|
|
|
|
|
{
|
2011-09-22 13:05:03 -07:00
|
|
|
void *sx_mem_ctx = ralloc_context(NULL);
|
|
|
|
|
s_expression *expr = s_expression::read_expression(sx_mem_ctx, src);
|
2010-04-07 14:38:03 -07:00
|
|
|
if (expr == NULL) {
|
2011-01-01 01:17:59 -08:00
|
|
|
ir_read_error(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) {
|
2011-01-01 01:17:59 -08:00
|
|
|
scan_for_prototypes(instructions, expr);
|
2010-08-11 16:53:52 -07:00
|
|
|
if (state->error)
|
|
|
|
|
return;
|
|
|
|
|
}
|
2010-04-21 17:52:36 -07:00
|
|
|
|
2011-01-01 01:17:59 -08:00
|
|
|
read_instructions(instructions, expr, NULL);
|
2011-09-22 13:05:03 -07:00
|
|
|
ralloc_free(sx_mem_ctx);
|
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
|
|
|
}
|
|
|
|
|
|
2011-01-01 01:17:59 -08:00
|
|
|
void
|
|
|
|
|
ir_reader::ir_read_error(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)
|
2011-01-21 14:32:31 -08:00
|
|
|
ralloc_asprintf_append(&state->info_log, "In function %s:\n",
|
|
|
|
|
state->current_function->function_name());
|
|
|
|
|
ralloc_strcat(&state->info_log, "error: ");
|
2010-04-07 17:24:44 -07:00
|
|
|
|
|
|
|
|
va_start(ap, fmt);
|
2011-01-21 14:32:31 -08:00
|
|
|
ralloc_vasprintf_append(&state->info_log, fmt, ap);
|
2010-04-07 17:24:44 -07:00
|
|
|
va_end(ap);
|
2011-01-21 14:32:31 -08:00
|
|
|
ralloc_strcat(&state->info_log, "\n");
|
2010-04-07 17:24:44 -07:00
|
|
|
|
2010-04-21 23:23:23 -07:00
|
|
|
if (expr != NULL) {
|
2011-01-21 14:32:31 -08:00
|
|
|
ralloc_strcat(&state->info_log, "...in this context:\n ");
|
2010-04-21 23:23:23 -07:00
|
|
|
expr->print();
|
2011-01-21 14:32:31 -08:00
|
|
|
ralloc_strcat(&state->info_log, "\n\n");
|
2010-04-21 23:23:23 -07:00
|
|
|
}
|
2010-04-07 17:24:44 -07:00
|
|
|
}
|
|
|
|
|
|
2011-01-01 01:17:59 -08:00
|
|
|
const glsl_type *
|
|
|
|
|
ir_reader::read_type(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 *s_base_type;
|
|
|
|
|
s_int *s_size;
|
|
|
|
|
|
|
|
|
|
s_pattern pat[] = { "array", s_base_type, s_size };
|
|
|
|
|
if (MATCH(expr, pat)) {
|
2011-01-01 01:17:59 -08:00
|
|
|
const glsl_type *base_type = read_type(s_base_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
|
|
|
if (base_type == NULL) {
|
2011-01-01 01:17:59 -08:00
|
|
|
ir_read_error(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) {
|
2011-01-01 01:17:59 -08:00
|
|
|
ir_read_error(expr, "expected <type>");
|
2010-04-07 17:24:44 -07:00
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2011-01-01 01:17:59 -08:00
|
|
|
const glsl_type *type = state->symbols->get_type(type_sym->value());
|
2010-04-07 17:24:44 -07:00
|
|
|
if (type == NULL)
|
2011-01-01 01:17:59 -08:00
|
|
|
ir_read_error(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
|
|
|
|
2011-01-01 01:17:59 -08:00
|
|
|
void
|
|
|
|
|
ir_reader::scan_for_prototypes(exec_list *instructions, s_expression *expr)
|
2010-04-21 17:52:36 -07:00
|
|
|
{
|
|
|
|
|
s_list *list = SX_AS_LIST(expr);
|
|
|
|
|
if (list == NULL) {
|
2011-01-01 01:17:59 -08:00
|
|
|
ir_read_error(expr, "Expected (<instruction> ...); found an atom.");
|
2010-04-21 17:52:36 -07:00
|
|
|
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.
|
|
|
|
|
|
2011-01-01 01:17:59 -08:00
|
|
|
ir_function *f = read_function(sub, true);
|
2010-04-21 18:14:06 -07:00
|
|
|
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
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2011-01-01 01:17:59 -08:00
|
|
|
ir_function *
|
|
|
|
|
ir_reader::read_function(s_expression *expr, bool skip_body)
|
2010-04-21 17:52:36 -07:00
|
|
|
{
|
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)) {
|
2011-01-01 01:17:59 -08:00
|
|
|
ir_read_error(expr, "Expected (function <name> (signature ...) ...)");
|
2010-04-21 18:14:06 -07:00
|
|
|
return NULL;
|
2010-04-21 17:52:36 -07:00
|
|
|
}
|
|
|
|
|
|
2011-01-01 01:17:59 -08:00
|
|
|
ir_function *f = state->symbols->get_function(name->value());
|
2010-04-21 18:14:06 -07:00
|
|
|
if (f == NULL) {
|
2011-01-01 01:17:59 -08:00
|
|
|
f = new(mem_ctx) ir_function(name->value());
|
|
|
|
|
added = state->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();
|
2011-01-01 01:17:59 -08:00
|
|
|
read_function_sig(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
|
|
|
}
|
|
|
|
|
|
2011-01-01 01:17:59 -08:00
|
|
|
void
|
|
|
|
|
ir_reader::read_function_sig(ir_function *f, s_expression *expr, bool skip_body)
|
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_expression *type_expr;
|
|
|
|
|
s_list *paramlist;
|
|
|
|
|
s_list *body_list;
|
|
|
|
|
|
|
|
|
|
s_pattern pat[] = { "signature", type_expr, paramlist, body_list };
|
|
|
|
|
if (!MATCH(expr, pat)) {
|
2011-01-01 01:17:59 -08:00
|
|
|
ir_read_error(expr, "Expected (signature <type> (parameters ...) "
|
|
|
|
|
"(<instruction> ...))");
|
2010-04-28 12:45:18 -07:00
|
|
|
return;
|
2010-04-21 17:52:36 -07:00
|
|
|
}
|
|
|
|
|
|
2011-01-01 01:17:59 -08:00
|
|
|
const glsl_type *return_type = read_type(type_expr);
|
2010-04-21 17:52:36 -07:00
|
|
|
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) {
|
2011-01-01 01:17:59 -08:00
|
|
|
ir_read_error(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;
|
2011-01-01 01:17:59 -08:00
|
|
|
state->symbols->push_scope();
|
2010-04-21 18:14:06 -07:00
|
|
|
|
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()) {
|
2011-01-01 01:17:59 -08:00
|
|
|
ir_variable *var = read_declaration((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. */
|
2011-01-01 01:17:59 -08:00
|
|
|
sig = new(mem_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) {
|
2011-01-01 01:17:59 -08:00
|
|
|
ir_read_error(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) {
|
2011-01-01 01:17:59 -08:00
|
|
|
ir_read_error(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. */
|
2011-01-01 01:17:59 -08:00
|
|
|
state->symbols->pop_scope();
|
2010-08-11 16:53:52 -07:00
|
|
|
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) {
|
2011-01-01 01:17:59 -08:00
|
|
|
ir_read_error(expr, "function %s redefined", f->name);
|
2010-04-28 12:45:18 -07:00
|
|
|
return;
|
|
|
|
|
}
|
2011-01-01 01:17:59 -08:00
|
|
|
state->current_function = sig;
|
|
|
|
|
read_instructions(&sig->body, body_list, NULL);
|
|
|
|
|
state->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
|
|
|
|
2011-01-01 01:17:59 -08:00
|
|
|
state->symbols->pop_scope();
|
2010-04-21 17:52:36 -07:00
|
|
|
}
|
|
|
|
|
|
2011-01-01 01:17:59 -08:00
|
|
|
void
|
|
|
|
|
ir_reader::read_instructions(exec_list *instructions, 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) {
|
2011-01-01 01:17:59 -08:00
|
|
|
ir_read_error(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();
|
2011-01-01 01:17:59 -08:00
|
|
|
ir_instruction *ir = read_instruction(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.
|
|
|
|
|
*/
|
2011-01-01 01:17:59 -08:00
|
|
|
if (state->current_function == NULL && ir->as_variable() != NULL)
|
2010-09-04 01:55:55 -07:00
|
|
|
instructions->push_head(ir);
|
|
|
|
|
else
|
|
|
|
|
instructions->push_tail(ir);
|
|
|
|
|
}
|
2010-04-10 01:45:08 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2011-01-01 01:17:59 -08:00
|
|
|
ir_instruction *
|
|
|
|
|
ir_reader::read_instruction(s_expression *expr, ir_loop *loop_ctx)
|
2010-04-09 17:40:51 -07:00
|
|
|
{
|
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)
|
2011-01-01 01:17:59 -08:00
|
|
|
return new(mem_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)
|
2011-01-01 01:17:59 -08:00
|
|
|
return new(mem_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()) {
|
2011-01-01 01:17:59 -08:00
|
|
|
ir_read_error(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) {
|
2011-01-01 01:17:59 -08:00
|
|
|
ir_read_error(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) {
|
2011-01-01 01:17:59 -08:00
|
|
|
inst = read_declaration(list);
|
2010-07-22 16:40:35 -07:00
|
|
|
} else if (strcmp(tag->value(), "assign") == 0) {
|
2011-01-01 01:17:59 -08:00
|
|
|
inst = read_assignment(list);
|
2010-04-12 14:25:41 -07:00
|
|
|
} else if (strcmp(tag->value(), "if") == 0) {
|
2011-01-01 01:17:59 -08:00
|
|
|
inst = read_if(list, loop_ctx);
|
2010-04-12 15:48:27 -07:00
|
|
|
} else if (strcmp(tag->value(), "loop") == 0) {
|
2011-01-01 01:17:59 -08:00
|
|
|
inst = read_loop(list);
|
2010-04-12 14:25:41 -07:00
|
|
|
} else if (strcmp(tag->value(), "return") == 0) {
|
2011-01-01 01:17:59 -08:00
|
|
|
inst = read_return(list);
|
2010-04-21 18:14:06 -07:00
|
|
|
} else if (strcmp(tag->value(), "function") == 0) {
|
2011-01-01 01:17:59 -08:00
|
|
|
inst = read_function(list, false);
|
2010-04-12 14:25:41 -07:00
|
|
|
} else {
|
2011-01-01 01:17:59 -08:00
|
|
|
inst = read_rvalue(list);
|
2010-04-12 14:25:41 -07:00
|
|
|
if (inst == NULL)
|
2011-01-01 01:17:59 -08:00
|
|
|
ir_read_error(NULL, "when reading instruction");
|
2010-04-12 14:25:41 -07:00
|
|
|
}
|
2010-04-09 17:40:51 -07:00
|
|
|
return inst;
|
|
|
|
|
}
|
|
|
|
|
|
2011-01-01 01:17:59 -08:00
|
|
|
ir_variable *
|
|
|
|
|
ir_reader::read_declaration(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)) {
|
2011-01-01 01:17:59 -08:00
|
|
|
ir_read_error(expr, "expected (declare (<qualifiers>) <type> <name>)");
|
2010-04-09 17:40:51 -07:00
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2011-01-01 01:17:59 -08:00
|
|
|
const glsl_type *type = read_type(s_type);
|
2010-04-09 17:40:51 -07:00
|
|
|
if (type == NULL)
|
|
|
|
|
return NULL;
|
|
|
|
|
|
2011-01-01 01:17:59 -08:00
|
|
|
ir_variable *var = new(mem_ctx) 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) {
|
2011-01-01 01:17:59 -08:00
|
|
|
ir_read_error(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;
|
2011-01-12 15:37:37 -08:00
|
|
|
} else if (strcmp(qualifier->value(), "const_in") == 0) {
|
|
|
|
|
var->mode = ir_var_const_in;
|
2010-04-09 17:40:51 -07:00
|
|
|
} 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) {
|
2011-10-25 18:06:37 -07:00
|
|
|
var->interpolation = INTERP_QUALIFIER_SMOOTH;
|
2010-04-09 17:40:51 -07:00
|
|
|
} else if (strcmp(qualifier->value(), "flat") == 0) {
|
2011-10-25 18:06:37 -07:00
|
|
|
var->interpolation = INTERP_QUALIFIER_FLAT;
|
2010-04-09 17:40:51 -07:00
|
|
|
} else if (strcmp(qualifier->value(), "noperspective") == 0) {
|
2011-10-25 18:06:37 -07:00
|
|
|
var->interpolation = INTERP_QUALIFIER_NOPERSPECTIVE;
|
2010-04-09 17:40:51 -07:00
|
|
|
} else {
|
2011-01-01 01:17:59 -08:00
|
|
|
ir_read_error(expr, "unknown qualifier: %s", qualifier->value());
|
2010-04-09 17:40:51 -07:00
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Add the variable to the symbol table
|
2011-01-01 01:17:59 -08:00
|
|
|
state->symbols->add_variable(var);
|
2010-04-09 17:40:51 -07:00
|
|
|
|
|
|
|
|
return var;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2011-01-01 01:17:59 -08:00
|
|
|
ir_if *
|
|
|
|
|
ir_reader::read_if(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)) {
|
2011-01-01 01:17:59 -08:00
|
|
|
ir_read_error(expr, "expected (if <condition> (<then>...) (<else>...))");
|
2010-04-10 01:45:08 -07:00
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2011-01-01 01:17:59 -08:00
|
|
|
ir_rvalue *condition = read_rvalue(s_cond);
|
2010-04-10 01:45:08 -07:00
|
|
|
if (condition == NULL) {
|
2011-01-01 01:17:59 -08:00
|
|
|
ir_read_error(NULL, "when reading condition of (if ...)");
|
2010-04-10 01:45:08 -07:00
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2011-01-01 01:17:59 -08:00
|
|
|
ir_if *iff = new(mem_ctx) ir_if(condition);
|
2010-04-10 01:45:08 -07:00
|
|
|
|
2011-01-01 01:17:59 -08:00
|
|
|
read_instructions(&iff->then_instructions, s_then, loop_ctx);
|
|
|
|
|
read_instructions(&iff->else_instructions, s_else, loop_ctx);
|
|
|
|
|
if (state->error) {
|
2010-04-10 01:45:08 -07:00
|
|
|
delete iff;
|
|
|
|
|
iff = NULL;
|
|
|
|
|
}
|
|
|
|
|
return iff;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2011-01-01 01:17:59 -08:00
|
|
|
ir_loop *
|
|
|
|
|
ir_reader::read_loop(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)) {
|
2011-01-01 01:17:59 -08:00
|
|
|
ir_read_error(expr, "expected (loop <counter> <from> <to> "
|
|
|
|
|
"<increment> <body>)");
|
2010-04-12 15:48:27 -07:00
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// FINISHME: actually read the count/from/to fields.
|
|
|
|
|
|
2011-01-01 01:17:59 -08:00
|
|
|
ir_loop *loop = new(mem_ctx) ir_loop;
|
|
|
|
|
read_instructions(&loop->body_instructions, s_body, loop);
|
|
|
|
|
if (state->error) {
|
2010-04-12 15:48:27 -07:00
|
|
|
delete loop;
|
|
|
|
|
loop = NULL;
|
|
|
|
|
}
|
|
|
|
|
return loop;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2011-01-01 01:17:59 -08:00
|
|
|
ir_return *
|
|
|
|
|
ir_reader::read_return(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
|
|
|
|
2011-06-29 15:30:40 -07:00
|
|
|
s_pattern return_value_pat[] = { "return", s_retval};
|
|
|
|
|
s_pattern return_void_pat[] = { "return" };
|
|
|
|
|
if (MATCH(expr, return_value_pat)) {
|
|
|
|
|
ir_rvalue *retval = read_rvalue(s_retval);
|
|
|
|
|
if (retval == NULL) {
|
|
|
|
|
ir_read_error(NULL, "when reading return value");
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
return new(mem_ctx) ir_return(retval);
|
|
|
|
|
} else if (MATCH(expr, return_void_pat)) {
|
|
|
|
|
return new(mem_ctx) ir_return;
|
|
|
|
|
} else {
|
|
|
|
|
ir_read_error(expr, "expected (return <rvalue>) or (return)");
|
2010-04-09 17:56:22 -07:00
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2011-01-01 01:17:59 -08:00
|
|
|
ir_rvalue *
|
|
|
|
|
ir_reader::read_rvalue(s_expression *expr)
|
2010-04-07 17:24:44 -07:00
|
|
|
{
|
|
|
|
|
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) {
|
2011-01-01 01:17:59 -08:00
|
|
|
ir_read_error(expr, "expected rvalue tag");
|
2010-04-07 17:24:44 -07:00
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2011-01-01 01:17:59 -08:00
|
|
|
ir_rvalue *rvalue = read_dereference(list);
|
|
|
|
|
if (rvalue != NULL || state->error)
|
2010-05-26 17:52:44 -07:00
|
|
|
return rvalue;
|
|
|
|
|
else if (strcmp(tag->value(), "swiz") == 0) {
|
2011-01-01 01:17:59 -08:00
|
|
|
rvalue = read_swizzle(list);
|
2010-04-12 14:27:39 -07:00
|
|
|
} else if (strcmp(tag->value(), "expression") == 0) {
|
2011-01-01 01:17:59 -08:00
|
|
|
rvalue = read_expression(list);
|
2010-04-28 12:54:21 -07:00
|
|
|
} else if (strcmp(tag->value(), "call") == 0) {
|
2011-01-01 01:17:59 -08:00
|
|
|
rvalue = read_call(list);
|
2010-04-12 14:27:39 -07:00
|
|
|
} else if (strcmp(tag->value(), "constant") == 0) {
|
2011-01-01 01:17:59 -08:00
|
|
|
rvalue = read_constant(list);
|
2010-04-12 14:27:39 -07:00
|
|
|
} else {
|
2011-01-01 01:17:59 -08:00
|
|
|
rvalue = read_texture(list);
|
|
|
|
|
if (rvalue == NULL && !state->error)
|
|
|
|
|
ir_read_error(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;
|
|
|
|
|
}
|
|
|
|
|
|
2011-01-01 01:17:59 -08:00
|
|
|
ir_assignment *
|
|
|
|
|
ir_reader::read_assignment(s_expression *expr)
|
2010-04-07 17:24:44 -07:00
|
|
|
{
|
2011-01-01 03:37:02 -08:00
|
|
|
s_expression *cond_expr = NULL;
|
|
|
|
|
s_expression *lhs_expr, *rhs_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_list *mask_list;
|
|
|
|
|
|
2011-01-01 03:37:02 -08:00
|
|
|
s_pattern pat4[] = { "assign", mask_list, lhs_expr, rhs_expr };
|
|
|
|
|
s_pattern pat5[] = { "assign", cond_expr, mask_list, lhs_expr, rhs_expr };
|
|
|
|
|
if (!MATCH(expr, pat4) && !MATCH(expr, pat5)) {
|
|
|
|
|
ir_read_error(expr, "expected (assign [<condition>] (<write mask>) "
|
2011-01-01 01:17:59 -08:00
|
|
|
"<lhs> <rhs>)");
|
2010-04-07 17:24:44 -07:00
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2011-01-01 03:37:02 -08:00
|
|
|
ir_rvalue *condition = NULL;
|
|
|
|
|
if (cond_expr != NULL) {
|
|
|
|
|
condition = read_rvalue(cond_expr);
|
|
|
|
|
if (condition == NULL) {
|
|
|
|
|
ir_read_error(NULL, "when reading condition of assignment");
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
2010-04-07 17:24:44 -07:00
|
|
|
}
|
|
|
|
|
|
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) {
|
2011-01-01 01:17:59 -08:00
|
|
|
ir_read_error(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') {
|
2011-01-01 01:17:59 -08:00
|
|
|
ir_read_error(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()) {
|
2011-01-01 01:17:59 -08:00
|
|
|
ir_read_error(mask_list, "expected () or (<write mask>)");
|
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 NULL;
|
2010-09-02 23:54:40 -07:00
|
|
|
}
|
|
|
|
|
|
2011-01-01 01:17:59 -08:00
|
|
|
ir_dereference *lhs = read_dereference(lhs_expr);
|
2010-04-07 17:24:44 -07:00
|
|
|
if (lhs == NULL) {
|
2011-01-01 01:17:59 -08:00
|
|
|
ir_read_error(NULL, "when reading left-hand side of assignment");
|
2010-04-07 17:24:44 -07:00
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2011-01-01 01:17:59 -08:00
|
|
|
ir_rvalue *rhs = read_rvalue(rhs_expr);
|
2010-04-07 17:24:44 -07:00
|
|
|
if (rhs == NULL) {
|
2011-01-01 01:17:59 -08:00
|
|
|
ir_read_error(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())) {
|
2011-01-01 01:17:59 -08:00
|
|
|
ir_read_error(expr, "non-zero write mask required.");
|
2010-09-02 23:54:40 -07:00
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2011-01-01 01:17:59 -08:00
|
|
|
return new(mem_ctx) ir_assignment(lhs, rhs, condition, mask);
|
2010-04-07 17:24:44 -07:00
|
|
|
}
|
|
|
|
|
|
2011-01-01 01:17:59 -08:00
|
|
|
ir_call *
|
|
|
|
|
ir_reader::read_call(s_expression *expr)
|
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_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)) {
|
2011-01-01 01:17:59 -08:00
|
|
|
ir_read_error(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();
|
2011-01-01 01:17:59 -08:00
|
|
|
ir_rvalue *param = read_rvalue(expr);
|
2010-04-28 12:54:21 -07:00
|
|
|
if (param == NULL) {
|
2011-01-01 01:17:59 -08:00
|
|
|
ir_read_error(expr, "when reading parameter to function call");
|
2010-04-28 12:54:21 -07:00
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
parameters.push_tail(param);
|
|
|
|
|
}
|
|
|
|
|
|
2011-01-01 01:17:59 -08:00
|
|
|
ir_function *f = state->symbols->get_function(name->value());
|
2010-04-28 12:54:21 -07:00
|
|
|
if (f == NULL) {
|
2011-01-01 01:17:59 -08:00
|
|
|
ir_read_error(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) {
|
2011-01-01 01:17:59 -08:00
|
|
|
ir_read_error(expr, "couldn't find matching signature for function "
|
2010-04-28 12:54:21 -07:00
|
|
|
"%s", name->value());
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2011-01-01 01:17:59 -08:00
|
|
|
return new(mem_ctx) ir_call(callee, ¶meters);
|
2010-04-28 12:54:21 -07:00
|
|
|
}
|
2010-04-07 17:24:44 -07:00
|
|
|
|
2011-01-01 01:17:59 -08:00
|
|
|
ir_expression *
|
|
|
|
|
ir_reader::read_expression(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 *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)) {
|
2011-01-01 01:17:59 -08:00
|
|
|
ir_read_error(expr, "expected (expression <type> <operator> "
|
|
|
|
|
"<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
|
|
|
|
2011-01-01 01:17:59 -08:00
|
|
|
const glsl_type *type = read_type(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) {
|
2011-01-01 01:17:59 -08:00
|
|
|
ir_read_error(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()) {
|
2011-01-01 01:17:59 -08:00
|
|
|
ir_read_error(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
|
|
|
}
|
|
|
|
|
|
2011-01-01 01:17:59 -08:00
|
|
|
ir_rvalue *arg1 = read_rvalue(s_arg1);
|
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 *arg2 = NULL;
|
2010-04-07 17:24:44 -07:00
|
|
|
if (arg1 == NULL) {
|
2011-01-01 01:17:59 -08:00
|
|
|
ir_read_error(NULL, "when reading first operand of %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
|
|
|
if (num_operands == 2) {
|
|
|
|
|
if (s_arg2->is_tail_sentinel() || !s_arg2->next->is_tail_sentinel()) {
|
2011-01-01 01:17:59 -08:00
|
|
|
ir_read_error(expr, "expected (expression <type> %s <operand> "
|
|
|
|
|
"<operand>)", s_op->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
|
|
|
return NULL;
|
|
|
|
|
}
|
2011-01-01 01:17:59 -08:00
|
|
|
arg2 = read_rvalue(s_arg2);
|
2010-04-07 17:24:44 -07:00
|
|
|
if (arg2 == NULL) {
|
2011-01-01 01:17:59 -08:00
|
|
|
ir_read_error(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;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2011-01-01 01:17:59 -08:00
|
|
|
return new(mem_ctx) ir_expression(op, type, arg1, arg2);
|
2010-04-07 17:24:44 -07:00
|
|
|
}
|
|
|
|
|
|
2011-01-01 01:17:59 -08:00
|
|
|
ir_swizzle *
|
|
|
|
|
ir_reader::read_swizzle(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)) {
|
2011-01-01 01:17:59 -08:00
|
|
|
ir_read_error(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) {
|
2011-01-01 01:17:59 -08:00
|
|
|
ir_read_error(expr, "expected a valid swizzle; found %s", swiz->value());
|
2010-04-07 17:24:44 -07:00
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2011-01-01 01:17:59 -08:00
|
|
|
ir_rvalue *rvalue = read_rvalue(sub);
|
2010-04-07 17:24:44 -07:00
|
|
|
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)
|
2011-01-01 01:17:59 -08:00
|
|
|
ir_read_error(expr, "invalid swizzle");
|
2010-04-28 13:16:31 -07:00
|
|
|
|
|
|
|
|
return ir;
|
2010-04-07 17:24:44 -07:00
|
|
|
}
|
|
|
|
|
|
2011-01-01 01:17:59 -08:00
|
|
|
ir_constant *
|
|
|
|
|
ir_reader::read_constant(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 *type_expr;
|
|
|
|
|
s_list *values;
|
|
|
|
|
|
|
|
|
|
s_pattern pat[] = { "constant", type_expr, values };
|
2010-12-31 02:03:21 -08:00
|
|
|
if (!MATCH(expr, pat)) {
|
2011-01-01 01:17:59 -08:00
|
|
|
ir_read_error(expr, "expected (constant <type> (...))");
|
2010-04-07 17:24:44 -07:00
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2011-01-01 01:17:59 -08:00
|
|
|
const glsl_type *type = read_type(type_expr);
|
2010-04-07 17:24:44 -07:00
|
|
|
if (type == NULL)
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
if (values == NULL) {
|
2011-01-01 01:17:59 -08:00
|
|
|
ir_read_error(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();
|
2011-01-01 01:17:59 -08:00
|
|
|
ir_constant *ir_elt = read_constant(elt);
|
2010-07-20 01:53:07 -07:00
|
|
|
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) {
|
2011-01-01 01:17:59 -08:00
|
|
|
ir_read_error(values, "expected exactly %u array elements, "
|
2010-12-31 01:48:02 -08:00
|
|
|
"given %u", type->length, elements_supplied);
|
|
|
|
|
return NULL;
|
2010-07-20 01:53:07 -07:00
|
|
|
}
|
2011-01-01 01:17:59 -08:00
|
|
|
return new(mem_ctx) ir_constant(type, &elements);
|
2010-07-20 01:53:07 -07:00
|
|
|
}
|
|
|
|
|
|
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).
|
2011-09-07 11:44:35 -06:00
|
|
|
unsigned k = 0;
|
2010-04-07 17:24:44 -07:00
|
|
|
foreach_iter(exec_list_iterator, it, values->subexpressions) {
|
|
|
|
|
if (k >= 16) {
|
2011-01-01 01:17:59 -08:00
|
|
|
ir_read_error(values, "expected at most 16 numbers");
|
2010-04-07 17:24:44 -07:00
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s_expression *expr = (s_expression*) it.get();
|
|
|
|
|
|
2011-10-25 12:55:54 -07:00
|
|
|
if (type->base_type == GLSL_TYPE_FLOAT) {
|
2010-04-07 17:24:44 -07:00
|
|
|
s_number *value = SX_AS_NUMBER(expr);
|
|
|
|
|
if (value == NULL) {
|
2011-01-01 01:17:59 -08:00
|
|
|
ir_read_error(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) {
|
2011-01-01 01:17:59 -08:00
|
|
|
ir_read_error(values, "expected integers");
|
2010-04-07 17:24:44 -07:00
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2011-10-25 12:55:54 -07:00
|
|
|
switch (type->base_type) {
|
2010-04-07 17:24:44 -07:00
|
|
|
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:
|
2011-01-01 01:17:59 -08:00
|
|
|
ir_read_error(values, "unsupported constant type");
|
2010-04-07 17:24:44 -07:00
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
++k;
|
|
|
|
|
}
|
2011-09-05 12:03:29 -07:00
|
|
|
if (k != type->components()) {
|
2011-09-07 11:44:35 -06:00
|
|
|
ir_read_error(values, "expected %u constant values, found %u",
|
2011-09-05 12:03:29 -07:00
|
|
|
type->components(), k);
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
2010-06-11 16:43:42 -07:00
|
|
|
|
2011-01-01 01:17:59 -08:00
|
|
|
return new(mem_ctx) ir_constant(type, &data);
|
2010-04-07 17:24:44 -07:00
|
|
|
}
|
2010-04-12 14:27:39 -07:00
|
|
|
|
2011-01-01 01:17:59 -08:00
|
|
|
ir_dereference *
|
|
|
|
|
ir_reader::read_dereference(s_expression *expr)
|
2010-05-26 17:52:44 -07:00
|
|
|
{
|
2010-12-31 02:17:58 -08:00
|
|
|
s_symbol *s_var;
|
|
|
|
|
s_expression *s_subject;
|
|
|
|
|
s_expression *s_index;
|
|
|
|
|
s_symbol *s_field;
|
|
|
|
|
|
|
|
|
|
s_pattern var_pat[] = { "var_ref", s_var };
|
|
|
|
|
s_pattern array_pat[] = { "array_ref", s_subject, s_index };
|
|
|
|
|
s_pattern record_pat[] = { "record_ref", s_subject, s_field };
|
|
|
|
|
|
|
|
|
|
if (MATCH(expr, var_pat)) {
|
2011-01-01 01:17:59 -08:00
|
|
|
ir_variable *var = state->symbols->get_variable(s_var->value());
|
2010-12-31 02:17:58 -08:00
|
|
|
if (var == NULL) {
|
2011-01-01 01:17:59 -08:00
|
|
|
ir_read_error(expr, "undeclared variable: %s", s_var->value());
|
2010-12-31 02:17:58 -08:00
|
|
|
return NULL;
|
|
|
|
|
}
|
2011-01-01 01:17:59 -08:00
|
|
|
return new(mem_ctx) ir_dereference_variable(var);
|
2010-12-31 02:17:58 -08:00
|
|
|
} else if (MATCH(expr, array_pat)) {
|
2011-01-01 01:17:59 -08:00
|
|
|
ir_rvalue *subject = read_rvalue(s_subject);
|
2010-12-31 02:17:58 -08:00
|
|
|
if (subject == NULL) {
|
2011-01-01 01:17:59 -08:00
|
|
|
ir_read_error(NULL, "when reading the subject of an array_ref");
|
2010-12-31 02:17:58 -08:00
|
|
|
return NULL;
|
|
|
|
|
}
|
2010-05-26 15:20:59 -07:00
|
|
|
|
2011-01-01 01:17:59 -08:00
|
|
|
ir_rvalue *idx = read_rvalue(s_index);
|
2010-12-31 02:17:58 -08:00
|
|
|
if (subject == NULL) {
|
2011-01-01 01:17:59 -08:00
|
|
|
ir_read_error(NULL, "when reading the index of an array_ref");
|
2010-12-31 02:17:58 -08:00
|
|
|
return NULL;
|
|
|
|
|
}
|
2011-01-01 01:17:59 -08:00
|
|
|
return new(mem_ctx) ir_dereference_array(subject, idx);
|
2010-12-31 02:17:58 -08:00
|
|
|
} else if (MATCH(expr, record_pat)) {
|
2011-01-01 01:17:59 -08:00
|
|
|
ir_rvalue *subject = read_rvalue(s_subject);
|
2010-12-31 02:17:58 -08:00
|
|
|
if (subject == NULL) {
|
2011-01-01 01:17:59 -08:00
|
|
|
ir_read_error(NULL, "when reading the subject of a record_ref");
|
2010-12-31 02:17:58 -08:00
|
|
|
return NULL;
|
|
|
|
|
}
|
2011-01-01 01:17:59 -08:00
|
|
|
return new(mem_ctx) ir_dereference_record(subject, s_field->value());
|
2010-05-26 15:20:59 -07:00
|
|
|
}
|
2010-12-31 02:17:58 -08:00
|
|
|
return NULL;
|
2010-04-12 14:27:39 -07:00
|
|
|
}
|
2010-05-26 17:55:10 -07:00
|
|
|
|
2011-01-01 01:17:59 -08:00
|
|
|
ir_texture *
|
|
|
|
|
ir_reader::read_texture(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;
|
2011-02-25 14:29:36 -08:00
|
|
|
s_expression *s_type = 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_sampler = NULL;
|
|
|
|
|
s_expression *s_coord = NULL;
|
2011-01-08 23:49:23 -08:00
|
|
|
s_expression *s_offset = 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_proj = NULL;
|
|
|
|
|
s_list *s_shadow = NULL;
|
|
|
|
|
s_expression *s_lod = NULL;
|
|
|
|
|
|
2011-01-25 13:09:57 -07:00
|
|
|
ir_texture_opcode op = ir_tex; /* silence warning */
|
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 tex_pattern[] =
|
2011-02-25 14:29:36 -08:00
|
|
|
{ "tex", s_type, s_sampler, s_coord, s_offset, s_proj, s_shadow };
|
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 txf_pattern[] =
|
2011-02-25 14:29:36 -08:00
|
|
|
{ "txf", s_type, s_sampler, s_coord, s_offset, s_lod };
|
2011-02-25 14:45:33 -08:00
|
|
|
s_pattern txs_pattern[] =
|
|
|
|
|
{ "txs", s_type, s_sampler, s_lod };
|
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 other_pattern[] =
|
2011-02-25 14:29:36 -08:00
|
|
|
{ tag, s_type, s_sampler, s_coord, s_offset, s_proj, s_shadow, s_lod };
|
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
|
|
|
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;
|
2011-02-25 14:45:33 -08:00
|
|
|
} else if (MATCH(expr, txs_pattern)) {
|
|
|
|
|
op = ir_txs;
|
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;
|
2011-01-25 13:09:57 -07:00
|
|
|
} else {
|
|
|
|
|
ir_read_error(NULL, "unexpected texture pattern");
|
|
|
|
|
return NULL;
|
2010-05-26 17:55:10 -07:00
|
|
|
}
|
|
|
|
|
|
2011-01-01 01:17:59 -08:00
|
|
|
ir_texture *tex = new(mem_ctx) ir_texture(op);
|
2010-05-26 17:55:10 -07:00
|
|
|
|
2011-02-25 14:29:36 -08:00
|
|
|
// Read return type
|
|
|
|
|
const glsl_type *type = read_type(s_type);
|
|
|
|
|
if (type == NULL) {
|
|
|
|
|
ir_read_error(NULL, "when reading type in (%s ...)",
|
|
|
|
|
tex->opcode_string());
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2010-05-26 17:55:10 -07:00
|
|
|
// Read sampler (must be a deref)
|
2011-01-01 01:17:59 -08:00
|
|
|
ir_dereference *sampler = read_dereference(s_sampler);
|
2010-06-03 15:07:34 -07:00
|
|
|
if (sampler == NULL) {
|
2011-01-01 01:17:59 -08:00
|
|
|
ir_read_error(NULL, "when reading sampler 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;
|
|
|
|
|
}
|
2011-02-25 14:29:36 -08:00
|
|
|
tex->set_sampler(sampler, type);
|
2010-05-26 17:55:10 -07:00
|
|
|
|
2011-02-25 14:45:33 -08:00
|
|
|
if (op != ir_txs) {
|
|
|
|
|
// Read coordinate (any rvalue)
|
|
|
|
|
tex->coordinate = read_rvalue(s_coord);
|
|
|
|
|
if (tex->coordinate == NULL) {
|
|
|
|
|
ir_read_error(NULL, "when reading coordinate in (%s ...)",
|
|
|
|
|
tex->opcode_string());
|
2011-01-08 23:49:23 -08:00
|
|
|
return NULL;
|
|
|
|
|
}
|
2011-02-25 14:45:33 -08:00
|
|
|
|
|
|
|
|
// Read texel offset - either 0 or an rvalue.
|
|
|
|
|
s_int *si_offset = SX_AS_INT(s_offset);
|
|
|
|
|
if (si_offset == NULL || si_offset->value() != 0) {
|
|
|
|
|
tex->offset = read_rvalue(s_offset);
|
|
|
|
|
if (tex->offset == NULL) {
|
|
|
|
|
ir_read_error(s_offset, "expected 0 or an expression");
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
}
|
2010-05-26 17:55:10 -07:00
|
|
|
}
|
|
|
|
|
|
2011-02-25 14:45:33 -08:00
|
|
|
if (op != ir_txf && op != ir_txs) {
|
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 *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 {
|
2011-01-01 01:17:59 -08:00
|
|
|
tex->projector = read_rvalue(s_proj);
|
2010-05-26 17:55:10 -07:00
|
|
|
if (tex->projector == NULL) {
|
2011-01-01 01:17:59 -08:00
|
|
|
ir_read_error(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 {
|
2011-01-01 01:17:59 -08:00
|
|
|
tex->shadow_comparitor = read_rvalue(s_shadow);
|
2010-05-26 17:55:10 -07:00
|
|
|
if (tex->shadow_comparitor == NULL) {
|
2011-01-01 01:17:59 -08:00
|
|
|
ir_read_error(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:
|
2011-01-01 01:17:59 -08:00
|
|
|
tex->lod_info.bias = read_rvalue(s_lod);
|
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 (tex->lod_info.bias == NULL) {
|
2011-01-01 01:17:59 -08:00
|
|
|
ir_read_error(NULL, "when reading LOD bias in (txb ...)");
|
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 NULL;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case ir_txl:
|
|
|
|
|
case ir_txf:
|
2011-02-25 14:45:33 -08:00
|
|
|
case ir_txs:
|
2011-01-01 01:17:59 -08:00
|
|
|
tex->lod_info.lod = read_rvalue(s_lod);
|
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 (tex->lod_info.lod == NULL) {
|
2011-01-01 01:17:59 -08:00
|
|
|
ir_read_error(NULL, "when reading LOD 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());
|
|
|
|
|
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)) {
|
2011-01-01 01:17:59 -08:00
|
|
|
ir_read_error(s_lod, "expected (dPdx dPdy) in (txd ...)");
|
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 NULL;
|
|
|
|
|
}
|
2011-01-01 01:17:59 -08:00
|
|
|
tex->lod_info.grad.dPdx = read_rvalue(s_dx);
|
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 (tex->lod_info.grad.dPdx == NULL) {
|
2011-01-01 01:17:59 -08:00
|
|
|
ir_read_error(NULL, "when reading dPdx in (txd ...)");
|
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 NULL;
|
|
|
|
|
}
|
2011-01-01 01:17:59 -08:00
|
|
|
tex->lod_info.grad.dPdy = read_rvalue(s_dy);
|
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 (tex->lod_info.grad.dPdy == NULL) {
|
2011-01-01 01:17:59 -08:00
|
|
|
ir_read_error(NULL, "when reading dPdy in (txd ...)");
|
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 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;
|
|
|
|
|
}
|