glsl: Refactor AST-to-HIR code handling variable initializers
[mesa.git] / src / glsl / ir_hv_accept.cpp
index e772018a45890e2302f14ea22752e2c48aec263d..4a607dc87499b800df7a6fff5c09b09fb49822be 100644 (file)
  *
  * \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.
  */
 ir_visitor_status
 visit_list_elements(ir_hierarchical_visitor *v, exec_list *l)
 {
-   exec_node *next;
    ir_instruction *prev_base_ir = v->base_ir;
 
-   for (exec_node *n = l->head; n->next != NULL; n = next) {
-      next = n->next;
-
+   foreach_list_safe(n, l) {
       ir_instruction *const ir = (ir_instruction *) n;
       v->base_ir = ir;
       ir_visitor_status s = ir->accept(v);
@@ -116,6 +113,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);
 }
@@ -186,6 +187,12 @@ 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:
       break;
@@ -211,7 +218,7 @@ ir_texture::accept(ir_hierarchical_visitor *v)
       break;
    }
 
-   return visit_continue_with_parent;
+   return (s == visit_stop) ? s : v->visit_leave(this);
 }
 
 
@@ -241,7 +248,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;
 
@@ -269,7 +283,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;