summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/glsl/ir.h9
-rw-r--r--src/glsl/ir_clone.cpp60
2 files changed, 69 insertions, 0 deletions
diff --git a/src/glsl/ir.h b/src/glsl/ir.h
index 89922c6bbcd..18294ebc314 100644
--- a/src/glsl/ir.h
+++ b/src/glsl/ir.h
@@ -1236,6 +1236,15 @@ visit_exec_list(exec_list *list, ir_visitor *visitor);
void validate_ir_tree(exec_list *instructions);
+/**
+ * Make a clone of each IR instruction in a list
+ *
+ * \param in List of IR instructions that are to be cloned
+ * \param out List to hold the cloned instructions
+ */
+void
+clone_ir_list(exec_list *out, const exec_list *in);
+
extern void
_mesa_glsl_initialize_variables(exec_list *instructions,
struct _mesa_glsl_parse_state *state);
diff --git a/src/glsl/ir_clone.cpp b/src/glsl/ir_clone.cpp
index 2bde585914a..f1547d9106f 100644
--- a/src/glsl/ir_clone.cpp
+++ b/src/glsl/ir_clone.cpp
@@ -344,3 +344,63 @@ ir_constant::clone(struct hash_table *ht) const
return NULL;
}
}
+
+
+class fixup_ir_call_visitor : public ir_hierarchical_visitor {
+public:
+ fixup_ir_call_visitor(struct hash_table *ht)
+ {
+ this->ht = ht;
+ }
+
+ virtual ir_visitor_status visit_enter(ir_call *ir)
+ {
+ /* Try to find the function signature referenced by the ir_call in the
+ * table. If it is found, replace it with the value from the table.
+ */
+ const ir_function_signature *const sig =
+ (ir_function_signature *) hash_table_find(this->ht, ir->get_callee());
+ if (sig != NULL)
+ ir->set_callee(sig);
+
+ /* Since this may be used before function call parameters are flattened,
+ * the children also need to be processed.
+ */
+ return visit_continue;
+ }
+
+private:
+ struct hash_table *ht;
+};
+
+
+static void
+fixup_function_calls(struct hash_table *ht, exec_list *instructions)
+{
+ fixup_ir_call_visitor v(ht);
+ v.run(instructions);
+}
+
+
+void
+clone_ir_list(exec_list *out, const exec_list *in)
+{
+ struct hash_table *ht =
+ hash_table_ctor(0, hash_table_pointer_hash, hash_table_pointer_compare);
+
+ foreach_list_const(node, in) {
+ const ir_instruction *const original = (ir_instruction *) node;
+ ir_instruction *copy = original->clone(ht);
+
+ out->push_tail(copy);
+ }
+
+ /* Make a pass over the cloned tree to fix up ir_call nodes to point to the
+ * cloned ir_function_signature nodes. This cannot be done automatically
+ * during cloning because the ir_call might be a forward reference (i.e.,
+ * the function signature that it references may not have been cloned yet).
+ */
+ fixup_function_calls(ht, out);
+
+ hash_table_dtor(ht);
+}