gallium: Fix typo in define name.
[mesa.git] / src / mesa / shader / slang / slang_compile.c
index 60539f19b6e962fccd704319db182a8373563fbe..294e46235c20a58d4d960bc73edc9bd5c48dd20f 100644 (file)
 #define TYPE_SPECIFIER_COUNT 32
 
 
+/**
+ * Check if the given identifier is legal.
+ */
+static GLboolean
+legal_identifier(slang_atom name)
+{
+   /* "gl_" is a reserved prefix */
+   if (_mesa_strncmp((char *) name, "gl_", 3) == 0) {
+      return GL_FALSE;
+   }
+   return GL_TRUE;
+}
+
+
 /**
  * Allocate storage for a variable of 'size' bytes from given pool.
  * Return the allocated address for the variable.
@@ -223,7 +237,7 @@ parse_float(slang_parse_ctx * C, float *number)
 }
 
 /* revision number - increment after each change affecting emitted output */
-#define REVISION 3
+#define REVISION 4
 
 static int
 check_revision(slang_parse_ctx * C)
@@ -677,14 +691,49 @@ parse_type_specifier(slang_parse_ctx * C, slang_output_ctx * O,
    return 1;
 }
 
+#define PRECISION_DEFAULT 0
+#define PRECISION_LOW     1
+#define PRECISION_MEDIUM  2
+#define PRECISION_HIGH    3
+
 static int
 parse_fully_specified_type(slang_parse_ctx * C, slang_output_ctx * O,
                            slang_fully_specified_type * type)
 {
+   GLuint precision;
+
    if (!parse_type_qualifier(C, &type->qualifier))
       return 0;
+   precision = *C->I++;
    if (!parse_type_specifier(C, O, &type->specifier))
       return 0;
+
+   switch (precision) {
+   case PRECISION_DEFAULT:
+      assert(type->specifier.type < TYPE_SPECIFIER_COUNT);
+      if (type->specifier.type < TYPE_SPECIFIER_COUNT)
+         type->precision = O->default_precision[type->specifier.type];
+      break;
+   case PRECISION_LOW:
+      type->precision = SLANG_PREC_LOW;
+      break;
+   case PRECISION_MEDIUM:
+      type->precision = SLANG_PREC_MEDIUM;
+      break;
+   case PRECISION_HIGH:
+      type->precision = SLANG_PREC_HIGH;
+      break;
+   default:
+      return 0;
+   }
+
+#if !FEATURE_es2_glsl
+   if (precision != PRECISION_DEFAULT) {
+      slang_info_log_error(C->L, "precision qualifiers not allowed");
+      return 0;
+   }
+#endif
+
    return 1;
 }
 
@@ -751,6 +800,7 @@ parse_fully_specified_type(slang_parse_ctx * C, slang_output_ctx * O,
 #define OP_FIELD 59
 #define OP_POSTINCREMENT 60
 #define OP_POSTDECREMENT 61
+#define OP_PRECISION 62
 
 
 /**
@@ -835,6 +885,12 @@ parse_statement(slang_parse_ctx * C, slang_output_ctx * O,
                o->type = SLANG_OPER_VARIABLE_DECL;
                o->locals->outer_scope = O->vars;
                o->a_id = O->vars->variables[i]->a_name;
+
+               if (!legal_identifier(o->a_id)) {
+                  slang_info_log_error(C->L, "illegal variable name '%s'",
+                                       (char *) o->a_id);
+                  return 0;
+               }
             }
          }
       }
@@ -916,6 +972,16 @@ parse_statement(slang_parse_ctx * C, slang_output_ctx * O,
             return 0;
       }
       break;
+   case OP_PRECISION:
+      {
+         /* set default precision for a type in this scope */
+         /* ignored at this time */
+         int prec_qual = *C->I++;
+         int datatype = *C->I++;
+         (void) prec_qual;
+         (void) datatype;
+      }
+      break;
    default:
       return 0;
    }
@@ -1240,12 +1306,16 @@ static int
 parse_parameter_declaration(slang_parse_ctx * C, slang_output_ctx * O,
                             slang_variable * param)
 {
+   int param_qual, precision_qual;
+
    /* parse and validate the parameter's type qualifiers (there can be
     * two at most) because not all combinations are valid
     */
    if (!parse_type_qualifier(C, &param->type.qualifier))
       return 0;
-   switch (*C->I++) {
+
+   param_qual = *C->I++;
+   switch (param_qual) {
    case PARAM_QUALIFIER_IN:
       if (param->type.qualifier != SLANG_QUAL_CONST
           && param->type.qualifier != SLANG_QUAL_NONE) {
@@ -1273,6 +1343,11 @@ parse_parameter_declaration(slang_parse_ctx * C, slang_output_ctx * O,
       return 0;
    }
 
+   /* parse precision qualifier (lowp, mediump, highp */
+   precision_qual = *C->I++;
+   /* ignored at this time */
+   (void) precision_qual;
+
    /* parse parameter's type specifier and name */
    if (!parse_type_specifier(C, O, &param->type.specifier))
       return 0;
@@ -1404,6 +1479,7 @@ parse_operator_name(slang_parse_ctx * C)
    return 0;
 }
 
+
 static int
 parse_function_prototype(slang_parse_ctx * C, slang_output_ctx * O,
                          slang_function * func)
@@ -1441,6 +1517,12 @@ parse_function_prototype(slang_parse_ctx * C, slang_output_ctx * O,
       return 0;
    }
 
+   if (!legal_identifier(func->header.a_name)) {
+      slang_info_log_error(C->L, "illegal function name '%s'",
+                           (char *) func->header.a_name);
+      return 0;
+   }
+
    /* parse function parameters */
    while (*C->I++ == PARAMETER_NEXT) {
       slang_variable *p = slang_variable_scope_grow(func->parameters);
@@ -1842,11 +1924,6 @@ parse_declaration(slang_parse_ctx * C, slang_output_ctx * O)
    return 1;
 }
 
-
-#define PRECISION_LOW    0
-#define PRECISION_MEDIUM 1
-#define PRECISION_HIGH   2
-
 static int
 parse_default_precision(slang_parse_ctx * C, slang_output_ctx * O)
 {
@@ -2025,6 +2102,12 @@ parse_code_unit(slang_parse_ctx * C, slang_code_unit * unit,
       A.vartable = o.vartable;
       A.log = C->L;
 
+      /* main() takes no parameters */
+      if (mainFunc->param_count > 0) {
+         slang_info_log_error(A.log, "main() takes no arguments");
+         return GL_FALSE;
+      }
+
       _slang_codegen_function(&A, mainFunc);
 
       shader->Main = GL_TRUE; /* this shader defines main() */
@@ -2285,7 +2368,7 @@ compile_shader(GLcontext *ctx, slang_code_object * object,
    GLboolean success;
    grammar id = 0;
 
-#if 1 /* for debug */
+#if 0 /* for debug */
    _mesa_printf("********* COMPILE SHADER ***********\n");
    _mesa_printf("%s\n", shader->Source);
    _mesa_printf("************************************\n");
@@ -2368,19 +2451,20 @@ _slang_compile(GLcontext *ctx, struct gl_shader *shader)
    _slang_delete_mempool((slang_mempool *) ctx->Shader.MemPool);
    ctx->Shader.MemPool = NULL;
 
-   if (shader->Type == GL_VERTEX_SHADER) {
-      /* remove any reads of varying (output) registers */
+   /* remove any reads of output registers */
 #if 0
-      printf("Pre-remove output reads:\n");
-      _mesa_print_program(shader->Programs);
+   printf("Pre-remove output reads:\n");
+   _mesa_print_program(shader->Program);
 #endif
+   _mesa_remove_output_reads(shader->Program, PROGRAM_OUTPUT);
+   if (shader->Type == GL_VERTEX_SHADER) {
+      /* and remove writes to varying vars in vertex programs */
       _mesa_remove_output_reads(shader->Program, PROGRAM_VARYING);
-      _mesa_remove_output_reads(shader->Program, PROGRAM_OUTPUT);
+   }
 #if 0
-      printf("Post-remove output reads:\n");
-      _mesa_print_program(shader->Programs);
+   printf("Post-remove output reads:\n");
+   _mesa_print_program(shader->Program);
 #endif
-   }
 
    return success;
 }