summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorIan Romanick <ian.d.romanick@intel.com>2010-07-15 20:20:36 -0700
committerIan Romanick <ian.d.romanick@intel.com>2010-07-19 14:50:43 -0700
commitfc9ae101b4b7a71ca7a5d4f185e887064007e0d1 (patch)
tree35f60e728a215a240c2d1f14a2428f521f4e3f69 /src
parent532c2d30850908b75f4b0ad0aa5fa7ce88f8202d (diff)
linker: Recursively resolve function calls in imported functions
Diffstat (limited to 'src')
-rw-r--r--src/glsl/link_functions.cpp49
1 files changed, 46 insertions, 3 deletions
diff --git a/src/glsl/link_functions.cpp b/src/glsl/link_functions.cpp
index 721bec65f3..a9ed49a349 100644
--- a/src/glsl/link_functions.cpp
+++ b/src/glsl/link_functions.cpp
@@ -51,6 +51,20 @@ public:
this->num_shaders = num_shaders;
this->success = true;
this->linked = linked;
+
+ this->locals = hash_table_ctor(0, hash_table_pointer_hash,
+ hash_table_pointer_compare);
+ }
+
+ ~call_link_visitor()
+ {
+ hash_table_dtor(this->locals);
+ }
+
+ virtual ir_visitor_status visit(ir_variable *ir)
+ {
+ hash_table_insert(locals, ir, ir);
+ return visit_continue;
}
virtual ir_visitor_status visit_enter(ir_call *ir)
@@ -143,12 +157,36 @@ public:
}
linked_sig->is_defined = true;
+ hash_table_dtor(ht);
- /* FINISHME: Patch references inside the function to things outside the
- * FINISHME: function (i.e., function calls and global variables).
+ /* Patch references inside the function to things outside the function
+ * (i.e., function calls and global variables).
*/
+ linked_sig->accept(this);
- hash_table_dtor(ht);
+ return visit_continue;
+ }
+
+ virtual ir_visitor_status visit(ir_dereference_variable *ir)
+ {
+ if (hash_table_find(locals, ir->var) == NULL) {
+ /* The non-function variable must be a global, so try to find the
+ * variable in the shader's symbol table. If the variable is not
+ * found, then it's a global that *MUST* be defined in the original
+ * shader.
+ */
+ ir_variable *var = linked->symbols->get_variable(ir->var->name);
+ if (var == NULL) {
+ /* Clone the ir_variable that the dereference already has and add
+ * it to the linked shader.
+ */
+ var = ir->var->clone(NULL);
+ linked->symbols->add_variable(var->name, var);
+ linked->ir->push_head(var);
+ }
+
+ ir->var = var;
+ }
return visit_continue;
}
@@ -178,6 +216,11 @@ private:
* global variables from the shader where the function originated.
*/
gl_shader *linked;
+
+ /**
+ * Table of variables local to the function.
+ */
+ hash_table *locals;
};