Mesa (glsl2): linker: First bits of intrastage, intershader function linking

Ian Romanick idr at kemper.freedesktop.org
Tue Jul 20 02:22:23 UTC 2010


Module: Mesa
Branch: glsl2
Commit: 8fe8a814b0c746f0f655a67f8755f9dee858d230
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=8fe8a814b0c746f0f655a67f8755f9dee858d230

Author: Ian Romanick <ian.d.romanick at intel.com>
Date:   Tue Jul 13 17:36:13 2010 -0700

linker: First bits of intrastage, intershader function linking

This handles the easy case of linking a function in a different
compilation unit that doesn't call any functions or reference any
global variables.

---

 src/glsl/Makefile           |    1 +
 src/glsl/link_functions.cpp |  176 +++++++++++++++++++++++++++++++++++++++++++
 src/glsl/linker.cpp         |    2 +
 src/glsl/linker.h           |   35 +++++++++
 4 files changed, 214 insertions(+), 0 deletions(-)

diff --git a/src/glsl/Makefile b/src/glsl/Makefile
index c09735d..497f6ca 100644
--- a/src/glsl/Makefile
+++ b/src/glsl/Makefile
@@ -53,6 +53,7 @@ CXX_SOURCES = \
 	ir_vec_index_to_cond_assign.cpp \
 	ir_vec_index_to_swizzle.cpp \
 	linker.cpp \
+	link_functions.cpp \
 	s_expression.cpp
 
 LIBS = \
diff --git a/src/glsl/link_functions.cpp b/src/glsl/link_functions.cpp
new file mode 100644
index 0000000..35bd223
--- /dev/null
+++ b/src/glsl/link_functions.cpp
@@ -0,0 +1,176 @@
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include <cstdlib>
+#include <cstdio>
+#include <cstdarg>
+
+extern "C" {
+#include <talloc.h>
+}
+
+#include "main/mtypes.h"
+#include "glsl_symbol_table.h"
+#include "glsl_parser_extras.h"
+#include "ir.h"
+#include "program.h"
+#include "hash_table.h"
+#include "linker.h"
+
+class call_link_visitor : public ir_hierarchical_visitor {
+public:
+   call_link_visitor(gl_shader_program *prog, gl_shader **shader_list,
+		     unsigned num_shaders)
+   {
+      this->prog = prog;
+      this->shader_list = shader_list;
+      this->num_shaders = num_shaders;
+      this->success = true;
+   }
+
+   virtual ir_visitor_status visit_enter(ir_call *ir)
+   {
+      /* If the function call references a function signature that does not
+       * have a definition, try to find the definition in one of the other
+       * shaders.
+       */
+      ir_function_signature *callee =
+	 const_cast<ir_function_signature *>(ir->get_callee());
+      assert(callee != NULL);
+
+      if (callee->is_defined)
+	 /* FINISHME: Do children need to be processed, or are all parameters
+	  * FINISHME: with function calls already flattend?
+	  */
+	 return visit_continue;
+
+      const char *const name = callee->function_name();
+
+      ir_function_signature *sig = const_cast<ir_function_signature *>
+	 (this->find_matching_signature(name, &ir->actual_parameters));
+      if (sig == NULL) {
+	 /* FINISHME: Log the full signature of unresolved function.
+	  */
+	 linker_error_printf(this->prog, "unresolved reference to function "
+			     "`%s'\n", name);
+	 this->success = false;
+	 return visit_stop;
+      }
+
+      /* Create an in-place clone of the function definition.  This multistep
+       * process introduces some complexity here, but it has some advantages.
+       * The parameter list and the and function body are cloned separately.
+       * The clone of the parameter list is used to prime the hashtable used
+       * to replace variable references in the cloned body.
+       *
+       * The big advantage is that the ir_function_signature does not change.
+       * This means that we don't have to process the rest of the IR tree to
+       * patch ir_call nodes.  In addition, there is no way to remove or replace
+       * signature stored in a function.  One could easily be added, but this
+       * avoids the need.
+       */
+      struct hash_table *ht = hash_table_ctor(0, hash_table_pointer_hash,
+					      hash_table_pointer_compare);
+      exec_list formal_parameters;
+      foreach_list_const(node, &sig->parameters) {
+	 const ir_instruction *const original = (ir_instruction *) node;
+	 assert(const_cast<ir_instruction *>(original)->as_variable());
+
+	 ir_instruction *copy = original->clone(ht);
+	 formal_parameters.push_tail(copy);
+      }
+
+      callee->replace_parameters(&formal_parameters);
+
+      assert(callee->body.is_empty());
+      foreach_list_const(node, &sig->body) {
+	 const ir_instruction *const original = (ir_instruction *) node;
+
+	 ir_instruction *copy = original->clone(ht);
+	 callee->body.push_tail(copy);
+      }
+
+      callee->is_defined = true;
+
+      /* FINISHME: Patch references inside the function to things outside the
+       * FINISHME: function (i.e., function calls and global variables).
+       */
+
+      hash_table_dtor(ht);
+
+      return visit_continue;
+   }
+
+   /** Was function linking successful? */
+   bool success;
+
+private:
+   /**
+    * Shader program being linked
+    *
+    * This is only used for logging error messages.
+    */
+   gl_shader_program *prog;
+
+   /** List of shaders available for linking. */
+   gl_shader **shader_list;
+
+   /** Number of shaders available for linking. */
+   unsigned num_shaders;
+
+   /**
+    * Searches all shaders for a particular function definition
+    */
+   const ir_function_signature *
+   find_matching_signature(const char *name, exec_list *actual_parameters)
+   {
+      for (unsigned i = 0; i < this->num_shaders; i++) {
+	 ir_function *const f =
+	    this->shader_list[i]->symbols->get_function(name);
+
+	 if (f == NULL)
+	    continue;
+
+	 const ir_function_signature *sig =
+	    f->matching_signature(actual_parameters);
+
+	 if ((sig == NULL) || !sig->is_defined)
+	    continue;
+
+	 return sig;
+      }
+
+      return NULL;
+   }
+};
+
+
+bool
+link_function_calls(gl_shader_program *prog, gl_shader *main,
+		    gl_shader **shader_list, unsigned num_shaders)
+{
+   call_link_visitor v(prog, shader_list, num_shaders);
+
+   v.run(main->ir);
+   return v.success;
+}
diff --git a/src/glsl/linker.cpp b/src/glsl/linker.cpp
index 155c9d4..f7c178e 100644
--- a/src/glsl/linker.cpp
+++ b/src/glsl/linker.cpp
@@ -77,6 +77,7 @@ extern "C" {
 #include "program.h"
 #include "hash_table.h"
 #include "shader_api.h"
+#include "linker.h"
 
 /**
  * Visitor that determines whether or not a variable is ever written.
@@ -699,6 +700,7 @@ link_intrastage_shaders(struct gl_shader_program *prog,
 
    /* Resolve initializers for global variables in the linked shader.
     */
+   link_function_calls(prog, linked, shader_list, num_shaders);
 
    return linked;
 }
diff --git a/src/glsl/linker.h b/src/glsl/linker.h
new file mode 100644
index 0000000..a8ce16a
--- /dev/null
+++ b/src/glsl/linker.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#pragma once
+#ifndef GLSL_LINKER_H
+#define GLSL_LINKER_H
+
+extern void
+linker_error_printf(gl_shader_program *prog, const char *fmt, ...);
+
+extern bool
+link_function_calls(gl_shader_program *prog, gl_shader *main,
+		    gl_shader **shader_list, unsigned num_shaders);
+
+#endif /* GLSL_LINKER_H */




More information about the mesa-commit mailing list