diff options
author | Kenneth Graunke <kenneth@whitecape.org> | 2010-04-21 17:52:36 -0700 |
---|---|---|
committer | Ian Romanick <ian.d.romanick@intel.com> | 2010-04-28 18:14:54 -0700 |
commit | 09cad1339d8e6eebe5b13d95a9e1d2a1da2fce29 (patch) | |
tree | 9fd879af32e9a30f229fc5e6507b68c3033b11fa /ir_reader.cpp | |
parent | ddf5a011e2c4c9fd65d5d08aaaa284759fcd2f6e (diff) |
ir_reader: Perform a preliminary pass to scan for function prototypes.
Diffstat (limited to 'ir_reader.cpp')
-rw-r--r-- | ir_reader.cpp | 126 |
1 files changed, 126 insertions, 0 deletions
diff --git a/ir_reader.cpp b/ir_reader.cpp index eb7b7fcb6b..e14f5c8579 100644 --- a/ir_reader.cpp +++ b/ir_reader.cpp @@ -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); } @@ -147,6 +157,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) { |