glsl: Add ir node for barrier
[mesa.git] / src / glsl / ir_hv_accept.cpp
index f936b3500ebd719596861e20b6a73c9f600bff16..d3662cf5063e7a08f4c5e8ca9c9c460495013695 100644 (file)
  */
 
 /**
- * Process a list of nodes using a hierarchical vistor
+ * Process a list of nodes using a hierarchical vistor.
+ *
+ * If statement_list is true (the default), this is a list of statements, so
+ * v->base_ir will be set to point to each statement just before iterating
+ * over it, and restored after iteration is complete.  If statement_list is
+ * false, this is a list that appears inside a statement (e.g. a parameter
+ * list), so v->base_ir will be left alone.
  *
  * \warning
  * This function will operate correctly if a node being processed is removed
- * from list.  However, if nodes are added to the list after the node being
- * processed, some of the added noded may not be processed.
+ * from the list.  However, if nodes are added to the list after the node being
+ * processed, some of the added nodes may not be processed.
  */
-static ir_visitor_status
-visit_list_elements(ir_hierarchical_visitor *v, exec_list *l)
+ir_visitor_status
+visit_list_elements(ir_hierarchical_visitor *v, exec_list *l,
+                    bool statement_list)
 {
-   exec_node *next;
-
-   for (exec_node *n = l->head; n->next != NULL; n = next) {
-      next = n->next;
+   ir_instruction *prev_base_ir = v->base_ir;
 
-      ir_instruction *const ir = (ir_instruction *) n;
+   foreach_in_list_safe(ir_instruction, ir, l) {
+      if (statement_list)
+         v->base_ir = ir;
       ir_visitor_status s = ir->accept(v);
 
       if (s != visit_continue)
         return s;
    }
+   if (statement_list)
+      v->base_ir = prev_base_ir;
 
    return visit_continue;
 }
 
 
+ir_visitor_status
+ir_rvalue::accept(ir_hierarchical_visitor *v)
+{
+   return v->visit(this);
+}
+
+
 ir_visitor_status
 ir_variable::accept(ir_hierarchical_visitor *v)
 {
@@ -75,26 +90,6 @@ ir_loop::accept(ir_hierarchical_visitor *v)
    if (s == visit_stop)
       return s;
 
-   if (s != visit_continue_with_parent) {
-      if (this->from) {
-        s = this->from->accept(v);
-        if (s != visit_continue)
-           return (s == visit_continue_with_parent) ? visit_continue : s;
-      }
-
-      if (this->to) {
-        s = this->to->accept(v);
-        if (s != visit_continue)
-           return (s == visit_continue_with_parent) ? visit_continue : s;
-      }
-
-      if (this->increment) {
-        s = this->increment->accept(v);
-        if (s != visit_continue)
-           return (s == visit_continue_with_parent) ? visit_continue : s;
-      }
-   }
-
    return v->visit_leave(this);
 }
 
@@ -113,6 +108,10 @@ ir_function_signature::accept(ir_hierarchical_visitor *v)
    if (s != visit_continue)
       return (s == visit_continue_with_parent) ? visit_continue : s;
 
+   s = visit_list_elements(v, &this->parameters);
+   if (s == visit_stop)
+      return s;
+
    s = visit_list_elements(v, &this->body);
    return (s == visit_stop) ? s : v->visit_leave(this);
 }
@@ -125,7 +124,7 @@ ir_function::accept(ir_hierarchical_visitor *v)
    if (s != visit_continue)
       return (s == visit_continue_with_parent) ? visit_continue : s;
 
-   s = visit_list_elements(v, &this->signatures);
+   s = visit_list_elements(v, &this->signatures, false);
    return (s == visit_stop) ? s : v->visit_leave(this);
 }
 
@@ -167,9 +166,11 @@ ir_texture::accept(ir_hierarchical_visitor *v)
    if (s != visit_continue)
       return (s == visit_continue_with_parent) ? visit_continue : s;
 
-   s = this->coordinate->accept(v);
-   if (s != visit_continue)
-      return (s == visit_continue_with_parent) ? visit_continue : s;
+   if (this->coordinate) {
+      s = this->coordinate->accept(v);
+      if (s != visit_continue)
+        return (s == visit_continue_with_parent) ? visit_continue : s;
+   }
 
    if (this->projector) {
       s = this->projector->accept(v);
@@ -183,8 +184,16 @@ ir_texture::accept(ir_hierarchical_visitor *v)
         return (s == visit_continue_with_parent) ? visit_continue : s;
    }
 
+   if (this->offset) {
+      s = this->offset->accept(v);
+      if (s != visit_continue)
+        return (s == visit_continue_with_parent) ? visit_continue : s;
+   }
+
    switch (this->op) {
    case ir_tex:
+   case ir_lod:
+   case ir_query_levels:
       break;
    case ir_txb:
       s = this->lod_info.bias->accept(v);
@@ -193,10 +202,16 @@ ir_texture::accept(ir_hierarchical_visitor *v)
       break;
    case ir_txl:
    case ir_txf:
+   case ir_txs:
       s = this->lod_info.lod->accept(v);
       if (s != visit_continue)
         return (s == visit_continue_with_parent) ? visit_continue : s;
       break;
+   case ir_txf_ms:
+      s = this->lod_info.sample_index->accept(v);
+      if (s != visit_continue)
+         return (s == visit_continue_with_parent) ? visit_continue : s;
+      break;
    case ir_txd:
       s = this->lod_info.grad.dPdx->accept(v);
       if (s != visit_continue)
@@ -206,9 +221,14 @@ ir_texture::accept(ir_hierarchical_visitor *v)
       if (s != visit_continue)
         return (s == visit_continue_with_parent) ? visit_continue : s;
       break;
+   case ir_tg4:
+      s = this->lod_info.component->accept(v);
+      if (s != visit_continue)
+         return (s == visit_continue_with_parent) ? visit_continue : s;
+      break;
    }
 
-   return visit_continue_with_parent;
+   return (s == visit_stop) ? s : v->visit_leave(this);
 }
 
 
@@ -238,7 +258,14 @@ ir_dereference_array::accept(ir_hierarchical_visitor *v)
    if (s != visit_continue)
       return (s == visit_continue_with_parent) ? visit_continue : s;
 
+   /* The array index is not the target of the assignment, so clear the
+    * 'in_assignee' flag.  Restore it after returning from the array index.
+    */
+   const bool was_in_assignee = v->in_assignee;
+   v->in_assignee = false;
    s = this->array_index->accept(v);
+   v->in_assignee = was_in_assignee;
+
    if (s != visit_continue)
       return (s == visit_continue_with_parent) ? visit_continue : s;
 
@@ -266,7 +293,9 @@ ir_assignment::accept(ir_hierarchical_visitor *v)
    if (s != visit_continue)
       return (s == visit_continue_with_parent) ? visit_continue : s;
 
+   v->in_assignee = true;
    s = this->lhs->accept(v);
+   v->in_assignee = false;
    if (s != visit_continue)
       return (s == visit_continue_with_parent) ? visit_continue : s;
 
@@ -295,7 +324,15 @@ ir_call::accept(ir_hierarchical_visitor *v)
    if (s != visit_continue)
       return (s == visit_continue_with_parent) ? visit_continue : s;
 
-   s = visit_list_elements(v, &this->actual_parameters);
+   if (this->return_deref != NULL) {
+      v->in_assignee = true;
+      s = this->return_deref->accept(v);
+      v->in_assignee = false;
+      if (s != visit_continue)
+        return (s == visit_continue_with_parent) ? visit_continue : s;
+   }
+
+   s = visit_list_elements(v, &this->actual_parameters, false);
    if (s == visit_stop)
       return s;
 
@@ -321,6 +358,23 @@ ir_return::accept(ir_hierarchical_visitor *v)
 }
 
 
+ir_visitor_status
+ir_discard::accept(ir_hierarchical_visitor *v)
+{
+   ir_visitor_status s = v->visit_enter(this);
+   if (s != visit_continue)
+      return (s == visit_continue_with_parent) ? visit_continue : s;
+
+   if (this->condition != NULL) {
+      s = this->condition->accept(v);
+      if (s != visit_continue)
+        return (s == visit_continue_with_parent) ? visit_continue : s;
+   }
+
+   return v->visit_leave(this);
+}
+
+
 ir_visitor_status
 ir_if::accept(ir_hierarchical_visitor *v)
 {
@@ -346,3 +400,38 @@ ir_if::accept(ir_hierarchical_visitor *v)
 
    return v->visit_leave(this);
 }
+
+ir_visitor_status
+ir_emit_vertex::accept(ir_hierarchical_visitor *v)
+{
+   ir_visitor_status s = v->visit_enter(this);
+   if (s != visit_continue)
+      return (s == visit_continue_with_parent) ? visit_continue : s;
+
+   s = this->stream->accept(v);
+   if (s != visit_continue)
+      return (s == visit_continue_with_parent) ? visit_continue : s;
+
+   return (s == visit_stop) ? s : v->visit_leave(this);
+}
+
+
+ir_visitor_status
+ir_end_primitive::accept(ir_hierarchical_visitor *v)
+{
+   ir_visitor_status s = v->visit_enter(this);
+   if (s != visit_continue)
+      return (s == visit_continue_with_parent) ? visit_continue : s;
+
+   s = this->stream->accept(v);
+   if (s != visit_continue)
+      return (s == visit_continue_with_parent) ? visit_continue : s;
+
+   return (s == visit_stop) ? s : v->visit_leave(this);
+}
+
+ir_visitor_status
+ir_barrier::accept(ir_hierarchical_visitor *v)
+{
+   return v->visit(this);
+}