ir_reader: Perform a preliminary pass to scan for function prototypes.
authorKenneth Graunke <kenneth@whitecape.org>
Thu, 22 Apr 2010 00:52:36 +0000 (17:52 -0700)
committerIan Romanick <ian.d.romanick@intel.com>
Thu, 29 Apr 2010 01:14:54 +0000 (18:14 -0700)
ir_reader.cpp

index eb7b7fcb6b3592bb79e073c4903d0b007e36dbdb..e14f5c85796232a2ff7229321677812eb4e8eb2f 100644 (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)