summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Romanick <ian.d.romanick@intel.com>2010-06-29 18:53:38 -0700
committerIan Romanick <ian.d.romanick@intel.com>2010-07-12 18:51:55 -0700
commit13f782c4ae4e38e64ec4fe87a1c24597a5e894c3 (patch)
tree073251c0f9c563a0f1ea59a6c274d03ac2c4714b
parente2e5d0def490ed03970efa0a7468fef0623ae617 (diff)
linker: Implement first bits of intrastage linking
This currently involves an ugly hack so that every link doesn't result in all the built-in functions showing up as multiply defined. As soon as the built-in functions are stored in a separate compilation unit, ir_function_signature::is_built_in can be removed.
-rw-r--r--src/glsl/ir.h3
-rw-r--r--src/glsl/ir_clone.cpp1
-rw-r--r--src/glsl/ir_reader.cpp1
-rw-r--r--src/glsl/linker.cpp60
4 files changed, 63 insertions, 2 deletions
diff --git a/src/glsl/ir.h b/src/glsl/ir.h
index fb94b5a560..25bf6c6d15 100644
--- a/src/glsl/ir.h
+++ b/src/glsl/ir.h
@@ -324,6 +324,9 @@ public:
/** Whether or not this function has a body (which may be empty). */
unsigned is_defined:1;
+ /** Whether or not this function signature is a built-in. */
+ unsigned is_built_in:1;
+
/** Body of instructions in the function. */
struct exec_list body;
diff --git a/src/glsl/ir_clone.cpp b/src/glsl/ir_clone.cpp
index f1547d9106..2562ad9118 100644
--- a/src/glsl/ir_clone.cpp
+++ b/src/glsl/ir_clone.cpp
@@ -287,6 +287,7 @@ ir_function_signature::clone(struct hash_table *ht) const
new(mem_ctx) ir_function_signature(this->return_type);
copy->is_defined = this->is_defined;
+ copy->is_built_in = this->is_built_in;
/* Clone the parameter list.
*/
diff --git a/src/glsl/ir_reader.cpp b/src/glsl/ir_reader.cpp
index 03212830cd..c83f92ef57 100644
--- a/src/glsl/ir_reader.cpp
+++ b/src/glsl/ir_reader.cpp
@@ -291,6 +291,7 @@ read_function_sig(_mesa_glsl_parse_state *st, ir_function *f, s_list *list,
}
} else {
sig = new(ctx) ir_function_signature(return_type);
+ sig->is_built_in = true;
f->add_signature(sig);
}
diff --git a/src/glsl/linker.cpp b/src/glsl/linker.cpp
index 04b4efd84b..3d8f24bb44 100644
--- a/src/glsl/linker.cpp
+++ b/src/glsl/linker.cpp
@@ -473,8 +473,64 @@ link_intrastage_shaders(struct gl_shader_program *prog,
struct gl_shader **shader_list,
unsigned num_shaders)
{
- (void) prog;
- assert(num_shaders == 1);
+ /* Check that global variables defined in multiple shaders are consistent.
+ */
+ if (!cross_validate_globals(prog, shader_list, num_shaders, false))
+ return NULL;
+
+ /* Check that there is only a single definition of each function signature
+ * across all shaders.
+ */
+ for (unsigned i = 0; i < (num_shaders - 1); i++) {
+ foreach_list(node, shader_list[i]->ir) {
+ ir_function *const f = ((ir_instruction *) node)->as_function();
+
+ if (f == NULL)
+ continue;
+
+ for (unsigned j = i + 1; j < num_shaders; j++) {
+ ir_function *const other =
+ shader_list[j]->symbols->get_function(f->name);
+
+ /* If the other shader has no function (and therefore no function
+ * signatures) with the same name, skip to the next shader.
+ */
+ if (other == NULL)
+ continue;
+
+ foreach_iter (exec_list_iterator, iter, *f) {
+ ir_function_signature *sig =
+ (ir_function_signature *) iter.get();
+
+ if (!sig->is_defined || sig->is_built_in)
+ continue;
+
+ ir_function_signature *other_sig =
+ other->exact_matching_signature(& sig->parameters);
+
+ if ((other_sig != NULL) && other_sig->is_defined
+ && !other_sig->is_built_in) {
+ linker_error_printf(prog,
+ "function `%s' is multiply defined",
+ f->name);
+ return NULL;
+ }
+ }
+ }
+ }
+ }
+
+ /* Find the shader that defines main, and make a clone of it.
+ *
+ * Starting with the clone, search for undefined references. If one is
+ * found, find the shader that defines it. Clone the reference and add
+ * it to the shader. Repeat until there are no undefined references or
+ * until a reference cannot be resolved.
+ */
+
+
+ /* Resolve initializers for global variables in the linked shader.
+ */
gl_shader *const linked = _mesa_new_shader(NULL, 0, shader_list[0]->Type);
linked->ir = new(linked) exec_list;