Convert everything from the talloc API to the ralloc API.
[mesa.git] / src / glsl / ast_to_hir.cpp
index 7a171f3a2bbb627008c2d6abb704559e2495acbb..75f28cd2c77c502896b5f7a658e325e980d8e46d 100644 (file)
@@ -639,7 +639,14 @@ do_assignment(exec_list *instructions, struct _mesa_glsl_parse_state *state,
    bool error_emitted = (lhs->type->is_error() || rhs->type->is_error());
 
    if (!error_emitted) {
-      if (!lhs->is_lvalue()) {
+      if (lhs->variable_referenced() != NULL
+          && lhs->variable_referenced()->read_only) {
+         _mesa_glsl_error(&lhs_loc, state,
+                          "assignment to read-only variable '%s'",
+                          lhs->variable_referenced()->name);
+         error_emitted = true;
+
+      } else if (!lhs->is_lvalue()) {
         _mesa_glsl_error(& lhs_loc, state, "non-lvalue in assignment");
         error_emitted = true;
       }
@@ -712,7 +719,7 @@ do_assignment(exec_list *instructions, struct _mesa_glsl_parse_state *state,
 static ir_rvalue *
 get_lvalue_copy(exec_list *instructions, ir_rvalue *lvalue)
 {
-   void *ctx = talloc_parent(lvalue);
+   void *ctx = ralloc_parent(lvalue);
    ir_variable *var;
 
    var = new(ctx) ir_variable(lvalue->type, "_post_incdec_tmp",
@@ -1809,7 +1816,6 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual,
       }
    }
 
-   /* FINISHME: Mark 'in' variables at global scope as read-only. */
    if (qual->flags.q.constant || qual->flags.q.attribute
        || qual->flags.q.uniform
        || (qual->flags.q.varying && (state->target == fragment_shader)))
@@ -2003,6 +2009,40 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual,
       }
    }
 
+   /* Layout qualifiers for gl_FragDepth, which are enabled by extension
+    * AMD_conservative_depth.
+    */
+   int depth_layout_count = qual->flags.q.depth_any
+      + qual->flags.q.depth_greater
+      + qual->flags.q.depth_less
+      + qual->flags.q.depth_unchanged;
+   if (depth_layout_count > 0
+       && !state->AMD_conservative_depth_enable) {
+       _mesa_glsl_error(loc, state,
+                        "extension GL_AMD_conservative_depth must be enabled "
+                       "to use depth layout qualifiers");
+   } else if (depth_layout_count > 0
+              && strcmp(var->name, "gl_FragDepth") != 0) {
+       _mesa_glsl_error(loc, state,
+                        "depth layout qualifiers can be applied only to "
+                        "gl_FragDepth");
+   } else if (depth_layout_count > 1
+              && strcmp(var->name, "gl_FragDepth") == 0) {
+      _mesa_glsl_error(loc, state,
+                       "at most one depth layout qualifier can be applied to "
+                       "gl_FragDepth");
+   }
+   if (qual->flags.q.depth_any)
+      var->depth_layout = ir_depth_layout_any;
+   else if (qual->flags.q.depth_greater)
+      var->depth_layout = ir_depth_layout_greater;
+   else if (qual->flags.q.depth_less)
+      var->depth_layout = ir_depth_layout_less;
+   else if (qual->flags.q.depth_unchanged)
+       var->depth_layout = ir_depth_layout_unchanged;
+   else
+       var->depth_layout = ir_depth_layout_none;
+
    if (var->type->is_array() && state->language_version != 110) {
       var->array_lvalue = true;
    }
@@ -2206,6 +2246,8 @@ ast_declarator_list::hir(exec_list *instructions,
                             mode, var->name, extra);
         }
       } else if (var->mode == ir_var_in) {
+         var->read_only = true;
+
         if (state->target == vertex_shader) {
            bool error_emitted = false;
 
@@ -2591,6 +2633,36 @@ ast_declarator_list::hir(exec_list *instructions,
                    && earlier->type == var->type
                    && earlier->mode == var->mode) {
            earlier->interpolation = var->interpolation;
+
+         /* Layout qualifiers for gl_FragDepth. */
+         } else if (state->AMD_conservative_depth_enable
+                    && strcmp(var->name, "gl_FragDepth") == 0
+                    && earlier->type == var->type
+                    && earlier->mode == var->mode) {
+
+            /** From the AMD_conservative_depth spec:
+             *     Within any shader, the first redeclarations of gl_FragDepth
+             *     must appear before any use of gl_FragDepth.
+             */
+            if (earlier->used) {
+               _mesa_glsl_error(&loc, state,
+                                "the first redeclaration of gl_FragDepth "
+                                "must appear before any use of gl_FragDepth");
+            }
+
+            /* Prevent inconsistent redeclaration of depth layout qualifier. */
+            if (earlier->depth_layout != ir_depth_layout_none
+                && earlier->depth_layout != var->depth_layout) {
+               _mesa_glsl_error(&loc, state,
+                                "gl_FragDepth: depth layout is declared here "
+                                "as '%s, but it was previously declared as "
+                                "'%s'",
+                                depth_layout_string(var->depth_layout),
+                                depth_layout_string(earlier->depth_layout));
+            }
+
+            earlier->depth_layout = var->depth_layout;
+
         } else {
            YYLTYPE loc = this->get_location();
            _mesa_glsl_error(&loc, state, "`%s' redeclared", decl->identifier);
@@ -3002,27 +3074,26 @@ ast_jump_statement::hir(exec_list *instructions,
       assert(state->current_function);
 
       if (opt_return_value) {
-        if (state->current_function->return_type->base_type ==
-            GLSL_TYPE_VOID) {
-           YYLTYPE loc = this->get_location();
-
-           _mesa_glsl_error(& loc, state,
-                            "`return` with a value, in function `%s' "
-                            "returning void",
-                            state->current_function->function_name());
-        }
-
         ir_rvalue *const ret = opt_return_value->hir(instructions, state);
-        assert(ret != NULL);
+
+        /* The value of the return type can be NULL if the shader says
+         * 'return foo();' and foo() is a function that returns void.
+         *
+         * NOTE: The GLSL spec doesn't say that this is an error.  The type
+         * of the return value is void.  If the return type of the function is
+         * also void, then this should compile without error.  Seriously.
+         */
+        const glsl_type *const ret_type =
+           (ret == NULL) ? glsl_type::void_type : ret->type;
 
         /* Implicit conversions are not allowed for return values. */
-        if (state->current_function->return_type != ret->type) {
+        if (state->current_function->return_type != ret_type) {
            YYLTYPE loc = this->get_location();
 
            _mesa_glsl_error(& loc, state,
                             "`return' with wrong type %s, in function `%s' "
                             "returning %s",
-                            ret->type->name,
+                            ret_type->name,
                             state->current_function->function_name(),
                             state->current_function->return_type->name);
         }
@@ -3321,7 +3392,7 @@ ast_struct_specifier::hir(exec_list *instructions,
     * the types to HIR.  This ensures that structure definitions embedded in
     * other structure definitions are processed.
     */
-   glsl_struct_field *const fields = talloc_array(state, glsl_struct_field,
+   glsl_struct_field *const fields = ralloc_array(state, glsl_struct_field,
                                                  decl_count);
 
    unsigned i = 0;