From: Kenneth Graunke Date: Thu, 22 Apr 2010 00:52:36 +0000 (-0700) Subject: ir_reader: Perform a preliminary pass to scan for function prototypes. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=09cad1339d8e6eebe5b13d95a9e1d2a1da2fce29;p=mesa.git ir_reader: Perform a preliminary pass to scan for function prototypes. --- diff --git a/ir_reader.cpp b/ir_reader.cpp index eb7b7fcb6b3..e14f5c85796 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); } @@ -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 ( ...); 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 (signature ...) ...)"); + return; + } + + s_symbol *name = SX_AS_SYMBOL(list->subexpressions.head->next); + if (name == NULL) { + ir_read_error(st, list, "Expected (function ...)"); + 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 (parameters ...) " + "( ...))"); + 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)