diff options
-rw-r--r-- | src/glsl/ir.h | 9 | ||||
-rw-r--r-- | src/glsl/ir_clone.cpp | 60 |
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); +} |