Merge remote branch 'cworth/master'

Conflicts:
	ast_to_hir.cpp
	ir.cpp

This brings in the talloc-based memory management work, so that the
compiler (almost) no longer leaks memory.
diff --git a/ast_to_hir.cpp b/ast_to_hir.cpp
index ddd4b73..33eb275 100644
--- a/ast_to_hir.cpp
+++ b/ast_to_hir.cpp
@@ -523,12 +523,15 @@
     * ends up not being used, the temp will get copy-propagated out.
     */
    ir_variable *var = new(ctx) ir_variable(rhs->type, "assignment_tmp");
-   instructions->push_tail(new(ctx) ir_assignment(new(ctx) ir_dereference_variable(var),
+   ir_dereference_variable *deref_var = new(ctx) ir_dereference_variable(var);
+   instructions->push_tail(var);
+   instructions->push_tail(new(ctx) ir_assignment(deref_var,
 						  rhs,
 						  NULL));
+   deref_var = new(ctx) ir_dereference_variable(var);
 
    instructions->push_tail(new(ctx) ir_assignment(lhs,
-						  new(ctx) ir_dereference_variable(var),
+						  deref_var,
 						  NULL));
 
    return new(ctx) ir_dereference_variable(var);
diff --git a/ir.cpp b/ir.cpp
index 6286d87..2756752 100644
--- a/ir.cpp
+++ b/ir.cpp
@@ -297,39 +297,6 @@
    }
 }
 
-ir_instruction *
-ir_constant::clone(struct hash_table *ht) const
-{
-   void *ctx = talloc_parent(this);
-
-   switch (this->type->base_type) {
-   case GLSL_TYPE_UINT:
-   case GLSL_TYPE_INT:
-   case GLSL_TYPE_FLOAT:
-   case GLSL_TYPE_BOOL:
-      return new(ctx) ir_constant(this->type, &this->value);
-
-   case GLSL_TYPE_STRUCT: {
-      ir_constant *c = new(ctx)ir_constant;
-
-      c->type = this->type;
-      for (exec_node *node = this->components.head
-	      ; !node->is_tail_sentinal()
-	      ; node = node->next) {
-	 ir_constant *const orig = (ir_constant *) node;
-
-	 c->components.push_tail(orig->clone(NULL));
-      }
-
-      return c;
-   }
-
-   default:
-      assert(!"Should not get here."); break;
-      return NULL;
-   }
-}
-
 bool
 ir_constant::get_bool_component(unsigned i) const
 {
diff --git a/ir_clone.cpp b/ir_clone.cpp
index 5ffd3fc..8417638 100644
--- a/ir_clone.cpp
+++ b/ir_clone.cpp
@@ -47,7 +47,7 @@
    var->interpolation = this->interpolation;
 
    if (ht) {
-      hash_table_insert(ht, (void *)const_cast<ir_variable *>(this), var);
+      hash_table_insert(ht, var, (void *)const_cast<ir_variable *>(this));
    }
 
    return var;
@@ -251,3 +251,37 @@
    /* FINISHME */
    abort();
 }
+
+ir_instruction *
+ir_constant::clone(struct hash_table *ht) const
+{
+   void *ctx = talloc_parent(this);
+   (void)ht;
+
+   switch (this->type->base_type) {
+   case GLSL_TYPE_UINT:
+   case GLSL_TYPE_INT:
+   case GLSL_TYPE_FLOAT:
+   case GLSL_TYPE_BOOL:
+      return new(ctx) ir_constant(this->type, &this->value);
+
+   case GLSL_TYPE_STRUCT: {
+      ir_constant *c = new(ctx) ir_constant;
+
+      c->type = this->type;
+      for (exec_node *node = this->components.head
+	      ; !node->is_tail_sentinal()
+	      ; node = node->next) {
+	 ir_constant *const orig = (ir_constant *) node;
+
+	 c->components.push_tail(orig->clone(NULL));
+      }
+
+      return c;
+   }
+
+   default:
+      assert(!"Should not get here."); break;
+      return NULL;
+   }
+}
diff --git a/ir_function_inlining.cpp b/ir_function_inlining.cpp
index 8a1cf4f..e55780c 100644
--- a/ir_function_inlining.cpp
+++ b/ir_function_inlining.cpp
@@ -91,6 +91,27 @@
    return v.progress;
 }
 
+static void
+replace_return_with_assignment(ir_instruction *ir, void *data)
+{
+   void *ctx = talloc_parent(ir);
+   ir_variable *retval = (ir_variable *)data;
+   ir_return *ret = ir->as_return();
+
+   if (ret) {
+      if (ret->value) {
+	 ir_rvalue *lhs = new(ctx) ir_dereference_variable(retval);
+	 ret->insert_before(new(ctx) ir_assignment(lhs, ret->value, NULL));
+	 ret->remove();
+      } else {
+	 /* un-valued return has to be the last return, or we shouldn't
+	  * have reached here. (see can_inline()).
+	  */
+	 assert(!ret->next->is_tail_sentinal());
+      }
+   }
+}
+
 ir_rvalue *
 ir_call::generate_inline(ir_instruction *next_ir)
 {
@@ -127,11 +148,12 @@
 
       /* Generate a new variable for the parameter. */
       parameters[i] = (ir_variable *)sig_param->clone(ht);
+      parameters[i]->mode = ir_var_auto;
       next_ir->insert_before(parameters[i]);
 
       /* Move the actual param into our param variable if it's an 'in' type. */
-      if (parameters[i]->mode == ir_var_in ||
-	  parameters[i]->mode == ir_var_inout) {
+      if (sig_param->mode == ir_var_in ||
+	  sig_param->mode == ir_var_inout) {
 	 ir_assignment *assign;
 
 	 assign = new(ctx) ir_assignment(new(ctx) ir_dereference_variable(parameters[i]),
@@ -146,8 +168,10 @@
    /* Generate the inlined body of the function. */
    foreach_iter(exec_list_iterator, iter, callee->body) {
       ir_instruction *ir = (ir_instruction *)iter.get();
+      ir_instruction *new_ir = ir->clone(ht);
 
-      next_ir->insert_before(ir->clone(ht));
+      next_ir->insert_before(new_ir);
+      visit_tree(new_ir, replace_return_with_assignment, retval);
    }
 
    /* Copy back the value of any 'out' parameters from the function body
diff --git a/ir_hierarchical_visitor.cpp b/ir_hierarchical_visitor.cpp
index 63ce878..0d520b1 100644
--- a/ir_hierarchical_visitor.cpp
+++ b/ir_hierarchical_visitor.cpp
@@ -268,3 +268,17 @@
 	 break;
    }
 }
+
+
+void
+visit_tree(ir_instruction *ir,
+	   void (*callback)(class ir_instruction *ir, void *data),
+	   void *data)
+{
+   ir_hierarchical_visitor v;
+
+   v.callback = callback;
+   v.data = data;
+
+   ir->accept(&v);
+}
diff --git a/ir_hierarchical_visitor.h b/ir_hierarchical_visitor.h
index e741155..8b9e49d 100644
--- a/ir_hierarchical_visitor.h
+++ b/ir_hierarchical_visitor.h
@@ -139,7 +139,6 @@
     */
    void run(struct exec_list *instructions);
 
-protected:
    /**
     * Callback function that is invoked on entry to each node visited.
     *
@@ -156,4 +155,8 @@
    void *data;
 };
 
+void visit_tree(ir_instruction *ir,
+		void (*callback)(class ir_instruction *ir, void *data),
+		void *data);
+
 #endif /* IR_HIERARCHICAL_VISITOR_H */
diff --git a/ir_print_visitor.cpp b/ir_print_visitor.cpp
index f15ffb6..be5a843 100644
--- a/ir_print_visitor.cpp
+++ b/ir_print_visitor.cpp
@@ -92,7 +92,7 @@
 	  cent, inv, mode[ir->mode], interp[ir->interpolation]);
 
    print_type(ir->type);
-   printf(" %s)", ir->name);
+   printf(" %s@%p)", ir->name, ir);
 }
 
 
@@ -220,7 +220,8 @@
 
 void ir_print_visitor::visit(ir_dereference_variable *ir)
 {
-   printf("(var_ref %s) ", ir->variable_referenced()->name);
+   ir_variable *var = ir->variable_referenced();
+   printf("(var_ref %s@%p) ", var->name, var);
 }