ir_reader: Add support for reading conditionals: (if ...)
authorKenneth Graunke <kenneth@whitecape.org>
Sat, 10 Apr 2010 08:45:08 +0000 (01:45 -0700)
committerIan Romanick <ian.d.romanick@intel.com>
Thu, 29 Apr 2010 01:14:54 +0000 (18:14 -0700)
ir_reader.cpp

index d0c7c7080f8003543a5c04d0b116d6678d745404..0c41fb176219343ebc42beeb24fa0416c1069d68 100644 (file)
 static void ir_read_error(s_expression *expr, const char *fmt, ...);
 static const glsl_type *read_type(_mesa_glsl_parse_state *, s_expression *);
 
+static void read_instructions(_mesa_glsl_parse_state *, exec_list *,
+                             s_expression *);
 static ir_instruction *read_instruction(_mesa_glsl_parse_state *,
                                        s_expression *);
 static ir_variable *read_declaration(_mesa_glsl_parse_state *, s_list *);
+static ir_if *read_if(_mesa_glsl_parse_state *, s_list *);
 static ir_return *read_return(_mesa_glsl_parse_state *, s_list *);
 
 static ir_rvalue *read_rvalue(_mesa_glsl_parse_state *, s_expression *);
@@ -60,24 +63,7 @@ _mesa_glsl_read_ir(_mesa_glsl_parse_state *state, exec_list *instructions,
    _mesa_glsl_initialize_constructors(instructions, state);
    _mesa_glsl_initialize_functions(instructions, state);
 
-   // Read in a list of instructions
-   s_list *list = SX_AS_LIST(expr);
-   if (list == NULL) {
-      ir_read_error(expr, "Expected (<instruction> ...); found an atom.");
-      state->error = true;
-      return;
-   }
-
-   foreach_iter(exec_list_iterator, it, list->subexpressions) {
-      s_expression *sub = (s_expression*) it.get();
-      ir_instruction *ir = read_instruction(state, sub);
-      if (ir == NULL) {
-        ir_read_error(sub, "Invalid instruction.\n");
-        state->error = true;
-        return;
-      }
-      instructions->push_tail(ir);
-   }
+   read_instructions(state, instructions, expr);
 }
 
 static void
@@ -152,6 +138,31 @@ read_type(_mesa_glsl_parse_state *st, s_expression *expr)
 }
 
 
+static void
+read_instructions(_mesa_glsl_parse_state *st, exec_list *instructions,
+                 s_expression *expr)
+{
+   // Read in a list of instructions
+   s_list *list = SX_AS_LIST(expr);
+   if (list == NULL) {
+      ir_read_error(expr, "Expected (<instruction> ...); found an atom.");
+      st->error = true;
+      return;
+   }
+
+   foreach_iter(exec_list_iterator, it, list->subexpressions) {
+      s_expression *sub = (s_expression*) it.get();
+      ir_instruction *ir = read_instruction(st, sub);
+      if (ir == NULL) {
+        ir_read_error(sub, "Invalid instruction.\n");
+        st->error = true;
+        return;
+      }
+      instructions->push_tail(ir);
+   }
+}
+
+
 static ir_instruction *
 read_instruction(_mesa_glsl_parse_state *st, s_expression *expr)
 {
@@ -168,6 +179,8 @@ read_instruction(_mesa_glsl_parse_state *st, s_expression *expr)
    ir_instruction *inst = NULL;
    if (strcmp(tag->value(), "declare") == 0)
       inst = read_declaration(st, list);
+   else if (strcmp(tag->value(), "if") == 0)
+      inst = read_if(st, list);
    else if (strcmp(tag->value(), "return") == 0)
       inst = read_return(st, list);
    else
@@ -247,6 +260,37 @@ read_declaration(_mesa_glsl_parse_state *st, s_list *list)
 }
 
 
+static ir_if *
+read_if(_mesa_glsl_parse_state *st, s_list *list)
+{
+   if (list->length() != 4) {
+      ir_read_error(list, "expected (if <condition> (<then> ...) "
+                          "(<else> ...))");
+      return NULL;
+   }
+
+   s_expression *cond_expr = (s_expression*) list->subexpressions.head->next;
+   ir_rvalue *condition = read_rvalue(st, cond_expr);
+   if (condition == NULL) {
+      ir_read_error(list, "when reading condition of (if ...)");
+      return NULL;
+   }
+
+   s_expression *then_expr = (s_expression*) cond_expr->next;
+   s_expression *else_expr = (s_expression*) then_expr->next;
+
+   ir_if *iff = new ir_if(condition);
+
+   read_instructions(st, &iff->then_instructions, then_expr);
+   read_instructions(st, &iff->else_instructions, else_expr);
+   if (st->error) {
+      delete iff;
+      iff = NULL;
+   }
+   return iff;
+}
+
+
 static ir_return *
 read_return(_mesa_glsl_parse_state *st, s_list *list)
 {