linker: Write errors to info log instead of stdout
authorIan Romanick <ian.d.romanick@intel.com>
Wed, 23 Jun 2010 19:07:22 +0000 (12:07 -0700)
committerIan Romanick <ian.d.romanick@intel.com>
Wed, 23 Jun 2010 19:07:22 +0000 (12:07 -0700)
linker.cpp

index 500a329e7d6c88810f61108089282c147daa8b21..4d1ff0167e86bbbf1fdea5236b9a19c7f7f672eb 100644 (file)
  */
 #include <cstdlib>
 #include <cstdio>
+#include <cstdarg>
+
+extern "C" {
+#include <talloc.h>
+}
 
 #include "main/mtypes.h"
 #include "glsl_symbol_table.h"
@@ -108,6 +113,18 @@ private:
 };
 
 
+void
+linker_error_printf(glsl_program *prog, const char *fmt, ...)
+{
+   va_list ap;
+
+   prog->InfoLog = talloc_strdup_append(prog->InfoLog, "error: ");
+   va_start(ap, fmt);
+   prog->InfoLog = talloc_vasprintf_append(prog->InfoLog, fmt, ap);
+   va_end(ap);
+}
+
+
 void
 invalidate_variable_locations(glsl_shader *sh, enum ir_variable_mode mode,
                              int generic_base)
@@ -167,20 +184,22 @@ count_attribute_slots(const glsl_type *t)
  * \param shader  Vertex shader executable to be verified
  */
 bool
-validate_vertex_shader_executable(struct glsl_shader *shader)
+validate_vertex_shader_executable(struct glsl_program *prog,
+                                 struct glsl_shader *shader)
 {
    if (shader == NULL)
       return true;
 
    if (!shader->symbols->get_function("main")) {
-      printf("error: vertex shader lacks `main'\n");
+      linker_error_printf(prog, "vertex shader lacks `main'\n");
       return false;
    }
 
    find_assignment_visitor find("gl_Position");
    find.run(&shader->ir);
    if (!find.variable_found()) {
-      printf("error: vertex shader does not write to `gl_Position'\n");
+      linker_error_printf(prog,
+                         "vertex shader does not write to `gl_Position'\n");
       return false;
    }
 
@@ -194,13 +213,14 @@ validate_vertex_shader_executable(struct glsl_shader *shader)
  * \param shader  Fragment shader executable to be verified
  */
 bool
-validate_fragment_shader_executable(struct glsl_shader *shader)
+validate_fragment_shader_executable(struct glsl_program *prog,
+                                   struct glsl_shader *shader)
 {
    if (shader == NULL)
       return true;
 
    if (!shader->symbols->get_function("main")) {
-      printf("error: fragment shader lacks `main'\n");
+      linker_error_printf(prog, "fragment shader lacks `main'\n");
       return false;
    }
 
@@ -211,14 +231,14 @@ validate_fragment_shader_executable(struct glsl_shader *shader)
    frag_data.run(&shader->ir);
 
    if (!frag_color.variable_found() && !frag_data.variable_found()) {
-      printf("error: fragment shader does not write to `gl_FragColor' or "
-            "`gl_FragData'\n");
+      linker_error_printf(prog, "fragment shader does not write to "
+                         "`gl_FragColor' or `gl_FragData'\n");
       return false;
    }
 
    if (frag_color.variable_found() && frag_data.variable_found()) {
-      printf("error: fragment shader write to both `gl_FragColor' and "
-            "`gl_FragData'\n");
+      linker_error_printf(prog,  "fragment shader writes to both "
+                         "`gl_FragColor' and `gl_FragData'\n");
       return false;
    }
 
@@ -230,7 +250,8 @@ validate_fragment_shader_executable(struct glsl_shader *shader)
  * Perform validation of uniforms used across multiple shader stages
  */
 bool
-cross_validate_uniforms(struct glsl_shader **shaders, unsigned num_shaders)
+cross_validate_uniforms(struct glsl_program *prog,
+                       struct glsl_shader **shaders, unsigned num_shaders)
 {
    /* Examine all of the uniforms in all of the shaders and cross validate
     * them.
@@ -250,18 +271,19 @@ cross_validate_uniforms(struct glsl_shader **shaders, unsigned num_shaders)
         ir_variable *const existing = uniforms.get_variable(var->name);
         if (existing != NULL) {
            if (var->type != existing->type) {
-              printf("error: uniform `%s' declared as type `%s' and "
-                     "type `%s'\n",
-                     var->name, var->type->name, existing->type->name);
+              linker_error_printf(prog, "uniform `%s' declared as type "
+                                  "`%s' and type `%s'\n",
+                                  var->name, var->type->name,
+                                  existing->type->name);
               return false;
            }
 
            if (var->constant_value != NULL) {
               if (existing->constant_value != NULL) {
                  if (!var->constant_value->has_value(existing->constant_value)) {
-                    printf("error: initializers for uniform `%s' have "
-                           "differing values\n",
-                           var->name);
+                    linker_error_printf(prog, "initializers for uniform "
+                                        "`%s' have differing values\n",
+                                        var->name);
                     return false;
                  }
               } else
@@ -284,7 +306,8 @@ cross_validate_uniforms(struct glsl_shader **shaders, unsigned num_shaders)
  * Validate that outputs from one stage match inputs of another
  */
 bool
-cross_validate_outputs_to_inputs(glsl_shader *producer, glsl_shader *consumer)
+cross_validate_outputs_to_inputs(struct glsl_program *prog,
+                                glsl_shader *producer, glsl_shader *consumer)
 {
    glsl_symbol_table parameters;
    /* FINISHME: Figure these out dynamically. */
@@ -324,47 +347,53 @@ cross_validate_outputs_to_inputs(glsl_shader *producer, glsl_shader *consumer)
         /* Check that the types match between stages.
          */
         if (input->type != output->type) {
-           printf("error: %s shader output `%s' delcared as type `%s', but "
-                  "%s shader input declared as type `%s'\n",
-                  producer_stage, output->name, output->type->name,
-                  consumer_stage, input->type->name);
+           linker_error_printf(prog,
+                               "%s shader output `%s' delcared as "
+                               "type `%s', but %s shader input declared "
+                               "as type `%s'\n",
+                               producer_stage, output->name,
+                               output->type->name,
+                               consumer_stage, input->type->name);
            return false;
         }
 
         /* Check that all of the qualifiers match between stages.
          */
         if (input->centroid != output->centroid) {
-           printf("error: %s shader output `%s' %s centroid qualifier, but "
-                  "%s shader input %s centroid qualifier\n",
-                  producer_stage,
-                  output->name,
-                  (output->centroid) ? "has" : "lacks",
-                  consumer_stage,
-                  (input->centroid) ? "has" : "lacks");
+           linker_error_printf(prog,
+                               "%s shader output `%s' %s centroid qualifier, "
+                               "but %s shader input %s centroid qualifier\n",
+                               producer_stage,
+                               output->name,
+                               (output->centroid) ? "has" : "lacks",
+                               consumer_stage,
+                               (input->centroid) ? "has" : "lacks");
            return false;
         }
 
         if (input->invariant != output->invariant) {
-           printf("error: %s shader output `%s' %s invariant qualifier, but "
-                  "%s shader input %s invariant qualifier\n",
-                  producer_stage,
-                  output->name,
-                  (output->invariant) ? "has" : "lacks",
-                  consumer_stage,
-                  (input->invariant) ? "has" : "lacks");
+           linker_error_printf(prog,
+                               "%s shader output `%s' %s invariant qualifier, "
+                               "but %s shader input %s invariant qualifier\n",
+                               producer_stage,
+                               output->name,
+                               (output->invariant) ? "has" : "lacks",
+                               consumer_stage,
+                               (input->invariant) ? "has" : "lacks");
            return false;
         }
 
         if (input->interpolation != output->interpolation) {
-           printf("error: %s shader output `%s' specifies %s interpolation "
-                  "qualifier, "
-                  "but %s shader input specifies %s interpolation "
-                  "qualifier\n",
-                  producer_stage,
-                  output->name,
-                  output->interpolation_string(),
-                  consumer_stage,
-                  input->interpolation_string());
+           linker_error_printf(prog,
+                               "%s shader output `%s' specifies %s "
+                               "interpolation qualifier, "
+                               "but %s shader input specifies %s "
+                               "interpolation qualifier\n",
+                               producer_stage,
+                               output->name,
+                               output->interpolation_string(),
+                               consumer_stage,
+                               input->interpolation_string());
            return false;
         }
       }
@@ -741,6 +770,11 @@ link_shaders(struct glsl_program *prog)
    prog->Validated = false;
    prog->_Used = false;
 
+   if (prog->InfoLog != NULL)
+      talloc_free(prog->InfoLog);
+
+   prog->InfoLog = talloc_strdup(NULL, "");
+
    /* Separate the shaders into groups based on their type.
     */
    struct glsl_shader **vert_shader_list;
@@ -775,8 +809,8 @@ link_shaders(struct glsl_program *prog)
 
    /* Verify that each of the per-target executables is valid.
     */
-   if (!validate_vertex_shader_executable(vert_shader_list[0])
-       || !validate_fragment_shader_executable(frag_shader_list[0]))
+   if (!validate_vertex_shader_executable(prog, vert_shader_list[0])
+       || !validate_fragment_shader_executable(prog, frag_shader_list[0]))
       goto done;
 
 
@@ -795,12 +829,14 @@ link_shaders(struct glsl_program *prog)
       prog->_NumLinkedShaders++;
    }
 
-   if (cross_validate_uniforms(prog->_LinkedShaders, prog->_NumLinkedShaders)) {
+   if (cross_validate_uniforms(prog, prog->_LinkedShaders,
+                              prog->_NumLinkedShaders)) {
       /* Validate the inputs of each stage with the output of the preceeding
        * stage.
        */
       for (unsigned i = 1; i < prog->_NumLinkedShaders; i++) {
-        if (!cross_validate_outputs_to_inputs(prog->_LinkedShaders[i - 1],
+        if (!cross_validate_outputs_to_inputs(prog,
+                                              prog->_LinkedShaders[i - 1],
                                               prog->_LinkedShaders[i]))
            goto done;
       }