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.
This commit is contained in:
@@ -324,6 +324,9 @@ public:
|
|||||||
/** Whether or not this function has a body (which may be empty). */
|
/** Whether or not this function has a body (which may be empty). */
|
||||||
unsigned is_defined:1;
|
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. */
|
/** Body of instructions in the function. */
|
||||||
struct exec_list body;
|
struct exec_list body;
|
||||||
|
|
||||||
|
@@ -287,6 +287,7 @@ ir_function_signature::clone(struct hash_table *ht) const
|
|||||||
new(mem_ctx) ir_function_signature(this->return_type);
|
new(mem_ctx) ir_function_signature(this->return_type);
|
||||||
|
|
||||||
copy->is_defined = this->is_defined;
|
copy->is_defined = this->is_defined;
|
||||||
|
copy->is_built_in = this->is_built_in;
|
||||||
|
|
||||||
/* Clone the parameter list.
|
/* Clone the parameter list.
|
||||||
*/
|
*/
|
||||||
|
@@ -291,6 +291,7 @@ read_function_sig(_mesa_glsl_parse_state *st, ir_function *f, s_list *list,
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
sig = new(ctx) ir_function_signature(return_type);
|
sig = new(ctx) ir_function_signature(return_type);
|
||||||
|
sig->is_built_in = true;
|
||||||
f->add_signature(sig);
|
f->add_signature(sig);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -473,8 +473,64 @@ link_intrastage_shaders(struct gl_shader_program *prog,
|
|||||||
struct gl_shader **shader_list,
|
struct gl_shader **shader_list,
|
||||||
unsigned num_shaders)
|
unsigned num_shaders)
|
||||||
{
|
{
|
||||||
(void) prog;
|
/* Check that global variables defined in multiple shaders are consistent.
|
||||||
assert(num_shaders == 1);
|
*/
|
||||||
|
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);
|
gl_shader *const linked = _mesa_new_shader(NULL, 0, shader_list[0]->Type);
|
||||||
linked->ir = new(linked) exec_list;
|
linked->ir = new(linked) exec_list;
|
||||||
|
Reference in New Issue
Block a user