ir_reader: Perform a preliminary pass to scan for function prototypes.

This commit is contained in:
Kenneth Graunke
2010-04-21 17:52:36 -07:00
committed by Ian Romanick
parent ddf5a011e2
commit 09cad1339d

View File

@@ -31,6 +31,12 @@ static void ir_read_error(_mesa_glsl_parse_state *, s_expression *,
const char *fmt, ...);
static const glsl_type *read_type(_mesa_glsl_parse_state *, s_expression *);
static void scan_for_prototypes(_mesa_glsl_parse_state *, exec_list *,
s_expression *);
static void read_prototypes(_mesa_glsl_parse_state *, exec_list *, s_list *);
static ir_function_signature *read_prototype(_mesa_glsl_parse_state *,
s_list *);
static void read_instructions(_mesa_glsl_parse_state *, exec_list *,
s_expression *, ir_loop *);
static ir_instruction *read_instruction(_mesa_glsl_parse_state *,
@@ -69,6 +75,10 @@ _mesa_glsl_read_ir(_mesa_glsl_parse_state *state, exec_list *instructions,
* FINISHME: _mesa_glsl_initialize_constructors(instructions, state);
*/
scan_for_prototypes(state, instructions, expr);
if (state->error)
return;
read_instructions(state, instructions, expr, NULL);
}
@@ -146,6 +156,122 @@ read_type(_mesa_glsl_parse_state *st, s_expression *expr)
}
static void
scan_for_prototypes(_mesa_glsl_parse_state *st, exec_list *instructions,
s_expression *expr)
{
s_list *list = SX_AS_LIST(expr);
if (list == NULL) {
ir_read_error(st, expr, "Expected (<instruction> ...); found an atom.");
return;
}
foreach_iter(exec_list_iterator, it, list->subexpressions) {
s_list *sub = SX_AS_LIST(it.get());
if (sub == NULL)
continue; // not a (function ...); ignore it.
s_symbol *tag = SX_AS_SYMBOL(sub->subexpressions.get_head());
if (tag == NULL || strcmp(tag->value(), "function") != 0)
continue; // not a (function ...); ignore it.
read_prototypes(st, instructions, sub);
if (st->error)
return;
}
}
static void
read_prototypes(_mesa_glsl_parse_state *st, exec_list *instructions,
s_list *list)
{
if (list->length() < 3) {
ir_read_error(st, list, "Expected (function <name> (signature ...) ...)");
return;
}
s_symbol *name = SX_AS_SYMBOL(list->subexpressions.head->next);
if (name == NULL) {
ir_read_error(st, list, "Expected (function <name> ...)");
return;
}
ir_function *f = new ir_function(name->value());
bool added = st->symbols->add_function(name->value(), f);
if (!added) {
ir_read_error(st, list, "Function %s already exists.", name->value());
return;
}
instructions->push_tail(f);
exec_list_iterator it = list->subexpressions.iterator();
it.next(); // skip "function" tag
it.next(); // skip function name
for (/* nothing */; it.has_next(); it.next()) {
s_list *siglist = SX_AS_LIST(it.get());
if (siglist == NULL) {
ir_read_error(st, list, "Expected (function (signature ...) ...)");
return;
}
s_symbol *tag = SX_AS_SYMBOL(siglist->subexpressions.get_head());
if (tag == NULL || strcmp(tag->value(), "signature") != 0) {
ir_read_error(st, siglist, "Expected (signature ...)");
return;
}
ir_function_signature *sig = read_prototype(st, siglist);
if (sig == NULL)
return;
f->add_signature(sig);
}
}
static ir_function_signature *
read_prototype(_mesa_glsl_parse_state *st, s_list *list)
{
if (list->length() != 4) {
ir_read_error(st, list, "Expected (signature <type> (parameters ...) "
"(<instruction> ...))");
return NULL;
}
s_expression *type_expr = (s_expression*) list->subexpressions.head->next;
const glsl_type *return_type = read_type(st, type_expr);
if (return_type == NULL)
return NULL;
s_list *paramlist = SX_AS_LIST(type_expr->next);
if (paramlist == NULL) {
ir_read_error(st, list, "Expected (signature %s (parameters ...) ...)",
return_type->name);
return NULL;
}
s_symbol *paramtag = SX_AS_SYMBOL(paramlist->subexpressions.get_head());
if (paramtag == NULL || strcmp(paramtag->value(), "parameters") != 0) {
ir_read_error(st, paramlist, "Expected (parameters ...)");
return NULL;
}
ir_function_signature *sig = new ir_function_signature(return_type);
exec_list_iterator it = paramlist->subexpressions.iterator();
for (it.next() /* skip "parameters" */; it.has_next(); it.next()) {
s_list *decl = SX_AS_LIST(it.get());
ir_variable *var = read_declaration(st, decl);
if (var == NULL) {
delete sig;
return NULL;
}
sig->parameters.push_tail(var);
}
return sig;
}
static void
read_instructions(_mesa_glsl_parse_state *st, exec_list *instructions,
s_expression *expr, ir_loop *loop_ctx)